How to run Ansible task only when item in complex JSON is defined?

2.3k views Asked by At

I have two hosts:

  • foo
  • bla

foo has no host_vars. bla has a host_vars file with this content:

---
# host_vars/bla
'a': {
  'b': {
    'c': 'string'
  }
}

my task should only run when the complex JSON exists and contains the item b. My logic would be: when a exists and has item b then it has also c.

My task looks like:

---
- name: example task
  file:
    dest: "{{ item.dest }}"
    owner: "{{ item.owner }}"
    state: directory
  with_items:
    - { dest: "/tmp/{{ a['b']['c'] }}", owner: root }
  when: a['b'] is defined

result

this task succeeds for bla (cause it has the correct JSON) but fails for foo which misses the JSON.

fatal: [foo]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'b'"}
ok: [bla] => (item={u'dest': u'/tmp/string', u'owner': u'root'})

expected

skipping: [foo]: => (item={u'dest': u'/tmp/', u'owner': u'root'})
ok: [bla] => (item={u'dest': u'/tmp/string', u'owner': u'root'})

notice

Now I know that the when statement is interpreted for each item therefore it will not work. Could someone provide a solution that works?

Ansible version is 2.2.0

edit

---
- name: example task
  file:
    dest: "{{ item.dest }}"
    owner: "{{ item.owner }}"
    state: directory
  with_items:
    - { dest: "/tmp/{{ a['b']['c'] | default([]) }}", owner: root }
  when: a['b'] is defined

this will not work because when is evaluated after with_items and as long as a['b'] is not defined it will fail.

fatal: [foo]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'b'"}
1

There are 1 answers

0
craver On BEST ANSWER

found something that works:

- name: example task
  file:
    dest: "{{ item.dest }}"
    owner: "{{ item.owner }}"
    state: directory
  with_items:
    - { dest: "/tmp/{{ (a['b'] | default({}))['c'] | default('nA') }}", owner: root }
  when: a['b'] is defined