Ansible Pattern: Templated Dictionary Keys

Except for cases like set_fact where this functionality has been specifically implemented, Ansible does not template dictionary keys. This means you cannot do things like this:

- name: Create a frobnitz
  frobnitz:
    frobnicators:
      "{{ foo }}": bar

Templating Dictionaries

As a workaround you can template the entire dictionary. In the simplest cases it isn’t unbearably ugly to do this inline:

- name: Create a frobnitz
  frobnitz:
    frobnicators: "{{ { foo: 'bar' } }}"

However, for even moderately complex structures it quickly becomes a pain to keep track of the Jinja data structure syntax when you’re more used to reading and writing YAML:

- name: Create a complicated frobnitz
  frobnitz:
    frobnicators: "{{ {
        foo: 'bar',
        'foo2': {
          'bar': 'baz',
        },
        'foo3': bar,
      } }}"

This is where I might use task vars to break the structure up into more readable declarations:

- name: Create a complicated frobnitz
  frobnitz:
    frobnicators: "{{ frobnicators | combine(t_frobnicators) }}"
  vars:
    frobnicators:
      foo2:
        bar: baz
      foo3: "{{ bar }}"
    t_frobnicators: "{{ { foo: 'bar' } }}"

Templating Lists

You can also employ more roundabout options, like creating a list with templated values that is easily transformable into a dictionary:

- name: Create a complicated frobnitz
  frobnitz:
    frobnicators: "{{ frobnicators | items2dict }}"
  vars:
    frobnicators:
      - key: "{{ foo }}"
        value: bar
      - key: foo2
        value:
          bar: baz
      - key: foo3
        value: "{{ bar }}"

Templating Strings

Another approach I’ve seen is to use Ansible’s key=value syntax (which is automatically converted to a dictionary in many, but not all, cases) instead of YAML:

- name: Create an intermediate frobnitz
  frobnitz:
    frobnicators: "{{ foo }}=bar foo3={{ bar }}"

This has limitations that aren’t present with proper data structures, but it can still be useful.