diff --git a/netutils/config/parser.py b/netutils/config/parser.py index 17c8a6a3..fb9d74cf 100644 --- a/netutils/config/parser.py +++ b/netutils/config/parser.py @@ -312,8 +312,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 @@ -988,8 +991,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] @@ -1386,7 +1392,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 ac72bbe8..84be8ccd 100644 --- a/tests/unit/test_parser.py +++ b/tests/unit/test_parser.py @@ -78,3 +78,20 @@ 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 + + +@pytest.mark.parametrize("network_os", ["cisco_ios", "arista_eos", "cisco_iosxr"]) +def test_leading_spaces_config_start(network_os): # pylint: disable=redefined-outer-name + 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[network_os](logging).config_lines # pylint: disable=expression-not-assigned