Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor(plugins): Move jinja filter code for arista.avd.range_expand to PyAVD #4138

Merged
164 changes: 16 additions & 148 deletions ansible_collections/arista/avd/plugins/filter/range_expand.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,23 @@

__metaclass__ = type

import re

from ansible.errors import AnsibleFilterError

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,
)
)


DOCUMENTATION = r"""
---
name: range_expand
Expand Down Expand Up @@ -82,153 +95,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 @@ -95,6 +95,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.status_render/$(PYAVD_FILTER_IMPORT)\.status_render/g' {} +

find $(PACKAGE_DIR) -name '*.py' -exec sed -i -e 's/ansible_collections\.arista\.avd\.plugins\.filter/$(VENDOR_IMPORT)\.j2\.filter/g' {} +
Expand Down
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
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,8 +9,8 @@
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

if TYPE_CHECKING:
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 @@ -8,7 +8,7 @@
from typing import TYPE_CHECKING

from ...._utils.merge import merge
from ....vendor.j2.filter.range_expand import range_expand
from ....j2filters.range_expand import range_expand
from ....vendor.strip_empties import strip_null_from_data
from ....vendor.utils import append_if_not_duplicate, get, groupby
from .utils import UtilsMixin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ....j2filters.generate_esi import generate_esi
from ....j2filters.generate_lacp_id import generate_lacp_id
from ....j2filters.generate_route_target import generate_route_target
from ....vendor.j2.filter.range_expand import range_expand
from ....j2filters.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 @@ -9,8 +9,8 @@

from ...._utils.password_utils.password import simple_7_encrypt
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
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
Loading