Corps du message compose de blocs, macros Centreon en suggestion
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (push) Successful in 9m50s
build / Garde-fou (push) Successful in 10m27s
build / Images Harbor (web, Dockerfile) (push) Successful in 13m25s

This commit is contained in:
hcornet committed 2026-09-11 16:46:31 +02:00
1 parent cdfa377f46
commit 3879b63a88
10 files changed
+958 -114

No files matched your search

+36
View File
@@ -0,0 +1,36 @@
"""Fixtures communes aux tests."""
from __future__ import annotations
import importlib
import pytest
@pytest.fixture()
def app(tmp_path, monkeypatch):
"""Application avec une base SQLite temporaire."""
monkeypatch.setenv("ENCLUME_DATABASE_URL", f"sqlite:///{tmp_path/'essai.db'}")
monkeypatch.setenv("ENCLUME_CATALOG", "catalog")
monkeypatch.setenv("ENCLUME_SECRET_KEY", "cle-de-test")
monkeypatch.setenv("ENCLUME_COOKIE_SECURE", "0")
import enclume.auth
import enclume.config
import enclume.db
import enclume.routes_donnees
import enclume.webapp
for module in (
enclume.config,
enclume.db,
enclume.auth,
enclume.routes_donnees,
enclume.webapp,
):
importlib.reload(module)
application = enclume.webapp.create_app()
with application.app_context():
enclume.db.db.create_all()
return application
+157
View File
@@ -214,3 +214,160 @@ def test_modele_sans_perimetre_ne_produit_aucun_cablage():
donnees["host_templates"] = [{"name": "App-Y-custom"}]
lignes = lignes_clapi(Project.from_dict(donnees))
assert not any("App-Y-custom" in ligne and "notification_period" in ligne for ligne in lignes)
def test_apercu_reprend_le_contexte_du_perimetre():
from enclume.notifications import apercu
projet = Project.from_dict(PROJET)
rendu = apercu(projet, projet.perimetres[0], "service")
assert "App-DB-MySQL-Connection-Time" in rendu["sujet"]
assert "CRITICAL" in rendu["sujet"]
for attendu in ("Facturation", "Equipe finance", "Majeure", "reprise-facturation"):
assert attendu in rendu["corps"]
assert rendu["script"].endswith("notif-applicatif-facturation.php")
def test_apercu_hote_n_affiche_pas_de_service():
from enclume.notifications import apercu
projet = Project.from_dict(PROJET)
rendu = apercu(projet, projet.perimetres[0], "host")
assert "Service" not in rendu["corps"].split("<table")[1].split("</table>")[0]
assert "DOWN" in rendu["sujet"]
def test_apercu_echappe_les_valeurs():
"""La sortie d'un plugin ou un champ metier ne doit pas pouvoir injecter du HTML."""
from enclume.notifications import apercu
donnees = dict(PROJET)
donnees["perimetres"] = [
dict(PROJET["perimetres"][0], impact="<script>alert(1)</script>")
]
projet = Project.from_dict(donnees)
rendu = apercu(projet, projet.perimetres[0], "service")
assert "<script>alert(1)</script>" not in rendu["corps"]
assert "&lt;script&gt;" in rendu["corps"]
def test_apercu_et_script_partagent_le_gabarit():
"""Les deux doivent montrer la meme chose : un gabarit unique le garantit."""
from enclume.notifications import GABARIT_HTML, GABARIT_LIGNE, rendre_script
projet = Project.from_dict(PROJET)
script = rendre_script(projet, projet.perimetres[0])
assert GABARIT_HTML in script
assert GABARIT_LIGNE in script
def test_route_d_apercu():
"""L'apercu ne demande ni base ni connexion : il ne conserve rien."""
from enclume.webapp import create_app
projet = Project.from_dict(PROJET).to_dict()
client = create_app().test_client()
reponse = client.post(
"/api/apercu-notification",
json={"project": projet, "perimetre": "Applicatif Facturation", "pour": "service"},
)
assert reponse.status_code == 200
assert "Emission des factures bloquee" in reponse.get_json()["corps"]
inconnu = client.post(
"/api/apercu-notification", json={"project": projet, "perimetre": "Inexistant"}
)
assert inconnu.status_code == 404
# --------------------------------------------------------------- composition
PROJET_COMPOSE = dict(
PROJET,
perimetres=[
dict(
PROJET["perimetres"][0],
blocs_service=[
{"type": "macro", "libelle": "Hote", "valeur": "$HOSTNAME$"},
{"type": "macro", "libelle": "Auteur", "valeur": "$NOTIFICATIONAUTHOR$"},
{"type": "macro", "libelle": "Commentaire", "valeur": "$NOTIFICATIONCOMMENT$"},
{"type": "lien", "libelle": "Documentation", "valeur": "$SERVICENOTESURL$"},
{"type": "texte", "libelle": "Astreinte", "valeur": "Appeler le 3000"},
{"type": "sortie", "libelle": "Sortie", "valeur": "$SERVICEOUTPUT$"},
],
)
],
)
def test_la_commande_transporte_les_macros_des_blocs():
lignes = lignes_clapi(Project.from_dict(PROJET_COMPOSE))
commande = next(ligne for ligne in lignes if "-Notify-Service" in ligne)
# Un argument par bloc qui porte une macro, le texte fixe reste dans le script.
assert "--b1='$HOSTNAME$'" in commande
assert "--b2='$NOTIFICATIONAUTHOR$'" in commande
assert "--b4='$SERVICENOTESURL$'" in commande
assert "--b5=" not in commande, "un bloc de texte fixe ne doit pas passer par la commande"
assert "--b6='$SERVICEOUTPUT$'" in commande
def test_les_blocs_par_defaut_couvrent_l_essentiel():
from enclume.notifications import blocs_par_defaut
projet = Project.from_dict(PROJET)
blocs = blocs_par_defaut(projet.perimetres[0], "service")
macros = [b.valeur for b in blocs if b.type == "macro"]
for attendue in ("$HOSTNAME$", "$SERVICEDESC$", "$NOTIFICATIONAUTHOR$", "$NOTIFICATIONCOMMENT$"):
assert attendue in macros
assert any(b.type == "sortie" for b in blocs)
# Le contexte du perimetre devient des blocs de texte.
assert any(b.type == "texte" and b.valeur == "Facturation" for b in blocs)
def test_l_apercu_suit_la_composition():
from enclume.notifications import apercu
projet = Project.from_dict(PROJET_COMPOSE)
rendu = apercu(projet, projet.perimetres[0], "service")
assert "Prise en compte" in rendu["corps"] # $NOTIFICATIONCOMMENT$
assert "Appeler le 3000" in rendu["corps"] # bloc de texte
assert "wiki.exemple.fr/mysql-facturation" in rendu["corps"] # bloc lien
assert "Criticite" not in rendu["corps"], "les blocs composes remplacent les defauts"
def test_macro_inconnue_affichee_en_reperage():
"""Une macro sans exemple doit tout de meme montrer la ligne qu'elle produira."""
from enclume.notifications import apercu
donnees = dict(PROJET)
donnees["perimetres"] = [
dict(
PROJET["perimetres"][0],
blocs_service=[{"type": "macro", "libelle": "Perso", "valeur": "$_SERVICEAPPLI$"}],
)
]
projet = Project.from_dict(donnees)
rendu = apercu(projet, projet.perimetres[0], "service")
assert "[$_SERVICEAPPLI$]" in rendu["corps"]
def test_liste_des_macros_exposee(app):
reponse = app.test_client().get("/api/macros-notification")
assert reponse.status_code == 200
macros = [m["macro"] for m in reponse.get_json()]
assert "$NOTIFICATIONAUTHOR$" in macros
assert "$SERVICENOTESURL$" in macros
def test_blocs_par_defaut_exposes(app):
projet = Project.from_dict(PROJET).to_dict()
reponse = app.test_client().post(
"/api/blocs-defaut",
json={"project": projet, "perimetre": "Applicatif Facturation", "pour": "host"},
)
assert reponse.status_code == 200
blocs = reponse.get_json()
assert any(b["valeur"] == "$HOSTOUTPUT$" for b in blocs)
assert not any(b["valeur"] == "$SERVICEDESC$" for b in blocs)
-22
View File
@@ -37,28 +37,6 @@ services:
"""
@pytest.fixture()
def app(tmp_path, monkeypatch):
monkeypatch.setenv("ENCLUME_DATABASE_URL", f"sqlite:///{tmp_path/'essai.db'}")
monkeypatch.setenv("ENCLUME_CATALOG", "catalog")
monkeypatch.setenv("ENCLUME_SECRET_KEY", "cle-de-test")
monkeypatch.setenv("ENCLUME_COOKIE_SECURE", "0")
import enclume.auth
import enclume.config
import enclume.db
import enclume.routes_donnees
import enclume.webapp
for module in (enclume.config, enclume.db, enclume.auth, enclume.routes_donnees, enclume.webapp):
importlib.reload(module)
application = enclume.webapp.create_app()
with application.app_context():
enclume.db.db.create_all()
return application
def _connecter(app, client, administrateur=False):
"""Cree un compte et ouvre une session, sans passer par le fournisseur OIDC."""
from enclume.db import Utilisateur, db