-
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: `sam logs` help text * fix: make ruff happy * fix: address comments
- Loading branch information
Showing
10 changed files
with
307 additions
and
29 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,119 @@ | ||
from click import Context, style | ||
|
||
from samcli.cli.core.command import CoreCommand | ||
from samcli.cli.row_modifiers import RowDefinition, ShowcaseRowModifier | ||
from samcli.commands.logs.core.formatters import LogsCommandHelpTextFormatter | ||
from samcli.commands.logs.core.options import OPTIONS_INFO | ||
|
||
COL_SIZE_MODIFIER = 38 | ||
|
||
|
||
class LogsCommand(CoreCommand): | ||
class CustomFormatterContext(Context): | ||
formatter_class = LogsCommandHelpTextFormatter | ||
|
||
context_class = CustomFormatterContext | ||
|
||
@staticmethod | ||
def format_examples(ctx: Context, formatter: LogsCommandHelpTextFormatter): | ||
with formatter.indented_section(name="Examples", extra_indents=1): | ||
with formatter.indented_section( | ||
name="Fetch logs with Lambda Function Logical ID and Cloudformation Stack Name" | ||
): | ||
formatter.write_rd( | ||
[ | ||
RowDefinition( | ||
text="\n", | ||
), | ||
RowDefinition( | ||
name=style(f"$ {ctx.command_path} -n HelloWorldFunction --stack-name mystack"), | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
] | ||
) | ||
with formatter.indented_section(name="View logs for specific time range"): | ||
formatter.write_rd( | ||
[ | ||
RowDefinition( | ||
text="\n", | ||
), | ||
RowDefinition( | ||
name=style( | ||
f"$ {ctx.command_path} -n HelloWorldFunction --stack-name mystack -s " | ||
f"'10min ago' -e '2min ago'" | ||
), | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
] | ||
) | ||
with formatter.indented_section(name="Tail new logs"): | ||
formatter.write_rd( | ||
[ | ||
RowDefinition( | ||
text="\n", | ||
), | ||
RowDefinition( | ||
name=style(f"$ {ctx.command_path} -n HelloWorldFunction --stack-name " f"mystack --tail"), | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
] | ||
) | ||
with formatter.indented_section(name="Fetch from Cloudwatch log groups"): | ||
formatter.write_rd( | ||
[ | ||
RowDefinition( | ||
text="\n", | ||
), | ||
RowDefinition( | ||
name=style( | ||
f"$ {ctx.command_path} --cw-log-group /aws/lambda/myfunction-123 " | ||
f"--cw-log-group /aws/lambda/myfunction-456" | ||
), | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
] | ||
) | ||
|
||
with formatter.indented_section(name="Fetch logs from supported resources in Cloudformation stack"): | ||
formatter.write_rd( | ||
[ | ||
RowDefinition( | ||
text="\n", | ||
), | ||
RowDefinition( | ||
name=style(f"$ {ctx.command_path} ---stack-name mystack"), | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
] | ||
) | ||
|
||
with formatter.indented_section(name="Fetch logs from resource defined in nested Cloudformation stack"): | ||
formatter.write_rd( | ||
[ | ||
RowDefinition( | ||
text="\n", | ||
), | ||
RowDefinition( | ||
name=style( | ||
f"$ {ctx.command_path} ---stack-name mystack -n MyNestedStack/HelloWorldFunction" | ||
), | ||
extra_row_modifiers=[ShowcaseRowModifier()], | ||
), | ||
] | ||
) | ||
|
||
def format_options(self, ctx: Context, formatter: LogsCommandHelpTextFormatter) -> 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) | ||
LogsCommand.format_examples(ctx, formatter) | ||
|
||
CoreCommand._format_options( | ||
ctx=ctx, | ||
params=self.get_params(ctx), | ||
formatter=formatter, | ||
formatting_options=OPTIONS_INFO, | ||
write_rd_overrides={"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.logs.core.options import ALL_OPTIONS | ||
|
||
|
||
class LogsCommandHelpTextFormatter(RootCommandHelpTextFormatter): | ||
# Picked an additive constant that gives an aesthetically pleasing look. | ||
ADDITIVE_JUSTIFICATION = 22 | ||
|
||
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,45 @@ | ||
""" | ||
Logs Command Options related Datastructures for formatting. | ||
""" | ||
from typing import Dict, List | ||
|
||
from samcli.cli.core.options import ALL_COMMON_OPTIONS, add_common_options_info | ||
from samcli.cli.row_modifiers import RowDefinition | ||
|
||
# The ordering of the option lists matter, they are the order in which options will be displayed. | ||
|
||
LOG_IDENTIFIER_OPTIONS: List[str] = ["stack_name", "cw_log_group", "name"] | ||
|
||
# Can be used instead of the options in the first list | ||
ADDITIONAL_OPTIONS: List[str] = ["include_traces", "filter", "output", "tail", "start_time", "end_time"] | ||
|
||
AWS_CREDENTIAL_OPTION_NAMES: List[str] = ["region", "profile"] | ||
|
||
CONFIGURATION_OPTION_NAMES: List[str] = ["config_env", "config_file"] | ||
|
||
ALL_OPTIONS: List[str] = ( | ||
LOG_IDENTIFIER_OPTIONS | ||
+ AWS_CREDENTIAL_OPTION_NAMES | ||
+ ADDITIONAL_OPTIONS | ||
+ CONFIGURATION_OPTION_NAMES | ||
+ ALL_COMMON_OPTIONS | ||
) | ||
|
||
OPTIONS_INFO: Dict[str, Dict] = { | ||
"Log Identifier Options": {"option_names": {opt: {"rank": idx} for idx, opt in enumerate(LOG_IDENTIFIER_OPTIONS)}}, | ||
"AWS Credential Options": { | ||
"option_names": {opt: {"rank": idx} for idx, opt in enumerate(AWS_CREDENTIAL_OPTION_NAMES)} | ||
}, | ||
"Additional Options": {"option_names": {opt: {"rank": idx} for idx, opt in enumerate(ADDITIONAL_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. " | ||
), | ||
], | ||
}, | ||
} | ||
add_common_options_info(OPTIONS_INFO) |
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,73 @@ | ||
import unittest | ||
from unittest.mock import Mock, patch | ||
from samcli.commands.logs.core.command import LogsCommand | ||
from samcli.commands.logs.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 TestLogsCommand(unittest.TestCase): | ||
@patch.object(LogsCommand, "get_params") | ||
def test_get_options_logs_command_text(self, mock_get_params): | ||
ctx = Mock() | ||
ctx.command_path = "sam logs" | ||
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=("--stack-name", ""), name="stack_name"), | ||
MockParams(rv=("--tail", ""), name="tail"), | ||
MockParams(rv=("--beta-features", ""), name="beta_features"), | ||
] | ||
|
||
cmd = LogsCommand(name="logs", requires_credentials=True, description=DESCRIPTION) | ||
expected_output = { | ||
"AWS Credential Options": [("", ""), ("--region", ""), ("", "")], | ||
"Additional Options": [("", ""), ("--tail", ""), ("", "")], | ||
"Beta Options": [("", ""), ("--beta-features", ""), ("", "")], | ||
"Configuration Options": [("", ""), ("--config-file", ""), ("", "")], | ||
"Description": [(cmd.description + cmd.description_addendum, "")], | ||
"Examples": [], | ||
"Fetch from Cloudwatch log groups": [ | ||
("", ""), | ||
( | ||
"$ sam logs --cw-log-group " | ||
"/aws/lambda/myfunction-123 " | ||
"--cw-log-group " | ||
"/aws/lambda/myfunction-456\x1b[0m", | ||
"", | ||
), | ||
], | ||
"Fetch logs from resource defined in nested Cloudformation stack": [ | ||
("", ""), | ||
("$ sam " "logs " "---stack-name " "mystack " "-n " "MyNestedStack/HelloWorldFunction\x1b[0m", ""), | ||
], | ||
"Fetch logs from supported resources in Cloudformation stack": [ | ||
("", ""), | ||
("$ sam logs " "---stack-name " "mystack\x1b[0m", ""), | ||
], | ||
"Fetch logs with Lambda Function Logical ID and Cloudformation Stack Name": [ | ||
("", ""), | ||
("$ " "sam " "logs " "-n " "HelloWorldFunction " "--stack-name " "mystack\x1b[0m", ""), | ||
], | ||
"Log Identifier Options": [("", ""), ("--stack-name", ""), ("", "")], | ||
"Other Options": [("", ""), ("--debug", ""), ("", "")], | ||
"Tail new logs": [("", ""), ("$ sam logs -n HelloWorldFunction --stack-name mystack " "--tail\x1b[0m", "")], | ||
"View logs for specific time range": [ | ||
("", ""), | ||
("$ sam logs -n HelloWorldFunction " "--stack-name mystack -s '10min ago' " "-e '2min ago'\x1b[0m", ""), | ||
], | ||
} | ||
cmd.format_options(ctx, formatter) | ||
self.assertEqual(formatter.data, expected_output) |
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,12 @@ | ||
from shutil import get_terminal_size | ||
from unittest import TestCase | ||
|
||
from samcli.cli.row_modifiers import BaseLineRowModifier | ||
from samcli.commands.logs.core.formatters import LogsCommandHelpTextFormatter | ||
|
||
|
||
class TestLogsCommandHelpTextFormatter(TestCase): | ||
def test_logs_formatter(self): | ||
self.formatter = LogsCommandHelpTextFormatter() | ||
self.assertTrue(self.formatter.left_justification_length <= get_terminal_size().columns // 2) | ||
self.assertIsInstance(self.formatter.modifiers[0], 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,12 @@ | ||
from unittest import TestCase | ||
|
||
from click import Option | ||
|
||
from samcli.commands.logs.command import cli | ||
from samcli.commands.logs.core.options import ALL_OPTIONS | ||
|
||
|
||
class TestOptions(TestCase): | ||
def test_all_options_formatted(self): | ||
command_options = [param.human_readable_name if isinstance(param, Option) else None for param in cli.params] | ||
self.assertEqual(sorted(ALL_OPTIONS), sorted(filter(lambda item: item is not None, command_options + ["help"]))) |