From 476515df01b3a3d5b0ce041cfd956e93b6b77df8 Mon Sep 17 00:00:00 2001 From: Karel van Klink <karel.vanklink@geant.org> Date: Wed, 14 Feb 2024 13:32:49 +0100 Subject: [PATCH] add manual steps to router insertion workflow --- gso/workflows/router/update_ibgp_mesh.py | 36 ++++++++++++++++++- .../workflows/router/test_update_ibgp_mesh.py | 8 ++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/gso/workflows/router/update_ibgp_mesh.py b/gso/workflows/router/update_ibgp_mesh.py index d2f6d8d6..d8ba52a0 100644 --- a/gso/workflows/router/update_ibgp_mesh.py +++ b/gso/workflows/router/update_ibgp_mesh.py @@ -2,10 +2,12 @@ from typing import Any +from orchestrator.config.assignee import Assignee from orchestrator.forms import FormPage +from orchestrator.forms.validators import Label from orchestrator.targets import Target from orchestrator.types import FormGenerator, State, UUIDstr -from orchestrator.workflow import StepList, done, init, step, workflow +from orchestrator.workflow import StepList, done, init, inputstep, step, workflow from orchestrator.workflows.steps import resync, store_process_subscription, unsync from orchestrator.workflows.utils import wrap_modify_initial_input_form from pydantic import root_validator @@ -188,6 +190,36 @@ def add_device_to_librenms(subscription: Router) -> State: return {"librenms_device": librenms_result} +@inputstep("Prompt RADIUS insertion", assignee=Assignee.SYSTEM) +def prompt_insert_in_radius() -> FormGenerator: + """Wait for confirmation from an operator that the router has been inserted in RADIUS.""" + + class RADIUSPrompt(FormPage): + class Config: + title = "Please update RADIUS before continuing" + + info_label: Label = "Insert the router into RADIUS, and continue the workflow once this has been completed." # type: ignore[assignment] + + yield RADIUSPrompt + + return {} + + +@inputstep("Prompt RADIUS login", assignee=Assignee.SYSTEM) +def prompt_radius_login() -> FormGenerator: + """Wait for confirmation from an operator that the router can be logged into using RADIUS.""" + + class RADIUSPrompt(FormPage): + class Config: + title = "Please check RADIUS before continuing" + + info_label: Label = "Log in to the router using RADIUS, and continue the workflow when this was successful." # type: ignore[assignment] + + yield RADIUSPrompt + + return {} + + @step("Update subscription model") def update_subscription_model(subscription: Router) -> State: """Update the database model, such that it should not be reached via :term:`OOB` access anymore.""" @@ -221,6 +253,8 @@ def update_ibgp_mesh() -> StepList: >> pp_interaction(add_all_pe_to_p_real) >> pp_interaction(check_ibgp_session) >> add_device_to_librenms + >> prompt_insert_in_radius + >> prompt_radius_login >> update_subscription_model >> resync >> done diff --git a/test/workflows/router/test_update_ibgp_mesh.py b/test/workflows/router/test_update_ibgp_mesh.py index 14543066..8c7da5d5 100644 --- a/test/workflows/router/test_update_ibgp_mesh.py +++ b/test/workflows/router/test_update_ibgp_mesh.py @@ -6,7 +6,8 @@ from pydantic_forms.exceptions import FormValidationError from gso.products import Iptrunk from gso.products.product_blocks.router import RouterRole -from test.workflows import assert_pp_interaction_success, extract_state, run_workflow +from test import USER_CONFIRM_EMPTY_FORM +from test.workflows import assert_pp_interaction_success, assert_suspended, extract_state, resume_workflow, run_workflow @pytest.fixture() @@ -33,6 +34,11 @@ def test_update_ibgp_mesh_success( for _ in range(5): result, step_log = assert_pp_interaction_success(result, process_stat, step_log) + # Handle two consecutive user input steps + for _ in range(2): + assert_suspended(result) + result, step_log = resume_workflow(process_stat, step_log, input_data=USER_CONFIRM_EMPTY_FORM) + state = extract_state(result) assert mock_execute_playbook.call_count == 5 -- GitLab