#### # detect the leaked gcp vm instance on dev environments # it will be added into gcloud function later ### import json import subprocess import os import argparse import yaml from kubernetes import client, config import base64 import time import csv from datetime import datetime result = subprocess.run(['gcloud', 'compute', 'instances', 'list', '--format', 'json'], stdout=subprocess.PIPE) instancesDict = json.loads(result.stdout) instances = [] for instance in instancesDict: name = '' if 'name' in instance: name = instance['name'] instances.append([instance['id'], name, instance['zone'], instance['selfLink'], instance['machineType'], instance['creationTimestamp']]) # gkeClusters = { # "staging-seed-asia-northeast1-83d8caa": "asia-northeast1", # "staging-seed-asia-southeast1-b7bc5b9": "asia-southeast1", # "staging-seed-us-central1-6159679": "us-central1", # "dev-seed-us-west1-3137aff": "us-west1", # "stability-seed-us-west1-67ac24a": "us-west1", # "staging-seed-us-west1-73cb72c": "us-west1", # "dev-seed-us-west2-9f7b847": "us-west2" # } gkeClusters = { "prod-seed-asia-northeast1-85509b9": "asia-northeast1", "prod-seed-asia-southeast1-f7a3983": "asia-southeast1", "prod-seed-us-central1-e5cf570": "us-central1", "prod-seed-us-west1-d5ae263": "us-west1", } outfile = 'instance.csv' csvFile = open(outfile, 'w', newline='') fieldnames = ['id', 'name', 'zone', 'machineType', 'creationTimestamp', 'selfLink'] writer = csv.DictWriter(csvFile, fieldnames=fieldnames) writer.writeheader() allRunInstances = [] def process_gke_clusters(): for gke in gkeClusters: os.system("gcloud container clusters get-credentials {} --region {}".format(gke, gkeClusters[gke])) config.kube_config.load_kube_config() apiClient = client.CoreV1Api() nodes = apiClient.list_node() for node in nodes.items: print("process gke {} node {}".format(gke, node.metadata.name)) allRunInstances.append(node.metadata.name) gardenerConfig = ["gardener-dev", "gardener-staging", "gardener-stability"] def process_all_shoot_clusters(): for gke in gkeClusters: os.system("gcloud container clusters get-credentials {} --region {}".format(gke, gkeClusters[gke])) config.kube_config.load_kube_config() apiClient = client.CoreV1Api() namespaces = apiClient.list_namespace() for ns in namespaces.items: os.system("gcloud container clusters get-credentials {} --region {}".format(gke, gkeClusters[gke])) config.kube_config.load_kube_config() apiClient = client.CoreV1Api() if 'shoot--' not in ns.metadata.name: continue print("process shoot {}".format(ns.metadata.name)) try: shootKubeconfig = apiClient.read_namespaced_secret('kubecfg', ns.metadata.name) shootKubeconfig = shootKubeconfig.data["kubeconfig"] shootKubeconfig = base64.b64decode(shootKubeconfig) shootKubeconfigFile = open(ns.metadata.name, "w") yaml.dump(yaml.load(shootKubeconfig), shootKubeconfigFile) shootKubeconfigFile.close() config.kube_config.load_kube_config(config_file=ns.metadata.name) apiClient = client.CoreV1Api() nodes = apiClient.list_node() namespaces = apiClient.list_namespace() pods = [] for ns in namespaces.items: namespaced_pods = apiClient.list_namespaced_pod(ns.metadata.name) for pod in namespaced_pods.items: pods.append(pod) for node in nodes.items: print("process shoot {} node {}".format(ns.metadata.name, node.metadata.name)) if "master" in node.metadata.name: allRunInstances.append(node.metadata.name) nodeFoundIt = False for pod in pods: if 'extra' in pod.metadata.name or \ 'db-pd' in pod.metadata.name or \ 'db-tidb' in pod.metadata.name or \ 'db-tikv' in pod.metadata.name or \ 'db-discovery' in pod.metadata.name or \ 'db-monitor' in pod.metadata.name: try: if pod.spec.node_name == node.metadata.name: nodeFoundIt = True break except Exception as e: print("bypass pod {}, because of {}".format(pod.metadata.name, str(e))) if nodeFoundIt: allRunInstances.append(node.metadata.name) except Exception as e: print("bypass shoot {}, because of {}".format(ns.metadata.name, str(e))) process_gke_clusters() process_all_shoot_clusters() for instance in allRunInstances: print(instance) for instance in instances: foundIt = False for runInstance in allRunInstances: if runInstance == instance[1]: foundIt = True seps = str.split(instance[4], '/') machineType = seps[len(seps) - 1] seps = str.split(instance[2], '/') region = seps[len(seps) - 1] if not foundIt: writer.writerow({ 'id': instance[0], 'name': instance[1], 'machineType': machineType, 'creationTimestamp': instance[5], 'zone': region, 'selfLink': instance[3]}) csvFile.close()