ciscoconfparse.CiscoConfParse Object

class ciscoconfparse.CiscoConfParse(config='', comment='!', debug=0, factory=False, linesplit_rgx='\\r*\\n+', ignore_blank_lines=True, syntax='ios', encoding='UTF-8', read_only=False)

Parse Cisco IOS configurations and answer queries about the configs.

Initialize CiscoConfParse.

Parameters

configlist or str

A list of configuration statements, or a configuration file path to be parsed

commentstr

A comment delimiter. This should only be changed when parsing non-Cisco IOS configurations, which do not use a ! as the comment delimiter. comment defaults to ‘!’. This value can hold multiple characters in case the config uses multiple characters for comment delimiters; however, the comment delimiters are always assumed to be one character wide

debugint

debug defaults to 0, and should be kept that way unless you’re working on a very tricky config parsing problem. Debug range goes from 0 (no debugging) to 5 (max debugging). Debug output is not particularly friendly.

factorybool

factory defaults to False; if set True, it enables a beta-quality configuration line classifier.

linesplit_rgxstr

linesplit_rgx is used when parsing configuration files to find where new configuration lines are. It is best to leave this as the default, unless you’re working on a system that uses unusual line terminations (for instance something besides Unix, OSX, or Windows)

ignore_blank_linesbool

ignore_blank_lines defaults to True; when this is set True, ciscoconfparse ignores blank configuration lines. You might want to set ignore_blank_lines to False if you intentionally use blank lines in your configuration (ref: Github Issue #3), or you are parsing configurations which naturally have blank lines (such as Cisco Nexus configurations).

syntaxstr

A string holding the configuration type. Default: ‘ios’. Must be one of: ‘ios’, ‘nxos’, ‘iosxr’, ‘asa’, ‘junos’. Use ‘junos’ for any brace-delimited network configuration (including F5, Palo Alto, etc…).

encodingstr

A string holding the coding type. Default is locale.getpreferredencoding()

read_onlybool

A bool indicating whether CiscoConfParse should execute read-only.

Returns

CiscoConfParse

Examples

This example illustrates how to parse a simple Cisco IOS configuration with CiscoConfParse into a variable called parse. This example also illustrates what the ConfigObjs and ioscfg attributes contain.

>>> from ciscoconfparse import CiscoConfParse
>>> config = [
...     'logging trap debugging',
...     'logging 172.28.26.15',
...     ]
>>> parse = CiscoConfParse(config=config)
>>> parse
<CiscoConfParse: 2 lines / syntax: ios / comment delimiter: '!' / factory: False>
>>> parse.ConfigObjs
<ConfigList, comment='!', conf=[<IOSCfgLine # 0 'logging trap debugging'>, <IOSCfgLine # 1 'logging 172.28.26.15'>]>
>>> parse.ioscfg
['logging trap debugging', 'logging 172.28.26.15']
>>>

Attributes

comment_delimiterstr

A string containing the comment-delimiter. Default: “!”

ConfigObjsConfigList

A custom list, which contains all parsed IOSCfgLine instances.

debugint

An int to enable verbose config parsing debugs. Default 0.

ioscfglist

A list of text configuration strings

objs

An alias for ConfigObjs

openargsdict

Returns a dictionary of valid arguments for open() (these change based on the running python version).

syntaxstr

A string holding the configuration type. Default: ‘ios’. Must be one of: ‘ios’, ‘nxos’, ‘iosxr’, ‘asa’, ‘junos’. Use ‘junos’ for any brace-delimited network configuration (including F5, Palo Alto, etc…).

ConfigObjs = None
__firstlineno__ = 601
__repr__()

Return a string that represents this CiscoConfParse object instance. The number of lines embedded in the string is calculated from the length of the ConfigObjs attribute.

__static_attributes__ = ('ConfigObjs', 'comment_delimiter', 'debug', 'encoding', 'factory', 'finished_config_parse', 'ignore_blank_lines', 'read_only', 'syntax')
append_line(linespec)

Unconditionally insert linespec (a text line) at the end of the configuration

Parameters

linespecstr

Text IOS configuration line

Returns

The parsed IOSCfgLine object instance

atomic()

Use atomic() to manually fix up ConfigObjs relationships after modifying a parsed configuration. This method is slow; try to batch calls to atomic() if possible.

Warnings

If you modify a configuration after parsing it with CiscoConfParse, you must call commit() or atomic() before searching the configuration again with methods such as find_objects() or find_lines(). Failure to call commit() or atomic() on config modifications could lead to unexpected search results.

See Also

commit().

check_ccp_input_good(config=None, logger=None, linesplit_rgx='\\r*\\n+')

The config parameter is a sequence of text config commands. Return True or False based on whether the config can be parsed.

comment_delimiter = '!'
commit()

Alias for calling the atomic() method. This method is slow; try to batch calls to commit() if possible.

Warnings

If you modify a configuration after parsing it with CiscoConfParse, you must call commit() or atomic() before searching the configuration again with methods such as find_objects() or find_lines(). Failure to call commit() or atomic() on config modifications could lead to unexpected search results.

See Also

atomic().

debug = 0
delete_lines(linespec, exactmatch=False, ignore_ws=False)

Find all IOSCfgLine objects whose text matches linespec, and delete the object

encoding = 'UTF-8'
factory = False
find_all_children(linespec, exactmatch=False, ignore_ws=False)

Returns the parents matching the linespec, and all their children. This method is different than find_children(), because find_all_children() finds children of children. find_children() only finds immediate children.

Parameters

linespecstr

Text regular expression for the line to be matched

exactmatchbool

boolean that controls whether partial matches are valid

ignore_wsbool

boolean that controls whether whitespace is ignored

Returns

list

A list of matching configuration lines

Examples

Suppose you are interested in finding all archive statements in the following configuration…

username ddclient password 7 107D3D232342041E3A
archive
 log config
  logging enable
  hidekeys
 path ftp://ns.foo.com//tftpboot/Foo-archive
!

Using the config above, we expect to find the following config lines…

archive
 log config
  logging enable
  hidekeys
 path ftp://ns.foo.com//tftpboot/Foo-archive

We would accomplish this by querying find_all_children(‘^archive’)

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['username ddclient password 7 107D3D232342041E3A',
...           'archive',
...           ' log config',
...           '  logging enable',
...           '  hidekeys',
...           ' path ftp://ns.foo.com//tftpboot/Foo-archive',
...           '!',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.find_all_children('^archive')
['archive', ' log config', '  logging enable', '  hidekeys', ' path ftp://ns.foo.com//tftpboot/Foo-archive']
>>>
find_blocks(linespec, exactmatch=False, ignore_ws=False)

Find all siblings matching the linespec, then find all parents of those siblings. Return a list of config lines sorted by line number, lowest first. Note: any children of the siblings should NOT be returned.

Parameters

linespecstr

Text regular expression for the line to be matched

exactmatchbool

boolean that controls whether partial matches are valid

ignore_wsbool

boolean that controls whether whitespace is ignored

Returns

list

A list of matching configuration lines

Examples

This example finds bandwidth percent statements in following config, the siblings of those bandwidth percent statements, as well as the parent configuration statements required to access them.

!
policy-map EXTERNAL_CBWFQ
 class IP_PREC_HIGH
  priority percent 10
  police cir percent 10
    conform-action transmit
    exceed-action drop
 class IP_PREC_MEDIUM
  bandwidth percent 50
  queue-limit 100
 class class-default
  bandwidth percent 40
  queue-limit 100
policy-map SHAPE_HEIR
 class ALL
  shape average 630000
  service-policy EXTERNAL_CBWFQ
!

The following config lines should be returned:

policy-map EXTERNAL_CBWFQ
 class IP_PREC_MEDIUM
  bandwidth percent 50
  queue-limit 100
 class class-default
  bandwidth percent 40
  queue-limit 100

We do this by quering find_blocks(‘bandwidth percent’)

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['!',
...           'policy-map EXTERNAL_CBWFQ',
...           ' class IP_PREC_HIGH',
...           '  priority percent 10',
...           '  police cir percent 10',
...           '    conform-action transmit',
...           '    exceed-action drop',
...           ' class IP_PREC_MEDIUM',
...           '  bandwidth percent 50',
...           '  queue-limit 100',
...           ' class class-default',
...           '  bandwidth percent 40',
...           '  queue-limit 100',
...           'policy-map SHAPE_HEIR',
...           ' class ALL',
...           '  shape average 630000',
...           '  service-policy EXTERNAL_CBWFQ',
...           '!',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.find_blocks('bandwidth percent')
['policy-map EXTERNAL_CBWFQ', ' class IP_PREC_MEDIUM', '  bandwidth percent 50', '  queue-limit 100', ' class class-default', '  bandwidth percent 40', '  queue-limit 100']
>>>
>>> p.find_blocks(' class class-default')
['policy-map EXTERNAL_CBWFQ', ' class IP_PREC_HIGH', ' class IP_PREC_MEDIUM', ' class class-default']
>>>
find_child_objects(parentspec, childspec=None, ignore_ws=False, recurse=False, escape_chars=False)

Parse through the children of all parents matching parentspec, and return a list of child objects, which matched the childspec.

Parameters

parentspecstr or list

Text regular expression for the line to be matched; this must match the parent’s line

childspecstr

Text regular expression for the line to be matched; this must match the child’s line

ignore_wsbool

boolean that controls whether whitespace is ignored

escape_charsbool

boolean that controls whether characters are escaped before searching

Returns

list

A list of matching child objects

Examples

This example finds the object for “ge-0/0/0” under “interfaces” in the following config…

interfaces
    ge-0/0/0
        unit 0
            family ethernet-switching
                port-mode access
                vlan
                    members VLAN_FOO
    ge-0/0/1
        unit 0
            family ethernet-switching
                port-mode trunk
                vlan
                    members all
                native-vlan-id 1
    vlan
        unit 0
            family inet
                address 172.16.15.5/22

The following object should be returned:

<IOSCfgLine # 7 '    ge-0/0/1' (parent is # 0)>

We do this by quering find_child_objects(); we set our parent as ^s*interface and set the child as ^s+ge-0/0/1.

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['interfaces',
...           '    ge-0/0/0',
...           '        unit 0',
...           '            family ethernet-switching',
...           '                port-mode access',
...           '                vlan',
...           '                    members VLAN_FOO',
...           '    ge-0/0/1',
...           '        unit 0',
...           '            family ethernet-switching',
...           '                port-mode trunk',
...           '                vlan',
...           '                    members all',
...           '                native-vlan-id 1',
...           '    vlan',
...           '        unit 0',
...           '            family inet',
...           '                address 172.16.15.5/22',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.find_child_objects('^\s*interfaces',
... r'\s+ge-0/0/1')
[<IOSCfgLine # 7 '    ge-0/0/1' (parent is # 0)>]
>>>
find_children(linespec, exactmatch=False, ignore_ws=False)

Returns the parents matching the linespec, and their immediate children. This method is different than find_all_children(), because find_all_children() finds children of children. find_children() only finds immediate children.

Parameters

linespecstr

Text regular expression for the line to be matched

exactmatchbool

boolean that controls whether partial matches are valid

ignore_wsbool

boolean that controls whether whitespace is ignored

Returns

list

A list of matching configuration lines

Examples

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['username ddclient password 7 107D3D232342041E3A',
...           'archive',
...           ' log config',
...           '  logging enable',
...           '  hidekeys',
...           ' path ftp://ns.foo.com//tftpboot/Foo-archive',
...           '!',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.find_children('^archive')
['archive', ' log config', ' path ftp://ns.foo.com//tftpboot/Foo-archive']
>>>
find_children_w_parents(parentspec, childspec, ignore_ws=False)

Parse through the children of all parents matching parentspec, and return a list of children that matched the childspec.

Parameters

parentspecstr

Text regular expression for the line to be matched; this must match the parent’s line

childspecstr

Text regular expression for the line to be matched; this must match the child’s line

ignore_wsbool

boolean that controls whether whitespace is ignored

Returns

list

A list of matching child configuration lines

Examples

This example finds the port-security lines on FastEthernet0/1 in following config…

!
interface FastEthernet0/1
 switchport access vlan 532
 switchport port-security
 switchport port-security violation protect
 switchport port-security aging time 5
 switchport port-security aging type inactivity
 spanning-tree portfast
 spanning-tree bpduguard enable
!
interface FastEthernet0/2
 switchport access vlan 300
 spanning-tree portfast
 spanning-tree bpduguard enable
!
interface FastEthernet0/2
 duplex full
 speed 100
 switchport access vlan 300
 spanning-tree portfast
 spanning-tree bpduguard enable
!

The following lines should be returned:

switchport port-security
switchport port-security violation protect
switchport port-security aging time 5
switchport port-security aging type inactivity

We do this by quering find_children_w_parents(); we set our parent as ^interface and set the child as switchport port-security.

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['!',
...           'interface FastEthernet0/1',
...           ' switchport access vlan 532',
...           ' switchport port-security',
...           ' switchport port-security violation protect',
...           ' switchport port-security aging time 5',
...           ' switchport port-security aging type inactivity',
...           ' spanning-tree portfast',
...           ' spanning-tree bpduguard enable',
...           '!',
...           'interface FastEthernet0/2',
...           ' switchport access vlan 300',
...           ' spanning-tree portfast',
...           ' spanning-tree bpduguard enable',
...           '!',
...           'interface FastEthernet0/3',
...           ' duplex full',
...           ' speed 100',
...           ' switchport access vlan 300',
...           ' spanning-tree portfast',
...           ' spanning-tree bpduguard enable',
...           '!',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.find_children_w_parents('^interface\sFastEthernet0/1',
... 'port-security')
[' switchport port-security', ' switchport port-security violation protect', ' switchport port-security aging time 5', ' switchport port-security aging type inactivity']
>>>
find_interface_objects(intfspec, exactmatch=True)

Find all IOSCfgLine or NXOSCfgLine objects whose text is an abbreviation for intfspec and return the objects in a python list.

Notes

The configuration must be parsed with factory=True to use this method.

Parameters

intfspecstr

A string which is the abbreviation (or full name) of the interface.

exactmatchbool

Defaults to True; when True, this option requires intfspec match the whole interface name and number.

Returns

list

A list of matching IOSIntfLine objects

Examples

>>> from ciscoconfparse import CiscoConfParse
>>> config = [
...     '!',
...     'interface Serial1/0',
...     ' ip address 1.1.1.1 255.255.255.252',
...     '!',
...     'interface Serial1/1',
...     ' ip address 1.1.1.5 255.255.255.252',
...     '!',
...     ]
>>> parse = CiscoConfParse(config=config, factory=True)
>>>
>>> parse.find_interface_objects('Se 1/0')
[<IOSIntfLine # 1 'Serial1/0' info: '1.1.1.1/30'>]
>>>
find_lineage(linespec, exactmatch=False)

Iterate through to the oldest ancestor of this object, and return a list of all ancestors / children in the direct line. Cousins or aunts / uncles are not returned. Note, all children of this object are returned.

Parameters

linespecstr

Text regular expression for the line to be matched

exactmatchbool

Defaults to False; when True, this option requires linespec the whole line (not merely a portion of the line)

Returns

list

A list of matching objects

find_lines(linespec, exactmatch=False, ignore_ws=False)

This method is the equivalent of a simple configuration grep (Case-sensitive).

Parameters

linespecstr

Text regular expression for the line to be matched

exactmatchbool

Defaults to False. When set True, this option requires linespec match the whole configuration line, instead of a portion of the configuration line.

ignore_wsbool

boolean that controls whether whitespace is ignored. Default is False.

Returns

list

A list of matching configuration lines

find_object_branches(branchspec=(), regex_flags=0, allow_none=True, regex_groups=False, debug=0)

Iterate over a tuple of regular expressions in branchspec and return matching objects in a list of lists (consider it similar to a table of matching config objects). branchspec expects to start at some ancestor and walk through the nested object hierarchy (with no limit on depth).

Previous CiscoConfParse() methods only handled a single parent regex and single child regex (such as find_parents_w_child()).

Transcend past one-level of parent-child relationship parsing to include multiple nested ‘branches’ of a single family (i.e. parents, children, grand-children, great-grand-children, etc). The result of handling longer regex chains is that it flattens what would otherwise be nested loops in your scripts; this makes parsing heavily-nested configuratations like Juniper, Palo-Alto, and F5 much simpler. Of course, there are plenty of applications for “flatter” config formats like IOS.

Return a list of lists (of object ‘branches’) which are nested to the same depth required in branchspec. However, unlike most other CiscoConfParse() methods, return an explicit None if there is no object match. Returning None allows a single search over configs that may not be uniformly nested in every branch.

Deprecation notice for the allow_none parameter

allow_none is deprecated and no longer a configuration option, as of version 1.6.16. Going forward, allow_none will always be considered True.

Parameters

branchspectuple

A tuple of python regular expressions to be matched.

regex_flags :

Chained regular expression flags, such as re.IGNORECASE|re.MULTILINE

regex_groupsbool (default False)

If True, return a tuple of re.Match groups instead of the matching configuration objects.

debugint

Set debug > 0 for debug messages

Returns

list

A list of lists of matching IOSCfgLine objects

Examples

>>> from operator import attrgetter
>>> from ciscoconfparse import CiscoConfParse
>>> config = [
...     'ltm pool FOO {',
...     '  members {',
...     '    k8s-05.localdomain:8443 {',
...     '      address 192.0.2.5',
...     '      session monitor-enabled',
...     '      state up',
...     '    }',
...     '    k8s-06.localdomain:8443 {',
...     '      address 192.0.2.6',
...     '      session monitor-enabled',
...     '      state down',
...     '    }',
...     '  }',
...     '}',
...     'ltm pool BAR {',
...     '  members {',
...     '    k8s-07.localdomain:8443 {',
...     '      address 192.0.2.7',
...     '      session monitor-enabled',
...     '      state down',
...     '    }',
...     '  }',
...     '}',
...     ]
>>> parse = CiscoConfParse(config=config, syntax='junos', comment='#')
>>>
>>> branchspec = (r'ltm\spool', r'members', r'\S+?:\d+', r'state\sup')
>>> branches = parse.find_object_branches(branchspec=branchspec)
>>>
>>> # We found three branches
>>> len(branches)
3
>>> # Each branch must match the length of branchspec
>>> len(branches[0])
4
>>> # Print out one object 'branch'
>>> branches[0]
[<IOSCfgLine # 0 'ltm pool FOO'>, <IOSCfgLine # 1 '    members' (parent is # 0)>, <IOSCfgLine # 2 '        k8s-05.localdomain:8443' (parent is # 1)>, <IOSCfgLine # 5 '            state up' (parent is # 2)>]
>>>
>>> # Get the a list of text lines for this branch...
>>> [ii.text for ii in branches[0]]
['ltm pool FOO', '    members', '        k8s-05.localdomain:8443', '            state up']
>>>
>>> # Get the config text of the root object of the branch...
>>> branches[0][0].text
'ltm pool FOO'
>>>
>>> # Note: `None` in branches[1][-1] because of no regex match
>>> branches[1]
[<IOSCfgLine # 0 'ltm pool FOO'>, <IOSCfgLine # 1 '    members' (parent is # 0)>, <IOSCfgLine # 6 '        k8s-06.localdomain:8443' (parent is # 1)>, None]
>>>
>>> branches[2]
[<IOSCfgLine # 10 'ltm pool BAR'>, <IOSCfgLine # 11 '    members' (parent is # 10)>, <IOSCfgLine # 12 '        k8s-07.localdomain:8443' (parent is # 11)>, None]
find_objects(linespec, exactmatch=False, ignore_ws=False)

Find all IOSCfgLine objects whose text matches linespec and return the IOSCfgLine objects in a python list. find_objects() is similar to find_lines(); however, the former returns a list of IOSCfgLine objects, while the latter returns a list of text configuration statements. Going forward, I strongly encourage people to start using find_objects() instead of find_lines().

Parameters

linespecstr

A string or python regular expression, which should be matched

exactmatchbool

Defaults to False. When set True, this option requires linespec match the whole configuration line, instead of a portion of the configuration line.

ignore_wsbool

boolean that controls whether whitespace is ignored. Default is False.

Returns

list

A list of matching IOSCfgLine objects

Examples

This example illustrates the difference between find_objects() and find_lines(). >>> from ciscoconfparse import CiscoConfParse >>> config = [ … ‘!’, … ‘interface Serial1/0’, … ‘ ip address 1.1.1.1 255.255.255.252’, … ‘!’, … ‘interface Serial1/1’, … ‘ ip address 1.1.1.5 255.255.255.252’, … ‘!’, … ] >>> parse = CiscoConfParse(config=config) >>> >>> parse.find_objects(r’^interface’) [<IOSCfgLine # 1 ‘interface Serial1/0’>, <IOSCfgLine # 4 ‘interface Serial1/1’>] >>> >>> parse.find_lines(r’^interface’) [‘interface Serial1/0’, ‘interface Serial1/1’] >>>

find_objects_dna(dnaspec, exactmatch=False)

Find all IOSCfgLine objects whose text matches dnaspec and return the IOSCfgLine objects in a python list.

Notes

find_objects_dna() requires the configuration to be parsed with factory=True.

Parameters

dnaspecstr

A string or python regular expression, which should be matched. This argument will be used to match dna attribute of the object

exactmatchbool

Defaults to False. When set True, this option requires dnaspec match the whole configuration line, instead of a portion of the configuration line.

Returns

list

A list of matching IOSCfgLine objects

Examples

>>> from ciscoconfparse import CiscoConfParse
>>> config = [
...     '!',
...     'hostname MyRouterHostname',
...     '!',
...     ]
>>> parse = CiscoConfParse(config=config, factory=True, syntax='ios')
>>>
>>> obj_list = parse.find_objects_dna(r'Hostname')
>>> obj_list
[<IOSHostnameLine # 1 'MyRouterHostname'>]
>>>
>>> # The IOSHostnameLine object has a hostname attribute
>>> obj_list[0].hostname
'MyRouterHostname'
find_objects_w_all_children(parentspec, childspec, ignore_ws=False, recurse=False)

Return a list of parent IOSCfgLine objects, which matched the parentspec and whose children match all elements in childspec. Only the parent IOSCfgLine objects will be returned.

Parameters

parentspecstr

Text regular expression for the IOSCfgLine object to be matched; this must match the parent’s line

childspeclist

A list of text regular expressions to be matched among the children

ignore_wsbool

boolean that controls whether whitespace is ignored

recursebool

Set True if you want to search all children (children, grand children, great grand children, etc…)

Returns

list

A list of matching parent IOSCfgLine objects

Examples

This example uses find_objects_w_child() to find all ports that are members of access vlan 300 in following config…

!
interface FastEthernet0/1
 switchport access vlan 532
 spanning-tree vlan 532 cost 3
!
interface FastEthernet0/2
 switchport access vlan 300
 spanning-tree portfast
!
interface FastEthernet0/2
 duplex full
 speed 100
 switchport access vlan 300
 spanning-tree portfast
!

The following interfaces should be returned:

interface FastEthernet0/2
interface FastEthernet0/3

We do this by quering find_objects_w_all_children(); we set our parent as ^interface and set the childspec as [‘switchport access vlan 300’, ‘spanning-tree portfast’].

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['!',
...           'interface FastEthernet0/1',
...           ' switchport access vlan 532',
...           ' spanning-tree vlan 532 cost 3',
...           '!',
...           'interface FastEthernet0/2',
...           ' switchport access vlan 300',
...           ' spanning-tree portfast',
...           '!',
...           'interface FastEthernet0/3',
...           ' duplex full',
...           ' speed 100',
...           ' switchport access vlan 300',
...           ' spanning-tree portfast',
...           '!',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.find_objects_w_all_children('^interface',
...     ['switchport access vlan 300', 'spanning-tree portfast'])
...
[<IOSCfgLine # 5 'interface FastEthernet0/2'>, <IOSCfgLine # 9 'interface FastEthernet0/3'>]
>>>
find_objects_w_child(parentspec, childspec, ignore_ws=False, recurse=False)

Return a list of parent IOSCfgLine objects, which matched the parentspec and whose children match childspec. Only the parent IOSCfgLine objects will be returned.

This is an alias for find_parent_objects()

Parameters

parentspecstr

Text regular expression for the IOSCfgLine object to be matched; this must match the parent’s line

childspecstr

Text regular expression for the line to be matched; this must match the child’s line

ignore_wsbool

boolean that controls whether whitespace is ignored

recursebool

Set True if you want to search all children (children, grand children, great grand children, etc…)

Returns

list

A list of matching parent IOSCfgLine objects

find_objects_w_missing_children(parentspec, childspec, ignore_ws=False)

Return a list of parent IOSCfgLine objects, which matched the parentspec and whose children do not match all elements in childspec. Only the parent IOSCfgLine objects will be returned.

Parameters

parentspecstr

Text regular expression for the IOSCfgLine object to be matched; this must match the parent’s line

childspeclist

A list of text regular expressions to be matched among the children

ignore_wsbool

boolean that controls whether whitespace is ignored

Returns

list

A list of matching parent IOSCfgLine objects

find_objects_w_parents(parentspec, childspec, ignore_ws=False)

Parse through the children of all parents matching parentspec, and return a list of child objects, which matched the childspec.

This is just an alias for find_child_objects()

Parameters

parentspecstr

Text regular expression for the line to be matched; this must match the parent’s line

childspecstr

Text regular expression for the line to be matched; this must match the child’s line

ignore_wsbool

boolean that controls whether whitespace is ignored

Returns

list

A list of matching child objects

find_objects_wo_child(parentspec, childspec, ignore_ws=False, recurse=False)

Return a list of parent IOSCfgLine objects, which matched the parentspec and whose children did not match childspec. Only the parent IOSCfgLine objects will be returned. For simplicity, this method only finds oldest_ancestors without immediate children that match.

Parameters

parentspecstr

Text regular expression for the IOSCfgLine object to be matched; this must match the parent’s line

childspecstr

Text regular expression for the line to be matched; this must match the child’s line

ignore_wsbool

boolean that controls whether whitespace is ignored

Returns

list

A list of matching parent configuration lines

find_parent_objects(parentspec, childspec=None, ignore_ws=False, recurse=False, escape_chars=False)

Return a list of parent IOSCfgLine objects, which matched the parentspec and whose children match childspec. Only the parent IOSCfgLine objects will be returned.

Parameters

parentspecstr or list

Text regular expression for the IOSCfgLine object to be matched; this must match the parent’s line

childspecstr

Text regular expression for the line to be matched; this must match the child’s line

ignore_wsbool

boolean that controls whether whitespace is ignored

recursebool

Set True if you want to search all children (children, grand children, great grand children, etc…)

escape_charsbool

Set True if you want to escape characters before searching

Returns

list

A list of matching parent IOSCfgLine objects

Examples

This example uses find_parent_objects() to find all ports that are members of access vlan 300 in following config…

!
interface FastEthernet0/1
 switchport access vlan 532
 spanning-tree vlan 532 cost 3
!
interface FastEthernet0/2
 switchport access vlan 300
 spanning-tree portfast
!
interface FastEthernet0/3
 duplex full
 speed 100
 switchport access vlan 300
 spanning-tree portfast
!

The following interfaces should be returned:

interface FastEthernet0/2
interface FastEthernet0/3

We do this by quering find_objects_w_child(); we set our parent as ^interface and set the child as switchport access vlan 300.

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['!',
...           'interface FastEthernet0/1',
...           ' switchport access vlan 532',
...           ' spanning-tree vlan 532 cost 3',
...           '!',
...           'interface FastEthernet0/2',
...           ' switchport access vlan 300',
...           ' spanning-tree portfast',
...           '!',
...           'interface FastEthernet0/3',
...           ' duplex full',
...           ' speed 100',
...           ' switchport access vlan 300',
...           ' spanning-tree portfast',
...           '!',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.find_parent_objects('^interface',
...     'switchport access vlan 300')
...
[<IOSCfgLine # 5 'interface FastEthernet0/2'>, <IOSCfgLine # 9 'interface FastEthernet0/3'>]
>>>
find_parent_objects_wo_child(parentspec, childspec, ignore_ws=False, recurse=False, escape_chars=False)

Return a list of parent IOSCfgLine objects, which matched the parentspec and whose children did not match childspec. Only the parent IOSCfgLine objects will be returned. For simplicity, this method only finds oldest_ancestors without immediate children that match.

Parameters

parentspecstr

Text regular expression for the IOSCfgLine object to be matched; this must match the parent’s line

childspecstr

Text regular expression for the line to be matched; this must match the child’s line

ignore_wsbool

boolean that controls whether whitespace is ignored

recursebool

boolean that controls whether to recurse through children of children

escape_charsbool

boolean that controls whether to escape characters before searching

Returns

list

A list of matching parent configuration lines

Examples

This example finds all ports that are autonegotiating in the following config…

!
interface FastEthernet0/1
 switchport access vlan 532
 spanning-tree vlan 532 cost 3
!
interface FastEthernet0/2
 switchport access vlan 300
 spanning-tree portfast
!
interface FastEthernet0/2
 duplex full
 speed 100
 switchport access vlan 300
 spanning-tree portfast
!

The following interfaces should be returned:

interface FastEthernet0/1
interface FastEthernet0/2

We do this by quering find_parent_objects_wo_child(); we set our parent as ^interface and set the child as speedsd+ (a regular-expression which matches the word ‘speed’ followed by an integer).

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['!',
...           'interface FastEthernet0/1',
...           ' switchport access vlan 532',
...           ' spanning-tree vlan 532 cost 3',
...           '!',
...           'interface FastEthernet0/2',
...           ' switchport access vlan 300',
...           ' spanning-tree portfast',
...           '!',
...           'interface FastEthernet0/3',
...           ' duplex full',
...           ' speed 100',
...           ' switchport access vlan 300',
...           ' spanning-tree portfast',
...           '!',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.find_parent_objects_wo_child(r'^interface', r'speed\s\d+')
[<IOSCfgLine # 1 'interface FastEthernet0/1'>, <IOSCfgLine # 5 'interface FastEthernet0/2'>]
>>>
find_parents_w_child(parentspec, childspec, ignore_ws=False)

Parse through all children matching childspec, and return a list of parents that matched the parentspec. Only the parent lines will be returned.

Parameters

parentspecstr

Text regular expression for the line to be matched; this must match the parent’s line

childspecstr

Text regular expression for the line to be matched; this must match the child’s line

ignore_wsbool

boolean that controls whether whitespace is ignored

Returns

list

A list of matching parent configuration lines

Examples

This example finds all ports that are members of access vlan 300 in following config…

!
interface FastEthernet0/1
 switchport access vlan 532
 spanning-tree vlan 532 cost 3
!
interface FastEthernet0/2
 switchport access vlan 300
 spanning-tree portfast
!
interface FastEthernet0/2
 duplex full
 speed 100
 switchport access vlan 300
 spanning-tree portfast
!

The following interfaces should be returned:

interface FastEthernet0/2
interface FastEthernet0/3

We do this by quering find_parents_w_child(); we set our parent as ^interface and set the child as switchport access vlan 300.

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['!',
...           'interface FastEthernet0/1',
...           ' switchport access vlan 532',
...           ' spanning-tree vlan 532 cost 3',
...           '!',
...           'interface FastEthernet0/2',
...           ' switchport access vlan 300',
...           ' spanning-tree portfast',
...           '!',
...           'interface FastEthernet0/3',
...           ' duplex full',
...           ' speed 100',
...           ' switchport access vlan 300',
...           ' spanning-tree portfast',
...           '!',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.find_parents_w_child('^interface', 'switchport access vlan 300')
['interface FastEthernet0/2', 'interface FastEthernet0/3']
>>>
find_parents_wo_child(parentspec, childspec, ignore_ws=False)

Parse through all parents matching parentspec, and return a list of parents that did NOT have children match the childspec. For simplicity, this method only finds oldest_ancestors without immediate children that match.

Parameters

parentspecstr

Text regular expression for the line to be matched; this must match the parent’s line

childspecstr

Text regular expression for the line to be matched; this must match the child’s line

ignore_wsbool

boolean that controls whether whitespace is ignored

Returns

list

A list of matching parent configuration lines

Examples

This example finds all ports that are autonegotiating in the following config…

!
interface FastEthernet0/1
 switchport access vlan 532
 spanning-tree vlan 532 cost 3
!
interface FastEthernet0/2
 switchport access vlan 300
 spanning-tree portfast
!
interface FastEthernet0/2
 duplex full
 speed 100
 switchport access vlan 300
 spanning-tree portfast
!

The following interfaces should be returned:

interface FastEthernet0/1
interface FastEthernet0/2

We do this by quering find_parents_wo_child(); we set our parent as ^interface and set the child as speedsd+ (a regular-expression which matches the word ‘speed’ followed by an integer).

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['!',
...           'interface FastEthernet0/1',
...           ' switchport access vlan 532',
...           ' spanning-tree vlan 532 cost 3',
...           '!',
...           'interface FastEthernet0/2',
...           ' switchport access vlan 300',
...           ' spanning-tree portfast',
...           '!',
...           'interface FastEthernet0/3',
...           ' duplex full',
...           ' speed 100',
...           ' switchport access vlan 300',
...           ' spanning-tree portfast',
...           '!',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.find_parents_wo_child('^interface', 'speed\s\d+')
['interface FastEthernet0/1', 'interface FastEthernet0/2']
>>>
finished_config_parse = False
handle_ccp_brace_syntax(tmp_lines=None, syntax=None)

Deal with brace-delimited syntax issues, such as conditionally discarding junos closing brace-lines.

has_line_with(linespec)

Return True if linespec is contained in the configuration.

ignore_blank_lines = True
insert_after(exist_val=None, new_val=None, exactmatch=False, ignore_ws=False, atomic=False, new_val_indent=-1, **kwargs)

Find all IOSCfgLine objects whose text matches exist_val, and insert new_val after those line objects.

If new_val_indent >= 0, then new_val will be inserted with the requested indent regardless of any existing indent on new_val.

Parameters

exist_valstr

Text regular expression for the line to be matched

new_valstr

text to be inserted after all occurances of exist_val

exactmatchbool

if exactmatch is True, do not match on substrings

ignore_wsbool

if ignore_ws is True, ignore whitespace differences

atomicbool

if atomic is True, this change will be commited

new_val_identint

integer indent for new_val

Examples

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['!',
...           'interface FastEthernet 0/1',
...           ' description Test intf to CloudFlare',
...           ' ip address 192.0.2.1 255.255.255.252',
...           ' no ip unreachables',
...           '!',
...           'interface FastEthernet 0/2',
...           ' description ProxySG model 8100',
...           ' ip address 192.0.2.5 255.255.255.252',
...           ' no ip unreachables',
...           '!',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.insert_after(r"interface\s+FastEthernet\s+0\/2", "no ip proxy-arp", new_val_indent=1)
insert_after_child(parentspec, childspec, insertstr=None, exactmatch=False, excludespec=None, ignore_ws=False, atomic=False)

Find all IOSCfgLine objects whose text matches linespec and have a child matching childspec, and insert an IOSCfgLine object for insertstr after those child objects.

insert_before(exist_val=None, new_val=None, exactmatch=False, ignore_ws=False, atomic=False, new_val_indent=-1, **kwargs)

Find all IOSCfgLine objects whose text matches exist_val, and insert new_val before those line objects.

If new_val_indent >= 0, then new_val will be inserted with the requested indent regardless of any existing indent on new_val.

Parameters

exist_valstr

Text regular expression for the line to be matched

new_valstr

text to be inserted before all occurances of exist_val

exactmatchbool

if exactmatch is True, do not match on substrings

ignore_wsbool

if ignore_ws is True, ignore whitespace differences

atomicbool

if atomic is True, this change will be commited

new_val_identint

integer indent for new_val

Examples

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['!',
...           'interface FastEthernet 0/1',
...           ' description Test intf to CloudFlare',
...           ' ip address 192.0.2.1 255.255.255.252',
...           ' no ip unreachables',
...           '!',
...           'interface FastEthernet 0/2',
...           ' description ProxySG model 8100',
...           ' ip address 192.0.2.5 255.255.255.252',
...           ' no ip unreachables',
...           '!',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.insert_before(r"interface\s+FastEthernet\s+0\/2", "default interface FastEthernet 0/2", new_val_indent=0)
property ioscfg

Return a list containing all text configuration statements.

property objs

CiscoConfParse().objs is an alias for the CiscoConfParse().ConfigObjs property; it returns a ConfigList() of config-line objects.

property openargs

Fix Py3.5 deprecation of universal newlines - Ref Github #114; also see https://softwareengineering.stackexchange.com/q/298677/23144.

prepend_line(linespec)

Unconditionally insert an IOSCfgLine object for linespec (a text line) at the top of the configuration

re_match_iter_typed(regexspec, group=1, result_type=<class 'str'>, default='', untyped_default=False)

Use regexspec to search the root parents in the config and return the contents of the regular expression group, at the integer group index, cast as result_type; if there is no match, default is returned.

Note

Only the first regex match is returned.

Parameters

regexspecstr

A string or python compiled regular expression, which should be matched. This regular expression should contain parenthesis, which bound a match group.

groupint

An integer which specifies the desired regex group to be returned. group defaults to 1.

result_typetype

A type (typically one of: str, int, float, or IPv4Obj). All returned values are cast as result_type, which defaults to str.

defaultany

The default value to be returned, if there is no match. The default is an empty string.

untyped_defaultbool

Set True if you don’t want the default value to be typed

Returns

result_type

The text matched by the regular expression group; if there is no match, default is returned. All values are cast as result_type. The default result_type is str.

Examples

This example illustrates how you can use re_match_iter_typed() to get the first interface name listed in the config.

>>> import re
>>> from ciscoconfparse import CiscoConfParse
>>> config = [
...     '!',
...     'interface Serial1/0',
...     ' ip address 1.1.1.1 255.255.255.252',
...     '!',
...     'interface Serial2/0',
...     ' ip address 1.1.1.5 255.255.255.252',
...     '!',
...     ]
>>> parse = CiscoConfParse(config=config)
>>> parse.re_match_iter_typed(r'interface\s(\S+)')
'Serial1/0'
>>>

The following example retrieves the hostname from the configuration

>>> from ciscoconfparse import CiscoConfParse
>>> config = [
...     '!',
...     'hostname DEN-EDGE-01',
...     '!',
...     'interface Serial1/0',
...     ' ip address 1.1.1.1 255.255.255.252',
...     '!',
...     'interface Serial2/0',
...     ' ip address 1.1.1.5 255.255.255.252',
...     '!',
...     ]
>>> parse = CiscoConfParse(config=config)
>>> parse.re_match_iter_typed(r'^hostname\s+(\S+)')
'DEN-EDGE-01'
>>>
re_search_children(regexspec, recurse=False)

Use regexspec to search for root parents in the config with text matching regex. If recurse is False, only root parent objects are returned. A list of matching objects is returned.

This method is very similar to find_objects() (when recurse is True); however it was written in response to the use-case described in Github Issue #156.

Parameters

regexspecstr

A string or python regular expression, which should be matched.

recursebool

Set True if you want to search all objects, and not just the root parents

Returns

list

A list of matching IOSCfgLine objects which matched. If there is no match, an empty list() is returned.

read_config_file(filepath=None, linesplit_rgx='\\r*\\n+')

Read the config lines from the filepath. Return the list of text configuration commands or raise an error.

read_only = False
replace_all_children(parentspec, childspec, replacestr, excludespec=None, exactmatch=False, atomic=False)

Replace lines matching childspec within all children (recursive) of lines whilch match parentspec

replace_children(parentspec, childspec, replacestr, excludespec=None, exactmatch=False, atomic=False)

Replace lines matching childspec within the parentspec’s immediate children.

Parameters

parentspecstr

Text IOS configuration line

childspecstr

Text IOS configuration line, or regular expression

replacestrstr

Text IOS configuration, which should replace text matching childspec.

excludespecstr

A regular expression, which indicates childspec lines which must be skipped. If excludespec is None, no lines will be excluded.

exactmatchbool

Defaults to False. When set True, this option requires linespec match the whole configuration line, instead of a portion of the configuration line.

Returns

list

A list of changed IOSCfgLine instances.

Examples

replace_children() just searches through a parent’s child lines and replaces anything matching childspec with replacestr. This method is one of my favorites for quick and dirty standardization efforts if you know the commands are already there (just set inconsistently).

One very common use case is rewriting all vlan access numbers in a configuration. The following example sets storm-control broadcast level 0.5 on all GigabitEthernet ports.

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['!',
...           'interface GigabitEthernet1/1',
...           ' description {I have a broken storm-control config}',
...           ' switchport',
...           ' switchport mode access',
...           ' switchport access vlan 50',
...           ' switchport nonegotiate',
...           ' storm-control broadcast level 0.2',
...           '!'
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.replace_children(r'^interface\sGigabit', r'broadcast\slevel\s\S+', 'broadcast level 0.5')
[' storm-control broadcast level 0.5']
>>>

One thing to remember about the last example, you cannot use a regular expression in replacestr; just use a normal python string.

replace_lines(linespec, replacestr, excludespec=None, exactmatch=False, atomic=False)

This method is a text search and replace (Case-sensitive). You can optionally exclude lines from replacement by including a string (or compiled regular expression) in excludespec.

Parameters

linespecstr

Text regular expression for the line to be matched

replacestrstr

Text used to replace strings matching linespec

excludespecstr

Text regular expression used to reject lines, which would otherwise be replaced. Default value of excludespec is None, which means nothing is excluded

exactmatchbool

boolean that controls whether partial matches are valid

atomicbool

boolean that controls whether the config is reparsed after replacement (default False)

Returns

list

A list of changed configuration lines

Examples

This example finds statements with EXTERNAL_CBWFQ in following config, and replaces all matching lines (in-place) with EXTERNAL_QOS. For the purposes of this example, let’s assume that we do not want to make changes to any descriptions on the policy.

!
policy-map EXTERNAL_CBWFQ
 description implement an EXTERNAL_CBWFQ policy
 class IP_PREC_HIGH
  priority percent 10
  police cir percent 10
    conform-action transmit
    exceed-action drop
 class IP_PREC_MEDIUM
  bandwidth percent 50
  queue-limit 100
 class class-default
  bandwidth percent 40
  queue-limit 100
policy-map SHAPE_HEIR
 class ALL
  shape average 630000
  service-policy EXTERNAL_CBWFQ
!

We do this by calling replace_lines(linespec=’EXTERNAL_CBWFQ’, replacestr=’EXTERNAL_QOS’, excludespec=’description’)

>>> from ciscoconfparse import CiscoConfParse
>>> config = ['!',
...           'policy-map EXTERNAL_CBWFQ',
...           ' description implement an EXTERNAL_CBWFQ policy',
...           ' class IP_PREC_HIGH',
...           '  priority percent 10',
...           '  police cir percent 10',
...           '    conform-action transmit',
...           '    exceed-action drop',
...           ' class IP_PREC_MEDIUM',
...           '  bandwidth percent 50',
...           '  queue-limit 100',
...           ' class class-default',
...           '  bandwidth percent 40',
...           '  queue-limit 100',
...           'policy-map SHAPE_HEIR',
...           ' class ALL',
...           '  shape average 630000',
...           '  service-policy EXTERNAL_CBWFQ',
...           '!',
...     ]
>>> p = CiscoConfParse(config=config)
>>> p.replace_lines('EXTERNAL_CBWFQ', 'EXTERNAL_QOS', 'description')
['policy-map EXTERNAL_QOS', '  service-policy EXTERNAL_QOS']
>>>
>>> # Now when we call `p.find_blocks('policy-map EXTERNAL_QOS')`, we get the
>>> # changed configuration, which has the replacements except on the
>>> # policy-map's description.
>>> p.find_blocks('EXTERNAL_QOS')
['policy-map EXTERNAL_QOS', ' description implement an EXTERNAL_CBWFQ policy', ' class IP_PREC_HIGH', ' class IP_PREC_MEDIUM', ' class class-default', 'policy-map SHAPE_HEIR', ' class ALL', '  shape average 630000', '  service-policy EXTERNAL_QOS']
>>>
req_cfgspec_all_diff(cfgspec, ignore_ws=False)

req_cfgspec_all_diff takes a list of required configuration lines, parses through the configuration, and ensures that none of cfgspec’s lines are missing from the configuration. req_cfgspec_all_diff returns a list of missing lines from the config.

One example use of this method is when you need to enforce routing protocol standards, or standards against interface configurations.

Warning

req_cfgspec_excl_diff() and req_cfgspec_all_diff() will be deprecated / removed in the future. Diff().diff() should be used going forward; however, “some assembly will be required”.

Examples

>>> from ciscoconfparse import CiscoConfParse
>>> config = [
...     'logging trap debugging',
...     'logging 172.28.26.15',
...     ]
>>> p = CiscoConfParse(config=config)
>>> required_lines = [
...     "logging 172.28.26.15",
...     "logging 172.16.1.5",
...     ]
>>> diffs = p.req_cfgspec_all_diff(required_lines)
>>> diffs
['logging 172.16.1.5']
>>>
req_cfgspec_excl_diff(linespec, uncfgspec, cfgspec)

req_cfgspec_excl_diff accepts a linespec, an unconfig spec, and a list of required configuration elements. Return a list of configuration diffs to make the configuration comply. All other config lines matching the linespec that are not listed in the cfgspec will be removed with the uncfgspec regex.

Uses for this method include the need to enforce syslog, acl, or aaa standards.

Warning

req_cfgspec_excl_diff() and req_cfgspec_all_diff() will be deprecated / removed in the future. Diff().diff() should be used going forward; however, “some assembly will be required”.

Examples

>>> from ciscoconfparse import CiscoConfParse
>>> config = [
...     'logging trap debugging',
...     'logging 172.28.26.15',
...     ]
>>> p = CiscoConfParse(config=config)
>>> required_lines = [
...     "logging 172.16.1.5",
...     "logging 1.10.20.30",
...     "logging 192.168.1.1",
...     ]
>>> linespec = "logging\s+\d+\.\d+\.\d+\.\d+"
>>> unconfspec = linespec
>>> diffs = p.req_cfgspec_excl_diff(linespec, unconfspec,
...     required_lines)
>>> diffs
['no logging 172.28.26.15', 'logging 172.16.1.5', 'logging 1.10.20.30', 'logging 192.168.1.1']
>>>
save_as(filepath)

Save a text copy of the configuration at filepath; this method uses the OperatingSystem’s native line separators (such as \r\n in Windows).

sync_diff(cfgspec=None, linespec=None, uncfgspec=None, ignore_order=True, remove_lines=True, syntax='', debug=0)

sync_diff() accepts a list of required configuration elements, a linespec, and an unconfig spec. This method return a list of Cisco IOS-style configuration diffs to make the configuration comply with cfgspec.

Internally, sync_diff() is implemented with HDiff().

Parameters

cfgspeclist

A list of required configuration lines to be used as a config template

linespecstr

A regular expression, which filters lines to be diff’d

uncfgspecstr

A regular expression, which is used to unconfigure lines. When ciscoconfparse removes a line, it takes the entire portion of the line that matches uncfgspec, and prepends “no” to it.

ignore_orderbool

Indicates whether the configuration should be reordered to minimize the number of diffs. Default: True (usually it’s a good idea to leave ignore_order True, except for ACL comparisions)

remove_linesbool

Indicates whether the lines which are not in cfgspec should be removed. Default: True. When remove_lines is True, all other config lines matching the linespec that are not listed in the cfgspec will be removed with the uncfgspec regex.

syntaxstr

The expected syntax of the diff lines. Default is an empty string, ‘’

debugint

Miscellaneous debugging; Default: 0

Returns

list

A list of string configuration diffs

Uses for this method include the need to enforce syslog, acl, or aaa standards.

Examples

>>> from ciscoconfparse import CiscoConfParse
>>> config = [
...     'logging trap debugging',
...     'logging 172.28.26.15',
...     ]
>>> p = CiscoConfParse(config=config)
>>> required_lines = [
...     "logging 172.16.1.5",
...     "logging 1.10.20.30",
...     "logging 192.168.1.1",
...     ]
>>> linespec = "logging\s+\d+\.\d+\.\d+\.\d+"
>>> uncfgspec = linespec
>>> diffs = p.sync_diff(required_lines,
...     linespec, uncfgspec)
>>> diffs
['no logging 172.28.26.15', 'logging 172.16.1.5', 'logging 1.10.20.30', 'logging 192.168.1.1']
>>>
>>> before_config = [
... 'logging trap debugging',
... 'logging 172.28.26.15',
... 'interface GigabitEthernet0',
... ' ip address 1.1.1.1 255.255.255.0',
... ]
>>>
>>> after_config = [
... 'no logging console guaranteed',
... 'logging 172.28.26.15',
... 'interface GigabitEthernet0',
... ' no ip proxy-arp',
... ]
>>>
>>> my_diff = HDiff(before_config, desired_config)
syntax = 'ios'
class ciscoconfparse.HDiff(before_config=None, after_config=None, syntax='ios', ordered_diff=False, allow_duplicates=False, ignore_blank_lines=True, output_format='unified', debug=0)

An object to implement diffs against configs or config templates. By default, the output diffs are ordered roughly as before_config, then after_config. HDiff() is intended as an internal CiscoConfParse building-block to implement methods such as ciscoconfparse.CiscoConfParse.sync_diff()

Initialize HDiff().

Parameters

before_configlist

A list of text configuration statements representing the original config. Default value: None

after_configlist

A list of text configuration statements representing the most-recent config. Default value: None

syntaxstr

A string holding the configuration type. Default: ‘ios’. Must be one of: ‘ios’, ‘nxos’, ‘iosxr’, ‘asa’, ‘junos’. Use ‘junos’ for any brace-delimited network configuration (including F5, Palo Alto, etc…).

ordered_diffbool

A boolean for whether the returned-diff lines must be ordered. Default value: False

allow_duplicatesbool

A boolean for whether the returned-diff lines may be duplicated. Default value: False

ignore_blank_linesbool

A boolean for whether blank lines in the configuration are ignored / removed.

debugint

debug defaults to 0, and should be kept that way unless you’re working on a tricky config diff problem. Debug range goes from 0 (no debugging) to 5 (max debugging). Debug output is not particularly friendly.

Returns

HDiff()

Examples

This example illustrates how to diff a simple Cisco IOS configuration with HDiff() into a variable called parse. This example also illustrates what the ConfigObjs and ioscfg attributes contain.

>>> from ciscoconfparse import HDiff
>>> begin_config = [
...     'logging trap debugging',
...     'logging 172.28.26.15',
...     'interface GigabitEthernet0',
...     ' ip address 1.1.1.1 255.255.255.0',
...     ]
>>> desired_config = [
...     'no logging console guaranteed',
...     'logging 172.28.26.15',
...     'interface GigabitEthernet0',
...     ' no ip proxy-arp',
...     ]
>>>
>>> # by default, diffs are ordered as before_config then after_config
>>> diff_obj = HDiff(begin_config, desired_config, syntax='ios')
>>> diff_obj
<ciscoconfparse.ciscoconfparse.HDiff object at 0x7f8fd292c160>
>>> for line in diff_obj.unified_diffs():
...     print(line)
...
--- /tmp/before 2023-02-10 09:22:08.476463
+++ /tmp/after  2023-02-10 09:22:08.476463
@@ -2,1 +2,1 @@
-logging trap debugging
 logging 172.28.26.15
 interface GigabitEthernet0
+ no ip proxy-arp
- ip address 1.1.1.1 255.255.255.0
+no logging console guaranteed
>>>
>>>
>>> # diff_obj.all_output_dicts is a list of dict
>>> for elem in diff_obj.all_output_dicts:
...     print(elem)
...
{'linenum': -1, 'diff_side': 'before', 'diff_word': 'remove', 'indent': 0, 'parents': [], 'text': 'logging trap debugging'}
{'linenum': -1, 'diff_side': 'before', 'diff_word': 'keep', 'indent': 0, 'parents': [], 'text': 'logging 172.28.26.15'}
{'linenum': -1, 'diff_side': 'before', 'diff_word': 'keep', 'indent': 0, 'parents': [], 'text': 'interface GigabitEthernet0'}
{'linenum': 3, 'diff_side': 'after', 'diff_word': 'add', 'indent': 1, 'parents': ['interface GigabitEthernet0'], 'text': ' no ip proxy-arp'}
{'linenum': -1, 'diff_side': 'before', 'diff_word': 'remove', 'indent': 1, 'parents': ['interface GigabitEthernet0'], 'text': ' ip address 1.1.1.1 255.255.255.0'}
{'linenum': 0, 'diff_side': 'after', 'diff_word': 'add', 'indent': 0, 'parents': [], 'text': 'no logging console-guaranteed'}
>>>

Attributes

parse_beforeCiscoConfParse

The parsed object for CiscoConfParse(before_config)

parse_afterCiscoConfParse

The parsed object for CiscoConfParse(after_config)

all_output_dictslist

A list of all the output dicts

__firstlineno__ = 4110
__static_attributes__ = ('after_config', 'after_obj', 'after_obj_list', 'all_output_dicts', 'allow_duplicates', 'before_config', 'before_obj', 'before_obj_list', 'debug', 'ignore_blank_lines', 'ordered_diff', 'parse_after', 'parse_before', 'syntax')
build_diff_obj_list(parse=None, default_diff_word=None)

Return a list of *CfgLine() objects which are relevant to the diff…

build_diff_obj_lists()

Assign the diff_side attribute to parse_before and parse_after *CfgLine() instances

build_ios_diffs()
compress_dict_diffs(all_lines=None, debug=0)

Summary

  • Accept a list of diff dicts (diff dicts are hereafter known as a “line”)

  • Note that duplicate line parent lines may exist in the input

  • Organize the lines such that diff parent lines (example: interface Foo) are not duplicated.

  • Return the updated and reorganized line (dict) list.

A line dict will look similar to this:

``` {

‘linenum’: -1, # do not save the before linenum ‘diff_side’: ‘before’, ‘diff_word’: ‘remove’, ‘indent’: 1, ‘parents’: [], ‘text’: ‘ some command here’, ‘diff_id_list’: [-7805827718597648250, -565516812775864492]

}

Note that the diff_id_list key above contains a list of hash() values which are calculated as a unique identifier for the combination of parent and child objects. This list of hashes is required because it’s possible for multiple parents to have the same child command (for instance the same ‘no ip proxy-arp’ child on multiple interface parent lines).

Please note that a config command object will not get the same hash() value for different script runs of the same code.

dict_diffs(before_obj_list, after_obj_list)
find_in_before_obj_list(before_obj_list, after_obj, consider_whitespace=False, debug=0)

Find matches for after_obj in before_obj_list. If a match found, the before_obj.diff_word is ‘keep’ and after_obj.diff_word is ‘unchanged’. If no match is found in before_obj_list, after_obj.diff_word is ‘add’.

parse_hdiff_configs()
render_after_obj_diffs(aobj=None)

Print after_obj (aobj) diffs to stdout. before_obj should not be handled here.

sort_lines(after_lines=None)

Typical output line dict-format… {

“linenum”: -1, # before line numbers are skipped… “diff_side”: “before”, “diff_word”: “keep”, “indent”: 0, “parents”: [], “text”: bobj.text, “diff_id_list”: bobj.diff_id_list,

}

unified_diff_header()

Return a unified diff header similar to this…

— /dev/null 2022-04-25 16:33:07.434605 +++ /dev/null 2022-04-25 16:33:07.434605 @@ -7,3 +9,3 @@

unified_diffs(header=True)

Return a python list of text which contains the unified diff of the before and after HDiff() configurations.

unified_diffs_contents(header=True)

Return a python list of unified diff contents which contain the unified diff of the before and after HDiff() configurations.