fix: override bootstrap.post_init via SPILO_CONFIGURATION to create missing 'postgres' role before Spilo's real post_init.sh runs. Spilo hardcodes ALTER VIEW...OWNER TO postgres with no way to parameterize, which fails since our superuser is PGadmin not postgres.
ci/woodpecker/push/deploy Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
This commit is contained in:
@@ -16,8 +16,11 @@
|
|||||||
# NOTE: command: blocks use $$(...) not $(...) — Compose's own variable
|
# NOTE: command: blocks use $$(...) not $(...) — Compose's own variable
|
||||||
# interpolation parses $( as an attempted ${VAR} reference and fails with
|
# interpolation parses $( as an attempted ${VAR} reference and fails with
|
||||||
# "invalid interpolation format" / "you may need to escape any $ with
|
# "invalid interpolation format" / "you may need to escape any $ with
|
||||||
# another $". $$ escapes to a literal $ for the shell at runtime. Same
|
# another $". $$ escapes to a literal $ for the shell at runtime. This
|
||||||
# reasoning applies to $$PGDATA below.
|
# applies uniformly to EVERY literal $ character anywhere in a command:
|
||||||
|
# block, including inside heredocs and nested quoting — Compose scans the
|
||||||
|
# raw text before any shell/heredoc logic ever runs, so quoting context
|
||||||
|
# doesn't exempt anything from this escaping requirement.
|
||||||
#
|
#
|
||||||
# NOTE: ETCD3_HOSTS not ETCD_HOSTS — confirmed against zalando/spilo
|
# NOTE: ETCD3_HOSTS not ETCD_HOSTS — confirmed against zalando/spilo
|
||||||
# configure_spilo.py: PATRONI_DCS includes both "etcd" (legacy v2 API,
|
# configure_spilo.py: PATRONI_DCS includes both "etcd" (legacy v2 API,
|
||||||
@@ -28,18 +31,28 @@
|
|||||||
# v3-API client.
|
# v3-API client.
|
||||||
#
|
#
|
||||||
# NOTE: "legacy" needs a pg_hba.conf rule permitting REPLICATION-type
|
# NOTE: "legacy" needs a pg_hba.conf rule permitting REPLICATION-type
|
||||||
# connections, which is a distinct connection class from normal client
|
# connections (distinct from normal client connections), fixed via a
|
||||||
# connections in Postgres. The vanilla postgres:17 image's default
|
# /docker-entrypoint-initdb.d/ hook script (official extension point).
|
||||||
# pg_hba.conf allows normal client connections (pg_dumpall worked earlier)
|
# "trust" is acceptable ONLY because this container is fully disposable.
|
||||||
# but NOT replication connections, which pg_basebackup (used by Patroni's
|
# See note "ADR-0001 Addendum — pg_hba.conf replication prerequisite
|
||||||
# CLONE_WITH_BASEBACKUP) requires. Fixed via a /docker-entrypoint-initdb.d/
|
# discovered in dry run" for the real production prerequisite this exposes.
|
||||||
# hook script (the officially supported extension point, runs once right
|
#
|
||||||
# after initdb, before the server's final restart) that appends a
|
# NOTE: patroni-0/patroni-1 override bootstrap.post_init via
|
||||||
# permissive "trust" rule for replication connections. "trust" is
|
# SPILO_CONFIGURATION (Spilo's documented, supported mechanism for
|
||||||
# acceptable ONLY because this container is fully disposable and exists
|
# overriding any generated Patroni config — configure_spilo.py deep-merges
|
||||||
# solely to validate cutover mechanics, not auth. See the note
|
# user-supplied SPILO_CONFIGURATION on top of its own generated config).
|
||||||
# "ADR-0001 Addendum — pg_hba.conf replication prerequisite discovered in
|
# This is needed because Spilo's own /scripts/post_init.sh hardcodes
|
||||||
# dry run" for the real production prerequisite this exposes.
|
# "ALTER VIEW ... OWNER TO postgres" with no way to parameterize that role
|
||||||
|
# name via env vars. Since our superuser is PGUSER_SUPERUSER=PGadmin (to
|
||||||
|
# match production), there is no role literally named "postgres" in the
|
||||||
|
# cloned data, so Spilo's unmodified script fails with
|
||||||
|
# 'ERROR: role "postgres" does not exist'. The override points
|
||||||
|
# bootstrap.post_init at our own wrapper script instead, which creates a
|
||||||
|
# harmless, idempotent, NOLOGIN "postgres" role first, then execs Spilo's
|
||||||
|
# real, UNMODIFIED post_init.sh with all original arguments passed through
|
||||||
|
# — Zalando's script itself is never patched or forked. This affects real
|
||||||
|
# production too (superuser there is also PGadmin, not postgres) and must
|
||||||
|
# be carried into the real staging/production compose files as well.
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────
|
||||||
version: "3.6"
|
version: "3.6"
|
||||||
|
|
||||||
@@ -156,6 +169,14 @@ services:
|
|||||||
export PGPASSWORD_STANDBY="$$(cat /run/secrets/postgresql_replication_password)"
|
export PGPASSWORD_STANDBY="$$(cat /run/secrets/postgresql_replication_password)"
|
||||||
export PATRONI_RESTAPI_PASSWORD="$$(cat /run/secrets/postgresql_patroni_password)"
|
export PATRONI_RESTAPI_PASSWORD="$$(cat /run/secrets/postgresql_patroni_password)"
|
||||||
export CLONE_PASSWORD="$$(cat /run/secrets/postgresql_password)"
|
export CLONE_PASSWORD="$$(cat /run/secrets/postgresql_password)"
|
||||||
|
mkdir -p /scripts
|
||||||
|
cat > /scripts/post_init_wrapper.sh <<'WRAP'
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
psql -d "$$2" -v ON_ERROR_STOP=1 -c 'DO $$do$$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = $$x$$postgres$$x$$) THEN CREATE ROLE postgres; END IF; END $$do$$;'
|
||||||
|
exec /scripts/post_init.sh "$$@"
|
||||||
|
WRAP
|
||||||
|
chmod +x /scripts/post_init_wrapper.sh
|
||||||
exec /bin/sh /launch.sh init
|
exec /bin/sh /launch.sh init
|
||||||
environment:
|
environment:
|
||||||
SCOPE: pgha-test
|
SCOPE: pgha-test
|
||||||
@@ -170,6 +191,9 @@ services:
|
|||||||
CLONE_HOST: postgresql
|
CLONE_HOST: postgresql
|
||||||
CLONE_PORT: "5432"
|
CLONE_PORT: "5432"
|
||||||
CLONE_USER: PGadmin
|
CLONE_USER: PGadmin
|
||||||
|
SPILO_CONFIGURATION: |
|
||||||
|
bootstrap:
|
||||||
|
post_init: /scripts/post_init_wrapper.sh "zalandos"
|
||||||
secrets:
|
secrets:
|
||||||
- postgresql_password
|
- postgresql_password
|
||||||
- postgresql_replication_password
|
- postgresql_replication_password
|
||||||
@@ -194,6 +218,14 @@ services:
|
|||||||
export PGPASSWORD_STANDBY="$$(cat /run/secrets/postgresql_replication_password)"
|
export PGPASSWORD_STANDBY="$$(cat /run/secrets/postgresql_replication_password)"
|
||||||
export PATRONI_RESTAPI_PASSWORD="$$(cat /run/secrets/postgresql_patroni_password)"
|
export PATRONI_RESTAPI_PASSWORD="$$(cat /run/secrets/postgresql_patroni_password)"
|
||||||
export CLONE_PASSWORD="$$(cat /run/secrets/postgresql_password)"
|
export CLONE_PASSWORD="$$(cat /run/secrets/postgresql_password)"
|
||||||
|
mkdir -p /scripts
|
||||||
|
cat > /scripts/post_init_wrapper.sh <<'WRAP'
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
psql -d "$$2" -v ON_ERROR_STOP=1 -c 'DO $$do$$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = $$x$$postgres$$x$$) THEN CREATE ROLE postgres; END IF; END $$do$$;'
|
||||||
|
exec /scripts/post_init.sh "$$@"
|
||||||
|
WRAP
|
||||||
|
chmod +x /scripts/post_init_wrapper.sh
|
||||||
exec /bin/sh /launch.sh init
|
exec /bin/sh /launch.sh init
|
||||||
environment:
|
environment:
|
||||||
SCOPE: pgha-test
|
SCOPE: pgha-test
|
||||||
@@ -208,6 +240,9 @@ services:
|
|||||||
CLONE_HOST: postgresql
|
CLONE_HOST: postgresql
|
||||||
CLONE_PORT: "5432"
|
CLONE_PORT: "5432"
|
||||||
CLONE_USER: PGadmin
|
CLONE_USER: PGadmin
|
||||||
|
SPILO_CONFIGURATION: |
|
||||||
|
bootstrap:
|
||||||
|
post_init: /scripts/post_init_wrapper.sh "zalandos"
|
||||||
secrets:
|
secrets:
|
||||||
- postgresql_password
|
- postgresql_password
|
||||||
- postgresql_replication_password
|
- postgresql_replication_password
|
||||||
|
|||||||
Reference in New Issue
Block a user