From 0d6550aff826caa0e86213a651dc856c704c07d8 Mon Sep 17 00:00:00 2001 From: Rokas Maciulaitis Date: Fri, 2 Nov 2018 14:55:01 +0100 Subject: [PATCH] cli: introducing run command * introducing run command, which wrapps `create`, `upload` & `start`. * deleting unused imports. Signed-off-by: Rokas Maciulaitis --- reana_client/cli/files.py | 7 +++- reana_client/cli/workflow.py | 68 +++++++++++++++++++++++++++++++++--- tests/conftest.py | 3 -- tests/test_cli_workflows.py | 23 ++++++++++++ 4 files changed, 93 insertions(+), 8 deletions(-) diff --git a/reana_client/cli/files.py b/reana_client/cli/files.py index 1cb2f55f..8324dddb 100644 --- a/reana_client/cli/files.py +++ b/reana_client/cli/files.py @@ -265,6 +265,8 @@ def upload_files(ctx, workflow, filenames, access_token): format(filename), fg='red'), err=True) + if 'invoked_by_subcommand' in ctx.parent.__dict__: + sys.exit(1) except FileUploadError as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) @@ -274,6 +276,8 @@ def upload_files(ctx, workflow, filenames, access_token): format(filename, str(e)), fg='red'), err=True) + if 'invoked_by_subcommand' in ctx.parent.__dict__: + sys.exit(1) except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) @@ -283,7 +287,8 @@ def upload_files(ctx, workflow, filenames, access_token): format(filename), fg='red'), err=True) - + if 'invoked_by_subcommand' in ctx.parent.__dict__: + sys.exit(1) else: click.echo( click.style('Workflow name must be provided either with ' diff --git a/reana_client/cli/workflow.py b/reana_client/cli/workflow.py index 71f2f516..ca94e42b 100644 --- a/reana_client/cli/workflow.py +++ b/reana_client/cli/workflow.py @@ -15,7 +15,6 @@ import click import tablib -import yaml from jsonschema.exceptions import ValidationError from reana_commons.utils import click_table_printer @@ -23,9 +22,9 @@ from reana_client.config import ERROR_MESSAGES, reana_yaml_default_file_path from reana_client.utils import (get_workflow_name_and_run_number, is_uuid_v4, - load_reana_spec, load_workflow_spec, - workflow_uuid_or_name) + load_reana_spec, workflow_uuid_or_name) from reana_client.cli.utils import add_access_token_options +from reana_client.cli.files import upload_files class _WorkflowStatus(Enum): @@ -178,7 +177,9 @@ def workflow_create(ctx, file, name, skip_validation, access_token): name, access_token) click.echo(click.style(response['workflow_name'], fg='green')) - + # check if command is called from wrapper command + if 'invoked_by_subcommand' in ctx.parent.__dict__: + ctx.parent.workflow_name = response['workflow_name'] except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) @@ -186,6 +187,8 @@ def workflow_create(ctx, file, name, skip_validation, access_token): click.style('Workflow could not be created: \n{}' .format(str(e)), fg='red'), err=True) + if 'invoked_by_subcommand' in ctx.parent.__dict__: + sys.exit(1) @click.command( @@ -246,6 +249,8 @@ def workflow_start(ctx, workflow, access_token, parameter): # noqa: D301 click.style('Workflow could not be started: \n{}' .format(str(e)), fg='red'), err=True) + if 'invoked_by_subcommand' in ctx.parent.__dict__: + sys.exit(1) else: click.echo( click.style('Workflow name must be provided either with ' @@ -477,9 +482,64 @@ def workflow_validate(ctx, file): err=True) +@click.command( + 'run', + help='Create, upload and run the REANA workflow.') +@click.option( + '-f', + '--file', + type=click.Path(exists=True, resolve_path=True), + default=reana_yaml_default_file_path, + help='REANA specifications file describing the workflow and ' + 'context which REANA should execute.') +@click.argument( + 'filenames', + metavar='SOURCES', + type=click.Path(exists=True, resolve_path=True), + nargs=-1) +@click.option( + '-n', + '--name', + default='', + help='Name of the workflow.') +@click.option( + '--skip-validation', + is_flag=True, + help="If set, specifications file is not validated before " + "submitting it's contents to REANA server.") +@click.option( + '-p', '--parameter', + multiple=True, + help='Optional operational parameters for the workflow execution. ' + 'E.g. CACHE=off.', +) +@add_access_token_options +@click.pass_context +def workflow_run(ctx, file, filenames, name, skip_validation, + access_token, parameter): + """Wrapper command for create, upload and start.""" + # set context parameters for subcommand + ctx.invoked_by_subcommand = True + ctx.workflow_name = "" + ctx.invoke(workflow_create, + file=file, + name=name, + skip_validation=skip_validation, + access_token=access_token) + ctx.invoke(upload_files, + workflow=ctx.workflow_name, + filenames=filenames, + access_token=access_token) + ctx.invoke(workflow_start, + workflow=ctx.workflow_name, + access_token=access_token, + parameter=parameter) + + workflow.add_command(workflow_workflows) workflow.add_command(workflow_create) workflow.add_command(workflow_start) workflow.add_command(workflow_validate) workflow.add_command(workflow_status) +workflow.add_command(workflow_run) # workflow.add_command(workflow_logs) diff --git a/tests/conftest.py b/tests/conftest.py index 83e7a4bc..4c30d695 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -42,9 +42,6 @@ def create_yaml_workflow_schema(): ''' version: 0.3.0 inputs: - files: - - code/helloworld.py - - inputs/names.txt parameters: sleeptime: 2 inputfile: inputs/names.txt diff --git a/tests/test_cli_workflows.py b/tests/test_cli_workflows.py index 5d997aa0..71a0861e 100644 --- a/tests/test_cli_workflows.py +++ b/tests/test_cli_workflows.py @@ -9,6 +9,7 @@ """REANA client workflow tests.""" import json +from mock import patch from click.testing import CliRunner @@ -209,3 +210,25 @@ def test_get_workflow_status_ok(mock_base_api_client): assert isinstance(json_response, list) assert len(json_response) == 1 assert json_response[0]['name'] in response['name'] + + +@patch('reana_client.cli.workflow.workflow_create') +@patch('reana_client.cli.workflow.upload_files') +@patch('reana_client.cli.workflow.workflow_start') +def test_run(workflow_start_mock, + upload_file_mock, + workflow_create_mock, + create_yaml_workflow_schema): + """Test run command, if wrapped commands are called.""" + reana_workflow_schema = "reana.yaml" + runner = CliRunner() + with runner.isolated_filesystem(): + with open(reana_workflow_schema, 'w') as f: + f.write(create_yaml_workflow_schema) + result = runner.invoke( + cli, + ['run', '-f', reana_workflow_schema], + ) + assert workflow_create_mock.called is True + assert upload_file_mock.called is True + assert workflow_start_mock.called is True