Set-OPS-Public/scripts/tests/test_fraicheur_icinga.py
Daniel Allaire 185b000c60 icinga : un service passif qui n a jamais rien recu passe au rouge
Gabarit setops-rapport-attendu : actif, dummy critique, check_interval = le
ttl que le noeud envoie. Prouve a t+60 s sur site-mon-01, deploye sur les trois
Icinga ; la garde test_fraicheur_icinga lie seuils et ttl.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 12:05:15 -04:00

66 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""Les seuils de fraicheur d'Icinga suivent les `ttl` que les noeuds envoient.
UNE LISTE QUI EN SUIT UNE AUTRE PREND DU RETARD (2026-09-28). Les services passifs de
Set-OPS passent CRITIQUES quand aucun rapport n'arrive dans leur `check_interval`. Ce
seuil vit dans `serveur_icinga` ; le `ttl` que chaque noeud envoie vit dans le role qui
rapporte. Si le seuil devient plus court que le rythme des rapports, tout rougit a tort ;
plus long, un noeud muet reste vert trop longtemps. Les deux doivent etre egaux.
Et plus aucun service passif ne doit revenir a `enable_active_checks = false` : c'est
exactement ce qui laissait un service jamais alimente « en attente », jamais rouge.
"""
from __future__ import annotations
import re
import sys
from pathlib import Path
import yaml
RACINE = Path(__file__).resolve().parents[2]
ROLES = RACINE / "roles"
def defauts(role: str) -> dict:
return yaml.safe_load((ROLES / role / "defaults" / "main.yml").read_text(encoding="utf-8")) or {}
def main() -> int:
icinga = defauts("serveur_icinga")
paires = [
("serveur_icinga_fraicheur_sauvegarde", "client_backup", "client_backup_ttl_icinga"),
("serveur_icinga_fraicheur_sauvegarde", "serveur_backup", "serveur_backup_ttl_icinga"),
("serveur_icinga_fraicheur_sante", "client_sante", "client_sante_ttl_icinga"),
("serveur_icinga_fraicheur_sondes", "client_sante", "client_sante_ttl_sondes"),
]
echecs = 0
for seuil, role, ttl in paires:
a, b = icinga.get(seuil), defauts(role).get(ttl)
if a is None or b is None or int(a) != int(b):
print(f"ECHEC {seuil} = {a} ≠ {role}.{ttl} = {b}")
echecs += 1
else:
print(f"ok {seuil} = {role}.{ttl} = {a}")
gabarits = ROLES / "serveur_icinga" / "templates"
for f in sorted(gabarits.glob("setops-*.conf.j2")):
code = re.sub(r"/\*.*?\*/|\{#.*?#\}", "", f.read_text(encoding="utf-8"), flags=re.S)
for bloc in re.findall(r'object Service "[^"]*" \{.*?\n\}', code, flags=re.S):
if "enable_passive_checks = true" in bloc and "setops-rapport-attendu" not in bloc:
print(f"ECHEC {f.name} : service passif sans `setops-rapport-attendu` :\n{bloc[:120]}")
echecs += 1
if "enable_active_checks = false" in code:
print(f"ECHEC {f.name} : `enable_active_checks = false` — un service jamais "
f"alimente resterait « en attente », jamais rouge")
echecs += 1
if echecs:
print(f"\n{echecs} echec(s).")
return 1
print("OK — fraicheur d'Icinga alignee sur les ttl, aucun service passif sans echeance.")
return 0
if __name__ == "__main__":
sys.exit(main())