Skip to content

Commit

Permalink
api: add seeding endpoint
Browse files Browse the repository at this point in the history
* Adds a redundant field `file_name` since bravado client doesn't
  propagate the file name. Waiting for Yelp/bravado-core#201 to be
  implemented.

Signed-off-by: Diego Rodriguez <diego.rodriguez@cern.ch>
  • Loading branch information
Diego Rodriguez committed Oct 19, 2017
1 parent adfa618 commit 2fc1586
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 27 deletions.
79 changes: 75 additions & 4 deletions docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"paths": {
"/api/analyses": {
"get": {
"description": "This resource return all analyses in JSON format.",
"description": "This resource return all current analyses in JSON format.",
"produces": [
"application/json"
],
Expand Down Expand Up @@ -74,13 +74,13 @@
}
}
},
"summary": "Returns list of all analyses."
"summary": "Returns list of all current analyses in REANA."
},
"post": {
"consumes": [
"application/json"
],
"description": "This resource is expecting JSON data with all the necessary informations to instantiate a yadage workflow.",
"description": "This resource is expecting JSON data with all the necessary information to instantiate a yadage workflow.",
"operationId": "create_analysis",
"parameters": [
{
Expand Down Expand Up @@ -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 which will 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.",
Expand Down Expand Up @@ -179,4 +250,4 @@
},
"swagger": "2.0",
"tags": []
}
}
11 changes: 8 additions & 3 deletions reana_server/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@
def get_spec(spec_file):
"""Get json specification from package data."""
spec_file_path = os.path.join(
pkg_resources.resource_filename('reana_server',
'openapi_connections'),
pkg_resources.
resource_filename(
'reana_server',
'openapi_connections'),
spec_file)

with open(spec_file_path) as f:
json_spec = json.load(f)
return json_spec
Expand All @@ -46,7 +49,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:
Expand Down
75 changes: 75 additions & 0 deletions reana_server/openapi_connections/reana_workflow_controller.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down
117 changes: 97 additions & 20 deletions reana_server/rest/analyses.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -34,13 +32,13 @@

@blueprint.route('/analyses', methods=['GET'])
def get_analyses(): # noqa
r"""Get all analyses.
r"""Get all current analyses in REANA.
---
get:
summary: Returns list of all analyses.
summary: Returns list of all current analyses in REANA.
description: >-
This resource return all analyses in JSON format.
This resource return all current analyses in JSON format.
produces:
- application/json
responses:
Expand Down Expand Up @@ -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

Expand All @@ -115,7 +113,7 @@ def create_analysis(): # noqa
summary: Creates a new yadage workflow.
description: >-
This resource is expecting JSON data with all the necessary
informations to instantiate a yadage workflow.
information to instantiate a yadage workflow.
operationId: create_analysis
consumes:
- application/json
Expand Down Expand Up @@ -167,10 +165,12 @@ def create_analysis(): # noqa
Request failed. The incoming data specification seems malformed
"""
try:
reana_spec_file = ''
reana_spec_url = ''
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
Expand All @@ -182,17 +182,94 @@ def create_analysis(): # noqa
raise Exception('Unknown workflow engine')

if workflow_engine == 'yadage':
if 'reana_spec_file' in locals():
if reana_spec_file:
# 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/<analysis_id>/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 which will 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:
Expand Down

0 comments on commit 2fc1586

Please sign in to comment.