From dd033080fc5e8aa454baa8aab63392da400b5903 Mon Sep 17 00:00:00 2001
From: Karel van Klink <karel.vanklink@geant.org>
Date: Tue, 5 Nov 2024 11:30:45 +0100
Subject: [PATCH] NREN L3 creation workflow only allows a single edge port as
 input

---
 .../create_nren_l3_core_service.py            | 91 ++++++++-----------
 .../test_create_nren_l3_core_service.py       |  4 +-
 2 files changed, 40 insertions(+), 55 deletions(-)

diff --git a/gso/workflows/nren_l3_core_service/create_nren_l3_core_service.py b/gso/workflows/nren_l3_core_service/create_nren_l3_core_service.py
index b07c06ea..c07ad501 100644
--- a/gso/workflows/nren_l3_core_service/create_nren_l3_core_service.py
+++ b/gso/workflows/nren_l3_core_service/create_nren_l3_core_service.py
@@ -1,6 +1,6 @@
 """Create a new NREN L3 Core Service subscription including GÉANT IP and IAS."""
 
-from typing import Annotated, Any
+from typing import Any
 from uuid import uuid4
 
 from orchestrator.forms import FormPage
@@ -10,10 +10,10 @@ from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUID
 from orchestrator.workflow import StepList, begin, done, step, workflow
 from orchestrator.workflows.steps import resync, set_status, store_process_subscription
 from orchestrator.workflows.utils import wrap_create_initial_input_form
-from pydantic import AfterValidator, BaseModel, ConfigDict, Field, computed_field
+from pydantic import BaseModel, ConfigDict, Field, computed_field
 from pydantic_forms.validators import Divider
 
-from gso.products.product_blocks.bgp_session import BFDSettings, BGPSession, IPFamily
+from gso.products.product_blocks.bgp_session import BGPSession, IPFamily
 from gso.products.product_blocks.nren_l3_core_service import NRENAccessPortInactive
 from gso.products.product_blocks.service_binding_port import ServiceBindingPortInactive
 from gso.products.product_types.edge_port import EdgePort
@@ -45,24 +45,15 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         edge_port: active_edge_port_selector(partner_id=initial_user_input.partner)  # type: ignore[valid-type]
         ap_type: APType
 
-    def validate_edge_ports_are_unique(edge_ports: list[EdgePortSelection]) -> list[EdgePortSelection]:
-        """Verify if interfaces are unique."""
-        port_names = [port.edge_port for port in edge_ports]
-        if len(port_names) != len(set(port_names)):
-            msg = "Edge Ports must be unique."
-            raise ValueError(msg)
-        return edge_ports
-
     class EdgePortSelectionForm(FormPage):
         model_config = ConfigDict(title=f"{product_name} - Select Edge Ports")
         info_label: Label = Field(
             f"Please select the Edge Ports where this {product_name} service will terminate", exclude=True
         )
 
-        edge_ports: Annotated[list[EdgePortSelection], AfterValidator(validate_edge_ports_are_unique)]
+        edge_port: EdgePortSelection
 
-    selected_edge_ports = yield EdgePortSelectionForm
-    ep_list = selected_edge_ports.edge_ports
+    selected_edge_port = yield EdgePortSelectionForm
 
     class BFDSettingsForm(BaseModel):
         bfd_enabled: bool = False
@@ -70,7 +61,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         bfd_multiplier: int | None = None
 
     class BaseBGPPeer(BaseModel):
-        bfd_settings: BFDSettingsForm = BFDSettingsForm(bfd_enabled=False, bfd_interval=None, bfd_multiplier=None)
+        bfd_settings: BFDSettingsForm
         has_custom_policies: bool = False
         authentication_key: str | None = None
         multipath_enabled: bool = False
@@ -95,47 +86,41 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         def families(self) -> list[IPFamily]:
             return [IPFamily.V6UNICAST, IPFamily.V6MULTICAST] if self.add_v6_multicast else [IPFamily.V6UNICAST]
 
-    binding_port_inputs = []
-    for ep_index, edge_port in enumerate(ep_list):
-
-        class BindingPortsInputForm(FormPage):
-            model_config = ConfigDict(title=f"{product_name} - Configure Edge Ports ({ep_index + 1}/{len(ep_list)})")
-            info_label: Label = Field("Please configure the Service Binding Ports for each Edge Port.", exclude=True)
-            current_ep_label: Label = Field(
-                f"Currently configuring on {EdgePort.from_subscription(edge_port.edge_port).description} "
-                f"(Access Port type: {edge_port.ap_type})",
-                exclude=True,
-            )
-
-            geant_sid: str
-            is_tagged: bool = False
-            v4_bfd_settings: BFDSettingsForm
-            v6_bfd_settings: BFDSettingsForm
-            vlan_id: VLAN_ID
-            ipv4_address: IPv4AddressType
-            ipv4_mask: IPV4Netmask
-            ipv6_address: IPv6AddressType
-            ipv6_mask: IPV6Netmask
-            custom_firewall_filters: bool = False
-            divider: Divider = Field(None, exclude=True)
-            v4_bgp_peer: IPv4BGPPeer
-            v6_bgp_peer: IPv6BGPPeer
-
-        binding_port_input_form = yield BindingPortsInputForm
-        binding_port_inputs.append(
-            binding_port_input_form.model_dump()
-            | {
-                "bgp_peers": [
-                    binding_port_input_form.v4_bgp_peer.model_dump(),
-                    binding_port_input_form.v6_bgp_peer.model_dump(),
-                ]
-            }
+    class BindingPortInputForm(FormPage):
+        model_config = ConfigDict(title=f"{product_name} - Configure Edge Port")
+        info_label: Label = Field("Please configure the Service Binding Ports for the Edge Port.", exclude=True)
+        current_ep_label: Label = Field(
+            f"Currently configuring on {EdgePort.from_subscription(selected_edge_port.edge_port.edge_port).description}"
+            f" (Access Port type: {selected_edge_port.edge_port.ap_type})",
+            exclude=True,
         )
 
+        geant_sid: str
+        is_tagged: bool = False
+        v4_bfd_settings: BFDSettingsForm
+        v6_bfd_settings: BFDSettingsForm
+        vlan_id: VLAN_ID
+        ipv4_address: IPv4AddressType
+        ipv4_mask: IPV4Netmask
+        ipv6_address: IPv6AddressType
+        ipv6_mask: IPV6Netmask
+        custom_firewall_filters: bool = False
+        divider: Divider = Field(None, exclude=True)
+        v4_bgp_peer: IPv4BGPPeer
+        v6_bgp_peer: IPv6BGPPeer
+
+    binding_port_input_form = yield BindingPortInputForm
+    binding_port_input = binding_port_input_form.model_dump() | {
+        "bgp_peers": [
+            binding_port_input_form.v4_bgp_peer.model_dump(),
+            binding_port_input_form.v6_bgp_peer.model_dump(),
+        ]
+    }
+
     return (
         initial_user_input.model_dump()
-        | selected_edge_ports.model_dump()
-        | {"binding_port_inputs": binding_port_inputs, "product_name": product_name}
+        | selected_edge_port.model_dump()
+        | {"binding_port_input": binding_port_input, "product_name": product_name}
     )
 
 
@@ -176,7 +161,7 @@ def initialize_subscription(
 
     subscription.description = f"{product_name} service"
     partner_name = get_partner_by_id(subscription.customer_id).name
- 
+
 
     return {"subscription": subscription, "edge_port_fqdn_list": edge_port_fqdn_list, "partner_name": partner_name}
 
diff --git a/test/workflows/nren_l3_core_service/test_create_nren_l3_core_service.py b/test/workflows/nren_l3_core_service/test_create_nren_l3_core_service.py
index b1797f83..c2b582f4 100644
--- a/test/workflows/nren_l3_core_service/test_create_nren_l3_core_service.py
+++ b/test/workflows/nren_l3_core_service/test_create_nren_l3_core_service.py
@@ -49,7 +49,7 @@ def test_create_nren_l3_core_service_success(
     form_input_data = [
         {"product": product_id},
         {"tt_number": faker.tt_number(), "partner": partner["partner_id"]},
-        {"edge_ports": [{"edge_port": edge_port_a, "ap_type": APType.PRIMARY}]},
+        {"edge_port": {"edge_port": edge_port_a, "ap_type": APType.PRIMARY}},
         {
             "geant_sid": faker.geant_sid(),
             "is_tagged": faker.boolean(),
@@ -88,5 +88,5 @@ def test_create_nren_l3_core_service_success(
     assert len(subscription.nren_l3_core_service.nren_ap_list) == 1
     assert (
         str(subscription.nren_l3_core_service.nren_ap_list[0].sbp.edge_port.owner_subscription_id)
-        == form_input_data[2]["edge_ports"][0]["edge_port"]
+        == form_input_data[2]["edge_port"]["edge_port"]
     )
-- 
GitLab