chart 0.3.0: AddonClaim FUERA del chart Helm (ADR-066 del IDP)
Bug en chart 0.2.x: AddonClaim era Helm hook pre-install,pre-upgrade weight -10 SIN hook-delete-policy. El default Helm 3 es before-hook-creation → borra el claim en cada upgrade → finalizer cleanup-logical rotaba credenciales + atoraba release en pending-upgrade. Cambios: - helm/APP_NAME/templates/addonclaim.yaml eliminado. - manifests/addonclaim.yaml creado con placeholders sed. - scripts/pre-helm-detach.sh idempotente para migracion v1.0.0 → 1.1.0. - .gitea/workflows/APP_NAME-build.yaml: 2 nuevos steps detach + apply AddonClaim entre kubeconfig y helm upgrade. - Chart.yaml bump 0.2.0 → 0.3.0. - README reescrito (3 pasos workflow + tabla hooks sin AddonClaim + seccion Por que FUERA del chart + opt-out actualizado). - Comentarios stale del AddonClaim como hook -10 limpiados en networkpolicy.yaml, role-db-secret-reader.yaml, job-alembic-upgrade.yaml. ADR-066 del IDP documenta la decision arquitectural completa.
This commit is contained in:
@@ -13,6 +13,8 @@ on:
|
||||
paths:
|
||||
- 'code/**'
|
||||
- 'helm/**'
|
||||
- 'manifests/**'
|
||||
- 'scripts/**'
|
||||
- '.gitea/workflows/__APP_NAME__-build.yaml'
|
||||
workflow_dispatch: {}
|
||||
|
||||
@@ -125,6 +127,36 @@ jobs:
|
||||
echo "$KUBECONFIG_B64" | base64 -d > "${HOME}/.kube/config"
|
||||
chmod 600 "${HOME}/.kube/config"
|
||||
|
||||
# ── ADR-066: AddonClaim vive FUERA del chart Helm ───────────────────
|
||||
# El claim lo gestiona addon-provisioner via finalizer cleanup-logical;
|
||||
# no debe acoplarse al lifecycle del release Helm para no rotar
|
||||
# credenciales en cada upgrade.
|
||||
|
||||
- name: De-adoptar AddonClaim legacy (migracion chart 1.0.0 -> 1.1.0)
|
||||
# Idempotente: skip silencioso si AddonClaim no existe (primera
|
||||
# instalacion) o si ya esta de-adoptado (segundo run post-migracion).
|
||||
# Si tiene annotations Helm de un release v1.0.0, las quita para que
|
||||
# el siguiente helm upgrade no intente borrarlo (no esta en el chart).
|
||||
# Sunset del step tras una rotacion completa (~2 semanas).
|
||||
run: |
|
||||
RELEASE_NAME=__APP_NAME__ bash scripts/pre-helm-detach.sh
|
||||
|
||||
- name: Aplicar AddonClaim
|
||||
# Sustitucion de placeholders con sed (evita dependencia de envsubst,
|
||||
# que no esta garantizado en la imagen del runner). kubectl apply es
|
||||
# idempotente: primer push lo crea, push subsiguientes son no-op si
|
||||
# el spec no cambia. helm upgrade --install nunca lo trackea ni lo borra.
|
||||
env:
|
||||
RELEASE_NAME: __APP_NAME__
|
||||
run: |
|
||||
# databaseName = release name con guiones a underscores + sufijo _db.
|
||||
# Coincide con el default del chart 1.0.0 (.Release.Name | replace
|
||||
# "-" "_" | printf "%s_db").
|
||||
DATABASE_NAME="$(echo "${RELEASE_NAME}" | tr '-' '_')_db"
|
||||
sed -e "s|\${RELEASE_NAME}|${RELEASE_NAME}|g" \
|
||||
-e "s|\${DATABASE_NAME}|${DATABASE_NAME}|g" \
|
||||
manifests/addonclaim.yaml | kubectl apply -f -
|
||||
|
||||
- name: Helm upgrade --install
|
||||
env:
|
||||
TENANT_ID: ${{ vars.TENANT_ID }}
|
||||
@@ -144,8 +176,8 @@ jobs:
|
||||
--wait --timeout 7m
|
||||
# 7m absorbe el peor caso del reconcile de addon-provisioner
|
||||
# (RECONCILE_INTERVAL 300s + initial_delay 60s) + StatefulSet MariaDB
|
||||
# ready (~60s) + Job DDL (~10s) + InitContainer wait-for-secret (~5s)
|
||||
# + Alembic upgrade. Ver helm/<APP_NAME>/templates/addonclaim.yaml.
|
||||
# ready (~60s) + Job DDL (~10s) + InitContainer wait-for-secret + Alembic.
|
||||
# AddonClaim ya fue aplicado en el step previo (ADR-066).
|
||||
|
||||
- name: Verificar rollout
|
||||
run: |
|
||||
|
||||
74
README.md
74
README.md
@@ -26,7 +26,11 @@ tenant, los placeholders en mayúsculas se sustituyen automáticamente.
|
||||
│ ├── pyproject.toml
|
||||
│ ├── requirements.txt
|
||||
│ └── Dockerfile
|
||||
├── helm/__APP_NAME__/ ← Helm chart con AddonClaim + hook Alembic
|
||||
├── helm/__APP_NAME__/ ← Helm chart (Deployment, Job Alembic, NP, RBAC)
|
||||
├── manifests/
|
||||
│ └── addonclaim.yaml ← AddonClaim fuera del chart (ADR-066)
|
||||
├── scripts/
|
||||
│ └── pre-helm-detach.sh ← migración v1.0.0 → v1.1.0 (idempotente)
|
||||
└── .gitea/workflows/ ← CI: tests + build + deploy
|
||||
```
|
||||
|
||||
@@ -48,30 +52,57 @@ tenant, los placeholders en mayúsculas se sustituyen automáticamente.
|
||||
|
||||
---
|
||||
|
||||
## Orden de hooks Helm
|
||||
## Orden de aplicación — AddonClaim + hooks Helm
|
||||
|
||||
El workflow del tenant sigue este orden en cada `git push`:
|
||||
|
||||
| Paso | Acción | Motivo |
|
||||
|------|--------|--------|
|
||||
| 1 | `bash scripts/pre-helm-detach.sh` | Migración chart 1.0.0 → 1.1.0: si el AddonClaim tiene labels/annotations de un release Helm previo, las quita. Idempotente: skip si no aplica. Sunset tras ~2 semanas. |
|
||||
| 2 | `kubectl apply -f manifests/addonclaim.yaml` (con `sed` para placeholders) | Crea o actualiza el `AddonClaim`. Idempotente. `addon-provisioner` empieza a reconciliar en paralelo. |
|
||||
| 3 | `helm upgrade --install <release> ./helm/<APP_NAME> --wait --timeout 7m` | Aplica el chart Helm. Los hooks `pre-install,pre-upgrade` corren en orden de `hook-weight` (ver tabla abajo). El Job Alembic espera al Secret. |
|
||||
|
||||
El chart usa hooks `pre-install,pre-upgrade` con `hook-weight` para garantizar
|
||||
el orden de creación. El `helm upgrade --install` funciona **sin `--no-hooks`**:
|
||||
el orden de creación de SUS recursos (sin AddonClaim — ese vive fuera).
|
||||
`helm upgrade --install` funciona **sin `--no-hooks`**:
|
||||
|
||||
| Recurso | Template | `hook-weight` | Motivo |
|
||||
|---------|----------|---------------|--------|
|
||||
| `AddonClaim` | `addonclaim.yaml` | `-10` | Declara la intención de la app de tener una BD — el primero en aplicarse para que `addon-provisioner` empiece a reconciliar lo antes posible |
|
||||
| `NetworkPolicy` | `networkpolicy.yaml` | `-8` | Bajo el `default-deny` del namespace `apps`, esta NP permite DNS + apiserver + addons:3306. Debe existir antes que el InitContainer del Job Alembic intente conectarse al apiserver. |
|
||||
| `Role` + `RoleBinding` | `role-db-secret-reader.yaml` | `-7` | Permite al SA leer el Secret `<APP_NAME>-db-creds` (lo consume el InitContainer `wait-for-secret` del Job Alembic) |
|
||||
| `ServiceAccount` | `serviceaccount.yaml` | `-5` | Lo referencia el pod del Job Alembic — debe existir antes |
|
||||
| `Job` Alembic | `job-alembic-upgrade.yaml` | `0` | InitContainer `wait-for-secret` espera al Secret publicado por `addon-provisioner` (hasta 240s), luego corre `alembic upgrade head` |
|
||||
|
||||
El `AddonClaim` (hook weight `-10`) NO declara `hook-delete-policy` intencionalmente:
|
||||
así sobrevive entre `helm upgrade` (re-apply idempotente) y se evita disparar el
|
||||
finalizer `cleanup-logical` del controller en cada upgrade (que dropearía el
|
||||
user de la BD y regeneraría el password, causando ventana de downtime).
|
||||
Trade-off: `helm uninstall` deja el AddonClaim huérfano y MariaDB sigue
|
||||
aprovisionada. Es coherente con `deletionPolicy: Retain` — borrar BD productiva
|
||||
debe ser decisión explícita, no side-effect del uninstall. Cleanup explícito:
|
||||
### Por qué el `AddonClaim` vive FUERA del chart (ADR-066)
|
||||
|
||||
En chart 0.2.x el `AddonClaim` era hook `pre-install,pre-upgrade` weight `-10`.
|
||||
El default de Helm 3 (`hook-delete-policy: before-hook-creation`) borraba el
|
||||
claim previo antes de aplicar el nuevo en cada `helm upgrade --install`. El
|
||||
finalizer `addon-provisioner.idp.coralware.cloud/cleanup-logical` ejecutaba
|
||||
entonces `REVOKE` + `DROP USER` + delete del Secret en cada upgrade → rotación
|
||||
involuntaria de credenciales + release atorado en `pending-upgrade`.
|
||||
|
||||
Convertir el `AddonClaim` a manifest principal del chart (no hook) también
|
||||
falla: los hooks `pre-install,pre-upgrade` corren ANTES del manifest principal,
|
||||
así que el Job Alembic intentaría leer el Secret antes de que el AddonClaim
|
||||
exista — chicken-and-egg fatal.
|
||||
|
||||
La solución es desacoplar el lifecycle del CRD del lifecycle del release Helm:
|
||||
el `AddonClaim` lo aplica el workflow con `kubectl apply` (idempotente, sin
|
||||
ownership Helm), y Helm gobierna sólo la app + sus hooks Alembic/NP/RBAC.
|
||||
|
||||
`helm uninstall` no toca el AddonClaim — desacoplamiento garantizado.
|
||||
Borrar la BD lógica es decisión explícita:
|
||||
|
||||
```bash
|
||||
kubectl delete addonclaim <release>-db -n apps
|
||||
```
|
||||
|
||||
(Con `deletionPolicy: Retain` — default — preserva la BD lógica; el operador
|
||||
emite Event `OrphanLogicalDatabase`. Cambiar a `Delete` previo para `DROP DATABASE`.)
|
||||
|
||||
### Por qué el ServiceAccount es hook
|
||||
|
||||
El `ServiceAccount` se materializa como hook (no en la fase principal de Helm)
|
||||
porque el Job Alembic, que también es hook, declara `serviceAccountName`. Si el
|
||||
SA viviera en la fase principal se crearía **después** del Job → el pod del Job
|
||||
@@ -108,28 +139,33 @@ claves `DATABASE_URL` / `DATABASE_HOST` / `DATABASE_PORT` / `DATABASE_NAME` /
|
||||
`DATABASE_USER` / `DATABASE_PASSWORD` (y opcionalmente `MIGRATION_DATABASE_URL`).
|
||||
|
||||
El Secret lo materializa automáticamente la plataforma vía el flujo
|
||||
`AddonClaim` → `addon-provisioner` (ADR-052 + ADR-064):
|
||||
`AddonClaim` → `addon-provisioner` (ADR-052 + ADR-064 + ADR-066):
|
||||
|
||||
1. El chart aplica `helm/__APP_NAME__/templates/addonclaim.yaml` como hook
|
||||
`pre-install,pre-upgrade` weight `-10` — declara `addonType: mariadb`,
|
||||
`databaseName` derivado del Release name y el `secretName` esperado.
|
||||
1. El workflow del tenant aplica `manifests/addonclaim.yaml` con
|
||||
`kubectl apply -f -` (placeholders sustituidos con `sed`). El claim declara
|
||||
`addonType: mariadb`, `databaseName` derivado del nombre del release y el
|
||||
`secretName` esperado.
|
||||
2. `addon-provisioner` (corriendo en el plano de control IDP) reconcilia el
|
||||
`AddonClaim`: crea una BD lógica + user + grant en la instancia MariaDB
|
||||
compartida del tenant (ns `addons` del cluster tenant) vía Job DDL efímero.
|
||||
3. Publica el Secret `__APP_NAME__-db-creds` en el ns `apps`.
|
||||
4. El InitContainer `wait-for-secret` del Job Alembic espera al Secret (hasta
|
||||
240s), Alembic ejecuta `upgrade head`, y el Deployment rola.
|
||||
4. El workflow corre `helm upgrade --install`. El InitContainer
|
||||
`wait-for-secret` del Job Alembic (hook `pre-install,pre-upgrade`) espera al
|
||||
Secret (hasta 240s), Alembic ejecuta `upgrade head`, y el Deployment rola.
|
||||
|
||||
### Opt-out — apps stateless
|
||||
|
||||
Si tu app no necesita BD, en `values.yaml`:
|
||||
Si tu app no necesita BD:
|
||||
|
||||
1. En `values.yaml`:
|
||||
```yaml
|
||||
database:
|
||||
enabled: false # no se aplica AddonClaim ni Role/RoleBinding
|
||||
enabled: false # no se aplica Role/RoleBinding al SA
|
||||
alembic:
|
||||
enabled: false # no corre el Job Alembic
|
||||
```
|
||||
2. Elimina el step "Aplicar AddonClaim" del workflow `.gitea/workflows/__APP_NAME__-build.yaml`
|
||||
(junto con `manifests/addonclaim.yaml` y el step `pre-helm-detach`).
|
||||
|
||||
Con `database.enabled=false` la app se despliega sin BD ni migraciones.
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
apiVersion: v2
|
||||
name: __APP_NAME__
|
||||
# Helm chart del Golden Path web-backend/python.
|
||||
# 0.3.0 (2026-05-25): ADR-066 — AddonClaim sale del chart y vive en
|
||||
# manifests/addonclaim.yaml. El workflow del tenant lo aplica con
|
||||
# kubectl apply ANTES de helm upgrade --install. Razon: en chart 0.2.x el
|
||||
# AddonClaim era hook pre-install,pre-upgrade weight -10 → el default Helm
|
||||
# `before-hook-creation` borraba el claim en cada upgrade → el finalizer
|
||||
# cleanup-logical rotaba credenciales y atoraba el release en
|
||||
# pending-upgrade. Desacoplar el lifecycle del CRD del lifecycle del
|
||||
# release Helm resuelve el bug de raiz.
|
||||
# 0.2.0 (2026-05-19): cambio Ingress controller Traefik (IngressRoute CRD)
|
||||
# → rke2-ingress-nginx (networking.k8s.io/v1 Ingress). Razón:
|
||||
# TENANT-INGRESS-CONTROLLER-MISMATCH (APERTURA COVE Sesión 3). El cluster
|
||||
@@ -8,7 +16,7 @@ name: __APP_NAME__
|
||||
# adicional. tlsSecretName por default = apps-wildcard-tls (Gap 3).
|
||||
description: Helm chart del Golden Path web-backend/python
|
||||
type: application
|
||||
version: 0.2.0
|
||||
version: 0.3.0
|
||||
appVersion: "0.1.0"
|
||||
keywords:
|
||||
- fastapi
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
{{- if .Values.database.enabled }}
|
||||
# AddonClaim — declara la intencion de la app de tener una BD (default MariaDB).
|
||||
# Lo materializa addon-provisioner (CRD idp.coralware.cloud/v1alpha1):
|
||||
# - reconcilia este claim cada RECONCILE_INTERVAL (default 300s) por TenantProfile.
|
||||
# - crea BD logica + user + grant via Job DDL efimero en el cluster tenant.
|
||||
# - publica el Secret `{{ .Values.database.secretName }}` en este ns (`apps`)
|
||||
# con DATABASE_URL / DATABASE_HOST / DATABASE_PORT / DATABASE_USER /
|
||||
# DATABASE_PASSWORD / DATABASE_NAME (contrato §2.3 del OpenSpec).
|
||||
#
|
||||
# Ordering con los hooks del chart (clave para que Alembic encuentre el Secret):
|
||||
# weight -10 (este AddonClaim)
|
||||
# -> weight -5 (ServiceAccount)
|
||||
# -> weight 0 (Job Alembic — espera al Secret via InitContainer wait-for-secret)
|
||||
#
|
||||
# delete-policy: NO se declara intencionalmente.
|
||||
# - Asi el AddonClaim sobrevive entre `helm upgrade` (re-apply idempotente).
|
||||
# - Evita disparar el finalizer `cleanup-logical` en cada upgrade (que dropearia
|
||||
# el user y regeneraria el password, causando ventana de downtime).
|
||||
# - Trade-off documentado: `helm uninstall` deja el AddonClaim orfano y MariaDB
|
||||
# sigue aprovisionada. Es coherente con `deletionPolicy: Retain` (default):
|
||||
# borrar BD productiva debe ser decision explicita, no side-effect del uninstall.
|
||||
# Cleanup explicito: `kubectl delete addonclaim {{ .Release.Name }}-db -n apps`.
|
||||
apiVersion: idp.coralware.cloud/v1alpha1
|
||||
kind: AddonClaim
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-db
|
||||
labels:
|
||||
{{- include "app.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": pre-install,pre-upgrade
|
||||
"helm.sh/hook-weight": "-10"
|
||||
spec:
|
||||
addonType: {{ .Values.database.addonType | default "mariadb" | quote }}
|
||||
databaseName: {{ .Values.database.databaseName | default (printf "%s_db" (.Release.Name | replace "-" "_")) | quote }}
|
||||
user:
|
||||
permissions: {{ .Values.database.user.permissions | default "rw" | quote }}
|
||||
secretName: {{ .Values.database.secretName | quote }}
|
||||
deletionPolicy: {{ .Values.database.deletionPolicy | default "Retain" | quote }}
|
||||
{{- end }}
|
||||
@@ -5,9 +5,11 @@
|
||||
# visible para `kubectl logs job/...` y diagnostico.
|
||||
#
|
||||
# InitContainer `wait-for-secret`:
|
||||
# - El AddonClaim (hook weight -10) ya fue aplicado, pero addon-provisioner es
|
||||
# timer-based (RECONCILE_INTERVAL 300s, initial_delay 60s) y materializa el
|
||||
# Secret `{{ .Values.database.secretName }}` de forma asincrona.
|
||||
# - El AddonClaim ya fue aplicado por el workflow del tenant ANTES del
|
||||
# `helm upgrade --install` (ADR-066, vive FUERA del chart en
|
||||
# manifests/addonclaim.yaml). addon-provisioner es timer-based
|
||||
# (RECONCILE_INTERVAL 300s, initial_delay 60s) y materializa el Secret
|
||||
# `{{ .Values.database.secretName }}` de forma asincrona.
|
||||
# - El InitContainer hace busy-wait hasta que el Secret existe — absorbe la
|
||||
# latencia del reconcile dentro del pod, sin tocar el operator ni
|
||||
# bajar RECONCILE_INTERVAL global.
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
# NetworkPolicy nunca se aplica en la fase principal.
|
||||
#
|
||||
# Weight ordering (mas chico = antes):
|
||||
# -10 AddonClaim -> -8 NetworkPolicy -> -7 Role/RoleBinding -> -5 SA -> 0 Job Alembic
|
||||
# -8 NetworkPolicy -> -7 Role/RoleBinding -> -5 SA -> 0 Job Alembic
|
||||
# (El AddonClaim vive FUERA del chart desde 0.3.0 — ADR-066. Lo aplica el
|
||||
# workflow del tenant ANTES de `helm upgrade --install`, asi que en la fase
|
||||
# de hooks ya existe y addon-provisioner ya esta reconciliando.)
|
||||
#
|
||||
# delete-policy: before-hook-creation (NO hook-succeeded): la fase principal del
|
||||
# Deployment necesita la NetworkPolicy viva en runtime; solo se borra/recrea al
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
# (hook pre-install/pre-upgrade weight 0) que hace busy-wait hasta que
|
||||
# addon-provisioner publica el Secret tras reconciliar el AddonClaim.
|
||||
#
|
||||
# Hook weight "-7" — entre AddonClaim (-10) y SA (-5):
|
||||
# Hook weight "-7" — entre NetworkPolicy (-8) y SA (-5):
|
||||
# - Garantiza que RBAC exista antes de que el SA del hook -5 se materialice
|
||||
# y antes de que el Job -0 intente leer el Secret.
|
||||
# - delete-policy: before-hook-creation para que sea idempotente entre upgrades
|
||||
# sin dejar Roles huerfanos.
|
||||
# (El AddonClaim ya no es hook del chart desde 0.3.0 — ADR-066. Lo aplica el
|
||||
# workflow del tenant ANTES del `helm upgrade --install`.)
|
||||
#
|
||||
# Scope minimo: solo lectura (get/watch) del Secret `<release>-db-creds`, no
|
||||
# secrets cluster-wide ni del ns `addons`. El root Secret de MariaDB vive en
|
||||
|
||||
34
manifests/addonclaim.yaml
Normal file
34
manifests/addonclaim.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
# AddonClaim — vive FUERA del chart Helm (ADR-066).
|
||||
#
|
||||
# El workflow del tenant sustituye los placeholders con `sed` y aplica con
|
||||
# `kubectl apply -f -` ANTES de `helm upgrade --install`. helm nunca lo
|
||||
# trackea — al `helm uninstall` no lo borra; al `helm upgrade --install`
|
||||
# repetido no lo toca. Idempotente.
|
||||
#
|
||||
# Lifecycle gobernado por addon-provisioner (CRD idp.coralware.cloud/v1alpha1):
|
||||
# - reconcilia cada RECONCILE_INTERVAL (default 300s) por TenantProfile.
|
||||
# - crea BD logica + user + GRANT via Job DDL efimero en cluster tenant.
|
||||
# - publica Secret `${RELEASE_NAME}-db-creds` en ns `apps`.
|
||||
# - agrega finalizer `addon-provisioner.idp.coralware.cloud/cleanup-logical`.
|
||||
#
|
||||
# Cleanup explicito post `helm uninstall`:
|
||||
# kubectl delete addonclaim ${RELEASE_NAME}-db -n apps
|
||||
# (con deletionPolicy: Retain — default — preserva la BD; Event
|
||||
# OrphanLogicalDatabase. Cambiar a Delete previo para DROP DATABASE.)
|
||||
apiVersion: idp.coralware.cloud/v1alpha1
|
||||
kind: AddonClaim
|
||||
metadata:
|
||||
name: ${RELEASE_NAME}-db
|
||||
namespace: apps
|
||||
labels:
|
||||
app.kubernetes.io/name: ${RELEASE_NAME}
|
||||
app.kubernetes.io/part-of: ${RELEASE_NAME}
|
||||
idp.coralware.cloud/golden-path: web-backend
|
||||
idp.coralware.cloud/golden-path-lang: python
|
||||
spec:
|
||||
addonType: mariadb
|
||||
databaseName: ${DATABASE_NAME}
|
||||
user:
|
||||
permissions: rw
|
||||
secretName: ${RELEASE_NAME}-db-creds
|
||||
deletionPolicy: Retain
|
||||
65
scripts/pre-helm-detach.sh
Executable file
65
scripts/pre-helm-detach.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
# Script de migracion v1.0.0 -> v1.1.0 del chart web-backend-python (ADR-066).
|
||||
#
|
||||
# Las apps desplegadas con chart 1.0.0 tienen el AddonClaim creado como Helm
|
||||
# hook con annotations `meta.helm.sh/release-name`, `app.kubernetes.io/managed-by=Helm`
|
||||
# y `helm.sh/hook`. El chart 1.1.0 mueve el AddonClaim FUERA del chart; el
|
||||
# workflow del tenant lo aplica con `kubectl apply -f` despues de este script.
|
||||
#
|
||||
# Sin de-adopcion, el siguiente `helm upgrade --install` veria el AddonClaim
|
||||
# en el state previo (release v_n) pero no en el manifest nuevo (chart 1.1.0)
|
||||
# → helm intentaria delete del recurso → el finalizer dropearia user/Secret.
|
||||
#
|
||||
# Este script:
|
||||
# - skip silencioso si el AddonClaim no existe (primera instalacion).
|
||||
# - skip silencioso si el AddonClaim NO tiene annotations Helm (ya de-adoptado).
|
||||
# - de-adopta si encuentra annotations Helm — quita las labels/annotations
|
||||
# que hacen que Helm lo reconozca como recurso del release.
|
||||
#
|
||||
# Idempotente. Sunset del script tras una rotacion completa de releases
|
||||
# desplegadas con chart 1.0.0 (~2 semanas).
|
||||
#
|
||||
# Variables de entorno requeridas:
|
||||
# - RELEASE_NAME: nombre del release Helm (== nombre de la app del tenant)
|
||||
# - KUBECONFIG: apuntando al cluster tenant
|
||||
#
|
||||
# Uso (desde el workflow del tenant):
|
||||
# RELEASE_NAME=__APP_NAME__ bash scripts/pre-helm-detach.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
: "${RELEASE_NAME:?ERROR: RELEASE_NAME no esta seteado}"
|
||||
NAMESPACE="${NAMESPACE:-apps}"
|
||||
CLAIM_NAME="${RELEASE_NAME}-db"
|
||||
|
||||
# Comprobar existencia. kubectl get devuelve exit 1 si NotFound — capturamos
|
||||
# con `|| true` para no romper bajo `set -e`.
|
||||
if ! kubectl get addonclaim "${CLAIM_NAME}" -n "${NAMESPACE}" >/dev/null 2>&1; then
|
||||
echo "[pre-helm-detach] AddonClaim ${CLAIM_NAME} no existe en ns ${NAMESPACE} — skip (primera instalacion)."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Detectar si tiene annotations Helm — si no, ya esta de-adoptado.
|
||||
RELEASE_ANNOTATION=$(kubectl get addonclaim "${CLAIM_NAME}" -n "${NAMESPACE}" \
|
||||
-o jsonpath='{.metadata.annotations.meta\.helm\.sh/release-name}' 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "${RELEASE_ANNOTATION}" ]; then
|
||||
echo "[pre-helm-detach] AddonClaim ${CLAIM_NAME} sin annotations Helm — skip (ya de-adoptado)."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "[pre-helm-detach] AddonClaim ${CLAIM_NAME} con release=${RELEASE_ANNOTATION} — de-adoptando…"
|
||||
|
||||
# Quitar annotations Helm — `-` sufijo significa "remove".
|
||||
kubectl annotate addonclaim "${CLAIM_NAME}" -n "${NAMESPACE}" \
|
||||
meta.helm.sh/release-name- \
|
||||
meta.helm.sh/release-namespace- \
|
||||
--overwrite
|
||||
|
||||
# Quitar label de managed-by — el hook tambien deja la annotation `helm.sh/hook`
|
||||
# en algunos casos; la dejamos viva porque no afecta el ownership tracking.
|
||||
kubectl label addonclaim "${CLAIM_NAME}" -n "${NAMESPACE}" \
|
||||
app.kubernetes.io/managed-by- \
|
||||
--overwrite
|
||||
|
||||
echo "[pre-helm-detach] De-adopcion completa. El siguiente helm upgrade --install no tocara este AddonClaim."
|
||||
Reference in New Issue
Block a user