Using jinja to append to a fact in Ansble

Viewed 120

I am trying to append to a list:

- name: Set found
  set_fact:
    found: |
      {% set j2found = [ 'hi' ] %}
        {%- for user in "1", "2" -%}
          {% set j2found = j2found + [ user ] %}
        {%- endfor %}
      {{ j2found }}

- name: Show found
  debug:
    msg: "WHAT I FOUND: {{ item }}"
  loop: "{{ found }}"

found contains only 'hi'. Why doesn't that variable get appended to? I'm doing something obvious and wrong, but I can't find it.

Thanks.

EDIT: The answers below show the preferable and simpler way to add to my list, and larsks is correct about the scope of the variable. So there's no way to do this with a set statement. But one can append to a list in jinja2 thusly:

set junk = j2found.append(user)

junk, of course, contains nothing useful and is ignored.

2 Answers

Take a look at the Jinja documentation on assignments. Quoting:

Please keep in mind that it is not possible to set variables inside a block and have them show up outside of it. This also applies to loops.

The {% set j2found = j2found + [ user ] %} inside your for loop is scoped to the body of the loop; any changes to j2found are not visible outside the loop.

The way you would normally do something like this is via an Ansible loop:

- hosts: localhost
  gather_facts: false
  tasks:
    - name: Set found
      set_fact:
        found: "{{ found + [item] }}"
      loop:
        - 1
        - 2
      vars:
        found: ["hi"]

    - name: Show found
      debug:
        msg: "WHAT I FOUND: {{ item }}"
      loop: "{{ found }}"

Which will output:

PLAY [localhost] ***************************************************************

TASK [Set found] ***************************************************************
ok: [localhost] => (item=1)
ok: [localhost] => (item=2)

TASK [Show found] **************************************************************
ok: [localhost] => (item=hi) => {
    "msg": "WHAT I FOUND: hi"
}
ok: [localhost] => (item=1) => {
    "msg": "WHAT I FOUND: 1"
}
ok: [localhost] => (item=2) => {
    "msg": "WHAT I FOUND: 2"
}

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

Simply add the lists. For example

    - name: Set found
      set_fact:
        found: "{{ j2found + users }}"
      vars:
        j2found: ['hi']
        users: [1, 2]
    - name: Show found
      debug:
        msg: "WHAT I FOUND: {{ item }}"
      loop: "{{ found }}"

gives

  msg: 'WHAT I FOUND: hi'
  msg: 'WHAT I FOUND: 1'
  msg: 'WHAT I FOUND: 2'
Related