"when" and "with_items" again, with a twist

113 views
Skip to first unread message

henrique....@reevoo.com

unread,
Jun 24, 2016, 12:37:30 PM6/24/16
to Ansible Project
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

Barry Kaplan

unread,
Feb 28, 2017, 11:47:13 AM2/28/17
to Ansible Project
Anybody figure out to get around these deprecation warnings?

Brian Coca

unread,
Feb 28, 2017, 11:55:20 AM2/28/17
to Ansible Project
default only applies to the 'last' item, so if you are going to do
several depths of var defintion that can be undefined, you should have
several defaults.

"{{ (example.json|default({})).url | default([]) }}"


----------
Brian Coca

Barry Kaplan

unread,
Feb 28, 2017, 12:06:50 PM2/28/17
to Ansible Project
Thanks Brian. Just saw that example in another post. It does work of course, but boy is it ugly.
Reply all
Reply to author
Forward
0 new messages