Append dict to list in Ansible

I’m having a problem when trying to append a dict to a list in Ansible.

My code:

- name: Initialize list for numbers
  ansible.builtin.set_fact:
    numbers: [123, 456, 789]

- name: Initialize list of objects
  ansible.builtin.set_fact:
    resources: []

- name: Initialize object
  ansible.builtin.set_fact:
    resource: {}

- name: Creating object for reference
  ansible.builtin.set_fact:
    resource:
      - projectRef:
          external: 'projects/{{ item }}'
    resources: "{{ resources + [ resource ] }}"
  loop: "{{ numbers }}"

And the output looks like so:

[
  {},
  [
    {
      'projectRef': {
        'external': 'projects/123'
      }
    }
  ],
  [
    {
      'projectRef': {
        'external': 'projects/456'
      }
    }
  ]
]

The first issue is that it omits the first value in the numbers list. Moreover I was expecting the output to be a list of dicts, not a list of lists. More like so:

[
    {
      'projectRef': {
        'external': 'projects/123'
      }
    },
    {
      'projectRef': {
        'external': 'projects/456'
      }
    },
    {
      'projectRef': {
        'external': 'projects/789'
      }
    }
]

It is simpler to declare the list

  resources: "{{ ['project']|product(numbers)|map('join', "https://stackoverflow.com/")|
                 map('community.general.dict_kv', 'external')|
                 map('community.general.dict_kv', 'projectRef') }}"

gives what you want

  resources:
  - projectRef:
      external: project/123
  - projectRef:
      external: project/456
  - projectRef:
      external: project/789

Optionally, you can use Jinja. The below declaration gives the same result

  resources: |
    [{% for i in numbers %}
    {"projectRef": {"external": "projects/{{ i }}"}},
    {% endfor %}]

Example of a complete playbook for testing

- hosts: all

  vars:

    numbers: [123, 456, 789]
    resource1: "{{ ['project']|product(numbers)|map('join', "https://stackoverflow.com/")|
                   map('community.general.dict_kv', 'external')|
                   map('community.general.dict_kv', 'projectRef') }}"
    resource2: |
      [{% for i in numbers %}
      {"projectRef": {"external": "projects/{{ i }}"}},
      {% endfor %}]
    
  tasks:


    - debug:
        var: resource1
    - debug:
        var: resource1.1.projectRef.external

    - debug:
        var: resource2
    - debug:
        var: resource2.1.projectRef.external

Leave a Comment