From 44e47c7e69c48a65785bcc37028d5331350058ff Mon Sep 17 00:00:00 2001 From: Juan Pardo Date: Wed, 19 Jul 2023 17:03:23 +0200 Subject: [PATCH] Fixed deleting a cluster while restoring/cloning --- CHANGES.rst | 3 +++ crate/operator/main.py | 12 +++++++++++- crate/operator/operations.py | 21 +++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 545f3495..52586547 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Changelog Unreleased ---------- +* Fixed a bug that lead to the namespace not being deleted after deleting a cluster + that had a snapshot restore/clone operation in progress. + 2.30.1 (2023-07-06) ------------------- diff --git a/crate/operator/main.py b/crate/operator/main.py index df43e309..c792d814 100644 --- a/crate/operator/main.py +++ b/crate/operator/main.py @@ -52,7 +52,10 @@ update_user_password_secret, ) from crate.operator.kube_auth import login_via_kubernetes_asyncio -from crate.operator.operations import update_sql_exporter_configmap +from crate.operator.operations import ( + is_namespace_terminating, + update_sql_exporter_configmap, +) from crate.operator.restore_backup import is_valid_snapshot from crate.operator.utils import crate from crate.operator.webhooks import webhook_client @@ -198,6 +201,13 @@ async def cluster_restore( """ Handles field changes which trigger restoring data from a backup. """ + + # Ensure the namespace is not terminating. Otherwise end with a permanent error. + if await is_namespace_terminating(namespace): + raise kopf.PermanentError( + "The namespace for the target operation is terminating" + ) + await restore_backup(namespace, name, diff, new, patch, status, started, logger) diff --git a/crate/operator/operations.py b/crate/operator/operations.py index 8080e442..f7d9e121 100644 --- a/crate/operator/operations.py +++ b/crate/operator/operations.py @@ -37,6 +37,7 @@ V1CronJobList, V1JobList, V1JobStatus, + V1Namespace, V1PersistentVolumeClaimList, V1PodList, V1Service, @@ -240,6 +241,26 @@ async def get_pods_in_deployment( return [{"uid": p.metadata.uid, "name": p.metadata.name} for p in all_pods.items] +async def get_namespace_resource(namespace_name: str) -> V1Namespace: + """ + Return the CrateDB custom resource. + + :param namespace_ am e: The Kubernetes namespace name to look up. + """ + async with ApiClient() as api_client: + core = CoreV1Api(api_client) + namespaces = await core.list_namespace() + for ns in namespaces.items: + if ns.metadata.name == namespace_name: + return ns + return None + + +async def is_namespace_terminating(namespace_name: str) -> bool: + namespace_obj = await get_namespace_resource(namespace_name) + return namespace_obj and namespace_obj.status.phase == "Terminating" + + async def get_cratedb_resource(namespace: str, name: str) -> dict: """ Return the CrateDB custom resource.