192 lines
6 KiB
Python
192 lines
6 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""Gere les hotes d'un inventaire Ansible statique Set-OPS."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import argparse
|
||
|
|
from pathlib import Path
|
||
|
|
import sys
|
||
|
|
|
||
|
|
import yaml
|
||
|
|
|
||
|
|
|
||
|
|
def charger_inventaire(path: Path) -> dict:
|
||
|
|
if not path.exists():
|
||
|
|
return {"all": {"children": {}}}
|
||
|
|
|
||
|
|
with path.open("r", encoding="utf-8") as inventory_file:
|
||
|
|
data = yaml.safe_load(inventory_file) or {}
|
||
|
|
|
||
|
|
if not isinstance(data, dict):
|
||
|
|
raise ValueError(f"{path} ne contient pas une table YAML.")
|
||
|
|
|
||
|
|
data.setdefault("all", {})
|
||
|
|
data["all"].setdefault("children", {})
|
||
|
|
return data
|
||
|
|
|
||
|
|
|
||
|
|
def ecrire_inventaire(path: Path, data: dict) -> None:
|
||
|
|
with path.open("w", encoding="utf-8") as inventory_file:
|
||
|
|
yaml.safe_dump(
|
||
|
|
data,
|
||
|
|
inventory_file,
|
||
|
|
default_flow_style=False,
|
||
|
|
sort_keys=False,
|
||
|
|
allow_unicode=True,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def enfants(data: dict) -> dict:
|
||
|
|
return data.setdefault("all", {}).setdefault("children", {})
|
||
|
|
|
||
|
|
|
||
|
|
def assurer_groupe(data: dict, group: str) -> dict:
|
||
|
|
group_data = enfants(data).setdefault(group, {})
|
||
|
|
group_data.setdefault("hosts", {})
|
||
|
|
return group_data
|
||
|
|
|
||
|
|
|
||
|
|
def variables_hote(data: dict, host: str) -> dict:
|
||
|
|
merged: dict = {}
|
||
|
|
for group_data in enfants(data).values():
|
||
|
|
hosts = group_data.get("hosts", {})
|
||
|
|
if host in hosts and isinstance(hosts[host], dict):
|
||
|
|
merged.update(hosts[host])
|
||
|
|
return merged
|
||
|
|
|
||
|
|
|
||
|
|
def groupes_hote(data: dict, host: str) -> list[str]:
|
||
|
|
groups: list[str] = []
|
||
|
|
for group, group_data in enfants(data).items():
|
||
|
|
if host in group_data.get("hosts", {}):
|
||
|
|
groups.append(group)
|
||
|
|
return groups
|
||
|
|
|
||
|
|
|
||
|
|
def retirer_hote_de_tous_les_groupes(data: dict, host: str) -> None:
|
||
|
|
for group_data in enfants(data).values():
|
||
|
|
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:
|
||
|
|
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
|
||
|
|
|
||
|
|
for group in groups:
|
||
|
|
assurer_groupe(data, group)["hosts"][host] = dict(vars_for_host)
|
||
|
|
|
||
|
|
|
||
|
|
def definir_groupes_hote(data: dict, host: str, groups: list[str]) -> None:
|
||
|
|
vars_for_host = variables_hote(data, host)
|
||
|
|
if not groupes_hote(data, host):
|
||
|
|
raise ValueError(f"Hote absent de l'inventaire: {host}")
|
||
|
|
retirer_hote_de_tous_les_groupes(data, host)
|
||
|
|
for group in groups:
|
||
|
|
assurer_groupe(data, group)["hosts"][host] = dict(vars_for_host)
|
||
|
|
|
||
|
|
|
||
|
|
def analyser_groupes(raw_groups: str) -> list[str]:
|
||
|
|
groups = [group.strip() for group in raw_groups.replace(",", " ").split() if group.strip()]
|
||
|
|
if not groups:
|
||
|
|
raise ValueError("Au moins un groupe est requis.")
|
||
|
|
return groups
|
||
|
|
|
||
|
|
|
||
|
|
def afficher_hote(data: dict, host: str) -> None:
|
||
|
|
groups = groupes_hote(data, host)
|
||
|
|
if not groups:
|
||
|
|
raise ValueError(f"Hote absent de l'inventaire: {host}")
|
||
|
|
|
||
|
|
yaml.safe_dump(
|
||
|
|
{
|
||
|
|
"hote": host,
|
||
|
|
"groupes": groups,
|
||
|
|
"variables": variables_hote(data, host),
|
||
|
|
},
|
||
|
|
sys.stdout,
|
||
|
|
default_flow_style=False,
|
||
|
|
sort_keys=False,
|
||
|
|
allow_unicode=True,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def afficher_playbooks_hote(data: dict, host: str, playbook_dir: Path) -> None:
|
||
|
|
groups = groupes_hote(data, host)
|
||
|
|
if not groups:
|
||
|
|
raise ValueError(f"Hote absent de l'inventaire: {host}")
|
||
|
|
|
||
|
|
missing_playbooks: list[str] = []
|
||
|
|
playbooks: list[Path] = []
|
||
|
|
|
||
|
|
for group in groups:
|
||
|
|
playbook = playbook_dir / f"{group}.yml"
|
||
|
|
if playbook.exists():
|
||
|
|
playbooks.append(playbook)
|
||
|
|
else:
|
||
|
|
missing_playbooks.append(group)
|
||
|
|
|
||
|
|
if missing_playbooks:
|
||
|
|
missing = ", ".join(missing_playbooks)
|
||
|
|
raise ValueError(f"Playbook de groupe manquant pour: {missing}")
|
||
|
|
|
||
|
|
for playbook in playbooks:
|
||
|
|
print(playbook)
|
||
|
|
|
||
|
|
|
||
|
|
def main() -> int:
|
||
|
|
parser = argparse.ArgumentParser(description="Gere les hotes d'un inventaire Ansible statique Set-OPS.")
|
||
|
|
parser.add_argument("--inventaire", required=True, type=Path)
|
||
|
|
|
||
|
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
||
|
|
|
||
|
|
add_parser = subparsers.add_parser("ajouter", help="Ajoute ou met a jour un hote dans un ou plusieurs groupes.")
|
||
|
|
add_parser.add_argument("--hote", required=True)
|
||
|
|
add_parser.add_argument("--groupes", required=True)
|
||
|
|
add_parser.add_argument("--adresse-ip")
|
||
|
|
add_parser.add_argument("--utilisateur-ansible")
|
||
|
|
|
||
|
|
groups_parser = subparsers.add_parser("definir-groupes", help="Remplace l'appartenance aux groupes pour un hote.")
|
||
|
|
groups_parser.add_argument("--hote", required=True)
|
||
|
|
groups_parser.add_argument("--groupes", required=True)
|
||
|
|
|
||
|
|
show_parser = subparsers.add_parser("afficher", help="Affiche les groupes et variables d'un hote.")
|
||
|
|
show_parser.add_argument("--hote", required=True)
|
||
|
|
|
||
|
|
playbooks_parser = subparsers.add_parser("playbooks", help="Affiche les playbooks de groupes pour un hote.")
|
||
|
|
playbooks_parser.add_argument("--hote", required=True)
|
||
|
|
playbooks_parser.add_argument("--dossier-playbooks", required=True, type=Path)
|
||
|
|
|
||
|
|
args = parser.parse_args()
|
||
|
|
|
||
|
|
try:
|
||
|
|
data = charger_inventaire(args.inventaire)
|
||
|
|
|
||
|
|
if args.command == "ajouter":
|
||
|
|
ajouter_hote(
|
||
|
|
data,
|
||
|
|
args.hote,
|
||
|
|
analyser_groupes(args.groupes),
|
||
|
|
args.adresse_ip,
|
||
|
|
args.utilisateur_ansible,
|
||
|
|
)
|
||
|
|
ecrire_inventaire(args.inventaire, data)
|
||
|
|
elif args.command == "definir-groupes":
|
||
|
|
definir_groupes_hote(data, args.hote, analyser_groupes(args.groupes))
|
||
|
|
ecrire_inventaire(args.inventaire, data)
|
||
|
|
elif args.command == "afficher":
|
||
|
|
afficher_hote(data, args.hote)
|
||
|
|
elif args.command == "playbooks":
|
||
|
|
afficher_playbooks_hote(data, args.hote, args.dossier_playbooks)
|
||
|
|
except Exception as exc:
|
||
|
|
print(f"erreur: {exc}", file=sys.stderr)
|
||
|
|
return 2
|
||
|
|
|
||
|
|
return 0
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
raise SystemExit(main())
|