From 4cc2f0c35511a59897be21201e9edf7a17893497 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Sun, 12 Apr 2026 14:24:17 -0300 Subject: [PATCH] cleanup(jenkins): gate orphan volume deletes by pvc namespace --- ariadne/services/jenkins_workspace_cleanup.py | 10 +++++++++- tests/test_jenkins_workspace_cleanup.py | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/ariadne/services/jenkins_workspace_cleanup.py b/ariadne/services/jenkins_workspace_cleanup.py index 5058b29..19949a9 100644 --- a/ariadne/services/jenkins_workspace_cleanup.py +++ b/ariadne/services/jenkins_workspace_cleanup.py @@ -263,6 +263,7 @@ def _workspace_longhorn_candidates(all_pv_names: set[str], removed_pv_names: set labels = metadata.get("labels") if isinstance(metadata.get("labels"), dict) else {} pvc_name = labels.get("kubernetes.io/created-for/pvc/name") + pvc_namespace = labels.get("kubernetes.io/created-for/pvc/namespace") robust_state = status.get("robustness") state = status.get("state") attached = status.get("isAttached") @@ -270,7 +271,14 @@ def _workspace_longhorn_candidates(all_pv_names: set[str], removed_pv_names: set should_delete = False if name in removed_pv_names: should_delete = True - elif _is_workspace_name(pvc_name) and name not in all_pv_names: + elif ( + _is_workspace_name(pvc_name) + and name not in all_pv_names + and ( + pvc_namespace in {None, ""} + or pvc_namespace == settings.jenkins_workspace_namespace + ) + ): should_delete = True if not should_delete: continue diff --git a/tests/test_jenkins_workspace_cleanup.py b/tests/test_jenkins_workspace_cleanup.py index a928208..9b347a6 100644 --- a/tests/test_jenkins_workspace_cleanup.py +++ b/tests/test_jenkins_workspace_cleanup.py @@ -111,6 +111,7 @@ def _fake_payloads(now_iso: str, old_iso: str) -> dict[str, dict[str, object]]: "creationTimestamp": old_iso, "labels": { "kubernetes.io/created-for/pvc/name": "pvc-workspace-orphan", + "kubernetes.io/created-for/pvc/namespace": "jenkins", }, } }, @@ -120,17 +121,29 @@ def _fake_payloads(now_iso: str, old_iso: str) -> dict[str, dict[str, object]]: "creationTimestamp": old_iso, "labels": { "kubernetes.io/created-for/pvc/name": "pvc-workspace-annotated-active", + "kubernetes.io/created-for/pvc/namespace": "jenkins", }, }, "status": {"state": "attached", "isAttached": True, "robustness": "healthy"}, "spec": {"frontend": "blockdev"}, }, + { + "metadata": { + "name": "pvc-orphan-other-namespace", + "creationTimestamp": old_iso, + "labels": { + "kubernetes.io/created-for/pvc/name": "pvc-workspace-orphan", + "kubernetes.io/created-for/pvc/namespace": "nextcloud", + }, + } + }, { "metadata": { "name": "pvc-orphan-fresh", "creationTimestamp": now_iso, "labels": { "kubernetes.io/created-for/pvc/name": "pvc-workspace-fresh", + "kubernetes.io/created-for/pvc/namespace": "jenkins", }, } }, @@ -141,6 +154,7 @@ def _fake_payloads(now_iso: str, old_iso: str) -> dict[str, dict[str, object]]: "deletionTimestamp": old_iso, "labels": { "kubernetes.io/created-for/pvc/name": "pvc-workspace-orphan", + "kubernetes.io/created-for/pvc/namespace": "jenkins", }, } }, @@ -238,6 +252,7 @@ def test_cleanup_jenkins_workspace_storage(monkeypatch) -> None: assert "/api/v1/persistentvolumes/pvc-old" in deleted_paths assert "/apis/longhorn.io/v1beta2/namespaces/longhorn-system/volumes/pvc-old" in deleted_paths assert "/apis/longhorn.io/v1beta2/namespaces/longhorn-system/volumes/pvc-orphan" in deleted_paths + assert "/apis/longhorn.io/v1beta2/namespaces/longhorn-system/volumes/pvc-orphan-other-namespace" not in deleted_paths assert "/apis/longhorn.io/v1beta2/namespaces/longhorn-system/volumes/pvc-attached" not in deleted_paths assert _metric_value( "ariadne_jenkins_workspace_cleanup_runs_total",