v0.0.8 | CORS 설정에 X-NHN-Appkey 헤더 허용 추가
All checks were successful
Build And Test / build-and-push (push) Successful in 36s
All checks were successful
Build And Test / build-and-push (push) Successful in 36s
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -51,6 +51,13 @@ class ApiNks(BaseAPI):
|
||||
headers.update(extra_headers)
|
||||
return headers
|
||||
|
||||
# ==================== Supports ====================
|
||||
|
||||
def get_supports(self) -> dict:
|
||||
"""지원되는 Kubernetes 버전 및 작업 종류 조회"""
|
||||
url = f"{self.nks_url}/v1/supports"
|
||||
return self._get(url)
|
||||
|
||||
# ==================== Cluster ====================
|
||||
|
||||
def get_cluster_list(self) -> dict:
|
||||
@ -195,6 +202,78 @@ class ApiNks(BaseAPI):
|
||||
logger.info(f"Private 클러스터 생성 요청: {cluster_name}")
|
||||
return self._post(url, payload)
|
||||
|
||||
def create_cluster(
|
||||
self,
|
||||
cluster_name: str,
|
||||
vpc_id: str,
|
||||
subnet_id: str,
|
||||
instance_type: str,
|
||||
keypair_name: str,
|
||||
kubernetes_version: str,
|
||||
availability_zone: str,
|
||||
is_public: bool = True,
|
||||
external_network_id: Optional[str] = None,
|
||||
external_subnet_id: Optional[str] = None,
|
||||
node_count: int = 1,
|
||||
boot_volume_size: int = 50,
|
||||
boot_volume_type: str = "General SSD",
|
||||
node_image: Optional[str] = None,
|
||||
) -> dict:
|
||||
"""
|
||||
클러스터 생성 (Public/Private 분기)
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
vpc_id: VPC ID
|
||||
subnet_id: 서브넷 ID
|
||||
instance_type: 인스턴스 타입 (Flavor ID)
|
||||
keypair_name: Keypair 이름
|
||||
kubernetes_version: Kubernetes 버전 (예: v1.28.3)
|
||||
availability_zone: 가용 영역 (예: kr-pub-a)
|
||||
is_public: Public 클러스터 여부 (기본 True)
|
||||
external_network_id: 외부 네트워크 ID (Public 클러스터 필수)
|
||||
external_subnet_id: 외부 서브넷 ID (Public 클러스터 필수)
|
||||
node_count: 노드 수 (기본 1)
|
||||
boot_volume_size: 부팅 볼륨 크기 (GB, 기본 50)
|
||||
boot_volume_type: 볼륨 타입 (기본 "General SSD")
|
||||
node_image: 노드 이미지 ID (기본 Ubuntu 20.04)
|
||||
|
||||
Returns:
|
||||
dict: 생성된 클러스터 정보
|
||||
"""
|
||||
if is_public:
|
||||
if not external_network_id or not external_subnet_id:
|
||||
raise ValueError("Public 클러스터에는 external_network_id와 external_subnet_id가 필요합니다.")
|
||||
return self.create_public_cluster(
|
||||
cluster_name=cluster_name,
|
||||
vpc_id=vpc_id,
|
||||
subnet_id=subnet_id,
|
||||
instance_type=instance_type,
|
||||
keypair_name=keypair_name,
|
||||
kubernetes_version=kubernetes_version,
|
||||
external_network_id=external_network_id,
|
||||
external_subnet_id=external_subnet_id,
|
||||
availability_zone=availability_zone,
|
||||
node_count=node_count,
|
||||
boot_volume_size=boot_volume_size,
|
||||
boot_volume_type=boot_volume_type,
|
||||
node_image=node_image,
|
||||
)
|
||||
else:
|
||||
return self.create_private_cluster(
|
||||
cluster_name=cluster_name,
|
||||
vpc_id=vpc_id,
|
||||
subnet_id=subnet_id,
|
||||
instance_type=instance_type,
|
||||
keypair_name=keypair_name,
|
||||
kubernetes_version=kubernetes_version,
|
||||
availability_zone=availability_zone,
|
||||
node_count=node_count,
|
||||
boot_volume_size=boot_volume_size,
|
||||
boot_volume_type=boot_volume_type,
|
||||
node_image=node_image,
|
||||
)
|
||||
|
||||
def delete_cluster(self, cluster_name: str) -> dict:
|
||||
"""클러스터 삭제"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}"
|
||||
@ -212,3 +291,349 @@ class ApiNks(BaseAPI):
|
||||
"""노드 그룹 상세 조회"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/nodegroups/{nodegroup_name}"
|
||||
return self._get(url)
|
||||
|
||||
def create_nodegroup(
|
||||
self,
|
||||
cluster_name: str,
|
||||
nodegroup_name: str,
|
||||
instance_type: str,
|
||||
node_count: int = 1,
|
||||
availability_zone: Optional[str] = None,
|
||||
boot_volume_size: int = 50,
|
||||
boot_volume_type: str = "General SSD",
|
||||
node_image: Optional[str] = None,
|
||||
) -> dict:
|
||||
"""
|
||||
노드 그룹 생성
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
nodegroup_name: 노드 그룹 이름
|
||||
instance_type: 인스턴스 타입 (Flavor ID)
|
||||
node_count: 노드 수 (기본 1)
|
||||
availability_zone: 가용 영역 (예: kr-pub-a)
|
||||
boot_volume_size: 부팅 볼륨 크기 (GB, 기본 50)
|
||||
boot_volume_type: 볼륨 타입 (기본 "General SSD")
|
||||
node_image: 노드 이미지 ID (기본 Ubuntu 20.04)
|
||||
|
||||
Returns:
|
||||
dict: 생성된 노드 그룹 정보
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/nodegroups"
|
||||
|
||||
payload = {
|
||||
"name": nodegroup_name,
|
||||
"flavor_id": instance_type,
|
||||
"node_count": node_count,
|
||||
"labels": {
|
||||
"boot_volume_size": str(boot_volume_size),
|
||||
"boot_volume_type": boot_volume_type,
|
||||
"node_image": node_image or self.default_node_image,
|
||||
},
|
||||
}
|
||||
|
||||
if availability_zone:
|
||||
payload["labels"]["availability_zone"] = availability_zone
|
||||
|
||||
logger.info(f"노드 그룹 생성 요청: {cluster_name}/{nodegroup_name}")
|
||||
return self._post(url, payload)
|
||||
|
||||
def delete_nodegroup(self, cluster_name: str, nodegroup_name: str) -> dict:
|
||||
"""노드 그룹 삭제"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/nodegroups/{nodegroup_name}"
|
||||
logger.info(f"노드 그룹 삭제 요청: {cluster_name}/{nodegroup_name}")
|
||||
return self._delete(url)
|
||||
|
||||
def start_node(self, cluster_name: str, nodegroup_name: str, node_id: str) -> dict:
|
||||
"""
|
||||
워커 노드 시작
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
nodegroup_name: 노드 그룹 이름
|
||||
node_id: 노드 ID
|
||||
|
||||
Returns:
|
||||
dict: 응답 결과
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/nodegroups/{nodegroup_name}/start_node"
|
||||
payload = {"node_id": node_id}
|
||||
logger.info(f"워커 노드 시작 요청: {cluster_name}/{nodegroup_name}/{node_id}")
|
||||
return self._post(url, payload)
|
||||
|
||||
def stop_node(self, cluster_name: str, nodegroup_name: str, node_id: str) -> dict:
|
||||
"""
|
||||
워커 노드 중지
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
nodegroup_name: 노드 그룹 이름
|
||||
node_id: 노드 ID
|
||||
|
||||
Returns:
|
||||
dict: 응답 결과
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/nodegroups/{nodegroup_name}/stop_node"
|
||||
payload = {"node_id": node_id}
|
||||
logger.info(f"워커 노드 중지 요청: {cluster_name}/{nodegroup_name}/{node_id}")
|
||||
return self._post(url, payload)
|
||||
|
||||
# ==================== Cluster Operations ====================
|
||||
|
||||
def resize_cluster(self, cluster_name: str, node_count: int) -> dict:
|
||||
"""
|
||||
클러스터 노드 수 조정 (리사이즈)
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
node_count: 조정할 노드 수
|
||||
|
||||
Returns:
|
||||
dict: 응답 결과
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/actions/resize"
|
||||
payload = {"node_count": node_count}
|
||||
logger.info(f"클러스터 리사이즈 요청: {cluster_name}, node_count={node_count}")
|
||||
return self._post(url, payload)
|
||||
|
||||
def upgrade_cluster(self, cluster_name: str, kubernetes_version: str) -> dict:
|
||||
"""
|
||||
클러스터 Kubernetes 버전 업그레이드
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
kubernetes_version: 업그레이드할 Kubernetes 버전
|
||||
|
||||
Returns:
|
||||
dict: 응답 결과
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/actions/upgrade"
|
||||
payload = {"kube_tag": kubernetes_version}
|
||||
logger.info(f"클러스터 업그레이드 요청: {cluster_name}, version={kubernetes_version}")
|
||||
return self._post(url, payload)
|
||||
|
||||
def get_cluster_events(self, cluster_uuid: str) -> dict:
|
||||
"""
|
||||
클러스터 작업 이력 목록 조회
|
||||
|
||||
Args:
|
||||
cluster_uuid: 클러스터 UUID
|
||||
|
||||
Returns:
|
||||
dict: 작업 이력 목록
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_uuid}/events"
|
||||
return self._get(url)
|
||||
|
||||
def get_cluster_event(self, cluster_uuid: str, event_uuid: str) -> dict:
|
||||
"""
|
||||
클러스터 작업 이력 상세 조회
|
||||
|
||||
Args:
|
||||
cluster_uuid: 클러스터 UUID
|
||||
event_uuid: 작업 이력 UUID
|
||||
|
||||
Returns:
|
||||
dict: 작업 이력 상세 정보
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_uuid}/events/{event_uuid}"
|
||||
return self._get(url)
|
||||
|
||||
# ==================== Autoscaler ====================
|
||||
|
||||
def get_autoscale_config(self, cluster_name: str, nodegroup_name: str) -> dict:
|
||||
"""
|
||||
오토스케일러 설정 조회
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
nodegroup_name: 노드 그룹 이름
|
||||
|
||||
Returns:
|
||||
dict: 오토스케일러 설정
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/nodegroups/{nodegroup_name}/autoscale"
|
||||
return self._get(url)
|
||||
|
||||
def set_autoscale_config(
|
||||
self,
|
||||
cluster_name: str,
|
||||
nodegroup_name: str,
|
||||
ca_enable: bool,
|
||||
ca_max_node_count: Optional[int] = None,
|
||||
ca_min_node_count: Optional[int] = None,
|
||||
ca_scale_down_enable: Optional[bool] = None,
|
||||
ca_scale_down_delay_after_add: Optional[int] = None,
|
||||
ca_scale_down_unneeded_time: Optional[int] = None,
|
||||
) -> dict:
|
||||
"""
|
||||
오토스케일러 설정 변경
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
nodegroup_name: 노드 그룹 이름
|
||||
ca_enable: 오토스케일러 활성화 여부
|
||||
ca_max_node_count: 최대 노드 수
|
||||
ca_min_node_count: 최소 노드 수
|
||||
ca_scale_down_enable: 스케일 다운 활성화 여부
|
||||
ca_scale_down_delay_after_add: 스케일 다운 지연 시간 (분)
|
||||
ca_scale_down_unneeded_time: 불필요 노드 대기 시간 (분)
|
||||
|
||||
Returns:
|
||||
dict: 변경된 오토스케일러 설정
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/nodegroups/{nodegroup_name}/autoscale"
|
||||
|
||||
payload = {"ca_enable": ca_enable}
|
||||
|
||||
if ca_max_node_count is not None:
|
||||
payload["ca_max_node_count"] = ca_max_node_count
|
||||
if ca_min_node_count is not None:
|
||||
payload["ca_min_node_count"] = ca_min_node_count
|
||||
if ca_scale_down_enable is not None:
|
||||
payload["ca_scale_down_enable"] = ca_scale_down_enable
|
||||
if ca_scale_down_delay_after_add is not None:
|
||||
payload["ca_scale_down_delay_after_add"] = ca_scale_down_delay_after_add
|
||||
if ca_scale_down_unneeded_time is not None:
|
||||
payload["ca_scale_down_unneeded_time"] = ca_scale_down_unneeded_time
|
||||
|
||||
logger.info(f"오토스케일러 설정 변경 요청: {cluster_name}/{nodegroup_name}")
|
||||
return self._post(url, payload)
|
||||
|
||||
# ==================== Node Group Configuration ====================
|
||||
|
||||
def upgrade_nodegroup(
|
||||
self,
|
||||
cluster_name: str,
|
||||
nodegroup_name: str,
|
||||
kubernetes_version: str,
|
||||
max_unavailable_worker: int = 1,
|
||||
) -> dict:
|
||||
"""
|
||||
노드 그룹 Kubernetes 버전 업그레이드
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
nodegroup_name: 노드 그룹 이름
|
||||
kubernetes_version: 업그레이드할 Kubernetes 버전
|
||||
max_unavailable_worker: 동시 업그레이드 가능한 노드 수
|
||||
|
||||
Returns:
|
||||
dict: 응답 결과
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/nodegroups/{nodegroup_name}/upgrade"
|
||||
payload = {
|
||||
"kube_tag": kubernetes_version,
|
||||
"max_unavailable_worker": max_unavailable_worker,
|
||||
}
|
||||
logger.info(f"노드 그룹 업그레이드 요청: {cluster_name}/{nodegroup_name}, version={kubernetes_version}")
|
||||
return self._post(url, payload)
|
||||
|
||||
def set_nodegroup_userscript(
|
||||
self,
|
||||
cluster_name: str,
|
||||
nodegroup_name: str,
|
||||
userscript: str,
|
||||
) -> dict:
|
||||
"""
|
||||
노드 그룹 사용자 스크립트 설정
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
nodegroup_name: 노드 그룹 이름
|
||||
userscript: 사용자 스크립트 내용
|
||||
|
||||
Returns:
|
||||
dict: 응답 결과
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/nodegroups/{nodegroup_name}/userscript"
|
||||
payload = {"userscript": userscript}
|
||||
logger.info(f"노드 그룹 사용자 스크립트 설정 요청: {cluster_name}/{nodegroup_name}")
|
||||
return self._post(url, payload)
|
||||
|
||||
def update_nodegroup(
|
||||
self,
|
||||
cluster_name: str,
|
||||
nodegroup_name: str,
|
||||
instance_type: Optional[str] = None,
|
||||
node_count: Optional[int] = None,
|
||||
) -> dict:
|
||||
"""
|
||||
노드 그룹 설정 변경 (인스턴스 타입, 노드 수 등)
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
nodegroup_name: 노드 그룹 이름
|
||||
instance_type: 인스턴스 타입 (Flavor ID)
|
||||
node_count: 노드 수
|
||||
|
||||
Returns:
|
||||
dict: 변경된 노드 그룹 정보
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/nodegroups/{nodegroup_name}"
|
||||
|
||||
payload = {}
|
||||
if instance_type is not None:
|
||||
payload["flavor_id"] = instance_type
|
||||
if node_count is not None:
|
||||
payload["node_count"] = node_count
|
||||
|
||||
logger.info(f"노드 그룹 설정 변경 요청: {cluster_name}/{nodegroup_name}")
|
||||
return self._patch(url, payload)
|
||||
|
||||
# ==================== Certificates ====================
|
||||
|
||||
def renew_certificates(self, cluster_name: str) -> dict:
|
||||
"""
|
||||
클러스터 인증서 갱신
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
|
||||
Returns:
|
||||
dict: 응답 결과
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/certificates/{cluster_name}"
|
||||
logger.info(f"클러스터 인증서 갱신 요청: {cluster_name}")
|
||||
return self._patch(url, {})
|
||||
|
||||
# ==================== API Endpoint IP ACL ====================
|
||||
|
||||
def get_api_endpoint_ipacl(self, cluster_name: str) -> dict:
|
||||
"""
|
||||
API 엔드포인트 IP 접근 제어 조회
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
|
||||
Returns:
|
||||
dict: IP 접근 제어 설정
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/api_ep_ipacl"
|
||||
return self._get(url)
|
||||
|
||||
def set_api_endpoint_ipacl(
|
||||
self,
|
||||
cluster_name: str,
|
||||
enable: bool,
|
||||
allowed_cidrs: Optional[list] = None,
|
||||
) -> dict:
|
||||
"""
|
||||
API 엔드포인트 IP 접근 제어 설정
|
||||
|
||||
Args:
|
||||
cluster_name: 클러스터 이름
|
||||
enable: IP 접근 제어 활성화 여부
|
||||
allowed_cidrs: 허용할 CIDR 목록 (예: ["192.168.0.0/24", "10.0.0.0/8"])
|
||||
|
||||
Returns:
|
||||
dict: 변경된 IP 접근 제어 설정
|
||||
"""
|
||||
url = f"{self.nks_url}/v1/clusters/{cluster_name}/api_ep_ipacl"
|
||||
|
||||
payload = {"enable": enable}
|
||||
if allowed_cidrs is not None:
|
||||
payload["allowed_cidrs"] = allowed_cidrs
|
||||
|
||||
logger.info(f"API 엔드포인트 IP 접근 제어 설정 요청: {cluster_name}")
|
||||
return self._post(url, payload)
|
||||
|
||||
Reference in New Issue
Block a user