site-deployer-tout : l orchestration existait, rien ne la lancait

playbooks/site.yml ordonne les couches pour n importe quelle instance. Mais
deployer-tout ne vise que l inventaire d un locataire, et le site n avait que
site-appliquer GROUPE=<un seul>.

Un hebergeur qu on ne peut remonter qu en enchainant onze groupes de memoire
n est pas reconstructible : il est reparable par quelqu un qui se souvient.

Et quatre gardes que --check rendait folles, toutes de la meme famille : une
garde qui compare contre ce qu une tache du meme play vient de produire n a rien
a dire tant que rien n a ete ecrit. Sept machines en echec sur un site sain, en
suivant le conseil du Makefile lui-meme.

Apres correction : 7/7, 0 echec, de 174 a 309 taches par machine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
This commit is contained in:
Daniel Allaire 2026-09-14 11:02:37 -04:00
parent 52b9d31a5d
commit 8eb482e0c6
6 changed files with 133 additions and 1 deletions

View file

@ -1,5 +1,43 @@
# CHANGELOG — Set-OPS
## 2026-09-14 (6) — Le site avait l'orchestration, pas le moyen de la lancer
`playbooks/site.yml` est genere par `orchestrer.py` et ordonne les couches pour
**n'importe quelle** instance — son en-tete le dit. Mais `deployer-tout` ne vise que
l'inventaire d'un LOCATAIRE, et le site n'avait que `site-appliquer GROUPE=<un seul>`.
Le site ne se deployait donc que **groupe par groupe, a la main**, dans un ordre qu'il
fallait se rappeler. Un hebergeur qu'on ne peut remonter qu'en enchainant onze groupes de
memoire n'est pas reconstructible : il est reparable par quelqu'un qui se souvient. C'est
nommement l'une des trois limites du jalon de reconstruction autonome — *« le SITE jamais
reconstruit »*.
`site-deployer-tout` comble le manque. Trois differences avec son equivalent locataire,
aucune cosmetique : l'inventaire est un **script** (un site se derive de son underlay, il
ne se fige pas dans un `hosts.yml`), la voute vit **a cote de la carte**
(`underlay.vault.yml`, hors depot), et le perimetre reste `hotes_actifs` — les
hyperviseurs et la frontiere sont dans l'inventaire mais ne se deploient pas.
### Quatre gardes que `--check` rendait folles
Le Makefile CONSEILLE l'essai a blanc — *« tester d'abord en idempotent »*. Suivre ce
conseil rendait **sept machines en echec** sur un site parfaitement sain. Quatre causes,
une seule famille : **une garde qui compare contre ce qu'une tache du meme play vient de
produire n'a rien a dire tant que rien n'a ete ecrit.**
| role | ce que `--check` cassait | remede |
|---|---|---|
| `hosts_statiques` | la lecture des deux fichiers etait sautee : `ne portent pas le meme nombre d'entrees ()` | `check_mode: false` sur la lecture |
| `hosts_statiques` | l'assertion comparait l'AVANT a l'APRES : `/etc/hosts=13 \| tmpl=2` | `not ansible_check_mode` sur l'assertion |
| `serveur_icinga` | le telechargement simule, l'installation cherchait un fichier absent | `check_mode: false` sur `get_url` |
| `serveur_ops` | la version du controleur non lue : `Le controleur tourne Python ` | `check_mode: false` sur la lecture |
**Les parentheses vides et l'espace apres « Python » sont tout le diagnostic** : il n'y
avait rien a comparer. Un essai a blanc qui ment est pire qu'aucun — il apprend a ne plus
le lancer.
Apres correction : **7/7, 0 echec**, de 174 a 309 taches par machine.
## 2026-09-14 (5) — Le site ne savait pas se configurer lui-meme
Parti pour eprouver une sonde, arrive sur un defaut structurel : **le runner du SITE ne

View file

@ -1054,6 +1054,45 @@ site-appliquer: ## Applique un role aux machines du site — GROUPE=<serveur_ops
ansible-playbook -i scripts/site_inventaire.py "playbooks/groupes/$(GROUPE).yml" \
"$${supp[@]}" $(ARGS)
.PHONY: site-deployer-tout
site-deployer-tout: ansible-runtime ## Deploie TOUT le site dans l'ordre des couches — CONFIRMER=true
@# LE SITE AVAIT L'ORCHESTRATION, PAS LE MOYEN DE LA LANCER (2026-09-14).
@#
@# `playbooks/site.yml` est genere par `orchestrer.py` et ordonne les couches pour
@# N'IMPORTE QUELLE instance — son en-tete le dit : « le meme fichier sert toute
@# instance ». Mais `deployer-tout` ne vise que l'inventaire d'un LOCATAIRE, et le
@# site n'avait que `site-appliquer GROUPE=<un seul>`.
@#
@# CE QUE CA COUTAIT : le site ne se DEPLOYAIT que groupe par groupe, a la main, dans
@# un ordre qu'il fallait se rappeler. Un hebergeur qu'on ne peut remonter qu'en
@# enchainant onze groupes de memoire n'est pas reconstructible — il est reparable par
@# quelqu'un qui se souvient. C'est nommement l'une des trois limites du jalon de
@# reconstruction autonome : « le SITE jamais reconstruit ».
@#
@# TROIS DIFFERENCES AVEC `deployer-tout`, ET AUCUNE N'EST COSMETIQUE :
@#
@# l'inventaire est un SCRIPT (`site_inventaire.py`), pas un fichier : un site se
@# derive de son underlay, il ne se fige pas dans un `hosts.yml`.
@# la voute vit a cote de la carte (`underlay.vault.yml`), hors depot, et non
@# dans `group_vars/all`. Sans le `-e @`, les roles partages echouent
@# sur une assertion qui ne dit pas qu'il manque un FICHIER.
@# le perimetre est `hotes_actifs`, comme chez un locataire — les hyperviseurs et
@# la frontiere sont dans l'inventaire mais ne se deploient pas.
@set -e; \
if [[ "$(CONFIRMER)" != "true" ]]; then \
printf '%s\n' 'Refus: deploiement ORCHESTRE de TOUT le site (action impactante).'; \
printf '%s\n' 'Relancer avec CONFIRMER=true. Astuce: tester d abord en idempotent avec MODE_CHECK=1.'; \
exit 2; \
fi; \
python3 scripts/verifier_genome_a_jour.py || exit 2; \
python3 scripts/orchestrer.py verifier; \
python3 scripts/orchestrer.py ecrire; \
voute="$$(dirname "$$(readlink -f underlay.yml)")/underlay.vault.yml"; \
supp=(); [[ -f "$$voute" ]] && supp+=( -e "@$$voute" ); \
mode="$$([[ -n "$(MODE_CHECK)" ]] && printf -- '--check --diff' || true)"; \
ansible-playbook -i scripts/site_inventaire.py playbooks/site.yml \
--limit "$(GROUPE_HOTES_ACTIFS)" "$${supp[@]}" $$mode $(ARGS)
# --- LE GENOME REMONTE SUR LA FORGE DU SITE -----------------------------------
#
# La forge du genome vit DANS le site, sur un reseau que le poste de l'exploitant ne route

View file

@ -43,7 +43,7 @@
| P28 | Pools Proxmox : un par tenant, sans collision | AFF-110 | ✅ OK | CONFORME : 5 pool(s) Proxmox, 44 VM placee(s), aucun nom ni VMID en collision. |
| P29 | Authentification : chaque role declare sa position | AFF-111 | ✅ OK | 33 role(s) serveur declares (interne-sans-auth 2, ldap-direct 2, sans-auth-humaine 22, socle-identite 2, web-sso 5) ; 2 lacune(s) nommee(s) : serveur_loki, serv |
| P30 | SDN EVPN : zones, VNets et sous-reseaux derives | AFF-112 | ✅ OK | CONFORME : SDN EVPN, 3 zone(s), 15 VNet(s), 15 sous-reseau(x), aucune collision. |
| P31 | Documentation : tout ce que le depot FAIT est nomme | — | ✅ OK | 65 scripts expliques et atteignables, 121 cibles make documentees, 68 roles avec README. |
| P31 | Documentation : tout ce que le depot FAIT est nomme | — | ✅ OK | 65 scripts expliques et atteignables, 122 cibles make documentees, 68 roles avec README. |
| P32 | Intrants exiges par les roles : tous fournis | — | ✅ OK | CONFORME : 38 exigence(s) de role, toutes satisfaites (149 cle(s) declaree(s) par l'instance). |
| P33 | Aucune collision de port entre roles co-localises | — | ✅ OK | CONFORME : 34 revendication(s) de port, aucune collision entre roles co-localises (36 groupes). |
| P34 | Chaque document declare son lecteur | — | ✅ OK | 45 document(s) declarent leur lecteur (40 genere(s) exempte(s)). |

View file

@ -196,6 +196,21 @@
executable: /bin/bash
register: hosts_statiques_accord
changed_when: false
# LIRE N'EST PAS CHANGER, ET `--check` NE DOIT PAS RENDRE LA GARDE FOLLE (2026-09-14).
#
# Sans `check_mode: false`, cette commande est SAUTEE en mode idempotent. La garde qui
# suit compare alors du VIDE et refuse, sur les sept machines a la fois :
#
# ne portent pas le meme nombre d'entrees ()
#
# Les parentheses vides sont tout le diagnostic — il n'y avait aucun compte a comparer.
# Le Makefile CONSEILLE pourtant ce mode (« tester d abord en idempotent »), donc un
# essai a blanc rendait sept faux echecs a qui suivait le conseil.
#
# Cette tache ne fait que LIRE deux fichiers et compter des lignes. La faire tourner en
# `--check` ne modifie rien et rend au mode idempotent ce qu'il promet : dire ce qui
# changerait, pas inventer des pannes.
check_mode: false
when:
- hosts_statiques_actif | bool
- ansible_facts.os_family | default('') == 'Debian'
@ -229,3 +244,17 @@
# divergence la ou il n'y a plus qu'un seul fichier. Une garde qui survit a ce qu'elle
# gardait ne mesure plus rien : elle invente.
- hosts_statiques_gabarits_cloud_init.stat.isdir | default(false)
# NI EN MODE IDEMPOTENT, POUR LA MEME RAISON (2026-09-14). Cette garde compare l'etat
# que la tache « Poser le plancher dans le gabarit maitre » vient d'etablir vingt
# lignes plus haut. En `--check`, cette ecriture est SIMULEE : le gabarit sur disque
# porte encore l'etat d'AVANT, et la garde compare donc l'avant a l'apres.
#
# /etc/hosts=13 | /etc/cloud/templates/hosts.debian.tmpl=2
#
# Sept machines en echec sur un essai a blanc, alors que le deploiement reel passe.
# Le Makefile CONSEILLE ce mode — « tester d abord en idempotent » — donc suivre le
# conseil fabriquait sept fausses pannes.
#
# Une assertion qui porte sur une post-condition de son propre play n'a rien a dire
# tant que ce play n'a rien ecrit.
- not ansible_check_mode

View file

@ -37,6 +37,22 @@
url: "{{ serveur_icinga_keyring_url }}"
dest: "/tmp/icinga-archive-keyring.deb"
mode: "0644"
# RECUPERER N'EST PAS INSTALLER, ET `--check` CASSAIT LA PAIRE (2026-09-14).
#
# Sans `check_mode: false`, ce telechargement est SIMULE en mode idempotent — et la
# tache qui suit cherche alors un fichier qui n'existe pas :
#
# Unable to install package: E:Could not open file
# /tmp/icinga-archive-keyring.deb - open (2: No such file or directory)
#
# Un essai a blanc rendait donc un echec sur la machine de supervision, alors que le
# deploiement reel passe. Le Makefile conseille ce mode : suivre le conseil fabriquait
# une fausse panne, et c'est la troisieme de cette famille dans le meme essai.
#
# Ce que ce `check_mode: false` autorise reellement : deposer un fichier dans `/tmp`.
# Rien du systeme gere n'en depend, et c'est ce qui permet a l'installation d'ETRE
# evaluee — donc au mode idempotent de dire ce qu'il promet.
check_mode: false
# LA CLE PASSE PAR LE CACHE, ELLE AUSSI (mesure du 2026-09-10).
#
# `get_url` ignore la configuration d'apt : le mandataire pose dans

View file

@ -122,6 +122,16 @@
become: false
run_once: true
changed_when: false
# LIRE UNE VERSION N'EST PAS CHANGER, ET `--check` RENDAIT LA GARDE MUETTE (2026-09-14).
#
# Sans `check_mode: false`, cette commande est sautee en mode idempotent : la garde qui
# suit compare alors contre du VIDE et refuse.
#
# Le controleur tourne Python et site-ops-01 tourne Python 3.13
#
# L'espace apres « Python » est tout le diagnostic — il n'y avait rien a comparer. Un
# essai a blanc rendait donc un echec sur le runner, alors que le deploiement reel passe.
check_mode: false
register: serveur_ops_python_controleur
- name: Exiger que le controleur et la cible partagent leur version de Python