MrDrMcCoy
MrDrMcCoy

Reputation: 366

How can one generate a dict in Jinja/Ansible as a var?

I need to dynamically generate a dict and assign it to an Ansible var so that the same data is available to every host and does not need to be regenerated on each one. This will be looped over by a task and template. It is possible to build lists by nesting Jinja in a var definition like so:

var_list: >
  [
    {% set data = [] %}
    {% for host in groups['all'] %}
    {{ data.append(host) }}
    {% endfor %}
    {{ data }}
  ]

However, I am not able to do so with dicts:

var_dict: >
  {
    {% set data = dict() %}
    {% for host in groups['all'] %}
    {{ data | combine({host: []}) }}
    {% endfor %}
    {{ data }}
  }

This results in a giant, garbled string: {u'host.subdom.dom.tld': []} {}...

What I am expecting is a var set to a true dict object that can have its components referenced individually (like {{ var_dict.host1[0] }}), with a structure similar to the following JSON:

{
  "host1": [],
  "host2": []
}

Is there a way to cause this to expand into a proper dict when assigned to the variable? Or is there perhaps another way to generate a dict from a loop without that awful set_fact hackery?

Upvotes: 2

Views: 6918

Answers (1)

techraf
techraf

Reputation: 68469

Either of your templates is broken (the first one produces nested lists, the second one prints data in loop with this expression {{ data | combine({host: []}) }}, the value of data remains empty until the end).


Jinja2 is a templating engine, you don't really need to create data structures to print them later. You can form your output directly.

For the list:

var_list: >
  [ {% for host in groups['all'] %}'{{ host }}',{% endfor %} ]

For the dictionary:

var_dict: >
  { {% for host in groups['all'] %}'{{ host }}': [],{% endfor %} }

As you expect the values to be interpreted by Ansible, you don't need to pay attention to the trailing coma, otherwise there is loop.last.

Upvotes: 2

Related Questions