Double iteration in Ansible

Viewed 39

How can I iterate by list of dictionaries and assign each list from key of dictionary to with_items and iterate by this list: For example:

- name: "Deploy"
  template:
    src: "myfile"
    dst: "{{ item }}/myfile"    //"item" is "mypath1", "mypath2"..
  with_items: {{ item.paths }}
  loop:
  - {group: "mygroup1", paths: ["mypath1", "mypath2"]}
  - {group: "mygroup2", paths: ["mypath3", "mypath4"]}
  when: "{{ item.group }} in group_names"
1 Answers

Use with_subelements. For example, given the inventory

shell> cat hosts
[mygroup1]
srv1
[mygroup2]
srv2

The playbook

shell> cat pb1.yml
- hosts: srv1,srv2
  tasks:
    - name: Deploy
      debug:
        msg: "{{ inventory_hostname }}: Create myfile at {{ item.1 }}/myfile"
      with_subelements:
        - "{{ _list }}"
        - paths
      when: item.0.group in group_names
      vars:
        _list:
          - {group: mygroup1, paths: [mypath1, mypath2]}
          - {group: mygroup2, paths: [mypath3, mypath4]}

gives

  msg: 'srv1: Create myfile at mypath1/myfile'
  msg: 'srv1: Create myfile at mypath2/myfile'
  msg: 'srv2: Create myfile at mypath3/myfile'
  msg: 'srv2: Create myfile at mypath4/myfile'

You'll be better off with a dictionary, instead of a list. For example, the playbook below gives the same results using a simple loop

shell> cat pb2.yml
- hosts: srv1,srv2
  tasks:
    - name: Deploy
      debug:
        msg: "{{ inventory_hostname }}: Create myfile at {{ item }}/myfile"
      loop: "{{ group_names|map('extract', _dict)|flatten }}"
      vars:
        _dict:
          mygroup1: [mypath1, mypath2]
          mygroup2: [mypath3, mypath4]

But, the Ansible-way would be to put the data into the group_vars. For example

shell> cat group_vars/mygroup1.yml 
my_paths: [mypath1, mypath2]

shell> cat group_vars/mygroup2.yml 
my_paths: [mypath3, mypath4]

and the simple playbook below give the same results

shell> cat pb3.yml
- hosts: srv1,srv2
  tasks:
    - name: Deploy
      debug:
        msg: "{{ inventory_hostname }}: Create myfile at {{ item }}/myfile"
      loop: "{{ my_paths }}"
Related