import json from analyst.libs import util from analyst.libs.consts import * from analyst.resource_leak import settings from analyst.resource_leak.model import * env2clinic_address = { 'dev': 'https://dev-clinic.pingcap.com/portal/#/clusters?page=1&pageSize=20&query={cluster_id}&showDeleted=true', 'staging': 'https://staging-clinic.pingcap.com/portal/#/clusters?page=1&pageSize=20&query={cluster_id}&showDeleted=true', 'prod': 'https://clinic.pingcap.com/portal/#/clusters?page=1&pageSize=20&query={cluster_id}&showDeleted=true', } def get_cluster_clinic_link(record: CloudAsset): # this cloud resource doesn't belong to any cluster if not util.CLUSTER_ID_RE.match(record.cluster_id): return '' addr = env2clinic_address.get(record.env) if not addr: return '' return addr.format(cluster_id=record.cluster_id) def label_empty(v: str) -> bool: return v == '' or v == 'null' def required_label_missed(r: CloudAsset) -> (bool, str): missed = False reasons = [] if label_empty(r.env): missed = True reasons.append('env') if label_empty(r.provider): missed = True reasons.append('provider') if label_empty(r.account_id): missed = True reasons.append('account_id') if label_empty(r.region): missed = True reasons.append('region') if label_empty(r.service_type): missed = True reasons.append('service_type') if label_empty(r.usedby): missed = True reasons.append('usedby') if r.arch != Arch.ThreeLayers \ and r.usedby in {UsedBy.DBaaSControlPlaneShoot} \ and label_empty(r.network_name): missed = True reasons.append('network_name') if r.arch != Arch.ThreeLayers \ and (r.product not in {AWSProduct.EBS, GCPProduct.Disk, AWSProduct.VPC, GCPProduct.VPC} and r.usedby not in {UsedBy.DBaaSControlPlaneSeed, UsedBy.DBaaSControlPlaneSeed} and label_empty(r.vpc_name)): missed = True reasons.append('vpc_name') if r.arch != Arch.ThreeLayers \ and (r.product not in {AWSProduct.EBS, GCPProduct.Disk} and r.usedby not in {UsedBy.DBaaSControlPlaneSeed, UsedBy.DBaaSControlPlaneSeed} and label_empty(r.k8s_name)): missed = True reasons.append('k8s_name') if missed: return missed, 'miss labels: ' + ','.join(reasons) else: return False, '' if __name__ == '__main__': from playhouse.shortcuts import model_to_dict init_db(create_db_instance()) # list all cloud resources, dedicated, serverless, etc resources_in_db: list[CloudAsset] = CloudAsset.select() results = [] for each in resources_in_db: # filter out deleted cloud resources which haven't status 'leaked', 'cleaned' if each.resource_deleted_at and each.status not in (ResourceUseState.Leaked, ResourceUseState.Cleaned): continue data: dict = model_to_dict(each) data['id'] = data['id'] data['usedby'] = data['_usedby'] data['network_name'] = data['_network_name'] data['show_tags'] = [] data['show_tags'].append(data['status']) if each.resource_deleted_at: data['show_tags'].append(ShowTag.Deleted) miss_label, reason = required_label_missed(each) if miss_label: data['show_tags'].append(ShowTag.MissLabel) data['reason'] = data['reason'] + '; ' + reason data['cluster_clinic_link'] = get_cluster_clinic_link(each) data['extra_info'] = json.dumps(data['extra_info']) # TODO(chenfei): # 1. add cluster CR status # 2. add network CR status and the cluster count in this network CR results.append(data) json.dump(results, open( settings.LEAK_ANALYSIS_RESULT_FILE, 'w'), indent=4, default=util.more)