diff --git a/services/workflow/test/test_workflow_service_rest_api.py b/services/workflow/test/test_workflow_service_rest_api.py index 0ea2197c4f28048a2ee1569969a43d00b12d31b4..6e7d5df752e2f3a367012e3a62cb3a23a95d202e 100644 --- a/services/workflow/test/test_workflow_service_rest_api.py +++ b/services/workflow/test/test_workflow_service_rest_api.py @@ -21,6 +21,7 @@ import datetime import http +import logging from unittest.mock import MagicMock import pytest @@ -31,6 +32,8 @@ from workspaces.workflow.schema import Workflow, WorkflowRequest from workspaces.workflow.services.workflow_info import WorkflowInfo from workspaces.workflow.services.workflow_service import WorkflowService +logger = logging.getLogger(__name__) + @pytest.fixture def workflow() -> Workflow: @@ -184,6 +187,34 @@ def test_send_carta_url_to_aat(workflow_request_request: DummyRequest): workflow_request_request.json_body = body_savepoint +def test_send_do_not_calibate_msg_to_aat(workflow_request_request: DummyRequest): + """ + Confirm that "Do Not Calibrate" message is sent to AAT with appropriate parameters + + :param workflow_request_request: + :return: + """ + # Init dummy request values + matchdict_savepoint = workflow_request_request.matchdict + body_savepoint = workflow_request_request.json_body + request_id = -1 + workflow_request_request.matchdict["request_id"] = request_id + sdm_id = "brain_000.58099.67095825232" + + # Mock out WorkflowService method call side effect + workflow_request_request.workflows.send_do_not_calibrate = MagicMock() + expected_response = f"SUCCESS for request #{request_id}: Sent 'Do Not Calibrate' for {sdm_id} to AAT" + try: + response = WorkflowRequestRestService(workflow_request_request).send_do_not_calibrate(request_id, sdm_id) + workflow_request_request.workflows.send_do_not_calibrate.assert_called_with(request_id, sdm_id) + assert response.status_code == http.HTTPStatus.OK + assert response.text == expected_response + finally: + # Reset dummy request properties to their initial values + workflow_request_request.matchdict = matchdict_savepoint + workflow_request_request.json_body = body_savepoint + + def test_get_request_htcondor_id(workflow_request_request: DummyRequest): matchdict_savepoint = workflow_request_request.matchdict workflow_request_request.matchdict["request_id"] = -1 diff --git a/services/workflow/workflow/server.py b/services/workflow/workflow/server.py index a71d2347f52223c4f37c9f4087c23dac4c6e987d..c9fdaea87cb9db31ff7dfd53de8c86d220cf6bd3 100644 --- a/services/workflow/workflow/server.py +++ b/services/workflow/workflow/server.py @@ -325,6 +325,19 @@ class WorkflowRequestRestService: body=f"SUCCESS: Sent CARTA URL {carta_url} to Workspaces System", ) + @view_config(request_method="POST", route_name="send_do_not_calibrate") + def send_do_not_calibrate(self, request_id: str, sdm_id: str): + """ + Pyramid view that sends a "Do Not Calibrate" message to the Workspaces system + + return: 200 (OK) HTTP Response + """ + self.request.workflows.send_do_not_calibrate(request_id, sdm_id) + return Response( + status_code=http.HTTPStatus.OK, + body=f"SUCCESS for request #{request_id}: Sent 'Do Not Calibrate' for {sdm_id} to AAT", + ) + @view_config(request_method="POST", route_name="announce_qa") def announce_qa(self): """ diff --git a/shared/workspaces/workspaces/workflow/enum.py b/shared/workspaces/workspaces/workflow/enum.py index 5b2a2ba6d17c07c0905b09176cd26624d1ad439a..ce7962c797cfa8cf53f5e95a1a4441106a17365d 100644 --- a/shared/workspaces/workspaces/workflow/enum.py +++ b/shared/workspaces/workspaces/workflow/enum.py @@ -15,6 +15,10 @@ # # You should have received a copy of the GNU General Public License # along with Workspaces. If not, see <https://www.gnu.org/licenses/>. + +# pylint: disable=C0116, R0903, W0406 + +""" Useful enums for workflows """ from enum import Enum @@ -36,6 +40,7 @@ class ArchiveWorkflows(Enum): CARTA = "carta" SECI = "vlass_seci" + DO_NOT_CALIBRATE = "do_not_calibrate" @classmethod def values(cls): diff --git a/shared/workspaces/workspaces/workflow/services/workflow_service.py b/shared/workspaces/workspaces/workflow/services/workflow_service.py index 260174494f36f11a0d6df4e73f4c254129885fc3..d0deb2a7ed96eda40bb81ac40d152b967a888473 100644 --- a/shared/workspaces/workspaces/workflow/services/workflow_service.py +++ b/shared/workspaces/workspaces/workflow/services/workflow_service.py @@ -38,7 +38,10 @@ from requests import Response from workspaces.system.services.remote_processing_service import CapoInjector from workspaces.workflow.enum import ArchiveWorkflows, WorkflowRequestState -from workspaces.workflow.message_architect import ArchiveMessageArchitect, WorkflowMessageArchitect +from workspaces.workflow.message_architect import ( + ArchiveMessageArchitect, + WorkflowMessageArchitect, +) from workspaces.workflow.schema import Workflow, WorkflowRequest, WorkflowRequestFile from workspaces.workflow.services.interfaces import WorkflowInfoIF, WorkflowServiceIF @@ -675,6 +678,8 @@ class WorkflowMessageHandler: else: status = "Unknown" + logger.info(f">>> message type: {message['type']}") + raise ValueError() logger.info( "Updating state on workflow request %s to %s...", request.workflow_request_id, @@ -725,6 +730,25 @@ class WorkflowMessageHandler: ) self.archive_messenger.send_message(**seci_msg) + def send_do_not_calibrate_message(self, **message: Dict): + """ + Tell the archive to set specified SDM to "Do Not Calibrate". + + :param message: message containing key-value pairs + :return: + """ + subject = message["subject"] + wf_id = subject["workflow_request_id"] + sdm_id = subject["fileset_id"] + wf_request = self.info.lookup_workflow_request(wf_id) + + if wf_request.workflow_name == ArchiveWorkflows.DO_NOT_CALIBRATE.value: + logger.info(f"SENDING 'DO NOT CALIBRATE' MESSAGE to AAT for request #{wf_id}!") + dnc_msg = ArchiveMessageArchitect( + routing_key="qa-script.fail", request=wf_id, sdm_id=sdm_id + ).compose_message("qa_fail") + self.archive_messenger.send_message(**dnc_msg) + def clean_remote_workflow(self, request: WorkflowRequest): injector = CapoInjector(request)