Reputation: 389
How can I achieve "nested when" (nested if) in Ansible task?
For example, I want to print item.name if item.name is defined and equals to "hello world".
- name: display foo if foo.name equals to "hello world"
debug:
var: item
when item.name is defined and item.name == "hello world"
with_items:
- {'name': 'hello world'}
- {'age': 14}
- {'name': 'john'}
However, if foo.name is not defined, it fails and reports item.name is not defined
Upvotes: 0
Views: 1355
Reputation: 11595
You can test if the field is available:
when: "'name' in item and item.name == 'hello world'"
You can also protect with a default
:
when: "item.name | default(None) and item.name == 'hello world'"
BTW, it's possible to express AND tests on different lines (but not sure it's good in that case because don't know if it use lazy evaluation, e.g. stop evaluating at first False
):
when:
- "'name' in item"
- "item.name == 'hello world'"
with_items
syntax is deprecated for the loop
syntax.
If possible, better to filter the input:
- name: display foo if foo.name equals to "hello world"
debug:
var: item
loop: "{{ input_list | selectattr('name', 'defined') | selectattr('name', 'equalto', 'hello world') }}"
(edit: added selectattr('name', 'defined')
to avoid error indicated by @Vladimir Botka)
Upvotes: 2
Reputation: 68044
Given the listl1:
- name: hello world
- age: 14
- name: john
Q: "Print item.name
if item.name
is defined and equals to hello world
."
A: Use json_query. This filter ignores missing attributes. For example,
l2: "{{ l1|json_query('[?name == `hello world`]') }}"
gives
l2:
- name: hello world
Notes
- hosts: localhost
vars:
l1:
- name: hello world
- age: 14
- name: john
l2: "{{ l1|json_query('[?name == `hello world`]') }}"
tasks:
- debug:
msg: "{{ item.name }}"
loop: "{{ l2 }}"
- debug:
msg: "{{ l1|selectattr('name', 'eq', 'hello world') }}"
fails
fatal: [localhost]: FAILED! =>
msg: |-
The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'name'
Upvotes: 1