diff --git a/turbinia/api/cli/turbinia_client/core/commands.py b/turbinia/api/cli/turbinia_client/core/commands.py index 35350ecc4..44ff60b74 100644 --- a/turbinia/api/cli/turbinia_client/core/commands.py +++ b/turbinia/api/cli/turbinia_client/core/commands.py @@ -123,13 +123,22 @@ def get_jobs(ctx: click.Context) -> None: @click.pass_context @click.argument('request_id') @click.option( - '--show_all', '-a', help='Shows all field regardless of priority.', + '--priority_filter', '-p', help='This sets what report sections are ' + 'shown in full detail in report output. Any tasks that have set a ' + 'report_priority value equal to or lower than this setting will be ' + 'shown in full detail, and tasks with a higher value will only have ' + 'a summary shown. The default is 20 which corresponds to "HIGH_PRIORITY"' + 'To see all tasks report output in full detail, set --priority_filter=100 ' + 'or to see CRITICAL only set --priority_filter=10', show_default=True, + default=20, type=int, required=False) +@click.option( + '--show_all', '-a', help='Shows all fields including saved output paths.', is_flag=True, required=False) @click.option( '--json_dump', '-j', help='Generates JSON output.', is_flag=True, required=False) def get_request( - ctx: click.Context, request_id: str, show_all: bool, + ctx: click.Context, request_id: str, priority_filter: int, show_all: bool, json_dump: bool) -> None: """Gets Turbinia request status.""" client: api_client.ApiClient = ctx.obj.api_client @@ -145,7 +154,7 @@ def get_request( formatter.echo_json(api_response) else: report = formatter.RequestMarkdownReport(api_response).generate_markdown( - show_all=show_all) + priority_filter=priority_filter, show_all=show_all) click.echo(report) except exceptions.ApiException as exception: log.error( diff --git a/turbinia/api/cli/turbinia_client/helpers/formatter.py b/turbinia/api/cli/turbinia_client/helpers/formatter.py index ef7e8d37b..bf90a3995 100644 --- a/turbinia/api/cli/turbinia_client/helpers/formatter.py +++ b/turbinia/api/cli/turbinia_client/helpers/formatter.py @@ -20,6 +20,7 @@ from abc import ABC, abstractmethod from click import echo as click_echo +from collections import defaultdict import logging import json import pandas @@ -271,7 +272,8 @@ def __init__(self, request_data: dict = None): super().__init__() self._request_data: dict = request_data - def generate_markdown(self, show_all=False, compact=False) -> str: + def generate_markdown( + self, priority_filter=None, show_all=False, compact=False) -> str: """Generate a markdown report.""" report: list[str] = [] task: dict = self._request_data @@ -280,6 +282,7 @@ def generate_markdown(self, show_all=False, compact=False) -> str: priority = task.get('report_priority') if task.get( 'report_priority') else MEDIUM_PRIORITY + priority_filter = priority_filter if priority_filter else HIGH_PRIORITY if priority <= CRITICAL_PRIORITY: name = f'{task.get("name")} ({"CRITICAL PRIORITY"})' @@ -291,16 +294,21 @@ def generate_markdown(self, show_all=False, compact=False) -> str: name = f'{task.get("name")} ({"LOW PRIORITY"})' try: - report.append(self.heading2(name)) - line = f"{self.bold('Evidence:'):s} {task.get('evidence_name')!s}" - report.append(self.bullet(line)) - line = f"{self.bold('Status:'):s} {task.get('status')!s}" - report.append(self.bullet(line)) - if show_all or priority <= MEDIUM_PRIORITY: + # Only show Task details if the Task has more priority than the + # priority_filter + if priority > priority_filter: + report.append(f'{self.heading2(name)}: {task.get("status")!s}') + else: + report.append(self.heading2(name)) + line = f"{self.bold('Evidence:'):s} {task.get('evidence_name')!s}" + report.append(self.bullet(line)) + line = f"{self.bold('Status:'):s} {task.get('status')!s}" + report.append(self.bullet(line)) + report.append(self.bullet(f"Task Id: {task.get('id')!s}")) report.append( self.bullet(f"Executed on worker {task.get('worker_name')!s}")) - if show_all or priority <= HIGH_PRIORITY: + if task.get('report_data'): if not compact: report.append('') @@ -308,7 +316,8 @@ def generate_markdown(self, show_all=False, compact=False) -> str: report.extend(task.get('report_data').splitlines()) if not compact: report.append('') - if show_all or priority <= CRITICAL_PRIORITY: + + if show_all and priority <= priority_filter: if not compact: report.append('') report.append(self.heading3('Saved Task Files:')) @@ -318,6 +327,8 @@ def generate_markdown(self, show_all=False, compact=False) -> str: report.append(self.bullet(self.code(path))) if not compact: report.append('') + else: + report.append('No saved files') report.append('') except TypeError as exception: log.warning(f'Error formatting the Markdown report: {exception!s}') @@ -335,10 +346,28 @@ def __init__(self, request_data: dict): self._request_data: dict = request_data sorted_tasks = sorted( - request_data.get('tasks'), key=lambda x: x['report_priority']) + request_data.get('tasks'), key=lambda x: + (x['report_priority'], x['name'])) tasks = [TaskMarkdownReport(task) for task in sorted_tasks] - self.add_components(tasks) + task_counter = defaultdict(int) + unique_tasks = [] + filtered_tasks = [] + + # Get unique tasks and task counts + for task in tasks: + task_counter[task] += 1 + if task not in unique_tasks: + unique_tasks.append(task) + + # Generate task list with counts + for task in unique_tasks: + if task_counter[task] > 1: + filtered_tasks.append(f'{task} ({task_counter[task]}x)') + else: + filtered_tasks.append(task) + + self.add_components(filtered_tasks) def add(self, component: MarkdownReportComponent) -> None: if component: @@ -355,7 +384,7 @@ def add_components(self, components: list[MarkdownReportComponent]) -> None: self.components.append(component) component.parent = self - def generate_markdown(self, show_all=False) -> str: + def generate_markdown(self, priority_filter=None, show_all=False) -> str: """Generates a Markdown version of Requests results.""" report: list[str] = [] request_dict: dict = self._request_data @@ -391,7 +420,9 @@ def generate_markdown(self, show_all=False) -> str: log.warning(f'Error formatting the Markdown report: {exception!s}') for task in self.components: - report.append(task.generate_markdown(show_all=show_all, compact=True)) + report.append( + task.generate_markdown( + priority_filter=priority_filter, show_all=show_all, compact=True)) self.report = '\n'.join(report) return self.report @@ -433,7 +464,7 @@ def __init__(self, workers_status: dict, days: int): def generate_markdown(self) -> str: """Generates a Markdown version of tasks per worker. - + Returns: markdown (str): Markdown version of tasks per worker. """ @@ -486,7 +517,7 @@ def __init__(self, statistics: dict): def stat_to_row(self, task: str, stat_dict: dict): """Generates a row of the statistics table. - + Args: task (str): Name of the current task. stat_dict (dict): Dictionary with information about current row. @@ -502,8 +533,8 @@ def generate_data_frame(self) -> pandas.DataFrame: Args: markdown (bool): Bool defining if the tasks should be in markdown format. - - Returns: + + Returns: data_frame (DataFrame): Statistics table in pandas DataFrame format. """ for stat_group, stat_dict in self._statistics.items(): @@ -520,7 +551,7 @@ def generate_data_frame(self) -> pandas.DataFrame: def generate_markdown(self) -> str: """Generates a Markdown version of task statistics. - + Returns: markdown(str): Markdown version of task statistics. """ @@ -532,7 +563,7 @@ def generate_markdown(self) -> str: def generate_csv(self) -> str: """Generates a CSV version of task statistics. - + Returns: csv(str): CSV version of task statistics. """