Hi,
I'm getting an error when using "when" and "with_items" together. As I've read many times, this happens because "when" runs inside "with_items", so we can use "| default([])" to bypass the error, but I think I found a new twist on it. Here's an example:
$ cat example.yml
---
- hosts: localhost
vars:
run: true
tasks:
- block:
- uri:
url: "http://httpbin.org/get"
register: example
- debug:
msg: "{{ example }}"
- debug:
msg: "{{ item }}"
with_items: "{{ example.json | default([]) }}"
- debug:
msg: "{{ item }}"
with_items: "{{ example.json.url | default([]) }}"
when: "{{ run }}" Let's run it twice, when "run" is set to "true" and when is it set to "false":
$ ansible-playbook example.yml -e run=true
PLAY [localhost] ***************************************************************
TASK [setup] *******************************************************************
ok: [localhost]
TASK [uri] *********************************************************************
ok: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": {
"access_control_allow_credentials": "true",
"access_control_allow_origin": "*",
"changed": false,
"connection": "close",
"content_length": "238",
"content_type": "application/json",
"date": "Fri, 24 Jun 2016 16:27:38 GMT",
"json": {
"args": {},
"headers": {
"Accept-Encoding": "identity",
"Cache-Control": "no-cache",
"Host": "httpbin.org",
"User-Agent": "ansible-httpget"
},
"origin": "31.221.70.170",
"url": "http://httpbin.org/get"
},
"msg": "OK (238 bytes)",
"redirected": false,
"server": "nginx",
"status": 200,
"url": "http://httpbin.org/get"
}
}
TASK [debug] *******************************************************************
ok: [localhost] => (item=origin) => {
"item": "origin",
"msg": "origin"
}
ok: [localhost] => (item=headers) => {
"item": "headers",
"msg": "headers"
}
ok: [localhost] => (item=args) => {
"item": "args",
"msg": "args"
}
ok: [localhost] => (item=url) => {
"item": "url",
"msg": "url"
}
TASK [debug] *******************************************************************
ok: [localhost] => (item=http://httpbin.org/get) => {
"item": "http://httpbin.org/get",
"msg": "http://httpbin.org/get"
}
PLAY RECAP *********************************************************************
localhost : ok=5 changed=0 unreachable=0 failed=0 $ ansible-playbook example.yml -e run=false
PLAY [localhost] ***************************************************************
TASK [setup] *******************************************************************
ok: [localhost]
TASK [uri] *********************************************************************
skipping: [localhost]
TASK [debug] *******************************************************************
skipping: [localhost]
TASK [debug] *******************************************************************
TASK [debug] *******************************************************************
[DEPRECATION WARNING]: Skipping task due to undefined Error, in the future this will be a fatal error.: 'dict object' has no attribute 'json'.
This feature will be removed in a
future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
skipping: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0
So it seems like the "| default([])" workaround doesn't work when you go one level deeper. I can understand the error, of course the attribute 'json' doesn't exist, but what other workaround could I use in this case? I've tried an ugly ternary operator to no avail:
with_items: "{{ example.json is defined | ternary(example.json.url | default([]), []) }}"
Thank you,
Henrique Rodrigues