Introducing when Conditional
Every task you’ve written in this course so far has run unconditionally, on every targeted host, every time. when: changes that — a task only runs if its condition evaluates true, and gets skipped, cleanly, for any host where it doesn’t.
What Is when:?
Attach when: to a task, and Ansible evaluates it before deciding whether to run that task at all:
- name: When Demo
hosts: servers
tasks:
- name: Only run on Debian-family systems
ansible.builtin.debug:
msg: "This is a Debian-family host"
when: ansible_facts['os_family'] == 'Debian'ok: [ubuntu] => {
"msg": "This is a Debian-family host"
}
skipping: [fedora]Same task, same play — ubuntu ran it, fedora didn’t, because each host’s own os_family fact was evaluated independently. A skipped task isn’t a failure; it’s reported distinctly, and the rest of the playbook continues normally.
Basic Comparisons
Ordinary comparison operators work exactly as you’d expect:
when: ansible_facts['memtotal_mb'] > 512
when: inventory_hostname != 'fedora'
when: ansible_facts['distribution'] == 'Ubuntu'Using A Fact Or Variable Directly As A Condition
If a variable already holds a boolean, you don’t need to compare it to anything — just reference it directly:
vars:
enable_backups: true
tasks:
- name: Run backup task
ansible.builtin.debug:
msg: "Backing up..."
when: enable_backupsNegate with not:
when: not enable_backupsThe in Operator
Check membership in a list — including, very usefully, the group_names magic variable from earlier in this course:
when: "'servers' in group_names"when: inventory_hostname in ['ubuntu', 'fedora']The first form is exactly how you’d write a condition that should apply to an entire group, without hardcoding which specific hosts belong to it.
when: Applies Per-Host
Worth stating plainly, since the opening example depends on it: on a multi-host play, when: is evaluated separately for each host, using that host’s own facts and variables. It’s not one shared true/false decision for the whole play — ubuntu and fedora genuinely reached different answers to the exact same condition in the very first example.
A Gotcha: Don’t Wrap The Condition In {{ }}
when: "{{ ansible_facts['os_family'] == 'Debian' }}"This is redundant, and it’s discouraged for a specific reason: when: is already treated as a Jinja2 expression — you’re not filling in a string that happens to contain an expression, the whole line is the expression. Wrapping it in {{ }} on top of that is unnecessary at best, and can cause genuine problems with more complex conditions at worst. Write it plainly instead:
when: ansible_facts['os_family'] == 'Debian'Best Practices
- Never wrap a
when:condition in{{ }}— it’s already an expression context, not a string waiting to be templated. - Use
group_names/inventory_hostnamewithinfor group- or host-specific conditions, rather than hardcoding a list of IPs or duplicating your inventory’s own grouping logic. - Remember
when:evaluates independently per host — a condition that’s true for one host in a play can be false for another, in the exact same task, on the exact same run.