Skip to content
Snippets Groups Projects
Commit 59e350ea authored by Aleksandr Kurbatov's avatar Aleksandr Kurbatov
Browse files

lso_client - resync with develop

parent 7c3ebd0c
No related branches found
No related tags found
1 merge request!267SDP mesh functions
Pipeline #89448 failed
This commit is part of merge request !267. Comments created here will be created in the context of that merge request.
...@@ -5,14 +5,14 @@ ...@@ -5,14 +5,14 @@
import json import json
import logging import logging
from typing import Any from typing import Any, Literal, TypedDict
import requests import requests
from orchestrator import step from orchestrator import step
from orchestrator.config.assignee import Assignee from orchestrator.config.assignee import Assignee
from orchestrator.types import State from orchestrator.types import State
from orchestrator.utils.errors import ProcessFailureError from orchestrator.utils.errors import ProcessFailureError
from orchestrator.workflow import Step, StepList, begin, callback_step, inputstep from orchestrator.workflow import Step, StepList, begin, callback_step, conditional, inputstep
from pydantic import ConfigDict from pydantic import ConfigDict
from pydantic_forms.core import FormPage from pydantic_forms.core import FormPage
from pydantic_forms.types import FormGenerator from pydantic_forms.types import FormGenerator
...@@ -23,6 +23,18 @@ from gso import settings ...@@ -23,6 +23,18 @@ from gso import settings
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class _LSOState(TypedDict): # noqa: PYI049
"""An expanded state that must contain at least the required keys for the execution of an Ansible playbook."""
playbook_name: str
extra_vars: dict[str, Any]
inventory: dict[Literal["all"], dict[Literal["hosts"], dict[str, Any] | None]]
__extra_values__: Any # This is feature unavailable in python 3.12
LSOState = State # FIXME: Use the above definition when python3.13 is released
def _send_request(parameters: dict, callback_route: str) -> None: def _send_request(parameters: dict, callback_route: str) -> None:
"""Send a request to :term:`LSO`. The callback address is derived using the process ID provided. """Send a request to :term:`LSO`. The callback address is derived using the process ID provided.
...@@ -48,11 +60,9 @@ def _send_request(parameters: dict, callback_route: str) -> None: ...@@ -48,11 +60,9 @@ def _send_request(parameters: dict, callback_route: str) -> None:
request.raise_for_status() request.raise_for_status()
def execute_playbook( @step("Execute Ansible playbook")
playbook_name: str, def _execute_playbook(
callback_route: str, playbook_name: str, callback_route: str, inventory: dict[str, Any], extra_vars: dict[str, Any]
inventory: dict[str, Any] | str,
extra_vars: dict[str, Any],
) -> None: ) -> None:
"""Execute a playbook remotely through the provisioning proxy. """Execute a playbook remotely through the provisioning proxy.
...@@ -71,7 +81,8 @@ def execute_playbook( ...@@ -71,7 +81,8 @@ def execute_playbook(
}, },
"host2.local": { "host2.local": {
"key": "value" "key": "value"
} },
"host3.local": None
} }
} }
} }
...@@ -141,7 +152,38 @@ def _show_results(state: State) -> FormGenerator: ...@@ -141,7 +152,38 @@ def _show_results(state: State) -> FormGenerator:
@step("Clean up keys from state") @step("Clean up keys from state")
def _clean_state() -> State: def _clean_state() -> State:
return {"__remove_keys": ["run_results", "lso_result_title", "lso_result_extra_label", "callback_result"]} return {
"__remove_keys": [
"run_results",
"lso_result_title",
"lso_result_extra_label",
"callback_result",
"playbook_name",
"callback_route",
"inventory",
"extra_vars",
]
}
def _inventory_is_set(state: State) -> bool:
"""Validate whether the passed Ansible inventory is empty.
If the inventory is empty, which can happen in select cases, there should be no playbook run. This conditional will
prevent from calling out to :term:`LSO` with an empty playbook, which would cause the Ansible runner process to
hang. This in turn will result in a workflow step that is never called back to.
"""
if "inventory" not in state:
msg = "Missing Ansible inventory for playbook."
raise ProcessFailureError(msg, details="Key 'inventory' not found in state.")
if "all" not in state["inventory"] or "hosts" not in state["inventory"]["all"]:
msg = "Malformed Ansible inventory found in state."
raise ProcessFailureError(msg, details="Ansible inventory must be in YAML form, not string.")
return state["inventory"]["all"]["hosts"]
_inventory_is_not_empty = conditional(_inventory_is_set)
def lso_interaction(provisioning_step: Step) -> StepList: def lso_interaction(provisioning_step: Step) -> StepList:
...@@ -162,9 +204,15 @@ def lso_interaction(provisioning_step: Step) -> StepList: ...@@ -162,9 +204,15 @@ def lso_interaction(provisioning_step: Step) -> StepList:
""" """
return ( return (
begin begin
>> callback_step(name=provisioning_step.name, action_step=provisioning_step, validate_step=_evaluate_results) >> provisioning_step
>> step("Inject result title")(lambda: {"lso_result_title": provisioning_step.name}) >> _inventory_is_not_empty(
>> _show_results begin
>> callback_step(
name="Running Ansible playbook", action_step=_execute_playbook, validate_step=_evaluate_results
)
>> step("Inject result title")(lambda: {"lso_result_title": provisioning_step.name})
>> _show_results
)
>> _clean_state >> _clean_state
) )
...@@ -187,9 +235,15 @@ def indifferent_lso_interaction(provisioning_step: Step) -> StepList: ...@@ -187,9 +235,15 @@ def indifferent_lso_interaction(provisioning_step: Step) -> StepList:
""" """
return ( return (
begin begin
>> callback_step(name=provisioning_step.name, action_step=provisioning_step, validate_step=_ignore_results) >> provisioning_step
>> step("Inject result title")(lambda: {"lso_result_title": provisioning_step.name}) >> _inventory_is_not_empty(
>> _show_results begin
>> callback_step(
name="Running Ansible playbook", action_step=_execute_playbook, validate_step=_ignore_results
)
>> step("Inject result title")(lambda: {"lso_result_title": provisioning_step.name})
>> _show_results
)
>> _clean_state >> _clean_state
) )
...@@ -207,6 +261,9 @@ def anonymous_lso_interaction(provisioning_step: Step, validation_step: Step = _ ...@@ -207,6 +261,9 @@ def anonymous_lso_interaction(provisioning_step: Step, validation_step: Step = _
""" """
return ( return (
begin begin
>> callback_step(name=provisioning_step.name, action_step=provisioning_step, validate_step=validation_step) >> provisioning_step
>> _inventory_is_not_empty(
callback_step(name="Running Ansible playbook", action_step=_execute_playbook, validate_step=validation_step)
)
>> _clean_state >> _clean_state
) )
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment