diff --git a/gso/workflows/vrf/modify_vrf_router_list.py b/gso/workflows/vrf/modify_vrf_router_list.py index d198d8f9738d6e9ea9d0160c9af74a4e94676018..efa7e531edf856673aa04cec984b307ce843b8e8 100644 --- a/gso/workflows/vrf/modify_vrf_router_list.py +++ b/gso/workflows/vrf/modify_vrf_router_list.py @@ -1,6 +1,6 @@ """Modify VRF to add or remove routers.""" -from typing import Annotated +from typing import Annotated, Any from orchestrator.forms import FormPage from orchestrator.targets import Target @@ -13,7 +13,9 @@ from pydantic_forms.validators import validate_unique_list from gso.products.product_types.router import Router from gso.products.product_types.vrf import VRF +from gso.services.lso_client import LSOState, lso_interaction from gso.utils.helpers import active_router_selector +from gso.utils.types.tt_number import TTNumber def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: @@ -25,6 +27,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: class ModifyVRFRouterListForm(FormPage): model_config = ConfigDict(title=f"Modify the {subscription.vrf.vrf_name} VRF to add or remove routers.") + tt_number: TTNumber router_list: Annotated[ list[RouterSelection], @@ -51,6 +54,48 @@ def update_subscription_model(subscription: VRF, router_list: list[dict[str, UUI return {"subscription": subscription} +@step("[DRY RUN] Update VRF on list of routers") +def update_vrf_on_routers_dry( + subscription: dict[str, Any], process_id: UUIDstr, tt_number: str, router_list: list[dict[str, UUIDstr]] +) -> LSOState: + """Deploy VRF on a list of routers - Dry run.""" + vrf_new_router_list = [Router.from_subscription(router["router_id"]) for router in router_list] + inventory = {"all": {"hosts": {router.router.router_fqdn: None for router in vrf_new_router_list}}} + extra_vars = { + "subscription": subscription, + "dry_run": True, + "verb": "update", + "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - " + f"Deploy config for {subscription["description"]}", + } + return { + "playbook_name": "gap_ansible/playbooks/vrf_update.yaml", + "inventory": inventory, + "extra_vars": extra_vars, + } + + +@step("[FOR REAL] Update VRF on list of routers") +def update_vrf_on_routers_real( + subscription: dict[str, Any], process_id: UUIDstr, tt_number: str, router_list: list[dict[str, UUIDstr]] +) -> LSOState: + """Deploy VRF on a list of routers - with commit.""" + vrf_new_router_list = [Router.from_subscription(router["router_id"]) for router in router_list] + inventory = {"all": {"hosts": {router.router.router_fqdn: None for router in vrf_new_router_list}}} + extra_vars = { + "subscription": subscription, + "dry_run": False, + "verb": "update", + "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - " + f"Deploy config for {subscription["description"]}", + } + return { + "playbook_name": "gap_ansible/playbooks/vrf_update.yaml", + "inventory": inventory, + "extra_vars": extra_vars, + } + + @workflow( "Modify VRF router list", initial_input_form=wrap_modify_initial_input_form(initial_input_form_generator), @@ -58,4 +103,13 @@ def update_subscription_model(subscription: VRF, router_list: list[dict[str, UUI ) def modify_vrf_router_list() -> StepList: """Modify the VRF router list.""" - return begin >> store_process_subscription(Target.MODIFY) >> unsync >> update_subscription_model >> resync >> done + return ( + begin + >> store_process_subscription(Target.MODIFY) + >> unsync + >> lso_interaction(update_vrf_on_routers_dry) + >> lso_interaction(update_vrf_on_routers_real) + >> update_subscription_model + >> resync + >> done + ) diff --git a/test/workflows/vrf/test_modify_vrf_router_list.py b/test/workflows/vrf/test_modify_vrf_router_list.py index 97f046561e503cb31eecd0e3f441911fc1a8318d..7a5bd14f79a52323580dbf8a5549654e4c98093d 100644 --- a/test/workflows/vrf/test_modify_vrf_router_list.py +++ b/test/workflows/vrf/test_modify_vrf_router_list.py @@ -1,22 +1,28 @@ import uuid +from unittest.mock import patch import pytest from pydantic_forms.exceptions import FormValidationError from gso.products.product_types.vrf import VRF -from test.workflows import assert_complete, extract_state, run_workflow +from test.workflows import assert_complete, assert_lso_interaction_success, extract_state, run_workflow @pytest.mark.workflow() -def test_modify_vrf_router_list(vrf_subscription_factory, router_subscription_factory, faker): +@patch("gso.services.lso_client._send_request") +def test_modify_vrf_router_list(mock_lso_call, vrf_subscription_factory, router_subscription_factory, faker): subscription_id = vrf_subscription_factory() initial_vrf_data = [ {"subscription_id": subscription_id}, { "router_list": [{"router_id": router_subscription_factory()}, {"router_id": router_subscription_factory()}], + "tt_number": faker.tt_number(), }, ] - result, _, _ = run_workflow("modify_vrf_router_list", initial_vrf_data) + result, process_stat, step_log = run_workflow("modify_vrf_router_list", initial_vrf_data) + for _ in range(2): + result, step_log = assert_lso_interaction_success(result, process_stat, step_log) + assert_complete(result) state = extract_state(result) @@ -24,6 +30,7 @@ def test_modify_vrf_router_list(vrf_subscription_factory, router_subscription_fa subscription = VRF.from_subscription(subscription_id) assert subscription.status == "active" assert len(subscription.vrf.vrf_router_list) == 2 + assert mock_lso_call.call_count == 2 @pytest.mark.workflow() @@ -31,9 +38,7 @@ def test_modify_vrf_router_list_with_invalid_router_id(vrf_subscription_factory, subscription_id = vrf_subscription_factory() initial_vrf_data = [ {"subscription_id": subscription_id}, - { - "router_list": [{"router_id": uuid.uuid4()}], - }, + {"router_list": [{"router_id": uuid.uuid4()}], "tt_number": faker.tt_number()}, ] with pytest.raises(FormValidationError, match="Input should be an instance of Select a router"): @@ -46,9 +51,7 @@ def test_modify_vrf_router_list_with_duplicate_router_id(vrf_subscription_factor router_id = router_subscription_factory() initial_vrf_data = [ {"subscription_id": subscription_id}, - { - "router_list": [{"router_id": router_id}, {"router_id": router_id}], - }, + {"router_list": [{"router_id": router_id}, {"router_id": router_id}], "tt_number": faker.tt_number()}, ] with pytest.raises(FormValidationError, match="List must be unique"):