{{- /*
CNPG Cluster + DSN-placeholder Secret for bp-newapi (issue #943, #1834).

NewAPI persists users, credits, channels, tokens, and an audit log to
PostgreSQL. The chart auto-provisions the backing Postgres via CNPG
when `cnpg.enabled=true` (DEFAULT). The chart renders:

  - postgresql.cnpg.io/v1.Cluster `<release>-newapi-pg` with the
    operator-configured size + storage from .Values.cnpg.cluster.*.
    CNPG auto-creates `<cluster>-app` Secret (basic-auth shape:
    username + password keys) and `<cluster>-rw` Service.

  - Placeholder Secret `<release>-newapi-db-dsn` with EMPTY SQL_DSN
    key, materialised at install time so the deployment.yaml
    secretKeyRef references a Secret that already exists (kubelet
    won't trip CreateContainerConfigError). The companion
    `database-secret-sync-job.yaml` Helm post-install Job then
    composes the full DSN string from CNPG's `<cluster>-app`
    password (polled until ready) and PATCHes the SQL_DSN key
    into this Secret in place.

TBD-A39 / Issue #1834 (2026-05-19, root-cause): The previous
implementation rendered the DSN via Helm `lookup` against
`<cluster>-app` at template-render time. On every freshly-franchised
Sovereign CNPG materialises that Secret only AFTER bp-newapi's
HelmRelease applies, so the first render's lookup returns nil and
the Secret committed an empty password — `postgres://newapi:@.../`.
The chart annotated the rendered Secret `helm.sh/resource-policy: keep`,
so Flux never overwrote the empty bytes on subsequent reconciles
even after CNPG had populated the source. Result on t32: newapi Pod
in 21x CrashLoopBackOff with `password authentication failed for
user "newapi"`. Switched to the canonical sync-job pattern lifted
from platform/gitea/chart/templates/database-secret-sync-job.yaml
(issue #830 Bug 2) + platform/wordpress-tenant/chart/templates/
database-secret-sync-job.yaml (issue #1786) — both proven on
otech30/t26. The sync-job is event-deterministic (polls until source
ready, PATCHes destination, exits 0) and idempotent across helm
upgrade.

  - `database.existingSecret` and `database.existingSecretKey` default
    to the chart-emitted Secret name and key when cnpg.enabled=true,
    so the deployment.yaml gate passes WITHOUT operator intervention.
    Per Inviolable Principle #4 the operator MAY still override
    `.Values.database.existingSecret` to wire NewAPI at an external
    Postgres without forking the chart.

Capabilities gate: the chart MUST NOT render the Cluster on a Sovereign
where bp-cnpg has not yet registered the `postgresql.cnpg.io/v1` CRD.
Without the gate, a cold install fails with "no matches for kind
Cluster". Same pattern the bp-external-dns chart uses (issue #190) and
the platform/powerdns/chart/templates/cnpg-cluster.yaml mirror.
*/}}
{{- if .Values.cnpg.enabled -}}
{{- $clusterName := printf "%s-newapi-pg" (include "bp-newapi.fullname" .) -}}
{{- $dsnSecretName := default (printf "%s-newapi-db-dsn" (include "bp-newapi.fullname" .)) .Values.cnpg.dsnSecretName -}}
{{- $database := .Values.cnpg.database | default "newapi" -}}
{{- if .Capabilities.APIVersions.Has "postgresql.cnpg.io/v1" -}}
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: {{ $clusterName }}
  labels:
    {{- include "bp-newapi.labels" . | nindent 4 }}
  annotations:
    helm.sh/resource-policy: keep
spec:
  instances: {{ .Values.cnpg.cluster.instances | default 1 }}
  imageName: {{ .Values.cnpg.cluster.imageName | default "ghcr.io/cloudnative-pg/postgresql:16.4" | quote }}
  storage:
    size: {{ .Values.cnpg.cluster.storage | default "5Gi" | quote }}
    {{- with .Values.cnpg.cluster.storageClassName }}
    storageClass: {{ . | quote }}
    {{- end }}
  bootstrap:
    initdb:
      database: {{ $database | quote }}
      owner: {{ .Values.cnpg.cluster.owner | default "newapi" | quote }}
      {{- with .Values.cnpg.cluster.postInitApplicationSQL }}
      postInitApplicationSQL:
        {{- toYaml . | nindent 8 }}
      {{- end }}
  {{- with .Values.cnpg.cluster.resources }}
  resources:
    {{- toYaml . | nindent 4 }}
  {{- end }}
{{- end }}
---
{{- /*
DSN placeholder Secret — populated by templates/database-secret-sync-
job.yaml at runtime. Rendered as a regular chart-managed resource (NOT
a Helm hook) so it remains owned by the bp-newapi HelmRelease and Flux
re-applies it on every reconcile. The post-install/post-upgrade
sync-job PATCHes the SQL_DSN bytes in place — Flux's strategic-merge
re-apply preserves those patched bytes because the chart-managed
template renders SQL_DSN: "" only as a placeholder; the sync-job's
strategic-merge PATCH wins server-side until the next chart render,
which then immediately fires the sync-job again. Idempotent.

Empty data.SQL_DSN value prevents CreateContainerConfigError on first
Pod schedule (kubelet only checks that the named key EXISTS, not that
it has non-empty content). The Pod will fail Postgres authentication
once and CrashLoop until the post-install sync-job completes — about
30-90s on a cold install — then come up Ready on the next kubelet
restart.
*/ -}}
apiVersion: v1
kind: Secret
metadata:
  name: {{ $dsnSecretName }}
  labels:
    {{- include "bp-newapi.labels" . | nindent 4 }}
type: Opaque
data:
  SQL_DSN: ""
{{- end }}
