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.
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.
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
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.
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):
# and we save the HostVars in the injected dictionary so they
# may be referenced from playbooks/templates
- inject['hostvars'] = hostvars
+ inject['hostvars'] = {}
+ inject['hostvars'][host] = hostvars
host_connection = inject.get('ansible_connection', self.transport)
if host_connection in [ 'paramiko', 'ssh', 'accelerate' ]: