Contrôler les tâches avec des conditions et des boucles

AnsibleBeginner
Pratiquer maintenant

Introduction

Un seul playbook peut sélectionner des travaux différents pour chaque hôte sans dupliquer toute la liste de tâches. Vous combinerez des entrées de politique booléennes avec les faits du système d'exploitation, traiterez chaque élément d'une liste structurée et utiliserez des résultats d'inspection réellement enregistrés pour une décision d'approbation indépendante. Des fichiers réels et un nettoyage explicite rendront observables les comportements sélectionnés et ignorés.

Sélectionner des tâches avec des entrées booléennes et des faits

Dans cette étape, vous ferez agir un playbook réutilisable différemment sur les deux hôtes et supprimerez explicitement les sorties lorsque la politique devient désactivée.

L'environnement préparé possède une entrée d'approbation séparée dans /home/automation/maintenance-approved uniquement sur web1. Laissez cette entrée inchangée pour le moment ; la première décision de politique utilise plutôt une variable booléenne et les faits découverts du système d'exploitation.

Entrez dans le projet du contrôleur :

cd /home/labex/project

Les fichiers de variables d'hôte associent des données à chaque nom d'inventaire. Écrivez les valeurs booléennes YAML sans guillemets afin qu'elles restent des valeurs true/false plutôt que des chaînes :

cat > host_vars/web1.yml <<'YAML'
maintenance_enabled: true
YAML
cat > host_vars/web2.yml <<'YAML'
maintenance_enabled: false
YAML

Le mot-clé when évalue une expression booléenne pour l'hôte actuel. N'entourez pas l'expression d'accolades Jinja. Ici, and exige à la fois une politique activée et des faits de famille Debian. not inverse un booléen et or permet à l'une ou l'autre raison de sélectionner la branche de nettoyage.

cat > maintenance.yml <<'YAML'
- name: Apply a host-specific maintenance policy
  hosts: all
  gather_facts: true
  tasks:
    - name: Prepare the common policy directory
      ansible.builtin.file:
        path: /home/automation/maintenance-policy
        state: directory
        mode: "0750"

    - name: Record enabled Debian maintenance
      ansible.builtin.copy:
        dest: /home/automation/maintenance-policy/enabled.txt
        content: "Enabled maintenance\n"
        mode: "0640"
      when: maintenance_enabled and ansible_facts.os_family == "Debian"

    - name: Remove the marker when the policy is disabled
      ansible.builtin.file:
        path: /home/automation/maintenance-policy/enabled.txt
        state: absent
      when: not maintenance_enabled or ansible_facts.os_family != "Debian"
YAML

Le répertoire commun existe sur les deux hôtes. Seuls les hôtes Debian activés reçoivent le fichier témoin ; la tâche absent complémentaire le supprime lorsque la politique est désactivée. Une tâche de création simplement ignorée laisserait un ancien fichier témoin : le nettoyage est donc une tâche distincte d'état souhaité.

Validez et appliquez la politique :

ansible-playbook maintenance.yml --syntax-check
ansible-playbook maintenance.yml

La sortie doit montrer des décisions changed/ok/skipped différentes pour web1 et web2. Examinez les métadonnées du véritable fichier témoin sur les deux hôtes :

ansible all -m ansible.builtin.stat -a 'path=/home/automation/maintenance-policy/enabled.txt'

Stat doit indiquer exists true sur web1 et false sur web2. Pour exercer le nettoyage, remplacez le booléen pour les deux hôtes. Les variables supplémentaires JSON préservent le type booléen false ; les guillemets simples englobants protègent le JSON de l'interprétation du shell :

ansible-playbook maintenance.yml -e '{"maintenance_enabled":false}'
ansible all -m ansible.builtin.stat -a 'path=/home/automation/maintenance-policy/enabled.txt'

Les deux fichiers témoins doivent maintenant être absents. Rétablissez la politique enregistrée par hôte en exécutant sans le remplacement temporaire :

ansible-playbook maintenance.yml

Web1 doit retrouver le fichier témoin tandis que web2 reste désactivé. Le remplacement n'a pas modifié les fichiers de variables d'hôte enregistrés.

Appliquer chaque élément d'une boucle structurée

Dans cette étape, vous produirez un véritable enregistrement de vérification de maintenance pour chaque élément déclaré sur l'hôte activé.

Une liste YAML contient plusieurs entrées introduites par un tiret. Chaque entrée ci-dessous est une correspondance avec les champs name et purpose. Les variables de groupe pour all rendent cette liste disponible aux deux hôtes, tandis que la condition booléenne existante décide toujours quel hôte reçoit les sorties.

cat > group_vars/all.yml <<'YAML'
maintenance_checks:
  - name: disk
    purpose: Inspect disk space
  - name: logs
    purpose: Inspect application logs
  - name: packages
    purpose: Inspect package state
YAML

loop répète une tâche pour chaque entrée de liste. Dans une itération, item.name et item.purpose lisent les champs de cette entrée. La condition when est évaluée pour chaque hôte et élément. Ajoutez ces tâches au playbook existant en alignant l'indentation avec les tâches précédentes :

cat >> maintenance.yml <<'YAML'

    - name: Prepare checks only for enabled Debian hosts
      ansible.builtin.file:
        path: /home/automation/maintenance-policy/checks
        state: directory
        mode: "0750"
      when: maintenance_enabled and ansible_facts.os_family == "Debian"

    - name: Write every declared maintenance check
      ansible.builtin.copy:
        dest: "/home/automation/maintenance-policy/checks/{{ item.name }}.txt"
        content: |
          host={{ inventory_hostname }}
          check={{ item.name }}
          purpose={{ item.purpose }}
        mode: "0640"
      loop: "{{ maintenance_checks }}"
      when: maintenance_enabled and ansible_facts.os_family == "Debian"

    - name: Remove check outputs when the policy is disabled
      ansible.builtin.file:
        path: /home/automation/maintenance-policy/checks
        state: absent
      when: not maintenance_enabled or ansible_facts.os_family != "Debian"
YAML

La tâche de nettoyage supprime tout le répertoire de vérifications sur les hôtes désactivés, y compris les anciennes sorties d'une politique précédemment activée. La boucle écrit un contenu stable et des permissions explicites sur les hôtes activés.

Appliquez le playbook étendu :

ansible-playbook maintenance.yml

Web1 doit avoir trois résultats de boucle, un par vérification. Web2 doit ignorer ces écritures et ne conserver aucun répertoire checks. Lisez les trois artefacts réels de web1 au lieu de considérer un seul élément réussi comme preuve pour toute la liste :

ansible web1 -m ansible.builtin.command -a 'cat /home/automation/maintenance-policy/checks/disk.txt /home/automation/maintenance-policy/checks/logs.txt /home/automation/maintenance-policy/checks/packages.txt'

La sortie doit identifier host=web1 pour chaque enregistrement et montrer le nom et le but de la vérification correspondante. Examinez l'hôte désactivé indépendamment :

ansible web2 -m ansible.builtin.stat -a 'path=/home/automation/maintenance-policy/checks'

Son résultat stat doit indiquer exists false. Ces enregistrements déclarent des instructions de vérification de maintenance ; ils ne prétendent pas exécuter eux-mêmes les inspections du disque, des journaux ou des paquets.

Choisir une branche selon un résultat d'inspection enregistré

Dans cette étape, vous utiliserez un véritable résultat stat comme entrée de décision indépendante et confirmerez que la politique complète est stable lors d'une répétition.

L'entrée d'approbation est distincte de maintenance_enabled. Une tâche stat examine toujours chaque hôte, puis register stocke son résultat. Son booléen stat.exists distingue de manière sûre une entrée existante d'un chemin absent. Ajoutez l'inspection et les tâches de sortie complémentaires :

cat >> maintenance.yml <<'YAML'

    - name: Inspect the independent approval input
      ansible.builtin.stat:
        path: /home/automation/maintenance-approved
      register: approval_info

    - name: Record an existing approval input
      ansible.builtin.copy:
        dest: /home/automation/maintenance-policy/approved.txt
        content: "Approval input exists\n"
        mode: "0640"
      when: approval_info.stat.exists

    - name: Remove the output when approval input is absent
      ansible.builtin.file:
        path: /home/automation/maintenance-policy/approved.txt
        state: absent
      when: not approval_info.stat.exists
YAML

La tâche copy consomme la valeur exists enregistrée. La tâche absent couvre son opposé afin que la suppression d'une entrée d'approbation supprime aussi la sortie d'approbation périmée. Cette branche repose sur l'état inspecté plutôt que sur un message debug fixe.

Exécutez la politique complète :

ansible-playbook maintenance.yml

L'entrée d'approbation préparée n'existe que sur web1 ; seul web1 doit donc avoir approved.txt. Examinez les deux chemins de sortie réels :

ansible all -m ansible.builtin.stat -a 'path=/home/automation/maintenance-policy/approved.txt'

Web1 doit indiquer exists true et web2 false. Répétez le playbook :

ansible-playbook maintenance.yml

Les deux lignes du récapitulatif doivent indiquer changed=0, failed=0 et unreachable=0. Des tâches ignorées sont attendues lorsque leur condition est fausse ; chaque élément de boucle requis et chaque sortie sélectionnée doivent toutefois exister avec le bon contenu.

Résumé

Vous avez utilisé des données booléennes par hôte et des faits découverts pour sélectionner les tâches, traité chaque correspondance dans une boucle et choisi des branches selon des métadonnées stat enregistrées. Des tâches absent complémentaires ont supprimé les sorties périmées au lieu de supposer qu'une création ignorée annule l'ancien état. Les deux hôtes ont convergé vers leurs résultats de politique distincts sans changements répétés inutiles.