fix(woodpecker): set database/owner on the wp-pg recovery bootstrap
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/pr-review Pipeline was successful

Addresses the second blocking review finding on #504.

bootstrap.recovery set only `source`. The live CRD documents the defaults:
`database` defaults to `app`, and `owner` defaults to whatever `database`
is. Neither name exists in the physically restored data, which carries
woodpecker/woodpecker from the backup.

So CNPG would have restored the real data, then provisioned a separate
empty `app` database and pointed the generated wp-pg-app Secret and the
-app Service at that instead — a cluster reporting healthy, holding the
right bytes, with the credentials aimed at the wrong database. The runbook's
own verification (psql -U woodpecker -d woodpecker using the wp-pg-app
password) would not have authenticated, so the failure would have surfaced
as a confusing auth error rather than as what it was.

kubernetes/RECOVERY.md sets both fields on all three recovery examples it
documents (ak-pg, im-pg, pprl-pg) for exactly this reason; this one did not
follow the pattern.

Added a runbook step to read dbname/username back out of the wp-pg-app
Secret before the row-count checks, so the mismatch is caught directly
rather than inferred from a psql failure.

Co-Authored-By: Claude Bot <claude-bot@renner.uno>
This commit is contained in:
2026-08-18 22:33:50 +02:00
parent b0ddbe0dfd
commit 1b5ad600d5
2 changed files with 22 additions and 2 deletions
@@ -98,8 +98,19 @@ logs carry the reason:
kubectl -n woodpecker logs -l cnpg.io/jobRole=full-recovery --tail=100
```
**Confirm the restore actually holds Woodpecker's data** — a cluster that comes
up healthy but empty is the failure mode worth catching:
**First check the generated app credentials target the right database.** CNPG
defaults `bootstrap.recovery.database` to `app`; the restored data uses
`woodpecker`. If this reads anything but `woodpecker`, the cluster has
provisioned an empty `app` database and the real data is unreachable through
the `-app` Secret and Service:
```sh
kubectl -n woodpecker get secret wp-pg-app -o jsonpath='{.data.dbname}' | base64 -d; echo
kubectl -n woodpecker get secret wp-pg-app -o jsonpath='{.data.username}' | base64 -d; echo
```
**Then confirm the restore actually holds Woodpecker's data** — a cluster that
comes up healthy but empty is the failure mode worth catching:
```sh
PGPASS=$(kubectl -n woodpecker get secret wp-pg-app -o jsonpath='{.data.password}' | base64 -d)
@@ -33,6 +33,15 @@ spec:
bootstrap:
recovery:
source: wp-pg-apps
# Must mirror the initdb values of the cluster this restores from
# (apps/wp-pg: database woodpecker, owner woodpecker). CNPG defaults
# `database` to `app` and `owner` to whatever `database` is, and those
# names do not exist in the physically restored data — it would provision
# an empty `app` database, point the generated wp-pg-app Secret and the
# -app Service at it, and leave the real data unreachable through them.
# Same pattern as every recovery example in kubernetes/RECOVERY.md.
database: woodpecker
owner: woodpecker
externalClusters:
- name: wp-pg-apps
plugin: