Aller au contenu
Infrastructure as Code medium

Conditions Ansible (when) : opérateurs, multi-conditions, tests Jinja

11 min de lecture

Logo Ansible

when: est la directive Ansible qui conditionne l’exécution d’une tâche, d’un block ou d’un rôle sur une expression Jinja2. Si l’expression est vraie, la tâche s’exécute ; sinon elle est marquée skipped dans le PLAY RECAP. Cette page couvre la syntaxe correcte (sans {{ }} ni quotes), les opérateurs de comparaison, les multi-conditions via liste (and implicite), les tests Jinja (is defined, is none, is mapping), et les pièges classiques.

C’est la directive la plus utilisée pour adapter un playbook à différentes distributions, environnements ou variables optionnelles.

  • La syntaxe de when: — pas de {{ }}, pas de quotes
  • Les opérateurs de comparaison : ==, !=, >, <, >=, <=, in, not in
  • Multi-conditions via liste (and implicite) ou expression (and, or, not)
  • Les tests Jinja : is defined, is undefined, is none, is mapping, is sequence
  • when: sur un block : applique la condition à toutes les tâches du block
- name: Installer nginx uniquement sur RedHat
ansible.builtin.dnf:
name: nginx
when: ansible_os_family == "RedHat"

3 règles importantes sur when: :

  1. Pas de {{ }} : when: accepte directement une expression Jinja, pas une interpolation.

    when: ansible_os_family == "RedHat" # ✅
    when: "{{ ansible_os_family == 'RedHat' }}" # ❌ erreur, double évaluation
  2. Pas de quotes externes sauf si l’expression contient des caractères ambigus :

    when: var == 1 # ✅
    when: "var == 1" # ✅ aussi OK
    when: var: var == 1 # ❌ deux-points cassent le YAML
  3. Une string non vide est truthy : when: my_var est vrai si my_var est défini ET non vide/zéro/false.

when: ansible_distribution == "AlmaLinux"
when: ansible_distribution != "Ubuntu"
when: ansible_distribution_major_version | int >= 10
when: ansible_memtotal_mb < 2048
when: "'docker' in ansible_facts.packages"
when: env not in ["dev", "staging"]

Le filtre | int ou | float est nécessaire quand le fact est une string (la plupart des ansible_*_version sont des strings).

Quand vous avez plusieurs conditions à combiner avec and (cas le plus fréquent), passez une liste :

when:
- ansible_distribution == "AlmaLinux"
- ansible_distribution_major_version | int >= 10
- ansible_memtotal_mb >= 1024

Toutes les conditions doivent être vraies pour que la tâche s’exécute. C’est plus lisible qu’une longue expression and.

Pour or ou des combinaisons mixtes, écrivez l’expression complète sur une ligne :

when: ansible_distribution == "AlmaLinux" or ansible_distribution == "RHEL"
when: (env == "prod" and not maintenance_mode) or force_run | default(false)

Les tests Jinja sont écrits avec is :

TestVrai si…
var is definedLa variable existe
var is undefinedElle n’existe pas
var is noneElle est None/null
var is mappingC’est un dict
var is sequenceC’est une liste
var is iterableItérable (liste, dict, string)
var is stringC’est une string
var is numberC’est un nombre
var is regexC’est un objet regex

Cas typique — variable optionnelle :

- name: Activer une feature optionnelle
ansible.builtin.copy:
dest: /tmp/feature.txt
content: "feature ON\n"
when:
- enable_feature is defined
- enable_feature | bool

enable_feature is defined évite l’erreur “undefined variable” ; | bool convertit 'true'/'1'/'yes' en vrai booléen.

- block:
- name: Tâche A (RedHat only)
ansible.builtin.dnf:
name: foo
- name: Tâche B (RedHat only)
ansible.builtin.systemd:
name: foo
state: started
when: ansible_os_family == "RedHat"

Le when: sur le block est propagé à toutes les tâches du block. Plus DRY que de répéter le when: sur chacune.

Cas pratique — 4 conditions ciblées (lab ecrire-code/conditions-when)

Section intitulée « Cas pratique — 4 conditions ciblées (lab ecrire-code/conditions-when) »

Voici l’exemple validé sur le lab 19-ecrire-code-conditions-when :

---
- name: Challenge conditions when
hosts: db1.lab
become: true
gather_facts: true
tasks:
- name: cond-redhat
ansible.builtin.copy:
dest: /tmp/cond-redhat.txt
content: "famille=redhat\n"
mode: "0644"
when: ansible_os_family == "RedHat"
- name: cond-alma10
ansible.builtin.copy:
dest: /tmp/cond-alma10.txt
content: "os=AlmaLinux10\n"
mode: "0644"
when:
- ansible_distribution == "AlmaLinux"
- ansible_distribution_major_version | int >= 10
- name: cond-feature
ansible.builtin.copy:
dest: /tmp/cond-feature.txt
content: "feature=enabled\n"
mode: "0644"
when:
- enable_feature is defined
- enable_feature | bool
- name: cond-debian (NE doit PAS s'exécuter sur AlmaLinux)
ansible.builtin.copy:
dest: /tmp/cond-debian.txt
content: "famille=debian\n"
mode: "0644"
when: ansible_os_family == "Debian"

Lancement avec --extra-vars "enable_feature=true" :

PLAY RECAP
db1.lab : ok=4 changed=3 skipped=1 failed=0

3 fichiers posés (redhat, alma10, feature), 1 task skipped (debian).

when: est évalué à chaque itération de la boucle :

- name: Installer uniquement les paquets activés
ansible.builtin.dnf:
name: "{{ item.name }}"
state: present
loop:
- { name: nginx, enabled: true }
- { name: redis, enabled: false }
- { name: postgresql, enabled: true }
when: item.enabled

redis est skippé pour cette itération uniquement ; les deux autres sont installés.

SymptômeCauseFix
when: "&#123;&#123; var == 'x' &#125;&#125;" ne fonctionne pasDouble évaluation JinjaRetirer &#123;&#123; &#125;&#125; : when: var == 'x'
Expression compare une string et un int incorrectlyType mismatchFiltre `
when: sur une variable absente planteVariable undefinedPréfixer par var is defined and ...
when: var est faux alors que var: "yes"'yes' est une string non vide donc truthy, mais YAML 1.2 ne convertit pasUtiliser `
not item.enabled fait planter quand enabled est absentAccès à clé inexistanteUtiliser `not item.enabled
  • when: prend une expression Jinja sans {{ }} ni quotes externes.
  • Multi-conditions and : passer une liste, plus lisible qu’une expression longue.
  • is defined + | bool sont les deux outils pour gérer les variables optionnelles proprement.
  • when: sur un block propage la condition à toutes les tâches enfants.
  • Combiné avec loop:, when: est évalué à chaque itération.

Cette page a un lab d’accompagnement : labs/ecrire-code/conditions-when/ dans stephrobert/ansible-training. Il contient un README.md guidé, un Makefile (make verify lance les tests), et un challenge final auto-évalué : conditionner 4 tâches sur ansible_os_family, version, et une variable optionnelle.

Une fois le lab provisionné :

Fenêtre de terminal
cd ~/Projets/ansible-training/labs/ecrire-code/conditions-when/
cat README.md # tuto pas à pas
cat challenge/README.md # consigne du challenge final
pytest -v challenge/tests/ # lancer les tests testinfra

Si les tests passent, vous maîtrisez les concepts couverts dans ce guide. En cas de blocage, docs/troubleshooting.md à la racine du repo couvre les pièges fréquents (rate-limit SSH, clé absente, collection manquante).

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn