
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.