diff --git a/samcli/commands/_utils/table_print.py b/samcli/commands/_utils/table_print.py index 76672632ff..6f161882cb 100644 --- a/samcli/commands/_utils/table_print.py +++ b/samcli/commands/_utils/table_print.py @@ -8,13 +8,14 @@ import click -def pprint_column_names(format_string, format_kwargs, margin=None, table_header=None): +def pprint_column_names(format_string, format_kwargs, margin=None, table_header=None, color="yellow"): """ :param format_string: format string to be used that has the strings, minimum width to be replaced :param format_kwargs: dictionary that is supplied to the format_string to format the string :param margin: margin that is to be reduced from column width for columnar text. :param table_header: Supplied table header + :param color: color supplied for table headers and column names. :return: boilerplate table string """ @@ -55,10 +56,10 @@ def pprint_wrap(func): def wrap(*args, **kwargs): # The table is setup with the column names, format_string contains the column names. if table_header: - click.secho("\n" + table_header) - click.secho("-" * usable_width) - click.secho(format_string.format(*format_args, **format_kwargs)) - click.secho("-" * usable_width) + click.secho("\n" + table_header, fg=color) + click.secho("-" * usable_width, fg=color) + click.secho(format_string.format(*format_args, **format_kwargs), fg=color) + click.secho("-" * usable_width, fg=color) # format_args which have the minimumwidth set per {} in the format_string is passed to the function # which this decorator wraps, so that the function has access to the correct format_args kwargs["format_args"] = format_args @@ -66,7 +67,7 @@ def wrap(*args, **kwargs): kwargs["margin"] = margin if margin else min_margin result = func(*args, **kwargs) # Complete the table - click.secho("-" * usable_width) + click.secho("-" * usable_width, fg=color) return result return wrap @@ -88,7 +89,7 @@ def wrapped_text_generator(texts, width, margin): yield textwrap.wrap(text, width=width - margin) -def pprint_columns(columns, width, margin, format_string, format_args, columns_dict): +def pprint_columns(columns, width, margin, format_string, format_args, columns_dict, color="yellow"): """ Print columns based on list of columnar text, associated formatting string and associated format arguments. @@ -99,6 +100,7 @@ def pprint_columns(columns, width, margin, format_string, format_args, columns_d :param format_string: A format string that has both width and text specifiers set. :param format_args: list of offset specifiers :param columns_dict: arguments dictionary that have dummy values per column + :param color: color supplied for rows within the table. :return: """ for columns_text in zip_longest(*wrapped_text_generator(columns, width, margin), fillvalue=""): @@ -107,4 +109,4 @@ def pprint_columns(columns, width, margin, format_string, format_args, columns_d for k, _ in columns_dict.items(): columns_dict[k] = columns_text[next(counter)] - click.secho(format_string.format(*format_args, **columns_dict)) + click.secho(format_string.format(*format_args, **columns_dict), fg=color) diff --git a/samcli/lib/deploy/deployer.py b/samcli/lib/deploy/deployer.py index b7e3a77969..74a50b3583 100644 --- a/samcli/lib/deploy/deployer.py +++ b/samcli/lib/deploy/deployer.py @@ -24,6 +24,7 @@ import botocore +from samcli.lib.deploy.utils import DeployColor from samcli.commands.deploy.exceptions import DeployFailedError, ChangeSetError, DeployStackOutPutFailedError from samcli.commands._utils.table_print import pprint_column_names, pprint_columns from samcli.commands.deploy import exceptions as deploy_exceptions @@ -69,6 +70,7 @@ def __init__(self, cloudformation_client, changeset_prefix="samcli-deploy"): self.backoff = 2 # Maximum number of attempts before raising exception back up the chain. self.max_attempts = 3 + self.deploy_color = DeployColor() def has_stack(self, stack_name): """ @@ -206,6 +208,7 @@ def describe_changeset(self, change_set_id, stack_name, **kwargs): for k, v in changes.items(): for value in v: + row_color = self.deploy_color.get_changeset_action_color(action=k) pprint_columns( columns=[changes_showcase.get(k, k), value["LogicalResourceId"], value["ResourceType"]], width=kwargs["width"], @@ -213,6 +216,7 @@ def describe_changeset(self, change_set_id, stack_name, **kwargs): format_string=DESCRIBE_CHANGESET_FORMAT_STRING, format_args=kwargs["format_args"], columns_dict=DESCRIBE_CHANGESET_DEFAULT_ARGS.copy(), + color=row_color, ) if not changeset: @@ -320,7 +324,7 @@ def describe_stack_events(self, stack_name, time_stamp_marker, **kwargs): for event in event_items["StackEvents"]: if event["EventId"] not in events and utc_to_timestamp(event["Timestamp"]) > time_stamp_marker: events.add(event["EventId"]) - + row_color = self.deploy_color.get_stack_events_status_color(status=event["ResourceStatus"]) pprint_columns( columns=[ event["ResourceStatus"], @@ -333,6 +337,7 @@ def describe_stack_events(self, stack_name, time_stamp_marker, **kwargs): format_string=DESCRIBE_STACK_EVENTS_FORMAT_STRING, format_args=kwargs["format_args"], columns_dict=DESCRIBE_STACK_EVENTS_DEFAULT_ARGS.copy(), + color=row_color, ) if self._check_stack_complete(stack_status): diff --git a/samcli/lib/deploy/utils.py b/samcli/lib/deploy/utils.py new file mode 100644 index 0000000000..6c556c7068 --- /dev/null +++ b/samcli/lib/deploy/utils.py @@ -0,0 +1,34 @@ +""" +Utilities for Deploy +""" + +from samcli.lib.utils.colors import Colored + + +class DeployColor: + def __init__(self): + self._color = Colored() + self.changeset_color_map = {"Add": "green", "Modify": "yellow", "Remove": "red"} + self.status_color_map = { + "CREATE_COMPLETE": "green", + "CREATE_FAILED": "red", + "CREATE_IN_PROGRESS": "yellow", + "DELETE_COMPLETE": "green", + "DELETE_FAILED": "red", + "DELETE_IN_PROGRESS": "red", + "REVIEW_IN_PROGRESS": "yellow", + "ROLLBACK_COMPLETE": "red", + "ROLLBACK_IN_PROGRESS": "red", + "UPDATE_COMPLETE": "green", + "UPDATE_COMPLETE_CLEANUP_IN_PROGRESS": "yellow", + "UPDATE_IN_PROGRESS": "yellow", + "UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS": "red", + "UPDATE_ROLLBACK_FAILED": "red", + "UPDATE_ROLLBACK_IN_PROGRESS": "red", + } + + def get_stack_events_status_color(self, status): + return self.status_color_map.get(status, "yellow") + + def get_changeset_action_color(self, action): + return self.changeset_color_map.get(action, "yellow")