The when parameter (which is like an if statement) can be used to do something when a condition evaluates to true or false.
when: <some condition>
Often, the when parameter is used to compare a variable to a boolean (such as true, false, 1, or 0), to a string (such as Hello World), or to an integer (such as 12345). In this example, the when parameter is used to determine if the foo variable contains string "bar". Notice foo is not wrapped in quotes and bar is wrapped in quotes. Since foo is not wrapped in quotes, foo is interpreted as a variable. Because bar is wrapped in quotes, bar is interpreted as a string.
---
- hosts: all
tasks:
- ansible.builtin.debug:
msg: the foo variable does not equal 'bar'
when: foo != 'bar'
...
The when parameter can also be used to compare a variable to another variable. In this example, the foo variable is compared to the bar variable. Notice both foo and bar are not wrapped in quotes, meaning that both will be interpreted as variables.
---
- hosts: all
tasks:
- ansible.builtin.debug:
msg: the foo variable does not equal the bar variable
when: foo != bar
...
Or you may want to pipe a variable to a boolean, integer, or string. In this example, the bar variable is piped to a string.
---
- hosts: all
tasks:
- ansible.builtin.debug:
msg: the foo variable does not equal the bar variable piped to a string
when: foo != bar|string
...
AVOID TROUBLE
Jinja2 double curly braces cannot be used in the when parameter
---
- hosts: all
tasks:
- ansible.builtin.debug:
msg: this will cause the playbook to fail fatal because Jinja double curley braces cannot be used in a when statement
when: foo != {{ bar }}
...
Here is how you can use variables in a when statement. In this example, the variable named item is used in the when statement.
In this example, target_directory will be set to /tmp/foo if my_directory is /tmp/foo or target_directory will be set to /tmp/bar if my_directory is /tmp/bar.
---
- hosts: all
tasks:
- ansible.builtin.set_fact:
target_directory: /tmp/{{ foo }}
when: my_directory is regex '/tmp/'+item
with_items:
- 'foo'
- 'bar'
...
Multiple when statements can be used.
---
- hosts: all
tasks:
- ansible.builtin.debug:
msg: multiple when statements
when: foo != hello and foo != world
...
Or like this, using or.
---
- hosts: all
tasks:
- ansible.builtin.debug:
msg: multiple when statements using or
when: foo != hello or foo != world
...
Or like this. This would perform an "and" situation, where all of the when statements would have to evaluate to true, not an "or" situation.
---
- hosts: all
tasks:
- ansible.builtin.debug:
msg: multiple when statements
when:
- foo != hello
- foo != world
...
Or like this, using or.
---
- hosts: all
tasks:
- ansible.builtin.debug:
msg: multiple when statements using or
when:
- foo != hello or
- foo != world
...
Here is an example of a when statement that has multiple and & or conditions.
---
- hosts: all
tasks:
- ansible.builtin.debug:
msg: multiple when statements
when: ((foo != hello) and (foo != world)) or ((bar != hello) and (bar != world))
...
Sometimes, for more complex situation, or to avoid multiple tasks, I will use a jinja if else statement.
---
- hosts: all
tasks:
- ansible.builtin.set_fact:
bar: "{%- if foo == 'hello' -%}Hello
{%- elif foo == 'world' -%}World
{%- else -%}false
{%- endif -%}"
...
And here is a jinja2 if else statement that checks if the foo variable contains hello or world.
---
- hosts: all
tasks:
- ansible.builtin.set_fact:
bar: "{%- if 'hello' in foo -%}Hello
{%- elif 'world' in foo -%}World
{%- else -%}false
{%- endif -%}"
...
Or like this.
---
- hosts: all
tasks:
- ansible.builtin.set_fact:
bar: "{%- if foo | regex_search('.*hello.*') -%}Hello
{%- elif 'world' in foo -%}World
{%- else -%}false
{%- endif -%}"
...
Here are more common when statements.
when the foo variable is defined or undefined (undefined can be prevented with the default filter) | when: foo is defined when: foo is undefined |
when the foo variable or list is empty or not empty | when: foo | length > 0 when: foo | length == 0 |
when the foo variable does or does not equal string hello or world | when: foo == 'hello' when: foo != 'world' |
when the foo variable does or does not contain an integer | when: foo | type_debug == 'int' when: foo | type_debug != 'int' |
when the foo variable does or does not contain a boolean | when: foo | type_debug == 'bool' when: foo | type_debug != 'bool' |
when the foo variable does or does not equal boolean true or false | when: foo == true when: foo != false |
when the foo variable, list or dictionary does or does not contain string hello or world | when: foo is search 'hello|world' when: foo is not search 'hello|world' |
when the content of the foo variable does or does not contain the content of the bar variable | when: bar in foo when: bar not in foo |
when the foo variable or list does or does not contain boolean true | when: true in foo when: false not in foo |
when the foo variable does or does not contain string hello or world with no whitespace | when: foo is regex '(?i)^(hello|world)$' when: foo is not regex '(?i)^(hello|world)$' |
when the foo variable does or does not contain the bar variable | when: foo is regex '(?i).*'+bar+'.*' when: foo is not regex '(?i).*'+bar+'.*' |
when the foo variable does or does not contain string hello (see regex_search) | when: foo | regex_search('(?i).*hello.*') when: not foo | regex_search('(?i).*hello.*') |
when the foo variable does or does not contain the bar variable (see regex_search) | when: foo | regex_search('(?i).*'+bar+'.*') when: not foo | regex_search('(?i).*'+bar+'.*') |
when hostname in one or more groups | when: inventory_hostname in ( groups['foo'] + groups['bar'] ) |
if file exists | see FreeKB - Ansible - Determine if a file or directory exists using the stat module |
Did you find this article helpful?
If so, consider buying me a coffee over at