
Ce guide vous fait écrire un rôle Ansible users en TDD complet — chaque feature commence par un test qui échoue, puis le code minimal pour le faire passer, puis un refactor. Le rôle créera des utilisateurs Linux avec shell custom et appartenance à des groupes.
À la fin, vous aurez expérimenté le cycle red-green-refactor sur Ansible et compris pourquoi cette discipline change votre pratique au long terme.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Écrire
verify.ymlAVANTtasks/main.yml(TDD pur). - Voir 3 cycles red-green-refactor consécutifs.
- Implémenter le rôle
usersqui supporteshell:,groups:, default fallback. - Refactorer sans peur grâce à la couverture de tests.
- Combiner avec
argument_specs.ymlpour valider les entrées.
Prérequis
Section intitulée « Prérequis »- Avoir suivi Introduction TDD Molecule et Installer Molecule.
- Podman fonctionnel (
podman run --rm hello-world).
Spécification du rôle users à développer
Section intitulée « Spécification du rôle users à développer »Le rôle doit :
- Créer une liste d’utilisateurs Linux (variable
users_to_create). - Chaque utilisateur a optionnellement un
shell:(default =/bin/bash). - Chaque utilisateur peut appartenir à des
groups:(liste). - Si pas de shell explicite, fallback sur
users_default_shell.
Étape 0 — Setup
Section intitulée « Étape 0 — Setup »mkdir -p roles/userscd roles/usersansible-galaxy role init . --offlinemolecule init scenarioCycle 1 — Créer les utilisateurs (RED → GREEN → REFACTOR)
Section intitulée « Cycle 1 — Créer les utilisateurs (RED → GREEN → REFACTOR) »1.1 Test rouge — verify.yml
Section intitulée « 1.1 Test rouge — verify.yml »---- name: Verify hosts: all become: true
tasks: - name: Vérifier que alice existe ansible.builtin.user: name: alice state: present check_mode: true register: alice_check failed_when: alice_check is changed
- name: Vérifier le shell d'alice ansible.builtin.command: getent passwd alice register: alice_passwd changed_when: false
- name: Assertion shell d'alice = /bin/zsh ansible.builtin.assert: that: - "'/bin/zsh' in alice_passwd.stdout" fail_msg: "alice doit avoir /bin/zsh"Le test décrit : « alice doit exister et avoir /bin/zsh ». Ce test échoue car le rôle est vide.
1.2 Le converge
Section intitulée « 1.2 Le converge »---- name: Converge hosts: all become: true
vars: users_to_create: - name: alice shell: /bin/zsh groups: - wheel - name: bob - name: carol
roles: - role: users1.3 Confirmer le rouge
Section intitulée « 1.3 Confirmer le rouge »molecule converge # n'arrive pas — pas de tasks à jouermolecule verify # ROUGE : "alice doit exister"1.4 Code minimal (GREEN)
Section intitulée « 1.4 Code minimal (GREEN) »# tasks/main.yml — minimum vital pour passer le test 1---- name: Créer les utilisateurs ansible.builtin.user: name: "{{ item.name }}" state: present loop: "{{ users_to_create }}"molecule converge # crée alice (et bob, carol)molecule verify # ROUGE — alice existe mais pas de shell1.5 Code suffisant pour passer le test
Section intitulée « 1.5 Code suffisant pour passer le test »- name: Créer les utilisateurs ansible.builtin.user: name: "{{ item.name }}" shell: "{{ item.shell | default('/bin/bash') }}" state: present loop: "{{ users_to_create }}"molecule converge # change le shell d'alicemolecule verify # VERTCycle 2 — Groupes secondaires (alice in wheel)
Section intitulée « Cycle 2 — Groupes secondaires (alice in wheel) »2.1 Ajouter le test rouge
Section intitulée « 2.1 Ajouter le test rouge »# verify.yml (suite)- name: Vérifier alice membre de wheel ansible.builtin.command: id alice register: alice_id changed_when: false
- name: Assertion alice in wheel ansible.builtin.assert: that: - "'wheel' in alice_id.stdout" fail_msg: "alice doit être dans wheel"molecule verify # ROUGE — alice n'est pas dans wheel2.2 Code pour passer
Section intitulée « 2.2 Code pour passer »- name: Créer les utilisateurs ansible.builtin.user: name: "{{ item.name }}" shell: "{{ item.shell | default('/bin/bash') }}" groups: "{{ item.groups | default([]) }}" append: true state: present loop: "{{ users_to_create }}"append: true est critique : sans lui, groups: [wheel] remplacerait les groupes existants de l’utilisateur. Avec append: true, on ajoute.
molecule converge # alice rejoint wheelmolecule verify # VERTCycle 3 — Default shell fallback
Section intitulée « Cycle 3 — Default shell fallback »3.1 Test rouge
Section intitulée « 3.1 Test rouge »- name: Vérifier carol shell = /bin/bash (default) ansible.builtin.command: getent passwd carol register: carol_passwd changed_when: false
- name: Assertion carol shell = /bin/bash ansible.builtin.assert: that: - "'/bin/bash' in carol_passwd.stdout"carol n’a pas de shell: dans users_to_create. Le test passe déjà car notre default('/bin/bash') fonctionne — mais le hard-coding /bin/bash n’est pas idéal.
3.2 REFACTOR — variable users_default_shell
Section intitulée « 3.2 REFACTOR — variable users_default_shell »users_default_shell: /bin/bashusers_create_home: trueusers_to_create: []# tasks/main.yml refactoré- name: Créer les utilisateurs ansible.builtin.user: name: "{{ item.name }}" shell: "{{ item.shell | default(users_default_shell) }}" groups: "{{ item.groups | default([]) }}" append: true create_home: "{{ users_create_home }}" state: present loop: "{{ users_to_create }}" loop_control: label: "{{ item.name }}"molecule verify # VERT — refactor n'a rien casséC’est le bénéfice du TDD : on refactor avec confiance car les tests garantissent qu’on n’a pas cassé le comportement.
Étape finale — argument_specs.yml
Section intitulée « Étape finale — argument_specs.yml »Ajouter la validation des entrées une fois le code stable :
argument_specs: main: options: users_to_create: type: list elements: dict options: name: type: str required: true shell: type: str choices: - /bin/bash - /bin/zsh - /bin/sh - /sbin/nologin groups: type: list elements: str default: [] users_default_shell: type: str default: /bin/bashRe-tester :
molecule verify # toujours VERTMaintenant, si un user du rôle passe shell: /bin/csh, Ansible refuse d’exécuter — pas de demi-déploiement.
Pratiquer dans le lab
Section intitulée « Pratiquer dans le lab »Cette page a un lab d’accompagnement : labs/molecule/tdd-cycle/ dans
stephrobert/ansible-training.
Le lab fournit le rôle users complet avec 4 assertions dans verify.yml (alice exists, alice shell, alice wheel, carol default shell). 6 tests structure validés.
cd ~/Projets/ansible-training/labs/molecule/tdd-cycle/cat roles/users/tasks/main.ymlcat molecule/default/verify.ymlpytest -v challenge/tests/Pour lancer Molecule réellement :
molecule test # cycle complet TDDÀ retenir
Section intitulée « À retenir »- TDD = un test rouge avant chaque ligne de code.
- 3 cycles minimum par feature (RED, GREEN, REFACTOR).
append: truemandatory surgroups:pour ne pas écraser les autres groupes.default(users_default_shell)pour fallback sur une valeur configurable.- Refactor sans peur grâce aux tests existants.
argument_specs.ymlvient après la stabilité, pour verrouiller l’API publique.