restauration : la section d'une base passe a psql par l'entree standard

postgres ne lit pas le repertoire jetable de root ; trouve en repetition
sur data-sql-01 de Technolibre. Le test l'exige desormais.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-09-30 02:51:19 -04:00
parent 8a9da0c31a
commit 515aac415a
3 changed files with 21 additions and 4 deletions

View file

@ -45,8 +45,18 @@ refuser d'écraser, bloquer puis libérer la sauvegarde, et couper la section d'
le `DROP DATABASE postgres;`. Le test a trouvé un défaut avant tout déploiement : une le `DROP DATABASE postgres;`. Le test a trouvé un défaut avant tout déploiement : une
apostrophe dans `${c:-…}`, que bash lit comme un guillemet ouvrant. apostrophe dans `${c:-…}`, que bash lit comme un guillemet ouvrant.
**Pas encore éprouvé par une reconstruction réelle** : validé par `ansible-lint` (0 remarque), **Déployé sur Technolibre** (runner, `deployer-tout`) : 13 hôtes, 0 échec. Chaque jeu vivant
`--syntax-check`, `make test`. L'épreuve est la prochaine reconstruction. reconnu `en_place` (rien écrasé) ; les deux serveurs web, vides, ont pris le chemin
`a_restaurer` depuis leur instantané d'avant. `make sauvegarder-maintenant` : les 8 dépôts
passent la garde. Répétitions sur les vraies données, sans rien toucher : annuaire à blanc
(12 entrées rejouables depuis `71fb5481`), courriel remis dans un répertoire jetable.
**La répétition a trouvé un défaut** : `psql` tourne en `postgres`, qui ne lit pas le
répertoire jetable de root (0700) — en reconstruction, la base serait restée vide et le
déploiement aurait échoué. La section passe désormais par l'entrée standard ; le test
l'exige.
**Pas encore éprouvé par une reconstruction réelle** : l'épreuve est la prochaine.
## 2026-09-30 (46) — Technolibre : l'état d'avant la reconstruction remis en place, sans reconstruire ## 2026-09-30 (46) — Technolibre : l'état d'avant la reconstruction remis en place, sans reconstruire

View file

@ -246,8 +246,10 @@ cmd_base() {
-c "ALTER DATABASE ${cible} OWNER TO ${proprio};" -c "ALTER DATABASE ${cible} OWNER TO ${proprio};"
# UNE SEULE TRANSACTION : une erreur au milieu laisse une base VIDE, que la prochaine # UNE SEULE TRANSACTION : une erreur au milieu laisse une base VIDE, que la prochaine
# passe retentera — pas une base a moitie chargee qu'on prendrait pour la bonne. # passe retentera — pas une base a moitie chargee qu'on prendrait pour la bonne.
# Par l'ENTREE STANDARD, pas `-f` : psql tourne en `postgres`, qui ne peut pas lire le
# repertoire jetable de root (0700). Trouve en repetition sur data-sql-01, 2026-09-30.
runuser -u postgres -- psql -X -q --single-transaction -v ON_ERROR_STOP=1 \ runuser -u postgres -- psql -X -q --single-transaction -v ON_ERROR_STOP=1 \
-d "${cible}" -f "${section}" >/dev/null -d "${cible}" < "${section}" >/dev/null
echo "RESTAURE ${INSTANTANE} : base ${nom} -> ${cible}, $(tables "${cible}") table(s)." echo "RESTAURE ${INSTANTANE} : base ${nom} -> ${cible}, $(tables "${cible}") table(s)."
} }

View file

@ -127,11 +127,15 @@ esac
""") """)
# PostgreSQL : on journalise, on garde la section rejouee ; toute base est vierge. # PostgreSQL : on journalise, on garde la section rejouee ; toute base est vierge.
executable(bin_ / "runuser", '#!/bin/bash\nwhile [[ "$1" != "--" ]]; do shift; done; shift; exec "$@"\n') executable(bin_ / "runuser", '#!/bin/bash\nwhile [[ "$1" != "--" ]]; do shift; done; shift; exec "$@"\n')
# Sans `-c`, psql lit la section sur son entree standard : c'est ainsi que l'outil
# doit la lui passer (`postgres` ne lit pas le repertoire jetable de root).
executable(bin_ / "psql", f"""#!/bin/bash executable(bin_ / "psql", f"""#!/bin/bash
echo "psql $*" >> "{log}/pg" echo "psql $*" >> "{log}/pg"
avec_c=0
while (( $# )); do while (( $# )); do
case "$1" in -f) cp "$2" "{log}/section.sql"; shift 2;; -c) [[ "$2" == select* ]] && echo 0; shift 2;; *) shift;; esac case "$1" in -f) echo "psql -f INTERDIT" >> "{log}/pg"; shift 2;; -c) avec_c=1; [[ "$2" == select* ]] && echo 0; shift 2;; *) shift;; esac
done done
if (( ! avec_c )); then cat > "{log}/section.sql"; fi
""") """)
executable(bin_ / "pg_dump", '#!/bin/bash\necho dump\n') executable(bin_ / "pg_dump", '#!/bin/bash\necho dump\n')
executable(bin_ / "dropdb", f'#!/bin/bash\necho "dropdb $*" >> "{log}/pg"\n') executable(bin_ / "dropdb", f'#!/bin/bash\necho "dropdb $*" >> "{log}/pg"\n')
@ -181,6 +185,7 @@ done
"la section s'arrete avant le DROP DATABASE postgres, et ne deborde sur aucune autre base") "la section s'arrete avant le DROP DATABASE postgres, et ne deborde sur aucune autre base")
pg = (log / "pg").read_text() pg = (log / "pg").read_text()
verifier("--single-transaction" in pg, "la base est rejouee en une seule transaction") verifier("--single-transaction" in pg, "la base est rejouee en une seule transaction")
verifier("INTERDIT" not in pg, "la section passe par l'entree standard, jamais par `psql -f`")
r = lancer("base", "inexistante") r = lancer("base", "inexistante")
verifier(r.returncode == 0 and "ABSENTE" in r.stdout, "une base absente de l'instantane est dite, pas inventee") verifier(r.returncode == 0 and "ABSENTE" in r.stdout, "une base absente de l'instantane est dite, pas inventee")