diff --git a/docs/openapi.json b/docs/openapi.json index 4dd54c7e..1a4edfd3 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -145,6 +145,77 @@ "summary": "Creates a new yadage workflow." } }, + "/api/analyses/{analysis_id}/workspace": { + "post": { + "consumes": [ + "multipart/form-data" + ], + "description": "This resource expects a file to be placed in the analysis workspace identified by the UUID `analysis_id`.", + "operationId": "seed_analysis", + "parameters": [ + { + "description": "Required. Organization which the analysis belongs to.", + "in": "query", + "name": "organization", + "required": true, + "type": "string" + }, + { + "description": "Required. UUID of analysis owner.", + "in": "query", + "name": "user", + "required": true, + "type": "string" + }, + { + "description": "Required. Analysis UUID.", + "in": "path", + "name": "analysis_id", + "required": true, + "type": "string" + }, + { + "description": "Required. File to be transferred to the analysis workspace.", + "in": "formData", + "name": "file_content", + "required": true, + "type": "file" + }, + { + "description": "Required. File name.", + "in": "query", + "name": "file_name", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Request succeeded. File successfully trasferred.", + "examples": { + "application/json": { + "message": "File successfully transferred" + } + }, + "schema": { + "properties": { + "message": { + "type": "string" + } + }, + "type": "object" + } + }, + "400": { + "description": "Request failed. The incoming data specification seems malformed" + } + }, + "summary": "Seeds the analysis workspace with the provided file." + } + }, "/api/ping": { "get": { "description": "Ping the server.", diff --git a/reana_server/api_client.py b/reana_server/api_client.py index 594e9482..d671ff95 100644 --- a/reana_server/api_client.py +++ b/reana_server/api_client.py @@ -46,7 +46,9 @@ def create_openapi_client(component): try: address, spec_file = COMPONENTS_DATA[component] json_spec = get_spec(spec_file) - client = SwaggerClient.from_spec(json_spec) + client = SwaggerClient.from_spec( + json_spec, + config={'also_return_response': True}) client.swagger_spec.api_url = address return client except KeyError: diff --git a/reana_server/openapi_connections/reana_workflow_controller.json b/reana_server/openapi_connections/reana_workflow_controller.json index e8671a5d..42b2a801 100644 --- a/reana_server/openapi_connections/reana_workflow_controller.json +++ b/reana_server/openapi_connections/reana_workflow_controller.json @@ -97,6 +97,81 @@ "summary": "Returns all workflows." } }, + "/api/workflows/{workflow_id}/workspace": { + "post": { + "consumes": [ + "multipart/form-data" + ], + "description": "This resource is expecting a workflow UUID and a file to place in the workflow workspace.", + "operationId": "seed_workflow", + "parameters": [ + { + "description": "Required. Organization which the worklow belongs to.", + "in": "query", + "name": "organization", + "required": true, + "type": "string" + }, + { + "description": "Required. UUID of workflow owner.", + "in": "query", + "name": "user", + "required": true, + "type": "string" + }, + { + "description": "Required. Workflow UUID.", + "in": "path", + "name": "workflow_id", + "required": true, + "type": "string" + }, + { + "description": "Required. File to add to the workflow workspace.", + "in": "formData", + "name": "file_content", + "required": true, + "type": "file" + }, + { + "description": "Required. File name.", + "in": "query", + "name": "file_name", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Request succeeded. The file has been added to the workspace.", + "examples": { + "application/json": { + "message": "Workflow has been added to the workspace", + "workflow_id": "cdcf48b1-c2f3-4693-8230-b066e088c6ac" + } + }, + "schema": { + "properties": { + "message": { + "type": "string" + }, + "workflow_id": { + "type": "string" + } + }, + "type": "object" + } + }, + "400": { + "description": "Request failed. The incoming data specification seems malformed" + } + }, + "summary": "Adds a file to the workflow workspace." + } + }, "/api/yadage/remote": { "post": { "consumes": [ diff --git a/reana_server/rest/analyses.py b/reana_server/rest/analyses.py index d1b6a030..e79adec4 100644 --- a/reana_server/rest/analyses.py +++ b/reana_server/rest/analyses.py @@ -21,8 +21,6 @@ """Reana-Server Ping-functionality Flask-Blueprint.""" -import json - from flask import current_app as app from flask import Blueprint, jsonify, request @@ -98,10 +96,10 @@ def get_analyses(): # noqa } """ try: - res = rwc_api_client.api.get_workflows( + response, status_code = rwc_api_client.api.get_workflows( organization='default', user='00000000-0000-0000-0000-000000000000').result() - return jsonify(res), 200 + return jsonify(response), status_code except Exception as e: return jsonify({"message": str(e)}), 500 @@ -169,8 +167,8 @@ def create_analysis(): # noqa try: if request.json: # validate against schema - reana_spec_file = request.json - workflow_engine = reana_spec_file['workflow']['type'] + reana_spec = request.json + workflow_engine = reana_spec['workflow']['type'] elif request.args.get('spec'): # TODO implement load workflow engine from remote return jsonify('Not implemented'), 501 @@ -182,17 +180,94 @@ def create_analysis(): # noqa raise Exception('Unknown workflow engine') if workflow_engine == 'yadage': - if 'reana_spec_file' in locals(): + if 'reana_spec' in locals(): # From spec file - res = rwc_api_client.api.run_yadage_workflow_from_spec( - workflow={ - 'parameters': reana_spec_file['parameters'], - 'workflow_spec': reana_spec_file['workflow']['spec'], - }, - user=request.args.get('user'), - organization=request.args.get('organization')).result() - - return jsonify(res), 200 + (response, status_code) = \ + rwc_api_client.api.run_yadage_workflow_from_spec( + workflow={ + 'parameters': reana_spec['parameters'], + 'workflow_spec': reana_spec['workflow']['spec'], + }, + user=request.args.get('user'), + organization=request.args.get('organization')).result() + + return jsonify(response), status_code + except KeyError as e: + return jsonify({"message": str(e)}), 400 + except Exception as e: + return jsonify({"message": str(e)}), 500 + + +@blueprint.route('/analyses//workspace', methods=['POST']) +def seed_analysis(analysis_id): # noqa + r"""Seed analysis with files. + + --- + post: + summary: Seeds the analysis workspace with the provided file. + description: >- + This resource expects a file to be placed in the analysis workspace + identified by the UUID `analysis_id`. + operationId: seed_analysis + consumes: + - multipart/form-data + produces: + - application/json + parameters: + - name: organization + in: query + description: Required. Organization which the analysis belongs to. + required: true + type: string + - name: user + in: query + description: Required. UUID of analysis owner. + required: true + type: string + - name: analysis_id + in: path + description: Required. Analysis UUID. + required: true + type: string + - name: file_content + in: formData + description: >- + Required. File to be transferred to the analysis workspace. + required: true + type: file + - name: file_name + in: query + description: Required. File name. + required: true + type: string + responses: + 200: + description: >- + Request succeeded. File successfully trasferred. + schema: + type: object + properties: + message: + type: string + examples: + application/json: + { + "message": "File successfully transferred", + } + 400: + description: >- + Request failed. The incoming data specification seems malformed + """ + try: + file_ = request.files['file_content'].stream.read() + response, status_code = rwc_api_client.api.seed_workflow( + user=request.args['user'], + organization=request.args['organization'], + workflow_id=analysis_id, + file_content=file_, + file_name=request.args['file_name']).result() + + return jsonify(response), status_code except KeyError as e: return jsonify({"message": str(e)}), 400 except Exception as e: