idiot one
idiot one

Reputation: 389

Ansible nested condition

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

Answers (2)

zigarn
zigarn

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

Vladimir Botka
Vladimir Botka

Reputation: 68044

Given the list

l1:
  - 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

  • Example of a complete playbook
- 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 }}"
  • It is not possible to use selectattr. The task below
    - 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

Related Questions