def delete_poddefaults_from_user_namespaces( poddefaults: List[Dict[str, Any]], user_namespaces: List[str], client: DynamicClient, logger: kopf.Logger, ) -> None: logger.debug( "Deleting PodDefaults %s from user Namespaces %s", [pd["metadata"]["name"] for pd in poddefaults], user_namespaces, ) for poddefault in poddefaults: for namespace in user_namespaces: try: delete_poddefault( namespace=namespace, name=poddefault["metadata"]["name"], client=client, logger=logger, ) except Exception as e: logger.warn( "Unable to delete PodDefault %s from Namespace %s: %s", poddefault["metadata"]["name"], namespace, str(e), )
def _patch_and_delete_stubborn_custom_resources( # type: ignore group: str, version: str, plural: str, namespace: str, status_element: str, logger: kopf.Logger, use_async=True, **_: Any, ): logger.info(f"_patch_and_delete_stubborn_custom_resources for {plural}.{group} in namespace {namespace}") co = CustomObjectsApi() resp = co.list_namespaced_custom_object(group=group, version=version, plural=plural, namespace=namespace) failed_res = [ item.get("metadata").get("name") for item in resp["items"] if item.get("status", {}).get(status_element) in ["Failed", "Completed", "InProgress"] ] for item in failed_res: try: logger.info(f"Patching item {item} in {plural}.{group}") patch = json.loads("""{"metadata":{"finalizers":[]}}""") co.patch_namespaced_custom_object( group=group, version=version, plural=plural, namespace=namespace, name=item, body=patch ) logger.info(f"Deleting item {item} in {plural}.{group}") co.delete_namespaced_custom_object( group=group, version=version, plural=plural, namespace=namespace, name=item, ) except ApiException as e: logger.warn("Trying to patch and delete failed: %s\n" % e)
def _delete_pods(namespace: str, logger: kopf.Logger, use_async=True, **_: Any): # type: ignore logger.info(f"Deleting ALL PODS in ns {namespace}") api = CoreV1Api() try: api.delete_collection_namespaced_pod( namespace=namespace, async_req=use_async, grace_period_seconds=0, propagation_policy="Background", body=V1DeleteOptions(), ) except ApiException as e: logger.warn("calling CustomObjectsApi->delete_collection_namespaced_pod: %s\n" % e)
def _remove_user_namespaces(namespace: str, team_spec: str, logger: kopf.Logger, **_: Any): # type: ignore logger.info( f"Removing all user namespaces with labels orbit/team={team_spec},orbit/space=user in namespace {namespace} " ) v1 = CoreV1Api() label_selector = f"orbit/team={team_spec},orbit/space=user" all_namespaces = v1.list_namespace(label_selector=label_selector).to_dict() all_ns = [ item.get("metadata").get("name") for item in all_namespaces["items"] if item.get("metadata", {}).get("name") ] for ns in all_ns: logger.info(f"Calling delete namespace {ns}") try: v1.delete_namespace(name=ns, async_req=True) except ApiException as e: logger.warn("calling CoreV1API->delete_namespace had an error: %s\n" % e)
def _delete_custom_objects( # type: ignore group: str, version: str, plural: str, namespace: str, logger: kopf.Logger, use_async=True, **_: Any ): logger.info(f"Deleting {plural}.{group} in ns {namespace}") co = CustomObjectsApi() try: resp = co.delete_collection_namespaced_custom_object( group=group, version=version, namespace=namespace, plural=plural, grace_period_seconds=0, propagation_policy="Background", pretty="true", async_req=use_async, body=V1DeleteOptions(), ) return resp except ApiException as e: logger.warn("calling CustomObjectsApi->delete_collection_namespaced_custom_object: %s\n" % e) logger.warn("Assume it did not exist")
def update_pod_images( namespace: str, labels: kopf.Labels, body: kopf.Body, patch: kopf.Patch, dryrun: bool, logger: kopf.Logger, warnings: List[str], namespaces_idx: kopf.Index[str, Dict[str, Any]], podsettings_idx: kopf.Index[str, Dict[str, Any]], **_: Any, ) -> kopf.Patch: if dryrun: logger.debug("DryRun - Skip Pod Mutation") return patch # This is a hack to get the only namespace from the index Store ns: Dict[str, Any] = {} for ns in cast(List[Dict[str, Any]], namespaces_idx.get(namespace, [{}])): logger.debug("Namespace: %s", ns) team = ns.get("labels", {}).get("orbit/team", None) if not team: logger.info("No 'orbit/team' label found on Pod's Namespace: %s", namespace) # warnings.append(f"No 'orbit/team' label found on Pod's Namespace: {namespace}") return patch team_podsettings: List[Dict[str, Any]] = cast(List[Dict[str, Any]], podsettings_idx.get(team, [])) if not team_podsettings: logger.info("No PodSettings found for Pod's Team: %s", team) # warnings.append(f"No PodSettings found for Pod's Team: {team}") return patch fitlered_podsettings = podsetting_utils.filter_podsettings( podsettings=team_podsettings, pod_labels=labels, logger=logger ) if not fitlered_podsettings: logger.info("No PodSetting Selectors matched the Pod") return patch applied_podsetting_names = [] body_dict = { "metadata": {k: v for k, v in body["metadata"].items()}, "spec": {k: v for k, v in body["spec"].items()}, } logger.debug("BodyDict: %s", body_dict) mutable_body = deepcopy(body) for podsetting in fitlered_podsettings: try: podsetting_utils.apply_settings_to_pod(namespace=ns, podsetting=podsetting, pod=mutable_body, logger=logger) applied_podsetting_names.append(podsetting["name"]) except Exception as e: logger.exception("Error applying PodSetting %s: %s", podsetting["name"], str(e)) warnings.append(f"Error applying PodSetting {podsetting['name']}: {str(e)}") if body_dict["spec"] == mutable_body["spec"] and body_dict["metadata"] == mutable_body["metadata"]: logger.warn("PodSetting Selectors matched the Pod but no changes were applied") warnings.append("PodSetting Selectors matched the Pod but no changes were applied") return patch patch["metadata"] = {} patch["metadata"]["annotations"] = { **mutable_body["metadata"].get("annotations", {}), **{"orbit/applied-podsettings": ",".join(applied_podsetting_names)}, } patch["metadata"]["annotations"] = {k.replace("/", "~1"): v for k, v in patch["metadata"]["annotations"].items()} if "labels" in mutable_body["metadata"]: patch["metadata"]["labels"] = {k.replace("/", "~1"): v for k, v in mutable_body["metadata"]["labels"].items()} patch["spec"] = mutable_body["spec"] logger.info("Applying Patch %s", patch) return patch