-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Deploy Help Text Overhaul (#4941)
* feat: Update sam deploy help text * Fix column spacing * Update formatting * Add tests * Change secondary required options to interactive options * Add test to check params
- Loading branch information
Showing
10 changed files
with
342 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
from typing import List | ||
|
||
from click import Context, style | ||
|
||
from samcli.cli.core.command import CoreCommand | ||
from samcli.cli.row_modifiers import RowDefinition, ShowcaseRowModifier | ||
from samcli.commands.deploy.core.formatters import DeployCommandHelpTextFormatter | ||
from samcli.commands.deploy.core.options import OPTIONS_INFO | ||
|
||
COL_SIZE_MODIFIER = 50 | ||
|
||
|
||
class DeployCommand(CoreCommand): | ||
class CustomFormatterContext(Context): | ||
formatter_class = DeployCommandHelpTextFormatter | ||
|
||
context_class = CustomFormatterContext | ||
|
||
@staticmethod | ||
def format_examples(ctx: Context, formatter: DeployCommandHelpTextFormatter): | ||
with formatter.indented_section(name="Examples", extra_indents=1): | ||
formatter.write_rd( | ||
[ | ||
RowDefinition( | ||
text="\n", | ||
), | ||
RowDefinition( | ||
name=style(f"$ {ctx.command_path} --guided"), extra_row_modifiers=[ShowcaseRowModifier()] | ||
), | ||
RowDefinition( | ||
name=style( | ||
f"$ {ctx.command_path} --template-file packaged.yaml --stack-name " | ||
f"sam-app --capabilities CAPABILITY_IAM" | ||
), | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
RowDefinition( | ||
name=style( | ||
f"$ {ctx.command_path} --parameter-overrides " | ||
f"'ParameterKey=InstanceType,ParameterValue=t1.micro'" | ||
), | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
RowDefinition( | ||
name=style( | ||
f"$ {ctx.command_path} --parameter-overrides KeyPairName=MyKey InstanceType=t1.micro" | ||
), | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
], | ||
col_max=COL_SIZE_MODIFIER, | ||
) | ||
|
||
@staticmethod | ||
def format_acronyms(formatter: DeployCommandHelpTextFormatter): | ||
with formatter.indented_section(name="Acronyms", extra_indents=1): | ||
formatter.write_rd( | ||
[ | ||
RowDefinition( | ||
text="\n", | ||
), | ||
RowDefinition( | ||
name="IAM", | ||
text="Identity and Access Management", | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
RowDefinition( | ||
name="ARN", | ||
text="Amazon Resource Name", | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
RowDefinition( | ||
name="S3", | ||
text="Simple Storage Service", | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
RowDefinition( | ||
name="SNS", | ||
text="Simple Notification Service", | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
RowDefinition( | ||
name="ECR", | ||
text="Elastic Container Registry", | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
RowDefinition( | ||
name="KMS", | ||
text="Key Management Service", | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
], | ||
col_max=COL_SIZE_MODIFIER, | ||
) | ||
|
||
def format_options(self, ctx: Context, formatter: DeployCommandHelpTextFormatter) -> None: # type:ignore | ||
# `ignore` is put in place here for mypy even though it is the correct behavior, | ||
# as the `formatter_class` can be set in subclass of Command. If ignore is not set, | ||
# mypy raises argument needs to be HelpFormatter as super class defines it. | ||
|
||
self.format_description(formatter) | ||
DeployCommand.format_examples(ctx, formatter) | ||
DeployCommand.format_acronyms(formatter) | ||
|
||
for option_heading, options in OPTIONS_INFO.items(): | ||
opts: List[RowDefinition] = sorted( | ||
[ | ||
CoreCommand.convert_param_to_row_definition( | ||
ctx=ctx, param=param, rank=options.get("option_names", {}).get(param.name, {}).get("rank", 0) | ||
) | ||
for param in self.get_params(ctx) | ||
if param.name in options.get("option_names", {}).keys() | ||
], | ||
key=lambda row_def: row_def.rank, | ||
) | ||
with formatter.indented_section(name=option_heading, extra_indents=1): | ||
formatter.write_rd(options.get("extras", [RowDefinition()]), col_max=COL_SIZE_MODIFIER) | ||
formatter.write_rd( | ||
[RowDefinition(name="", text="\n")] | ||
+ [ | ||
opt | ||
for options in zip(opts, [RowDefinition(name="", text="\n")] * (len(opts))) | ||
for opt in options | ||
], | ||
col_max=COL_SIZE_MODIFIER, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from samcli.cli.formatters import RootCommandHelpTextFormatter | ||
from samcli.cli.row_modifiers import BaseLineRowModifier | ||
from samcli.commands.deploy.core.options import ALL_OPTIONS | ||
|
||
|
||
class DeployCommandHelpTextFormatter(RootCommandHelpTextFormatter): | ||
# Picked an additive constant that gives an aesthetically pleasing look. | ||
ADDITIVE_JUSTIFICATION = 15 | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
# Add Additional space after determining the longest option. | ||
# However, do not justify with padding for more than half the width of | ||
# the terminal to retain aesthetics. | ||
self.left_justification_length = min( | ||
max([len(option) for option in ALL_OPTIONS]) + self.ADDITIVE_JUSTIFICATION, | ||
self.width // 2 - self.indent_increment, | ||
) | ||
self.modifiers = [BaseLineRowModifier()] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
""" | ||
Deploy Command Options related Datastructures for formatting. | ||
""" | ||
from typing import Dict, List | ||
|
||
from samcli.cli.row_modifiers import RowDefinition | ||
|
||
# The ordering of the option lists matter, they are the order in which options will be displayed. | ||
|
||
REQUIRED_OPTIONS: List[str] = ["stack_name", "capabilities", "resolve_s3"] | ||
|
||
# Can be used instead of the options in the first list | ||
INTERACTIVE_OPTIONS: List[str] = ["guided"] | ||
|
||
AWS_CREDENTIAL_OPTION_NAMES: List[str] = ["region", "profile"] | ||
|
||
INFRASTRUCTURE_OPTION_NAMES: List[str] = [ | ||
"parameter_overrides", | ||
"s3_bucket", | ||
"s3_prefix", | ||
"resolve_image_repos", | ||
"image_repository", | ||
"image_repositories", | ||
"role_arn", | ||
"kms_key_id", | ||
"notification_arns", | ||
"tags", | ||
"metadata", | ||
] | ||
|
||
DEPLOYMENT_OPTIONS: List[str] = [ | ||
"no_execute_changeset", | ||
"fail_on_empty_changeset", | ||
"confirm_changeset", | ||
"disable_rollback", | ||
"on_failure", | ||
"force_upload", | ||
] | ||
|
||
CONFIGURATION_OPTION_NAMES: List[str] = ["config_env", "config_file"] | ||
|
||
ADDITIONAL_OPTIONS: List[str] = [ | ||
"no_progressbar", | ||
"signing_profiles", | ||
"template_file", | ||
"use_json", | ||
] | ||
|
||
OTHER_OPTIONS: List[str] = ["debug"] | ||
|
||
ALL_OPTIONS: List[str] = ( | ||
REQUIRED_OPTIONS | ||
+ INTERACTIVE_OPTIONS | ||
+ AWS_CREDENTIAL_OPTION_NAMES | ||
+ INFRASTRUCTURE_OPTION_NAMES | ||
+ DEPLOYMENT_OPTIONS | ||
+ CONFIGURATION_OPTION_NAMES | ||
+ ADDITIONAL_OPTIONS | ||
+ OTHER_OPTIONS | ||
) | ||
|
||
OPTIONS_INFO: Dict[str, Dict] = { | ||
"Required Options": {"option_names": {opt: {"rank": idx} for idx, opt in enumerate(REQUIRED_OPTIONS)}}, | ||
"Interactive Options": { | ||
"option_names": {opt: {"rank": idx} for idx, opt in enumerate(INTERACTIVE_OPTIONS)}, | ||
"extras": [ | ||
RowDefinition(name="Use the guided flag for a step-by-step flow instead of using the required options. ") | ||
], | ||
}, | ||
"AWS Credential Options": { | ||
"option_names": {opt: {"rank": idx} for idx, opt in enumerate(AWS_CREDENTIAL_OPTION_NAMES)} | ||
}, | ||
"Infrastructure Options": { | ||
"option_names": {opt: {"rank": idx} for idx, opt in enumerate(INFRASTRUCTURE_OPTION_NAMES)} | ||
}, | ||
"Deployment Options": {"option_names": {opt: {"rank": idx} for idx, opt in enumerate(DEPLOYMENT_OPTIONS)}}, | ||
"Configuration Options": { | ||
"option_names": {opt: {"rank": idx} for idx, opt in enumerate(CONFIGURATION_OPTION_NAMES)}, | ||
"extras": [ | ||
RowDefinition(name="Learn more about configuration files at:"), | ||
RowDefinition( | ||
name="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli" | ||
"-config.html. " | ||
), | ||
], | ||
}, | ||
"Additional Options": {"option_names": {opt: {"rank": idx} for idx, opt in enumerate(ADDITIONAL_OPTIONS)}}, | ||
"Other Options": {"option_names": {opt: {"rank": idx} for idx, opt in enumerate(OTHER_OPTIONS)}}, | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import unittest | ||
from unittest.mock import Mock, patch | ||
from samcli.commands.deploy.core.command import DeployCommand | ||
from samcli.commands.deploy.command import DESCRIPTION | ||
from tests.unit.cli.test_command import MockFormatter | ||
|
||
|
||
class MockParams: | ||
def __init__(self, rv, name): | ||
self.rv = rv | ||
self.name = name | ||
|
||
def get_help_record(self, ctx): | ||
return self.rv | ||
|
||
|
||
class TestDeployCommand(unittest.TestCase): | ||
@patch.object(DeployCommand, "get_params") | ||
def test_get_options_deploy_command_text(self, mock_get_params): | ||
ctx = Mock() | ||
ctx.command_path = "sam deploy" | ||
ctx.parent.command_path = "sam" | ||
formatter = MockFormatter(scrub_text=True) | ||
# NOTE(sriram-mv): One option per option section. | ||
mock_get_params.return_value = [ | ||
MockParams(rv=("--region", "Region"), name="region"), | ||
MockParams(rv=("--debug", ""), name="debug"), | ||
MockParams(rv=("--config-file", ""), name="config_file"), | ||
MockParams(rv=("--s3-bucket", ""), name="s3_bucket"), | ||
MockParams(rv=("--signing-profiles", ""), name="signing_profiles"), | ||
MockParams(rv=("--stack-name", ""), name="stack_name"), | ||
MockParams(rv=("--no-execute-changeset", ""), name="no_execute_changeset"), | ||
MockParams(rv=("--guided", ""), name="guided"), | ||
] | ||
|
||
cmd = DeployCommand(name="deploy", requires_credentials=False, description=DESCRIPTION) | ||
expected_output = { | ||
"AWS Credential Options": [("", ""), ("--region", ""), ("", "")], | ||
"Additional Options": [("", ""), ("--signing-profiles", ""), ("", "")], | ||
"Deployment Options": [("", ""), ("--no-execute-changeset", ""), ("", "")], | ||
"Configuration Options": [("", ""), ("--config-file", ""), ("", "")], | ||
"Other Options": [("", ""), ("--debug", ""), ("", "")], | ||
"Required Options": [("", ""), ("--stack-name", ""), ("", "")], | ||
"Infrastructure Options": [("", ""), ("--s3-bucket", ""), ("", "")], | ||
"Interactive Options": [("", ""), ("--guided", ""), ("", "")], | ||
"Description": [(cmd.description + cmd.description_addendum, "")], | ||
"Acronyms": [("", ""), ("IAM", ""), ("ARN", ""), ("S3", ""), ("SNS", ""), ("ECR", ""), ("KMS", "")], | ||
"Examples": [ | ||
("", ""), | ||
("$ sam deploy --guided\x1b[0m", ""), | ||
( | ||
"$ sam deploy --template-file packaged.yaml --stack-name sam-app --capabilities CAPABILITY_IAM\x1b[0m", | ||
"", | ||
), | ||
("$ sam deploy --parameter-overrides 'ParameterKey=InstanceType,ParameterValue=t1.micro'\x1b[0m", ""), | ||
("$ sam deploy --parameter-overrides KeyPairName=MyKey InstanceType=t1.micro\x1b[0m", ""), | ||
], | ||
} | ||
|
||
cmd.format_options(ctx, formatter) | ||
self.assertEqual(formatter.data, expected_output) |
Oops, something went wrong.