""" NHN Cloud API Serializers API 요청/응답 직렬화 """ from rest_framework import serializers # ==================== Token ==================== class TokenRequestSerializer(serializers.Serializer): """토큰 생성 요청""" tenant_id = serializers.CharField( help_text="NHN Cloud 테넌트 ID", max_length=64, ) username = serializers.CharField( help_text="NHN Cloud 사용자 ID (이메일 또는 API 사용자 ID)", max_length=255, ) password = serializers.CharField( help_text="NHN Cloud API 비밀번호", write_only=True, ) class TokenResponseSerializer(serializers.Serializer): """토큰 생성 응답""" token = serializers.CharField(help_text="API 토큰") tenant_id = serializers.CharField(help_text="테넌트 ID") expires_at = serializers.CharField(help_text="만료 시간", allow_null=True) # ==================== Common ==================== class ErrorResponseSerializer(serializers.Serializer): """에러 응답""" error = serializers.CharField(help_text="에러 메시지") code = serializers.IntegerField(help_text="에러 코드", required=False) # ==================== Compute ==================== class ComputeInstanceSerializer(serializers.Serializer): """인스턴스 생성 요청""" name = serializers.CharField( help_text="인스턴스 이름", max_length=255, ) image_id = serializers.CharField( help_text="이미지 ID", ) flavor_id = serializers.CharField( help_text="Flavor ID", ) subnet_id = serializers.CharField( help_text="서브넷 ID", ) keypair_name = serializers.CharField( help_text="Keypair 이름", ) volume_size = serializers.IntegerField( help_text="볼륨 크기 (GB)", default=50, min_value=20, max_value=2048, ) volume_type = serializers.CharField( help_text="볼륨 타입 (General SSD, General HDD)", default="General SSD", required=False, ) security_groups = serializers.ListField( child=serializers.CharField(), help_text="보안 그룹 목록", required=False, ) availability_zone = serializers.CharField( help_text="가용 영역", required=False, ) # ==================== VPC ==================== class VpcSerializer(serializers.Serializer): """VPC 생성 요청""" name = serializers.CharField( help_text="VPC 이름", max_length=255, ) cidr = serializers.CharField( help_text="CIDR 블록 (예: 10.0.0.0/16)", ) class SubnetSerializer(serializers.Serializer): """서브넷 생성 요청""" vpc_id = serializers.CharField( help_text="VPC ID", ) name = serializers.CharField( help_text="서브넷 이름", max_length=255, ) cidr = serializers.CharField( help_text="CIDR 블록 (예: 10.0.1.0/24)", ) # ==================== NKS ==================== class NksClusterSerializer(serializers.Serializer): """NKS 클러스터 생성 요청""" cluster_name = serializers.CharField( help_text="클러스터 이름", max_length=255, ) vpc_id = serializers.CharField( help_text="VPC ID", ) subnet_id = serializers.CharField( help_text="서브넷 ID", ) instance_type = serializers.CharField( help_text="인스턴스 타입 (Flavor ID)", ) keypair_name = serializers.CharField( help_text="Keypair 이름", ) kubernetes_version = serializers.CharField( help_text="Kubernetes 버전 (예: v1.28.3)", ) availability_zone = serializers.CharField( help_text="가용 영역 (예: kr-pub-a)", ) is_public = serializers.BooleanField( help_text="Public 클러스터 여부 (외부 접근 가능, True 선택 시 External Network 자동 설정)", default=True, ) node_count = serializers.IntegerField( help_text="노드 수", default=1, min_value=1, max_value=100, ) boot_volume_size = serializers.IntegerField( help_text="부팅 볼륨 크기 (GB)", default=50, min_value=50, max_value=1000, ) boot_volume_type = serializers.CharField( help_text="볼륨 타입", default="General SSD", ) # ==================== Storage ==================== class StorageContainerSerializer(serializers.Serializer): """스토리지 컨테이너 생성 요청""" name = serializers.CharField( help_text="컨테이너 이름", max_length=255, ) # ==================== NKS Advanced ==================== class NksNodeGroupSerializer(serializers.Serializer): """NKS 노드 그룹 생성 요청""" nodegroup_name = serializers.CharField( help_text="노드 그룹 이름", max_length=255, ) instance_type = serializers.CharField( help_text="인스턴스 타입 (Flavor ID)", ) node_count = serializers.IntegerField( help_text="노드 수", default=1, min_value=1, max_value=100, ) availability_zone = serializers.CharField( help_text="가용 영역 (예: kr-pub-a)", required=False, ) boot_volume_size = serializers.IntegerField( help_text="부팅 볼륨 크기 (GB)", default=50, min_value=50, max_value=1000, ) boot_volume_type = serializers.CharField( help_text="볼륨 타입", default="General SSD", ) class NksNodeActionSerializer(serializers.Serializer): """워커 노드 액션 요청""" node_id = serializers.CharField( help_text="노드 ID", ) class NksClusterResizeSerializer(serializers.Serializer): """클러스터 리사이즈 요청""" node_count = serializers.IntegerField( help_text="조정할 노드 수", min_value=1, max_value=100, ) class NksClusterUpgradeSerializer(serializers.Serializer): """클러스터 업그레이드 요청""" kubernetes_version = serializers.CharField( help_text="업그레이드할 Kubernetes 버전 (예: v1.28.3)", ) class NksAutoscaleConfigSerializer(serializers.Serializer): """오토스케일러 설정 요청""" ca_enable = serializers.BooleanField( help_text="오토스케일러 활성화 여부", ) ca_max_node_count = serializers.IntegerField( help_text="최대 노드 수", required=False, min_value=1, max_value=100, ) ca_min_node_count = serializers.IntegerField( help_text="최소 노드 수", required=False, min_value=0, max_value=100, ) ca_scale_down_enable = serializers.BooleanField( help_text="스케일 다운 활성화 여부", required=False, ) ca_scale_down_delay_after_add = serializers.IntegerField( help_text="스케일 다운 지연 시간 (분)", required=False, ) ca_scale_down_unneeded_time = serializers.IntegerField( help_text="불필요 노드 대기 시간 (분)", required=False, ) class NksNodeGroupUpgradeSerializer(serializers.Serializer): """노드 그룹 업그레이드 요청""" kubernetes_version = serializers.CharField( help_text="업그레이드할 Kubernetes 버전", ) max_unavailable_worker = serializers.IntegerField( help_text="동시 업그레이드 가능한 노드 수", default=1, min_value=1, ) class NksNodeGroupUpdateSerializer(serializers.Serializer): """노드 그룹 설정 변경 요청""" instance_type = serializers.CharField( help_text="인스턴스 타입 (Flavor ID)", required=False, ) node_count = serializers.IntegerField( help_text="노드 수", required=False, min_value=0, max_value=100, ) class NksUserScriptSerializer(serializers.Serializer): """사용자 스크립트 설정 요청""" userscript = serializers.CharField( help_text="사용자 스크립트 내용", ) class NksApiEndpointIpAclSerializer(serializers.Serializer): """API 엔드포인트 IP 접근 제어 요청""" enable = serializers.BooleanField( help_text="IP 접근 제어 활성화 여부", ) allowed_cidrs = serializers.ListField( child=serializers.CharField(), help_text="허용할 CIDR 목록", required=False, ) # ==================== DNS Plus ==================== class DnsZoneSerializer(serializers.Serializer): """DNS Zone 생성 요청""" zone_name = serializers.CharField( help_text="Zone 이름 (도메인, 예: example.com.)", max_length=255, ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, ) class DnsZoneUpdateSerializer(serializers.Serializer): """DNS Zone 수정 요청""" description = serializers.CharField( help_text="설명", ) class DnsRecordSerializer(serializers.Serializer): """DNS 레코드""" recordContent = serializers.CharField( help_text="레코드 내용", ) recordDisabled = serializers.BooleanField( help_text="비활성화 여부", default=False, ) class DnsRecordSetSerializer(serializers.Serializer): """DNS 레코드 세트 생성 요청""" recordset_name = serializers.CharField( help_text="레코드 세트 이름", max_length=255, ) recordset_type = serializers.ChoiceField( choices=["A", "AAAA", "CAA", "CNAME", "MX", "NAPTR", "PTR", "TXT", "SRV", "NS"], help_text="레코드 타입", ) recordset_ttl = serializers.IntegerField( help_text="TTL (초)", min_value=1, max_value=2147483647, ) record_list = serializers.ListField( child=DnsRecordSerializer(), help_text="레코드 목록", ) class DnsRecordSetUpdateSerializer(serializers.Serializer): """DNS 레코드 세트 수정 요청""" recordset_type = serializers.ChoiceField( choices=["A", "AAAA", "CAA", "CNAME", "MX", "NAPTR", "PTR", "TXT", "SRV", "NS"], help_text="레코드 타입", ) recordset_ttl = serializers.IntegerField( help_text="TTL (초)", min_value=1, max_value=2147483647, ) record_list = serializers.ListField( child=DnsRecordSerializer(), help_text="레코드 목록", ) class DnsEndpointSerializer(serializers.Serializer): """Pool 엔드포인트""" endpointAddress = serializers.CharField( help_text="엔드포인트 주소 (IP 또는 도메인)", ) endpointWeight = serializers.FloatField( help_text="가중치 (0~1.00)", min_value=0, max_value=1.0, default=1.0, ) endpointDisabled = serializers.BooleanField( help_text="비활성화 여부", default=False, ) class DnsPoolSerializer(serializers.Serializer): """Pool 생성 요청""" pool_name = serializers.CharField( help_text="Pool 이름", max_length=255, ) endpoint_list = serializers.ListField( child=DnsEndpointSerializer(), help_text="엔드포인트 목록", ) pool_disabled = serializers.BooleanField( help_text="비활성화 여부", default=False, ) health_check_id = serializers.CharField( help_text="Health Check ID", required=False, ) class DnsPoolUpdateSerializer(serializers.Serializer): """Pool 수정 요청""" pool_name = serializers.CharField( help_text="Pool 이름", required=False, ) endpoint_list = serializers.ListField( child=DnsEndpointSerializer(), help_text="엔드포인트 목록", required=False, ) pool_disabled = serializers.BooleanField( help_text="비활성화 여부", required=False, ) health_check_id = serializers.CharField( help_text="Health Check ID", required=False, allow_null=True, ) class DnsConnectedPoolSerializer(serializers.Serializer): """GSLB 연결 Pool""" poolId = serializers.CharField( help_text="Pool ID", ) connectedPoolOrder = serializers.IntegerField( help_text="연결 순서 (우선순위)", min_value=1, ) connectedPoolRegionContent = serializers.CharField( help_text="지역 콘텐츠 (GEOLOCATION 규칙 사용 시)", required=False, ) class DnsGslbSerializer(serializers.Serializer): """GSLB 생성 요청""" gslb_name = serializers.CharField( help_text="GSLB 이름", max_length=255, ) gslb_ttl = serializers.IntegerField( help_text="TTL (초)", min_value=1, max_value=2147483647, ) gslb_routing_rule = serializers.ChoiceField( choices=["FAILOVER", "RANDOM", "GEOLOCATION"], help_text="라우팅 규칙", ) gslb_disabled = serializers.BooleanField( help_text="비활성화 여부", default=False, ) connected_pool_list = serializers.ListField( child=DnsConnectedPoolSerializer(), help_text="연결된 Pool 목록", required=False, ) class DnsGslbUpdateSerializer(serializers.Serializer): """GSLB 수정 요청""" gslb_name = serializers.CharField( help_text="GSLB 이름", required=False, ) gslb_ttl = serializers.IntegerField( help_text="TTL (초)", required=False, ) gslb_routing_rule = serializers.ChoiceField( choices=["FAILOVER", "RANDOM", "GEOLOCATION"], help_text="라우팅 규칙", required=False, ) gslb_disabled = serializers.BooleanField( help_text="비활성화 여부", required=False, ) connected_pool_list = serializers.ListField( child=DnsConnectedPoolSerializer(), help_text="연결된 Pool 목록", required=False, ) class DnsPoolConnectSerializer(serializers.Serializer): """GSLB에 Pool 연결 요청""" connected_pool_order = serializers.IntegerField( help_text="연결 순서 (우선순위)", min_value=1, ) connected_pool_region_content = serializers.CharField( help_text="지역 콘텐츠 (GEOLOCATION 규칙 사용 시)", required=False, ) class DnsHealthCheckSerializer(serializers.Serializer): """Health Check 생성 요청""" health_check_name = serializers.CharField( help_text="Health Check 이름", max_length=255, ) health_check_protocol = serializers.ChoiceField( choices=["HTTPS", "HTTP", "TCP"], help_text="프로토콜", ) health_check_port = serializers.IntegerField( help_text="포트", min_value=1, max_value=65535, ) health_check_interval = serializers.IntegerField( help_text="체크 간격 (초)", default=30, min_value=10, max_value=3600, ) health_check_timeout = serializers.IntegerField( help_text="타임아웃 (초)", default=5, min_value=1, max_value=10, ) health_check_retries = serializers.IntegerField( help_text="재시도 횟수", default=2, min_value=1, max_value=10, ) # HTTP/HTTPS 전용 health_check_path = serializers.CharField( help_text="경로 (HTTP/HTTPS 전용)", required=False, ) health_check_expected_codes = serializers.CharField( help_text="예상 응답 코드 (HTTP/HTTPS 전용)", required=False, ) health_check_expected_body = serializers.CharField( help_text="예상 응답 본문 (HTTP/HTTPS 전용)", required=False, ) class DnsHealthCheckUpdateSerializer(serializers.Serializer): """Health Check 수정 요청""" health_check_name = serializers.CharField( help_text="Health Check 이름", required=False, ) health_check_protocol = serializers.ChoiceField( choices=["HTTPS", "HTTP", "TCP"], help_text="프로토콜", required=False, ) health_check_port = serializers.IntegerField( help_text="포트", required=False, ) health_check_interval = serializers.IntegerField( help_text="체크 간격 (초)", required=False, ) health_check_timeout = serializers.IntegerField( help_text="타임아웃 (초)", required=False, ) health_check_retries = serializers.IntegerField( help_text="재시도 횟수", required=False, ) health_check_path = serializers.CharField( help_text="경로 (HTTP/HTTPS 전용)", required=False, ) health_check_expected_codes = serializers.CharField( help_text="예상 응답 코드 (HTTP/HTTPS 전용)", required=False, ) health_check_expected_body = serializers.CharField( help_text="예상 응답 본문 (HTTP/HTTPS 전용)", required=False, ) class DnsIdListSerializer(serializers.Serializer): """ID 목록 요청""" id_list = serializers.ListField( child=serializers.CharField(), help_text="ID 목록", min_length=1, ) # ==================== Load Balancer ==================== class LoadBalancerSerializer(serializers.Serializer): """로드밸런서 생성 요청""" vip_subnet_id = serializers.CharField( help_text="VIP가 할당될 서브넷 ID (필수)", ) name = serializers.CharField( help_text="로드밸런서 이름", required=False, max_length=255, ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, ) vip_address = serializers.CharField( help_text="VIP 주소 (지정하지 않으면 자동 할당)", required=False, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", default=True, ) loadbalancer_type = serializers.ChoiceField( choices=["shared", "dedicated"], help_text="로드밸런서 타입 (shared: 공유형, dedicated: 전용형)", default="shared", ) class LoadBalancerUpdateSerializer(serializers.Serializer): """로드밸런서 수정 요청""" name = serializers.CharField( help_text="로드밸런서 이름", required=False, max_length=255, ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", required=False, ) class LBListenerSerializer(serializers.Serializer): """리스너 생성 요청""" loadbalancer_id = serializers.CharField( help_text="로드밸런서 ID", ) protocol = serializers.ChoiceField( choices=["TCP", "HTTP", "HTTPS", "TERMINATED_HTTPS"], help_text="프로토콜", ) protocol_port = serializers.IntegerField( help_text="포트 번호 (1-65535)", min_value=1, max_value=65535, ) name = serializers.CharField( help_text="리스너 이름", required=False, max_length=255, ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, ) default_pool_id = serializers.CharField( help_text="기본 풀 ID", required=False, ) connection_limit = serializers.IntegerField( help_text="연결 제한 (-1: 무제한)", default=-1, ) keepalive_timeout = serializers.IntegerField( help_text="Keepalive 타임아웃 (초)", default=300, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", default=True, ) default_tls_container_ref = serializers.CharField( help_text="TLS 인증서 컨테이너 참조 (TERMINATED_HTTPS 사용 시)", required=False, ) class LBListenerUpdateSerializer(serializers.Serializer): """리스너 수정 요청""" name = serializers.CharField( help_text="리스너 이름", required=False, max_length=255, ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, ) default_pool_id = serializers.CharField( help_text="기본 풀 ID", required=False, allow_null=True, ) connection_limit = serializers.IntegerField( help_text="연결 제한 (-1: 무제한)", required=False, ) keepalive_timeout = serializers.IntegerField( help_text="Keepalive 타임아웃 (초)", required=False, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", required=False, ) class SessionPersistenceSerializer(serializers.Serializer): """세션 지속성 설정""" type = serializers.ChoiceField( choices=["SOURCE_IP", "HTTP_COOKIE", "APP_COOKIE"], help_text="세션 지속성 타입", ) cookie_name = serializers.CharField( help_text="쿠키 이름 (APP_COOKIE 타입 사용 시)", required=False, ) class LBPoolSerializer(serializers.Serializer): """풀 생성 요청""" lb_algorithm = serializers.ChoiceField( choices=["ROUND_ROBIN", "LEAST_CONNECTIONS", "SOURCE_IP"], help_text="로드밸런싱 알고리즘", ) protocol = serializers.ChoiceField( choices=["TCP", "HTTP", "HTTPS", "PROXY"], help_text="프로토콜", ) loadbalancer_id = serializers.CharField( help_text="로드밸런서 ID (listener_id와 둘 중 하나 필수)", required=False, ) listener_id = serializers.CharField( help_text="리스너 ID (loadbalancer_id와 둘 중 하나 필수)", required=False, ) name = serializers.CharField( help_text="풀 이름", required=False, max_length=255, ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", default=True, ) session_persistence = SessionPersistenceSerializer( help_text="세션 지속성 설정", required=False, ) class LBPoolUpdateSerializer(serializers.Serializer): """풀 수정 요청""" name = serializers.CharField( help_text="풀 이름", required=False, max_length=255, ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, ) lb_algorithm = serializers.ChoiceField( choices=["ROUND_ROBIN", "LEAST_CONNECTIONS", "SOURCE_IP"], help_text="로드밸런싱 알고리즘", required=False, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", required=False, ) session_persistence = SessionPersistenceSerializer( help_text="세션 지속성 설정", required=False, allow_null=True, ) class LBMemberSerializer(serializers.Serializer): """멤버 추가 요청""" address = serializers.CharField( help_text="멤버 IP 주소", ) protocol_port = serializers.IntegerField( help_text="멤버 포트 번호", min_value=1, max_value=65535, ) subnet_id = serializers.CharField( help_text="멤버가 속한 서브넷 ID", required=False, ) weight = serializers.IntegerField( help_text="가중치 (1-256)", default=1, min_value=1, max_value=256, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", default=True, ) class LBMemberUpdateSerializer(serializers.Serializer): """멤버 수정 요청""" weight = serializers.IntegerField( help_text="가중치 (1-256)", required=False, min_value=1, max_value=256, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", required=False, ) class LBHealthMonitorSerializer(serializers.Serializer): """헬스 모니터 생성 요청""" pool_id = serializers.CharField( help_text="풀 ID", ) type = serializers.ChoiceField( choices=["TCP", "HTTP", "HTTPS"], help_text="헬스 체크 타입", ) delay = serializers.IntegerField( help_text="헬스 체크 간격 (초)", min_value=1, ) timeout = serializers.IntegerField( help_text="응답 대기 시간 (초)", min_value=1, ) max_retries = serializers.IntegerField( help_text="최대 재시도 횟수 (정상 판정)", min_value=1, max_value=10, ) max_retries_down = serializers.IntegerField( help_text="최대 재시도 횟수 (비정상 판정)", default=3, min_value=1, max_value=10, ) http_method = serializers.ChoiceField( choices=["GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "OPTIONS", "CONNECT", "PATCH"], help_text="HTTP 메서드 (HTTP/HTTPS 타입 시)", default="GET", ) url_path = serializers.CharField( help_text="URL 경로 (HTTP/HTTPS 타입 시)", default="/", ) expected_codes = serializers.CharField( help_text="예상 응답 코드 (예: 200, 200,201, 200-204)", default="200", ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", default=True, ) host_header = serializers.CharField( help_text="Host 헤더 값", required=False, ) class LBHealthMonitorUpdateSerializer(serializers.Serializer): """헬스 모니터 수정 요청""" delay = serializers.IntegerField( help_text="헬스 체크 간격 (초)", required=False, min_value=1, ) timeout = serializers.IntegerField( help_text="응답 대기 시간 (초)", required=False, min_value=1, ) max_retries = serializers.IntegerField( help_text="최대 재시도 횟수 (정상 판정)", required=False, min_value=1, max_value=10, ) max_retries_down = serializers.IntegerField( help_text="최대 재시도 횟수 (비정상 판정)", required=False, min_value=1, max_value=10, ) http_method = serializers.ChoiceField( choices=["GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "OPTIONS", "CONNECT", "PATCH"], help_text="HTTP 메서드", required=False, ) url_path = serializers.CharField( help_text="URL 경로", required=False, ) expected_codes = serializers.CharField( help_text="예상 응답 코드", required=False, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", required=False, ) host_header = serializers.CharField( help_text="Host 헤더 값", required=False, ) class LBL7PolicySerializer(serializers.Serializer): """L7 정책 생성 요청""" listener_id = serializers.CharField( help_text="리스너 ID", ) action = serializers.ChoiceField( choices=["REDIRECT_TO_POOL", "REDIRECT_TO_URL", "REJECT"], help_text="액션", ) position = serializers.IntegerField( help_text="정책 우선순위 (낮을수록 먼저 적용)", default=1, min_value=1, ) name = serializers.CharField( help_text="정책 이름", required=False, max_length=255, ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, ) redirect_pool_id = serializers.CharField( help_text="리다이렉트 대상 풀 ID (REDIRECT_TO_POOL 액션 시)", required=False, ) redirect_url = serializers.CharField( help_text="리다이렉트 URL (REDIRECT_TO_URL 액션 시)", required=False, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", default=True, ) class LBL7PolicyUpdateSerializer(serializers.Serializer): """L7 정책 수정 요청""" name = serializers.CharField( help_text="정책 이름", required=False, max_length=255, ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, ) action = serializers.ChoiceField( choices=["REDIRECT_TO_POOL", "REDIRECT_TO_URL", "REJECT"], help_text="액션", required=False, ) position = serializers.IntegerField( help_text="정책 우선순위", required=False, min_value=1, ) redirect_pool_id = serializers.CharField( help_text="리다이렉트 대상 풀 ID", required=False, allow_null=True, ) redirect_url = serializers.CharField( help_text="리다이렉트 URL", required=False, allow_null=True, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", required=False, ) class LBL7RuleSerializer(serializers.Serializer): """L7 룰 생성 요청""" type = serializers.ChoiceField( choices=["COOKIE", "FILE_TYPE", "HEADER", "HOST_NAME", "PATH"], help_text="룰 타입", ) compare_type = serializers.ChoiceField( choices=["CONTAINS", "ENDS_WITH", "STARTS_WITH", "EQUAL_TO", "REGEX"], help_text="비교 방식", ) value = serializers.CharField( help_text="비교할 값", ) key = serializers.CharField( help_text="키 값 (COOKIE, HEADER 타입 사용 시)", required=False, ) invert = serializers.BooleanField( help_text="조건 반전 여부", default=False, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", default=True, ) class LBL7RuleUpdateSerializer(serializers.Serializer): """L7 룰 수정 요청""" type = serializers.ChoiceField( choices=["COOKIE", "FILE_TYPE", "HEADER", "HOST_NAME", "PATH"], help_text="룰 타입", required=False, ) compare_type = serializers.ChoiceField( choices=["CONTAINS", "ENDS_WITH", "STARTS_WITH", "EQUAL_TO", "REGEX"], help_text="비교 방식", required=False, ) value = serializers.CharField( help_text="비교할 값", required=False, ) key = serializers.CharField( help_text="키 값", required=False, allow_null=True, ) invert = serializers.BooleanField( help_text="조건 반전 여부", required=False, ) admin_state_up = serializers.BooleanField( help_text="관리자 상태", required=False, ) class LBIpAclTargetSerializer(serializers.Serializer): """IP ACL 타깃""" ip_address = serializers.CharField( help_text="IP 주소 또는 CIDR (예: 10.0.0.1, 10.0.0.0/24)", ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, ) class LBIpAclGroupSerializer(serializers.Serializer): """IP ACL 그룹 생성 요청""" action = serializers.ChoiceField( choices=["ALLOW", "DENY"], help_text="액션 (ALLOW 또는 DENY)", ) name = serializers.CharField( help_text="그룹 이름", required=False, max_length=255, ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, ) ipacl_targets = serializers.ListField( child=LBIpAclTargetSerializer(), help_text="IP ACL 타깃 목록", required=False, ) loadbalancers = serializers.ListField( child=serializers.CharField(), help_text="적용할 로드밸런서 ID 목록", required=False, ) class LBIpAclGroupUpdateSerializer(serializers.Serializer): """IP ACL 그룹 수정 요청""" name = serializers.CharField( help_text="그룹 이름", required=False, max_length=255, ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, ) loadbalancers = serializers.ListField( child=serializers.CharField(), help_text="적용할 로드밸런서 ID 목록", required=False, ) class LBIpAclTargetCreateSerializer(serializers.Serializer): """IP ACL 타깃 추가 요청""" ipacl_group_id = serializers.CharField( help_text="IP ACL 그룹 ID", ) ip_address = serializers.CharField( help_text="IP 주소 또는 CIDR (예: 10.0.0.1, 10.0.0.0/24)", ) description = serializers.CharField( help_text="설명", required=False, allow_blank=True, )