Skip to content

Commit

Permalink
Refactor(plugins): Move jinja filter code for arista.avd.range_expand…
Browse files Browse the repository at this point in the history
… to PyAVD
  • Loading branch information
Laxmikant Chintakindi authored and Laxmikant Chintakindi committed Jun 20, 2024
1 parent faa4684 commit 07981a4
Show file tree
Hide file tree
Showing 19 changed files with 193 additions and 178 deletions.
163 changes: 16 additions & 147 deletions ansible_collections/arista/avd/plugins/filter/range_expand.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,23 @@
#
from __future__ import absolute_import, division, print_function

from ansible.errors import AnsibleFilterError

__metaclass__ = type

import re
from ansible_collections.arista.avd.plugins.plugin_utils.pyavd_wrappers import RaiseOnUse, wrap_filter

PLUGIN_NAME = "arista.avd.range_expand"

try:
from pyavd.j2filters.range_expand import range_expand
except ImportError as e:
range_expand = RaiseOnUse(
AnsibleFilterError(
f"The '{PLUGIN_NAME}' plugin requires the 'pyavd' Python library. Got import error",
orig_exc=e,
)
)

from ansible.errors import AnsibleFilterError

Expand Down Expand Up @@ -82,153 +96,8 @@
"""


def range_expand(range_to_expand):
if not (isinstance(range_to_expand, list) or isinstance(range_to_expand, str)):
raise AnsibleFilterError(f"value must be of type list or str, got {type(range_to_expand)}")

result = []

# If we got a list, unpack it and run this function recursively
if isinstance(range_to_expand, list):
for r in range_to_expand:
result.extend(range_expand(r))

# Must be a str now
else:
prefix = ""

# Unpack list in string
for one_range in range_to_expand.split(","):
if one_range is None:
continue

# Find prefix (if any)
regex = r"^(.*?)(((\d+)-)?(\d+)\/)?(((\d+)-)?(\d+)\/)?(((\d+)-)?(\d+))(\.((\d+)-)?(\d+))?"
# Number of groups in this regex.
regex_groups = 17
# Groups one-by-one:
# Group 1 (.*?) matches prefix ex. Ethernet, Eth, Po, Port-Channel
# Group 2 (((\d+)-)?(\d+)\/)? matches module(s) and slash ex. 12/, 1-3/
# Group 3 ((\d+)-)? matches first module and dash ex. 1-
# Group 4 (\d+) matches first module ex. 1
# Group 5 (\d+) matches last module ex. 12, 3
# Group 6 (((\d+)-)?(\d+)\/)? matches parent interface(s) and slash ex. 47/, 1-48/
# Group 7 ((\d+)-)? matches parent interface(s) and dash ex. 47-
# Group 8 (\d+) matches first parent interface ex. 1
# Group 9 (\d+) matches last parent interface ex. 47, 48
# Group 10 (((\d+)-)?(\d+)) matches (breakout) interface(s) ex. 1, 1-4, 1-48
# Group 11 ((\d+)-)? matches first interfaces and dash ex. 1-, 1-
# Group 12 (\d+) matches first interface
# Group 13 (\d+) matches last interface ex. 1, 4, 48
# Group 14 (\.((\d+)-)?(\d+))? matches dot and sub-interface(s) ex. .141, .12-15
# Group 15 ((\d+)-)? matches first sub-interface and dash ex. 12-
# Group 16 (\d+) matches first sub-interface ex. 12
# Group 17 (\d+) matches last sub-interface ex. 141, 15
# Remember that the groups() object is 0-based and the group numbers above are 1-based
search_result = re.search(regex, one_range)
if search_result:
if len(search_result.groups()) == regex_groups:
groups = search_result.groups()
first_module = last_module = None
first_parent_interface = last_parent_interface = None
first_interface = last_interface = None
first_subinterface = last_subinterface = None
# Set prefix if found (otherwise use last set prefix)
if groups[0]:
prefix = groups[0]
if groups[4]:
last_module = int(groups[4])
if groups[3]:
first_module = int(groups[3])
else:
first_module = last_module
if groups[8]:
last_parent_interface = int(groups[8])
if groups[7]:
first_parent_interface = int(groups[7])
else:
first_parent_interface = last_parent_interface
if groups[12]:
last_interface = int(groups[12])
if groups[11]:
first_interface = int(groups[11])
else:
first_interface = last_interface
if groups[16]:
last_subinterface = int(groups[16])
if groups[15]:
first_subinterface = int(groups[15])
else:
first_subinterface = last_subinterface

def expand_subinterfaces(interface_string):
result = []
if last_subinterface is not None:
if first_subinterface > last_subinterface:
raise AnsibleFilterError(
f"Range {one_range} could not be expanded because the first subinterface {first_subinterface} is larger than last"
f" subinterface {last_subinterface} in the range."
)
for subinterface in range(first_subinterface, last_subinterface + 1):
result.append(f"{interface_string}.{subinterface}")
else:
result.append(interface_string)
return result

def expand_interfaces(interface_string):
result = []
if first_interface > last_interface:
raise AnsibleFilterError(
f"Range {one_range} could not be expanded because the first interface {first_interface} is larger than last interface"
f" {last_interface} in the range."
)
for interface in range(first_interface, last_interface + 1):
for res in expand_subinterfaces(f"{interface_string}{interface}"):
result.append(res)
return result

def expand_parent_interfaces(interface_string):
result = []
if last_parent_interface:
if first_parent_interface > last_parent_interface:
raise AnsibleFilterError(
f"Range {one_range} could not be expanded because the first interface {first_parent_interface} is larger than last"
f" interface {last_parent_interface} in the range."
)
for parent_interface in range(first_parent_interface, last_parent_interface + 1):
for res in expand_interfaces(f"{interface_string}{parent_interface}/"):
result.append(res)
else:
for res in expand_interfaces(f"{interface_string}"):
result.append(res)
return result

def expand_module(interface_string):
result = []
if last_module:
if first_module > last_module:
raise AnsibleFilterError(
f"Range {one_range} could not be expanded because the first module {first_module} is larger than last module"
f" {last_module} in the range."
)
for module in range(first_module, last_module + 1):
for res in expand_parent_interfaces(f"{interface_string}{module}/"):
result.append(res)
else:
for res in expand_parent_interfaces(f"{interface_string}"):
result.append(res)
return result

result.extend(expand_module(prefix))

else:
raise AnsibleFilterError(f"Invalid range, got {one_range} and found {search_result.groups()}")

return result


class FilterModule(object):
def filters(self):
return {
"range_expand": range_expand,
"range_expand": wrap_filter(PLUGIN_NAME)(range_expand),
}
1 change: 1 addition & 0 deletions python-avd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ fix-libs: ## Fix/remove various Ansible specifics things from python files
find $(PACKAGE_DIR) -name '*.py' -exec sed -i -e 's/ansible_collections\.arista\.avd\.plugins\.filter.generate_route_target/$(PYAVD_FILTER_IMPORT)\.generate_route_target/g' {} +
find $(PACKAGE_DIR) -name '*.py' -exec sed -i -e 's/ansible_collections\.arista\.avd\.plugins\.filter.hide_passwords/$(PYAVD_FILTER_IMPORT)\.hide_passwords/g' {} +
find $(PACKAGE_DIR) -name '*.py' -exec sed -i -e 's/ansible_collections\.arista\.avd\.plugins\.filter.list_compress/$(PYAVD_FILTER_IMPORT)\.list_compress/g' {} +
find $(PACKAGE_DIR) -name '*.py' -exec sed -i -e 's/ansible_collections\.arista\.avd\.plugins\.filter.range_expand/$(PYAVD_FILTER_IMPORT)\.range_expand/g' {} +

find $(PACKAGE_DIR) -name '*.py' -exec sed -i -e 's/ansible_collections\.arista\.avd\.plugins\.filter/$(VENDOR_IMPORT)\.j2\.filter/g' {} +

Expand Down
2 changes: 1 addition & 1 deletion python-avd/pyavd/_eos_designs/eos_designs_facts/uplinks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
from typing import TYPE_CHECKING

from ...j2filters.list_compress import list_compress
from ...j2filters.range_expand import range_expand
from ...vendor.errors import AristaAvdError
from ...vendor.j2.filter.range_expand import range_expand
from ...vendor.utils import append_if_not_duplicate, get, unique

if TYPE_CHECKING:
Expand Down
2 changes: 1 addition & 1 deletion python-avd/pyavd/_eos_designs/eos_designs_facts/vlans.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from ...j2filters.convert_dicts import convert_dicts
from ...j2filters.list_compress import list_compress
from ...vendor.j2.filter.range_expand import range_expand
from ...j2filters.range_expand import range_expand
from ...vendor.utils import get

if TYPE_CHECKING:
Expand Down
2 changes: 1 addition & 1 deletion python-avd/pyavd/_eos_designs/ip_addressing/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from functools import cached_property
from typing import TYPE_CHECKING

from ...j2filters.range_expand import range_expand
from ...vendor.errors import AristaAvdError, AristaAvdMissingVariableError
from ...vendor.j2.filter.range_expand import range_expand
from ...vendor.utils import get

if TYPE_CHECKING:
Expand Down
2 changes: 1 addition & 1 deletion python-avd/pyavd/_eos_designs/shared_utils/cv_topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from functools import cached_property
from typing import TYPE_CHECKING

from ...vendor.j2.filter.range_expand import range_expand
from ...j2filters.range_expand import range_expand
from ...vendor.utils import get, get_item

if TYPE_CHECKING:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from ..._utils.merge import merge
from ...j2filters.convert_dicts import convert_dicts
from ...j2filters.natural_sort import natural_sort
from ...j2filters.range_expand import range_expand
from ...vendor.errors import AristaAvdError, AristaAvdMissingVariableError
from ...vendor.j2.filter.range_expand import range_expand
from ...vendor.utils import default, get, get_item, unique
Expand Down
2 changes: 1 addition & 1 deletion python-avd/pyavd/_eos_designs/shared_utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

from ...j2filters.convert_dicts import convert_dicts
from ...j2filters.natural_sort import natural_sort
from ...j2filters.range_expand import range_expand
from ...vendor.errors.errors import AristaAvdError, AristaAvdMissingVariableError
from ...vendor.j2.filter.range_expand import range_expand
from ...vendor.utils import default, get, get_item

if TYPE_CHECKING:
Expand Down
2 changes: 1 addition & 1 deletion python-avd/pyavd/_eos_designs/shared_utils/mlag.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
from re import findall
from typing import TYPE_CHECKING

from ...j2filters.range_expand import range_expand
from ...vendor.errors import AristaAvdError, AristaAvdMissingVariableError
from ...vendor.j2.filter.range_expand import range_expand
from ...vendor.utils import default, get

if TYPE_CHECKING:
Expand Down
2 changes: 1 addition & 1 deletion python-avd/pyavd/_eos_designs/shared_utils/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from functools import cached_property
from typing import TYPE_CHECKING

from ...j2filters.range_expand import range_expand
from ...vendor.errors.errors import AristaAvdError, AristaAvdMissingVariableError
from ...vendor.j2.filter.range_expand import range_expand
from ...vendor.utils import get

if TYPE_CHECKING:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
from functools import cached_property
from typing import TYPE_CHECKING

from ....j2filters.range_expand import range_expand
from ....vendor.errors import AristaAvdError, AristaAvdMissingVariableError
from ....vendor.j2.filter.range_expand import range_expand
from ....vendor.strip_empties import strip_null_from_data
from ....vendor.utils import append_if_not_duplicate, default, get, replace_or_append_item
from ...interface_descriptions import InterfaceDescriptionData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

from ....j2filters.generate_esi import generate_esi
from ....j2filters.generate_route_target import generate_route_target
from ....j2filters.range_expand import range_expand
from ....vendor.j2.filter.generate_lacp_id import generate_lacp_id
from ....vendor.j2.filter.range_expand import range_expand
from ....vendor.strip_empties import strip_null_from_data
from ....vendor.utils import append_if_not_duplicate, get
from ...interface_descriptions import InterfaceDescriptionData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
from typing import TYPE_CHECKING, Literal, Tuple

from ....j2filters.natural_sort import natural_sort
from ....j2filters.range_expand import range_expand
from ....vendor.errors import AristaAvdError, AristaAvdMissingVariableError
from ....vendor.j2.filter.range_expand import range_expand
from ....vendor.password_utils.password import simple_7_encrypt
from ....vendor.utils import default, get, get_item
from .utils_zscaler import UtilsZscalerMixin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from typing import TYPE_CHECKING, NoReturn

from ....j2filters.natural_sort import natural_sort
from ....j2filters.range_expand import range_expand
from ....vendor.errors import AristaAvdError, AristaAvdMissingVariableError
from ....vendor.j2.filter.range_expand import range_expand
from ....vendor.utils import append_if_not_duplicate, default, get, get_item, unique
from .utils import UtilsMixin

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from typing import TYPE_CHECKING

from ....j2filters.natural_sort import natural_sort
from ....j2filters.range_expand import range_expand
from ....vendor.errors import AristaAvdError
from ....vendor.j2.filter.range_expand import range_expand
from ....vendor.strip_empties import strip_empties_from_dict
from ....vendor.utils import default, get, get_item
from ...interface_descriptions import InterfaceDescriptionData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from typing import TYPE_CHECKING

from ....j2filters.natural_sort import natural_sort
from ....vendor.j2.filter.range_expand import range_expand
from ....j2filters.range_expand import range_expand
from ....vendor.utils import get, get_item
from .utils import UtilsMixin

Expand Down
Loading

0 comments on commit 07981a4

Please sign in to comment.