Source code for reana_workflow_controller.rest.workflows_session

# -*- coding: utf-8 -*-
#
# This file is part of REANA.
# Copyright (C) 2020, 2021 CERN.
#
# REANA is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.

"""REANA Workflow Controller interactive sessions REST API."""


from flask import Blueprint, jsonify, request
from reana_db.utils import _get_workflow_with_uuid_or_name
from reana_db.models import WorkflowSession, InteractiveSessionType, RunStatus

from reana_workflow_controller.workflow_run_manager import KubernetesWorkflowRunManager


blueprint = Blueprint("workflows_session", __name__)


[docs]@blueprint.route( "/workflows/<workflow_id_or_name>/open/" "<interactive_session_type>", methods=["POST"], ) def open_interactive_session(workflow_id_or_name, interactive_session_type): # noqa r"""Start an interactive session inside the workflow workspace. --- post: summary: Start an interactive session inside the workflow workspace. description: >- This resource is expecting a workflow to start an interactive session within its workspace. operationId: open_interactive_session consumes: - application/json produces: - application/json parameters: - name: user in: query description: Required. UUID of workflow owner. required: true type: string - name: workflow_id_or_name in: path description: Required. Workflow UUID or name. required: true type: string - name: interactive_session_type in: path description: >- Optional. Type of interactive session to use, by default Jupyter Notebook. required: false type: string - name: interactive_session_configuration in: body description: >- Interactive session configuration. required: false schema: type: object properties: image: type: string description: >- Replaces the default Docker image of an interactive session. responses: 200: description: >- Request succeeded. The interactive session has been opened. schema: type: object properties: path: type: string examples: application/json: { "path": "/dd4e93cf-e6d0-4714-a601-301ed97eec60", } 400: description: >- Request failed. The incoming data specification seems malformed. examples: application/json: { "message": "Malformed request." } 404: description: >- Request failed. Either User or Workflow does not exist. examples: application/json: { "message": "Interactive session type terminl not found, try with one of: [jupyter]" } application/json: { "message": "Workflow 256b25f4-4cfb-4684-b7a8-73872ef455a1 does not exist" } 500: description: >- Request failed. Internal controller error. """ try: if interactive_session_type not in InteractiveSessionType.__members__: return ( jsonify( { "message": "Interactive session type {0} not found, try " "with one of: {1}".format( interactive_session_type, [e.name for e in InteractiveSessionType], ) } ), 404, ) interactive_session_configuration = request.json if request.is_json else {} user_uuid = request.args["user"] workflow = None workflow = _get_workflow_with_uuid_or_name(workflow_id_or_name, user_uuid) if workflow.sessions.first() is not None: return ( jsonify({"message": "Interactive session is already open"}), 404, ) if workflow.status == RunStatus.deleted: return ( jsonify( { "message": "Interactive session can't be opened from a deleted workflow" } ), 404, ) kwrm = KubernetesWorkflowRunManager(workflow) access_path = kwrm.start_interactive_session( interactive_session_type, image=interactive_session_configuration.get("image", None), ) return jsonify({"path": "{}".format(access_path)}), 200 except (KeyError, ValueError) as e: status_code = 400 if workflow else 404 return jsonify({"message": str(e)}), status_code except Exception as e: return jsonify({"message": str(e)}), 500
[docs]@blueprint.route("/workflows/<workflow_id_or_name>/close", methods=["POST"]) def close_interactive_session(workflow_id_or_name): # noqa r"""Close an interactive workflow session. --- post: summary: Close an interactive workflow session. description: >- This resource is expecting a workflow to close an interactive session within its workspace. operationId: close_interactive_session consumes: - application/json produces: - application/json parameters: - name: user in: query description: Required. UUID of workflow owner. required: true type: string - name: workflow_id_or_name in: path description: Required. Workflow UUID or name. required: true type: string responses: 200: description: >- Request succeeded. The interactive session has been closed. schema: type: object properties: message: type: string examples: application/json: { "message": "The interactive session has been closed", } 400: description: >- Request failed. The incoming data specification seems malformed. examples: application/json: { "message": "Malformed request." } 404: description: >- Request failed. Either User or Workflow does not exist. examples: application/json: { "message": "Workflow 256b25f4-4cfb-4684-b7a8-73872ef455a1 does not exist" } 500: description: >- Request failed. Internal controller error. """ try: user_uuid = request.args["user"] workflow = None workflow = _get_workflow_with_uuid_or_name(workflow_id_or_name, user_uuid) int_session = workflow.sessions.first() if not int_session: return ( jsonify( { "message": "Workflow - {} has no open interactive session.".format( workflow_id_or_name ) } ), 404, ) kwrm = KubernetesWorkflowRunManager(workflow) kwrm.stop_interactive_session(int_session.id_) return jsonify({"message": "The interactive session has been closed"}), 200 except (KeyError, ValueError) as e: status_code = 400 if workflow else 404 return jsonify({"message": str(e)}), status_code except Exception as e: return jsonify({"message": str(e)}), 500