From 040ad1d20d475f78ad6a6de1007cdf147d1be31f Mon Sep 17 00:00:00 2001 From: IvanHunters Date: Fri, 24 Jul 2026 15:33:36 +0300 Subject: [PATCH] fix(kubernetes-nodes): fail unpin hook on KMT discovery error, do not leak The pre-delete unpin hook discovered this pool's hash-suffixed KubevirtMachineTemplates through `kubectl get ... 2>/dev/null | grep ... || true`, which turned an API or RBAC failure into an empty result: the Job then reported success while the keep-annotated templates stayed pinned and leaked on uninstall (Helm skips keep-annotated resources). That contradicts the unpin() contract right above it, where annotate failures are deliberately propagated. Split the list out of the pipe so its failure fails the Job (set -e, bounded by backoffLimit/activeDeadlineSeconds, logs retained), while a successful-but-empty listing still no-ops the loop. Signed-off-by: IvanHunters --- .../kubernetes-nodes/templates/pre-delete-unpin.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/apps/kubernetes-nodes/templates/pre-delete-unpin.yaml b/packages/apps/kubernetes-nodes/templates/pre-delete-unpin.yaml index 8bc623962..47e5e954f 100644 --- a/packages/apps/kubernetes-nodes/templates/pre-delete-unpin.yaml +++ b/packages/apps/kubernetes-nodes/templates/pre-delete-unpin.yaml @@ -157,9 +157,15 @@ spec: unpin "machinedeployment.cluster.x-k8s.io/${BASE}" unpin "machinehealthcheck.cluster.x-k8s.io/${BASE}" unpin "workloadmonitor.cozystack.io/${BASE}" - for kmt in $(kubectl -n "${NS}" get kubevirtmachinetemplate.infrastructure.cluster.x-k8s.io \ - -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' 2>/dev/null | - grep -E "^${BASE}-[0-9a-f]{6}$" || true); do + # Discover this pool's hash-suffixed KMTs. The list is NOT wrapped in + # `2>/dev/null || true`: an API/RBAC failure here must fail the Job + # (set -e), not masquerade as an empty result and silently leak the + # keep-annotated templates on uninstall, the same "Failures are NOT + # swallowed" contract unpin() above holds. A successful-but-empty + # listing is fine: grep then matches nothing and the loop is a no-op. + kmts=$(kubectl -n "${NS}" get kubevirtmachinetemplate.infrastructure.cluster.x-k8s.io \ + -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}') + for kmt in $(printf '%s\n' "${kmts}" | grep -E "^${BASE}-[0-9a-f]{6}$" || true); do unpin "kubevirtmachinetemplate.infrastructure.cluster.x-k8s.io/${kmt}" done echo "unpin done"