build / Garde-fou (pull_request) Failing after 7s
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (pull_request) Skipped
build / Images Harbor (web, Dockerfile) (pull_request) Skipped
build / Garde-fou (push) Failing after 8s
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (push) Skipped
build / Images Harbor (web, Dockerfile) (push) Skipped
124 lines
4.3 KiB
Python
124 lines
4.3 KiB
Python
"""Garde-fous minimaux : ce qui casserait silencieusement le code genere."""
|
|
|
|
import json
|
|
|
|
from enclume.catalog import Catalog
|
|
from enclume.generator import build_plan, render_bundle
|
|
from enclume.model import Project, strip_secrets, validate
|
|
from enclume.packs import pack_to_project
|
|
from enclume.webapp import create_app
|
|
|
|
|
|
def projet_exemple() -> Project:
|
|
catalog = Catalog("catalog")
|
|
return pack_to_project(catalog.get("os-linux-snmp"))
|
|
|
|
|
|
def test_catalogue_lisible():
|
|
catalog = Catalog("catalog")
|
|
assert not catalog.errors
|
|
assert len(catalog.packs) >= 20
|
|
|
|
|
|
def test_plan_complet():
|
|
plan = build_plan(projet_exemple())
|
|
lignes = plan.ops
|
|
assert any(o.obj == "CMD" and o.action == "ADD" for o in lignes)
|
|
assert any(o.obj == "STPL" and o.action == "addhosttemplate" for o in lignes)
|
|
assert not plan.has_errors
|
|
|
|
|
|
def test_prefixe_applique_aux_references():
|
|
projet = projet_exemple()
|
|
projet.prefix = "ACME-"
|
|
lignes = [o.import_line() for o in build_plan(projet).ops if o.obj != "#"]
|
|
liaison = [l for l in lignes if l.startswith("STPL;addhosttemplate")][0]
|
|
assert liaison.count("ACME-") == 2
|
|
|
|
|
|
def test_version_historique_convertie():
|
|
"""Un projet enregistre avec l'ancienne notation reste lisible."""
|
|
projet = Project.from_dict({"centreon_version": "24.x"})
|
|
assert projet.centreon_version == "24.10"
|
|
assert Project.from_dict({}).centreon_version == "25.10"
|
|
|
|
|
|
def test_macros_trois_champs_sur_ancienne_version():
|
|
projet = projet_exemple()
|
|
projet.centreon_version = "legacy"
|
|
macro = [o for o in build_plan(projet).ops if o.action == "setmacro"][0]
|
|
assert len(macro.values) == 3
|
|
|
|
|
|
def test_echappement_shell_des_macros_centreon():
|
|
fichiers = render_bundle(build_plan(projet_exemple()))
|
|
ligne = [l for l in fichiers["deploy.sh"].splitlines() if "HOSTADDRESS" in l][0]
|
|
assert ligne.startswith("clapi -o CMD -a ADD -v '")
|
|
|
|
|
|
def test_point_virgule_refuse():
|
|
projet = projet_exemple()
|
|
projet.commands[0].line += "; rm -rf /"
|
|
erreurs = [i for i in validate(projet) if i["level"] == "error"]
|
|
assert erreurs
|
|
|
|
|
|
def test_les_mots_de_passe_ne_sont_pas_conserves():
|
|
projet = projet_exemple()
|
|
projet.host_templates[0].macros.append(
|
|
type(projet.host_templates[0].macros[0])(name="PASSWORD", value="secret", is_password=True)
|
|
)
|
|
assert all(not m.value for m in strip_secrets(projet).host_templates[0].macros if m.is_password)
|
|
|
|
|
|
def test_api_de_generation():
|
|
client = create_app().test_client()
|
|
reponse = client.post("/api/generer", json={"project": projet_exemple().to_dict()})
|
|
donnees = reponse.get_json()
|
|
assert reponse.status_code == 200
|
|
assert donnees["files"]["deploy.clapi"].startswith("#")
|
|
assert donnees["summary"]["operations"] > 0
|
|
|
|
|
|
def test_sante():
|
|
reponse = create_app().test_client().get("/sante")
|
|
assert reponse.get_json()["statut"] == "ok"
|
|
|
|
|
|
def test_repli_sur_le_catalogue_de_l_image(tmp_path, monkeypatch):
|
|
"""Un volume vide ne doit jamais donner un site sans aucun pack."""
|
|
import importlib
|
|
|
|
monkeypatch.setenv("ENCLUME_CATALOG", str(tmp_path))
|
|
monkeypatch.setenv("ENCLUME_CATALOG_FALLBACK", "catalog")
|
|
import enclume.webapp as webapp
|
|
|
|
importlib.reload(webapp)
|
|
reponse = webapp.create_app().test_client().get("/sante")
|
|
donnees = reponse.get_json()
|
|
assert donnees["packs"] >= 20
|
|
assert donnees["source_catalogue"] == "catalog"
|
|
|
|
|
|
def test_toutes_les_ressources_de_la_page_existent():
|
|
"""Un lien casse vers le script rend l'interface muette sans aucune erreur serveur."""
|
|
import re
|
|
|
|
client = create_app().test_client()
|
|
html = client.get("/").data.decode()
|
|
refs = re.findall(r'(?:src|href)="(/static/[^"]+)"', html)
|
|
assert refs, "la page ne reference aucune ressource statique"
|
|
for ref in refs:
|
|
assert client.get(ref).status_code == 200, f"ressource introuvable : {ref}"
|
|
|
|
|
|
def test_le_script_expose_les_gestionnaires_attendus():
|
|
"""Les identifiants du gabarit et ceux du script doivent correspondre."""
|
|
import re
|
|
|
|
client = create_app().test_client()
|
|
html = client.get("/").data.decode()
|
|
script = client.get("/static/editeur.js").data.decode()
|
|
for identifiant in re.findall(r'id="(btn-[^"]+|projet-[^"]+)"', html):
|
|
assert identifiant in script, f"aucun gestionnaire pour {identifiant}"
|