Consolider le flux operationnel des inventaires
This commit is contained in:
parent
f941b66d39
commit
72c3ac6007
11 changed files with 180 additions and 42 deletions
|
|
@ -256,7 +256,7 @@ Les cibles d'exploitation des VM doivent privilégier les groupes :
|
|||
```text
|
||||
make deployer HOTE=web-01
|
||||
make deployer-groupe GROUPE=serveurs_debian
|
||||
make appliquer GROUPE=serveurs_debian
|
||||
make hote-planifier HOTE=obs-01 VMID=94101 GROUPES="serveurs_debian serveurs_durcis serveurs_prometheus"
|
||||
```
|
||||
|
||||
Éviter les cibles parallèles qui réappliquent les mêmes rôles par couche, par exemple `make socle`, `make durcissement`, `make converger` ou `make deployer-vm`.
|
||||
|
|
@ -336,7 +336,8 @@ clients_ldap
|
|||
clients_supervision
|
||||
clients_metriques
|
||||
serveurs_web
|
||||
serveurs_bases_donnees
|
||||
serveurs_postgresql
|
||||
serveurs_prometheus
|
||||
```
|
||||
|
||||
Ne pas cibler `all` par défaut pour un playbook qui ne s'applique pas réellement à tous les hôtes.
|
||||
|
|
|
|||
16
CHANGELOG.md
16
CHANGELOG.md
|
|
@ -1,5 +1,21 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-06-22
|
||||
|
||||
### Ajouté
|
||||
- Ajout de `make hote-planifier` pour renseigner un hôte, son VMID et ses groupes sans création ni déploiement immédiat.
|
||||
- Ajout de `scripts/inventory_rules.py` pour centraliser les règles partagées entre la gestion CLI et l'interface locale d'inventaire.
|
||||
|
||||
### Modifié
|
||||
- Renforcement de la validation d'inventaire :
|
||||
- un hôte doit être soit planifié, soit actif, mais pas les deux ;
|
||||
- un hôte actif doit avoir `ansible_host` ;
|
||||
- un hôte doit porter au moins un groupe opérationnel ;
|
||||
- les VMID dupliqués sont refusés.
|
||||
- Conservation du VMID dans l'inventaire lors de `make creer-vm` et `make hote-ajouter`.
|
||||
- Alignement de l'aide Makefile et de la documentation sur le flux opérateur : planifier, activer/créer, déployer.
|
||||
- Retrait des groupes génériques obsolètes `serveurs_bases_donnees` et `serveurs_supervision` au profit des groupes de services précis.
|
||||
|
||||
## 2026-06-21
|
||||
|
||||
### Ajouté
|
||||
|
|
|
|||
21
Makefile
21
Makefile
|
|
@ -95,12 +95,14 @@ aide:
|
|||
@printf '%s\n' ' make config'
|
||||
@printf '%s\n' ''
|
||||
@printf '%s\n' 'Hotes'
|
||||
@printf '%s\n' ' Planifier un hote sans le deployer:'
|
||||
@printf '%s\n' ' make hote-planifier HOTE=obs-01 VMID=94101 GROUPES="serveurs_debian serveurs_durcis serveurs_prometheus serveurs_loki"'
|
||||
@printf '%s\n' ' Remettre un hote en conformite selon ses groupes:'
|
||||
@printf '%s\n' ' make deployer HOTE=web-01'
|
||||
@printf '%s\n' ' Afficher un hote:'
|
||||
@printf '%s\n' ' make hote-afficher HOTE=web-01'
|
||||
@printf '%s\n' ' Ajouter un hote existant:'
|
||||
@printf '%s\n' ' make hote-ajouter HOTE=web-01 ADRESSE_IP=192.168.12.101 GROUPES="serveurs_debian serveurs_durcis"'
|
||||
@printf '%s\n' ' make hote-ajouter HOTE=web-01 VMID=99101 ADRESSE_IP=192.168.12.101 GROUPES="serveurs_debian serveurs_durcis"'
|
||||
@printf '%s\n' ' Modifier ses groupes:'
|
||||
@printf '%s\n' ' make hote-groupes HOTE=web-01 GROUPES="serveurs_debian serveurs_durcis"'
|
||||
@printf '%s\n' ' Diagnostiquer:'
|
||||
|
|
@ -109,8 +111,6 @@ aide:
|
|||
@printf '%s\n' 'Groupes'
|
||||
@printf '%s\n' ' Appliquer un groupe complet:'
|
||||
@printf '%s\n' ' make deployer-groupe GROUPE=serveurs_debian'
|
||||
@printf '%s\n' ' Rejouer directement le playbook d un groupe:'
|
||||
@printf '%s\n' ' make appliquer GROUPE=serveurs_debian'
|
||||
@printf '%s\n' ' Convention:'
|
||||
@printf '%s\n' ' groupe serveurs_debian -> playbooks/groupes/serveurs_debian.yml'
|
||||
@printf '%s\n' ''
|
||||
|
|
@ -173,7 +173,7 @@ syntaxe-proxmox: ansible-runtime
|
|||
.PHONY: verifier
|
||||
verifier: lint inventaire-verifier syntaxe
|
||||
|
||||
.PHONY: inventaire hote-ajouter hote-groupes hote-afficher appliquer deployer deployer-groupe cloner-vm creer-vm config inventaire-ui inventaire-verifier inventaire-lister inventaire-graphe inventaire-hote inventaire-lab inventaire-production
|
||||
.PHONY: inventaire hote-planifier hote-ajouter hote-groupes hote-afficher appliquer deployer deployer-groupe cloner-vm creer-vm config inventaire-ui inventaire-verifier inventaire-lister inventaire-graphe inventaire-hote inventaire-lab inventaire-production
|
||||
inventaire: inventaire-production
|
||||
|
||||
config:
|
||||
|
|
@ -187,7 +187,16 @@ hote-ajouter: ansible-runtime
|
|||
printf '%s\n' 'Refus: relancer avec HOTE=nom_hote ADRESSE_IP=adresse_ip.'; \
|
||||
exit 2; \
|
||||
fi
|
||||
python3 scripts/inventory_host.py --inventaire $(FICHIER_INVENTAIRE) ajouter --hote $(HOTE) --adresse-ip $(ADRESSE_IP) --utilisateur-ansible $(UTILISATEUR_ANSIBLE) --groupes "$(GROUPES)" --dossier-playbooks $(DOSSIER_PLAYBOOKS_GROUPES)
|
||||
python3 scripts/inventory_host.py --inventaire $(FICHIER_INVENTAIRE) ajouter --hote $(HOTE) --adresse-ip $(ADRESSE_IP) --utilisateur-ansible $(UTILISATEUR_ANSIBLE) --vmid "$(VMID)" --groupes "$(GROUPES)" --dossier-playbooks $(DOSSIER_PLAYBOOKS_GROUPES)
|
||||
$(MAKE) inventaire-verifier
|
||||
$(MAKE) hote-afficher HOTE="$(HOTE)" FICHIER_INVENTAIRE="$(FICHIER_INVENTAIRE)"
|
||||
|
||||
hote-planifier: ansible-runtime
|
||||
@if [[ -z "$(HOTE)" ]]; then \
|
||||
printf '%s\n' 'Refus: relancer avec HOTE=nom_hote GROUPES="groupe1 groupe2".'; \
|
||||
exit 2; \
|
||||
fi
|
||||
python3 scripts/inventory_host.py --inventaire $(FICHIER_INVENTAIRE) ajouter --hote $(HOTE) --vmid "$(VMID)" --groupes "$(GROUPES)" --dossier-playbooks $(DOSSIER_PLAYBOOKS_GROUPES)
|
||||
$(MAKE) inventaire-verifier
|
||||
$(MAKE) hote-afficher HOTE="$(HOTE)" FICHIER_INVENTAIRE="$(FICHIER_INVENTAIRE)"
|
||||
|
||||
|
|
@ -307,7 +316,7 @@ creer-vm:
|
|||
exit 2; \
|
||||
fi
|
||||
$(MAKE) cloner-vm HOTE="$(HOTE)" VMID_MODELE="$(VMID_MODELE)" VMID="$(VMID)" NOEUD_PROXMOX="$(NOEUD_PROXMOX)" STOCKAGE_PROXMOX="$(STOCKAGE_PROXMOX)" FORMAT_DISQUE="$(FORMAT_DISQUE)" TAILLE_DISQUE="$(TAILLE_DISQUE)" DISQUE_PROXMOX="$(DISQUE_PROXMOX)" ADRESSE_IP="$(ADRESSE_IP)" CIDR="$(CIDR)" PASSERELLE="$(PASSERELLE)" DNS="$(DNS)" DHCP="$(DHCP)" CIUSER="$(CIUSER)" CLE_SSH_PUBLIQUE="$(CLE_SSH_PUBLIQUE)" PONT_PROXMOX="$(PONT_PROXMOX)" VLAN="$(VLAN)" DEMARRER="$(DEMARRER)" CLONE_COMPLET="$(CLONE_COMPLET)"
|
||||
$(MAKE) hote-ajouter HOTE="$(HOTE)" ADRESSE_IP="$(ADRESSE_IP)" GROUPES="$(GROUPES)" FICHIER_INVENTAIRE="$(FICHIER_INVENTAIRE)"
|
||||
$(MAKE) hote-ajouter HOTE="$(HOTE)" ADRESSE_IP="$(ADRESSE_IP)" VMID="$(VMID)" GROUPES="$(GROUPES)" FICHIER_INVENTAIRE="$(FICHIER_INVENTAIRE)"
|
||||
|
||||
inventaire-verifier: ansible-runtime
|
||||
ansible-inventory -i $(INVENTAIRE_LAB) --list > /dev/null
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -66,10 +66,16 @@ Ouvrir l'interface locale de gestion d'inventaire :
|
|||
make inventaire-ui
|
||||
```
|
||||
|
||||
Planifier une VM sans la créer ni la déployer :
|
||||
|
||||
```bash
|
||||
make hote-planifier HOTE=obs-01 VMID=94101 GROUPES="serveurs_debian serveurs_durcis serveurs_prometheus serveurs_loki"
|
||||
```
|
||||
|
||||
Ajouter une VM à l'inventaire production et l'associer aux groupes qui détermineront sa configuration :
|
||||
|
||||
```bash
|
||||
make hote-ajouter HOTE=web-01 ADRESSE_IP=192.168.12.101 GROUPES="serveurs_debian serveurs_durcis"
|
||||
make hote-ajouter HOTE=web-01 VMID=99101 ADRESSE_IP=192.168.12.101 GROUPES="serveurs_debian serveurs_durcis"
|
||||
make hote-groupes HOTE=web-01 GROUPES="serveurs_debian serveurs_durcis"
|
||||
```
|
||||
|
||||
|
|
@ -117,3 +123,5 @@ Déployer ou remettre en conformité un groupe :
|
|||
```bash
|
||||
make deployer-groupe GROUPE=serveurs_debian
|
||||
```
|
||||
|
||||
Les déploiements de groupes ciblent automatiquement les hôtes actifs seulement.
|
||||
|
|
|
|||
|
|
@ -61,6 +61,18 @@ Les hôtes prévus mais non encore déployés sont placés dans `hotes_planifies
|
|||
|
||||
Les hôtes réellement joignables par Ansible sont placés dans `hotes_actifs`.
|
||||
|
||||
Planifier un hôte :
|
||||
|
||||
```bash
|
||||
make hote-planifier HOTE=obs-01 VMID=94101 GROUPES="serveurs_debian serveurs_durcis serveurs_prometheus serveurs_loki"
|
||||
```
|
||||
|
||||
Activer un hôte existant ou déjà cloné :
|
||||
|
||||
```bash
|
||||
make hote-ajouter HOTE=obs-01 VMID=94101 ADRESSE_IP=192.168.12.141 GROUPES="serveurs_debian serveurs_durcis serveurs_prometheus serveurs_loki"
|
||||
```
|
||||
|
||||
Les déploiements groupés limitent automatiquement l'exécution à :
|
||||
|
||||
```text
|
||||
|
|
|
|||
|
|
@ -100,6 +100,10 @@ Cloud-init ne remplace pas Ansible pour la configuration réelle du serveur.
|
|||
|
||||
Une VM déployée doit être placée dans les groupes d'inventaire qui décrivent l'état voulu.
|
||||
|
||||
Les hôtes prévus mais non créés restent dans `hotes_planifies`.
|
||||
|
||||
Les hôtes joignables par Ansible sont dans `hotes_actifs`.
|
||||
|
||||
Chaque groupe opérationnel doit avoir un playbook homonyme :
|
||||
|
||||
```text
|
||||
|
|
@ -114,14 +118,16 @@ web-01 dans serveurs_debian -> applique le socle Debian
|
|||
web-01 dans serveurs_durcis -> applique le durcissement commun
|
||||
```
|
||||
|
||||
Un groupe sans playbook ne doit pas être assigné à une VM de production tant que son rôle n'est pas implémenté.
|
||||
Un groupe sans playbook ne doit pas être assigné à une VM de production.
|
||||
|
||||
Un playbook de groupe peut être un contrat temporaire sans rôle tant que le service n'est pas encore implémenté. Il doit rester idempotent et explicite.
|
||||
|
||||
## 6. Socle Debian
|
||||
|
||||
Le groupe `serveurs_debian` maintient les composants de base :
|
||||
|
||||
```bash
|
||||
make appliquer GROUPE=serveurs_debian
|
||||
make deployer-groupe GROUPE=serveurs_debian
|
||||
```
|
||||
|
||||
## 7. Hardening commun
|
||||
|
|
@ -129,7 +135,7 @@ make appliquer GROUPE=serveurs_debian
|
|||
Le groupe `serveurs_durcis` maintient les couches de sécurité communes :
|
||||
|
||||
```bash
|
||||
make appliquer GROUPE=serveurs_durcis
|
||||
make deployer-groupe GROUPE=serveurs_durcis
|
||||
```
|
||||
|
||||
L'accès SSH par mot de passe est désactivé dès le socle. L'activation de nftables doit rester dépendante des règles réseau propres au rôle du serveur.
|
||||
|
|
@ -139,7 +145,7 @@ L'accès SSH par mot de passe est désactivé dès le socle. L'activation de nft
|
|||
Pour une VM déjà clonée et démarrée :
|
||||
|
||||
```bash
|
||||
make hote-ajouter HOTE=web-01 ADRESSE_IP=192.168.12.101 GROUPES="serveurs_debian serveurs_durcis"
|
||||
make hote-ajouter HOTE=web-01 VMID=99101 ADRESSE_IP=192.168.12.101 GROUPES="serveurs_debian serveurs_durcis"
|
||||
make deployer HOTE=web-01
|
||||
```
|
||||
|
||||
|
|
@ -159,6 +165,8 @@ Pour converger un groupe complet :
|
|||
make deployer-groupe GROUPE=serveurs_debian
|
||||
```
|
||||
|
||||
Cette commande limite le playbook au croisement entre le groupe demandé et `hotes_actifs`.
|
||||
|
||||
## 9. Variables template et conformité
|
||||
|
||||
Les variables du template servent à construire le golden template dans `inventories/lab/group_vars/modeles_vm.yml`.
|
||||
|
|
|
|||
|
|
@ -16,11 +16,5 @@ all:
|
|||
serveurs_web:
|
||||
hosts: {}
|
||||
|
||||
serveurs_bases_donnees:
|
||||
hosts: {}
|
||||
|
||||
serveurs_supervision:
|
||||
hosts: {}
|
||||
|
||||
hotes_proxmox:
|
||||
hosts: {}
|
||||
|
|
|
|||
|
|
@ -74,10 +74,6 @@ all:
|
|||
web-02:
|
||||
ansible_host: 192.168.12.102
|
||||
ansible_user: ansible
|
||||
serveurs_bases_donnees:
|
||||
hosts: {}
|
||||
serveurs_supervision:
|
||||
hosts: {}
|
||||
serveurs_keycloak:
|
||||
hosts:
|
||||
idm-01: {}
|
||||
|
|
|
|||
|
|
@ -11,12 +11,17 @@ from urllib.parse import urlparse
|
|||
|
||||
import yaml
|
||||
|
||||
from inventory_rules import (
|
||||
GROUPE_HOTES_ACTIFS,
|
||||
GROUPE_HOTES_PLANIFIES,
|
||||
GROUPES_ETAT_HOTE,
|
||||
est_groupe_operationnel,
|
||||
groupes_operationnels_connus,
|
||||
)
|
||||
|
||||
RACINE = Path(__file__).resolve().parents[1]
|
||||
INVENTAIRE_DEFAUT = RACINE / "inventories/production/hosts.yml"
|
||||
DOSSIER_PLAYBOOKS_GROUPES = RACINE / "playbooks/groupes"
|
||||
GROUPES_OPERATIONNELS_PREFIXES = ("serveurs_", "clients_")
|
||||
GROUPES_ETAT = ("hotes_actifs", "hotes_planifies")
|
||||
|
||||
|
||||
def charger_yaml(path: Path) -> dict:
|
||||
|
|
@ -41,9 +46,7 @@ def enfants(data: dict) -> dict:
|
|||
|
||||
|
||||
def groupes_disponibles(data: dict) -> list[str]:
|
||||
groupes = set(enfants(data))
|
||||
groupes.update(playbook.stem for playbook in DOSSIER_PLAYBOOKS_GROUPES.glob("*.yml"))
|
||||
return sorted(group for group in groupes if group.startswith(GROUPES_OPERATIONNELS_PREFIXES))
|
||||
return groupes_operationnels_connus(enfants(data), DOSSIER_PLAYBOOKS_GROUPES)
|
||||
|
||||
|
||||
def variables_hote(data: dict, hote: str) -> dict:
|
||||
|
|
@ -65,15 +68,21 @@ def liste_hotes(data: dict) -> list[dict]:
|
|||
for nom in sorted(noms):
|
||||
groupes = []
|
||||
etat = "planifie"
|
||||
visible = False
|
||||
for groupe, groupe_data in enfants(data).items():
|
||||
if nom not in groupe_data.get("hosts", {}):
|
||||
continue
|
||||
if groupe == "hotes_actifs":
|
||||
if groupe == GROUPE_HOTES_ACTIFS:
|
||||
etat = "actif"
|
||||
elif groupe in GROUPES_ETAT:
|
||||
visible = True
|
||||
elif groupe in GROUPES_ETAT_HOTE:
|
||||
visible = True
|
||||
continue
|
||||
elif groupe.startswith(GROUPES_OPERATIONNELS_PREFIXES):
|
||||
elif est_groupe_operationnel(groupe):
|
||||
groupes.append(groupe)
|
||||
visible = True
|
||||
if not visible:
|
||||
continue
|
||||
variables = variables_hote(data, nom)
|
||||
hotes.append(
|
||||
{
|
||||
|
|
@ -114,8 +123,8 @@ def donnees_hote(hote: dict) -> dict:
|
|||
def construire_inventaire(payload: dict, groupes_connus: list[str]) -> dict:
|
||||
enfants_data: dict = {
|
||||
"modeles_vm": {"hosts": {}},
|
||||
"hotes_actifs": {"hosts": {}},
|
||||
"hotes_planifies": {"hosts": {}},
|
||||
GROUPE_HOTES_ACTIFS: {"hosts": {}},
|
||||
GROUPE_HOTES_PLANIFIES: {"hosts": {}},
|
||||
}
|
||||
for groupe in groupes_connus:
|
||||
enfants_data.setdefault(groupe, {"hosts": {}})
|
||||
|
|
@ -126,7 +135,7 @@ def construire_inventaire(payload: dict, groupes_connus: list[str]) -> dict:
|
|||
if not nom:
|
||||
continue
|
||||
variables = donnees_hote(hote)
|
||||
groupe_etat = "hotes_actifs" if hote.get("etat") == "actif" else "hotes_planifies"
|
||||
groupe_etat = GROUPE_HOTES_ACTIFS if hote.get("etat") == "actif" else GROUPE_HOTES_PLANIFIES
|
||||
enfants_data[groupe_etat]["hosts"][nom] = variables
|
||||
for groupe in hote.get("groupes", []):
|
||||
if groupe not in groupes_connus:
|
||||
|
|
@ -138,6 +147,7 @@ def construire_inventaire(payload: dict, groupes_connus: list[str]) -> dict:
|
|||
|
||||
def valider_payload(payload: dict, groupes_connus: list[str]) -> None:
|
||||
noms: set[str] = set()
|
||||
vmids: dict[str, str] = {}
|
||||
for hote in payload.get("hotes", []):
|
||||
nom = str(hote.get("nom", "")).strip()
|
||||
if not nom:
|
||||
|
|
@ -145,12 +155,20 @@ def valider_payload(payload: dict, groupes_connus: list[str]) -> None:
|
|||
if nom in noms:
|
||||
raise ValueError(f"Hote en double: {nom}")
|
||||
noms.add(nom)
|
||||
if hote.get("etat") == "actif" and not str(hote.get("adresse_ip", "")).strip():
|
||||
raise ValueError(f"Hote actif sans adresse IP: {nom}")
|
||||
groupes = hote.get("groupes", [])
|
||||
if not groupes:
|
||||
raise ValueError(f"Aucun groupe operationnel pour: {nom}")
|
||||
inconnus = sorted(set(groupes) - set(groupes_connus))
|
||||
if inconnus:
|
||||
raise ValueError(f"Groupes inconnus pour {nom}: {', '.join(inconnus)}")
|
||||
vmid = str(hote.get("vmid", "")).strip()
|
||||
if not vmid:
|
||||
continue
|
||||
if vmid in vmids:
|
||||
raise ValueError(f"VMID en double: {vmid} pour {vmids[vmid]} et {nom}")
|
||||
vmids[vmid] = nom
|
||||
|
||||
|
||||
HTML = r"""<!doctype html>
|
||||
|
|
|
|||
|
|
@ -9,11 +9,12 @@ import sys
|
|||
|
||||
import yaml
|
||||
|
||||
|
||||
GROUPES_OPERATIONNELS_PREFIXES = ("serveurs_", "clients_")
|
||||
GROUPE_HOTES_ACTIFS = "hotes_actifs"
|
||||
GROUPE_HOTES_PLANIFIES = "hotes_planifies"
|
||||
GROUPES_ETAT_HOTE = {GROUPE_HOTES_ACTIFS, GROUPE_HOTES_PLANIFIES}
|
||||
from inventory_rules import (
|
||||
GROUPE_HOTES_ACTIFS,
|
||||
GROUPE_HOTES_PLANIFIES,
|
||||
GROUPES_ETAT_HOTE,
|
||||
est_groupe_operationnel,
|
||||
)
|
||||
|
||||
|
||||
def charger_inventaire(path: Path) -> dict:
|
||||
|
|
@ -61,6 +62,13 @@ def variables_hote(data: dict, host: str) -> dict:
|
|||
return merged
|
||||
|
||||
|
||||
def tous_les_hotes(data: dict) -> list[str]:
|
||||
hosts: set[str] = set()
|
||||
for group_data in enfants(data).values():
|
||||
hosts.update(group_data.get("hosts", {}))
|
||||
return sorted(hosts)
|
||||
|
||||
|
||||
def groupes_hote(data: dict, host: str) -> list[str]:
|
||||
groups: list[str] = []
|
||||
for group, group_data in enfants(data).items():
|
||||
|
|
@ -74,12 +82,21 @@ def retirer_hote_de_tous_les_groupes(data: dict, host: str) -> None:
|
|||
group_data.get("hosts", {}).pop(host, None)
|
||||
|
||||
|
||||
def ajouter_hote(data: dict, host: str, groups: list[str], ip: str | None, ansible_user: str | None) -> None:
|
||||
def ajouter_hote(
|
||||
data: dict,
|
||||
host: str,
|
||||
groups: list[str],
|
||||
ip: str | None,
|
||||
ansible_user: str | None,
|
||||
vmid: str | None,
|
||||
) -> None:
|
||||
vars_for_host = variables_hote(data, host)
|
||||
if ip:
|
||||
vars_for_host["ansible_host"] = ip
|
||||
if ansible_user:
|
||||
vars_for_host["ansible_user"] = ansible_user
|
||||
if vmid:
|
||||
vars_for_host["proxmox_vmid"] = int(vmid) if vmid.isdigit() else vmid
|
||||
|
||||
for group in groups:
|
||||
assurer_groupe(data, group)["hosts"][host] = dict(vars_for_host)
|
||||
|
|
@ -87,6 +104,9 @@ def ajouter_hote(data: dict, host: str, groups: list[str], ip: str | None, ansib
|
|||
if ip:
|
||||
assurer_groupe(data, GROUPE_HOTES_ACTIFS)["hosts"][host] = dict(vars_for_host)
|
||||
assurer_groupe(data, GROUPE_HOTES_PLANIFIES)["hosts"].pop(host, None)
|
||||
else:
|
||||
assurer_groupe(data, GROUPE_HOTES_PLANIFIES)["hosts"][host] = dict(vars_for_host)
|
||||
assurer_groupe(data, GROUPE_HOTES_ACTIFS)["hosts"].pop(host, None)
|
||||
|
||||
|
||||
def definir_groupes_hote(data: dict, host: str, groups: list[str]) -> None:
|
||||
|
|
@ -136,7 +156,7 @@ def afficher_playbooks_hote(data: dict, host: str, playbook_dir: Path) -> None:
|
|||
playbooks: list[Path] = []
|
||||
|
||||
for group in groups:
|
||||
if not group.startswith(GROUPES_OPERATIONNELS_PREFIXES):
|
||||
if not est_groupe_operationnel(group):
|
||||
continue
|
||||
playbook = playbook_dir / f"{group}.yml"
|
||||
if playbook.exists():
|
||||
|
|
@ -161,6 +181,36 @@ def verifier_hote_actif(data: dict, host: str) -> None:
|
|||
raise ValueError(f"Hote non actif dans l'inventaire: {host}")
|
||||
|
||||
|
||||
def verifier_coherence_hotes(data: dict) -> None:
|
||||
vmids: dict[str, str] = {}
|
||||
|
||||
for host in tous_les_hotes(data):
|
||||
groups = groupes_hote(data, host)
|
||||
state_groups = [group for group in groups if group in GROUPES_ETAT_HOTE]
|
||||
operational_groups = [group for group in groups if est_groupe_operationnel(group)]
|
||||
vars_for_host = variables_hote(data, host)
|
||||
|
||||
if not state_groups and not operational_groups:
|
||||
continue
|
||||
if len(state_groups) != 1:
|
||||
raise ValueError(
|
||||
f"{host} doit appartenir exactement a un groupe d'etat: "
|
||||
f"{GROUPE_HOTES_ACTIFS} ou {GROUPE_HOTES_PLANIFIES}"
|
||||
)
|
||||
if not operational_groups:
|
||||
raise ValueError(f"{host} doit appartenir a au moins un groupe operationnel.")
|
||||
if GROUPE_HOTES_ACTIFS in state_groups and not vars_for_host.get("ansible_host"):
|
||||
raise ValueError(f"{host} est actif mais n'a pas ansible_host.")
|
||||
|
||||
vmid = vars_for_host.get("proxmox_vmid")
|
||||
if vmid in (None, ""):
|
||||
continue
|
||||
vmid_key = str(vmid)
|
||||
if vmid_key in vmids and vmids[vmid_key] != host:
|
||||
raise ValueError(f"VMID en double: {vmid_key} pour {vmids[vmid_key]} et {host}")
|
||||
vmids[vmid_key] = host
|
||||
|
||||
|
||||
def verifier_playbooks_groupes(data: dict, playbook_dir: Path) -> None:
|
||||
missing_playbooks: list[str] = []
|
||||
|
||||
|
|
@ -168,7 +218,7 @@ def verifier_playbooks_groupes(data: dict, playbook_dir: Path) -> None:
|
|||
hosts = group_data.get("hosts", {})
|
||||
if not hosts:
|
||||
continue
|
||||
if not group.startswith(GROUPES_OPERATIONNELS_PREFIXES):
|
||||
if not est_groupe_operationnel(group):
|
||||
continue
|
||||
playbook = playbook_dir / f"{group}.yml"
|
||||
if not playbook.exists():
|
||||
|
|
@ -178,6 +228,8 @@ def verifier_playbooks_groupes(data: dict, playbook_dir: Path) -> None:
|
|||
missing = ", ".join(sorted(missing_playbooks))
|
||||
raise ValueError(f"Playbook de groupe manquant pour: {missing}")
|
||||
|
||||
verifier_coherence_hotes(data)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Gere les hotes d'un inventaire Ansible statique Set-OPS.")
|
||||
|
|
@ -190,6 +242,7 @@ def main() -> int:
|
|||
add_parser.add_argument("--groupes", required=True)
|
||||
add_parser.add_argument("--adresse-ip")
|
||||
add_parser.add_argument("--utilisateur-ansible")
|
||||
add_parser.add_argument("--vmid")
|
||||
add_parser.add_argument("--dossier-playbooks", type=Path)
|
||||
|
||||
groups_parser = subparsers.add_parser("definir-groupes", help="Remplace l'appartenance aux groupes pour un hote.")
|
||||
|
|
@ -225,6 +278,7 @@ def main() -> int:
|
|||
analyser_groupes(args.groupes),
|
||||
args.adresse_ip,
|
||||
args.utilisateur_ansible,
|
||||
args.vmid,
|
||||
)
|
||||
if args.dossier_playbooks:
|
||||
verifier_playbooks_groupes(data, args.dossier_playbooks)
|
||||
|
|
|
|||
22
scripts/inventory_rules.py
Normal file
22
scripts/inventory_rules.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Regles partagees pour les inventaires statiques Set-OPS."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
GROUPES_OPERATIONNELS_PREFIXES = ("serveurs_", "clients_")
|
||||
GROUPE_HOTES_ACTIFS = "hotes_actifs"
|
||||
GROUPE_HOTES_PLANIFIES = "hotes_planifies"
|
||||
GROUPES_ETAT_HOTE = {GROUPE_HOTES_ACTIFS, GROUPE_HOTES_PLANIFIES}
|
||||
|
||||
|
||||
def est_groupe_operationnel(groupe: str) -> bool:
|
||||
return groupe.startswith(GROUPES_OPERATIONNELS_PREFIXES)
|
||||
|
||||
|
||||
def groupes_operationnels_connus(enfants: dict, dossier_playbooks: Path) -> list[str]:
|
||||
groupes = set(enfants)
|
||||
groupes.update(playbook.stem for playbook in dossier_playbooks.glob("*.yml"))
|
||||
return sorted(groupe for groupe in groupes if est_groupe_operationnel(groupe))
|
||||
Reference in a new issue