pgha-dryrun.yaml: trigger secret re-provisioning after regenerating postgresql_replication_password (excludes &<>\" per pystache HTML-escaping bug found this session)
ci/woodpecker/push/deploy Pipeline was successful

This commit is contained in:
2026-07-30 21:44:49 -07:00
parent 8afe0049c4
commit dc6120ffd4
+35 -9
View File
@@ -1,6 +1,13 @@
# ───────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────
# postgresql/cutover/test/pgha-dryrun.yaml — DISPOSABLE dry-run stack # postgresql/cutover/test/pgha-dryrun.yaml — DISPOSABLE dry-run stack
# #
# TRIGGER NOTE (2026-08-01): touched to force Woodpecker to re-run secret
# provisioning for the `postgresql` stack case after regenerating
# postgresql_replication_password to exclude &<>" (see ADR-0001 Dry-Run
# Debugging Log note for context — Spilo's pystache config templating
# HTML-escapes double-brace {{PGPASSWORD_STANDBY}} substitutions, corrupting
# any password containing those characters).
#
# Validates the ADR-0001 cutover mechanics WITHOUT touching production: # Validates the ADR-0001 cutover mechanics WITHOUT touching production:
# - own overlay network (pgha-test_db-backend), own stack name # - own overlay network (pgha-test_db-backend), own stack name
# - throwaway "legacy" postgres:17 seeded with marker data, carrying the # - throwaway "legacy" postgres:17 seeded with marker data, carrying the
@@ -61,23 +68,42 @@
# docs example (that name assumes a plain Patroni method map without # docs example (that name assumes a plain Patroni method map without
# Spilo's wrapper naming). # Spilo's wrapper naming).
# #
# BUG FOUND DURING THIS DRY RUN (2026-08-01, unrelated to standby_cluster
# itself, but discovered while testing it): Spilo's pystache templating
# engine renders `password: '{{PGPASSWORD_STANDBY}}'` using DOUBLE braces
# in its TEMPLATE constant (confirmed from configure_spilo.py source) —
# pystache HTML-escapes double-brace substitutions by default (only
# triple-brace {{{...}}} skips escaping, which Spilo deliberately uses for
# archive_command elsewhere in the same template for exactly this reason).
# This means any password containing &, <, >, or " gets corrupted into
# HTML entities (e.g. & becomes &amp;) inside Patroni's own rendered
# /run/postgres.yml AND /run/postgresql/pgpass — breaking real
# password-based Patroni-to-Patroni replication auth (confirmed via direct
# file inspection: the raw secret was verified clean via `cat | xxd`, but
# the rendered config had "&amp;" baked in). This surfaced here specifically
# because standby_cluster's cascade-replica bootstrap (patroni-0 replicating
# from patroni-1) uses genuine hostssl+md5 auth, unlike legacy's disposable
# "trust" rule which never actually checks the password. Fix: regenerate
# postgresql_replication_password to exclude &<>" entirely — done
# 2026-08-01, this file re-tests with the corrected secret.
#
# OPEN QUESTIONS THIS DRY RUN IS DESIGNED TO ANSWER (do not assume the # OPEN QUESTIONS THIS DRY RUN IS DESIGNED TO ANSWER (do not assume the
# answer — observe actual logs): # answer — observe actual logs):
# - Does Patroni require a pre-created replication slot on "legacy" for # - Does Patroni require a pre-created replication slot on "legacy" for
# the standby_cluster link (primary_slot_name), or does it work # the standby_cluster link (primary_slot_name), or does it work
# without one since we haven't set that key? Docs say slots are only # without one since we haven't set that key? ANSWERED (first attempt,
# required "if you use replication slots" for this link — ambiguous # pre-password-fix): works fine without one — patroni-1 successfully
# whether that's opt-in or on-by-default given use_slots:true is set # bootstrapped as standby leader and began streaming from legacy with
# cluster-wide by Spilo's own template for OTHER purposes. # no slot configured.
# - Does "legacy" (vanilla, unmanaged postgres:17) actually need # - Does "legacy" (vanilla, unmanaged postgres:17) actually need
# postgresql.conf discoverable in PGDATA for Patroni's remote checks? # postgresql.conf discoverable in PGDATA for Patroni's remote checks?
# (Docs: "Patroni expects to find postgresql.conf or # ANSWERED: yes, works fine — vanilla image keeps it there by default,
# postgresql.conf.backup in PGDATA of the remote primary" — vanilla # no complaint logged.
# images keep it there by default, expected to be fine, but confirm.)
# - Does promotion off the standby cluster (detaching from "legacy" and # - Does promotion off the standby cluster (detaching from "legacy" and
# becoming a normal read-write cluster) work cleanly and pick up the # becoming a normal read-write cluster) work cleanly and pick up the
# very latest streamed WAL, closing the gap as intended? This is the # very latest streamed WAL, closing the gap as intended? STILL TO TEST
# actual feature under test — Step 7c below. # — this is the actual feature under test, blocked behind the password
# bug above on the first attempt, retesting now.
# #
# ─── Fixes still carried forward from the CLONE_WITH_BASEBACKUP dry run ─── # ─── Fixes still carried forward from the CLONE_WITH_BASEBACKUP dry run ───
# #