diff --git a/netutils/config/parser.py b/netutils/config/parser.py index 4876672f..cc7b6e16 100644 --- a/netutils/config/parser.py +++ b/netutils/config/parser.py @@ -311,8 +311,11 @@ def build_config_relationship(self) -> t.List[ConfigLine]: ... ] True """ - for line in self.generator_config: - if not line[0].isspace(): + for index, line in enumerate(self.generator_config): + current_spaces = self.get_leading_space_count(line) if line[0].isspace() else 0 + if index == 0 and line[0].isspace(): + self._current_parents = self._remove_parents(line, current_spaces) + elif not line[0].isspace(): self._current_parents = () if self.is_banner_start(line): line = self._build_banner(line) # type: ignore @@ -985,8 +988,11 @@ def build_config_relationship(self) -> t.List[ConfigLine]: ... ] True """ - for line in self.generator_config: - if not line[0].isspace(): + for index, line in enumerate(self.generator_config): + current_spaces = self.get_leading_space_count(line) if line[0].isspace() else 0 + if index == 0 and line[0].isspace(): + self._current_parents = self._remove_parents(line, current_spaces) + elif not line[0].isspace(): self._current_parents = () else: previous_config = self.config_lines[-1] @@ -1383,7 +1389,11 @@ def build_config_relationship(self) -> t.List[ConfigLine]: ... ] True """ - for line in self.generator_config: + for index, line in enumerate(self.generator_config): + current_spaces = self.get_leading_space_count(line) if line[0].isspace() else 0 + + if index == 0 and line[0].isspace(): + self._current_parents = self._remove_parents(line, current_spaces) if not line[0].isspace(): self._current_parents = () if self.is_banner_start(line): diff --git a/tests/unit/test_parser.py b/tests/unit/test_parser.py index 26a50963..208cfbb0 100644 --- a/tests/unit/test_parser.py +++ b/tests/unit/test_parser.py @@ -80,3 +80,21 @@ def test_duplicate_line(): ) with pytest.raises(IndexError, match=r".*This error is likely from a duplicate line detected.*"): compliance.parser_map["cisco_ios"](logging).config_lines # pylint: disable=expression-not-assigned + + +def test_leading_spaces_config_start(): + logging = ( + "! Command: show running-config\n" + " 24.1.4\n" + "!\n" + "no aaa root\n" + "!\n" + "management api http-commands\n" + " no shutdown\n" + "no service interface inactive port-id allocation disabled\n" + "transceiver qsfp default-mode 4x10G\n" + ) + with pytest.raises(IndexError, match=r".*Validate the first line does not begin with a space.*"): + compliance.parser_map["cisco_ios"](logging).config_lines # pylint: disable=expression-not-assigned + compliance.parser_map["arista_eos"](logging).config_lines # pylint: disable=expression-not-assigned + compliance.parser_map["cisco_xr"](logging).config_lines # pylint: disable=expression-not-assigned