import logging import os import pickle import dotmap from gevent import pool from kubernetes import client from kubernetes.client import api, models from . import decorator logger = logging.getLogger("oncall_master.util") def get_cluster_cr(cr_api: api.CustomObjectsApi, group: str, version: str, plural: str, name: str) -> dotmap.DotMap | None: try: resp = cr_api.get_cluster_custom_object(group, version, plural, name, ) except client.exceptions.ApiException as e: if e.status == 404: logger.info(f"cr{plural}.{group}/{version} {name} not found", ) return None else: raise return dotmap.DotMap(resp) def list_cluster_crs(cr_api: api.CustomObjectsApi, group: str, version: str, plural: str, **kwargs) -> list[ dotmap.DotMap]: try: resp = cr_api.list_cluster_custom_object(group, version, plural, **kwargs) except client.exceptions.ApiException as e: raise out: list[dotmap.DotMap] = [] for item in resp["items"]: out.append(dotmap.DotMap(item)) return out def get_namespaced_cr(cr_api: api.CustomObjectsApi, group: str, version: str, ns: str, plural: str, name: str) -> dotmap.DotMap | None: try: resp = cr_api.get_namespaced_custom_object(group, version, ns, plural, name, ) except client.exceptions.ApiException as e: if e.status == 404: logger.info(f"CR {plural}.{group}/{version} {name} in {ns} not found", ) return None else: raise return dotmap.DotMap(resp) def list_namespaced_cr(cr_api: api.CustomObjectsApi, group: str, version: str, ns: str, plural: str, **kwargs) -> list[dotmap.DotMap] | None: try: resp = cr_api.list_namespaced_custom_object(group, version, ns, plural, **kwargs) except client.exceptions.ApiException as e: raise out: list[dotmap.DotMap] = [] for item in resp["items"]: out.append(dotmap.DotMap(item)) return out @decorator.run_once def list_crds(api: client.ApiextensionsV1Api) -> list[models.V1CustomResourceDefinition]: if os.path.exists('crds.pickle'): logger.info('load CRDs from disk') with open('crds.pickle', 'rb') as f: return pickle.load(f) else: logger.info('list CRDs from api-server start...') resp: models.V1CustomResourceDefinitionList = api.list_custom_resource_definition() logger.info('list CRDs from api-server end...') logger.info('dumps CRds in to disk') with open('crds.pickle', 'wb') as f: pickle.dump(resp.items, f) return resp.items def list_crds_by_category(k8s_cli: client.ApiClient, category: str) -> list[models.V1CustomResourceDefinition]: api = client.ApiextensionsV1Api(k8s_cli) crds = list_crds(api) results = [] for crd in crds: if not crd.spec.names.categories: continue if category in crd.spec.names.categories: results.append(crd) logger.info(f'{category} CRDs: {len(results)}') return results def list_cluster_crs_by_category(k8s_cli: client.ApiClient, category: str, **kwargs) -> dict[str, list[dotmap.DotMap]]: cr_api = client.CustomObjectsApi(api_client=k8s_cli) crds = list_crds_by_category(k8s_cli, category) out = {} p = pool.Pool(15) for crd in crds: def wrap(crd): version = crd.spec.versions[0].name crs = list_cluster_crs(cr_api, crd.spec.group, version, crd.spec.names.plural, **kwargs) out[f'{crd.spec.group}/{crd.spec.names.plural}'] = crs p.spawn(wrap, crd) p.join() return out