Esempio n. 1
0
def workflow_workflows(  # noqa: C901
    ctx,
    workflow,
    sessions,
    _format,
    output_format,
    access_token,
    show_all,
    verbose,
    human_readable_or_raw,
    sort_columm_name,
    page,
    size,
    filters,
    include_progress,
    include_workspace_size,
):  # noqa: D301
    """List all workflows and sessions.

    The ``list`` command lists workflows and sessions. By default, the list of
    workflows is returned. If you would like to see the list of your open
    interactive sessions, you need to pass the ``--sessions`` command-line
    option.

    Example: \n
    \t $ reana-client list --all \n
    \t $ reana-client list --sessions \n
    \t $ reana-client list --verbose --bytes
    """
    import tablib
    from reana_client.api.client import get_workflows

    logging.debug("command: {}".format(ctx.command_path.replace(" ", ".")))
    for p in ctx.params:
        logging.debug("{param}: {value}".format(param=p, value=ctx.params[p]))
    type = "interactive" if sessions else "batch"

    status_filter = None
    search_filter = None
    if filters:
        filter_names = ["name", "status"]
        status_filter, search_filter = parse_filter_parameters(filters, filter_names)
    if _format:
        parsed_format_filters = parse_format_parameters(_format)
    try:
        response = get_workflows(
            access_token,
            type,
            verbose=bool(verbose),
            page=page,
            size=size,
            status=status_filter,
            search=search_filter,
            include_progress=include_progress,
            include_workspace_size=include_workspace_size,
            workflow=workflow,
        )
        verbose_headers = ["id", "user"]
        workspace_size_header = ["size"]
        progress_header = ["progress"]
        headers = {
            "batch": ["name", "run_number", "created", "started", "ended", "status"],
            "interactive": [
                "name",
                "run_number",
                "created",
                "session_type",
                "session_uri",
                "session_status",
            ],
        }
        if verbose:
            headers[type] += verbose_headers
        if verbose or include_workspace_size:
            headers[type] += workspace_size_header
        if verbose or include_progress:
            headers[type] += progress_header
        data = []
        for workflow in response:
            workflow["size"] = workflow["size"][human_readable_or_raw]
            if workflow["status"] == "deleted" and not show_all:
                continue
            name, run_number = get_workflow_name_and_run_number(workflow["name"])
            workflow["name"] = name
            workflow["run_number"] = run_number
            if type == "interactive":
                workflow["session_uri"] = format_session_uri(
                    reana_server_url=ctx.obj.reana_server_url,
                    path=workflow["session_uri"],
                    access_token=access_token,
                )
            row = []
            for header in headers[type]:
                value = None
                if header in progress_header:
                    value = get_formatted_progress(workflow.get("progress"))
                elif header in ["started", "ended"]:
                    _key = (
                        "run_started_at" if header == "started" else "run_finished_at"
                    )
                    value = workflow.get("progress", {}).get(_key) or "-"
                if not value:
                    value = workflow.get(header)
                row.append(value)
            data.append(row)
        sort_column_id = 2
        if sort_columm_name.lower() in headers[type]:
            sort_column_id = headers[type].index(sort_columm_name.lower())
        data = sorted(data, key=lambda x: x[sort_column_id], reverse=True)
        workflow_ids = ["{0}.{1}".format(w[0], w[1]) for w in data]
        if os.getenv("REANA_WORKON", "") in workflow_ids:
            active_workflow_idx = workflow_ids.index(os.getenv("REANA_WORKON", ""))
            for idx, row in enumerate(data):
                if idx == active_workflow_idx:
                    run_number = str(data[idx][headers[type].index("run_number")])
                    run_number += " *"
        tablib_data = tablib.Dataset()
        tablib_data.headers = headers[type]
        for row in data:
            tablib_data.append(row=row, tags=row)

        if _format:
            tablib_data, filtered_headers = format_data(
                parsed_format_filters, headers[type], tablib_data
            )
            if output_format:
                display_message(json.dumps(tablib_data))
            else:
                tablib_data = [list(item.values()) for item in tablib_data]
                click_table_printer(filtered_headers, filtered_headers, tablib_data)
        else:
            if output_format:
                display_message(tablib_data.export(output_format))
            else:
                click_table_printer(headers[type], _format, data)

    except Exception as e:
        logging.debug(traceback.format_exc())
        logging.debug(str(e))
        display_message(
            "Workflow list could not be retrieved: \n{}".format(str(e)),
            msg_type="error",
        )
Esempio n. 2
0
def workflow_status(  # noqa: C901
    ctx, workflow, _format, output_format, access_token, verbose
):  # noqa: D301
    """Get status of a workflow.

    The ``status`` command allow to retrieve status of a workflow. The status can
    be created, queued, running, failed, etc. You can increase verbosity or
    filter retrieved information by passing appropriate command-line options.

    Examples: \n
    \t $ reana-client status -w myanalysis.42 \n
    \t $ reana-client status -w myanalysis.42 -v --json
    """
    import tablib
    from reana_client.api.client import get_workflow_status

    def render_progress(finished_jobs, total_jobs):
        if total_jobs:
            return "{0}/{1}".format(finished_jobs, total_jobs)
        else:
            return "-/-"

    def add_data_from_reponse(row, data, headers):
        name, run_number = get_workflow_name_and_run_number(row["name"])
        total_jobs = row["progress"].get("total")
        if total_jobs:
            total_jobs = total_jobs.get("total")
        else:
            total_jobs = 0
        finished_jobs = row["progress"].get("finished")
        if finished_jobs:
            finished_jobs = finished_jobs.get("total")
        else:
            finished_jobs = 0

        parsed_response = list(
            map(str, [name, run_number, row["created"], row["status"]])
        )
        if row["progress"]["total"].get("total") or 0 > 0:
            if "progress" not in headers:
                headers += ["progress"]
                parsed_response.append(render_progress(finished_jobs, total_jobs))

        if row["status"] in ["running", "finished", "failed", "stopped"]:
            started_at = row["progress"].get("run_started_at")
            finished_at = row["progress"].get("run_finished_at")
            if started_at:
                after_created_pos = headers.index("created") + 1
                headers.insert(after_created_pos, "started")
                parsed_response.insert(after_created_pos, started_at)
                if finished_at:
                    after_started_pos = headers.index("started") + 1
                    headers.insert(after_started_pos, "ended")
                    parsed_response.insert(after_started_pos, finished_at)

        data.append(parsed_response)
        return data

    def add_verbose_data_from_response(response, verbose_headers, headers, data):
        for k in verbose_headers:
            if k == "command":
                current_command = response["progress"]["current_command"]
                if current_command:
                    if current_command.startswith('bash -c "cd '):
                        current_command = current_command[
                            current_command.index(";") + 2 : -2
                        ]
                    data[-1] += [current_command]
                else:
                    if "current_step_name" in response["progress"] and response[
                        "progress"
                    ].get("current_step_name"):
                        current_step_name = response["progress"].get(
                            "current_step_name"
                        )
                        data[-1] += [current_step_name]
                    else:
                        headers.remove("command")
            else:
                data[-1] += [response.get(k)]
        return data

    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:
            if _format:
                parsed_filters = parse_format_parameters(_format)
                _format = [item["column_name"] for item in parsed_filters]
            response = get_workflow_status(workflow, access_token)
            headers = ["name", "run_number", "created", "status"]
            verbose_headers = ["id", "user", "command"]
            data = []
            if not isinstance(response, list):
                response = [response]
            for workflow in response:
                add_data_from_reponse(workflow, data, headers)
                if verbose:
                    headers += verbose_headers
                    add_verbose_data_from_response(
                        workflow, verbose_headers, headers, data
                    )

            if output_format:
                tablib_data = tablib.Dataset()
                tablib_data.headers = headers
                for row in data:
                    tablib_data.append(row)

                if _format:
                    tablib_data = tablib_data.subset(rows=None, cols=list(_format))

                display_message(tablib_data.export(output_format))
            else:
                click_table_printer(headers, _format, data)

        except Exception as e:
            logging.debug(traceback.format_exc())
            logging.debug(str(e))
            display_message(
                "Cannot retrieve the status of a workflow {}: \n"
                "{}".format(workflow, str(e)),
                msg_type="error",
            )
Esempio n. 3
0
def get_files(
    ctx,
    workflow,
    _format,
    filters,
    output_format,
    filename,
    access_token,
    page,
    size,
    human_readable_or_raw,
):  # noqa: D301
    """List workspace files.

    The ``ls`` command lists workspace files of a workflow specified by the
    environment variable REANA_WORKON or provided as a command-line flag
    ``--workflow`` or ``-w``. The SOURCE argument is optional and specifies a
    pattern matching files and directories.

    Examples: \n
    \t $ reana-client ls --workflow myanalysis.42 \n
    \t $ reana-client ls --workflow myanalysis.42 --human-readable \n
    \t $ reana-client ls --workflow myanalysis.42 'data/*root*' \n
    \t $ reana-client ls --workflow myanalysis.42 --filter name=hello
    """  # noqa: W605
    import tablib
    from reana_client.api.client import current_rs_api_client, list_files

    logging.debug("command: {}".format(ctx.command_path.replace(" ", ".")))
    for p in ctx.params:
        logging.debug("{param}: {value}".format(param=p, value=ctx.params[p]))

    search_filter = None
    headers = ["name", "size", "last-modified"]
    if filters:
        _, search_filter = parse_filter_parameters(filters, headers)
    if _format:
        parsed_format_filters = parse_format_parameters(_format)
    if workflow:
        logging.info('Workflow "{}" selected'.format(workflow))
        try:
            response = list_files(workflow, access_token, filename, page, size,
                                  search_filter)
            data = []
            file_path = get_path_from_operation_id(
                current_rs_api_client.swagger_spec.spec_dict["paths"],
                "download_file")
            urls = []
            for file_ in response:
                if not file_["name"].startswith(FILES_BLACKLIST):
                    data.append(
                        list(
                            map(
                                str,
                                [
                                    file_["name"],
                                    file_["size"][human_readable_or_raw],
                                    file_["last-modified"],
                                ],
                            )))
                    urls.append(ctx.obj.reana_server_url + file_path.format(
                        workflow_id_or_name=workflow, file_name=file_["name"]))
            tablib_data = tablib.Dataset()
            tablib_data.headers = headers
            for row in data:
                tablib_data.append(row)
            if output_format == URL:
                display_message("\n".join(urls))
            elif _format:
                tablib_data, filtered_headers = format_data(
                    parsed_format_filters, headers, tablib_data)
                if output_format == JSON:
                    display_message(json.dumps(tablib_data))
                else:
                    tablib_data = [list(item.values()) for item in tablib_data]
                    click_table_printer(filtered_headers, filtered_headers,
                                        tablib_data)
            else:
                if output_format == JSON:
                    display_message(tablib_data.export(output_format))
                else:
                    click_table_printer(headers, _format, data)

        except Exception as e:
            logging.debug(traceback.format_exc())
            logging.debug(str(e))

            display_message(
                "Something went wrong while retrieving file list"
                " for workflow {0}:\n{1}".format(workflow, str(e)),
                msg_type="error",
            )