reconstruire-locataire : le runner du site tire ses trois depots avant toute etape

Moteur, plan du locataire, depot du site (deduit d'underlay.yml), en
avance rapide seulement ; refus devant une modification locale. Vaut
aussi pour une reprise DEPUIS=creer ou inseminer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-09-30 15:35:23 -04:00
parent 5a6d0f28f6
commit a5a21ee4c5
2 changed files with 39 additions and 2 deletions

View file

@ -15,6 +15,12 @@ Le nom de l'écosystème s'écrit en toutes lettres (`INSTANCE=`), comme pour `r
n'a pas d'autre condition. Arrêt à la première étape en échec, avec la commande de reprise
(`DEPUIS=<étape>`) ; journal complet dans `<locataire>/logs/`.
**Le runner du site se met à jour avant sa première étape** (quelle que soit la reprise) :
il tire le moteur, le plan du locataire et SON dépôt de site — déduit du lien `underlay.yml`,
pas nommé —, en avance rapide seulement, et refuse devant une modification locale (éprouvé :
une ligne ajoutée au README du site → REFUS, rc=1 ; fichier remis). Avant, seul `raser`
tirait, deux dépôts sur trois, et une reprise `DEPUIS=creer` ne tirait rien.
**Éprouvé sur Technolibre de `armer` à `bilan`** (les étapes non destructives) : 26 min,
0 échec — armement, flotte montée et recettée, pare-feu 13/13 sans flux perdu, bilan.
Un défaut de forme corrigé : chaque relevé de suivi recopiait tout le journal distant ; seul

View file

@ -83,6 +83,32 @@ def sur_site(args, commande: str, filtre: tuple[str, ...] = ()) -> int:
"sudo -u setops bash -lc " + shlex.quote(distante)], filtre=filtre)
def site_a_jour(args, tenant: str) -> int:
"""Le runner du SITE tire les trois depots qu'il va utiliser, AVANT sa premiere etape.
Le moteur (Set-OPS-public), le plan du locataire, et le depot du SITE — deduit du lien
`underlay.yml`, pas nomme : un autre site s'appelle autrement. Jusqu'au 2026-09-30 seul
`raser` tirait, et seulement les deux premiers : une reprise `DEPUIS=creer` partait de
ce que le runner avait sous la main, et `flotte-creer` lisait un plan du site jamais tire.
AVANCE RAPIDE SEULEMENT, et refus devant une modification locale : un runner n'edite
pas ce qu'il tire. S'il porte un ecart, c'est a comprendre, pas a ecraser.
"""
r = args.racine_runner
commande = (
'site=$(dirname "$(readlink -f underlay.yml)"); '
f'for d in {r}/Set-OPS-public {r}/{tenant} "$site"; do '
' git -C "$d" rev-parse --git-dir >/dev/null 2>&1 '
' || { echo "REFUS : $d n est pas un depot git"; exit 1; }; '
' if [ -n "$(git -C "$d" status --porcelain --untracked-files=no)" ]; then '
' echo "REFUS : modification locale dans $d"; exit 1; fi; '
' git -C "$d" pull -q --ff-only '
' || { echo "REFUS : $d ne se met pas a jour en avance rapide"; exit 1; }; '
' echo "a jour : $(basename "$d") $(git -C "$d" rev-parse --short HEAD)"; '
'done')
return sur_site(args, commande, filtre=("a jour :", "REFUS"))
def sur_locataire(ip: str, commande: str, journaliser: bool = True) -> tuple[int, str]:
distante = "sudo -u setops bash -lc " + shlex.quote(commande)
r = subprocess.run(SSH_NEUF + [f"ansible@{ip}", distante], capture_output=True, text=True,
@ -149,15 +175,20 @@ def main() -> int:
f"INSTANCE={args.instance} CONFIRMER=true DEPUIS={nom}")
return rc or 1
site_tire = False
for nom in a_faire:
etape(nom)
if nom in ("raser", "creer", "inseminer") and not site_tire:
rc = site_a_jour(args, T)
if rc != 0:
return arret(nom, rc, "le runner du site n'a pas pu se mettre a jour")
site_tire = True
if nom == "sauvegarder":
rc = lancer(["ansible-playbook", "-i", str(inv), "playbooks/backup/restauration.yml",
"-e", "restauration_action=sauvegarder"], env=env,
filtre=("fatal:", "PLAY RECAP", "failed="))
elif nom == "raser":
rc = sur_site(args, f"git pull -q --ff-only && git -C {args.racine_runner}/{T} pull -q --ff-only "
f"&& SETOPS_INSTANCE={args.racine_runner}/{T} make raser CONFIRMER=true "
rc = sur_site(args, f"SETOPS_INSTANCE={args.racine_runner}/{T} make raser CONFIRMER=true "
f"INSTANCE={shlex.quote(args.instance)}",
filtre=("detruite", "VM detruites", "Refus", "REFUS", "ERREUR"))
elif nom == "creer":