Utilities
CiscoAutomationFramework also provides some integrated utility functions for doing various things with data from switches such as abbreviating interfaces, checking if IP addresses are valid, and printing output in a nice format.
- CiscoAutomationFramework.util.abbreviate_interface(interface_string, max_chars=2)
Takes an Interface name ex. GigabitEthernet1/0/4 and abbreviates it ex Gi1/0/4
- Parameters:
interface_string (str) – Interface String ex. GigabitEthernet1/0/4
:param :return: Abbreviated interface string :rtype: str
- CiscoAutomationFramework.util.chunker(list, size)
Splits 1 large list into a list sub lists, where the sub lists can be any specific size
- CiscoAutomationFramework.util.column_print(data, spaces_between_columns=2, separator_char=None)
Print in nice even columns where each column is only the width it needs to be, not the width of the widest column in the list. This will give output in a table format similar to much Windows/Linux CLI output. Based off of code from https://stackoverflow.com/questions/9989334/create-nice-column-output-in-python
- Parameters:
data (list[Union[list, tuple]]) – List of List/Tuples of equal length, the first list being the header, all the rest being the data.
spaces_between_columns (int) – Number of spaces to be between each column (default 2)
separator_char (str) – Character to place in a row between the header and data, default to nothing
- Returns:
Nothing. This function executes the print
- CiscoAutomationFramework.util.convert_config_tree_to_list(tree, indent=0, indent_step=0)
Converts a tree representation of the configuration into a list that can be pasted into a device
- Parameters:
tree (dict) – Tree representation of a configuration file
indent (int) – number of spaces to indent root with
indent_step – number of indent spaces to increment when going from a root to a branch (default 0, no indent)
- Returns:
List representation of config tree
- Return type:
list
- CiscoAutomationFramework.util.extract_line_from_tree(tree, search_term, case_sensitive=True, full_match=False, find_all=True)
Extracts the first (or all) occurances of “search_term” from “tree”. Can specify case sensitive, and full match in the search
- CiscoAutomationFramework.util.get_config_sections(tree, search_terms, case_sensitive=True, full_match=False, min_search_depth=0, max_search_depth=0, _depth=0)
Searches the configuration tree for section headers that match the given search terms and returns the full path to root and the complete nested section(s) under those matches. This works very similar to search_config_tree with the exception that it will not only return the full path to root for any matches, but the full nested path.
- Parameters:
tree (dict) – Configuration tree to search
search_terms (str | list | tuple) – Search term(s) (string, list, or tuple)
case_sensitive (bool) – Whether the search is case-sensitive
full_match (bool) – If True, requires exact match; if False, allows partial matches
min_search_depth (int) – Minimum nesting level to include matches (0 = no restriction)
max_search_depth (int) – Maximum nesting level to include matches (0 = infinite)
_depth (int) – Internal recursion tracker (do not pass manually)
- Returns:
Dictionary containing the full path to root and complete matched sections
- Return type:
dict
- CiscoAutomationFramework.util.indented_text_to_tree(config)
Takes in a string/list that is formatted in a heiarchy by indents similar to below line one
line two line three
line four
line five
And parses it based on the indents, Can be arbitrary
This is used to parse the running/startup config. Also useful for parsing things like “show interfaces” output.
- CiscoAutomationFramework.util.is_ipv4(addr)
Checks if the IP address provided is an IPv4 Address.
- Parameters:
addr (str) – IP address to check
- Returns:
True/False
- Return type:
bool
- CiscoAutomationFramework.util.is_ipv4_subnet(string)
Checks if a string that you pass in is a representation of an IPv4 Subnet ex. 192.168.10.0/24, 10.0.0.0/8, 0.0.0.0/0.
- Parameters:
string (str) – String to check
- Returns:
True/False
- Return type:
bool
- CiscoAutomationFramework.util.matches_search_terms(key, search_terms, case_sensitive, full_match)
Checks if the key matches any search term based on given options.
- CiscoAutomationFramework.util.modify_config_tree_inline(tree, search_terms, case_sensitive=True, full_match=False, min_search_depth=0, max_search_depth=0, prepend_text='', append_text='', replace_tuple=('', ''), modifier_callback=None, prematch_extend_callback=None, postmatch_extend_callback=None, _depth=0)
Searches the config tree for a set of search terms, and any match will be eligible for modification. Any line that DOES not match the search terms will still be returned, but not eligible to be modified by the modification arguments that are passed in. THis allows you to modify only certain config but return the entire config tree that was passed in.
This function is very similar to search_and_modify_config_tree but instead of only returning the matches and the outdened path to the root, it will return everything that was passed in, but still only allowing modification of lines that contain the search_terms matches
Modification will ONLY occur to lines that CONTAIN a match! if you search for “description example” it will also return in the tree the interface name ex. interface GigabitEthernet1/0/1, however that line will NOT be eligible for the string modification because it does not contain “description example”.
Additionally using that same interface example, the interface will likely have other config besides the description, but if you search for the description, all other commands in that layer of the tree will not be returned, just the path up to the root which in this case is the interface name.
You may also specify if you want your search to be case sensitive, and you may also specify if you want a full or partial match. For example if I do a full match for “description” but the line of configuration is “description example” it will NOT match. Also if I do a partial match (by setting full match to false) for “descrip”, and the line is “description example” it WILL match.
If the integrated prepend, append, or replace functionality does not provide enough flexibility in terms of modification, you can pass in a modifier_callback function and implement your own modification algorthm. One thing to note is the function you pass in MUST accept a single argument as the line which matches your search term will be passed in. Keep in mind the prepend, append, and modify will still run after your modifier_callback runs. Your modifier callback will overwrite all lines that are passed into it so make sure that you take into account that every match will be run through your modifier_callback and will be overwritten with whatever your modifier_callback returns
If you need to add additional lines to the configuration before and/or after the match line you also have the ability to pass in a “pre_extend_callback” to extend a single or multiple lines before the match line and a “post_extend_callback” function to extend a single or multiple lines after the match line. Both of these user defined functions MUST accept a single argument which will be the matched line, and you may return a single string, list of strings, and tuple of strings to extend the config. Unlike the modifier_callback, the integrated prepend, append, and find/replace features of this function will NOT be applied to what is returned by the pre/post_extend_callback functions.
These functions are especially useful when generating change configuration where you need to “no” the command and re apply it with different paramaters
Keep in mind when using the postmatch_extend_callback, if your match line has nested configuration under it such as the following example matching “router bgp”: router bgp 65000
nested config1 nested config2
nested config3
and your post match callback returns “Post Match Line” it would come after the last line of nested config on the same level as your match line such as below:
- router bgp 65000
nested config1 nested config2
nested config3
Post Match Line
- Parameters:
search_terms (list) – List of search terms to search for.
case_sensitive (bool) – Whether the search is case-sensitive.
full_match (bool) – If True, matches the whole word exactly; else, allows partial matches.
prepend_text (str) – Text to prepend to matches.
append_text (str) – Text to append to matches.
replace_tuple (tuple or None) – A tuple (old_text, new_text) for replacing matches.
modifier_callback (function) – User defined function to call whenever a line matches search terms, MUST accept a single argument as the matching line of config will be passed in.
prematch_extend_callback (function) – User defined function to insert a line or multiple lines before the match line. User defined function may return string, list, or tuple.
postmatch_extend_callback (function) – User defined function to insert a line or multiple lines after the match line. User defined function may return string, list, or tuple.
tree (dict or None) – The configuration tree to search. Do not specify this, its only used for recursion
- Default case_sensitive:
True
- Default full_match:
False
- Default prepend_text:
“”
- Default append_text:
“”
- Default replace_tuple:
None
- Default modifier_callback:
None
- Default tree:
None
- Returns:
A dictionary containing matched and modified results.
- Return type:
dict
- CiscoAutomationFramework.util.search_and_modify_config_tree(tree, search_terms, case_sensitive=True, full_match=False, min_search_depth=0, max_search_depth=0, prepend_text='', append_text='', replace_tuple=('', ''), modifier_callback=None, prematch_extend_callback=None, postmatch_extend_callback=None, _depth=0)
Searches the config tree for a set of search terms, and if specified will run each line that matches a search term through a modification algorithm to prepend, append, and find/replace specified text on that line.
Modification will ONLY occur to lines that CONTAIN a match! if you search for “description example” it will also return in the tree the interface name ex. interface GigabitEthernet1/0/1, however that line will NOT be eligible for the string modification because it does not contain “description example”.
Additionally using that same interface example, the interface will likely have other config besides the description, but if you search for the description, all other commands in that layer of the tree will not be returned, just the path up to the root which in this case is the interface name.
You may also specify if you want your search to be case sensitive, and you may also specify if you want a full or partial match. For example if I do a full match for “description” but the line of configuration is “description example” it will NOT match. Also if I do a partial match (by setting full match to false) for “descrip”, and the line is “description example” it WILL match.
If the integrated prepend, append, or replace functionality does not provide enough flexibility in terms of modification, you can pass in a modifier_callback function and implement your own modification algorthm. One thing to note is the function you pass in MUST accept a single argument as the line which matches your search term will be passed in. Keep in mind the prepend, append, and modify will still run after your modifier_callback runs. Your modifier callback will overwrite all lines that are passed into it so make sure that you take into account that every match will be run through your modifier_callback and will be overwritten with whatever your modifier_callback returns
If you need to add additional lines to the configuration before and/or after the match line you also have the ability to pass in a “pre_extend_callback” to extend a single or multiple lines before the match line and a “post_extend_callback” function to extend a single or multiple lines after the match line. Both of these user defined functions MUST accept a single argument which will be the matched line, and you may return a single string, list of strings, and tuple of strings to extend the config. Unlike the modifier_callback, the integrated prepend, append, and find/replace features of this function will NOT be applied to what is returned by the pre/post_extend_callback functions.
These functions are especially useful when generating change configuration where you need to “no” the command and re apply it with different paramaters
Keep in mind when using the postmatch_extend_callback, if your match line has nested configuration under it such as the following example matching “router bgp”: router bgp 65000
nested config1 nested config2
nested config3
and your post match callback returns “Post Match Line” it would come after the last line of nested config on the same level as your match line such as below:
- router bgp 65000
nested config1 nested config2
nested config3
Post Match Line
- Parameters:
search_terms (list) – List of search terms to search for.
case_sensitive (bool) – Whether the search is case-sensitive.
full_match (bool) – If True, matches the whole word exactly; else, allows partial matches.
prepend_text (str) – Text to prepend to matches.
append_text (str) – Text to append to matches.
replace_tuple (tuple or None) – A tuple (old_text, new_text) for replacing matches.
modifier_callback (function) – User defined function to call whenever a line matches search terms, MUST accept a single argument as the matching line of config will be passed in.
prematch_extend_callback (function) – User defined function to insert a line or multiple lines before the match line. User defined function may return string, list, or tuple.
postmatch_extend_callback (function) – User defined function to insert a line or multiple lines after the match line. User defined function may return string, list, or tuple.
tree (dict or None) – The configuration tree to search. Do not specify this, its only used for recursion
- Default case_sensitive:
True
- Default full_match:
False
- Default prepend_text:
“”
- Default append_text:
“”
- Default replace_tuple:
None
- Default modifier_callback:
None
- Default tree:
None
- Returns:
A dictionary containing matched and modified results.
- Return type:
dict
- CiscoAutomationFramework.util.search_config_tree(tree, search_terms, case_sensitive=True, full_match=False, min_search_depth=0, max_search_depth=0, _depth=0)
Searches the config tree for a set of search terms and returns the path to root for that match and any sub branchs under the match. Note: if a match is found, and there are other branches in that same level that dont match, it will not return any of the other branches. For example if you search for an IP address and it is found in an interface, it wont also return the description if there is one, but it will return the “interface x”.
You may also specify if you want your search to be case sensitive, and you may also specify if you want a full or partial match. For example if I do a full match for “description” but the line of configuration is “description example” it will NOT match. Also if I do a partial match (by setting full match to false) for “descrip”, and the line is “description example” it WILL match.
You can also specify the minimum depth to search the tree, for example using the config below searching for “router bgp” will not yield any results, searching “vrf MYVRF” will yield results, but searching “vrf MYVRF” with a nest_level of 1 will NOT because it is nested once, and you specified to not return any matches at or below index 1: router bgp 65000
- ipv4 vrf MYVRF
network 10.0.0.0
You can also
- Parameters:
tree (dict or None) – The configuration tree to search.
search_terms (list) – List of search terms to search for.
min_search_depth (int) – Minimum depth at which to return search results if matches are found (0 returns anything, 1 excludes root, 2 excludes root and 1st nest level)
max_search_depth (int) – Maximum depth at which to return search results if matches are found (0 infinite [default], only includes root, 2 excludes root and 1st nest level).
case_sensitive (bool) – Whether the search is case-sensitive.
full_match (bool) – If True, matches the whole word exactly; else, allows partial matches.
- Default max_search_depth:
0
- Default case_sensitive:
True
- Returns:
A dictionary containing matched and modified results.
- Return type:
dict
- CiscoAutomationFramework.util.trees_are_equal(tree1: dict, tree2: dict, exclude_keys=[]) bool
Will check if 2 trees are equal or not. Can specify to exclude certain text NOTE this will check recursively and symmetrically so you cant have extra config in either tree and match