feat: AddonClaim + InitContainer wait-for-secret en chart helm
Cierra GOLDEN-PATH-ADDONCLAIM-MISSING (P0 hands-off pipeline). Cambios: - helm/APP_NAME/templates/addonclaim.yaml (NEW): hook pre-install/pre-upgrade weight -10, SIN delete-policy (sobrevive upgrades, evita disparar finalizer cleanup-logical). Gated por .Values.database.enabled (default true). - helm/APP_NAME/templates/role-db-secret-reader.yaml (NEW): Role + RoleBinding weight -7 que permite al SA leer el Secret <release>-db-creds. Lo consume el InitContainer wait-for-secret del Job Alembic. - helm/APP_NAME/templates/job-alembic-upgrade.yaml: gated por database.enabled, anade InitContainer wait-for-secret (48x5s=240s) que espera a que addon-provisioner publique el Secret tras reconciliar el AddonClaim. Absorbe la latencia del @kopf.timer (RECONCILE_INTERVAL 300s + initial_delay 60s) sin tocar el operator. - helm/APP_NAME/values.yaml: bloque database completo (enabled, addonType, databaseName, user.permissions, deletionPolicy Retain). Opt-out con database.enabled=false + alembic.enabled=false. - .gitea/workflows/APP_NAME-build.yaml: helm timeout 5m -> 7m (margen para reconcile addon-provisioner + StatefulSet ready + DDL Job + Alembic). - claim-mariadb.yaml (DELETED): obsoleto - estaba en la raiz del template y nunca se renderizaba por helm. Reemplazado por addonclaim.yaml dentro del chart helm. - README.md: documenta nueva tabla de hook weights, opt-out database, y trade-off del orphan AddonClaim post-uninstall (cleanup explicito). Decision arquitectural: Opcion D modificada (Opus 4.6 consult). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -141,7 +141,11 @@ jobs:
|
|||||||
--set tenantId=${TENANT_ID} \
|
--set tenantId=${TENANT_ID} \
|
||||||
--set tenantIdNodashes=${TENANT_ID_NODASHES} \
|
--set tenantIdNodashes=${TENANT_ID_NODASHES} \
|
||||||
--set tier=${TENANT_TIER} \
|
--set tier=${TENANT_TIER} \
|
||||||
--wait --timeout 5m
|
--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.
|
||||||
|
|
||||||
- name: Verificar rollout
|
- name: Verificar rollout
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
59
README.md
59
README.md
@@ -26,8 +26,7 @@ tenant, los placeholders en mayúsculas se sustituyen automáticamente.
|
|||||||
│ ├── pyproject.toml
|
│ ├── pyproject.toml
|
||||||
│ ├── requirements.txt
|
│ ├── requirements.txt
|
||||||
│ └── Dockerfile
|
│ └── Dockerfile
|
||||||
├── helm/__APP_NAME__/ ← Helm chart con hook Alembic pre-upgrade
|
├── helm/__APP_NAME__/ ← Helm chart con AddonClaim + hook Alembic
|
||||||
├── claim-mariadb.yaml ← AddonClaim de la BD (ver §Base de datos)
|
|
||||||
└── .gitea/workflows/ ← CI: tests + build + deploy
|
└── .gitea/workflows/ ← CI: tests + build + deploy
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -56,8 +55,22 @@ el orden de creación. El `helm upgrade --install` funciona **sin `--no-hooks`**
|
|||||||
|
|
||||||
| Recurso | Template | `hook-weight` | Motivo |
|
| 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 |
|
||||||
|
| `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 |
|
| `ServiceAccount` | `serviceaccount.yaml` | `-5` | Lo referencia el pod del Job Alembic — debe existir antes |
|
||||||
| `Job` Alembic | `job-alembic-upgrade.yaml` | `0` | Corre `alembic upgrade head` antes de rolar el Deployment |
|
| `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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl delete addonclaim <release>-db -n apps
|
||||||
|
```
|
||||||
|
|
||||||
El `ServiceAccount` se materializa como hook (no en la fase principal de Helm)
|
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
|
porque el Job Alembic, que también es hook, declara `serviceAccountName`. Si el
|
||||||
@@ -68,8 +81,9 @@ El SA-hook usa `hook-delete-policy: before-hook-creation` (no `hook-succeeded`):
|
|||||||
el Deployment lo necesita vivo en runtime, así que solo se borra/recrea al
|
el Deployment lo necesita vivo en runtime, así que solo se borra/recrea al
|
||||||
inicio del siguiente hook, manteniéndolo idempotente entre upgrades.
|
inicio del siguiente hook, manteniéndolo idempotente entre upgrades.
|
||||||
|
|
||||||
El `imagePullSecret` y el Secret `<APP_NAME>-db-creds` que referencia el Job los
|
El `imagePullSecret` lo provee la plataforma (stack-deployer), no el chart.
|
||||||
provee la plataforma (stack-deployer / addon), no el chart.
|
El Secret `<APP_NAME>-db-creds` lo publica `addon-provisioner` tras reconciliar
|
||||||
|
el `AddonClaim` (ver §Base de datos).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -90,14 +104,34 @@ provee la plataforma (stack-deployer / addon), no el chart.
|
|||||||
## Base de datos
|
## Base de datos
|
||||||
|
|
||||||
Tu app espera un Secret `__APP_NAME__-db-creds` en su namespace con las
|
Tu app espera un Secret `__APP_NAME__-db-creds` en su namespace con las
|
||||||
claves `DATABASE_URL` y `MIGRATION_DATABASE_URL`. El Secret lo provisiona la
|
claves `DATABASE_URL` / `DATABASE_HOST` / `DATABASE_PORT` / `DATABASE_NAME` /
|
||||||
plataforma:
|
`DATABASE_USER` / `DATABASE_PASSWORD` (y opcionalmente `MIGRATION_DATABASE_URL`).
|
||||||
|
|
||||||
- **PoC / MVP** — Coralware lo crea manualmente siguiendo el runbook
|
El Secret lo materializa automáticamente la plataforma vía el flujo
|
||||||
`docs/runbook-mariadb-poc.md` en el repo IDP. Tú no haces nada.
|
`AddonClaim` → `addon-provisioner` (ADR-052 + ADR-064):
|
||||||
- **Producción (Fase 5.5+)** — `claim-mariadb.yaml` lo materializa
|
|
||||||
automáticamente cuando esté disponible el controller `addon-provisioner`
|
1. El chart aplica `helm/__APP_NAME__/templates/addonclaim.yaml` como hook
|
||||||
(ver ADR-052).
|
`pre-install,pre-upgrade` weight `-10` — declara `addonType: mariadb`,
|
||||||
|
`databaseName` derivado del Release name 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.
|
||||||
|
|
||||||
|
### Opt-out — apps stateless
|
||||||
|
|
||||||
|
Si tu app no necesita BD, en `values.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
database:
|
||||||
|
enabled: false # no se aplica AddonClaim ni Role/RoleBinding
|
||||||
|
alembic:
|
||||||
|
enabled: false # no corre el Job Alembic
|
||||||
|
```
|
||||||
|
|
||||||
|
Con `database.enabled=false` la app se despliega sin BD ni migraciones.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -165,4 +199,5 @@ Sin lock-in técnico.
|
|||||||
|
|
||||||
- `docs/adr-053-shape-web-backend-python.md` — anatomía del shape
|
- `docs/adr-053-shape-web-backend-python.md` — anatomía del shape
|
||||||
- `docs/adr-052-tenant-addon-claim-model.md` — modelo de add-ons (BD)
|
- `docs/adr-052-tenant-addon-claim-model.md` — modelo de add-ons (BD)
|
||||||
|
- `docs/adr-064-free-trial-allows-mariadb.md` — free-trial permite MariaDB
|
||||||
- `docs/adr-038-ci-estandar-reusable-workflow.md` — pipeline Python
|
- `docs/adr-038-ci-estandar-reusable-workflow.md` — pipeline Python
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
# AddonClaim — referencia futura para cuando ADR-052 esté implementado.
|
|
||||||
#
|
|
||||||
# DURANTE LA POC NEXOBMS Y HASTA QUE addon-provisioner ESTÉ DISPONIBLE:
|
|
||||||
# este archivo NO se aplica. Coralware materializa el Secret
|
|
||||||
# __APP_NAME__-db-creds manualmente siguiendo docs/runbook-mariadb-poc.md.
|
|
||||||
#
|
|
||||||
# CUANDO ADR-052 ESTÉ EN FASE 5.5+:
|
|
||||||
# - el dev/CI hace `kubectl apply -f claim-mariadb.yaml` al ns de la app
|
|
||||||
# - addon-provisioner crea BD lógica + user + Secret automáticamente
|
|
||||||
# - el campo .spec.secretName debe coincidir con .Values.database.secretName
|
|
||||||
# del Helm chart (por convención: "<APP_NAME>-db-creds")
|
|
||||||
apiVersion: idp.coralware.cloud/v1alpha1
|
|
||||||
kind: AddonClaim
|
|
||||||
metadata:
|
|
||||||
name: __APP_NAME__-db
|
|
||||||
labels:
|
|
||||||
idp.coralware.cloud/tenant-id: __TENANT_ID__
|
|
||||||
idp.coralware.cloud/app: __APP_NAME__
|
|
||||||
spec:
|
|
||||||
addonType: mariadb
|
|
||||||
databaseName: __APP_NAME___db # nombre de la BD lógica
|
|
||||||
user:
|
|
||||||
permissions: rw # rw | ro — default rw
|
|
||||||
secretName: __APP_NAME__-db-creds
|
|
||||||
deletionPolicy: Retain # Retain (default) | Delete
|
|
||||||
39
helm/APP_NAME/templates/addonclaim.yaml
Normal file
39
helm/APP_NAME/templates/addonclaim.yaml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{{- 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 }}
|
||||||
@@ -1,8 +1,17 @@
|
|||||||
{{- if .Values.alembic.enabled }}
|
{{- if and .Values.alembic.enabled .Values.database.enabled }}
|
||||||
# Job pre-upgrade que corre Alembic antes de rolar el Deployment.
|
# Job pre-upgrade que corre Alembic antes de rolar el Deployment.
|
||||||
# - backoffLimit: 0 → si falla, NO reintenta; Helm aborta el upgrade.
|
# - backoffLimit: 0 -> si falla, NO reintenta; Helm aborta el upgrade.
|
||||||
# - hook-delete-policy hook-succeeded → solo se borra al éxito; en fallo queda
|
# - hook-delete-policy hook-succeeded -> solo se borra al exito; en fallo queda
|
||||||
# visible para `kubectl logs job/...` y diagnóstico.
|
# 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 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.
|
||||||
|
# - Loop: 48 iteraciones x 5s = 240s — encaja dentro del helm timeout 7m.
|
||||||
apiVersion: batch/v1
|
apiVersion: batch/v1
|
||||||
kind: Job
|
kind: Job
|
||||||
metadata:
|
metadata:
|
||||||
@@ -28,6 +37,42 @@ spec:
|
|||||||
securityContext:
|
securityContext:
|
||||||
runAsNonRoot: true
|
runAsNonRoot: true
|
||||||
runAsUser: 1001
|
runAsUser: 1001
|
||||||
|
initContainers:
|
||||||
|
- name: wait-for-secret
|
||||||
|
image: bitnami/kubectl:1.30
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
set -eu
|
||||||
|
# Espera hasta que addon-provisioner publique el Secret tras
|
||||||
|
# reconciliar el AddonClaim (hook weight -10). 48 x 5s = 240s.
|
||||||
|
SECRET="{{ .Values.database.secretName }}"
|
||||||
|
i=1
|
||||||
|
while [ "$i" -le 48 ]; do
|
||||||
|
if kubectl get secret "$SECRET" -n "$NAMESPACE" >/dev/null 2>&1; then
|
||||||
|
echo "Secret $SECRET encontrado en intento $i"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "[$i/48] Secret $SECRET aun no publicado, esperando 5s..."
|
||||||
|
sleep 5
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
echo "ERROR: Secret $SECRET no aparecio tras 240s — addon-provisioner stuck?"
|
||||||
|
exit 1
|
||||||
|
env:
|
||||||
|
- name: NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
resources:
|
||||||
|
requests: {cpu: 10m, memory: 32Mi}
|
||||||
|
limits: {cpu: 100m, memory: 64Mi}
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
capabilities:
|
||||||
|
drop: ["ALL"]
|
||||||
containers:
|
containers:
|
||||||
- name: alembic
|
- name: alembic
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
@@ -37,7 +82,7 @@ spec:
|
|||||||
name: {{ .Values.database.secretName }}
|
name: {{ .Values.database.secretName }}
|
||||||
env:
|
env:
|
||||||
# Si el Secret expone MIGRATION_DATABASE_URL, lo usa; si no, env.py
|
# Si el Secret expone MIGRATION_DATABASE_URL, lo usa; si no, env.py
|
||||||
# cae a DATABASE_URL automáticamente (ver settings.migration_url).
|
# cae a DATABASE_URL automaticamente (ver settings.migration_url).
|
||||||
- name: DATABASE_URL
|
- name: DATABASE_URL
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
|
|||||||
50
helm/APP_NAME/templates/role-db-secret-reader.yaml
Normal file
50
helm/APP_NAME/templates/role-db-secret-reader.yaml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{{- if .Values.database.enabled }}
|
||||||
|
# Role + RoleBinding que permiten al SA de la app leer el Secret `<release>-db-creds`
|
||||||
|
# en el ns `apps`. Lo consume el InitContainer `wait-for-secret` del Job Alembic
|
||||||
|
# (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):
|
||||||
|
# - 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.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# `addons` y nunca debe ser accesible desde `apps` (ADR-052 §6.1).
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: {{ .Release.Name }}-db-secret-reader
|
||||||
|
labels:
|
||||||
|
{{- include "app.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
"helm.sh/hook": pre-install,pre-upgrade
|
||||||
|
"helm.sh/hook-weight": "-7"
|
||||||
|
"helm.sh/hook-delete-policy": before-hook-creation
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["secrets"]
|
||||||
|
resourceNames: [{{ .Values.database.secretName | quote }}]
|
||||||
|
verbs: ["get", "watch", "list"]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ .Release.Name }}-db-secret-reader
|
||||||
|
labels:
|
||||||
|
{{- include "app.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
"helm.sh/hook": pre-install,pre-upgrade
|
||||||
|
"helm.sh/hook-weight": "-7"
|
||||||
|
"helm.sh/hook-delete-policy": before-hook-creation
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ .Release.Name }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: {{ .Release.Name }}-db-secret-reader
|
||||||
|
{{- end }}
|
||||||
@@ -18,7 +18,24 @@ goldenPath: web-backend
|
|||||||
goldenPathLang: python
|
goldenPathLang: python
|
||||||
|
|
||||||
database:
|
database:
|
||||||
|
# Si enabled=false: no se aplica AddonClaim, no se crea Role/RoleBinding,
|
||||||
|
# ni corre el Job Alembic. El shape web-backend/python es BD-first por
|
||||||
|
# diseño, asi que el default es true. Para una app stateless, el dev
|
||||||
|
# opt-out poniendo database.enabled=false (y alembic.enabled=false).
|
||||||
|
enabled: true
|
||||||
|
# Tipo de add-on solicitado al addon-provisioner. R1 solo soporta mariadb.
|
||||||
|
addonType: mariadb
|
||||||
|
# Nombre del Secret a publicar en el ns `apps` con el connection string.
|
||||||
|
# El Job Alembic y el Deployment lo montan via envFrom.
|
||||||
secretName: __APP_NAME__-db-creds
|
secretName: __APP_NAME__-db-creds
|
||||||
|
# Nombre de la BD logica. Vacio -> addon-provisioner deriva del Release.Name
|
||||||
|
# (snake_case + "_db"). Ver template addonclaim.yaml.
|
||||||
|
databaseName: ""
|
||||||
|
user:
|
||||||
|
permissions: rw # rw | ro
|
||||||
|
# Retain (default) | Delete — ver ADR-052 §6.2. Retain preserva la BD
|
||||||
|
# logica si el claim se borra (recomendado para PoC/free-trial).
|
||||||
|
deletionPolicy: Retain
|
||||||
|
|
||||||
config:
|
config:
|
||||||
logLevel: INFO
|
logLevel: INFO
|
||||||
|
|||||||
Reference in New Issue
Block a user