Saturday, August 31, 2019

Checking duplicate interfaces or addresses in Ansible

Consider the scenario that you have the following variable consisting of information about the uplink ports of a router.

uplink_ports:
    - {port: "Te0/0/26", ip: 10.10.10.11/31, peer_name: neighbor1, peer_port: Gi0/0/2 }
    - {port: "Te0/0/27", ip: 10.10.10.13/31, peer_name: neighbor2, peer_port: Gi0/0/2 }

Before proceeding to config generation and application on the router, it's a good idea to check for duplicates. Very often, usually when we copy paste, we forget to change all the parameters and this may result in unexpected failures on the network.

One of the approaches is to check for duplicates using the 'assert' module. You actually ask Ansible to check certain conditions and report back, either with a success or a fail message.

  - name: Check uplink ports for duplicates
    assert:
      that: uplink_ports|map(attribute='port')|list|length  == uplink_ports|map(attribute='port')|list|unique|length
      fail_msg: "Duplicates exist in your uplink ports variable. Please revise."
    delegate_to: localhost
    changed_when: false

The tricky part here is the condition you specify to the function. As you see we compare
"uplink_ports|map(attribute='port')|list|length" to "uplink_ports|map(attribute='port')|list|unique|length", but what does it mean?


  • map(attribute='port')|list ==> Will produce a list of items including only the 'port' key of our variable
  • unique ==> Will remove all the duplicates from the previous list
  • length ==> Will calculate the length of the list
So, we compare the length of the list to the length of the same list after having removed the duplicates. This means if our variable had duplicates in the first place, the length of the lists won't match. If no duplicates existed, the length would be the same before and after the 'unique' operation.

You can actually assert multiple conditions at once. If you want to check both the 'port' and the 'ip' keys for duplicates you can do the following.


  - name: Check uplink ports for duplicates
    assert:
      that: 
       - uplink_ports|map(attribute='port')|list|length  == uplink_ports|map(attribute='port')|list|unique|length
       - uplink_ports|map(attribute='ip')|list|length  == uplink_ports|map(attribute='ip')|list|unique|length
      fail_msg: "Duplicates exist in your uplink ports variable. Please revise."
    delegate_to: localhost
    changed_when: false

No comments:

Post a Comment