Set-OPS-Public/scripts/tests/test_appels_locataire.py

88 lines
3.7 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
"""`make creer-vm TENANT=` lance-t-il le MEME clonage que l'ancien chemin, l'instance montee ?
Compare, machine par machine, la ligne `ansible-playbook` qui part reellement — un faux
`ansible-playbook` en tete du PATH la consigne au lieu de cloner. Trois appels par machine :
- l'ancien chemin : `SETOPS_INSTANCE=<locataire> make creer-vm HOTE=h` ;
- le runner du SITE : aucune instance, `TENANT=<locataire>` ;
- le POSTE : l'AUTRE locataire monte, `TENANT=<locataire>`.
POURQUOI (2026-10-05, materialisation M2). Comparer les parametres de clonage ne suffisait pas :
le sous-make `cloner-vm` nommait encore le pool par l'instance MONTEE (`--pool-actif`). Sur le
site, la VM serait nee hors de tout pool ; sur le poste, dans le pool de l'autre locataire. Seule
la ligne finale montre tout ce qui part, y compris ce qu'aucune liste de parametres ne nomme.
Les dossiers sont designes par des liens SANS ESPACE : le Makefile prend `SETOPS_INSTANCE`
dans des `$(wildcard …)`, qu'une espace coupe en deux (le runner du site vit sous `/opt/setops`).
"""
from __future__ import annotations
import os
import subprocess
import sys
import tempfile
from pathlib import Path
RACINE = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(RACINE / "scripts"))
import contexte as C # noqa: E402
FAUX = "#!/bin/bash\nfor a in \"$@\"; do printf '%s\\n' \"$a\"; done >> \"$CAPTURE\"\n"
def appel(tmp: Path, instance: str, hote: str, tenant: str | None) -> tuple[int, str]:
capture = tmp / "capture"
capture.write_text("")
env = dict(os.environ, CAPTURE=str(capture), SETOPS_INSTANCE=instance,
PATH=f"{tmp / 'faux'}:{os.environ['PATH']}")
env.pop("SETOPS_INVENTAIRE", None)
cmd = ["make", "--no-print-directory", "creer-vm", "ATTENDRE=false", f"HOTE={hote}"]
if tenant:
cmd.append(f"TENANT={tenant}")
r = subprocess.run(cmd, cwd=RACINE, env=env, capture_output=True, text=True,
stdin=subprocess.DEVNULL)
return r.returncode, capture.read_text()
def main() -> int:
couples = C.couples_hebergeur()
locataires = sorted({l for _s, l in couples}, key=lambda l: l.nom)
if len(locataires) < 2:
print("SAUTE il faut deux locataires freres (le cas du poste monte l'autre)")
return 0
echecs, n = [], 0
with tempfile.TemporaryDirectory() as t:
tmp = Path(t)
(tmp / "faux").mkdir()
faux = tmp / "faux" / "ansible-playbook"
faux.write_text(FAUX)
faux.chmod(0o755)
liens = {}
for l in locataires:
liens[l.nom] = tmp / l.nom
liens[l.nom].symlink_to(l.depot.resolve())
for l in locataires:
autre = next(x for x in locataires if x.nom != l.nom)
for h in C.hotes_actifs(l.face_publiee() or {}):
rc0, ancien = appel(tmp, str(liens[l.nom]), h, None)
rc1, site = appel(tmp, "/nulle/part", h, l.nom)
rc2, poste = appel(tmp, str(liens[autre.nom]), h, l.nom)
n += 1
if rc0 or not ancien:
echecs.append(f"{l.nom} {h} : l'ancien chemin n'a rien lance (code {rc0})")
elif (rc1, site) != (0, ancien):
echecs.append(f"{l.nom} {h} : le site lancerait autre chose (code {rc1})")
elif (rc2, poste) != (0, ancien):
echecs.append(f"{l.nom} {h} : le poste ({autre.nom} monte) lancerait autre chose")
for e in echecs:
print("ECHEC " + e)
if echecs:
return 1
print(f"OK {n} machine(s) : site et poste lancent le clonage de l'ancien chemin, a l'argument pres")
return 0
if __name__ == "__main__":
sys.exit(main())