Templates & looping on json data structure

Hello,

I have a data structure gathered from a postgres db (external inventory) with a list of json data structures as follows :

[
{‘name’: conf1, ‘myvar1’: 1, ‘myvar2’: blabla},
{‘name’: conf2, ‘myvar1’: 44, ‘myvar2’: hello}
]

And i would like to use a kind of loop to create a file like :

[conf1]
param1 = 1
param2 = blabla

[conf2]
param1 = 44
param2 = hello

I’ve read in the ansible
"
ansible allows Jinja2 loops and conditionals in templates, but in playbooks, we do not use them. Ansible templates are pure machine-parseable YAML. This is an rather important feature as it means it is possible to code-generate pieces of files, or to have other ecosystem tools read Ansible files. Not everyone will need this but it can unlock possibilities.

"

Is there a way to perform that kind of loops please ?

Regards,
Smana

my current script generates this output :

{
“databases”: {
“hosts”: ,
“vars”: {}
},
“webservers”: {
“hosts”: [
“10.18.2.1”,
“10.18.2.2”,
],
“vars”: {}
},
“Site”: {
“children”: [
“databases”,
“webservers”
],
“vars”: [
{
“id”: 4912,
“path”: “test1.mp3”,
}

{
“id”: 4913,
“path”: “test2.mp3”,
}

]
}
}

But i got this error when executing ansible :

/etc/ansible/services/mysite 0 # ansible all -i ./inventory.py

Traceback (most recent call last):
File “/usr/bin/ansible”, line 157, in
(runner, results) = cli.run(options, args)
File “/usr/bin/ansible”, line 79, in run
inventory_manager = inventory.Inventory(options.inventory)
File “/usr/lib/python2.7/dist-packages/ansible/inventory/init.py”, line 101, in init
self.parser = InventoryScript(filename=host_list)
File “/usr/lib/python2.7/dist-packages/ansible/inventory/script.py”, line 47, in init
self.groups = self._parse(stderr)
File “/usr/lib/python2.7/dist-packages/ansible/inventory/script.py”, line 92, in _parse
for k, v in data[‘vars’].iteritems():
AttributeError: ‘list’ object has no attribute ‘iteritems’

I need to iterate on a list of several variables.
Do you think that’s possible ?

Regards,
Smana

Any idea please ?

Regards,
Smana

Smain,

Although full jinja2 templating is not available in tasks/playbooks, other features like pipes/filters are.Try piping your datastructure with to_json like

  • name: do a thing
    copy: src=“{{item}}” dest=/foo
    with_items: {{output | to_json}}

I used something like this as well, where _requested_hosts was a dict passed in to a task like
[main.yml]

  • include: { playbook.yml, _requested_hosts: {{some_dict_defined_in_vars_main.yml}} }

[playbook.yml]

  • debug: msg=“{{_requested_hosts | to_json | capture(requested_hosts)}}”

The problem is that passing structures between playbook files seems to serialize it, and this deserializes it.

kesten

I don’t endorse the above suggestion by Kesten, and I’m pretty sure it’s not going to work :slight_smile:

You have a list data structure so iteritems isn’t a method on a list.

If you just want to generate the config file I would do this as a template module:

(WARNING: untested general idea)

{% for entry in foo %}
{% for (k,v) in entry.iteritems() %}
{% if k == ‘name’ %}
[{{ v }}]
{% endif %}
{% endfor %}

{% for (k,v) in entry.iteritems() %}
{% if k != ‘name’ %}
{{ k }}={{ v }}
{% endif %}
{% endfor %}

{% endfor %}

  • template: src=foo.j2 dest=wherever.out

Note that I’m answering your first question and not your second – your variable structures are different in each.

Hello all,

For information i managed to do what i wanted.
i just changed my list into a dictionnary :

mylist = [ {‘name’: conf1, ‘myvar1’: 1, ‘myvar2’: blabla}, {‘name’: conf2, ‘myvar1’: 44, ‘myvar2’: hello} ]
mydict = { mylist }

then i used this dictionnary in my playbook as follows :

  • name: foo configuration
    template: src=foo.cfg dest=/etc/foo/{{ item[‘name’] }}.sh
    with_items: $mydict

the “item” variable can also be use inside the template.

Thanks for your help.

Regards

No need for the legacy variable here, BTW, just do this:

with_items: mydict