The first twenty interfaces.


From #network_to_code:

"hey guys, I have a situation where I am using ansible_net_interfaces and then later I want to pull the first 20 type: Gigabit Ethernet interfaces. Anyone have an idea as how to do this?"

Seems simple right?

The ios_facts module will collect interfaces and store them as ansible_net_interfaces.

- name: Get interfaces
  hosts: all
  connection: local
  gather_facts: no
  tasks:
    - name: Get facts
      ios_facts:
        host: "{{ inventory_hostname }}"
        gather_subset: "interfaces"

The issue is, ansible_net_interfaces is returned as a dictionary and appears to have been alphabetically sorted:

  /working ansible-playbook -i inventory.txt playbook.yml

PLAY [Get interfaces] **********************************************************

TASK [Get facts] ***************************************************************
ok: [router]

TASK [debug] *******************************************************************
ok: [router] => {
    "ansible_net_interfaces": {
        "FastEthernet1": {
            "bandwidth": 10000,
            "description": null,
            "duplex": null,
            "ipv4": null,
            "lineprotocol": "down ",
            "macaddress": "18e7.28b2.0841",
            "mediatype": null,
            "mtu": 1500,
            "operstatus": "down",
            "type": "RP management port"
        },
        "GigabitEthernet1/1": {
            "bandwidth": 1000000,
            "description": null,
            "duplex": null,
            "ipv4": null,
            "lineprotocol": "up (connected) ",
            "macaddress": "f07f.066c.e410",
            "mediatype": "10/100/1000-TX",
            "mtu": 1500,
            "operstatus": "up",
            "type": "Gigabit Ethernet Port"
        },
        "GigabitEthernet1/10": {
            "bandwidth": 1000000,
            "description": null,
            "duplex": null,
            "ipv4": null,
            "lineprotocol": "up (connected) ",
            "macaddress": "f07f.066c.e419",
            "mediatype": "10/100/1000-TX",
            "mtu": 1500,
            "operstatus": "up",
            "type": "Gigabit Ethernet Port"
        },

What if we need the first 20 Gb interfaces? ("type": "Gigabit Ethernet Port")?

This is where a custom filter can be handy. We'll need to parse out the slot and the interface and order them correctly. We need the first twenty interfaces in the chassis not the first twenty in ansible_net_interfaces:

filter_plugins/filters.py

import re

def collect_ints(interfaces, mtype, count):
    filtered = []
    for interface in interfaces:
        if interfaces[interface]['type'] == mtype:
            matches = re.search(r"(\d*)\/(\d*\.?\d+)", interface)
            interfaces[interface]['name'] = interface
            interfaces[interface]['slot'] = float(matches.group(1))
            interfaces[interface]['interface'] = float(matches.group(2))
            filtered.append(interfaces[interface])
    ordered = sorted(filtered, key = lambda x: (x['slot'], x['interface']))
    names = map(lambda x: x['name'], ordered)
    return names[0:count]

class FilterModule(object):
    def filters(self):
        return {'collect_ints': collect_ints}

ansible.cfg

[defaults]
filter_plugins = ./filter_plugins

playbook.yml

- name: Get interfaces
    hosts: all
    connection: local
    gather_facts: no
    tasks:
      - name: Get facts
        ios_facts:
          host: "{{ inventory_hostname }}"
          gather_subset: "interfaces"
      - set_fact:
          twenty: "{{ ansible_net_interfaces|collect_ints('Gigabit Ethernet Port', 20) }}"
      - debug: var=ansible_net_interfaces[item]['operstatus']
        with_items: "{{ twenty }}"

The result:

  /working ansible-playbook -i inventory.txt playbook.yml

PLAY [Get interfaces] **********************************************************

TASK [Get facts] ***************************************************************
ok: [router]

TASK [set_fact] ****************************************************************
ok: [router]

TASK [debug] *******************************************************************
ok: [router] => (item=GigabitEthernet1/1) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/1"
}
ok: [router] => (item=GigabitEthernet1/2) => {
    "ansible_net_interfaces[item]['operstatus']": "down",
    "item": "GigabitEthernet1/2"
}
ok: [router] => (item=GigabitEthernet1/3) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/3"
}
ok: [router] => (item=GigabitEthernet1/4) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/4"
}
ok: [router] => (item=GigabitEthernet1/5) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/5"
}
ok: [router] => (item=GigabitEthernet1/6) => {
    "ansible_net_interfaces[item]['operstatus']": "down",
    "item": "GigabitEthernet1/6"
}
ok: [router] => (item=GigabitEthernet1/7) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/7"
}
ok: [router] => (item=GigabitEthernet1/8) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/8"
}
ok: [router] => (item=GigabitEthernet1/9) => {
    "ansible_net_interfaces[item]['operstatus']": "down",
    "item": "GigabitEthernet1/9"
}
ok: [router] => (item=GigabitEthernet1/10) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/10"
}
ok: [router] => (item=GigabitEthernet1/11) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/11"
}
ok: [router] => (item=GigabitEthernet1/12) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/12"
}
ok: [router] => (item=GigabitEthernet1/13) => {
    "ansible_net_interfaces[item]['operstatus']": "down",
    "item": "GigabitEthernet1/13"
}
ok: [router] => (item=GigabitEthernet1/14) => {
    "ansible_net_interfaces[item]['operstatus']": "down",
    "item": "GigabitEthernet1/14"
}
ok: [router] => (item=GigabitEthernet1/15) => {
    "ansible_net_interfaces[item]['operstatus']": "down",
    "item": "GigabitEthernet1/15"
}
ok: [router] => (item=GigabitEthernet1/16) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/16"
}
ok: [router] => (item=GigabitEthernet1/17) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/17"
}
ok: [router] => (item=GigabitEthernet1/18) => {
    "ansible_net_interfaces[item]['operstatus']": "down",
    "item": "GigabitEthernet1/18"
}
ok: [router] => (item=GigabitEthernet1/19) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/19"
}
ok: [router] => (item=GigabitEthernet1/20) => {
    "ansible_net_interfaces[item]['operstatus']": "up",
    "item": "GigabitEthernet1/20"
}

PLAY RECAP *********************************************************************
router : ok=3    changed=0    unreachable=0    failed=0