Skip to content

Commit

Permalink
cli: passing operational options to cwl
Browse files Browse the repository at this point in the history
* Allows passing operational options for CWL enggine.
  Connects github.com/reanahub/reana-workflow-engine-cwl/issues/69

Signed-off-by: Rokas Maciulaitis <rokas.maciulaitis@cern.ch>
  • Loading branch information
Rokas Maciulaitis authored and Diego Rodriguez committed Dec 4, 2018
1 parent cb84aa8 commit 76347f9
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 20 deletions.
36 changes: 19 additions & 17 deletions reana_client/cli/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
from reana_client.config import ERROR_MESSAGES, reana_yaml_default_file_path
from reana_client.decorators import with_api_client
from reana_client.utils import (get_workflow_name_and_run_number, is_uuid_v4,
load_reana_spec, workflow_uuid_or_name)
load_reana_spec, workflow_uuid_or_name,
validate_cwl_operational_options,
validate_serial_operational_options,
validate_input_parameters)
from reana_client.cli.utils import add_access_token_options
from reana_client.cli.files import upload_files

Expand Down Expand Up @@ -234,7 +237,8 @@ def workflow_create(ctx, file, name, skip_validation, access_token):
'-o', '--option', 'options',
multiple=True,
help='Additional operatioal options for the workflow execution. '
'E.g. CACHE=off.',
'E.g. CACHE=off. (workflow engine - serial) '
'E.g. --debug (workflow engine - cwl)',
)
@click.pass_context
@with_api_client
Expand All @@ -250,28 +254,26 @@ def workflow_start(ctx, workflow, access_token,
click.style(ERROR_MESSAGES['missing_access_token'],
fg='red'), err=True)
sys.exit(1)

parsed_parameters = {'input_parameters':
dict(p.split('=') for p in parameters)}
parsed_parameters['operational_options'] = \
dict(p.split('=') for p in options)

parsed_parameters['operational_options'] = ' '.join(options).split()
if workflow:
if parameters:
if parameters or options:
try:
response = \
ctx.obj.client.get_workflow_parameters(workflow,
access_token)
parsed_input_parameters = \
dict(parsed_parameters['input_parameters'])
for parameter in parsed_input_parameters.keys():
if parameter not in response['parameters']:
click.echo(
click.style('Given parameter - {0}, is not in '
'reana.yaml'.format(parameter),
fg='red'),
err=True)
del parsed_parameters['input_parameters'][parameter]
if response['type'] == 'cwl':
validate_cwl_operational_options(
parsed_parameters['operational_options'])
if response['type'] == 'serial':
parsed_parameters['operational_options'] = \
validate_serial_operational_options(
parsed_parameters['operational_options'])
parsed_parameters['input_parameters'] = \
validate_input_parameters(
parsed_parameters['input_parameters'],
response['parameters'])
except Exception as e:
click.echo(
click.style('Could not apply given input parameters: '
Expand Down
46 changes: 44 additions & 2 deletions reana_client/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import json
import logging
import os
import subprocess
import sys
from uuid import UUID

Expand Down Expand Up @@ -108,12 +109,10 @@ def load_reana_spec(filepath, skip_validation=False):
reana_yaml['workflow'].get('file'),
**kwargs
)

if reana_yaml['workflow']['type'] == 'cwl' and \
'inputs' in reana_yaml:
with open(reana_yaml['inputs']['parameters']['input']) as f:
reana_yaml['inputs']['parameters']['input'] = yaml.load(f)

return reana_yaml
except IOError as e:
logging.info(
Expand Down Expand Up @@ -215,3 +214,46 @@ def get_workflow_root():
workflow_root = parent_dir
workflow_root += '/'
return workflow_root


def validate_cwl_operational_options(operational_options):
"""Validate cwl operational options."""
forbidden_args = ['--debug', '--tmpdir-prefix', '--tmp-outdir-prefix'
'--default-container', '--outdir']
for option in operational_options:
if option in forbidden_args:
click.echo('Operational option {0} are not allowed. \n'
.format(operational_options), err=True)
sys.exit(1)
cmd = 'cwltool --version {0}'.format(' '.join(operational_options))
try:
subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError as err:
click.echo('Operational options {0} are not valid. \n'
'{1}'.format(operational_options, err), err=True)
sys.exit(1)


def validate_serial_operational_options(operational_options):
"""Return validated serial operational options."""
try:
operational_options = {'input_parameters':
dict(p.split('=') for p in operational_options)}
except Exception as err:
click.echo('Operational options {0} are not valid. \n'
'{1}'.format(operational_options, err), err=True)
sys.exit(1)


def validate_input_parameters(live_parameters, original_parameters):
"""Return validated input parameters."""
parsed_input_parameters = dict(live_parameters)
for parameter in parsed_input_parameters.keys():
if parameter not in original_parameters:
click.echo(
click.style('Given parameter - {0}, is not in '
'reana.yaml'.format(parameter),
fg='red'),
err=True)
del live_parameters[parameter]
return live_parameters
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@

install_requires = [
'click>=7,<8',
'cwltool==1.0.20180912090223',
'cwltool==1.0.20181118133959',
'pyOpenSSL==17.5.0', # FIXME remove once yadage-schemas solves deps.
'reana-commons>=0.5.0.dev20181204,<0.6.0',
'rfc3987==1.3.7', # FIXME remove once yadage-schemas solves deps.
Expand Down
1 change: 1 addition & 0 deletions tests/test_cli_workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ def test_workflow_input_parameters(mock_base_api_client):
status_code = 200
response = {'id': 'd9304bdf-0d19-45d9-ae87-d5fd18059193',
'name': 'workflow.19',
'type': 'serial',
'parameters': {'helloworld': 'code/helloworld.py',
'inputfile': 'data/names.txt',
'outputfile': 'results/greetings.txt',
Expand Down

0 comments on commit 76347f9

Please sign in to comment.