Score:1

Ansible : Loop inside loop

ga flag

On ansible [core 2.13.3] my var.yml file is like this :

vlans:
  Servers:
    vlan_id: 10
    ip: 192.168.22.20
    mask: 255.255.255.0
    mode:
      tagged: 1/1,1/2
      untagged: 1/3
  Clients:
    vlan_id: 20
    mode:
      tagged: 1/1,1/3
  Printers:
    vlan_id: 30

The objective is to launch one task for each elements in vlans (Servers, Clients, Printers...) and for each mode (tagged, untagged, forbid...).

I successful iterate on vlans but not in vlans and mode. I can't find the good way to success nested loop. Try everything like subelement, with_subelements, loop_nested without success.

  - name: Set member of vlan
    arubaoss_vlan:
      command: config_vlan_port
      config: "create"
      vlan_id: "{{ item.value.vlan_id }}"
      port_id: "{{ item.value.port | default('') }}"
      port_mode: "{{ item.value.mode | default('POM_UNTAGGED') | regex_replace('^tagged$', 'POM_TAGGED_STATIC') | regex_replace('^untagged$', 'POM_UNTAGGED') | regex_replace('^forbid$', 'POM_FORBIDDEN') }}"
      api_version: "{{ ansible_api_version }}"
      use_ssl: "{{ ansible_use_ssl }}"
      port: "{{ ansible_port }}"
      host: "{{ ansible_host }}"
      username: "{{ ansible_user }}"
      password: "{{ ansible_password }}"
    loop: "{{ lookup('dict', vlans) }}"
    when: "'port' in dict(item)"
    tags:
      - vlans
      - vlans_mode

How I can make nested loop in Ansible ?

  - name: Debug2
    debug:
      msg: "Name: {{ item.key }} - mode: {{ item.value.mode }}"
    loop: "{{ lookup('dict', vlans) }}"
    when: "'mode' in dict(item.value)"
    tags:
      - debug

Debug 2 return :

ok: [sw39stack01.group.corp] => (item={'key': 'Servers', 'value': {'vlan_id': 10, 'ip': '192.168.22.20', 'mask': '255.255.255.0', 'mode': {'tagged': '1/1,1/2', 'untagged': '1/3'}}}) => { "msg": "Name: Servers - mode: {'tagged': '1/1,1/2', 'untagged': '1/3'}" } ok: [sw39stack01.group.corp] => (item={'key': 'Clients', 'value': {'vlan_id': 20, 'mode': {'tagged': '1/1,1/3'}}}) => { "msg": "Name: Clients - mode: {'tagged': '1/1,1/3'}" } skipping: [sw39stack01.group.corp] => (item={'key': 'Printers', 'value': {'vlan_id': 30}}) => { "ansible_loop_var": "item", "item": { "key": "Printers", "value": { "vlan_id": 30 } } }

Best regards,

Score:2
br flag

Convert the dictionaries mode to lists

  modes: |
    {% for k,v in vlans.items() %}
    {{ k }}:
      mode: {{ v.mode|d({})|dict2items }}
    {% endfor %}
  vlans2: "{{ vlans|combine(modes|from_yaml, recursive=true) }}"

gives

  vlans2:
    Clients:
      mode:
      - key: tagged
        value: 1/1,1/3
      vlan_id: 20
    Printers:
      mode: []
      vlan_id: 30
    Servers:
      ip: 192.168.22.20
      mask: 255.255.255.0
      mode:
      - key: tagged
        value: 1/1,1/2
      - key: untagged
        value: 1/3
      vlan_id: 10

Convert the dictionary vlans2 to a list and iterate with subelements value.mode

    - debug:
        msg: "{{ item.0.key }} {{ item.1.key }} {{ item.1.value }}"
      loop: "{{ vlans2|dict2items|subelements('value.mode') }}"

gives (abridged)

  msg: Servers tagged 1/1,1/2
  msg: Servers untagged 1/3
  msg: Clients tagged 1/1,1/3

Example of a complete playbook

- hosts: localhost

  vars:

    vlans:
      Servers:
        vlan_id: 10
        ip: 192.168.22.20
        mask: 255.255.255.0
        mode:
          tagged: 1/1,1/2
          untagged: 1/3
      Clients:
        vlan_id: 20
        mode:
          tagged: 1/1,1/3
      Printers:
        vlan_id: 30

    modes: |
      {% for k,v in vlans.items() %}
      {{ k }}:
        mode: {{ v.mode|d({})|dict2items }}
      {% endfor %}
    vlans2: "{{ vlans|combine(modes|from_yaml, recursive=true) }}"

  tasks:

    - debug:
        var: modes|from_yaml
    - debug:
        var: vlans2
    - debug:
        msg: "{{ item.0.key }} {{ item.1.key }} {{ item.1.value }}"
      loop: "{{ vlans2|dict2items|subelements('value.mode') }}"
Score:0
ga flag

Inventory file are edited like this:

vlans:
  - name: Servers
    vlan_id: 10
    ip: 192.168.22.20
    mask: 255.255.255.0
    mode:
      - tagged: 1/1,1/2
      - untagged: 1/3
  - name: Clients
    vlan_id: 20
    mode:
      - tagged: 1/1,1/3
  - name: Printers
    vlan_id: 30

And query is used:

  - name: Debug1
    ansible.builtin.debug: var=item
    loop: "{{ query('subelements', vlans, 'mode', {'skip_missing': True}) }}"
    tags:
      - debug

Output work as expected:

ok: [sw] => (item=[{'name': 'Servers', 'vlan_id': 10, 'ip': '192.168.22.20', 'mask': '255.255.255.0'}, {'tagged': '1/1,1/2'}]) => {
    "ansible_loop_var": "item",
    "item": [
        {
            "ip": "192.168.22.20",
            "mask": "255.255.255.0",
            "name": "Servers",
            "vlan_id": 10
        },
        {
            "tagged": "1/1,1/2"
        }
    ]
}
ok: [sw] => (item=[{'name': 'Servers', 'vlan_id': 10, 'ip': '192.168.22.20', 'mask': '255.255.255.0'}, {'untagged': '1/3'}]) => {
    "ansible_loop_var": "item",
    "item": [
        {
            "ip": "192.168.22.20",
            "mask": "255.255.255.0",
            "name": "Servers",
            "vlan_id": 10
        },
        {
            "untagged": "1/3"
        }
    ]
}
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.