Masquer les packs deja importes dans la fenetre d'import
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (push) Successful in 9m52s
build / Garde-fou (push) Successful in 10m41s
build / Images Harbor (web, Dockerfile) (push) Successful in 13m15s

This commit is contained in:
hcornet committed 2026-09-11 19:32:39 +02:00
1 parent 2187a1971e
commit ec195cac8f
71 files changed
+796 -30

No files matched your search

+41 -1
View File
@@ -30,7 +30,11 @@ const dom = new JSDOM(html, {
const { window } = dom;
// Reponses minimales mais de la bonne forme, comme celles du serveur.
const reponses = {
'/api/packs': [],
'/api/packs': [
{ id: 'app-essai', name: 'Essai', category: 'applications', category_label: 'Applications',
status: 'verified', plugin: 'essai.pl', description: 'Pack d essai',
host_template: 'App-Essai-custom', services: [] },
],
'/api/generer': { summary: {}, issues: [], files: { 'deploy.clapi': '' } },
'/api/projets': [],
};
@@ -90,6 +94,42 @@ if (erreurs.length === 0) {
}
}
// Un pack deja dans le projet ne doit plus etre proposable a l'import.
try {
window.eval("projetCourant().host_templates.push({ name: 'App-Essai-custom', macros: [], parents: [] });");
document.getElementById('btn-pack').click();
await new Promise((r) => setTimeout(r, 30));
const corps = document.getElementById('modal-corps');
const boutons = [...corps.querySelectorAll('button')].map((b) => b.textContent);
if (boutons.includes('Sondes par defaut')) {
erreurs.push('un pack deja importe reste proposable');
}
if (!corps.textContent.includes('deja dans le projet')) {
erreurs.push('le masquage des packs importes n est pas signale');
}
// Affiches a la demande, ils restent sans action : les reimporter n'aurait
// aucun effet, et un bouton inerte ferait douter l'utilisateur.
const afficher = [...corps.querySelectorAll('button')]
.find((b) => b.textContent === 'Les afficher');
if (!afficher) {
erreurs.push('aucun moyen d afficher les packs masques');
} else {
afficher.click();
await new Promise((r) => setTimeout(r, 30));
const apres = [...corps.querySelectorAll('button')].map((b) => b.textContent);
if (apres.includes('Sondes par defaut')) {
erreurs.push('un pack deja importe redevient proposable une fois affiche');
}
if (!corps.textContent.includes('deja importe')) {
erreurs.push('un pack affiche n est pas signale comme deja importe');
}
}
document.querySelector('[data-fermer-modal]').click();
} catch (erreur) {
erreurs.push('catalogue de packs : ' + erreur.message);
}
// Les notifications doivent s'afficher, avec leur type.
try {
window.eval("notifier('essai de reussite', 'succes'); notifier('essai d erreur', 'erreur');");
+91
View File
@@ -208,3 +208,94 @@ def test_rollback_supprime_les_groupes_d_hotes():
projet = Project.from_dict({"groupes_hotes": [{"name": "HG-Essai"}]})
lignes = [o.import_line() for o in build_plan(projet).rollback_ops]
assert "HG;DEL;HG-Essai" in lignes
def test_chaque_pack_livre_son_groupe_d_hotes():
"""Un utilisateur qui importe un pack doit recevoir une configuration complete."""
from enclume.packs import pack_to_project
catalogue = Catalog("catalog")
sans = [p.id for p in catalogue.packs.values() if not p.groupe_hote]
assert not sans, f"packs sans groupe d'hotes : {sans}"
projet = pack_to_project(catalogue.get("app-mysql"))
assert [g.name for g in projet.groupes_hotes] == ["HG-App-DB-MySQL"]
lignes = [o.import_line() for o in build_plan(projet).ops if o.obj == "HG"]
assert lignes == ["HG;ADD;HG-App-DB-MySQL;MySQL / MariaDB"]
def test_commande_et_fuseau_sur_l_hote():
"""La commande de verification et le fuseau appartiennent a l'hote."""
projet = Project.from_dict(
{
"hosts": [
{
"name": "srv-01",
"address": "10.0.4.1",
"check_command": "check_centreon_ping",
"check_command_args": "!3!200,20%!400,50%",
"timezone": "Europe/Paris",
}
]
}
)
lignes = [o.import_line() for o in build_plan(projet).ops if o.obj == "HOST"]
assert "HOST;setparam;srv-01;check_command;check_centreon_ping" in lignes
assert "HOST;setparam;srv-01;check_command_arguments;!3!200,20%!400,50%" in lignes
assert "HOST;setparam;srv-01;timezone;Europe/Paris" in lignes
def test_fuseau_horaire_errone_refuse():
"""Une faute de frappe sur un fuseau ne se verrait qu'a l'execution."""
from enclume.model import fuseaux_horaires, validate
if not fuseaux_horaires():
return # base de fuseaux absente de la machine
projet = Project.from_dict(
{"hosts": [{"name": "srv", "address": "10.0.0.1", "timezone": "Europe/Pariss"}]}
)
erreurs = [i["message"] for i in validate(projet) if i["level"] == "error"]
assert any("fuseau horaire inconnu" in m for m in erreurs)
def test_les_fuseaux_sont_exposes():
client = create_app().test_client()
fuseaux = client.get("/api/fuseaux").get_json()
assert "Europe/Paris" in fuseaux
commandes = [c["nom"] for c in client.get("/api/commandes-usuelles").get_json()]
assert "check_centreon_ping" in commandes
def test_guide_snmp_accessible_et_complet():
"""Une page d'aide qui n'aborde pas la securite ferait plus de mal que de bien."""
page = create_app().test_client().get("/aide/snmp").data.decode()
for systeme in ("Debian", "RHEL", "Windows", "Cisco"):
assert systeme in page, systeme
# Les points de securite qui distinguent une configuration tenable.
for notion in ("authPriv", "rocommunity", "PermittedManagers", "snmpwalk", "firewall-cmd"):
assert notion in page, notion
# La lecture seule, jamais l'ecriture.
assert "Ne jamais utiliser 8" in page
def test_valeurs_standards_exposees():
"""Les listes proposees remplacent la saisie libre : elles doivent exister."""
valeurs = create_app().test_client().get("/api/valeurs-standards").get_json()
assert "generic-active-host-custom" in valeurs["modeles_hote"]
assert "generic-active-service-custom" in valeurs["modeles_service"]
assert valeurs["versions_snmp"] == ["1", "2c", "3"]
assert "/usr/lib/centreon/plugins" in valeurs["repertoires_plugins"]
assert "Critique" in valeurs["criticites"]
def test_nom_affiche_et_baseline():
"""Le nom affiche est « Forge Centreon » ; le projet et les images restent « Enclume »."""
page = create_app().test_client().get("/").data.decode()
assert "Forge Centreon" in page
assert "Générateur de configuration pour Centreon avec CLAPI" in page
# La mention d'independance devient d'autant plus necessaire.
assert "Centreon SAS" in page