The when Clause
Every task can include a 'when' key with a Jinja2 expression (written without the {{ }} delimiters) that Ansible evaluates before deciding whether to run the task on a given host. If the expression evaluates to false for a particular host, that task is skipped for that host only — other hosts in the same play may still run it if their expression evaluates true, since 'when' is evaluated per-host, not once for the whole play.
Cricket analogy: The 'when' clause is like a captain only bringing on a spinner when the pitch report shows dry conditions — the decision is re-evaluated fresh for each match (host), not fixed for the whole season.
Combining Conditions and Using Facts
Conditions can combine multiple expressions using Jinja2's 'and', 'or', and 'not', or by supplying a YAML list under 'when' where every list item must be true (an implicit AND). Conditionals commonly reference Ansible facts gathered automatically at play start — like ansible_facts['os_family'] or ansible_facts['distribution_major_version'] — letting a single playbook branch its behavior correctly across Debian, RedHat, and other families without maintaining separate playbooks.
Cricket analogy: Combining conditions with 'and' is like a bowling change that only happens if it's both the death overs AND the required run rate is above ten — both facts about the match state must hold simultaneously.
tasks:
- name: Install Apache on Debian-based systems
ansible.builtin.apt:
name: apache2
state: present
when: ansible_facts['os_family'] == "Debian"
- name: Install Apache on RedHat-based systems
ansible.builtin.yum:
name: httpd
state: present
when: ansible_facts['os_family'] == "RedHat"
- name: Check disk usage
ansible.builtin.command: df -h /
register: disk_check
changed_when: false
- name: Alert if root partition usage is high
ansible.builtin.debug:
msg: "Warning: disk usage is high on {{ inventory_hostname }}"
when:
- disk_check.stdout is defined
- "'9' in disk_check.stdout.split()[-2]"
Conditionals on register Results
The 'register' keyword captures a task's full result — return code, stdout, stderr, and a 'changed'/'failed' status — into a variable that later tasks can reference in their own 'when' conditions. This is the standard pattern for making a playbook react to runtime information it couldn't know in advance, such as only sending a notification task 'when: disk_check.rc != 0' or skipping a migration step 'when: not migration_status.stat.exists'.
Cricket analogy: register is like noting down the exact result of a review (out, not out, umpire's call) so the next tactical decision — whether to review again — is based on that specific recorded outcome.
Always pair ansible.builtin.command or ansible.builtin.shell tasks used purely for inspection with 'changed_when: false' (and often 'failed_when' too) — otherwise Ansible reports them as 'changed' on every run even though you're just reading state to feed a later 'when' condition.
- 'when' takes a Jinja2 expression (no {{ }}) and is evaluated per-host before a task runs.
- A YAML list under 'when' means all items must be true (implicit AND).
- ansible_facts (e.g., os_family, distribution) let one playbook branch across OS families.
- 'register' captures a task's rc, stdout, stderr, and changed/failed status into a variable.
- Later tasks can condition on registered results, e.g. when: result.rc != 0.
- Inspection-only command/shell tasks should use changed_when: false to avoid false 'changed' reports.
- Conditionals are evaluated independently per host, so behavior can legitimately differ across a play.
Practice what you learned
1. How is a 'when' expression written in a task?
2. What does supplying a YAML list of conditions under 'when' mean?
3. What does the 'register' keyword do?
4. Why should you add 'changed_when: false' to a command task used only to inspect state?
5. Is 'when' evaluated once for the whole play, or separately per host?
Was this page helpful?
You May Also Like
Loops in Ansible
Use the 'loop' keyword and its variants to run a single task repeatedly over lists, dictionaries, and nested data structures.
Tasks and Modules
Understand how Ansible tasks invoke modules to perform idempotent actions, and how to choose the right module for the job.
Handlers and Notifications
Learn how Ansible handlers run only when notified by a change, and how to coordinate restarts and other follow-up actions efficiently.
Related Reading
Related Study Notes in DevOps
Browse all study notesNginx Study Notes
DevOps · 30 topics
DevOpsAdvanced Kubernetes Study Notes
Kubernetes · 30 topics
DevOpsAdvanced Bash Scripting Study Notes
Bash · 30 topics
DevOpsApache Kafka Study Notes
Kafka · 30 topics
DevOpsDocker & Kubernetes Study Notes
YAML · 40 topics
DevOpsCI/CD Tools & Pipelines Study Notes
YAML · 37 topics