def test_workflow_start_follow(initial_status, final_status, exit_code): """Test start workflow with follow flag.""" workflow_name = "mytest.1" initial_reponse = { "status": initial_status, "message": "Server message", "id": "256b25f4-4cfb-4684-b7a8-73872ef455a1", "workflow_name": workflow_name, "user": "******", "size": { "raw": 0, "human_readable": "0 Bytes" }, } final_reponse = { "status": final_status, "message": "Server message", "id": "256b25f4-4cfb-4684-b7a8-73872ef455a1", "workflow_name": workflow_name, "user": "******", "size": { "raw": 340, "human_readable": "340 Bytes" }, } initial_expected_message = get_workflow_status_change_msg( workflow_name, initial_status) final_Expected_message = get_workflow_status_change_msg( workflow_name, final_status) status_code = 200 mock_http_response = Mock() mock_http_response.status_code = status_code mock_api_client = Mock() mock_start_workflow_result = Mock(return_value=(mock_http_response, mock_http_response)) mock_api_client.api.start_workflow.return_value = Mock( result=mock_start_workflow_result) mock_get_workflow_status_result = Mock(side_effect=[ (initial_reponse, mock_http_response), (final_reponse, mock_http_response), ]) mock_api_client.api.get_workflow_status.return_value = Mock( result=mock_get_workflow_status_result) reana_token = "000000" env = {"REANA_SERVER_URL": "localhost"} runner = CliRunner(env=env) with runner.isolation(): with patch("reana_client.api.client.current_rs_api_client", mock_api_client): result = runner.invoke( cli, ["start", "-t", reana_token, "-w", workflow_name, "--follow"]) assert result.exit_code == exit_code assert initial_expected_message in result.output assert final_Expected_message in result.output
def workflow_delete(ctx, workflow, all_runs, workspace, hard_delete, access_token): """Delete a workflow run given the workflow name and run number.""" logging.debug('command: {}'.format(ctx.command_path.replace(" ", "."))) for p in ctx.params: logging.debug('{param}: {value}'.format(param=p, value=ctx.params[p])) if not access_token: click.echo(click.style(ERROR_MESSAGES['missing_access_token'], fg='red'), err=True) sys.exit(1) if workflow: try: logging.info('Connecting to {0}'.format( current_rs_api_client.swagger_spec.api_url)) response = delete_workflow(workflow, all_runs, hard_delete, workspace, access_token) if all_runs: message = 'All workflows named \'{}\' have been deleted.'.\ format(workflow.split('.')[0]) else: message = get_workflow_status_change_msg(workflow, 'deleted') click.secho(message, fg='green') except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) click.echo(click.style( 'Workflow could not be deleted: \n{}'.format(str(e)), fg='red'), err=True)
def workflow_stop(ctx, workflow, force_stop, access_token): """Stop given workflow.""" if not force_stop: click.secho( 'Graceful stop not implement yet. If you really want to ' 'stop your workflow without waiting for jobs to finish' ' use: --force option', fg='red') raise click.Abort() if not access_token: click.secho(ERROR_MESSAGES['missing_access_token'], fg='red', err=True) sys.exit(1) if workflow: try: logging.info( 'Sending a request to stop workflow {}'.format(workflow)) response = stop_workflow(workflow, force_stop, access_token) click.secho(get_workflow_status_change_msg(workflow, 'stopped'), fg='green') except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) click.secho('Workflow could not be stopped: \n{}'.format(str(e)), fg='red', err=True)
def test_workflow_start_successful(status): """Test workflow start when creation is successfull.""" workflow_name = "mytest.1" response = { "status": status, "message": "Server message", "id": "256b25f4-4cfb-4684-b7a8-73872ef455a1", "workflow_name": workflow_name, "user": "******", } status_code = 200 reana_token = "000000" expected_message = get_workflow_status_change_msg(workflow_name, status) mock_http_response = Mock() mock_http_response.status_code = status_code mock_response = response env = {"REANA_SERVER_URL": "localhost"} runner = CliRunner(env=env) with runner.isolation(): with patch( "reana_client.api.client.current_rs_api_client", make_mock_api_client("reana-server")(mock_response, mock_http_response), ): result = runner.invoke( cli, ["start", "-t", reana_token, "-w", response["workflow_name"]]) assert result.exit_code == 0 assert expected_message in result.output
def workflow_stop(ctx, workflow, force_stop, access_token): # noqa: D301 """Stop a running workflow. The `stop` command allows to hard-stop the running workflow process. Note that soft-stopping of the workflow is currently not supported. This command should be therefore used with care, only if you are absolutely sure that there is no point in continuing the running the workflow. Example: \n \t $ reana-client stop -w myanalysis.42 --force """ from reana_client.api.client import get_workflow_status, stop_workflow if not force_stop: click.secho( 'Graceful stop not implement yet. If you really want to ' 'stop your workflow without waiting for jobs to finish' ' use: --force option', fg='red') raise click.Abort() if workflow: try: logging.info( 'Sending a request to stop workflow {}'.format(workflow)) response = stop_workflow(workflow, force_stop, access_token) click.secho(get_workflow_status_change_msg(workflow, 'stopped'), fg='green') except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) click.secho('Cannot stop workflow {}: \n{}'.format( workflow, str(e)), fg='red', err=True)
def workflow_start(ctx, workflow, access_token, parameters, options): # noqa: D301 """Start previously created workflow.""" logging.debug('command: {}'.format(ctx.command_path.replace(" ", "."))) for p in ctx.params: logging.debug('{param}: {value}'.format(param=p, value=ctx.params[p])) if not access_token: click.echo(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'] = ' '.join(options).split() if workflow: if parameters or options: try: response = get_workflow_parameters(workflow, access_token) 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: ' '{0} \n{1}'.format(parameters, str(e))), err=True) try: logging.info('Connecting to {0}'.format( current_rs_api_client.swagger_spec.api_url)) response = start_workflow(workflow, access_token, parsed_parameters) current_status = get_workflow_status(workflow, access_token).get('status') click.secho(get_workflow_status_change_msg(workflow, current_status), fg='green') except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) click.echo(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)
def workflow_delete(ctx, workflow, all_runs, workspace, hard_delete, access_token): # noqa: D301 """Delete a workflow. The `delete` command allows to remove workflow runs from the database and the workspace. By default, the command removes the workflow and all its cached information and hides the workflow from the workflow list. Note that workflow workspace will still be accessible until you use `--include-workspace` flag. Note also that you can remove all past runs of a workflow by specifying `--include-all-runs` flag. Example: \n \t $ reana-client delete -w myanalysis.42 \n \t $ reana-client delete -w myanalysis.42 --include-records """ logging.debug('command: {}'.format(ctx.command_path.replace(" ", "."))) for p in ctx.params: logging.debug('{param}: {value}'.format(param=p, value=ctx.params[p])) if not access_token: click.echo(click.style(ERROR_MESSAGES['missing_access_token'], fg='red'), err=True) sys.exit(1) if workflow: try: logging.info('Connecting to {0}'.format( current_rs_api_client.swagger_spec.api_url)) response = delete_workflow(workflow, all_runs, hard_delete, workspace, access_token) if all_runs: message = 'All workflows named \'{}\' have been deleted.'.\ format(workflow.split('.')[0]) else: message = get_workflow_status_change_msg(workflow, 'deleted') click.secho(message, fg='green') except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) click.echo(click.style( 'Workflow could not be deleted: \n{}'.format(str(e)), fg='red'), err=True)
def workflow_delete(ctx, workflow, all_runs, workspace, access_token): # noqa: D301 """Delete a workflow. The `delete` command allows to remove workflow runs from the database and the workspace. By default, the command removes the workflow and all its cached information and hides the workflow from the workflow list. Note that workflow workspace will still be accessible until you use `--include-workspace` flag. Note also that you can remove all past runs of a workflow by specifying `--include-all-runs` flag. Example: \n \t $ reana-client delete -w myanalysis.42 \n \t $ reana-client delete -w myanalysis.42 --include-all-runs \n \t $ reana-client delete -w myanalysis.42 --include-workspace """ from reana_client.api.client import delete_workflow, get_workflow_status from reana_client.utils import get_api_url logging.debug("command: {}".format(ctx.command_path.replace(" ", "."))) for p in ctx.params: logging.debug("{param}: {value}".format(param=p, value=ctx.params[p])) if workflow: try: logging.info("Connecting to {0}".format(get_api_url())) response = delete_workflow(workflow, all_runs, workspace, access_token) if all_runs: message = "All workflows named '{}' have been deleted.".format( workflow.split(".")[0]) else: message = get_workflow_status_change_msg(workflow, "deleted") click.secho(message, fg="green") except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) click.echo( click.style("Cannot delete workflow {} \n{}".format( workflow, str(e)), fg="red"), err=True, )
def workflow_stop(ctx, workflow, force_stop, access_token): # noqa: D301 """Stop a running workflow. The ``stop`` command allows to hard-stop the running workflow process. Note that soft-stopping of the workflow is currently not supported. This command should be therefore used with care, only if you are absolutely sure that there is no point in continuing the running the workflow. Example: \n \t $ reana-client stop -w myanalysis.42 --force """ from reana_client.api.client import stop_workflow if not force_stop: display_message( "Graceful stop not implement yet. If you really want to " "stop your workflow without waiting for jobs to finish" " use: --force option", msg_type="error", ) raise click.Abort() if workflow: try: logging.info("Sending a request to stop workflow {}".format(workflow)) stop_workflow(workflow, force_stop, access_token) display_message( get_workflow_status_change_msg(workflow, "stopped"), msg_type="success", ) except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) display_message( "Cannot stop workflow {}: \n{}".format(workflow, str(e)), msg_type="error", )
def workflow_restart( ctx, workflow, access_token, parameters, options, file ): # noqa: D301 """Restart previously run workflow. The ``restart`` command allows to restart a previous workflow on the same workspace. Note that workflow restarting can be used in a combination with operational options ``FROM`` and ``TARGET``. You can also pass a modified workflow specification with ``-f`` or ``--file`` flag. You can furthermore use modified input prameters using ``-p`` or ``--parameters`` flag and by setting additional operational options using ``-o`` or ``--options``. The input parameters and operational options can be repetitive. Examples: \n \t $ reana-client restart -w myanalysis.42 -p sleeptime=10 -p myparam=4 \n \t $ reana-client restart -w myanalysis.42 -p myparam=myvalue\n \t $ reana-client restart -w myanalysis.42 -o TARGET=gendata\n \t $ reana-client restart -w myanalysis.42 -o FROM=fitdata """ from reana_client.utils import get_api_url from reana_client.api.client import ( get_workflow_parameters, get_workflow_status, start_workflow, ) logging.debug("command: {}".format(ctx.command_path.replace(" ", "."))) for p in ctx.params: logging.debug("{param}: {value}".format(param=p, value=ctx.params[p])) parsed_parameters = { "input_parameters": parameters, "operational_options": options, "restart": True, } if file: parsed_parameters["reana_specification"] = load_reana_spec( click.format_filename(file) ) if workflow: if parameters or options: try: if "reana_specification" in parsed_parameters: workflow_type = parsed_parameters["reana_specification"][ "workflow" ]["type"] original_parameters = ( parsed_parameters["reana_specification"] .get("inputs", {}) .get("parameters", {}) ) else: response = get_workflow_parameters(workflow, access_token) workflow_type = response["type"] original_parameters = response["parameters"] parsed_parameters["operational_options"] = validate_operational_options( workflow_type, parsed_parameters["operational_options"] ) parsed_parameters["input_parameters"] = validate_input_parameters( parsed_parameters["input_parameters"], original_parameters ) except REANAValidationError as e: display_message(e.message, msg_type="error") sys.exit(1) except Exception as e: display_message( "Could not apply given input parameters: " "{0} \n{1}".format(parameters, str(e)), msg_type="error", ) try: logging.info("Connecting to {0}".format(get_api_url())) response = start_workflow(workflow, access_token, parsed_parameters) workflow = response["workflow_name"] + "." + str(response["run_number"]) current_status = get_workflow_status(workflow, access_token).get("status") display_message( get_workflow_status_change_msg(workflow, current_status), msg_type="success", ) except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) display_message( "Cannot start workflow {}: \n{}".format(workflow, str(e)), msg_type="error", ) if "invoked_by_subcommand" in ctx.parent.__dict__: sys.exit(1)
def workflow_start( ctx, workflow, access_token, parameters, options, follow ): # noqa: D301 """Start previously created workflow. The ``start`` command allows to start previously created workflow. The workflow execution can be further influenced by passing input prameters using ``-p`` or ``--parameters`` flag and by setting additional operational options using ``-o`` or ``--options``. The input parameters and operational options can be repetitive. For example, to disable caching for the Serial workflow engine, you can set ``-o CACHE=off``. Examples: \n \t $ reana-client start -w myanalysis.42 -p sleeptime=10 -p myparam=4 \n \t $ reana-client start -w myanalysis.42 -p myparam1=myvalue1 -o CACHE=off """ from reana_client.utils import get_api_url from reana_client.api.client import ( get_workflow_parameters, get_workflow_status, start_workflow, ) logging.debug("command: {}".format(ctx.command_path.replace(" ", "."))) for p in ctx.params: logging.debug("{param}: {value}".format(param=p, value=ctx.params[p])) parsed_parameters = {"input_parameters": parameters, "operational_options": options} if workflow: if parameters or options: try: response = get_workflow_parameters(workflow, access_token) workflow_type = response["type"] original_parameters = response["parameters"] validate_operational_options( workflow_type, parsed_parameters["operational_options"] ) parsed_parameters["input_parameters"] = validate_input_parameters( parsed_parameters["input_parameters"], original_parameters ) except REANAValidationError as e: display_message(e.message, msg_type="error") sys.exit(1) except Exception as e: display_message( "Could not apply given input parameters: " "{0} \n{1}".format(parameters, str(e)), msg_type="error", ) try: logging.info("Connecting to {0}".format(get_api_url())) response = start_workflow(workflow, access_token, parsed_parameters) current_status = get_workflow_status(workflow, access_token).get("status") display_message( get_workflow_status_change_msg(workflow, current_status), msg_type="success", ) if follow: while "running" in current_status: time.sleep(TIMECHECK) current_status = get_workflow_status(workflow, access_token).get( "status" ) display_message( get_workflow_status_change_msg(workflow, current_status), msg_type="success", ) if "finished" in current_status: if follow: display_message( "Listing workflow output files...", msg_type="info", ) ctx.invoke( get_files, workflow=workflow, access_token=access_token, output_format="url", ) sys.exit(0) elif "failed" in current_status or "stopped" in current_status: sys.exit(1) except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) display_message( "Cannot start workflow {}: \n{}".format(workflow, str(e)), msg_type="error", ) if "invoked_by_subcommand" in ctx.parent.__dict__: sys.exit(1)
def workflow_start(ctx, workflow, access_token, parameters, options, follow): # noqa: D301 """Start previously created workflow. The `start` command allows to start previously created workflow. The workflow execution can be further influenced by passing input prameters using `-p` or `--parameters` flag and by setting additional operational options using `-o` or `--options`. The input parameters and operational options can be repetitive. For example, to disable caching for the Serial workflow engine, you can set `-o CACHE=off`. Examples: \n \t $ reana-client start -w myanalysis.42 -p sleeptime=10 -p myparam=4 \n \t $ reana-client start -w myanalysis.42 -p myparam1=myvalue1 -o CACHE=off """ logging.debug('command: {}'.format(ctx.command_path.replace(" ", "."))) for p in ctx.params: logging.debug('{param}: {value}'.format(param=p, value=ctx.params[p])) if not access_token: click.echo(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'] = ' '.join(options).split() if workflow: if parameters or options: try: response = get_workflow_parameters(workflow, access_token) 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: ' '{0} \n{1}'.format(parameters, str(e))), err=True) try: logging.info('Connecting to {0}'.format( current_rs_api_client.swagger_spec.api_url)) response = start_workflow(workflow, access_token, parsed_parameters) current_status = get_workflow_status(workflow, access_token).get('status') click.secho(get_workflow_status_change_msg(workflow, current_status), fg='green') if follow: while 'running' in current_status: time.sleep(TIMECHECK) current_status = get_workflow_status( workflow, access_token).get('status') click.secho(get_workflow_status_change_msg( workflow, current_status), fg='green') if 'finished' in current_status: if follow: click.secho( '[INFO] Listing workflow output ' 'files...', bold=True) ctx.invoke(get_files, workflow=workflow, access_token=access_token, output_format='url') sys.exit(0) elif 'failed' in current_status or \ 'stopped' in current_status: sys.exit(1) except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) click.echo(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)
def workflow_restart(ctx, workflow, access_token, parameters, options, file): # noqa: D301 """Restart previously run workflow. The `restart` command allows to restart a previous workflow on the same workspace. Note that workflow restarting can be used in a combination with operational options ``FROM`` and ``TARGET``. You can also pass a modified workflow specification with ``-f`` or `--file`` flag. You can furthermore use modified input prameters using `-p` or `--parameters` flag and by setting additional operational options using `-o` or `--options`. The input parameters and operational options can be repetitive. Examples: \n \t $ reana-client restart -w myanalysis.42 -p sleeptime=10 -p myparam=4 \n \t $ reana-client restart -w myanalysis.42 -p myparam=myvalue\n \t $ reana-client restart -w myanalysis.42 -o TARGET=gendata\n \t $ reana-client restart -w myanalysis.42 -o FROM=fitdata """ from reana_client.utils import get_api_url from reana_client.api.client import (get_workflow_parameters, get_workflow_status, start_workflow) logging.debug('command: {}'.format(ctx.command_path.replace(" ", "."))) for p in ctx.params: logging.debug('{param}: {value}'.format(param=p, value=ctx.params[p])) parsed_parameters = { 'input_parameters': parameters, 'operational_options': options, 'restart': True } if file: parsed_parameters['reana_specification'] = \ load_reana_spec(click.format_filename(file)) if workflow: if parameters or options: try: if 'reana_specification' in parsed_parameters: workflow_type = \ parsed_parameters['reana_specification']['workflow'][ 'type'] original_parameters = \ parsed_parameters['reana_specification'].get( 'inputs', {}).get('parameters', {}) else: response = get_workflow_parameters(workflow, access_token) workflow_type = response['type'] original_parameters = response['parameters'] parsed_parameters['operational_options'] = \ validate_operational_options( workflow_type, parsed_parameters['operational_options']) parsed_parameters['input_parameters'] = \ validate_input_parameters( parsed_parameters['input_parameters'], original_parameters) except REANAValidationError as e: click.secho(e.message, err=True, fg='red') sys.exit(1) except Exception as e: click.secho('Could not apply given input parameters: ' '{0} \n{1}'.format(parameters, str(e)), err=True) try: logging.info('Connecting to {0}'.format(get_api_url())) response = start_workflow(workflow, access_token, parsed_parameters) workflow = response['workflow_name'] + '.' + \ str(response['run_number']) current_status = get_workflow_status(workflow, access_token).get('status') click.secho(get_workflow_status_change_msg(workflow, current_status), fg='green') except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) click.echo(click.style('Cannot start workflow {}: \n{}'.format( workflow, str(e)), fg='red'), err=True) if 'invoked_by_subcommand' in ctx.parent.__dict__: sys.exit(1)
def workflow_start(ctx, workflow, access_token, parameters, options, follow): # noqa: D301 """Start previously created workflow. The `start` command allows to start previously created workflow. The workflow execution can be further influenced by passing input prameters using `-p` or `--parameters` flag and by setting additional operational options using `-o` or `--options`. The input parameters and operational options can be repetitive. For example, to disable caching for the Serial workflow engine, you can set `-o CACHE=off`. Examples: \n \t $ reana-client start -w myanalysis.42 -p sleeptime=10 -p myparam=4 \n \t $ reana-client start -w myanalysis.42 -p myparam1=myvalue1 -o CACHE=off """ from reana_client.utils import get_api_url from reana_client.api.client import (get_workflow_parameters, get_workflow_status, start_workflow) logging.debug('command: {}'.format(ctx.command_path.replace(" ", "."))) for p in ctx.params: logging.debug('{param}: {value}'.format(param=p, value=ctx.params[p])) parsed_parameters = { 'input_parameters': parameters, 'operational_options': options } if workflow: if parameters or options: try: response = get_workflow_parameters(workflow, access_token) workflow_type = response['type'] original_parameters = response['parameters'] validate_operational_options( workflow_type, parsed_parameters['operational_options']) parsed_parameters['input_parameters'] = \ validate_input_parameters( parsed_parameters['input_parameters'], original_parameters) except REANAValidationError as e: click.secho(e.message, err=True, fg='red') sys.exit(1) except Exception as e: click.secho('Could not apply given input parameters: ' '{0} \n{1}'.format(parameters, str(e)), err=True) try: logging.info('Connecting to {0}'.format(get_api_url())) response = start_workflow(workflow, access_token, parsed_parameters) current_status = get_workflow_status(workflow, access_token).get('status') click.secho(get_workflow_status_change_msg(workflow, current_status), fg='green') if follow: while 'running' in current_status: time.sleep(TIMECHECK) current_status = get_workflow_status( workflow, access_token).get('status') click.secho(get_workflow_status_change_msg( workflow, current_status), fg='green') if 'finished' in current_status: if follow: click.secho( '[INFO] Listing workflow output ' 'files...', bold=True) ctx.invoke(get_files, workflow=workflow, access_token=access_token, output_format='url') sys.exit(0) elif 'failed' in current_status or \ 'stopped' in current_status: sys.exit(1) except Exception as e: logging.debug(traceback.format_exc()) logging.debug(str(e)) click.echo(click.style('Cannot start workflow {}: \n{}'.format( workflow, str(e)), fg='red'), err=True) if 'invoked_by_subcommand' in ctx.parent.__dict__: sys.exit(1)