4.3 : Conditions : when

On a effleuré when à la fin de la leçon précédente, avec un exemple qui adapte l’installation selon la distribution. Voyons maintenant cette condition en détail — c’est elle qui permet à un playbook de s’adapter au contexte plutôt que d’exécuter bêtement la même suite d’actions, peu importe la situation.

Le principe de base

when s’ajoute au niveau d’une tâche, et cette tâche ne s’exécute que si la condition est vraie :

- name: Installer Apache uniquement sur Debian/Ubuntu
  ansible.builtin.apt:
    name: apache2
    state: present
  when: ansible_os_family == "Debian"

Si la condition est fausse, la tâche apparaît avec le statut skipped dans le résultat — ni ok, ni changed, ni failed : elle n’a tout simplement jamais été évaluée.

Comparer des valeurs

Les opérateurs classiques fonctionnent tels quels :

- name: Alerte si la mémoire est insuffisante
  ansible.builtin.debug:
    msg: "Attention, mémoire faible sur cette machine"
  when: ansible_memtotal_mb < 2048

- name: Vérifier une version précise
  ansible.builtin.debug:
    msg: "Version Debian 12 détectée"
  when: ansible_distribution_version == "12"

Combiner plusieurs conditions

Avec and (les deux doivent être vraies) :

- name: Action réservée aux serveurs web Debian
  ansible.builtin.debug:
    msg: "Serveur web Debian confirmé"
  when: ansible_os_family == "Debian" and "webservers" in group_names

Avec or (au moins une doit être vraie) :

- name: Compatible Debian ou Ubuntu
  ansible.builtin.apt:
    name: curl
    state: present
  when: ansible_distribution == "Debian" or ansible_distribution == "Ubuntu"

Sous forme de liste (équivalent à un and implicite), souvent plus lisible avec plusieurs critères :

- name: Action très ciblée
  ansible.builtin.debug:
    msg: "Toutes les conditions sont réunies"
  when:
    - ansible_os_family == "Debian"
    - ansible_memtotal_mb > 1024
    - "webservers" in group_names

Vérifier qu’une variable existe (ou pas)

Un piège classique : utiliser une variable qui n’a jamais été définie provoque une erreur, pas juste un false. Le test is defined (ou son inverse is not defined) permet de s’en prémunir :

- name: N'agir que si la variable a été fournie
  ansible.builtin.debug:
    msg: "Port personnalisé : {{ apache_port }}"
  when: apache_port is defined

Utiliser le résultat d’une tâche précédente

C’est une combinaison qu’on retrouve très souvent : une tâche register son résultat (on détaille register en profondeur plus loin dans la formation), et une tâche suivante s’appuie sur ce résultat via when :

- name: Vérifier si Apache est déjà installé
  ansible.builtin.command: dpkg -l apache2
  register: apache_check
  failed_when: false
  changed_when: false

- name: Afficher un message uniquement si Apache est absent
  ansible.builtin.debug:
    msg: "Apache n'est pas encore installé, installation en cours"
  when: apache_check.rc != 0

Ici, apache_check.rc est le code de retour de la commande (0 = succès, autre chose = échec) — un réflexe très courant pour condition­ner une action sur le résultat d’une vérification précédente.

Ce qu’il faut retenir

  • when s’ajoute au niveau d’une tâche, qui devient skipped si la condition est fausse.
  • Les listes sous when fonctionnent comme un and implicite, souvent plus lisible que d’enchaîner les and sur une seule ligne.
  • is defined protège contre l’utilisation d’une variable qui n’a jamais été déclarée.
  • On combine très souvent when avec un register d’une tâche précédente pour construire une vraie logique conditionnelle.

Dans la prochaine leçon, on regarde loop : comment répéter une même tâche pour plusieurs éléments, sans dupliquer le YAML autant de fois qu’il y a d’éléments.