Ошибка AnsibleUndefinedVariable: ‘dict object’ has no attribute

Question:

Hello everyone. I came across a curious problem.

Input data (ansible 2.2):

  1. Inventory
[api]
api01.domain.tld max_fails=12 fail_timeout=70 
api02.domain.tld max_fails=13 fail_timeout=70 
api03.domain.tld max_fails=12 fail_timeout=70 
api04.domain.tld max_fails=12 fail_timeout=70
  1. Template for describing nginx upstreams (the second loop is important):

{% for upstream1 in nginx_upstreams1.iteritems() %}
upstream {{ upstream1[0] }} {
{% for item in upstream1[1] %}
  {{ item }};
{% endfor %}
{% for host in groups[upstream1[0]] %}
  # {{ host }}
  server {{ hostvars[host].ansible_eth0.ipv4.address }} ;
  {{ hostvars[host].max_fails }}
{% endfor %}
}
{% endfor %}
max_fails {{ hostvars['api01.domain.tld'].max_fails }}
max_fails {{ hostvars['api02.domain.tld'].max_fails }}
  1. As a result, I get that

a) the code - {{ hostvars[host].max_fails }} – produces "msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'max_fails'"

b) when I specify the hostname in hostvars with my hands, everything works out correctly ( max_fails {{ hostvars['api01.domain.tld'].max_fails }} )

c) when I watch ad-hoc debugging output via -m debug , or hostvars[host] to a rendered template – max_fails is there.

What am I doing wrong?

Answer:

I rather have a comment "on my version of ansible everything works", I am writing an answer only so that the listings are readable.

I also want you to make a fully reproducible example since some variables are missing (nginx_upstreams1) – and I had to throw them away. Perhaps this affected the execution of the script.

By the way, I do not remember if there is some kind of service variable host but I know for sure that in all scripts I prefer to call the variable for bypassing item . Is it possible that there is some new variable introduced in 2.2?

The script itself:

- name: http://ru.stackoverflow.com/questions/601512/
  hosts: api
  tasks:
    - name: template nginx conf
      template:
        src="test.j2"
        dest="/home/ansible/test.txt"

Sample:

upstream {

{% for host in groups['api'] %}
  # {{ host }}
  server {{ hostvars[host].ansible_eth0.ipv4.address }} ;
  {{ hostvars[host].max_fails }}
{% endfor %}
}

max_fails {{ hostvars['api01.domain.tld'].max_fails }}
max_fails {{ hostvars['api02.domain.tld'].max_fails }}

Software version:

$ ansible --version
ansible 2.1.2.0
  config file = /home/ak/ansible/so/601512/ansible.cfg
  configured module search path = Default w/o overrides

PS And even through a variable it works:

Script:

- name: http://ru.stackoverflow.com/questions/601512/
  hosts: api
  vars:
    group_name: "api"
  tasks:
    - name: debug group_name
      debug: msg="{{ group_name }}"
    - name: template nginx conf
      template:
        src="test.j2"
        dest="/home/ansible/test.txt"

Sample:

upstream {

{% for host in groups['api'] %}
  # {{ host }}
  server {{ hostvars[host].ansible_eth0.ipv4.address }} ;
  {{ hostvars[host].max_fails }}
{% endfor %}

{% for host in groups[group_name] %}
  # {{ host }}
  server {{ hostvars[host].ansible_eth0.ipv4.address }} ;
  {{ hostvars[host].max_fails }}
{% endfor %}
}

max_fails {{ hostvars['api01.domain.tld'].max_fails }}
max_fails {{ hostvars['api02.domain.tld'].max_fails }}

PPS Likewise, no problem and around play_hosts do a workaround: https://stackoverflow.com/questions/39005760/ansible-play-hosts-template-loop

Scroll to Top