reconstruire-locataire : le nom de l'ecosysteme n'est plus demande deux fois
TENANT= le designe en toutes lettres ; le nom qu'exige raser en est derive par raser.nom_court (une seule derivation). raser seul garde son garde-fou. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a5a21ee4c5
commit
249d37d2c4
5 changed files with 35 additions and 17 deletions
|
|
@ -11,8 +11,12 @@ fois la voûte du locataire et l'accès au runner du site) :
|
|||
sauf `ARMER=oui`) → `monter` (`make monter-flotte` sur le runner du locataire, suivi toutes
|
||||
les 30 s) → `parefeu` (`--flotte`) → `bilan` (ce que chaque jeu d'état est devenu).
|
||||
|
||||
Le nom de l'écosystème s'écrit en toutes lettres (`INSTANCE=`), comme pour `raser`, qui
|
||||
n'a pas d'autre condition. Arrêt à la première étape en échec, avec la commande de reprise
|
||||
`TENANT=` désigne l'écosystème en toutes lettres ; le nom qu'exige `raser` en est DÉRIVÉ
|
||||
(`raser.nom_court`, une seule dérivation), pas redemandé. La première version exigeait aussi
|
||||
`INSTANCE=` — relevé par l'exploitant : « pourquoi cette cible a besoin de se faire dire
|
||||
"chezlepro" deux fois ? ». Le garde-fou de `raser` n'a de sens que pour `raser` seul, qui rase
|
||||
l'écosystème du lien `instance/` ; ici, rien d'implicite n'est à confirmer. `raser` n'a pas
|
||||
d'autre condition que sa confirmation. 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) :
|
||||
|
|
|
|||
12
Makefile
12
Makefile
|
|
@ -1451,16 +1451,16 @@ monter-flotte: _instance-requise ## Monte une flotte deja creee : flux, AC et DN
|
|||
# RECONSTRUIRE UN LOCATAIRE DE BOUT EN BOUT, DEPUIS LE POSTE (2026-09-30). Les deux
|
||||
# reconstructions du 2026-09-30 passaient par cinq endroits et des commandes tapees a la
|
||||
# main ; la sequence vit desormais dans `scripts/reconstruire_locataire.py` (voir son
|
||||
# en-tete). Le nom de l'ecosysteme s'ecrit en toutes lettres (`INSTANCE=`), comme pour
|
||||
# `raser`. L'armement marque une pause, sauf `ARMER=oui`. `DEPUIS=<etape>` reprend apres un
|
||||
# en-tete). `TENANT=` designe l'ecosysteme en toutes lettres : le nom qu'exige `raser` en est
|
||||
# derive, pas redemande. L'armement marque une pause, sauf `ARMER=oui`. `DEPUIS=<etape>` reprend apres un
|
||||
# arret. Le journal complet va dans `<locataire>/logs/`.
|
||||
.PHONY: reconstruire-locataire
|
||||
reconstruire-locataire: ## Rase et reconstruit un locataire, du site a la recette, etat remis — TENANT= INSTANCE= CONFIRMER=true
|
||||
@if [[ -z "$(TENANT)" || -z "$(INSTANCE)" ]]; then \
|
||||
printf '%s\n' 'Refus: TENANT=<OPS-X> et INSTANCE=<nom de l ecosysteme, en toutes lettres> requis.'; \
|
||||
reconstruire-locataire: ## Rase et reconstruit un locataire, du site a la recette, etat remis — TENANT=OPS-X CONFIRMER=true
|
||||
@if [[ -z "$(TENANT)" ]]; then \
|
||||
printf '%s\n' 'Refus: TENANT=<OPS-X> requis (le dossier du locataire, en toutes lettres).'; \
|
||||
exit 2; \
|
||||
fi
|
||||
python3 scripts/reconstruire_locataire.py --tenant "$(TENANT)" --instance "$(INSTANCE)" \
|
||||
python3 scripts/reconstruire_locataire.py --tenant "$(TENANT)" \
|
||||
$(if $(filter true,$(CONFIRMER)),--confirmer) $(if $(DEPUIS),--depuis "$(DEPUIS)") \
|
||||
$(if $(filter oui,$(ARMER)),--armer)
|
||||
|
||||
|
|
|
|||
|
|
@ -480,7 +480,7 @@ runbooks:
|
|||
nature: destructif
|
||||
portee: poste
|
||||
duree: "long"
|
||||
variables: [TENANT, INSTANCE, DEPUIS, ARMER]
|
||||
variables: [TENANT, DEPUIS, ARMER]
|
||||
fixes: {CONFIRMER: "true"}
|
||||
pourquoi: >-
|
||||
TOUT, d'une commande, depuis le poste : sauvegarder, raser et recreer (runner du
|
||||
|
|
|
|||
|
|
@ -41,14 +41,22 @@ from inventory_rules import instance_courante # noqa: E402
|
|||
RACINE = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
def nom_court(dossier: Path) -> str:
|
||||
"""Le nom qu'il faut TAPER pour raser cet ecosysteme : `OPS-Technolibre` -> `technolibre`.
|
||||
|
||||
Une seule derivation : `reconstruire_locataire.py` l'importe au lieu de redemander le
|
||||
nom (2026-09-30) — la ou l'ecosysteme est deja designe explicitement par `TENANT=`.
|
||||
"""
|
||||
return dossier.name.removeprefix("OPS-").lower()
|
||||
|
||||
|
||||
def instance_active() -> tuple[Path, str]:
|
||||
"""Dossier de l'instance montee, et son nom court (celui qu'il faudra taper)."""
|
||||
base = instance_courante()
|
||||
if not base.exists():
|
||||
raise SystemExit("Aucune instance montee : rien a raser.")
|
||||
reel = base.resolve()
|
||||
nom = reel.name.removeprefix("OPS-").lower()
|
||||
return reel, nom
|
||||
return reel, nom_court(reel)
|
||||
|
||||
|
||||
def plan_derive(base: Path) -> list[tuple[str, int]]:
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pas les secrets du locataire, et c'est voulu : l'armement reste un geste du post
|
|||
LES ETAPES, dans l'ordre (`--depuis` reprend a l'une d'elles apres un arret) :
|
||||
|
||||
sauvegarder poste deposer l'etat de chaque noeud MAINTENANT (sinon on perd la journee)
|
||||
raser runner du site detruire les VM — le nom de l'ecosysteme s'ecrit en toutes lettres
|
||||
raser runner du site detruire les VM
|
||||
creer runner du site recreer les VM depuis le gabarit
|
||||
inseminer runner du site amorcer le runner du locataire (socle + moteur, sans secret)
|
||||
armer poste lui remettre sa voute et sa cle — pause, sauf `--armer`
|
||||
|
|
@ -26,6 +26,12 @@ LES ETAPES, dans l'ordre (`--depuis` reprend a l'une d'elles apres un arret) :
|
|||
|
||||
La premiere etape en echec arrete tout, et le dit. `raser` n'a pas d'autre condition que sa
|
||||
confirmation (decision de l'exploitant) : c'est la PROCEDURE qui sauvegarde avant.
|
||||
|
||||
LE NOM N'EST DEMANDE QU'UNE FOIS. `raser`, seul, exige qu'on tape le nom de l'ecosysteme
|
||||
parce qu'il rase celui du lien `instance/`, qui peut pointer n'importe ou. Ici l'ecosysteme
|
||||
est deja designe en toutes lettres par `TENANT=` : le nom que `raser` attend en est DERIVE
|
||||
(`raser.nom_court`), pas redemande. Une premiere version l'exigeait deux fois — une
|
||||
occasion de se tromper de plus, et aucune protection de plus (2026-09-30).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
|
|
@ -42,6 +48,7 @@ sys.path.insert(0, str(RACINE / "scripts"))
|
|||
|
||||
from devis_reseau import DOSSIER_INSTANCES # noqa: E402
|
||||
from eprouver_parefeu import _ip_par_hote # noqa: E402
|
||||
from raser import nom_court # noqa: E402
|
||||
|
||||
ETAPES = ["sauvegarder", "raser", "creer", "inseminer", "armer", "monter", "parefeu", "bilan"]
|
||||
SSH = ["ssh", "-o", "BatchMode=yes", "-o", "ConnectTimeout=15", "-o", "ServerAliveInterval=30",
|
||||
|
|
@ -134,8 +141,6 @@ def main() -> int:
|
|||
global JOURNAL
|
||||
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
||||
ap.add_argument("--tenant", required=True, help="dossier du locataire, ex. OPS-Technolibre")
|
||||
ap.add_argument("--instance", required=True,
|
||||
help="nom de l'ecosysteme, ecrit en toutes lettres (celui qu'exige `raser`)")
|
||||
ap.add_argument("--confirmer", action="store_true", help="sans lui, rien n'est fait")
|
||||
ap.add_argument("--depuis", choices=ETAPES, default=ETAPES[0], help="reprendre a cette etape")
|
||||
ap.add_argument("--armer", action="store_true",
|
||||
|
|
@ -148,6 +153,7 @@ def main() -> int:
|
|||
|
||||
T = args.tenant
|
||||
dossier = DOSSIER_INSTANCES / T
|
||||
ecosysteme = nom_court(dossier)
|
||||
inv = dossier / "inventories" / "principal" / "hosts.yml"
|
||||
if not inv.is_file():
|
||||
print(f"REFUS : {inv} introuvable.")
|
||||
|
|
@ -155,7 +161,7 @@ def main() -> int:
|
|||
runner_nom, runner_ip = runner_du_locataire(T)
|
||||
a_faire = ETAPES[ETAPES.index(args.depuis):]
|
||||
if not args.confirmer:
|
||||
print(f"Refus : RECONSTRUCTION de {T} ({args.instance}) — ses VM seront DETRUITES puis refaites.")
|
||||
print(f"Refus : RECONSTRUCTION de {T} ({ecosysteme}) — ses VM seront DETRUITES puis refaites.")
|
||||
print(f" etapes : {' -> '.join(a_faire)} ; runner du locataire : {runner_nom} ({runner_ip})")
|
||||
print(" Relancer avec CONFIRMER=true.")
|
||||
return 2
|
||||
|
|
@ -172,7 +178,7 @@ def main() -> int:
|
|||
def arret(nom: str, rc: int, quoi: str = "") -> int:
|
||||
dire(f"\nARRET a l'etape « {nom} » (code {rc}){' — ' + quoi if quoi else ''}.")
|
||||
dire(f"Reprendre, une fois la cause comprise : make reconstruire-locataire TENANT={T} "
|
||||
f"INSTANCE={args.instance} CONFIRMER=true DEPUIS={nom}")
|
||||
f"CONFIRMER=true DEPUIS={nom}")
|
||||
return rc or 1
|
||||
|
||||
site_tire = False
|
||||
|
|
@ -189,7 +195,7 @@ def main() -> int:
|
|||
filtre=("fatal:", "PLAY RECAP", "failed="))
|
||||
elif nom == "raser":
|
||||
rc = sur_site(args, f"SETOPS_INSTANCE={args.racine_runner}/{T} make raser CONFIRMER=true "
|
||||
f"INSTANCE={shlex.quote(args.instance)}",
|
||||
f"INSTANCE={shlex.quote(ecosysteme)}",
|
||||
filtre=("detruite", "VM detruites", "Refus", "REFUS", "ERREUR"))
|
||||
elif nom == "creer":
|
||||
rc = sur_site(args, f"SETOPS_INSTANCE={args.racine_runner}/{T} make flotte-creer "
|
||||
|
|
|
|||
Loading…
Reference in a new issue