Strange behavior of Jinja2 expression for same input vars

32 views
Skip to first unread message

Cos Bug

unread,
Jul 6, 2016, 5:59:59 AM7/6/16
to Ansible Project
Hi All,

I'm using a Jinja2 expression to exclude form one list the elements present in another list but it doesn't work as expected.

Here is an extract from a larger playbook which captures the input and out put before and after 'set_fact' statement:

- debug: var=excluded_ids

- debug: var=instance_ids

- name: Exclude them from instance_ids
  set_fact
: instance_ids1="{% for item in instance_ids if item not in excluded_ids %}{{ item }}{% endfor %}"

- debug: var=instance_ids1

and here the strange output of instance_ids1 variable:

TASK: [debug var=excluded_ids] ************************************
ok
: [127.0.0.1] => {
   
"var": {
       
"excluded_ids": [
           
"i-bae34407"
       
]
   
}
}

TASK
: [debug var=instance_ids] ************************************
ok
: [127.0.0.1] => {
   
"var": {
       
"instance_ids": [
           
"i-bae34407",
           
"i-d2e4436f"
       
]
   
}
}

TASK
: [Exclude them from instance_ids] ****************************
ok
: [127.0.0.1] => {"ansible_facts": {"instance_ids1": "u, ud26f"}}


TASK
: [debug var=instance_ids1] ***********************************
ok
: [127.0.0.1] => {
   
"var": {
       
"instance_ids1": "u, ud26f"
   
}
}

As you can see I get some rubbish in instance_ids1.

But if I run a separate playbook defined like this:

---
#
- hosts: localhost
  connection
: local
  gather_facts
: no

  vars
:

    instance_ids
:
     
- "i-bae34407"
     
- "i-d2e4436f"

    excluded_ids
:
     
- "i-bae34407"

  tasks
:

   
- debug: var=excluded_ids

   
- debug: var=instance_ids

   
- set_fact: instance_ids1="{% for item in instance_ids if item not in excluded_ids %}{{ item }}{% endfor %}"

   
- debug: var=instance_ids1


I get the correct/expected behavior:

TASK: [debug var=excluded_ids] ************************************************
ok
: [127.0.0.1] => {
   
"var": {
       
"excluded_ids": [
           
"i-bae34407"
       
]
   
}
}

TASK
: [debug var=instance_ids] ************************************************
ok
: [127.0.0.1] => {
   
"var": {
       
"instance_ids": [
           
"i-bae34407",
           
"i-d2e4436f"
       
]
   
}
}

TASK
: [set_fact instance_ids1="{% for item in instance_ids if item not in excluded_ids %}{{ item }}{% endfor %}"] ***
ok
: [127.0.0.1] => {"ansible_facts": {"instance_ids1": "i-d2e4436f"}}

TASK
: [debug var=instance_ids1] ***********************************************
ok
: [127.0.0.1] => {
   
"var": {
       
"instance_ids1": "i-d2e4436f"
   
}
}



Why Ansible / Jinja2 treats these list variables differently ?
Are they stored internally as different types ?
 
In debug statements in both cases they appear to be similar (at least printing out)  ...

Thanks & Regards,
Constantin


Aneesh Joseph

unread,
Jul 6, 2016, 7:53:28 AM7/6/16
to Ansible Project
have you tried the difference filter  - http://docs.ansible.com/ansible/playbooks_filters.html

I'm not sure if you can combine a for loop and an if condition like that, I would have used something like this

set_fact: instance_ids1="{{ instance_ids  | difference(excluded_ids) }}"

or

set_fact: instance_ids1="{% for item in instance_ids %}{% if item not in excluded_ids %}{{ item }}{% endif %}{% endfor %}"




On Wednesday, July 6, 2016 at 3:29:59 PM UTC+5:30, Cos Bug wrote:
Hi All,
Enter code here...


Cos Bug

unread,
Jul 6, 2016, 10:08:42 AM7/6/16
to Ansible Project
Thanks Aneesh,

The first suggestion brings this:

TASK: [Exclude them from instance_ids] ****************************

ok
: [127.0.0.1] => {"ansible_facts": {"instance_ids1": "set([u' ', u'd', u'f', u',', u'2', u'u', u'6'])"}}



TASK
: [debug var=instance_ids1] ***********************************
ok
: [127.0.0.1] => {
   
"var": {

       
"instance_ids1": "set([u' ', u'd', u'f', u',', u'2', u'u', u'6'])"
   
}
}

the second one doesn't work either (already tried before posting this :-) ).

Tested with Ansible version 1.9.4 & 2.2.0

Aneesh Joseph

unread,
Jul 6, 2016, 11:59:33 PM7/6/16
to Ansible Project
Hey, tried both in 2.2.0 and they work for me

---
#
- hosts: localhost
  connection
: local
  gather_facts
: no


  vars
:


    instance_ids
:
     
- "i-bae34407"
     
- "i-d2e4436f"


    excluded_ids
:
     
- "i-bae34407"


  tasks
:


   
- debug: var=excluded_ids


   
- debug: var=
instance_ids


   
- set_fact: instance_ids1="{% for item in instance_ids %}{% if item not in excluded_ids %}{{ item }}{% endif %}{% endfor %}"


   
- debug: var=instance_ids1

Result
 [WARNING]: provided hosts list is empty, only localhost is available




PLAY
[localhost] ***************************************************************


TASK
[debug] *******************************************************************
ok
: [localhost] => {
   
"excluded_ids": [
       
"i-bae34407"
   
]
}


TASK
[debug] *******************************************************************
ok
: [localhost] => {
   
"instance_ids": [
       
"i-bae34407",
       
"i-d2e4436f"
   
]
}


TASK
[set_fact] ****************************************************************
ok
: [localhost]


TASK
[debug] *******************************************************************
ok
: [localhost] => {
   
"instance_ids1": "i-d2e4436f"
}


PLAY RECAP
*********************************************************************
localhost                  
: ok=4    changed=0    unreachable=0    failed=0


---
#
- hosts: localhost
  connection
: local
  gather_facts
: no


  vars
:


    instance_ids
:
     
- "i-bae34407"
     
- "i-d2e4436f"


    excluded_ids
:
     
- "i-bae34407"


  tasks
:


   
- debug: var=excluded_ids


   
- debug: var=
instance_ids


   
- set_fact: instance_ids1="{{ instance_ids  | difference(excluded_ids) }}"


   
- debug: var=instance_ids1


Result

 [WARNING]: provided hosts list is empty, only localhost is available




PLAY
[localhost] ***************************************************************


TASK
[debug] *******************************************************************
ok
: [localhost] => {
   
"excluded_ids": [
       
"i-bae34407"
   
]
}


TASK
[debug] *******************************************************************
ok
: [localhost] => {
   
"instance_ids": [
       
"i-bae34407",
       
"i-d2e4436f"
   
]
}


TASK
[set_fact] ****************************************************************
ok
: [localhost]


TASK
[debug] *******************************************************************
ok
: [localhost] => {
   
"instance_ids1": [
       
"i-d2e4436f"
   
]
}


PLAY RECAP
*********************************************************************
localhost                  
: ok=4    changed=0    unreachable=0    failed=0

Cos Bug

unread,
Jul 7, 2016, 1:37:29 AM7/7/16
to Ansible Project
Yes, they work both in a test script where both the excluded_ids and  instance_ids  variables are defined manually but not in original playbook in which these variables are registered as outputs from other modules/tasks
despite the debug shows that their contents are the same.

Reply all
Reply to author
Forward
0 new messages