Skip to content

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:

when_demo.yaml
- 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_backups

Negate with not:

when: not enable_backups

The 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_hostname with in for 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.
Last updated on