Unable to access hostvars when the inventory_host is inserted as a variable

Harald picture Harald · Dec 3, 2018 · Viewed 13.1k times · Source

I have a jinja2 template, and I'm trying to loop through a host group, and insert the ipv4 address of all the hosts in my template. But I'm getting an error when I do it, even though the way I'm doing it is the way every post and article suggest it should be done.

Here's the template that's producing the error:

{% if groups['linux-hosts'] %}
{% for item in groups['linux-hosts'] %}
define host {
    use                     generic-host-normal
    host_name               {{ item }}
    alias                   {{ item }}
    address                 {{ hostvars[item].ansible_default_ipv4.address }}
}
{% endfor %}
{% endif %}

And the error I'm getting is:

failed: [server] (item=servers.cfg) => {"changed": false, "item": "servers.cfg", "msg": "AnsibleUndefinedVariable: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'ansible_default_ipv4'"}

If I don't use the variable 'item' in the square brackets, but instead specify a specific host from the inventory, Ansible is able to get the ipv4 address. Example ('server' is the name of a host from my inventory):

{{ hostvars['server'].ansible_default_ipv4.address }}

Answer

awalker125 picture awalker125 · Sep 25, 2019

I came across this problem with a similar use case. My problem turned out to be that I included hosts in a group which were not the target of the play. Therefore gather facts had not run against all the hosts in the group. I fixed this by running setup against all the hosts I needed like this

- name: get cluster facts
  hosts: k8s-cluster
  tags:
    - always
  tasks:
    - name:
      setup:
      become: true

- name: deploy HA Proxy
  hosts: kube-master
  become: yes
  roles:
    - { role: ansible-role-haproxy }

Note: kube-master is a subset of k8s-cluster