pythonjsonloopsdictionaryansible

How to Iterate Over Nested Lists of Varying Length in Ansible Loop?


When trying to iterate over this data from an ansible debug output I'm only able to iterate over the first element of the index which is zero 0. I would like to iterate over all of the elements. Below is a sample of the output coming out of ansible and below the output is the ansible tasks I'm working with.

{
    "ansible_loop_var": "item",
    "item": {
        "key": "SwitchName",
        "value": [
            {
                "key": "1",
                "value": {
                    "cdp": {
                        "address": "192.168.16.225",
                        "deviceId": "482ef8200",
                        "portId": "Port C9300",
                        "sourcePort": "1"
                    },
                    "lldp": {
                        "managementAddress": "192.168.16.225",
                        "portId": "2",
                        "sourcePort": "1",
                        "systemName": "**LAB-Remote-1**"
                    }
                }
            },
            {
                "key": "4",
                "value": {
                    "cdp": {
                        "address": "10.22.89.16",
                        "deviceId": "12efa487400",
                        "portId": "Port 1",
                        "sourcePort": "4"
                    },
                    "lldp": {
                        "managementAddress": "10.22.89.16",
                        "portId": "1",
                        "sourcePort": "4",
                        "systemName": "C9300"
                    }
                }
            },
            {
                "key": "5",
                "value": {
                    "cdp": {
                        "address": "172.16.254.56",
                        "deviceId": "f43fc84af710",
                        "portId": "Port 1",
                        "sourcePort": "5"
                    },
                    "lldp": {
                        "managementAddress": "172.16.254.56",
                        "portId": "1",
                        "sourcePort": "5"
                    }
                }
            },
            {
                "key": "6",
                "value": {
                    "cdp": {
                        "address": "10.254.255.216",
                        "deviceId": "4835187cff00",
                        "portId": "Port 50",
                        "sourcePort": "6"
                    },
                    "lldp": {
                        "managementAddress": "10.254.255.216",
                        "portId": "50",
                        "sourcePort": "6"
                    }
                }
            }
        ]
    }
}

Here is the code that I'm using looks like and in my task example I'm printing the 0 index of the list, and it returns the data fine, but I want to print all elements of the list, and the list size will vary.

- name: print out lldp port data
  debug:
    var: item.value.0.value.lldp.systemName
  loop: "{{cdp_lldp_by_switch | dict2items}}"

This task will print out LAB-Remote-1 since its 0 in the list.


Solution

  • I discovered that using a nested loop configuration is the best approach to handle this situation.

    I implemented the following solution:

    Outer Loop: I use include_tasks to call another task file and loop over each switch.

    Inner Loop: In the inner loop, I calculate the length of the list and then iterate over the list elements.

    This approach was inspired by this YouTube video [Using Nested Loops In Ansible], which was very helpful in solving the issue.

    https://www.youtube.com/watch?v=89Yhc4P_Ggc&lc=Ugx48QKBqkZWx1zWN9B4AaABAg.A7_XCM8LlODA7a3V9_r4_L

      outer loop task:
    - name: Include task for nested loop
      include_tasks: ./inner_loop.yml
      loop: "{{ cdp_lldp_by_switch | dict2items }}"
      loop_control:
        loop_var: current_switch
    
    
      inner loop task:
    - name: Set port list length
      set_fact:
        port_len: "{{ current_switch.value | length | default(0) }}"
    
    - name: Print out inner loop
      debug:
        msg: "{{ current_switch.value[item].value.lldp.systemName | default('none') }}:{{ current_switch.value[item].value.lldp.sourcePort | default('none') }}"
      loop: "{{ range(0, port_len | int) }}"
      loop_control:
        loop_var: item