From b9063dfee500ad80981ba3e7ecfd2f6a6577aea2 Mon Sep 17 00:00:00 2001 From: "juvenal.diaz" Date: Sat, 26 Sep 2026 11:10:06 -0600 Subject: [PATCH] Treat pending Helm releases as stale --- lib/jeannie/pipeline.sh | 34 ++++++++++++++++++++++++++-------- lib/jeannie/toolchain.sh | 35 ++++++++++++++++++++++++++--------- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/lib/jeannie/pipeline.sh b/lib/jeannie/pipeline.sh index 170d944..84d0cd2 100644 --- a/lib/jeannie/pipeline.sh +++ b/lib/jeannie/pipeline.sh @@ -212,13 +212,30 @@ tofu_state_has_resource() { tofu -chdir="${REPO_ROOT}/${stack}" state show "${resource_address}" >/dev/null 2>&1 } -helm_release_secret_exists() { +cleanup_stale_helm_release_secrets() { + local namespace="$1" + local release_name="$2" + + kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" get secrets \ + -l "owner=helm,name=${release_name}" \ + -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.status}{"\n"}{end}' 2>/dev/null | + while IFS=$'\t' read -r secret status; do + case "${status}" in + pending-install|pending-upgrade|pending-rollback|failed|uninstalling) + echo "Deleting stale Helm release secret ${namespace}/${secret} with status=${status}..." + kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" delete secret "${secret}" + ;; + esac + done +} + +helm_release_deployed_secret_exists() { local namespace="$1" local release_name="$2" local secret_name secret_name="$(kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" get secrets \ - -l "owner=helm,name=${release_name}" \ + -l "owner=helm,name=${release_name},status=deployed" \ -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)" [[ -n "${secret_name}" ]] @@ -243,17 +260,18 @@ adopt_tofu_helm_release() { local namespace="$3" local release_name="$4" local has_state=false - local has_release_secret=false + local has_deployed_release=false if tofu_state_has_resource "${stack}" "${resource_address}"; then has_state=true fi - if helm_release_secret_exists "${namespace}" "${release_name}"; then - has_release_secret=true + cleanup_stale_helm_release_secrets "${namespace}" "${release_name}" + if helm_release_deployed_secret_exists "${namespace}" "${release_name}"; then + has_deployed_release=true fi - if [[ "${has_state}" == "true" && "${has_release_secret}" == "false" ]]; then - echo "Removing stale Helm release state for ${namespace}/${release_name} from ${stack} (${resource_address}) because no Helm release secret exists..." + if [[ "${has_state}" == "true" && "${has_deployed_release}" == "false" ]]; then + echo "Removing stale Helm release state for ${namespace}/${release_name} from ${stack} (${resource_address}) because no deployed Helm release exists..." tofu -chdir="${REPO_ROOT}/${stack}" state rm "${resource_address}" return 0 fi @@ -261,7 +279,7 @@ adopt_tofu_helm_release() { if [[ "${has_state}" == "true" ]]; then return 0 fi - if [[ "${has_release_secret}" == "false" ]]; then + if [[ "${has_deployed_release}" == "false" ]]; then return 0 fi diff --git a/lib/jeannie/toolchain.sh b/lib/jeannie/toolchain.sh index 0a83004..4a76596 100644 --- a/lib/jeannie/toolchain.sh +++ b/lib/jeannie/toolchain.sh @@ -26,13 +26,30 @@ tofu_state_has_resource() { tofu -chdir="${REPO_ROOT}/${stack}" state show "${resource_address}" >/dev/null 2>&1 } -helm_release_secret_exists() { +cleanup_stale_helm_release_secrets() { + local namespace="$1" + local release_name="$2" + + kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" get secrets \ + -l "owner=helm,name=${release_name}" \ + -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.status}{"\n"}{end}' 2>/dev/null | + while IFS=$'\t' read -r secret status; do + case "${status}" in + pending-install|pending-upgrade|pending-rollback|failed|uninstalling) + echo "Deleting stale Helm release secret ${namespace}/${secret} with status=${status}..." + kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" delete secret "${secret}" + ;; + esac + done +} + +helm_release_deployed_secret_exists() { local namespace="$1" local release_name="$2" local secret_name secret_name="$(kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" get secrets \ - -l "owner=helm,name=${release_name}" \ + -l "owner=helm,name=${release_name},status=deployed" \ -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)" [[ -n "${secret_name}" ]] @@ -57,17 +74,18 @@ adopt_tofu_helm_release() { local namespace="$3" local release_name="$4" local has_state=false - local has_release_secret=false + local has_deployed_release=false if tofu_state_has_resource "${stack}" "${resource_address}"; then has_state=true fi - if helm_release_secret_exists "${namespace}" "${release_name}"; then - has_release_secret=true + cleanup_stale_helm_release_secrets "${namespace}" "${release_name}" + if helm_release_deployed_secret_exists "${namespace}" "${release_name}"; then + has_deployed_release=true fi - if [[ "${has_state}" == "true" && "${has_release_secret}" == "false" ]]; then - echo "Removing stale Helm release state for ${namespace}/${release_name} from ${stack} (${resource_address}) because no Helm release secret exists..." + if [[ "${has_state}" == "true" && "${has_deployed_release}" == "false" ]]; then + echo "Removing stale Helm release state for ${namespace}/${release_name} from ${stack} (${resource_address}) because no deployed Helm release exists..." tofu -chdir="${REPO_ROOT}/${stack}" state rm "${resource_address}" return 0 fi @@ -75,7 +93,7 @@ adopt_tofu_helm_release() { if [[ "${has_state}" == "true" ]]; then return 0 fi - if [[ "${has_release_secret}" == "false" ]]; then + if [[ "${has_deployed_release}" == "false" ]]; then return 0 fi @@ -123,4 +141,3 @@ adopt_tofu_kubernetes_manifest() { echo "Importing existing Kubernetes ${manifest_kind} ${namespace}/${resource_name} into ${stack} state (${resource_address})..." tofu -chdir="${REPO_ROOT}/${stack}" import -input=false "${resource_address}" "${import_id}" } -