# variables and their (multiple layer) resolution

**URL:** <https://forum.ansible.com/t/variables-and-their-multiple-layer-resolution/15460>\
**Category:** Ansible Project\
**Created:** [June 13, 2014, 8:45pm UTC](https://forum.ansible.com/t/variables-and-their-multiple-layer-resolution/15460 "2014-06-13T20:45:09Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dimon](https://avatars.discourse-cdn.com/v4/letter/d/eb8c5e/32.png) [@Dimon](https://forum.ansible.com/u/Dimon)\
**Post date:** [June 13, 2014, 8:45pm UTC](https://forum.ansible.com/t/variables-and-their-multiple-layer-resolution/15460/1 "2014-06-13T20:45:09Z")

</div>

I have a playbook, and in one of the templates I need to walk over all the hosts in certain groups grabbing their hostvars etc.

I followed [http://docs.ansible.com/faq.html](http://docs.ansible.com/faq.html) and everything seems to work as expected but with one quirk:

In template I have:

{% for host in groups[‘nova’] %}  
{% set myvars=hostvars[host] %}

{% endfor %}

in group\_vars/nova.yml I have:

…  
service\_admin\_ip: 192.168.0.138  
service\_public\_ip: “{{ ansible\_default\_ipv4.address }}”  
service\_internal\_ip: “{{ ansible\_default\_ipv4.address }}”

service\_region: RegionOne  
…

so as a result I get:

Note that service\_public\_ip did not get resolved as expected (even though facts were collected for that host already), and service\_admin\_ip works fine when I hardcode it and don’t use facts. Is there a way to get around this issue? I do not want to drop ansible\_default\_ipv4 stuff into the role’s playbook but prefer to keep it “configurable” with some sane default (default\_ipv4). What am I missing in this?

P.S.  
I have some other plays where group\_vars/all.yml defines vars in similar fashion (referencing some of the facts) and those work just fine.

---

<div class="post-metadata">

**Author:** ![Dimon](https://avatars.discourse-cdn.com/v4/letter/d/eb8c5e/32.png) [@Dimon](https://forum.ansible.com/u/Dimon)\
**Post date:** [June 16, 2014, 4:05pm UTC](https://forum.ansible.com/t/variables-and-their-multiple-layer-resolution/15460/2 "2014-06-16T16:05:26Z")

</div>

Shall I assume that below is a bug?

---

<div class="post-metadata">

**Author:** ![Dimon](https://avatars.discourse-cdn.com/v4/letter/d/eb8c5e/32.png) [@Dimon](https://forum.ansible.com/u/Dimon)\
**Post date:** [June 16, 2014, 11:12pm UTC](https://forum.ansible.com/t/variables-and-their-multiple-layer-resolution/15460/3 "2014-06-16T23:12:00Z")

</div>

Looks like it’s some sort of problem with templates, consider this simplified playbook:

roles/keystone/tasks/main.yml:

---

<div class="post-metadata">

**Author:** ![Tomasz\_Kontusz](https://avatars.discourse-cdn.com/v4/letter/t/bc79bd/32.png) [@Tomasz\_Kontusz](https://forum.ansible.com/u/Tomasz_Kontusz)\
**Post date:** [June 17, 2014, 5:46am UTC](https://forum.ansible.com/t/variables-and-their-multiple-layer-resolution/15460/4 "2014-06-17T05:46:20Z")

</div>

Dmitry Makovey \<droopy4096@gmail.com\> napisał:

> Looks like it's some sort of problem with templates, consider this  
> simplified playbook:
> 
> roles/keystone/tasks/main.yml:
> 
> ---
> 
> - name: test template  
> template: src=template.j2 dest=/tmp/template.txt
> 
> - name: test simple var  
> debug: var=simple\_var
> 
> - name: test nested var  
> debug: var=nested\_var
> 
> - name: test fact var  
> debug: var=fact\_var
> 
> and roles/keystone/templates/templatej.j2:  
> -------  
> {{ simple\_var }}  
> {{ nested\_var }}  
> {{ fact\_var }}
> 
> Var extraction:
> 
> {% for h in groups['keystone'] %}  
> {% set myvars=hostvars[h] %}  
> {{ myvars.simple\_var }}  
> {{ myvars.nested\_var }}  
> {{ myvars.fact\_var }}  
> {% endfor %}
> 
> -------
> 
> the playbook output is as expected - vars all rendered properly ,  
> however  
> templates are not so clean:  
> -------  
> Simple var  
> Simple var  
> 192.168.0.138
> 
> Var extraction:
> 
> &nbsp;&nbsp;Simple var  
> {{simple\_var}}  
> {{ansible\_default\_ipv4.address}}
> 
> -------
> 
> as you can see when iterating over hosts from the group for some reason
> 
> vars are not being resolved as expected.

The reason is: multiple layers of resolution are implemented as a magic dictionary that renders the variables on access. For some reason it explicitly ignores fancy dictionaries, and hostvars is one of those (it has some magic for caching).  
I think it's a bug, but that should be decided by devs. Still, filling an issue should be OK 🙂

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [June 17, 2014, 12:48pm UTC](https://forum.ansible.com/t/variables-and-their-multiple-layer-resolution/15460/5 "2014-06-17T12:48:52Z")

</div>

There was a ticket raised (possibly by you) recently that recursion in Jinja2 templates does not appear to be a thing. Since I think that’s filed already, we should be good to go, but I would consider this as something that should work.

As an alternative, if you put the variable name directly in the template, or use the “set\_fact” module to assign the variable to a new name, you should be ok.

---

<div class="post-metadata">

**Author:** ![Dimon](https://avatars.discourse-cdn.com/v4/letter/d/eb8c5e/32.png) [@Dimon](https://forum.ansible.com/u/Dimon)\
**Post date:** [June 17, 2014, 3:08pm UTC](https://forum.ansible.com/t/variables-and-their-multiple-layer-resolution/15460/6 "2014-06-17T15:08:30Z")

</div>

> There was a ticket raised (possibly by you) recently that recursion in Jinja2 templates does not appear to be a thing. Since I think that’s filed already, we should be good to go, but I would consider this as something that should work.

yes, I did file a ticket ( [Jinja variable handling inconsistencies · Issue #7799 · ansible/ansible · GitHub](https://github.com/ansible/ansible/issues/7799) ) as I was digging deeper into this issue it felt more and more like a bug, but I was hoping it was just me {ab,mis}using it.

> As an alternative, if you put the variable name directly in the template, or use the “set\_fact” module to assign the variable to a new name, you should be ok.

thanks for the tip - I did test this workaround and it works, albeit it puts quite a few extra items in a playbook to work around the issue. Just for posterity trick like that worked for me so far:

# prepend to site.yml …

- hosts: keystone  
tasks:
- set\_fact: nested\_var={{ nested\_var }}  
…

makes variable resolution inside Jinja template consistent with resolution in playbook. Ain’t pretty but it works.

Bonus question: can I write above statement using “with\_items” so at least I don’t have to copy-paste entire stanza and only have to enumerate var names? (my guess is “no” but hey, maybe I’m wrong?)

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [June 17, 2014, 7:00pm UTC](https://forum.ansible.com/t/variables-and-their-multiple-layer-resolution/15460/7 "2014-06-17T19:00:26Z")

</div>

“Bonus question: can I write above statement using “with\_items” so at least I don’t have to copy-paste entire stanza and only have to enumerate var names? (my guess is “no” but hey, maybe I’m wrong?)”

This seems to be another topic, so let’s start a new thread on that, though seems easy for you to try first and maybe post if it’s not 🙂

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [June 17, 2014, 7:07pm UTC](https://forum.ansible.com/t/variables-and-their-multiple-layer-resolution/15460/8 "2014-06-17T19:07:57Z")

</div>

It was discussed recently that in templates variables were not being recursive as they should be.

This is something we will look into.
