Skip to content
Mar 2 / Greg

Set Cisco Nexus Interface Description From CDP Using Ansible AAP


A customer recently asked about setting CDP neighbors as interface descriptions on their switches, which is actually a pretty cool idea. I thought, though, that I don’t want just anything set…ya know, like I don’t care if the neighbor is an IP phone, what I really care about are other switches. So I created a playbook that will find the CDP neighbors and set the interface description to that neighbor IF it is a switch.

Video Overview

Playbooks

First, you can find all of my playbooks in my public git repo here.

So the playbook is actually broken into two parts. One is the main playbook, and one is a task file used for looping.

Main playbook(cisco-nxos-cdp-interface.yml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
---
- name: set interface desc based on cdp neighbors
  hosts: nexus9k1
  gather_facts: false
  vars:
  tasks:
  - name: Gather all legacy facts
    cisco.nxos.nxos_facts:
      gather_subset: all
    register: gather_info
 
#  - name: debug gather_info
#    ansible.builtin.debug:
#      var: gather_info
 
#  - name: debug gather_info filtered
#    ansible.builtin.debug:
#      msg: "{{ item.key }} - {{ item.value.mode | default('nothing') }}"
#    loop: "{{ gather_info.ansible_facts.ansible_net_interfaces | dict2items | selectattr('value.mode','defined') | selectattr('value.mode','search','trunk') }}"
 
  - name: gather cdp neighbors
    nxos_command:
      commands: "show cdp neighbors | json"
    register: cdp_neighbors
 
 
#  - name: debug cdp_neighbors crazy filter stuff
##    when: gather_info.ansible_facts.ansible_net_interfaces | dict2items | selectattr('key','search',item.intf_id) | selectattr('value.mode','defined') | map(attribute='value.mode') | default('access') == 'trunk'
##    when: gather_info.ansible_facts.ansible_net_interfaces | dict2items | selectattr('key','search',item.intf_id) | selectattr('value.mode','defined') | map(attribute='value.mode') | default('access') == "trunk"
#    when: gather_info.ansible_facts.ansible_net_interfaces | dict2items | selectattr('key','equalto',item.intf_id) | selectattr('value.mode','defined') | map(attribute='value.mode') | default('access') == "trunk"
#    ansible.builtin.debug:
##      var: cdp_neighbors.stdout[0].TABLE_cdp_neighbor_brief_info
##      var: gather_info.ansible_facts.ansible_net_interfaces | dict2items | selectattr('key','search',item.intf_id) | selectattr('value.mode','defined') | map(attribute='value.mode') | default('access')
#      msg: "{{ device_id }} on {{ item.intf_id }}"
#    loop: "{{ cdp_neighbors.stdout[0].TABLE_cdp_neighbor_brief_info.ROW_cdp_neighbor_brief_info }}"
 
  - name: loop through cdp neighbors and call the task file to further search for trunks
    ansible.builtin.include_tasks:
      file: cisco-nxos-cdp-interface-taskfile.yml
    loop: "{{ cdp_neighbors.stdout[0].TABLE_cdp_neighbor_brief_info.ROW_cdp_neighbor_brief_info }}"
    loop_control:
      loop_var: cdp_loop

I’ll break it down into its pieces:

1
2
3
4
5
6
7
8
9
  - name: Gather all legacy facts
    cisco.nxos.nxos_facts:
      gather_subset: all
    register: gather_info
 
  - name: gather cdp neighbors
    nxos_command:
      commands: "show cdp neighbors | json"
    register: cdp_neighbors

These first two tasks are all about information gathering. On the very first task I’m using the nxos_facts module to gather information about the switch. While it pulls a lot of info, what I’m really interested in here is how the interfaces are configured, and in particular if the interface mode is set to access or trunk.
The second task issues a simple command via the nxos_command module “show cdp neighbors | json”. Here I’m piping the output to json, which means it will be saved in my “cdp_neighbors” variable directly as key/value pairs(which means it’s directly ready for me to reference without having to do any parsing).

Here’s the last task in the main playbook:

1
2
3
4
5
6
  - name: loop through cdp neighbors and call the task file to further search for trunks
    ansible.builtin.include_tasks:
      file: cisco-nxos-cdp-interface-taskfile.yml
    loop: "{{ cdp_neighbors.stdout[0].TABLE_cdp_neighbor_brief_info.ROW_cdp_neighbor_brief_info }}"
    loop_control:
      loop_var: cdp_loop

This task loops over the collected CDP neighbors, and for each one it will call the “cisco-nxos-cdp-interface-taskfile.yml” task file for further processing. Just remember that each time we hit the taskfile I’ll be processing a single CDP neighbor.

Now for the task file(cisco-nxos-cdp-interface-taskfile.yml):

1
2
3
4
5
6
7
8
- name: Update interface descpription when it's a trunk port using Merge
  when: item == "trunk"
  check_mode: true
  cisco.nxos.nxos_interfaces:
    config:
    - name: "{{ cdp_loop.intf_id }}"
      description: "{{ cdp_loop.device_id }} on {{ cdp_loop.port_id }}"
  loop: "{{ gather_info.ansible_facts.ansible_net_interfaces | dict2items | selectattr('key','equalto',cdp_loop.intf_id) | selectattr('value.mode','defined') | map(attribute='value.mode') | default('access') }}"

There is only a single task here, but I am doing some kungfu down in the loop section. Also note that I have “check_mode: true” set; I’m doing this because it is a demo I want to run multiple times and show interesting results, so I have it set to check mode so it won’t actually make the change, rather just show what it would do(in production this wouldn’t be there).
The loop section looks pretty wacky, and if you don’t fully understand it, have a look at this article where I explain how to do complex parsing. In short I’m: taking the gathered facts interfaces, converting them to a list, finding the key field that has the same interface name(meaning while it’s a loop, it will return only a single object), then I ensure that the mode is defined(either access or trunk), I then map that value(which means I return just that one piece of info), and last if the value is null I set it to “access”. So really what I’m doing is just finding out if it’s a “trunk” port, and if it’s not I make sure it’s set to “access”.
At the top of the task you can see there’s a conditional that only processes the task if the interface that the CDP neighbor lives in is actually a “trunk” port.
If it is a trunk port, then the interface description is set to the ID of the remote device as well as the port it is connecting via.

Conclusion

This is a pretty simple example of using ansible for a task, but I tried to jazz it up a bit by adding the extra filtering to give you an idea of how you can extend simple tasks with more specificity. I’d be curious to hear how you’d tweak or tune this to fit your environment.

Thanks and happy automating!

Feb 27 / Greg

Fantasy Restaurant Scott Wiener

Welcome to the warmup exercise for the Why Am I podcast called “the Fantasy Restaurant.”  In here my guests get to pick their favorite: drink, appetizer, main, sides, and dessert…anything goes.  Scott read the brief, then he said “How about we do it live.”  I can tell you this is the most fun I’ve had in the Fantasy Restaurant ever, and I can’t wait for you to enjoy this fly by the seat of your pants adventure.  Please share with a friend to help us grow, and also, enjoy this meal with Scott.
Youtube version here:
If you want to support the podcast you can do so via https://www.patreon.com/whyamipod (this gives you access to bonus content including their Fantasy Restaurant!)
Feb 19 / Greg

Why Am I Scott Wiener

Hey everybody, I’m Greg Sowell and this is Why Am I, a podcast where I talk to interesting people and try to trace a path to where they find themselves today.  My guest this go around is Scott Wiener.  This dude is pizza personified.  He has been running a pizza tour business in NYC since 2008 called Scott’s Pizza Tours.  This guy is live, and spontaneous as everything he does is custom catered to what his audience is interested in…it’s like a choose your own adventure, but with pizza.  He’s done a couple of other things like: written a book on pizza box art, has the guinness world record for largest pizza box collection, writes a column for Pizza Today Magazine, has done a TV-like series for thrillist called Really Dough(that’s soooo fun), and he has a non-profit called Slice Out Hunger.  I hope you enjoy this conversation with Scott.
Youtube version here:
If you want to support the podcast you can do so via https://www.patreon.com/whyamipod (this gives you access to bonus content including their Fantasy Restaurant!)
Feb 12 / Greg

Why Am I Marianne Apostolides

Hey everybody, I’m Greg Sowell and this is Why Am I, a podcast where I talk to interesting people and try to trace a path to where they find themselves today.  My guest this go around is Marianne Apostolides.  She’s a long time writer, not author, who has several interesting books.  Marianne is a deep thinker who brings philosophy into her work where she tries to explore what her body is telling her about her desires and appetites, which is human kind’s ultimate goal.  Please share with a friend to help us grow!  I hope you enjoy this conversation with Marianne.
Youtube version here:
Please show them some love on their socials here: http://marianne-apostolides.com/, https://deepsaltwater.bandcamp.com/releases.
If you want to support the podcast you can do so via https://www.patreon.com/whyamipod (this gives you access to bonus content including their Fantasy Restaurant!)
Feb 5 / Greg

Why Am I Woody Shticks

Hey everybody, I’m Greg Sowell and this is Why Am I, a podcast where I talk to interesting people and try to trace a path to where they find themselves today.  My guest this go around is Woody Shticks.  Woody is a self described comedy stripper and Queer with a capital Q.  He grew up in a puritan religious community…with this in mind he learned to advocate for himself and then begin to do the same for others; even enduring years of “conversion” therapy.  He now channels all of this into his comedy, one-man shows, group performances, dance, and video work…dude stays busy!  Something that really drew me to him in the first place is the extremely thoughtful way he looks at the world around him and the things that are important to him; all the while he makes you laugh your ass off.  If you enjoy this or any of my other episodes, please share with a friend!  At any rate, I hope you enjoy this conversation with Woody.
Youtube version here:
If you want to support the podcast you can do so via https://www.patreon.com/whyamipod (this gives you access to bonus content including their Fantasy Restaurant!)
Jan 29 / Greg

Why Am I Jimmy Gownley

Hey everybody, I’m Greg Sowell and this is Why Am I, a podcast where I talk to interesting people and try to trace a path to where they find themselves today.  My guest this go around is Jimmy Gownley.  Jimmy is a cartoonist who got started around 15, and now after 35 years of work he’s a New York Times best selling author.  He’s created his own series and written for the likes of Disney, BUT his current project is what really has my attention.  It’s a graphic novel he hopes to complete this year on fighting depression with creativity.  It’s something all too real for a lot of folks, and hearing the way he articulates it is one of the best things to come out of this podcast.  I could have literally talked to Jimmy all day, but alas, I’m all out of special drink.  If you enjoyed this or any other episode, please share it with a friend; help me grow 🙂.  Now, I hope you enjoy this chat with Jimmy.
Youtube version here:
If you want to support the podcast you can do so via https://www.patreon.com/whyamipod (this gives you access to bonus content including their Fantasy Restaurant!)
Jan 22 / Greg

Why Am I George Collins

Hey everybody, I’m Greg Sowell and this is Why Am I, a podcast where I talk to interesting people and try to trace a path to where they find themselves today.  My guest this go around is George Collins.  He’s a standup that went from introvert to…well still an introvert, just one that gets up on stage and does comedy.  He’s rounding out himself by also doing two podcasts and is currently writing a post apocalyptic novel.  BTW: there is also a published ten page love poem from when he was 17 floating around out there…so the dude knows real pain.  I hope you enjoy this chat with George.  If you’ve enjoyed this or any of the podcasts I’m asking you to share it with at least one person; help me grow!
Youtube version here:
Please show them some love on their socials here: https://whomst.substack.com/, https://twitter.com/RegularAsGeorge/.
If you want to support the podcast you can do so via https://www.patreon.com/whyamipod (this gives you access to bonus content including their Fantasy Restaurant!)