# Jinja2 Template and Dictionary issue

**URL:** <https://forum.ansible.com/t/jinja2-template-and-dictionary-issue/26731>\
**Category:** Ansible Project\
**Created:** [February 14, 2018, 4:07pm UTC](https://forum.ansible.com/t/jinja2-template-and-dictionary-issue/26731 "2018-02-14T16:07:00Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Owen\_Corcoran](https://avatars.discourse-cdn.com/v4/letter/o/977dab/32.png) [@Owen\_Corcoran](https://forum.ansible.com/u/Owen_Corcoran)\
**Post date:** [February 14, 2018, 4:07pm UTC](https://forum.ansible.com/t/jinja2-template-and-dictionary-issue/26731/1 "2018-02-14T16:07:00Z")

</div>

Can anyone help me with the below, maybe my approach is wrong. What I’m trying to do is to create from a template a keepalived file based on the elements in a dictionary.

I’ve included the code below, when its ran the error that appears is

msg": “AnsibleUndefinedVariable: ‘dict object’ has no attribute ‘hostname’”

The error appears to in the second loop in the jinja2 template, where i try to extract the elements from the sub lst in the dictionary.

ANSIBLE Dictionary

keepalived\_virtual\_ip:

- vip\_details\_1:

haproxy\_vip\_name: “AddressCleaner\_Development”

ip: “1.0.1.2”

front\_end\_port: 80

haproxy\_backend\_servers:

- servers\_1.1:

hostname: system12

address: 2.0.0.1

- servers\_1.2:

hostname: system13

address: 2.0.0.2

- vip\_details\_2:

haproxy\_vip\_name: “AddressCleaner\_Cert”

ip: “3.0.0.114”

front\_end\_port: 80

haproxy\_backend\_servers:

- servers\_2.1:

hostname: system21

address: 2.0.0.3

- servers\_2.2:

hostname: system22

address: 2.0.0.4

keepalived\_virtual\_ip:

- vip\_details\_1:

haproxy\_vip\_name: “AddressCleaner\_Development”

ip: “3.0.0.115”

front\_end\_port: 80

haproxy\_backend\_servers:

- servers\_1.1:

hostname: lonldpostal01

address: 3.0.0.87

- servers\_1.2:

hostname: lonldpostal02

address: 3.0.0.100

- vip\_details\_2:

haproxy\_vip\_name: “AddressCleaner\_Cert”

ip: “3.0.0.114”

front\_end\_port: 80

haproxy\_backend\_servers:

- servers\_2.1:

hostname: lonlcpostal01

address: 3.0.0.96

- servers\_2.2:

hostname: lonlcpostal02

address: 3.0.0.104

HA PROXY TEMPLATE

{% for item in keepalived\_virtual\_ip %}

listen {{ item.haproxy\_vip\_name }} {{ item.ip }}:{{ item.front\_end\_port }}

mode {{ haproxy\_mode }}

balance {{ haproxy\_vip\_algo }}

default\_backend {{ item.haproxy\_vip\_name }}\_backend

{% endfor %}

{% for item in keepalived\_virtual\_ip %}

backend {{ item.haproxy\_vip\_name }}\_backend

mode tcp

balance source

{% for backend in item.haproxy\_backend\_servers %}

server {{ backend.hostname }} {{ backend.address }}:{{ haproxy\_vip\_port }} maxconn 9000 send-proxy check

{% endfor %}

{% endfor %}

---

<div class="post-metadata">

**Author:** ![Kai\_Stian\_Olstad](https://avatars.discourse-cdn.com/v4/letter/k/e19adc/32.png) [@Kai\_Stian\_Olstad](https://forum.ansible.com/u/Kai_Stian_Olstad)\
**Post date:** [February 14, 2018, 6:36pm UTC](https://forum.ansible.com/t/jinja2-template-and-dictionary-issue/26731/2 "2018-02-14T18:36:11Z")

</div>

> keepalived\_virtual\_ip:  
> &nbsp;&nbsp;- vip\_details\_1:  
> &nbsp;&nbsp;&nbsp;&nbsp;haproxy\_vip\_name: "AddressCleaner\_Development"  
> &nbsp;&nbsp;&nbsp;&nbsp;ip: "1.0.1.2"  
> &nbsp;&nbsp;&nbsp;&nbsp;front\_end\_port: 80  
> &nbsp;&nbsp;&nbsp;&nbsp;haproxy\_backend\_servers:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- servers\_1.1:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hostname: system12  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address: 2.0.0.1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- servers\_1.2:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hostname: system13  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address: 2.0.0.2

It's not allowed to have . (dot) in variable name only letters, numbers and underscores is allowed so servers\_1.1: is invalid

> {% for item in keepalived\_virtual\_ip %}  
> backend {{ item.haproxy\_vip\_name }}\_backend  
> &nbsp;&nbsp;&nbsp;&nbsp;mode tcp  
> &nbsp;&nbsp;&nbsp;&nbsp;balance source  
> &nbsp;&nbsp;&nbsp;&nbsp;{% for backend in item.haproxy\_backend\_servers %}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;server {{ backend.hostname }} {{ backend.address }}:{{ haproxy\_vip\_port }} maxconn 9000 send-proxy check  
> &nbsp;&nbsp;&nbsp;&nbsp;{% endfor %}  
> {% endfor %}  
> &nbsp;&nbsp;  
> Lets say that servers\_1.1: is servers\_1\_1:, the same for server\_1.2

item.haproxy\_backend\_server is a list of dictonary, the hostname is not backend.hostname but  
backend.servers\_1\_1.hostname and backend.servers\_1\_2.hostname

---

<div class="post-metadata">

**Author:** ![Owen\_Corcoran](https://avatars.discourse-cdn.com/v4/letter/o/977dab/32.png) [@Owen\_Corcoran](https://forum.ansible.com/u/Owen_Corcoran)\
**Post date:** [February 14, 2018, 8:54pm UTC](https://forum.ansible.com/t/jinja2-template-and-dictionary-issue/26731/3 "2018-02-14T20:54:14Z")

</div>

Could i have instead of :

Servers\_1.1  
Servers\_1.2  
Servers\_2.1  
Servers\_2.2  
Servers\_3.1  
Servers\_3.2

Call each list

servers

The reason being i dont want to have to hard code names in the jinja2 template of the elements in the lists of backends, depending on the size of the dictionary i might shink or add hosts/backends and i want the template to dynamically pick these additions or substractions without a code change in the template file.

---

<div class="post-metadata">

**Author:** ![Kai\_Stian\_Olstad](https://avatars.discourse-cdn.com/v4/letter/k/e19adc/32.png) [@Kai\_Stian\_Olstad](https://forum.ansible.com/u/Kai_Stian_Olstad)\
**Post date:** [February 15, 2018, 6:02am UTC](https://forum.ansible.com/t/jinja2-template-and-dictionary-issue/26731/4 "2018-02-15T06:02:12Z")

</div>

The easiest to do is make haproxy\_backend\_servers a list of dictionaries and not a list of dictionary.

So if you can change you haproxy\_backend\_servers to

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;haproxy\_backend\_servers:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: servers\_1.1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hostname: system12  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address: 2.0.0.1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: servers\_1.2:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hostname: system13  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address: 2.0.0.2

You code will work as is since you can call backend.hostname and not backend.\<something\>.hostname
