# special dict hostvars

**URL:** <https://forum.ansible.com/t/special-dict-hostvars/17556>\
**Category:** Ansible Project\
**Created:** [February 18, 2015, 6:45pm UTC](https://forum.ansible.com/t/special-dict-hostvars/17556 "2015-02-18T18:45:56Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [February 18, 2015, 6:45pm UTC](https://forum.ansible.com/t/special-dict-hostvars/17556/1 "2015-02-18T18:45:56Z")

</div>

Hi,

We’re used to do things like

hostvars[inventory\_hostname].somevar

Now, I wanted to debug someting and did

ansible all -m debug -a var=hostvars

I expected this to return something like

{ ‘hostvars’:

‘host1’:

‘somevar’ : somevalue  
…

‘host2’:  
…  
…  
}

Instead I got

host1:

{ ‘somevar’ : somevalue  
…

}

host2:  
…

Another example is at [https://p.6core.net/p/RCJAYyK1gzBuEcwZa8Tgx4S5](https://p.6core.net/p/RCJAYyK1gzBuEcwZa8Tgx4S5)

Now i know ‘hostvars’ is a special kind of object (some kind of dict that caches things), but I’m confused on this difference, and have no explanation for it.

Serge

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [February 18, 2015, 7:07pm UTC](https://forum.ansible.com/t/special-dict-hostvars/17556/2 "2015-02-18T19:07:47Z")

</div>

In code the difference is mostly that hostvars is a 'cache' object  
that internally implements most (but not all, it seems) the methods of  
a dictionary. The default cache is an actual in memory dictionary but  
the object still acts as an intermediary.

There is probably a way to make it behave exactly the same in this  
case, but I would need to look into it deeper.

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [February 18, 2015, 7:33pm UTC](https://forum.ansible.com/t/special-dict-hostvars/17556/3 "2015-02-18T19:33:15Z")

</div>

> In code the difference is mostly that hostvars is a 'cache' object  
> that internally implements most (but not all, it seems) the methods of  
> a dictionary. The default cache is an actual in memory dictionary but  
> the object still acts as an intermediary.

​Yes, that's what special about hostvars in the code. But as to what the  
'hostvars' var is in ansible playbooks,  
we're still missing ​the difference between two things in your assertion  
here.

It sounds like something weird though.

There is probably a way to make it behave exactly the same in this

> case, but I would need to look into it deeper.

​Given time I'll try to have a look myself. Perhaps this is part a thing  
for -devel, as it seems to me

BTW, another example of how this is weird, just run these commands from an  
empty dir:

serge@cyberlab:~/tmp$ ansible all -i localhost, -c local -m debug -a

> var=hostvars[inventory\_hostname]

localhost | success \>\> {

> &nbsp;&nbsp;&nbsp;&nbsp;"hostvars[inventory\_hostname]": {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"group\_names": ,  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"inventory\_hostname": "localhost",  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"inventory\_hostname\_short": "localhost"  
> &nbsp;&nbsp;&nbsp;&nbsp;}  
> }
> 
> serge@cyberlab:~/tmp$ ansible all -i localhost, -c local -m debug -a  
> var=hostvars  
> localhost | success \>\> {  
> &nbsp;&nbsp;&nbsp;&nbsp;"hostvars": {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"group\_names": ,  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"inventory\_hostname": "localhost",  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"inventory\_hostname\_short": "localhost"  
> &nbsp;&nbsp;&nbsp;&nbsp;}  
> }

Thanks,

&nbsp;&nbsp;&nbsp;Serge

---

<div class="post-metadata">

**Author:** ![jpmens.dns](https://avatars.discourse-cdn.com/v4/letter/j/c57346/32.png) [@jpmens.dns](https://forum.ansible.com/u/jpmens.dns)\
**Post date:** [February 18, 2015, 8:20pm UTC](https://forum.ansible.com/t/special-dict-hostvars/17556/4 "2015-02-18T20:20:25Z")

</div>

The question then is, how do I loop over the hostvars for hosts in a template?  
The original question popped up today, because I was trying something which  
used to work:

{% for host, v in hostvars.iteritems() %}  
{{ host }} == {{ v[‘ansible\_distribution\_version’] }} … etc.  
{% endfor %}

I _know_ this worked for hosts because I copied it from an old presentation I did.  
Nowadays (1.8.2) it no longer works: because of the extra keys in hostvars.

Regards,

-JP

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [February 18, 2015, 10:25pm UTC](https://forum.ansible.com/t/special-dict-hostvars/17556/5 "2015-02-18T22:25:42Z")

</div>

i have this from an old template:

{% for host in groups['all'] %}  
{% for k in hostvars[host] %} ....

---

<div class="post-metadata">

**Author:** ![Jan-Piet\_Mens](https://avatars.discourse-cdn.com/v4/letter/j/34f0e0/32.png) [@Jan-Piet\_Mens](https://forum.ansible.com/u/Jan-Piet_Mens)\
**Post date:** [February 19, 2015, 7:48am UTC](https://forum.ansible.com/t/special-dict-hostvars/17556/6 "2015-02-19T07:48:13Z")

</div>

Thanks Brian, but that also no longer works, at least not for me.

I've put up an example here: [https://p.6core.net/p/yIT8nVBZXlOJyZERHoxA3Rmz](https://p.6core.net/p/yIT8nVBZXlOJyZERHoxA3Rmz)

Am I misunderstanding what hostvars \_should\_ contain?

Regards,

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-JP

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [February 19, 2015, 8:28am UTC](https://forum.ansible.com/t/special-dict-hostvars/17556/7 "2015-02-19T08:28:53Z")

</div>

AFAIK, hostvars should be a dict of dicts, where the keys are the  
inventory\_hostnames.  
The fact that host variables are put directly in hostvars, is a bug, I  
think.​

Looking at the code, I think there was confusion between 'hostvars' as we  
know to use it in playbooks and templates, which is a variable in the  
'inject',  
and hostvars, a host specific vari containg the hosts' variables, and used  
in the Runner() object.

This might fix it:

diff --git a/lib/ansible/runner/\_\_init\_\_.py b/lib/ansible/runner/\_\_init\_\_.py  
index 79a167c..501dc41 100644  
--- a/lib/ansible/runner/\_\_init\_\_.py  
+++ b/lib/ansible/runner/\_\_init\_\_.py  
@@ -684,7 +684,8 @@ class Runner(object):

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# and we save the HostVars in the injected dictionary so they  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# may be referenced from playbooks/templates  
- inject['hostvars'] = hostvars  
+ inject['hostvars'] = {}  
+ inject['hostvars'][host] = hostvars

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host\_connection = inject.get('ansible\_connection', self.transport)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if host\_connection in ['paramiko', 'ssh', 'accelerate']:

You can check out my branch here to test that:

&nbsp;&nbsp;[https://github.com/srvg/ansible/tree/fix\_inject\_hostvars](https://github.com/srvg/ansible/tree/fix_inject_hostvars)

Serge

---

<div class="post-metadata">

**Author:** ![Jan-Piet\_Mens](https://avatars.discourse-cdn.com/v4/letter/j/34f0e0/32.png) [@Jan-Piet\_Mens](https://forum.ansible.com/u/Jan-Piet_Mens)\
**Post date:** [February 19, 2015, 9:29am UTC](https://forum.ansible.com/t/special-dict-hostvars/17556/8 "2015-02-19T09:29:02Z")

</div>

> You can check out my branch here to test that:

As mentioned to you privately, this reports KeyError '127.0.0.1' on a  
template which contains

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{% for host in hostvars %}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{ host }}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{% endfor %}

Regards,

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-JP

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [February 19, 2015, 1:10pm UTC](https://forum.ansible.com/t/special-dict-hostvars/17556/9 "2015-02-19T13:10:54Z")

</div>

I just tested this and it seems to work fine in current devel:

----dump.j2  
{% for host in groups['all'] %}

{{host}}:  
{% for k in hostvars[host] %}  
&nbsp;&nbsp;&nbsp;&nbsp;{{k}}: {{ hostvars[host][k]}}  
{% endfor %}  
{% endfor %}  
--- play.yml

- hosts: localhost  
&nbsp;&nbsp;tasks:  
&nbsp;&nbsp;&nbsp;&nbsp;- template: src=templates/dump.j2 dest=/tmp/dump.txt  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection: local
