As part of a larger script I’m making I want to acquire the hostname/identity of the device connected to every ethernet interface on a switch and store them in an array for later use. What I essentially need is some way to have an array where the hostnames of neighbors are associated with the interface they are attached to so I can do something like:
:put $idList->ether1
and have it return the hostname.
So far my experimentation has lead me down 2 different paths so I’ll document both of those.
Adding referenced array values to the array
Ideally this would work similar to a python dictionary object where I could just append a new key:value pair to the end of the array dynamically and have it work just like a statically defined one, however I’ve not found a way to get this to work.
:local neighborList [/ip neighbor print as-value]; #Unformatted input
:local idList [{}]
:foreach neighbor in=$neighborList do={
#Append the interface hostname pair to the end of the list
:set idList ($idList,{[:tostr ($neighbor->"interface")]=[:tostr ($neighbor->"identity")]})#Problem here
}
:local ifName ether4; #Interface to find
:put $idList; #Debugging; Remove
:put ($idList->$ifName); #Print the desired interface
Despite various combinations of “:tostr”, “:parse”, converting to a string elsewhere, concatenating additional empty strings, and various other hacks I cannot get it to treat as anything other than a logical comparison thus resulting in an array filled with nothing but “false” 48 times.
I know that the rest of my code works and that the idea is sound because it works as I would expect if I statically set the key like such:
:set idList ($idList,{ether4=[:tostr ($neighbor->"identity")]})
The above actually work to associate the interface and a hostname, only problem is that it can only associate one interface and keeps overwriting it for the whole loop meaning that instead of getting interface ether4’s hostname I get ether48’s hostname.
String matching
After spending a couple hours messing with the above and reading numerous wiki pages and forum threads I came to the conclusion that the above is either impossible or has no easy solution so I decided to try kludging it by just storing everything as one string and using the “:find” to get the right entry. However my problem is that I can’t get “:find” to do anything except exact matching.
:local neighborList [/ip neighbor print as-value]; #Unformatted input
:local idList [{}]
:foreach neighbor in=$neighborList do={
#Extracts the interface name and hostname and adds them to list
:set idList ($idList , [:tostr ($neighbor->"interface")]. " " .[:tostr ($neighbor->"identity")])
}
:local ifName ether4; #Interface to find
:put $idList; #Debugging; Remove
:put ($idList->[:find $idList ~ ([:tostr $ifName]."*")]); #Wild card match any string with the right interface in front
I have gotten it to work be replacing the * with an exact copy of the device’s hostname but that’s not a viable solution since obviously all the devices don’t have the same hostname.
Conclusiong
Any help with either of the 2 above paths or a 3rd totally separate way to accomplish what I’m looking for would be much appreciated.