diff --git a/CHANGELOG.md b/CHANGELOG.md index d33497a..4ae6bfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,9 +57,21 @@ restauré. Je m'y suis trompé un moment. - `shellcheck` des deux scripts rendus : rien, avant comme après. - `make verifier` conforme, **94/94**. -**Reste** : déployer `client_backup` sur les deux locataires (les nœuds de Chezlepro n'ont pas -la nouvelle unité : `sauvegarder-maintenant` y refuserait), puis reconstruire Chezlepro avec -des témoins pris pour de vrai, puis étiqueter la release. +**Déployé** : `client_backup` sur les deux locataires, simulé d'abord (`--check --diff`) : +4 changements par nœud détenteur d'état (script, outil, comparateur, unité), 2 ailleurs, +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 diff --git a/roles/client_backup/files/setops-temoins.py b/roles/client_backup/files/setops-temoins.py index 2f3d3e9..613cb0f 100644 --- a/roles/client_backup/files/setops-temoins.py +++ b/roles/client_backup/files/setops-temoins.py @@ -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})") return r 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 []) r.compte = len(lignes) for b in sorted(bases - vivantes): diff --git a/scripts/tests/test_temoins.py b/scripts/tests/test_temoins.py index 40b1e21..cec86a6 100644 --- a/scripts/tests/test_temoins.py +++ b/scripts/tests/test_temoins.py @@ -65,6 +65,7 @@ mail: marie@exemple.internal DUMP = r"""CREATE ROLE keycloak; CREATE ROLE postgres; +CREATE DATABASE template1 WITH TEMPLATE = template0 ENCODING = 'UTF8'; CREATE DATABASE keycloak WITH TEMPLATE = template0 ENCODING = 'UTF8'; \connect keycloak 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", "--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"} def interroger(base: str, sql: str): 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: return list(roles) table = sql.rsplit(" ", 1)[-1]