Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/859.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed config parser failing to parse more than three consecutive banners, which caused "Unable to parse banner end." errors on configs with many banners (e.g. Cisco IOS).
15 changes: 11 additions & 4 deletions netutils/config/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ def _update_config_lines(self, config_line: str) -> None:
entry = ConfigLine(config_line, self._current_parents)
self.config_lines.append(entry)

# pylint: disable=too-many-branches
def build_config_relationship(self) -> t.List[ConfigLine]:
r"""Parse text tree of config lines and their parents.

Expand Down Expand Up @@ -337,10 +338,11 @@ def build_config_relationship(self) -> t.List[ConfigLine]:
if line is None:
break
elif self.is_banner_start(line):
line = self._build_banner(line) # type: ignore
# line can potentially be another banner start therefore we do a secondary check.
if self.is_banner_start(line):
# Handles multiple consecutive banners (e.g. Cisco IOS)
while line is not None and self.is_banner_start(line):
line = self._build_banner(line) # type: ignore
if line is None:
break

self._update_config_lines(line)
return self.config_lines
Expand Down Expand Up @@ -1371,6 +1373,7 @@ def set_delimiter(self, config_line: str) -> None:
return None
raise ValueError("Unable to find banner delimiter.")

# pylint: disable=too-many-branches
def build_config_relationship(self) -> t.List[ConfigLine]:
r"""Parse text tree of config lines and their parents.

Expand Down Expand Up @@ -1413,7 +1416,11 @@ def build_config_relationship(self) -> t.List[ConfigLine]:
if line is None:
break
elif self.is_banner_start(line):
line = self._build_banner(line) # type: ignore
# Handles multiple consecutive banners (e.g. Cisco IOS)
while line is not None and self.is_banner_start(line):
line = self._build_banner(line) # type: ignore
if line is None:
break

self._update_config_lines(line)
return self.config_lines
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
hostname multi-banner
!
banner exec ^C
* exec banner *
^C
banner incoming ^C
* incoming banner *
^C
banner login ^C
* login banner actual *
^C
banner motd ^C
* motd banner *
^C
banner prompt-timeout ^C
* prompt-timeout banner *
^C
!
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
feature = {"name": "login banner", "ordered": False, "section": ["banner login"]}
network_os = "cisco_ios"
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
hostname multi-banner
!
banner exec ^C
* exec banner *
^C
banner incoming ^C
* incoming banner *
^C
banner login ^C
* login banner intended *
^C
banner motd ^C
* motd banner *
^C
banner prompt-timeout ^C
* prompt-timeout banner *
^C
!
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
data = {
"compliant": False,
"missing": "banner login ^C\n* login banner intended *\n^C",
"extra": "banner login ^C\n* login banner actual *\n^C",
"cannot_parse": True,
"unordered_compliant": False,
"ordered_compliant": False,
"actual": "banner login ^C\n* login banner actual *\n^C",
"intended": "banner login ^C\n* login banner intended *\n^C",
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@
ConfigLine(
config_line="======\nintended config motd banner\n======\n || ($hostname) ||\n^C", parents=("banner motd ^C",)
),
ConfigLine(config_line=None, parents=()),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from netutils.config.parser import ConfigLine

data = [
ConfigLine(config_line="hostname multi-banner", parents=()),
ConfigLine(config_line="banner exec ^C", parents=()),
ConfigLine(config_line="* exec banner line 1 *\n* exec banner line 2 *\n^C", parents=("banner exec ^C",)),
ConfigLine(config_line="banner incoming ^C", parents=()),
ConfigLine(
config_line="* incoming banner line 1 *\n* incoming banner line 2 *\n^C", parents=("banner incoming ^C",)
),
ConfigLine(config_line="banner login ^C", parents=()),
ConfigLine(config_line="* login banner line 1 *\n* login banner line 2 *\n^C", parents=("banner login ^C",)),
ConfigLine(config_line="banner motd ^C", parents=()),
ConfigLine(config_line="* motd banner line 1 *\n* motd banner line 2 *\n^C", parents=("banner motd ^C",)),
ConfigLine(config_line="banner prompt-timeout ^C", parents=()),
ConfigLine(config_line="* prompt-timeout banner line 1 *\n^C", parents=("banner prompt-timeout ^C",)),
ConfigLine(config_line="ip route 0.0.0.0 0.0.0.0 192.168.1.1", parents=()),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
hostname multi-banner
!
banner exec ^C
* exec banner line 1 *
* exec banner line 2 *
^C
banner incoming ^C
* incoming banner line 1 *
* incoming banner line 2 *
^C
banner login ^C
* login banner line 1 *
* login banner line 2 *
^C
banner motd ^C
* motd banner line 1 *
* motd banner line 2 *
^C
banner prompt-timeout ^C
* prompt-timeout banner line 1 *
^C
ip route 0.0.0.0 0.0.0.0 192.168.1.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from netutils.config.parser import ConfigLine

data = [
ConfigLine(config_line="hostname multi-banner-xr", parents=()),
ConfigLine(config_line="banner exec ~", parents=()),
ConfigLine(config_line="* exec banner line 1 *\n* exec banner line 2 *\n~", parents=("banner exec ~",)),
ConfigLine(config_line="banner login ~", parents=()),
ConfigLine(config_line="* login banner line 1 *\n* login banner line 2 *\n~", parents=("banner login ~",)),
ConfigLine(config_line="banner motd ~", parents=()),
ConfigLine(config_line="* motd banner line 1 *\n* motd banner line 2 *\n~", parents=("banner motd ~",)),
ConfigLine(config_line="banner prompt-timeout ~", parents=()),
ConfigLine(config_line="* prompt-timeout banner line 1 *\n~", parents=("banner prompt-timeout ~",)),
ConfigLine(config_line="logging trap informational", parents=()),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
hostname multi-banner-xr
!
banner exec ~
* exec banner line 1 *
* exec banner line 2 *
~
banner login ~
* login banner line 1 *
* login banner line 2 *
~
banner motd ~
* motd banner line 1 *
* motd banner line 2 *
~
banner prompt-timeout ~
* prompt-timeout banner line 1 *
~
logging trap informational
Loading