Skip to content

Commit

Permalink
Merge from develop branch pull request #4179
Browse files Browse the repository at this point in the history
chore: merge from develop branch
  • Loading branch information
moelasmar authored Sep 1, 2022
2 parents f717ef0 + c7d28da commit e9bd573
Show file tree
Hide file tree
Showing 93 changed files with 3,587 additions and 304 deletions.
4 changes: 2 additions & 2 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ boto3>=1.19.5,==1.*
jmespath~=0.10.0
PyYAML~=5.3
cookiecutter~=2.1.1
aws-sam-translator==1.48.0
aws-sam-translator==1.50.0
#docker minor version updates can include breaking changes. Auto update micro version only.
docker~=4.2.0
dateparser~=1.0
requests==2.25.1
serverlessrepo==0.1.10
aws_lambda_builders==1.18.0
aws_lambda_builders==1.19.0
tomlkit==0.7.2
watchdog==2.1.2

Expand Down
16 changes: 8 additions & 8 deletions requirements/reproducible-linux.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ attrs==20.3.0 \
--hash=sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6 \
--hash=sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700
# via jsonschema
aws-lambda-builders==1.18.0 \
--hash=sha256:555c1bb72bab633deeb806cc347b40ed865d63166e536c89ff71f0ba739577b1 \
--hash=sha256:c0bd4b4288f0aa9cba27493065f5fb986425b5b49620b93a391620403eeb97e0 \
--hash=sha256:c5235699d36b8edda7e649fbc3a23ed868eda1e15c4a83528df33939bdb75754
aws-lambda-builders==1.19.0 \
--hash=sha256:32e26425ad626c7e2c41989c894c2c5f70cce7574ed7729e37cdd262a049fd8a \
--hash=sha256:38fcb9023df09f3c39504498cf45a213a29b176be5cec36126b13b77604731bd \
--hash=sha256:61e3f1e77b62ab72b97f822c09385ce16dc0e5478b52de7296a79570be41be73
# via aws-sam-cli (setup.py)
aws-sam-translator==1.48.0 \
--hash=sha256:7171037323dfa30f8f73e9bccb9210e4c384a585e087219a9518a5204f0a2c44 \
--hash=sha256:be18dfa3dfe7ab291d281667c5f73ac62dbe6bfe86df7d122e4258b906b736f0 \
--hash=sha256:ca4f8f9910d7713aeaba59346775bfb3198f6acb47c6704572f9bd3fc0fb5bf0
aws-sam-translator==1.50.0 \
--hash=sha256:09668d12b5d330412421d30d4a8e826da6fe06f5a451f771c3b37f48f1b25889 \
--hash=sha256:85bea2739e1b4a61b3e4add8a12f727d7a8e459e3da195dfd0cd2e756be054ec \
--hash=sha256:d375e9333c0262ed74b6d7ae90938060713ab17341f4e06c5cdbfd755902d9b4
# via aws-sam-cli (setup.py)
backports-zoneinfo==0.2.1 \
--hash=sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf \
Expand Down
2 changes: 1 addition & 1 deletion samcli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
SAM CLI version
"""

__version__ = "1.53.0"
__version__ = "1.56.0"
10 changes: 8 additions & 2 deletions samcli/cli/cli_config_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,22 @@ def configuration_callback(cmd_name, option_name, saved_callback, provider, ctx,
cmd_name = cmd_name or ctx.info_name
param.default = None
config_env_name = ctx.params.get("config_env") or DEFAULT_ENV

config_file = ctx.params.get("config_file") or DEFAULT_CONFIG_FILE_NAME
config_dir = getattr(ctx, "samconfig_dir", None) or os.getcwd()
# If --config-file is an absolute path, use it, if not, start from config_dir
config_file_name = config_file if os.path.isabs(config_file) else os.path.join(config_dir, config_file)
config_file_path = config_file if os.path.isabs(config_file) else os.path.join(config_dir, config_file)
if config_file and config_file != DEFAULT_CONFIG_FILE_NAME and not Path(config_file_path).absolute().is_file():
error_msg = f"Config file {config_file} does not exist or could not be read!"
LOG.debug(error_msg)
raise ConfigException(error_msg)

config = get_ctx_defaults(
cmd_name,
provider,
ctx,
config_env_name=config_env_name,
config_file=config_file_name,
config_file=config_file_path,
)
ctx.default_map.update(config)

Expand Down
24 changes: 21 additions & 3 deletions samcli/cli/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,16 @@ class CfnTags(click.ParamType):
"""
Custom Click options type to accept values for tag parameters.
tag parameters can be of the type KeyName1=string KeyName2=string
If multiple_values_per_key is set to True, the returned dictionary will map
each key to a list of corresponding values.
E.g. Input: KeyName1=Value1 KeyName1=Value2 Output: {KeyName1 : [Value1, Value2]}
"""

def __init__(self, multiple_values_per_key=False):
self.multiple_values_per_key = multiple_values_per_key

_EXAMPLE = "KeyName1=string KeyName2=string"
# Tags have additional constraints and they allow "+ - = . _ : / @" apart from alpha-numerics.
TAG_REGEX = '[A-Za-z0-9\\"_:\\.\\/\\+-\\@=]'
Expand Down Expand Up @@ -212,16 +220,15 @@ def convert(self, value, param, ctx):
parsed, tags = self._space_separated_key_value_parser(val)
if parsed:
for k in tags:
result[_unquote_wrapped_quotes(k)] = _unquote_wrapped_quotes(tags[k])
self._add_value(result, _unquote_wrapped_quotes(k), _unquote_wrapped_quotes(tags[k]))
else:
groups = re.findall(self._pattern, val)

if not groups:
fail = True
for group in groups:
key, v = group
# assign to result['KeyName1'] = string and so on.
result[_unquote_wrapped_quotes(key)] = _unquote_wrapped_quotes(v)
self._add_value(result, _unquote_wrapped_quotes(key), _unquote_wrapped_quotes(v))

if fail:
return self.fail(
Expand All @@ -232,6 +239,17 @@ def convert(self, value, param, ctx):

return result

def _add_value(self, result: dict, key: str, new_value: str):
"""
Add a given value to a given key in the result map.
"""
if self.multiple_values_per_key:
if not result.get(key):
result[key] = []
result[key].append(new_value)
return
result[key] = new_value

@staticmethod
def _standard_key_value_parser(tag_value):
"""
Expand Down
4 changes: 3 additions & 1 deletion samcli/commands/_utils/experimental.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ class ExperimentalFlag:
"""Class for storing all experimental related ConfigEntries"""

All = ExperimentalEntry("experimentalAll", EXPERIMENTAL_ENV_VAR_PREFIX + "FEATURES")
Esbuild = ExperimentalEntry("experimentalEsbuild", EXPERIMENTAL_ENV_VAR_PREFIX + "ESBUILD")
BuildPerformance = ExperimentalEntry(
"experimentalBuildPerformance", EXPERIMENTAL_ENV_VAR_PREFIX + "BUILD_PERFORMANCE"
)
IaCsSupport = {
"terraform": ExperimentalEntry(
"experimentalTerraformSupport", EXPERIMENTAL_ENV_VAR_PREFIX + "TERRAFORM_SUPPORT"
Expand Down
97 changes: 57 additions & 40 deletions samcli/commands/build/build_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@

import click

from samcli.commands._utils.experimental import ExperimentalFlag, prompt_experimental
from samcli.lib.build.bundler import EsbuildBundlerManager
from samcli.lib.providers.sam_api_provider import SamApiProvider
from samcli.lib.telemetry.event import EventTracker
from samcli.lib.utils.packagetype import IMAGE

from samcli.commands._utils.template import get_template_data
Expand All @@ -34,6 +35,7 @@
BuildError,
UnsupportedBuilderLibraryVersionError,
ContainerBuildNotSupported,
ApplicationBuildResult,
)
from samcli.commands._utils.constants import DEFAULT_BUILD_DIR
from samcli.lib.build.workflow_config import UnsupportedRuntimeException
Expand Down Expand Up @@ -222,6 +224,8 @@ def run(self):
if is_sam_template:
SamApiProvider.check_implicit_api_resource_ids(self.stacks)

self._stacks = self._handle_build_pre_processing()

try:
builder = ApplicationBuilder(
self.get_resources_to_build(),
Expand All @@ -243,29 +247,14 @@ def run(self):
raise UserException(str(ex), wrapped_from=ex.__class__.__name__) from ex

try:
self._check_esbuild_warning()
self._check_exclude_warning()

build_result = builder.build()
artifacts = build_result.artifacts

stack_output_template_path_by_stack_path = {
stack.stack_path: stack.get_output_template_path(self.build_dir) for stack in self.stacks
}
for stack in self.stacks:
modified_template = builder.update_template(
stack,
artifacts,
stack_output_template_path_by_stack_path,
)
output_template_path = stack.get_output_template_path(self.build_dir)
self._handle_build_post_processing(builder, build_result)

if self._create_auto_dependency_layer:
LOG.debug("Auto creating dependency layer for each function resource into a nested stack")
nested_stack_manager = NestedStackManager(
stack, self._stack_name, self.build_dir, modified_template, build_result
)
modified_template = nested_stack_manager.generate_auto_dependency_layer_stack()
move_template(stack.location, output_template_path, modified_template)
for f in self.get_resources_to_build().functions:
EventTracker.track_event("BuildFunctionRuntime", f.runtime)

click.secho("\nBuild Succeeded", fg="green")

Expand Down Expand Up @@ -307,6 +296,54 @@ def run(self):
wrapped_from = deep_wrap if deep_wrap else ex.__class__.__name__
raise UserException(str(ex), wrapped_from=wrapped_from) from ex

def _handle_build_pre_processing(self) -> List[Stack]:
"""
Pre-modify the stacks as required before invoking the build
:return: List of modified stacks
"""
stacks = []
if any(EsbuildBundlerManager(stack).esbuild_configured() for stack in self.stacks):
# esbuild is configured in one of the stacks, will check and update stack metadata accordingly
for stack in self.stacks:
stacks.append(EsbuildBundlerManager(stack).set_sourcemap_metadata_from_env())
self.function_provider.update(stacks, self._use_raw_codeuri, locate_layer_nested=self._locate_layer_nested)
return stacks if stacks else self.stacks

def _handle_build_post_processing(self, builder: ApplicationBuilder, build_result: ApplicationBuildResult) -> None:
"""
Add any template modifications necessary before moving the template to build directory
:param stack: Stack resources
:param template: Current template file
:param build_result: Result of the application build
:return: Modified template dict
"""
artifacts = build_result.artifacts

stack_output_template_path_by_stack_path = {
stack.stack_path: stack.get_output_template_path(self.build_dir) for stack in self.stacks
}
for stack in self.stacks:
modified_template = builder.update_template(
stack,
artifacts,
stack_output_template_path_by_stack_path,
)
output_template_path = stack.get_output_template_path(self.build_dir)

stack_name = self._stack_name if self._stack_name else ""
if self._create_auto_dependency_layer:
LOG.debug("Auto creating dependency layer for each function resource into a nested stack")
nested_stack_manager = NestedStackManager(
stack, stack_name, self.build_dir, modified_template, build_result
)
modified_template = nested_stack_manager.generate_auto_dependency_layer_stack()

esbuild_manager = EsbuildBundlerManager(stack=stack, template=modified_template)
if esbuild_manager.esbuild_configured():
modified_template = esbuild_manager.set_sourcemap_env_from_metadata()

move_template(stack.location, output_template_path, modified_template)

@staticmethod
def gen_success_msg(artifacts_dir: str, output_template_path: str, is_default_build_dir: bool) -> str:

Expand Down Expand Up @@ -589,28 +626,8 @@ def _is_layer_buildable(layer: LayerVersion):
return False
return True

_ESBUILD_WARNING_MESSAGE = (
"Using esbuild for bundling Node.js and TypeScript is a beta feature.\n"
"Please confirm if you would like to proceed with using esbuild to build your function.\n"
"You can also enable this beta feature with 'sam build --beta-features'."
)

_EXCLUDE_WARNING_MESSAGE = "Resource expected to be built, but marked as excluded.\nBuilding anyways..."

def _check_esbuild_warning(self) -> None:
"""
Prints warning message and confirms that the user wants to enable beta features
"""
resources_to_build = self.get_resources_to_build()
is_building_esbuild = False
for function in resources_to_build.functions:
if function.metadata and function.metadata.get("BuildMethod", "") == "esbuild":
is_building_esbuild = True
break

if is_building_esbuild:
prompt_experimental(ExperimentalFlag.Esbuild, self._ESBUILD_WARNING_MESSAGE)

def _check_exclude_warning(self) -> None:
"""
Prints warning message if a single resource to build is also being excluded
Expand Down
25 changes: 25 additions & 0 deletions samcli/commands/deploy/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from samcli.cli.cli_config_file import TomlProvider, configuration_option
from samcli.cli.main import aws_creds_options, common_options, pass_context, print_cmdline_args
from samcli.commands._utils.cdk_support_decorators import unsupported_command_cdk
from samcli.commands._utils.click_mutex import ClickMutex
from samcli.commands._utils.options import (
capabilities_option,
guided_deploy_stack_name,
Expand Down Expand Up @@ -107,6 +108,26 @@
required=False,
is_flag=True,
help="Preserves the state of previously provisioned resources when an operation fails.",
cls=ClickMutex,
incompatible_params=["on_failure"],
)
@click.option(
"--on-failure",
default="ROLLBACK",
type=click.Choice(["ROLLBACK", "DELETE", "DO_NOTHING"]),
required=False,
help="""
Provide an action to determine what will happen when a stack fails to create. Three actions are available:\n
- ROLLBACK: This will rollback a stack to a previous known good state.\n
- DELETE: The stack will rollback to a previous state if one exists, otherwise the stack will be deleted.\n
- DO_NOTHING: The stack will not rollback or delete, this is the same as disabling rollback.\n
Default behaviour is ROLLBACK.\n\n
This option is mutually exclusive with --disable-rollback/--no-disable-rollback. You can provide
--on-failure or --disable-rollback/--no-disable-rollback but not both at the same time.
""",
cls=ClickMutex,
incompatible_params=["disable_rollback", "no_disable_rollback"],
)
@stack_name_option(callback=guided_deploy_stack_name) # pylint: disable=E1120
@s3_bucket_option(disable_callback=True) # pylint: disable=E1120
Expand Down Expand Up @@ -162,6 +183,7 @@ def cli(
config_file,
config_env,
disable_rollback,
on_failure,
):
"""
`sam deploy` command entry point
Expand Down Expand Up @@ -196,6 +218,7 @@ def cli(
config_env,
resolve_image_repos,
disable_rollback,
on_failure,
) # pragma: no cover


Expand Down Expand Up @@ -228,6 +251,7 @@ def do_cli(
config_env,
resolve_image_repos,
disable_rollback,
on_failure,
):
"""
Implementation of the ``cli`` method
Expand Down Expand Up @@ -330,5 +354,6 @@ def do_cli(
use_changeset=True,
disable_rollback=guided_context.disable_rollback if guided else disable_rollback,
poll_delay=poll_delay,
on_failure=on_failure,
) as deploy_context:
deploy_context.run()
Loading

0 comments on commit e9bd573

Please sign in to comment.