2026-06-24 20:17:46 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
"""Lit et valide le registre des domaines publics Set-OPS (instance/plan/domaines.yml)."""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
|
import sys
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
from inventory_rules import (
|
resolution d'instance : une seule, partagee — au lieu de neuf copies
Cinq jours, cinq defauts, tous de la meme famille : « quelle instance, quel inventaire ? »
Neuf modules portaient chacun leur reponse.
- 18 aout : P03 comparait chaque instance a l'inventaire d'une AUTRE ;
- 19 aout : verifier_ports codait `principal/` en dur ; verifier_intrants et
_frontiere_absente lisaient le symlink au lieu de la variable ;
- 20 aout : devis_placement rendait un verdict juste sur le mauvais tenant ;
- 22 aout : P35, puis P36 — la dixieme, trouvee par la preuve elle-meme.
Aucune n'etait une faute d'inattention : chacune avait ete ecrite de bonne foi, a un
moment ou le besoin semblait local. C'est le mode de panne de la duplication — pas
l'erreur, mais la DERIVE, invisible depuis l'interieur d'un fichier.
LA RESOLUTION UNIQUE. `inventory_rules` porte instance_courante(), inventaire_de(),
dossier_inventaire() et plan_de(). Trois niveaux de repli, dont le TROISIEME manquait a la
moitie des copies : un hosts.yml existant, puis un REPERTOIRE existant (instance neuve —
c'est ce qui faisait echouer `make instancier` sur le modele public), puis le defaut.
Vingt-huit modules y sont branches.
CE QUI REND CE REFACTOR SUR : avant de toucher quoi que ce soit, chaque module a ete
interroge sur ce qu'il resolvait, pour les DEUX ecosystemes. Apres refactor, meme mesure :
17 modules x 2 instances, diff VIDE. Aucune resolution n'a change — prouve, pas suppose.
P41 echoue des qu'un module reintroduit une copie. Eprouvee en negatif : une copie
replacee dans genome.py est signalee avec son numero de ligne. Trois exemptions nommees :
instances.py et inventory_gui.py manipulent le SYMLINK lui-meme (bascule d'instance), et
devis_opnsense lit deliberement quelle instance est ACTIVE. Elles parlent du lien, pas de
la resolution.
make verifier 41 OK, 0 echec, 0 saute ; make ci idem ; lint vert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 14:19:55 -04:00
|
|
|
instance_courante,
|
2026-06-24 20:17:46 -04:00
|
|
|
charger_applications,
|
|
|
|
|
charger_domaines,
|
|
|
|
|
expositions_des_applications,
|
|
|
|
|
valider_domaines,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
RACINE = Path(__file__).resolve().parents[1]
|
resolution d'instance : une seule, partagee — au lieu de neuf copies
Cinq jours, cinq defauts, tous de la meme famille : « quelle instance, quel inventaire ? »
Neuf modules portaient chacun leur reponse.
- 18 aout : P03 comparait chaque instance a l'inventaire d'une AUTRE ;
- 19 aout : verifier_ports codait `principal/` en dur ; verifier_intrants et
_frontiere_absente lisaient le symlink au lieu de la variable ;
- 20 aout : devis_placement rendait un verdict juste sur le mauvais tenant ;
- 22 aout : P35, puis P36 — la dixieme, trouvee par la preuve elle-meme.
Aucune n'etait une faute d'inattention : chacune avait ete ecrite de bonne foi, a un
moment ou le besoin semblait local. C'est le mode de panne de la duplication — pas
l'erreur, mais la DERIVE, invisible depuis l'interieur d'un fichier.
LA RESOLUTION UNIQUE. `inventory_rules` porte instance_courante(), inventaire_de(),
dossier_inventaire() et plan_de(). Trois niveaux de repli, dont le TROISIEME manquait a la
moitie des copies : un hosts.yml existant, puis un REPERTOIRE existant (instance neuve —
c'est ce qui faisait echouer `make instancier` sur le modele public), puis le defaut.
Vingt-huit modules y sont branches.
CE QUI REND CE REFACTOR SUR : avant de toucher quoi que ce soit, chaque module a ete
interroge sur ce qu'il resolvait, pour les DEUX ecosystemes. Apres refactor, meme mesure :
17 modules x 2 instances, diff VIDE. Aucune resolution n'a change — prouve, pas suppose.
P41 echoue des qu'un module reintroduit une copie. Eprouvee en negatif : une copie
replacee dans genome.py est signalee avec son numero de ligne. Trois exemptions nommees :
instances.py et inventory_gui.py manipulent le SYMLINK lui-meme (bascule d'instance), et
devis_opnsense lit deliberement quelle instance est ACTIVE. Elles parlent du lien, pas de
la resolution.
make verifier 41 OK, 0 echec, 0 saute ; make ci idem ; lint vert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 14:19:55 -04:00
|
|
|
INSTANCE = instance_courante()
|
2026-06-24 20:17:46 -04:00
|
|
|
FICHIER = INSTANCE / "plan/domaines.yml"
|
|
|
|
|
FICHIER_APPLICATIONS = INSTANCE / "plan/applications.yml"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def lister(registre: dict, applications: dict) -> None:
|
|
|
|
|
domaines = registre.get("domaines_publics", {})
|
|
|
|
|
if not domaines:
|
|
|
|
|
print("Aucun domaine public declare.")
|
|
|
|
|
return
|
|
|
|
|
expos = expositions_des_applications(applications, registre)
|
|
|
|
|
for nom_domaine, conf in domaines.items():
|
|
|
|
|
secondaires = conf.get("secondaires") or []
|
|
|
|
|
dnssec = "oui" if conf.get("dnssec") else "non"
|
|
|
|
|
print(f"{nom_domaine} [autorite {conf.get('autorite', '?')}, edge {conf.get('edge', '-')}, dnssec {dnssec}]")
|
|
|
|
|
print(f" secondaires: {', '.join(secondaires) if secondaires else '(aucun)'}")
|
|
|
|
|
for e in [x for x in expos if x["domaine"] == nom_domaine]:
|
|
|
|
|
print(f" exposition: {e['fqdn']} -> application {e['application']} (sur {e['hote']})")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main() -> int:
|
|
|
|
|
parser = argparse.ArgumentParser(description="Registre des domaines publics Set-OPS.")
|
|
|
|
|
sub = parser.add_subparsers(dest="commande", required=True)
|
|
|
|
|
sub.add_parser("lister", help="Affiche domaines, autorite et expositions (depuis les applications).")
|
|
|
|
|
sub.add_parser("verifier", help="Valide la coherence du registre.")
|
|
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
try:
|
|
|
|
|
registre = charger_domaines(FICHIER)
|
|
|
|
|
if args.commande == "lister":
|
|
|
|
|
lister(registre, charger_applications(FICHIER_APPLICATIONS))
|
|
|
|
|
elif args.commande == "verifier":
|
|
|
|
|
valider_domaines(registre)
|
|
|
|
|
print("Registre des domaines valide.")
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
print(f"erreur: {exc}", file=sys.stderr)
|
|
|
|
|
return 2
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
raise SystemExit(main())
|