3

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'"}
craver
  • 67
  • 1
  • 9
  • Possible duplicate of [Skip Ansible task when variable not defined](http://stackoverflow.com/questions/40424899/skip-ansible-task-when-variable-not-defined) – techraf Dec 22 '16 at 23:55
  • probably yes. but this question doesn't answer my problem it is only pointing it out. – craver Dec 23 '16 at 09:04
  • It is giving the exact solution you need to apply to get away with your problem. Just like the answer I posted below. – techraf Dec 23 '16 at 09:05
  • it points out the problem but does not solve it. you wrote it in your answer it will fail as long as the parent item is not defined. I am looking for a solution which will *not* fail when the parent (in this case `a['b']`) is not defined. The way how `default()` works is totally crap IMHO. – craver Dec 24 '16 at 14:39

1 Answers1

2

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
craver
  • 67
  • 1
  • 9