D. Seah
D. Seah

Reputation: 4592

ansible get result from role and append to a list

I have a play like this

---
- name: List images in ACRs
  any_errors_fatal: true
  hosts:
    - localhost
  gather_facts: false

  vars:
    acrs: ["registry1", "registry2"]

  tasks:
    - name: list repos
      with_items: "{{ acrs }}"
      include_role:
        name: list_docker_image_repos
      vars:
        registry_name: "{{ item }}"

list_docker_image_repos will do set_fact which a list of dicts. How can I append all the facts (from every iteration) to a list?

Or is there are different way to do this?

thanks

Upvotes: 2

Views: 921

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 68024

In each iteration put the list into a dictionary. For example, given the role

shell> cat roles/list_docker_image_repos/tasks/main.yml
- set_fact:
    docker_image_repos: "{{ ['repo1', 'repo2', 'repo3']|
                            product([registry_name])|
                            map('join', '-')|
                            list }}"
- set_fact:
    my_lists: "{{ my_lists|
                  combine({registry_name: docker_image_repos}) }}"

the playbook

- hosts: localhost

  vars:

    acrs: [reg1, reg2]
    my_lists: {}

  tasks:

    - name: list repos
      include_role:
        name: list_docker_image_repos
      loop: "{{ acrs }}"
      vars:
        registry_name: "{{ item }}"

    - debug:
        var: my_lists

gives the dictionary

my_lists:
  reg1:
    - repo1-reg1
    - repo2-reg1
    - repo3-reg1
  reg2:
    - repo1-reg2
    - repo2-reg2
    - repo3-reg2

A dictionary is a more suitable structure for this purpose compared with a list. There are many ways how to use it. For example, you can

  • extract the lists
    - debug:
        msg: "{{ acrs|map('extract', my_lists)|list }}"

gives

msg:
  - - repo1-reg1
    - repo2-reg1
    - repo3-reg1
  - - repo1-reg2
    - repo2-reg2
    - repo3-reg2
  • Use the filter flatten to put all items into a single list
    - debug:
        msg: "{{ acrs|map('extract', my_lists)|flatten }}"

gives

msg:
  - repo1-reg1
  - repo2-reg1
  - repo3-reg1
  - repo1-reg2
  - repo2-reg2
  - repo3-reg2
  • Use the filter dict2items to iterate items
    - debug:
        var: item
      loop: "{{ my_lists|dict2items }}"

gives (abridged)

  item:
    key: reg1
    value:
    - repo1-reg1
    - repo2-reg1
    - repo3-reg1

  item:
    key: reg2
    value:
    - repo1-reg2
    - repo2-reg2
    - repo3-reg2
  • Or, use the lookup plugin subelements to iterate the items of the lists as well
    - debug:
        var: item
      with_subelements:
        - "{{ my_lists|dict2items }}"
        - value

gives (abridged)

  item:
  - key: reg1
  - repo1-reg1

  item:
  - key: reg1
  - repo2-reg1

  item:
  - key: reg1
  - repo3-reg1

  item:
  - key: reg2
  - repo1-reg2

  item:
  - key: reg2
  - repo2-reg2

  item:
  - key: reg2
  - repo3-reg2

Example of a complete playbook for testing

- hosts: localhost

  vars:

    acrs: [reg1, reg2]
    my_lists: {}

  tasks:

    - name: list repos
      include_role:
        name: list_docker_image_repos
      loop: "{{ acrs }}"
      vars:
        registry_name: "{{ item }}"

    - debug:
        var: my_lists
    - debug:
        msg: "{{ acrs|map('extract', my_lists)|list }}"
    - debug:
        msg: "{{ acrs|map('extract', my_lists)|flatten }}"
    - debug:
        var: item
      loop: "{{ my_lists|dict2items }}"
    - debug:
        var: item
      with_subelements:
        - "{{ my_lists|dict2items }}"
        - value

Upvotes: 2

Related Questions