Skip to content

CiscoIOSXRConfigParser fails with ValueError: empty separator when the banner is at the end of a config. #614

Open
@jtdub

Description

@jtdub

Environment

  • Python version: 3.9.19 and 3.11.3
  • netutils version: 1.10.0, 1.11.0, and 1.12.0

Expected Behavior

When loading an intended config into the netutils config parser, I expect the config to be loaded without error.

Observed Behavior

In the intended config, when a banner is loaded at the very end of the config and the banner delimiter is the last character, the config will fail to load in the parser with a value error.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jtdub/Documents/code/netutils/netutils/config/parser.py", line 1305, in __init__
    super(IOSXRConfigParser, self).__init__(config)
  File "/Users/jtdub/Documents/code/netutils/netutils/config/parser.py", line 534, in __init__
    super(CiscoConfigParser, self).__init__(config)
  File "/Users/jtdub/Documents/code/netutils/netutils/config/parser.py", line 65, in __init__
    super(BaseSpaceConfigParser, self).__init__(config)
  File "/Users/jtdub/Documents/code/netutils/netutils/config/parser.py", line 32, in __init__
    self.build_config_relationship()
  File "/Users/jtdub/Documents/code/netutils/netutils/config/parser.py", line 1386, in build_config_relationship
    line = self._build_banner(line)  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jtdub/Documents/code/netutils/netutils/config/parser.py", line 1329, in _build_banner
    banner, end, _ = line.rpartition(self.delimiter)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: empty separator

Steps to Reproduce

  1. Create two sample configs. The first with a banner at the end of the config. The second with the banner not at the end of the config.

banner1.txt

ntp
 server 192.0.2.1
 server 192.0.2.2

banner motd ^This is the first line test banner.
This is the second line of a test banner.
This is the third line of a test banner.^

banner2.txt

banner motd ^This is the first line of a test banner.
This is the second line of a test banner.
This is the third line of a test banner.^

ntp
 server 192.0.2.1
 server 192.0.2.2
  1. In the python IDE import the pathlib.Path and netutils.config.parser.IOSXRConfigParser libraries.
from pathlib import Path
from netutils.config.parser import IOSXRConfigParser
  1. In the python IDE, load the two banners as strings from their respective files.
banner1 = Path().joinpath("iosxr_banner1.txt").read_text()
banner2 = Path().joinpath("iosxr_banner2.txt").read_text()
>>> banner1
'ntp\n server 192.0.2.1\n server 192.0.2.2\n\nbanner motd ^This is the first line test banner.\nThis is the second line of a test banner.\nThis is the third line of a test banner.^\n'
>>> banner2
'banner motd ^\nThis is the first line of a test banner.\nThis is the second line of a test banner.\nThis is the third line of a test banner.^\n\nntp\n server 192.0.2.1\n server 192.0.2.2\n'
  1. In the python IDE, load the banner1 string into the IOSXRConfigParser. This will result in a traceback.
parsed_banner1 = IOSXRConfigParser(banner1)
>>> parsed_banner1 = IOSXRConfigParser(banner1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jtdub/Documents/code/netutils/netutils/config/parser.py", line 1305, in __init__
    super(IOSXRConfigParser, self).__init__(config)
  File "/Users/jtdub/Documents/code/netutils/netutils/config/parser.py", line 534, in __init__
    super(CiscoConfigParser, self).__init__(config)
  File "/Users/jtdub/Documents/code/netutils/netutils/config/parser.py", line 65, in __init__
    super(BaseSpaceConfigParser, self).__init__(config)
  File "/Users/jtdub/Documents/code/netutils/netutils/config/parser.py", line 32, in __init__
    self.build_config_relationship()
  File "/Users/jtdub/Documents/code/netutils/netutils/config/parser.py", line 1386, in build_config_relationship
    line = self._build_banner(line)  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jtdub/Documents/code/netutils/netutils/config/parser.py", line 1329, in _build_banner
    banner, end, _ = line.rpartition(self.delimiter)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: empty separator
  1. In the python IDE, load the banner2 string into the IOSXRConfigParser. This will load as expected.
parsed_banner2 = IOSXRConfigParser(banner2)
>>> parsed_banner2 = IOSXRConfigParser(banner2)
>>> parsed_banner2.build_config_relationship()
[ConfigLine(config_line='banner motd ^', parents=()), ConfigLine(config_line='This is the first line of a test banner.\nThis is the second line of a test banner.\nThis is the third line of a test banner.^', parents=('banner motd ^',)), ConfigLine(config_line='ntp', parents=()), ConfigLine(config_line=' server 192.0.2.1', parents=('ntp',)), ConfigLine(config_line=' server 192.0.2.2', parents=('ntp',))]

The condition that is being met is a result of the last character of the config being a banner delimiter. Either the delimiter isn't properly being set or the delimiter is set, but the parser is failing to recognize the character at the end of the file and the use of rpartition is raising a ValueError.

https://github.com/networktocode/netutils/blob/develop/netutils/config/parser.py#L1329

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions