sokolata
sokolata

Reputation: 549

Iterate over Variable in Jinja Template

I would like to iterate over a variable in ansible yaml and add key and value in jinja template

variable:

my:
    variable:
        - name: test
          path: /etc/apt
          cert: key.crt

my template

{% for key, value in item() %}
      {{key}}: {{value}}
{% endfor %}

ansible yaml

- name: test
  template:
    force: yes
    src: test.conf.j2
    dest: /tmp/test.conf"
  become: yes
  with_items:
    - "{{ my.variable }}"

How my yaml should look like:

path: /etc/apt
cert: key.crt

Upvotes: 3

Views: 2537

Answers (1)

β.εηοιτ.βε
β.εηοιτ.βε

Reputation: 39344

You actually have three issues in your task:

  1. When using a loop, may it be loop or all the flavour of with_* you access the element currently looped in with the variable item, so not a function like you used in your task (item())

  2. You are doing a superfluous list of list in

    with_items:
      - "{{ my.variable }}"
    

    A first step would be to do with_items: "{{ my.variable }}".
    An ever better step would be to use the loop replacement of the with_* syntax as suggested in the documentation

    We added loop in Ansible 2.5. It is not yet a full replacement for with_<lookup>, but we recommend it for most use cases.

    So you will end up with

    loop: "{{ my.variable }}"
    
  3. Then accessing properties of a dictionary in Jinja is done using the syntax

    {% for key, value in dict.items() %}
    

    Source: https://jinja.palletsprojects.com/en/2.11.x/templates/#for
    So in your case:

    {% for key, value in item.items() %}
    

All together, a working playbook demonstrating this would be:

- hosts: all
  gather_facts: no
      
  tasks:
    - debug:
        msg: |
          {% for key, value in item.items() %}
            {{key}}: {{value}}
          {% endfor %}
      loop: "{{ my.variable }}"
      vars:
        my:
          variable:
            - name: test
              path: /etc/apt
              cert: key.crt

That yields the result:

PLAY [all] *******************************************************************************************************

TASK [debug] *****************************************************************************************************
ok: [localhost] => (item={'name': 'test', 'path': '/etc/apt', 'cert': 'key.crt'}) => {
    "msg": "  name: test\n  path: /etc/apt\n  cert: key.crt\n"
}

PLAY RECAP *******************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Now you just have to reuse this in your template and loop and you should have what you expect.

Upvotes: 2

Related Questions