From 0956a7ea6387853cd93c37185ea3e3fd41585b40 Mon Sep 17 00:00:00 2001 From: Karel van Klink <karel.vanklink@geant.org> Date: Fri, 18 Apr 2025 14:38:21 +0200 Subject: [PATCH] Allow for creation of Edge Ports on a Juniper router --- gso/workflows/edge_port/create_edge_port.py | 14 +-- test/conftest.py | 2 +- .../edge_port/test_create_edge_port.py | 87 ++++++++++--------- 3 files changed, 58 insertions(+), 45 deletions(-) diff --git a/gso/workflows/edge_port/create_edge_port.py b/gso/workflows/edge_port/create_edge_port.py index 2455ee3de..d221c969f 100644 --- a/gso/workflows/edge_port/create_edge_port.py +++ b/gso/workflows/edge_port/create_edge_port.py @@ -31,8 +31,9 @@ from gso.utils.helpers import ( partner_choice, validate_edge_port_number_of_members_based_on_lacp, ) +from gso.utils.shared_enums import Vendor from gso.utils.types.geant_ids import IMPORTED_GA_ID -from gso.utils.types.interfaces import LAGMember, PhysicalPortCapacity +from gso.utils.types.interfaces import JuniperLAGMember, LAGMember, PhysicalPortCapacity from gso.utils.types.tt_number import TTNumber from gso.utils.workflow_steps import start_moodi, stop_moodi from gso.workflows.shared import create_summary_form @@ -50,7 +51,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: service_type: EdgePortType enable_lacp: bool = False speed: PhysicalPortCapacity - encapsulation: EncapsulationType = EncapsulationType.DOT1Q + encapsulation: EncapsulationType | str = EncapsulationType.DOT1Q # TODO: remove type hint workaround number_of_members: int minimum_links: int mac_address: str | None = None @@ -81,13 +82,16 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: initial_user_input = yield CreateEdgePortForm - class EdgePortLAGMember(LAGMember): + class NokiaEdgePortLAGMember(LAGMember): interface_name: available_interfaces_choices( # type: ignore[valid-type] initial_user_input.node, initial_user_input.speed ) + selected_router = Router.from_subscription(initial_user_input.node) + lag_member = JuniperLAGMember if selected_router.router.vendor == Vendor.JUNIPER else NokiaEdgePortLAGMember + lag_ae_members = Annotated[ - list[EdgePortLAGMember], + list[lag_member], # type: ignore[valid-type] AfterValidator(validate_unique_list), Len( min_length=initial_user_input.number_of_members, @@ -98,7 +102,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: class SelectInterfaceForm(FormPage): model_config = ConfigDict(title="Select Interfaces") - name: available_service_lags_choices(initial_user_input.node) # type: ignore[valid-type] + name: available_service_lags_choices(initial_user_input.node) or str # type: ignore[valid-type] description: str | None = None ae_members: lag_ae_members diff --git a/test/conftest.py b/test/conftest.py index 926cd183b..2d2c1a784 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -134,7 +134,7 @@ class FakerProvider(BaseProvider): return self.generator.numerify("ae@#") def nokia_lag_interface_name(self) -> str: - return self.generator.numerify("lag-@#") + return self.generator.numerify("lag-3#") def link_members_juniper(self) -> LAGMemberList[LAGMember]: iface_amount = self.generator.random_int(min=2, max=5) diff --git a/test/workflows/edge_port/test_create_edge_port.py b/test/workflows/edge_port/test_create_edge_port.py index 941995bcd..b907a4138 100644 --- a/test/workflows/edge_port/test_create_edge_port.py +++ b/test/workflows/edge_port/test_create_edge_port.py @@ -47,51 +47,57 @@ def _netbox_client_mock(): @pytest.fixture() def input_form_wizard_data(request, router_subscription_factory, partner_factory, faker): - create_edge_port_step = { - "tt_number": faker.tt_number(), - "node": str(router_subscription_factory(vendor=Vendor.NOKIA).subscription_id), - "partner": partner_factory(name="GAAR", email=faker.email())["partner_id"], - "service_type": EdgePortType.PUBLIC, - "enable_lacp": True, - "speed": PhysicalPortCapacity.HUNDRED_GIGABIT_PER_SECOND, - "encapsulation": EncapsulationType.DOT1Q, - "number_of_members": 2, - "minimum_links": 1, - "custom_service_name": faker.sentence(), - "generate_ga_id": False, - "ga_id": "GA-12345", - } - create_edge_port_interface_step = { - "name": "lag-21", - "description": faker.sentence(), - "ae_members": [ - { - "interface_name": f"Interface{interface}", - "interface_description": faker.sentence(), - } - for interface in range(2) - ], - } - summary_view_step = {} - - return [ - create_edge_port_step, - create_edge_port_interface_step, - summary_view_step, - ] + def input_form_factory(vendor: Vendor = Vendor.NOKIA): + partner = partner_factory(name="GAAR", email=faker.email()) + create_edge_port_step = { + "tt_number": faker.tt_number(), + "node": str(router_subscription_factory(vendor=vendor, partner=partner).subscription_id), + "partner": partner["partner_id"], + "service_type": EdgePortType.PUBLIC, + "enable_lacp": True, + "speed": PhysicalPortCapacity.HUNDRED_GIGABIT_PER_SECOND, + "encapsulation": EncapsulationType.DOT1Q, + "number_of_members": 2, + "minimum_links": 1, + "custom_service_name": faker.sentence(), + "generate_ga_id": False, + "ga_id": "GA-12345", + } + create_edge_port_interface_step = { + "name": faker.nokia_lag_interface_name(), + "description": faker.sentence(), + "ae_members": [ + { + "interface_name": faker.network_interface() if vendor == Vendor.JUNIPER else f"Interface{i}", + "interface_description": faker.sentence(), + } + for i in range(2) + ], + } + summary_view_step = {} + + return [ + create_edge_port_step, + create_edge_port_interface_step, + summary_view_step, + ] + + return input_form_factory @pytest.mark.workflow() +@pytest.mark.parametrize("router_vendor", [*Vendor.values()]) @patch("gso.services.lso_client._send_request") def test_successful_edge_port_creation( mock_execute_playbook, + router_vendor, input_form_wizard_data, faker, _netbox_client_mock, # noqa: PT019 test_client, ): product_id = get_product_id_by_name(ProductName.EDGE_PORT) - initial_data = [{"product": product_id}, *input_form_wizard_data] + initial_data = [{"product": product_id}, *input_form_wizard_data(vendor=router_vendor)] result, process_stat, step_log = run_workflow("create_edge_port", initial_data) for _ in range(3): @@ -106,9 +112,12 @@ def test_successful_edge_port_creation( subscription = EdgePort.from_subscription(subscription_id) assert subscription.status == "active" - router_fqdn = Router.from_subscription(input_form_wizard_data[0]["node"]).router.router_fqdn + router_fqdn = Router.from_subscription(initial_data[1]["node"]).router.router_fqdn assert subscription.edge_port.ga_id == "GA-12345" - assert subscription.description == f"Edge Port lag-21 on {router_fqdn}, GAAR, {subscription.edge_port.ga_id}" + assert ( + subscription.description + == f"Edge Port {initial_data[2]["name"]} on {router_fqdn}, GAAR, {subscription.edge_port.ga_id}" + ) assert len(subscription.edge_port.edge_port_ae_members) == 2 assert mock_execute_playbook.call_count == 4 @@ -123,7 +132,7 @@ def test_successful_edge_port_creation_with_auto_ga_id_creation( test_client, ): product_id = get_product_id_by_name(ProductName.EDGE_PORT) - initial_data = [{"product": product_id}, *input_form_wizard_data] + initial_data = [{"product": product_id}, *input_form_wizard_data()] initial_data[1]["generate_ga_id"] = True initial_data[1]["ga_id"] = None result, process_stat, step_log = run_workflow("create_edge_port", initial_data) @@ -152,8 +161,8 @@ def test_edge_port_creation_with_invalid_input( ): product_id = get_product_id_by_name(ProductName.EDGE_PORT) # If the number of members is greater than 1 then LACP must be enabled. - input_form_wizard_data[0]["enable_lacp"] = False - initial_data = [{"product": product_id}, *input_form_wizard_data] + initial_data = [{"product": product_id}, *input_form_wizard_data()] + initial_data[1]["enable_lacp"] = False with pytest.raises(FormValidationError) as error: run_workflow("create_edge_port", initial_data) @@ -175,7 +184,7 @@ def test_edge_port_creation_with_existing_ga_id( ): subscription = edge_port_subscription_factory(ga_id="GA-12345") product_id = get_product_id_by_name(ProductName.EDGE_PORT) - initial_data = [{"product": product_id}, *input_form_wizard_data] + initial_data = [{"product": product_id}, *input_form_wizard_data()] with pytest.raises(FormValidationError) as error: run_workflow("create_edge_port", initial_data) -- GitLab