Skip to content

Commit

Permalink
Merge pull request #141 from netdevops/driver-preprocessor
Browse files Browse the repository at this point in the history
Introduces config preprocessor into driver
  • Loading branch information
jtdub authored Dec 18, 2024
2 parents e8068ae + 4acbf83 commit 7ab373a
Show file tree
Hide file tree
Showing 12 changed files with 316 additions and 269 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
version: 1.5.1
- name: Build and publish to PyPI
env:
TWINE_API_KEY: ${{ secrets.PYPI_API_TOKEN }}
TWINE_API_KEY: ${{ secrets.TWINE_API_KEY }}
run: |
poetry config pypi-token.pypi $TWINE_API_KEY
poetry publish --build
48 changes: 1 addition & 47 deletions hier_config/constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,7 @@ def _config_from_string_lines_end_of_banner_test(


def _load_from_string_lines(config: HConfig, config_text: str) -> None: # noqa: C901
if isinstance(config.driver, HConfigDriverJuniperJUNOS):
config_text = _convert_to_set_commands(config_text)

config_text = config.driver.config_preprocessor(config_text)
current_section: Union[HConfig, HConfigChild] = config
most_recent_item: Union[HConfig, HConfigChild] = current_section
indent_adjust = 0
Expand Down Expand Up @@ -299,47 +297,3 @@ def _load_from_string_lines(config: HConfig, config_text: str) -> None: # noqa:
if in_banner:
message = "we are still in a banner for some reason"
raise ValueError(message)


def _convert_to_set_commands(config_raw: str) -> str:
"""Convert a Juniper style config string into a list of set commands.
Args:
config_raw (str): The config string to convert to set commands
Returns:
config_raw (str): Configuration string
"""
lines = config_raw.split("\n")
path: list[str] = []
set_commands: list[str] = []

for line in lines:
stripped_line = line.strip()

# Skip empty lines
if not stripped_line:
continue

# Strip ; from the end of the line
if stripped_line.endswith(";"):
stripped_line = stripped_line.replace(";", "")

# Count the number of spaces at the beginning to determine the level
level = line.find(stripped_line) // 4

# Adjust the current path based on the level
path = path[:level]

# If the line ends with '{' or '}', it starts a new block
if stripped_line.endswith(("{", "}")):
path.append(stripped_line[:-1].strip())
elif stripped_line.startswith(("set", "delete")):
# It's already a set command, so just add it to the list
set_commands.append(stripped_line)
else:
# It's a command line, construct the full command
command = f"set {' '.join(path)} {stripped_line}"
set_commands.append(command)

return "\n".join(set_commands)
2 changes: 1 addition & 1 deletion hier_config/platforms/cisco_ios/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ def native_vlan(self) -> Optional[int]:

@property
def number(self) -> str:
return sub("^[a-zA-Z-]+", "", self.name)
return sub(r"^[a-zA-Z-]+", "", self.name)

@property
def parent_name(self) -> Optional[str]:
Expand Down
2 changes: 1 addition & 1 deletion hier_config/platforms/cisco_nxos/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def native_vlan(self) -> Optional[int]:

@property
def number(self) -> str:
return sub("^[a-zA-Z-]+", "", self.name)
return sub(r"^[a-zA-Z-]+", "", self.name)

@property
def parent_name(self) -> Optional[str]:
Expand Down
2 changes: 1 addition & 1 deletion hier_config/platforms/cisco_xr/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def native_vlan(self) -> Optional[int]:

@property
def number(self) -> str:
return sub("^[a-zA-Z-]+", "", self.name)
return sub(r"^[a-zA-Z-]+", "", self.name)

@property
def parent_name(self) -> Optional[str]:
Expand Down
4 changes: 4 additions & 0 deletions hier_config/platforms/driver_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ def declaration_prefix(self) -> str:
def negation_prefix(self) -> str:
return "no "

@staticmethod
def config_preprocessor(config_text: str) -> str:
return config_text

@staticmethod
@abstractmethod
def _instantiate_rules() -> HConfigDriverRules:
Expand Down
44 changes: 44 additions & 0 deletions hier_config/platforms/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,47 @@ def expand_range(number_range_str: str) -> tuple[int, ...]:
message = "len(set(numbers)) must be equal to len(numbers)."
raise ValueError(message)
return tuple(numbers)


def convert_to_set_commands(config_raw: str) -> str:
"""Convert a Juniper style config string into a list of set commands.
Args:
config_raw (str): The config string to convert to set commands
Returns:
config_raw (str): Configuration string
"""
lines = config_raw.split("\n")
path: list[str] = []
set_commands: list[str] = []

for line in lines:
stripped_line = line.strip()

# Skip empty lines
if not stripped_line:
continue

# Strip ; from the end of the line
if stripped_line.endswith(";"):
stripped_line = stripped_line.replace(";", "")

# Count the number of spaces at the beginning to determine the level
level = line.find(stripped_line) // 4

# Adjust the current path based on the level
path = path[:level]

# If the line ends with '{' or '}', it starts a new block
if stripped_line.endswith(("{", "}")):
path.append(stripped_line[:-1].strip())
elif stripped_line.startswith(("set", "delete")):
# It's already a set command, so just add it to the list
set_commands.append(stripped_line)
else:
# It's a command line, construct the full command
command = f"set {' '.join(path)} {stripped_line}"
set_commands.append(command)

return "\n".join(set_commands)
2 changes: 1 addition & 1 deletion hier_config/platforms/hp_procurve/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def native_vlan(self) -> Optional[int]:

@property
def number(self) -> str:
return re.sub("^[a-zA-Z-]+", "", self.name)
return re.sub(r"^[a-zA-Z-]+", "", self.name)

@property
def parent_name(self) -> Optional[str]:
Expand Down
5 changes: 5 additions & 0 deletions hier_config/platforms/juniper_junos/driver.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from hier_config.child import HConfigChild
from hier_config.platforms.driver_base import HConfigDriverBase, HConfigDriverRules
from hier_config.platforms.functions import convert_to_set_commands


class HConfigDriverJuniperJUNOS(HConfigDriverBase): # pylint: disable=too-many-instance-attributes
Expand All @@ -23,6 +24,10 @@ def declaration_prefix(self) -> str:
def negation_prefix(self) -> str:
return "delete "

@staticmethod
def config_preprocessor(config_text: str) -> str:
return convert_to_set_commands(config_text)

@staticmethod
def _instantiate_rules() -> HConfigDriverRules:
return HConfigDriverRules()
5 changes: 5 additions & 0 deletions hier_config/platforms/vyos/driver.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from hier_config.child import HConfigChild
from hier_config.platforms.driver_base import HConfigDriverBase, HConfigDriverRules
from hier_config.platforms.functions import convert_to_set_commands


class HConfigDriverVYOS(HConfigDriverBase): # pylint: disable=too-many-instance-attributes
Expand All @@ -20,6 +21,10 @@ def declaration_prefix(self) -> str:
def negation_prefix(self) -> str:
return "delete "

@staticmethod
def config_preprocessor(config_text: str) -> str:
return convert_to_set_commands(config_text)

@staticmethod
def _instantiate_rules() -> HConfigDriverRules:
return HConfigDriverRules()
Loading

0 comments on commit 7ab373a

Please sign in to comment.