Contrôler l'État des Tâches avec changed_when et failed_when
Dans cette étape, vous obtiendrez un contrôle plus fin sur la manière dont Ansible interprète le résultat de vos tâches. Vous découvrirez deux directives puissantes : changed_when et failed_when.
changed_when : Par défaut, les modules comme ansible.builtin.command ou ansible.builtin.shell rapportent presque toujours un état "changed" (modifié), même si la commande qu'ils ont exécutée n'a pas modifié le système. changed_when vous permet de définir une condition personnalisée qui détermine si une tâche doit être signalée comme "changed". Ceci est crucial pour écrire des playbooks idempotents et pour déclencher correctement les handlers.
failed_when : Parfois, une commande peut se terminer avec un code de retour non nul (ce qu'Ansible considère comme un échec) même lorsque le résultat est acceptable. failed_when vous permet de remplacer les conditions d'échec par défaut, permettant à votre playbook de continuer en fonction de critères plus intelligents, tels que la sortie de la commande ou un code de sortie spécifique.
Commençons par configurer un nouveau répertoire de projet.
cd ~/project
mkdir control-state-lab
cd control-state-lab
Créez le fichier inventory standard pour localhost.
nano inventory
Ajoutez le contenu suivant :
localhost ansible_connection=local
Enregistrez et quittez l'éditeur (Ctrl+X, Y, Entrée).
Utilisation de changed_when
Tout d'abord, voyons comment se comporte une tâche de commande par défaut. Nous allons créer un playbook qui exécute la commande date. Cette commande affiche simplement la date et ne modifie pas le système, mais le module command la signalera comme un changement.
Créez un nouveau playbook nommé playbook.yml.
nano playbook.yml
Entrez le contenu suivant :
---
- name: Control Task State
hosts: localhost
tasks:
- name: Check local time (default behavior)
ansible.builtin.command: date
Enregistrez et quittez. Exécutez maintenant le playbook.
ansible-playbook -i inventory playbook.yml
Remarquez dans la sortie que la tâche est signalée comme changed=1, même si rien sur le système n'a été modifié.
...
TASK [Check local time (default behavior)] *************************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 ...
Maintenant, utilisons changed_when pour indiquer à Ansible que cette commande ne modifie jamais le système. Modifiez playbook.yml.
nano playbook.yml
Ajoutez changed_when: false à la tâche.
---
- name: Control Task State
hosts: localhost
tasks:
- name: Check local time (with changed_when)
ansible.builtin.command: date
changed_when: false
Enregistrez et quittez. Exécutez à nouveau le playbook.
ansible-playbook -i inventory playbook.yml
Cette fois, la tâche signale ok et le récapitulatif final montre changed=0. Vous avez réussi à outrepasser le comportement par défaut.
...
TASK [Check local time (with changed_when)] ************************************
ok: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 ...
Utilisation de failed_when
Ensuite, explorons failed_when. Nous allons créer une tâche qui vérifie l'existence d'un fichier qui n'est pas là. La commande "échouera" par défaut.
Tout d'abord, créez un fichier factice dans lequel rechercher.
echo "System is running" > status.txt
Maintenant, modifiez playbook.yml pour rechercher le mot "ERROR" dans ce fichier. La commande grep se terminera avec un code de retour de 1 car le mot n'est pas trouvé, ce qu'Ansible interprète comme un échec.
nano playbook.yml
Remplacez le contenu par le suivant :
---
- name: Control Task State
hosts: localhost
tasks:
- name: Check for ERROR in status file (will fail)
ansible.builtin.command: grep ERROR status.txt
Enregistrez et quittez. Exécutez le playbook.
ansible-playbook -i inventory playbook.yml
Comme prévu, l'exécution du playbook s'arrête avec un message FAILED!.
...
TASK [Check for ERROR in status file (will fail)] ******************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["grep", "ERROR", "status.txt"], "delta": "...", "end": "...", "msg": "non-zero return code", "rc": 1, ...}
...
Ce n'est pas ce que nous voulons. L'absence de "ERROR" est une condition de succès pour nous. Nous pouvons utiliser failed_when pour redéfinir ce qui constitue un échec. Nous indiquerons à Ansible de ne échouer que si le code de retour de la commande est supérieur à 1. Un code de retour de 1 (motif non trouvé) sera désormais considéré comme un succès. Nous devons également register le résultat de la tâche pour inspecter son code de retour (rc).
Modifiez playbook.yml une dernière fois.
nano playbook.yml
Mettez à jour le playbook avec register et failed_when.
---
- name: Control Task State
hosts: localhost
tasks:
- name: Check for ERROR in status file (with failed_when)
ansible.builtin.command: grep ERROR status.txt
register: grep_result
failed_when: grep_result.rc > 1
changed_when: false
Nous avons également ajouté changed_when: false car grep est une opération en lecture seule et ne modifie pas le système.
Enregistrez et quittez. Exécutez le playbook final.
ansible-playbook -i inventory playbook.yml
Succès ! La tâche signale maintenant ok car son code de retour était 1, ce qui ne satisfait pas notre nouvelle condition d'échec (rc > 1). Le playbook se termine avec succès.
...
TASK [Check for ERROR in status file (with failed_when)] ***********************
ok: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 ...
Vous avez maintenant appris à utiliser changed_when et failed_when pour définir précisément les états de succès, de changement et d'échec de vos tâches, ce qui conduit à une automatisation plus robuste et plus intelligente.