import logging import dotmap from kubernetes import client from src import util from src.context import env, get_infra_api_cli from . import base CR_GROUP = "cloud.pingcap.com" CR_VERSION = "v1" logger = logging.getLogger('oncall_master.suspicions.crossplane') class BaseCrossplane(base.SuspicionABC): def __init__(self, *args, **kwargs): """ :param project_id: :param kwargs: """ super().__init__(*args, **kwargs) ctx = kwargs["ctx"] self.infra_api_k8s_cli = get_infra_api_cli() self.cr_api = client.CustomObjectsApi(api_client=self.infra_api_k8s_cli) self.project_id = ctx.project_id self.network_name = ctx.network_name self.namespace = f"{env.STAGE}-{self.project_id}" self.network = util.get_namespaced_cr(self.cr_api, CR_GROUP, CR_VERSION, self.namespace, "networks", self.network_name) class NetworkUsedCrossplaneCRsRemain(BaseCrossplane): def verify(self) -> bool: label_selector = { 'tidbcloud-namespace': self.namespace, 'tidbcloud-network': self.network_name } uk2crs = util.list_cluster_crs_by_category( self.infra_api_k8s_cli, 'crossplane', label_selector=util.build_label_selector(label_selector) ) remaining_crs = [] for uk, crs in uk2crs.items(): if not crs: continue if uk == 'ec2.aws.crossplane.io/vpcs': self.check_why_vpc_delete_failed(crs) remaining_crs.extend(crs) if remaining_crs: self._solution.append('find why `remaining_crs` remain here') self.info['remaining_crs'] = remaining_crs return len(remaining_crs) != 0 def check_why_vpc_delete_failed(self, vpcs: list[dotmap.DotMap]): for vpc in vpcs: if not vpc.metadata.deletionTimestamp: self._solution.append(f'{vpc.kind}/{vpc.metadata.name} is undeleted') continue synced_condition = None for condition in vpc.status.conditions: if condition.type == 'Synced': synced_condition = condition break if synced_condition: self._solution.append( f'{vpc.kind}/{vpc.metadata.name} is not synced, reason: {synced_condition.reason}, message: {synced_condition.message}') if 'has dependencies and cannot be deleted' in synced_condition.message: atProvider = vpc.status.atProvider self._solution.append( f'try manually delete' f'` AWS_PROFILE={atProvider.ownerId} aws ec2 delete-vpc --vpc-id {atProvider.vpcId} --region {vpc.spec.forProvider.region}`' ) # Before you can delete a VPC using the command line, you must terminate or delete any resources that # created a requester-managed network interface in the VPC. You must also delete or detach all VPC resources # that you created, such as subnets, security groups, network ACLs, route tables, internet gateways, # and egress-only internet gateways. You do not need to delete the default security group, # default route table, or default network ACL. # https://docs.aws.amazon.com/vpc/latest/userguide/vpc-delete.html