# with\_dict and Jinja templates - Error

**URL:** <https://forum.ansible.com/t/with-dict-and-jinja-templates-error/15967>\
**Category:** Ansible Project\
**Created:** [August 16, 2014, 11:38am UTC](https://forum.ansible.com/t/with-dict-and-jinja-templates-error/15967 "2014-08-16T11:38:23Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Matt\_Silverlock](https://avatars.discourse-cdn.com/v4/letter/m/41988e/32.png) [@Matt\_Silverlock](https://forum.ansible.com/u/Matt_Silverlock)\
**Post date:** [August 16, 2014, 11:38am UTC](https://forum.ansible.com/t/with-dict-and-jinja-templates-error/15967/1 "2014-08-16T11:38:23Z")

</div>

Hi all,

Trying to pull together my understanding of Jinja’s looping constructs, Ansible’s with\_dict and from what I’ve seen out in the wild (i.e. on GitHub). I’ve taken a look around at some other examples but can’t seem to adapt them to my approach (i.e. [https://github.com/timmahoney/ansible-redhat-extra-repos/blob/master/defaults/main.yml](https://github.com/timmahoney/ansible-redhat-extra-repos/blob/master/defaults/main.yml) is close to what I’m after)

At the moment I’m attempting to loop over a YAML dict of OS user ↔ DB user mappings (for pg\_ident.conf) and am running into an error:

**# host\_vars/**  
postgres\_users:  
baltar:  
os: “{{ username }}”  
db: “{{ db\_name }}”  
caprica:  
os: “{{ username }}”  
db: “{{ db\_name }}”

**# pg\_ident.conf.j2**

{% for user in postgres\_users %}  
{{ user.db }} {{ user.os }} {{ user.key }}  
{% endfor %}

**# roles/postgresql/tasks/postgres.yml**

- name: copy postgres ident maps  
template: src=pg\_ident.conf.j2 dest=/etc/postgresql/9.3/main/pg\_ident.conf owner=postgres group=postgres mode=0640  
register: postgres\_ident  
with\_dict: postgres\_users

**# error message**

TASK: [postgres | copy postgres ident maps] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
fatal: [default] =\> {‘msg’: “AnsibleUndefinedVariable: One or more undefined variables: ‘str object’ has no attribute ‘db’”, ‘failed’: True}  
fatal: [default] =\> {‘msg’: ‘One or more items failed.’, ‘failed’: True, ‘changed’: False, ‘results’: [{‘msg’: “AnsibleUndefinedVariable: One or more undefined variables: ‘str object’ has no attribute ‘db’”, ‘failed’: True}]}

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [August 16, 2014, 3:14pm UTC](https://forum.ansible.com/t/with-dict-and-jinja-templates-error/15967/2 "2014-08-16T15:14:39Z")

</div>

With dict works a little differently than with\_items.

with\_items will return one item in the postgres\_users list, one after another, if it were a list of users.

postgres\_users:

- name: boxey  
db: cargo\_ship

Now, when using with\_dict, it works differently, returning keys as item.key and values as item.value

[http://docs.ansible.com/playbooks\_loops.html#looping-over-hashes](http://docs.ansible.com/playbooks_loops.html#looping-over-hashes)

I’d consider either passing a list as above or using with\_dict, but noting what it returns.

Meanwhile, this looks problematic:

template: src=pg\_ident.conf.j2 dest=/etc/postgresql/9.3/main/pg\_ident.conf owner=postgres group=postgres mode=0640

Why?

You’re evaluating it multiple times in a loop, but there is no variable in the destination path. The result is you’ve re-templated the file many times.

I think you don’t need the loop, and just need to simply reference postgres\_users as a variable in the template, and templating the file once is fine.

But you can’t use a simple for loop, because postgres\_users is not a list.

Try:

{% for (key, value) in postgres\_users.iteritems() %}

{% endfor %}

if you want to keep things as a hash/dictionary.

---

<div class="post-metadata">

**Author:** ![Matt\_Silverlock](https://avatars.discourse-cdn.com/v4/letter/m/41988e/32.png) [@Matt\_Silverlock](https://forum.ansible.com/u/Matt_Silverlock)\
**Post date:** [August 17, 2014, 12:55am UTC](https://forum.ansible.com/t/with-dict-and-jinja-templates-error/15967/3 "2014-08-17T00:55:02Z")

</div>

> Meanwhile, this looks problematic:

> template: src=pg\_ident.conf.j2 dest=/etc/postgresql/9.3/main/pg\_ident.conf owner=postgres group=postgres mode=0640

> Why?  
> You’re evaluating it multiple times in a loop, but there is no variable in the destination path. The result is you’ve re-templated the file many times.  
> I think you don’t need the loop, and just need to simply reference postgres\_users as a variable in the template, and templating the file once is fine.

I was originally under the impression that you needed to pass lists/dicts to templates explicitly (i.e. for use by Jinja) - hadn’t realised that they were global.

You’ve solved my confusion though (and dropped in a BSG reference to boot!) — thanks Michael.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [August 17, 2014, 12:59pm UTC](https://forum.ansible.com/t/with-dict-and-jinja-templates-error/15967/4 "2014-08-17T12:59:55Z")

</div>

No problem!

“hadn’t realised that they were global.”

Not always global, some variables are scoped to the host because they are set on the group or host (like group\_vars, host\_vars, facts, etc). But yeah you don’t have to pass anything explicitly to the template module ever, it grabs everything that should be in scope, and takes care of sorting variable precedence out automatically.
