Skip to content

fix(infra/ansible): un playbook en échec dit enfin QUELLE tâche, et pourquoi - #310

Merged
stephrobert merged 3 commits into
mainfrom
fix/ansible-dire-la-cause
Oct 12, 2026
Merged

stephrobert merged 3 commits into
mainfrom
fix/ansible-dire-la-cause

Conversation

@stephrobert

Copy link
Copy Markdown
Owner

Summary

Deux utilisateurs externes ont ouvert
kubernetes#94
le 10 octobre avec ceci, et rien d'autre :

✘ setup.yaml a échoué pour cka-troubleshoot-apiserver sur la target « cp »
  (rc=4, status=failed). Stats : {}

Un rapport exemplaire, deux environnements différents, et deux jours sans la
moindre piste
— pour eux comme pour nous.

Ce que dsoxlab savait, et jetait

runner_on_failed ansible-runner envoie le nom de la tâche, l'hôte et le message
PlaybookResult.stdout la sortie complète était déjà capturée
runtimes/vm.py ne levait qu'avec rc, status et stats
finally supprimait le répertoire d'artefacts

C'est le défaut corrigé dans l'appliance en 0.3.4 — la cause existait, dans un
endroit que personne ne regarde — mais cette fois dans le moteur, donc sur
tous les labs vm de tous les catalogues.

Trois niveaux, parce qu'aucun n'est toujours disponible

  1. les tâches qu'ansible déclare en échec : nom, hôte, message ;
  2. à défaut, les dernières lignes parlantes de sa sortie — c'est le cas de
    Stats: {}
    , où aucun événement n'est émis et où s'en tenir au premier
    niveau reproduirait le défaut d'origine ;
  3. et toujours, une trace conservée sous ~/.local/state/dsoxlab/ansible/,
    horodatée pour qu'un second essai n'écrase pas le premier.

Le collecteur tourne avant le callback de l'appelant et dans son propre
try : perdre le diagnostic parce que la barre de progression a planté serait
le défaut qu'on corrige.

Ce que ça donne, dès le premier essai

✘ setup.yaml a échoué pour cka-troubleshoot-apiserver … (rc=2, status=failed).
  ✘ Installer le CNI, Calico — k8s-cp.lab (échec) : The command exited with a
    non-zero return code.
  Sortie complète d'ansible : ~/.local/state/dsoxlab/ansible/…log

Et la trace donnait la cause en une ligne : dial tcp 10.10.50.11:6443: connect: connection refused.

L'enquête : ce qui est écarté, par la mesure

Le cluster kubeadm a été monté ici et le lab de l'issue joué en entier,
deux fois :

ansible-core 2.19.14, cluster neuf    réussit de bout en bout
ansible-core 2.21.5,  cluster neuf    réussit de bout en bout
les 5 fichiers du socle               se parsent dans les deux versions
include_tasks ../../shared/           résout (éprouvé via run_playbook)

Ni le catalogue, ni le motif d'inclusion, ni la version d'ansible — alors que
pyproject.toml déclare ansible-core>=2.16 sans plafond, ce qui en faisait
la suspecte n° 1. La cause de #94 reste inconnue, et c'est ce correctif
qui permettra de la nommer : sans lui, la demande adressée aux rapporteurs
n'aurait aucun moyen d'aboutir.

Un défaut trouvé en chemin, hors périmètre de cette PR

cka-troubleshoot-apiserver casse l'API server exprès — c'est son sujet —
et un second dsoxlab run échoue sur l'héritage du premier, le socle supposant
un cluster sain. Pour un apprenant qui recommence, c'est un mur. À traiter
séparément, côté catalogue.

Deux garde-fous du dépôt m'ont repris, et ils avaient raison

test_journal_en_anglais a attrapé un message de journal écrit en français.
Et le test de cette PR a montré que TacheEnEchec.resume() rendait une ligne
s'arrêtant sur deux-points quand le message est vide : le repli vivait chez
l'appelant, pas dans la méthode.

Type of change

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • Chore / tooling
  • Security / supply chain

Checklist

Always

  • ruff check src/dsoxlab tests tests_e2e fuzz scripts — propre
  • mypy src/dsoxlab — strict, 88 fichiers
  • pytest — 1317 passed, dont 12 nouveaux sur le diagnostic
  • pytest tests_e2e — joué en CI sur cette PR
  • Moteur domain-agnostic — aucun nom de domaine ajouté
  • Aucun chemin personnel ni hôte en dur
  • Éprouvé sur un dépôt fournisseur en provisionnant pour de vrai :
    cluster kubeadm monté, lab joué de bout en bout, deux versions d'ansible

When behavior changes

  • CHANGELOG.md et CHANGELOG.fr.md
  • Version portée à 0.3.5, uv lock rejoué

When a command or option is added, removed or changed

N/A — aucune commande ni option ne change. Trois clés i18n ajoutées des deux
côtés pour le nouveau message, et le message de journal reste en anglais.

When .github/workflows/ is touched

N/A.

When the declarative contract changes

N/A.

Related issues

Donne les moyens de diagnostiquer
stephrobert/kubernetes-dsoxlab-training#94 — ne la ferme pas.

🤖 Generated with Claude Code

stephrobert and others added 3 commits October 12, 2026 08:27
…ourquoi

Deux utilisateurs externes ont ouvert kubernetes#94 le 10 octobre avec ceci,
et rien d'autre :

    ✘ setup.yaml a échoué pour cka-troubleshoot-apiserver sur la target « cp »
      (rc=4, status=failed). Stats : {}

Un rapport exemplaire, deux environnements, et deux jours sans la moindre
piste — pour eux comme pour nous.

CE QUE DSOXLAB SAVAIT ET JETAIT

ansible-runner lui envoie un événement `runner_on_failed` qui porte le nom de
la tâche, l'hôte et le message. `PlaybookResult` capturait déjà la sortie
complète dans son champ `stdout`. Les deux partaient à la poubelle :
`runtimes/vm.py` ne levait qu'avec rc, status et stats, et le `finally`
supprimait le répertoire d'artefacts.

C'est exactement le défaut corrigé dans l'appliance en 0.3.4 — la cause
existait, dans un endroit que personne ne regarde — mais cette fois dans le
moteur, et il touche tous les labs `vm` de tous les catalogues.

TROIS NIVEAUX, PARCE QU'AUCUN N'EST TOUJOURS DISPONIBLE

1. les tâches qu'ansible déclare en échec : nom, hôte, message ;
2. à défaut, les dernières lignes parlantes de sa sortie. C'est le cas de
   `Stats: {}` — aucun événement émis, donc rien à afficher si l'on s'en
   tenait au premier niveau, ce qui est précisément le défaut d'origine ;
3. et toujours, le chemin d'une trace conservée sous
   `~/.local/state/dsoxlab/ansible/`, horodatée pour qu'un second essai
   n'écrase pas le premier — c'est souvent la comparaison des deux qui parle.

Le collecteur tourne AVANT le callback de l'appelant et dans son propre
`try` : perdre le diagnostic parce que la barre de progression a planté serait
le défaut qu'on corrige.

CE QUE LE CORRECTIF A DONNÉ DÈS LE PREMIER ESSAI

    ✘ setup.yaml a échoué pour cka-troubleshoot-apiserver … (rc=2)
      ✘ Installer le CNI, Calico — k8s-cp.lab (échec) : The command exited
        with a non-zero return code.
      Sortie complète d'ansible : ~/.local/state/dsoxlab/ansible/…log

et la trace donnait la cause en une ligne : `dial tcp 10.10.50.11:6443:
connect: connection refused`.

CE QUE L'ENQUÊTE A ÉCARTÉ, PAR LA MESURE

Le cluster kubeadm a été monté ici, et le lab de l'issue joué en entier :

  ansible-core 2.19.14, cluster neuf    réussit de bout en bout
  ansible-core 2.21.5,  cluster neuf    réussit de bout en bout
  les 5 fichiers du socle               se parsent dans les deux versions
  include_tasks ../../shared/           résout (éprouvé via run_playbook)

Donc ni le catalogue, ni le motif d'inclusion, ni la version d'ansible. La
cause de #94 est dans l'environnement des rapporteurs, et c'est maintenant ce
correctif qui permettra de la nommer.

DEUX GARDE-FOUS DU DÉPÔT M'ONT REPRIS, ET ILS AVAIENT RAISON

`test_journal_en_anglais` a attrapé un message de journal que j'avais écrit en
français. Et mon propre test a montré que `TacheEnEchec.resume()` rendait une
ligne s'arrêtant sur deux-points quand le message est vide : le repli vivait
chez l'appelant, pas dans la méthode.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Le diagnostic des playbooks en échec, publié pour que les deux rapporteurs de
kubernetes#94 puissent enfin nommer leur cause. Sans cette version, la demande
qu'on leur adresse n'a aucun moyen d'aboutir : leur 0.3.3 ne produit que
« rc=4, Stats : {} ».

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…portement

Il cherchait le mot « aucun », donc la traduction FRANÇAISE du repli. Il
passait sur ma machine, où le contexte du dépôt fixe la langue à `fr`, et
tombait sur les quatre versions de Python en CI, où la langue par défaut est
l'anglais et où le repli s'écrit « (no message) ».

L'invariant n'a jamais été le texte : c'est qu'une ligne ne s'arrête pas sur
deux-points, ce qui se lirait comme un bug d'affichage plutôt que comme un
module muet. C'est lui qui est testé maintenant.

Toute la suite est désormais jouée dans les deux langues — 1317 verts sous
`DSOXLAB_LANG=en` comme sous `DSOXLAB_LANG=fr`. C'est le contrôle qui manquait,
et que la CI faisait à ma place sans que j'y pense.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@stephrobert
stephrobert merged commit 2dffd98 into main Oct 12, 2026
21 checks passed
@stephrobert
stephrobert deleted the fix/ansible-dire-la-cause branch October 12, 2026 06:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant