Zach
Zach

Reputation: 25

How can nest loops inside of module functions in ansible?

Hopefully I worded this question correctly.

I have a group_vars file that defines the following:

etherchannels:
  access2:
    - channelnumber: 1
      interfaces:
        - FastEthernet 1/14
        - FastEthernet 1/15
  access1:
    - channelnumber: 1
      interfaces:
        - FastEthernet 1/14
        - FastEthernet 1/15

And my playbook looks like this:

- name: LAN Switches
  hosts: access

  tasks:
  - name: config unused access ports
    cisco.ios.ios_lag_interfaces:
      config:
      - name: "{{ item.channelnumber }}"
        members:
        - member: "{{ item.interface }}"
          mode: on
    loop: "{{ etherchannels[inventory_hostname] }}"

The expected outcome is:

  1. ansible will run through the task for each hostnames under etherchannels(access 1 and 2)
  2. for each hostnames it would run the "name" function, defining the etherchannel and then
  3. for each etherchannel it would run the "members" function and add every listed interface

So it would function something like this, assuming I added more etherchannels:

name: 1
 members:
 - member: FastEthernetX
   mode: on
 - member: FastEthernetY
   mode: on
name: 2
 members: 
 - member: FastEthernetZ
   mode: on
 - member: FastEthernetA
   mode: on

I've tried to add a loop inside the "cisco.ios.ios_lag_interfaces" module command but no dice.

Upvotes: 1

Views: 82

Answers (1)

larsks
larsks

Reputation: 312148

This looks like a job for the subelements filter. In the following example, I've wrapped your task in a debug task so that I can run it locally and demonstrate the concept:

- hosts: all
  gather_facts: false
  vars:
    etherchannels:
      access2:
        - channelnumber: 1
          interfaces:
            - FastEthernet 1/14
            - FastEthernet 1/15
      access1:
        - channelnumber: 1
          interfaces:
            - FastEthernet 1/14
            - FastEthernet 1/15
  tasks:
    - debug:
        msg: |
          cisco.ios.ios_lag_interfaces:
            config:
            - name: "{{ item.0.channelnumber }}"
              members:
              - member: "{{ item.1 }}"
                mode: on
      loop: "{{ etherchannels[inventory_hostname]|subelements('interfaces') }}"

If I run the above playbook, the output looks like:

TASK [debug] ******************************************************************************************************************************************************************************************************
ok: [access1] => (item=[{'channelnumber': 1, 'interfaces': ['FastEthernet 1/14', 'FastEthernet 1/15']}, 'FastEthernet 1/14']) => {
    "msg": "cisco.ios.ios_lag_interfaces:\n  config:\n  - name: \"1\"\n    members:\n    - member: \"FastEthernet 1/14\"\n      mode: on\n"
}
ok: [access2] => (item=[{'channelnumber': 1, 'interfaces': ['FastEthernet 1/14', 'FastEthernet 1/15']}, 'FastEthernet 1/14']) => {
    "msg": "cisco.ios.ios_lag_interfaces:\n  config:\n  - name: \"1\"\n    members:\n    - member: \"FastEthernet 1/14\"\n      mode: on\n"
}
ok: [access1] => (item=[{'channelnumber': 1, 'interfaces': ['FastEthernet 1/14', 'FastEthernet 1/15']}, 'FastEthernet 1/15']) => {
    "msg": "cisco.ios.ios_lag_interfaces:\n  config:\n  - name: \"1\"\n    members:\n    - member: \"FastEthernet 1/15\"\n      mode: on\n"
}
ok: [access2] => (item=[{'channelnumber': 1, 'interfaces': ['FastEthernet 1/14', 'FastEthernet 1/15']}, 'FastEthernet 1/15']) => {
    "msg": "cisco.ios.ios_lag_interfaces:\n  config:\n  - name: \"1\"\n    members:\n    - member: \"FastEthernet 1/15\"\n      mode: on\n"
}

I think that's exactly what you were looking for. Your actual task would of course drop the debug wrapper:

- hosts: all
  gather_facts: false
  vars:
    etherchannels:
      access2:
        - channelnumber: 1
          interfaces:
            - FastEthernet 1/14
            - FastEthernet 1/15
      access1:
        - channelnumber: 1
          interfaces:
            - FastEthernet 1/14
            - FastEthernet 1/15
  tasks:
    = cisco.ios.ios_lag_interfaces:
        config:
        - name: "{{ item.0.channelnumber }}"
          members:
          - member: "{{ item.1 }}"
            mode: on
      loop: "{{ etherchannels[inventory_hostname]|subelements('interfaces') }}"

Upvotes: 1

Related Questions