P03 : la preuve regarde TOUTES les instances — et trouve une collision d'emblee
P03 ne verifiait la fraicheur de l'inventaire que pour l'instance ACTIVE. Or la frontiere nord/sud est PARTAGEE : ses alias d'hotes sont construits depuis le hosts.yml de CHAQUE tenant. Un tenant qu'on ne regarde pas — parce qu'il n'a aucune VM, precisement — impose donc ses adresses au pare-feu de tout le monde. Elle boucle desormais sur les instances decouvertes, chacune verifiee via SETOPS_INSTANCE (que instancier.py honore deja). AU PREMIER PASSAGE, elle a trouve une troisieme instance perimee et une collision franche : OPS-Chezlepro-lab (index 1) applique : 10.11.18.21 <- ancienne derivation OPS-Technolibre (index 11) derive : 10.11.x.x <- nouvelle derivation Le lab occupait EXACTEMENT la plage desormais attribuee a Technolibre. P21 garde les index ; rien ne gardait les inventaires APPLIQUES. La collision serait apparue le jour ou les deux auraient tourne ensemble. Les trois instances sont alignees : 10.1 (lab), 10.11 (Technolibre), 10.17 (Chezlepro). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
a694cb1487
commit
93a92aae86
3 changed files with 80 additions and 5 deletions
25
CHANGELOG.md
25
CHANGELOG.md
|
|
@ -1,5 +1,30 @@
|
||||||
# CHANGELOG — Set-OPS
|
# CHANGELOG — Set-OPS
|
||||||
|
|
||||||
|
## 2026-08-12 — P03 regarde TOUTES les instances, et trouve une collision au premier essai
|
||||||
|
|
||||||
|
P03 ne vérifiait la fraîcheur de l'inventaire que pour l'instance **active** — laissant un
|
||||||
|
tenant qu'on ne regarde pas imposer ses adresses à la frontière partagée. Elle boucle
|
||||||
|
désormais sur les instances **découvertes**, chacune vérifiée avec `SETOPS_INSTANCE`.
|
||||||
|
|
||||||
|
**Au premier passage, elle a trouvé une troisième instance périmée** — et une collision
|
||||||
|
franche que personne n'avait vue :
|
||||||
|
|
||||||
|
```
|
||||||
|
OPS-Chezlepro-lab (index 1) applique : 10.11.18.21 ← ancienne derivation (10+1)
|
||||||
|
OPS-Technolibre (index 11) derive : 10.11.x.x ← nouvelle derivation
|
||||||
|
```
|
||||||
|
|
||||||
|
Le lab occupait **exactement la plage désormais attribuée à Technolibre**. Sans cette
|
||||||
|
preuve, la collision serait apparue le jour où les deux auraient tourné ensemble — c'est
|
||||||
|
`P21` qui garde les index, rien ne gardait les inventaires *appliqués*.
|
||||||
|
|
||||||
|
Les trois instances sont maintenant alignées : `10.1` (lab), `10.11` (Technolibre),
|
||||||
|
`10.17` (Chezlepro).
|
||||||
|
|
||||||
|
> **Ce que la preuve ne fait pas** : vérifier que le boîtier porte ce que le devis dit —
|
||||||
|
> c'est `make frontiere-plan`. Elle garde l'**intrant** de ce devis, pas sa sortie. Les
|
||||||
|
> deux sont nécessaires, et c'est l'intrant qui manquait.
|
||||||
|
|
||||||
## 2026-08-12 — Un tenant périmé injecte ses vieilles adresses dans le pare-feu partagé
|
## 2026-08-12 — Un tenant périmé injecte ses vieilles adresses dans le pare-feu partagé
|
||||||
|
|
||||||
Après le renumérotage de Chezlepro, la frontière portait encore **17 adresses `10.21.x`**
|
Après le renumérotage de Chezlepro, la frontière portait encore **17 adresses `10.21.x`**
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| P01 | Lint (ansible-lint) | AFF-006 | ✅ OK | [0m[0m |
|
| P01 | Lint (ansible-lint) | AFF-006 | ✅ OK | [0m[0m |
|
||||||
| P02 | Tests unitaires (inventory_host) | — | ✅ OK | >>> le verrou tient : aucune VM n'aurait ete touchee |
|
| P02 | Tests unitaires (inventory_host) | — | ✅ OK | >>> le verrou tient : aucune VM n'aurait ete touchee |
|
||||||
| P03 | Diff-vide du plan (inventaire genere) | AFF-001, AFF-004, AFF-030, AFF-031, AFF-032 | ✅ OK | DIFF VIDE : le plan reproduit exactement l'inventaire actuel. Bascule possible. |
|
| P03 | Diff-vide du plan — TOUTES les instances | AFF-001, AFF-004, AFF-030, AFF-031, AFF-032 | ✅ OK | 3 instance(s) verifiee(s) — OPS-Chezlepro-lab, OPS-Technolibre, OPS-Chezlepro : plan et inventaire applique coincident. |
|
||||||
| P04 | Groupes <-> playbooks homonymes | AFF-008 | ✅ OK | |
|
| P04 | Groupes <-> playbooks homonymes | AFF-008 | ✅ OK | |
|
||||||
| P05 | Dependances causales de groupes | AFF-009, AFF-084 | ✅ OK | |
|
| P05 | Dependances causales de groupes | AFF-009, AFF-084 | ✅ OK | |
|
||||||
| P06 | Validateurs de registres (serveurs/apps/bases/domaines) | AFF-003 | ✅ OK | Registre des domaines valide. |
|
| P06 | Validateurs de registres (serveurs/apps/bases/domaines) | AFF-003 | ✅ OK | Registre des domaines valide. |
|
||||||
|
|
|
||||||
|
|
@ -472,6 +472,58 @@ def preuve_base_par_consommateur() -> tuple[bool, str]:
|
||||||
f"({len(bases)} entree(s) au registre).")
|
f"({len(bases)} entree(s) au registre).")
|
||||||
|
|
||||||
|
|
||||||
|
def preuve_diff_vide_toutes_instances() -> tuple[bool, str]:
|
||||||
|
"""CHAQUE instance decouverte a un inventaire applique conforme a son plan.
|
||||||
|
|
||||||
|
Pourquoi toutes, et pas seulement l'active. La frontiere nord/sud est PARTAGEE :
|
||||||
|
ses alias d'hotes (`SETOPS_<T>_SERVEUR_*`) sont construits depuis le `hosts.yml` de
|
||||||
|
CHAQUE tenant, pas depuis la formule. Le 2026-08-12, l'inventaire de Technolibre est
|
||||||
|
reste a `10.21.x` apres un changement de derivation — et la frontiere a garde ces
|
||||||
|
adresses pendant que ses alias RESEAU, eux, passaient a `10.11`. Le devis annoncait
|
||||||
|
« conforme » : il lisait fidelement un intrant perime.
|
||||||
|
|
||||||
|
Un tenant qu'on ne regarde pas — parce qu'il n'a aucune VM, precisement — impose donc
|
||||||
|
ses adresses au pare-feu de tout le monde. Verifier la seule instance active laissait
|
||||||
|
cet angle entier.
|
||||||
|
|
||||||
|
CE QU'ELLE NE TESTE PAS : que le boitier porte ce que le devis dit — c'est
|
||||||
|
`make frontiere-plan`. Ici on garde l'INTRANT de ce devis, pas sa sortie.
|
||||||
|
"""
|
||||||
|
sys.path.insert(0, str(RACINE / "scripts"))
|
||||||
|
import instances as mod_instances
|
||||||
|
|
||||||
|
trouvees = mod_instances.decouvrir()
|
||||||
|
if not trouvees:
|
||||||
|
return True, "Aucune instance decouverte : rien a comparer."
|
||||||
|
|
||||||
|
ecarts: list[str] = []
|
||||||
|
verifiees: list[str] = []
|
||||||
|
for i in trouvees:
|
||||||
|
chemin = RACINE.parent / i["nom"]
|
||||||
|
if not (chemin / "inventories").is_dir():
|
||||||
|
continue
|
||||||
|
env = {**os.environ, "SETOPS_INSTANCE": str(chemin)}
|
||||||
|
gen = subprocess.run([sys.executable, "scripts/instancier.py", "generer"],
|
||||||
|
cwd=RACINE, env=env, capture_output=True, text=True, timeout=300)
|
||||||
|
if gen.returncode != 0:
|
||||||
|
ecarts.append(f"{i['nom']} : generation impossible")
|
||||||
|
continue
|
||||||
|
cmp_ = subprocess.run([sys.executable, "scripts/instancier.py", "comparer", "--strict"],
|
||||||
|
cwd=RACINE, env=env, capture_output=True, text=True, timeout=300)
|
||||||
|
verifiees.append(i["nom"])
|
||||||
|
if cmp_.returncode != 0:
|
||||||
|
lignes = [l.strip() for l in cmp_.stdout.splitlines() if l.strip()]
|
||||||
|
resume = next((l for l in lignes if "ecart" in l), "diff non vide")
|
||||||
|
ecarts.append(f"{i['nom']} : {resume}")
|
||||||
|
|
||||||
|
if ecarts:
|
||||||
|
return False, (f"{len(ecarts)}/{len(verifiees)} instance(s) dont l'inventaire "
|
||||||
|
f"applique ne suit plus le plan : " + " | ".join(ecarts)
|
||||||
|
+ " — basculer avec `make instancier-appliquer` sur chacune.")
|
||||||
|
return True, (f"{len(verifiees)} instance(s) verifiee(s) — "
|
||||||
|
f"{', '.join(verifiees)} : plan et inventaire applique coincident.")
|
||||||
|
|
||||||
|
|
||||||
def preuve_etat_sauvegarde() -> tuple[bool, str]:
|
def preuve_etat_sauvegarde() -> tuple[bool, str]:
|
||||||
"""Tout hote qui detient de l'etat non regenerable porte `client_backup`.
|
"""Tout hote qui detient de l'etat non regenerable porte `client_backup`.
|
||||||
|
|
||||||
|
|
@ -700,10 +752,8 @@ PREUVES: list[dict] = [
|
||||||
{"id": "P02", "titre": "Tests unitaires (inventory_host)", "refs": [],
|
{"id": "P02", "titre": "Tests unitaires (inventory_host)", "refs": [],
|
||||||
"cmds": [[sys.executable, "scripts/tests/test_inventory_host.py"],
|
"cmds": [[sys.executable, "scripts/tests/test_inventory_host.py"],
|
||||||
[sys.executable, "scripts/tests/test_raser.py"]]},
|
[sys.executable, "scripts/tests/test_raser.py"]]},
|
||||||
{"id": "P03", "titre": "Diff-vide du plan (inventaire genere)", "refs": ["AFF-001", "AFF-004", "AFF-030", "AFF-031", "AFF-032"],
|
{"id": "P03", "titre": "Diff-vide du plan — TOUTES les instances", "refs": ["AFF-001", "AFF-004", "AFF-030", "AFF-031", "AFF-032"],
|
||||||
"refs": ["AFF-001", "AFF-004", "AFF-030", "AFF-031", "AFF-032"],
|
"func": preuve_diff_vide_toutes_instances},
|
||||||
"cmds": [[sys.executable, "scripts/instancier.py", "generer"],
|
|
||||||
[sys.executable, "scripts/instancier.py", "comparer", "--strict"]]},
|
|
||||||
{"id": "P04", "titre": "Groupes <-> playbooks homonymes", "refs": ["AFF-008"],
|
{"id": "P04", "titre": "Groupes <-> playbooks homonymes", "refs": ["AFF-008"],
|
||||||
"cmds": [[sys.executable, "scripts/inventory_host.py", "--inventaire", INV,
|
"cmds": [[sys.executable, "scripts/inventory_host.py", "--inventaire", INV,
|
||||||
"verifier-playbooks", "--dossier-playbooks", GROUPES]]},
|
"verifier-playbooks", "--dossier-playbooks", GROUPES]]},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue