temoins : toutes les bases, modeles compris (template1 dite perdue a tort)
Premier essai reel sur Technolibre : pg_dumpall --clean recree template1, et les bases vivantes etaient lues sans les modeles. Le test reproduit le filtre. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
11b5bb5733
commit
543791e859
3 changed files with 23 additions and 6 deletions
18
CHANGELOG.md
18
CHANGELOG.md
|
|
@ -57,9 +57,21 @@ restauré. Je m'y suis trompé un moment.
|
||||||
- `shellcheck` des deux scripts rendus : rien, avant comme après.
|
- `shellcheck` des deux scripts rendus : rien, avant comme après.
|
||||||
- `make verifier` conforme, **94/94**.
|
- `make verifier` conforme, **94/94**.
|
||||||
|
|
||||||
**Reste** : déployer `client_backup` sur les deux locataires (les nœuds de Chezlepro n'ont pas
|
**Déployé** : `client_backup` sur les deux locataires, simulé d'abord (`--check --diff`) :
|
||||||
la nouvelle unité : `sauvegarder-maintenant` y refuserait), puis reconstruire Chezlepro avec
|
4 changements par nœud détenteur d'état (script, outil, comparateur, unité), 2 ailleurs,
|
||||||
des témoins pris pour de vrai, puis étiqueter la release.
|
0 échec ; l'application a fait exactement cela.
|
||||||
|
|
||||||
|
**Premier essai réel**, Technolibre, contre l'instantané de la veille (`SOURCE=candidat` :
|
||||||
|
celui de 11:34 n'existe plus). Nextcloud identique (268 fichiers, `instanceid` compris) ;
|
||||||
|
annuaire identique (12 entrées, `sysadmin` compris) ; clés et certificats de l'AC
|
||||||
|
inchangés, seule sa base `db/` a bougé ; DKIM inchangée ; aucun courriel perdu ; Keycloak a
|
||||||
|
quelques sessions et événements de plus. **Un faux écart**, du comparateur : `template1`
|
||||||
|
« perdue », parce que les bases vivantes étaient lues sans les modèles alors que
|
||||||
|
`pg_dumpall --clean` recrée `template1`. Corrigé (toutes les bases) ; le test reproduit le
|
||||||
|
filtre de PostgreSQL, et l'ancienne requête le fait échouer.
|
||||||
|
|
||||||
|
**Reste** : reconstruire Chezlepro avec des témoins pris pour de vrai, puis étiqueter la
|
||||||
|
release.
|
||||||
|
|
||||||
## 2026-10-07 (100) — Pré-vol de M4 : la face tient devant le cluster, deux en-têtes disaient faux
|
## 2026-10-07 (100) — Pré-vol de M4 : la face tient devant le cluster, deux en-têtes disaient faux
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,9 @@ def jeu_postgresql(dump: Path, interroger=psql) -> Rapport:
|
||||||
r.ecarts.append(f"l'instantane n'emporte pas de dump ({dump.name})")
|
r.ecarts.append(f"l'instantane n'emporte pas de dump ({dump.name})")
|
||||||
return r
|
return r
|
||||||
bases, roles, lignes = lire_dump(dump.read_text(errors="replace"))
|
bases, roles, lignes = lire_dump(dump.read_text(errors="replace"))
|
||||||
vivantes = set(interroger("postgres", "select datname from pg_database where not datistemplate") or [])
|
# TOUTES les bases, modeles compris : `pg_dumpall --clean` recree `template1`, et le
|
||||||
|
# premier essai reel (Technolibre, 2026-10-07) l'a dite « perdue » faute de la chercher.
|
||||||
|
vivantes = set(interroger("postgres", "select datname from pg_database") or [])
|
||||||
roles_vivants = set(interroger("postgres", "select rolname from pg_roles") or [])
|
roles_vivants = set(interroger("postgres", "select rolname from pg_roles") or [])
|
||||||
r.compte = len(lignes)
|
r.compte = len(lignes)
|
||||||
for b in sorted(bases - vivantes):
|
for b in sorted(bases - vivantes):
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ mail: marie@exemple.internal
|
||||||
|
|
||||||
DUMP = r"""CREATE ROLE keycloak;
|
DUMP = r"""CREATE ROLE keycloak;
|
||||||
CREATE ROLE postgres;
|
CREATE ROLE postgres;
|
||||||
|
CREATE DATABASE template1 WITH TEMPLATE = template0 ENCODING = 'UTF8';
|
||||||
CREATE DATABASE keycloak WITH TEMPLATE = template0 ENCODING = 'UTF8';
|
CREATE DATABASE keycloak WITH TEMPLATE = template0 ENCODING = 'UTF8';
|
||||||
\connect keycloak
|
\connect keycloak
|
||||||
COPY public.realm (id, name) FROM stdin;
|
COPY public.realm (id, name) FROM stdin;
|
||||||
|
|
@ -189,12 +190,14 @@ def postgresql() -> None:
|
||||||
argv = ["--avant", str(d / "avant"), "--instantane", "x", "--jeu", "postgresql=/var/backups/setops/postgresql",
|
argv = ["--avant", str(d / "avant"), "--instantane", "x", "--jeu", "postgresql=/var/backups/setops/postgresql",
|
||||||
"--dump", "/var/backups/setops/postgresql/toutes-bases.sql"]
|
"--dump", "/var/backups/setops/postgresql/toutes-bases.sql"]
|
||||||
|
|
||||||
def cluster(bases=("postgres", "keycloak"), roles=("postgres", "keycloak"), comptes=None):
|
def cluster(bases=("postgres", "template1", "keycloak"), roles=("postgres", "keycloak"), comptes=None):
|
||||||
comptes = comptes if comptes is not None else {"public.realm": "2", "public.user_session": "1"}
|
comptes = comptes if comptes is not None else {"public.realm": "2", "public.user_session": "1"}
|
||||||
|
|
||||||
def interroger(base: str, sql: str):
|
def interroger(base: str, sql: str):
|
||||||
if "pg_database" in sql:
|
if "pg_database" in sql:
|
||||||
return list(bases)
|
# Comme PostgreSQL : `template1` est un modele, qu'un filtre sur
|
||||||
|
# `datistemplate` ecarterait (le faux « base perdue » du premier essai reel).
|
||||||
|
return [b for b in bases if not ("datistemplate" in sql and b == "template1")]
|
||||||
if "pg_roles" in sql:
|
if "pg_roles" in sql:
|
||||||
return list(roles)
|
return list(roles)
|
||||||
table = sql.rsplit(" ", 1)[-1]
|
table = sql.rsplit(" ", 1)[-1]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue