diff --git a/Makefile b/Makefile index 8251027..548b7a7 100644 --- a/Makefile +++ b/Makefile @@ -376,7 +376,7 @@ inventaire-verifier: ansible-runtime python3 scripts/bases_donnees.py verifier python3 scripts/domaines.py verifier -.PHONY: bases bases-verifier domaines domaines-verifier applications applications-verifier serveurs serveurs-verifier serveurs-bootstrap +.PHONY: bases bases-verifier domaines domaines-verifier applications applications-verifier applications-bootstrap serveurs serveurs-verifier serveurs-bootstrap serveurs: python3 scripts/serveurs.py lister @@ -404,6 +404,9 @@ applications: applications-verifier: python3 scripts/applications.py verifier +applications-bootstrap: + python3 scripts/applications.py bootstrap + inventaire-lister: ansible-runtime ansible-inventory -i $(FICHIER_INVENTAIRE) --list diff --git a/docs/applications.yml b/docs/applications.yml index 8613975..39c438d 100644 --- a/docs/applications.yml +++ b/docs/applications.yml @@ -3,9 +3,57 @@ # Une VM peut porter plusieurs applications ; une base se lie a une application. --- applications: + collabora: + groupe: serveurs_collabora + hote: collab-01 + nextcloud: + groupe: serveurs_nextcloud + hote: collab-01 pg-principal: groupe: serveurs_postgresql hote: data-01 + redis: + groupe: serveurs_redis + hote: data-01 forge: groupe: serveurs_forgejo hote: forge-01 + keycloak: + groupe: serveurs_keycloak + hote: idm-01 + openldap: + groupe: serveurs_openldap + hote: idm-01 + powerdns: + groupe: serveurs_powerdns + hote: infra-dns-01 + nginx: + groupe: serveurs_nginx + hote: infra-edge-01 + sendmail: + groupe: serveurs_sendmail + hote: infra-mail-01 + step_ca: + groupe: serveurs_step_ca + hote: infra-pki-01 + icinga: + groupe: serveurs_icinga + hote: mon-01 + grafana: + groupe: serveurs_grafana + hote: obs-01 + loki: + groupe: serveurs_loki + hote: obs-01 + prometheus: + groupe: serveurs_prometheus + hote: obs-01 + web_dorsaux: + groupe: serveurs_web_dorsaux + hote: web-dorsal-01 + web_frontaux: + groupe: serveurs_web_frontaux + hote: web-frontal-01 + web_frontaux-web-frontal-02: + groupe: serveurs_web_frontaux + hote: web-frontal-02 diff --git a/scripts/applications.py b/scripts/applications.py index 310b271..1ffea3d 100644 --- a/scripts/applications.py +++ b/scripts/applications.py @@ -9,6 +9,7 @@ from pathlib import Path import yaml +from inventory_gui import charger_yaml, liste_hotes from inventory_rules import ( bases_de_application, chaine_connexion, @@ -22,6 +23,11 @@ RACINE = Path(__file__).resolve().parents[1] FICHIER = RACINE / "docs/applications.yml" FICHIER_BASES = RACINE / "docs/bases-donnees.yml" FICHIER_DOMAINES = RACINE / "docs/domaines.yml" +INVENTAIRE = RACINE / "inventories/production/hosts.yml" + +# Groupes 'serveurs_*' qui sont des capacites de SOCLE (sur toutes les VM), +# pas des applications a part entiere. +GROUPES_SOCLE = {"serveurs_debian", "serveurs_durcis"} def _liste(valeur: str) -> list: @@ -63,11 +69,39 @@ def lister(registre: dict, bases: dict) -> None: print(f" DSN ({portee}/{base.get('usage', '-')}): {chaine_connexion(base, entree['serveur'])}") +def bootstrap(registre_existant: dict) -> dict: + """(Re)genere les applications depuis les appartenances de groupes de l'inventaire. + + Un groupe 'serveurs_*' (hors socle) sur un hote = une application. Les entrees + existantes correspondant a un couple (groupe, hote) toujours present sont + preservees telles quelles (port / expose / requiert ...). + """ + existant = registre_existant.get("applications") or {} + par_cle = {(a.get("groupe"), a.get("hote")): (cle, a) for cle, a in existant.items()} + apps: dict = {} + for h in liste_hotes(charger_yaml(INVENTAIRE)): + hote = h.get("nom") + if not hote: + continue + for groupe in sorted(h.get("groupes", [])): + if not groupe.startswith("serveurs_") or groupe in GROUPES_SOCLE: + continue + garde = par_cle.get((groupe, hote)) + if garde: + apps[garde[0]] = garde[1] + continue + base = groupe[len("serveurs_"):] + app_id = base if base not in apps else f"{base}-{hote}" + apps[app_id] = {"groupe": groupe, "hote": hote} + return {"applications": apps} + + def main() -> int: parser = argparse.ArgumentParser(description="Registre des applications Set-OPS.") sub = parser.add_subparsers(dest="commande", required=True) sub.add_parser("lister", help="Affiche les applications et leurs DSN resolus.") sub.add_parser("verifier", help="Valide la coherence du registre.") + sub.add_parser("bootstrap", help="(Re)genere applications.yml depuis les groupes de l'inventaire.") pa = sub.add_parser("ajouter", help="Ajoute ou met a jour une application.") pa.add_argument("--id", required=True) @@ -89,6 +123,11 @@ def main() -> int: elif args.commande == "verifier": valider_applications(registre, domaines) print("Registre des applications valide.") + elif args.commande == "bootstrap": + registre = bootstrap(registre) + valider_applications(registre, domaines) + ecrire(registre) + print(f"docs/applications.yml genere depuis l'inventaire ({len(registre['applications'])} applications).") elif args.commande == "ajouter": app = {"groupe": args.groupe, "hote": args.hote} if args.port is not None: