# Create variable as dict using jinja2 within playbook

**URL:** <https://forum.ansible.com/t/create-variable-as-dict-using-jinja2-within-playbook/16565>\
**Category:** Ansible Project\
**Created:** [October 21, 2014, 3:55am UTC](https://forum.ansible.com/t/create-variable-as-dict-using-jinja2-within-playbook/16565 "2014-10-21T03:55:28Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Anth\_Courtney](https://avatars.discourse-cdn.com/v4/letter/a/e9c0ed/32.png) [@Anth\_Courtney](https://forum.ansible.com/u/Anth_Courtney)\
**Post date:** [October 21, 2014, 3:55am UTC](https://forum.ansible.com/t/create-variable-as-dict-using-jinja2-within-playbook/16565/1 "2014-10-21T03:55:28Z")

</div>

Hello there,

Is it possible to create a variable which is a dict using jinja2 within a playbook?

For example, I have the following (contrived) playbook, within which I am trying to create a ‘host\_info’ dict which I can then access from a task:

---

<div class="post-metadata">

**Author:** ![James\_Cammarata](https://avatars.discourse-cdn.com/v4/letter/j/7c8e57/32.png) [@James\_Cammarata](https://forum.ansible.com/u/James_Cammarata)\
**Post date:** [October 23, 2014, 4:29pm UTC](https://forum.ansible.com/t/create-variable-as-dict-using-jinja2-within-playbook/16565/2 "2014-10-23T16:29:38Z")

</div>

Hi Anth,

Unfortunately, this cannot be done the way you’re trying it. You’re creating YAML after the YAML structure is already parsed, so the variable is just storing it as a string.

Instead of doing this, I would recommend using the add\_host module ([http://docs.ansible.com/add\_host\_module.html](http://docs.ansible.com/add_host_module.html)), which can also accept any additional variables you may wish to associate with that host entry.

Thanks!

---

<div class="post-metadata">

**Author:** ![Steve\_Jacobs](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@Steve\_Jacobs](https://forum.ansible.com/u/Steve_Jacobs)\
**Post date:** [April 9, 2015, 3:17pm UTC](https://forum.ansible.com/t/create-variable-as-dict-using-jinja2-within-playbook/16565/3 "2015-04-09T15:17:54Z")

</div>

I realize this is an old thread, but why does this not work? It works as expected for arrays…

For instance see this blog post:  
[http://adamj.eu/tech/2014/10/02/merging-groups-and-hostvars-in-ansible-variables/](http://adamj.eu/tech/2014/10/02/merging-groups-and-hostvars-in-ansible-variables/)

That works just fine, but if you try to modify this to output an array of dictionaries, or similar, ansible doesn’t interpret the result correctly. Why?

---

<div class="post-metadata">

**Author:** ![Steve\_Jacobs](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@Steve\_Jacobs](https://forum.ansible.com/u/Steve_Jacobs)\
**Post date:** [April 9, 2015, 3:34pm UTC](https://forum.ansible.com/t/create-variable-as-dict-using-jinja2-within-playbook/16565/4 "2015-04-09T15:34:12Z")

</div>

Why is it possible to do with an array though?

- hosts: all  
connection: local  
gather\_facts: false  
tasks:
- set\_fact:  
myvar: |  
{% set comma = joiner(“,”) %}  
[{% for item in [‘honey’, ‘bunch’] -%}  
{{ comma() }}“monkey”  
{%- endfor %}]
- debug: var=myvar

PLAY [all] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

TASK: [set\_fact] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [127.0.0.1]

TASK: [debug var=myvar] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [127.0.0.1] =\> {  
“var”: {  
“myvar”: [  
“monkey”,  
“monkey”  
]  
}  
}

PLAY RECAP \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0

But:

- hosts: all  
connection: local  
gather\_facts: false  
tasks:
- set\_fact:  
myvar: |  
{% set comma = joiner(“,”) %}  
[{% for item in [‘honey’, ‘bunch’] -%}  
{{ comma() }}{ monkey: banana }  
{%- endfor %}]
- debug: var=myvar

Produces:

TASK: [debug var=myvar] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [127.0.0.1] =\> {  
“var”: {  
“myvar”: “[{ monkey: banana },{ monkey: banana }]”  
}  
}

And:

- hosts: all  
connection: local  
gather\_facts: false  
tasks:
- set\_fact:  
myvar: |  
{{ “\n” }}  
{%- for item in [‘honey’, ‘bunch’] -%}
- { monkey: banana }  
{% endfor %}
- debug: var=myvar

TASK: [debug var=myvar] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [127.0.0.1] =\> {  
“var”: {  
“myvar”: “\n- { monkey: banana }\n- { monkey: banana }\n”  
}  
}

Why does one way work and the other way fail?

---

<div class="post-metadata">

**Author:** ![Anand\_Buddhdev2](https://avatars.discourse-cdn.com/v4/letter/a/48db29/32.png) [@Anand\_Buddhdev2](https://forum.ansible.com/u/Anand_Buddhdev2)\
**Post date:** [April 9, 2015, 10:37pm UTC](https://forum.ansible.com/t/create-variable-as-dict-using-jinja2-within-playbook/16565/5 "2015-04-09T22:37:12Z")

</div>

I would also like to know this. I have previously tried to template playbooks using Jinja2, without success. I would like to ask again: wouldn’t it be super if Ansible’s playbooks were _first_ run through Jinja2, so that we could use all of Jinja’s features to customise some parts of playbooks?

Anand

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [April 9, 2015, 11:13pm UTC](https://forum.ansible.com/t/create-variable-as-dict-using-jinja2-within-playbook/16565/6 "2015-04-09T23:13:45Z")

</div>

> wouldn't it be super if Ansible's playbooks were \*first\* run through Jinja2, so that  
> we could use all of Jinja's features to customise some parts of playbooks?

No.

short answer: it defeats the simplicity goal

---

<div class="post-metadata">

**Author:** ![Steve\_Jacobs](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@Steve\_Jacobs](https://forum.ansible.com/u/Steve_Jacobs)\
**Post date:** [April 9, 2015, 11:15pm UTC](https://forum.ansible.com/t/create-variable-as-dict-using-jinja2-within-playbook/16565/7 "2015-04-09T23:15:57Z")

</div>

Sure I understand why not to do this. My question is why does one way work (arrays) and the other way (dicts) not work. Simple question, I can’t find an answer to it.

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [April 9, 2015, 11:16pm UTC](https://forum.ansible.com/t/create-variable-as-dict-using-jinja2-within-playbook/16565/8 "2015-04-09T23:16:42Z")

</div>

The answer is that neither returns what you think it does, both return  
a string, the issue is that with some fields they expect a string or  
array or array in string (which then they split with , to get a real  
array). Fields that expect dicts do not do any magic nor expect  
strings at any point.

---

<div class="post-metadata">

**Author:** ![Nehal\_J\_Wani](https://avatars.discourse-cdn.com/v4/letter/n/a9a28c/32.png) [@Nehal\_J\_Wani](https://forum.ansible.com/u/Nehal_J_Wani)\
**Post date:** [February 11, 2017, 7:34pm UTC](https://forum.ansible.com/t/create-variable-as-dict-using-jinja2-within-playbook/16565/9 "2017-02-11T19:34:39Z")

</div>

I know this is 2 year old thread, but I bumped into this today and was able to create a dictionary. Something like this:

/tmp $ cat example.yml

- hosts: 127.0.0.1

vars:  
app\_servers: 5  
ipaddress\_base: “192.168.0”  
rmi\_portbase: 10000  
host\_info: |  
{% set res = -%}  
{%- for number in range(1,app\_servers + 1) -%}  
{% set ignored = res.extend([{  
‘hostname’: ‘app’ + number|string,  
‘ipaddress’: ipaddress\_base + ‘.’ + number|string,  
‘rmi\_port’: rmi\_portbase|int + ( number \* 10)  
}]) -%}  
{%- endfor %}  
{{ res }}

tasks:

- debug: var=host\_info  
/tmp $ ansible-playbook example.yml  
[WARNING]: provided hosts list is empty, only localhost is available

PLAY [127.0.0.1] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

TASK [setup] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [127.0.0.1]

TASK [debug] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [127.0.0.1] =\> {  
“host\_info”: [  
{  
“hostname”: “app1”,  
“ipaddress”: “192.168.0.1”,  
“rmi\_port”: 10010  
},  
{  
“hostname”: “app2”,  
“ipaddress”: “192.168.0.2”,  
“rmi\_port”: 10020  
},  
{  
“hostname”: “app3”,  
“ipaddress”: “192.168.0.3”,  
“rmi\_port”: 10030  
},  
{  
“hostname”: “app4”,  
“ipaddress”: “192.168.0.4”,  
“rmi\_port”: 10040  
},  
{  
“hostname”: “app5”,  
“ipaddress”: “192.168.0.5”,  
“rmi\_port”: 10050  
}  
]  
}

PLAY RECAP \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0
