DDStackoverflow
DDStackoverflow

Reputation: 643

Ansible/Jinja templating

I am looking to set a fact with its constituent being a dictionary but in below code my_dict_var

is rendering as a string although I want it to be a dictionary.

- set_fact:
    my_fact: "{{ my_fact | default({}) | combine( my_dcit_var ) }}"
  vars:
    my_dcit_var: { "{{ item }}" : ['some string value'] }
  with_items:
    - 1
    - 2
    - 3

I am expecting final result should be. {1: ['some string value'], 2: ['some string value'], 3: ['some string value']} could someone point out my mistake.

Upvotes: 0

Views: 199

Answers (2)

Moon
Moon

Reputation: 3037

The part { "{{ item }}" : ['some string value'] } creates a dict with same key "{{ item }}" as a literal string instead of a variable for each item in the loop. So, combine overwrites the dict key:value pair with the latest pair every time. Here is how you can fix it,

- set_fact:
    my_fact: "{{ my_fact | default({}) | combine( my_dict_var ) }}"
  vars:
    my_dict_var: "{{ { item : ['some string value'] } }}"
  with_items:
    - 1
    - 2
    - 3

or, simply

- set_fact:
    my_fact: "{{ my_fact | default({}) | combine( { item: ['some string value'] } ) }}"
  with_items:
    - 1
    - 2
    - 3

Ansible also recommends use of loop instead of with_ lookup where possible. Here is an example using loop and specified key:value pairs.

- set_fact:
    my_fact: "{{ my_fact | default({}) | combine( { item.key: item.val } ) }}"
  loop:
    - { key: 1, val: ['some string value1'] }
    - { key: 2, val: ['some string value2'] }
    - { key: 3, val: ['some string value3'] }

Upvotes: 3

Vladimir Botka
Vladimir Botka

Reputation: 67959

The filter dict serves the purpose of creating a dictionary from a list of key-value pairs. Let's use filter product to create the list. For example

    - set_fact:
        my_fact: "{{ dict(list1|product(list2)) }}"
      vars:
        list1:
          - 1
          - 2
          - 3
        list2:
          - ['some string value']
    - debug:
        var: my_fact
    - debug:
        msg: "{{ my_fact|to_json }}"

gives the expected result

  my_fact:
    1:
    - some string value
    2:
    - some string value
    3:
    - some string value

  msg: '{"1": ["some string value"], "2": ["some string value"], "3": ["some string value"]}'

Below is an example of how to use filter zip to create a dictionary from two lists. For example

    - set_fact:
        my_fact: "{{ dict(list1|zip(list2)) }}"
      vars:
        list1:
          - 1
          - 2
          - 3
        list2:
          - [value-1a, value-1b, value-1c]
          - [value-2a, value-2b, value-2c]
          - [value-3a, value-3b, value-3c]
    - debug:
        var: my_fact

gives

  my_fact:
    1:
    - value-1a
    - value-1b
    - value-1c
    2:
    - value-2a
    - value-2b
    - value-2c
    3:
    - value-3a
    - value-3b
    - value-3c

Upvotes: 0

Related Questions