diff --git a/gso/workflows/l2_circuit/migrate_layer_2_circuit.py b/gso/workflows/l2_circuit/migrate_layer_2_circuit.py
index d6d4a8f8a7c1529385544cb96055a31ecaaa4e31..70a91e5aaaf24c274ca510bb9121e3b2ac37a882 100644
--- a/gso/workflows/l2_circuit/migrate_layer_2_circuit.py
+++ b/gso/workflows/l2_circuit/migrate_layer_2_circuit.py
@@ -26,7 +26,7 @@ from orchestrator.forms import FormPage, SubmitFormPage
from orchestrator.forms.validators import Choice, Label
from orchestrator.targets import Target
from orchestrator.utils.errors import ProcessFailureError
-from orchestrator.workflow import StepList, begin, done
+from orchestrator.workflow import StepList, begin, conditional, done
from orchestrator.workflows.steps import resync, store_process_subscription, unsync
from orchestrator.workflows.utils import wrap_modify_initial_input_form
from pydantic import ConfigDict, Field
@@ -75,6 +75,11 @@ def input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
label_a: Label = Field("Are we migrating to a different site?", exclude=True)
migrate_to_different_site: bool = False
+ label_b: Label = Field("Execute Ansible playbooks on the OLD side of the circuit?", exclude=True)
+ run_old_side_ansible: bool = True
+ label_c: Label = Field("Execute Ansible playbooks on the NEW side of the circuit?", exclude=True)
+ run_new_side_ansible: bool = True
+
initial_user_input = yield MigrateL2CircuitForm
replace_side_partner = get_partner_by_id(EdgePort.from_subscription(initial_user_input.replace_side).customer_id)
@@ -87,6 +92,8 @@ def input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
return {
"tt_number": initial_user_input.tt_number,
+ "run_old_side_ansible": initial_user_input.run_old_side_ansible,
+ "run_new_side_ansible": initial_user_input.run_new_side_ansible,
"subscription": subscription,
"subscription_id": subscription_id,
"old_edge_port": initial_user_input.replace_side,
@@ -124,19 +131,22 @@ def update_subscription_model(subscription: Layer2Circuit, old_edge_port: UUIDst
)
def migrate_layer_2_circuit() -> StepList:
"""Migrate a Layer 2 Circuit."""
+ run_old_side_ansible = conditional(lambda state: state["run_old_side_ansible"])
+ run_new_side_ansible = conditional(lambda state: state["run_new_side_ansible"])
+
return (
begin
>> store_process_subscription(Target.MODIFY)
>> unsync
- >> generate_fqdn_list
- >> extract_partner_name_from_edge_port
- >> lso_interaction(terminate_l2circuit_dry)
- >> lso_interaction(terminate_l2circuit_real)
+ >> run_old_side_ansible(generate_fqdn_list)
+ >> run_old_side_ansible(extract_partner_name_from_edge_port)
+ >> run_old_side_ansible(lso_interaction(terminate_l2circuit_dry))
+ >> run_old_side_ansible(lso_interaction(terminate_l2circuit_real))
>> update_subscription_model
- >> generate_fqdn_list
- >> extract_partner_name_from_edge_port
- >> lso_interaction(provision_l2circuit_dry)
- >> lso_interaction(provision_l2circuit_real)
+ >> run_new_side_ansible(generate_fqdn_list)
+ >> run_new_side_ansible(extract_partner_name_from_edge_port)
+ >> run_new_side_ansible(lso_interaction(provision_l2circuit_dry))
+ >> run_new_side_ansible(lso_interaction(provision_l2circuit_real))
>> resync
>> done
)
diff --git a/gso/workflows/l2_circuit/modify_layer_2_circuit.py b/gso/workflows/l2_circuit/modify_layer_2_circuit.py
index 120ba474de4d3bc306b6b3c6a025a4310be02110..ae879037c0700a515ca7d2507fbad6eba7d83715 100644
--- a/gso/workflows/l2_circuit/modify_layer_2_circuit.py
+++ b/gso/workflows/l2_circuit/modify_layer_2_circuit.py
@@ -3,7 +3,7 @@
from orchestrator import begin, done, workflow
from orchestrator.forms import FormPage, SubmitFormPage
from orchestrator.targets import Target
-from orchestrator.workflow import StepList, step
+from orchestrator.workflow import StepList, conditional, step
from orchestrator.workflows.steps import resync, store_process_subscription, unsync
from orchestrator.workflows.utils import wrap_modify_initial_input_form
from pydantic import BaseModel, ConfigDict, Field
@@ -43,6 +43,9 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
policer_enabled: bool = subscription.layer_2_circuit.policer_enabled
custom_service_name: str | None = subscription.layer_2_circuit.custom_service_name
+ label: Label = Field("Should this workflow execute Ansible playbooks on routers?", exclude=True)
+ run_ansible_steps: bool = True
+
layer_2_circuit_input = yield ModifyL2CircuitForm
class ModifyLayer2CircuitServiceSidesPage(SubmitFormPage):
@@ -134,15 +137,17 @@ def modify_layer_2_circuit_subscription(
)
def modify_layer_2_circuit() -> StepList:
"""Modify an existing Layer 2 Circuit service subscription."""
+ run_ansible_steps = conditional(lambda state: state["run_ansible_steps"])
+
return (
begin
>> store_process_subscription(Target.MODIFY)
>> unsync
- >> generate_fqdn_list
- >> extract_partner_name_from_edge_port
+ >> run_ansible_steps(generate_fqdn_list)
+ >> run_ansible_steps(extract_partner_name_from_edge_port)
>> modify_layer_2_circuit_subscription
- >> lso_interaction(provision_l2circuit_dry)
- >> lso_interaction(provision_l2circuit_real)
+ >> run_ansible_steps(lso_interaction(provision_l2circuit_dry))
+ >> run_ansible_steps(lso_interaction(provision_l2circuit_real))
>> resync
>> done
)
diff --git a/gso/workflows/l2_circuit/terminate_layer_2_circuit.py b/gso/workflows/l2_circuit/terminate_layer_2_circuit.py
index 223523b55b786151d9a3e6653d68eb0163281665..bab755eb824c8d92f0ed1e91d815eaf6a9df1fb4 100644
--- a/gso/workflows/l2_circuit/terminate_layer_2_circuit.py
+++ b/gso/workflows/l2_circuit/terminate_layer_2_circuit.py
@@ -4,10 +4,12 @@ from orchestrator import begin, workflow
from orchestrator.forms import SubmitFormPage
from orchestrator.targets import Target
from orchestrator.types import SubscriptionLifecycle
-from orchestrator.workflow import StepList, done
+from orchestrator.workflow import StepList, conditional, done
from orchestrator.workflows.steps import resync, set_status, store_process_subscription, unsync
from orchestrator.workflows.utils import wrap_modify_initial_input_form
+from pydantic import Field
from pydantic_forms.types import FormGenerator, UUIDstr
+from pydantic_forms.validators import Label
from gso.products.product_types.layer_2_circuit import Layer2Circuit
from gso.services.lso_client import lso_interaction
@@ -26,6 +28,9 @@ def _input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
class TerminateForm(SubmitFormPage):
tt_number: TTNumber
+ label: Label = Field("Should this workflow run Ansible playbooks to remove configuration from routers?")
+ run_ansible_steps: bool = True
+
user_input = yield TerminateForm
return {"subscription": layer_2_circuit} | user_input.model_dump()
@@ -37,14 +42,16 @@ def _input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
)
def terminate_layer_2_circuit() -> StepList:
"""Terminate a Layer 2 Circuit subscription."""
+ run_ansible_steps = conditional(lambda state: state["run_ansible_steps"])
+
return (
begin
>> store_process_subscription(Target.TERMINATE)
>> unsync
- >> generate_fqdn_list
- >> extract_partner_name_from_edge_port
- >> lso_interaction(terminate_l2circuit_dry)
- >> lso_interaction(terminate_l2circuit_real)
+ >> run_ansible_steps(generate_fqdn_list)
+ >> run_ansible_steps(extract_partner_name_from_edge_port)
+ >> run_ansible_steps(lso_interaction(terminate_l2circuit_dry))
+ >> run_ansible_steps(lso_interaction(terminate_l2circuit_real))
>> set_status(SubscriptionLifecycle.TERMINATED)
>> resync
>> done
diff --git a/test/workflows/l2_circuit/test_migrate_layer_2_circuit.py b/test/workflows/l2_circuit/test_migrate_layer_2_circuit.py
index efc1c8495cf6d37e309ef4f68724f18133fe9f9c..9c016cd28a5abbbd1a3d9cfd8572eeb78c5fedff 100644
--- a/test/workflows/l2_circuit/test_migrate_layer_2_circuit.py
+++ b/test/workflows/l2_circuit/test_migrate_layer_2_circuit.py
@@ -10,9 +10,13 @@ from test.workflows import assert_complete, assert_lso_interaction_success, extr
@pytest.mark.workflow()
@pytest.mark.parametrize("layer_2_circuit_service_type", LAYER_2_CIRCUIT_SERVICE_TYPES)
+@pytest.mark.parametrize("run_old_side_ansible", [False, True])
+@pytest.mark.parametrize("run_new_side_ansible", [False, True])
@patch("gso.services.lso_client._send_request")
def test_migrate_layer_2_circuit(
mock_lso_interaction,
+ run_new_side_ansible,
+ run_old_side_ansible,
layer_2_circuit_service_type,
layer_2_circuit_subscription_factory,
edge_port_subscription_factory,
@@ -33,13 +37,19 @@ def test_migrate_layer_2_circuit(
"tt_number": faker.tt_number(),
"replace_side": old_edge_port.subscription_id,
"migrate_to_different_site": False,
+ "run_old_side_ansible": run_old_side_ansible,
+ "run_new_side_ansible": run_new_side_ansible,
},
{"new_edge_port": new_edge_port.subscription_id},
]
result, process_stat, step_log = run_workflow("migrate_layer_2_circuit", initial_layer_2_circuit_data)
- for _ in range(4):
+ lso_step_count = 0
+ lso_step_count += 2 if run_old_side_ansible else 0
+ lso_step_count += 2 if run_new_side_ansible else 0
+
+ for _ in range(lso_step_count):
result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
assert_complete(result)
@@ -48,7 +58,7 @@ def test_migrate_layer_2_circuit(
subscription_id = state["subscription_id"]
subscription = Layer2Circuit.from_subscription(subscription_id)
assert subscription.status == "active"
- assert mock_lso_interaction.call_count == 4
+ assert mock_lso_interaction.call_count == lso_step_count
replaced_edge_port = subscription.layer_2_circuit.layer_2_circuit_sides[1].sbp.edge_port
assert replaced_edge_port.model_dump(exclude="edge_port_ae_members") == new_edge_port.edge_port.model_dump(
diff --git a/test/workflows/l2_circuit/test_modify_layer_2_circuit.py b/test/workflows/l2_circuit/test_modify_layer_2_circuit.py
index da4dcb6c8dffbef64ff2d7ef5ab1df1a18cd3761..e4f4dcce33efeabe2dac11c54a41b014577ab0de 100644
--- a/test/workflows/l2_circuit/test_modify_layer_2_circuit.py
+++ b/test/workflows/l2_circuit/test_modify_layer_2_circuit.py
@@ -9,11 +9,13 @@ from test.workflows import assert_complete, assert_lso_interaction_success, extr
@pytest.mark.parametrize("layer_2_circuit_service_type", LAYER_2_CIRCUIT_SERVICE_TYPES)
+@pytest.mark.parametrize("run_ansible_steps", [False, True])
@pytest.mark.workflow()
@patch("gso.services.lso_client._send_request")
def test_modify_layer_2_circuit_change_policer_bandwidth(
mock_lso_interaction,
layer_2_circuit_service_type,
+ run_ansible_steps,
layer_2_circuit_subscription_factory,
faker,
partner_factory,
@@ -26,6 +28,7 @@ def test_modify_layer_2_circuit_change_policer_bandwidth(
"layer_2_circuit_type": Layer2CircuitType.VLAN,
"policer_enabled": False,
"custom_service_name": faker.sentence(),
+ "run_ansible_steps": run_ansible_steps,
},
{
"vlan_range_lower_bound": subscription.layer_2_circuit.vlan_range_lower_bound,
@@ -38,12 +41,14 @@ def test_modify_layer_2_circuit_change_policer_bandwidth(
]
result, process_stat, step_log = run_workflow("modify_layer_2_circuit", input_form_data)
- for _ in range(2):
+ lso_step_count = 2 if run_ansible_steps else 0
+
+ for _ in range(lso_step_count):
result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
subscription = Layer2Circuit.from_subscription(str(subscription.subscription_id))
assert_complete(result)
- assert mock_lso_interaction.call_count == 2
+ assert mock_lso_interaction.call_count == lso_step_count
assert subscription.status == SubscriptionLifecycle.ACTIVE
assert subscription.layer_2_circuit.policer_enabled is False
assert subscription.layer_2_circuit.bandwidth is None
@@ -63,11 +68,13 @@ def test_modify_layer_2_circuit_change_policer_bandwidth(
@pytest.mark.parametrize("layer_2_circuit_service_type", LAYER_2_CIRCUIT_SERVICE_TYPES)
+@pytest.mark.parametrize("run_ansible_steps", [False, True])
@pytest.mark.workflow()
@patch("gso.services.lso_client._send_request")
def test_modify_layer_2_circuit_change_circuit_type(
mock_lso_interaction,
layer_2_circuit_service_type,
+ run_ansible_steps,
layer_2_circuit_subscription_factory,
faker,
partner_factory,
@@ -78,6 +85,7 @@ def test_modify_layer_2_circuit_change_circuit_type(
{
"tt_number": faker.tt_number(),
"layer_2_circuit_type": Layer2CircuitType.ETHERNET,
+ "run_ansible_steps": run_ansible_steps,
},
{
"vlan_range_lower_bound": None,
@@ -89,13 +97,15 @@ def test_modify_layer_2_circuit_change_circuit_type(
]
result, process_stat, step_log = run_workflow("modify_layer_2_circuit", input_form_data)
- for _ in range(2):
+ lso_step_count = 2 if run_ansible_steps else 0
+
+ for _ in range(lso_step_count):
result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
assert_complete(result)
state = extract_state(result)
subscription = Layer2Circuit.from_subscription(state["subscription_id"])
- assert mock_lso_interaction.call_count == 2
+ assert mock_lso_interaction.call_count == lso_step_count
assert subscription.status == SubscriptionLifecycle.ACTIVE
assert subscription.layer_2_circuit.vlan_range_lower_bound is None
assert subscription.layer_2_circuit.vlan_range_upper_bound is None
diff --git a/test/workflows/l2_circuit/test_terminate_layer_2_circuit.py b/test/workflows/l2_circuit/test_terminate_layer_2_circuit.py
index 2d5a26606f26c37836f4f51719cc0993e42a30b4..55deedededc9c3c43ef3ca56d6145508cbf7f5d4 100644
--- a/test/workflows/l2_circuit/test_terminate_layer_2_circuit.py
+++ b/test/workflows/l2_circuit/test_terminate_layer_2_circuit.py
@@ -8,17 +8,23 @@ from test.workflows import assert_complete, assert_lso_interaction_success, extr
@pytest.mark.workflow()
@pytest.mark.parametrize("layer_2_circuit_service_type", LAYER_2_CIRCUIT_SERVICE_TYPES)
+@pytest.mark.parametrize("run_ansible_steps", [True, False])
@patch("gso.services.lso_client._send_request")
def test_terminate_layer_2_circuit(
- mock_lso_interaction, layer_2_circuit_service_type, layer_2_circuit_subscription_factory, faker
+ mock_lso_interaction, layer_2_circuit_service_type, run_ansible_steps, layer_2_circuit_subscription_factory, faker
):
subscription_id = str(
layer_2_circuit_subscription_factory(layer_2_circuit_service_type=layer_2_circuit_service_type).subscription_id
)
- initial_layer_2_circuit_data = [{"subscription_id": subscription_id}, {"tt_number": faker.tt_number()}]
+ initial_layer_2_circuit_data = [
+ {"subscription_id": subscription_id},
+ {"tt_number": faker.tt_number(), "run_ansible_steps": run_ansible_steps},
+ ]
result, process_stat, step_log = run_workflow("terminate_layer_2_circuit", initial_layer_2_circuit_data)
- for _ in range(2):
+ lso_step_count = 2 if run_ansible_steps else 0
+
+ for _ in range(lso_step_count):
result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
assert_complete(result)
@@ -27,4 +33,4 @@ def test_terminate_layer_2_circuit(
subscription_id = state["subscription_id"]
subscription = Layer2Circuit.from_subscription(subscription_id)
assert subscription.status == "terminated"
- assert mock_lso_interaction.call_count == 2
+ assert mock_lso_interaction.call_count == lso_step_count