Skip to content

Commit

Permalink
feature: Added support for parameter --resolve-s3 for non-guided depl…
Browse files Browse the repository at this point in the history
…oyments (#2102)

* fix: Region shows as "None" after stack deploys using manual parameters

* fix: Region shows as "None" after stack deploys using manual parameters

* fix: Region shows as "None" after stack deploys using manual parameters

* fix: Region shows as "None" after stack deploys using manual parameters

* feature: Added support for parameter --resolve-s3 for non-guided deployments

* feature: Added support for parameter --resolve-s3 for non-guided deployments

* Added unit and integration tests for resolve_s3

* Added unit tests for 100% coverage

* Fixed some error messages

Co-authored-by: Makati <mmmakati@3c22fb31532f.ant.amazon.com>
Co-authored-by: Makati <mmmakati@3c22fb7d737e.ant.amazon.com>
Co-authored-by: Alex Wood <awood45@gmail.com>
Co-authored-by: Mufaddal Makati <mmmakati@amazon.com>
  • Loading branch information
5 people committed Aug 13, 2020
1 parent f269fe2 commit cc2313e
Show file tree
Hide file tree
Showing 11 changed files with 364 additions and 4 deletions.
21 changes: 21 additions & 0 deletions samcli/commands/deploy/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from samcli.commands.deploy.utils import sanitize_parameter_overrides
from samcli.lib.telemetry.metrics import track_command
from samcli.lib.utils import osutils
from samcli.lib.bootstrap.bootstrap import manage_stack

SHORT_HELP = "Deploy an AWS SAM application."

Expand Down Expand Up @@ -127,6 +128,13 @@
help="Indicates whether to use JSON as the format for "
"the output AWS CloudFormation template. YAML is used by default.",
)
@click.option(
"--resolve-s3",
required=False,
is_flag=True,
help="Automatically resolve s3 bucket for non-guided deployments."
"Do not use --s3-guided parameter with this option.",
)
@metadata_override_option
@notification_arns_override_option
@tags_override_option
Expand Down Expand Up @@ -155,6 +163,7 @@ def cli(
metadata,
guided,
confirm_changeset,
resolve_s3,
):

# All logic must be implemented in the ``do_cli`` method. This helps with easy unit testing
Expand All @@ -178,6 +187,7 @@ def cli(
confirm_changeset,
ctx.region,
ctx.profile,
resolve_s3,
) # pragma: no cover


Expand All @@ -201,10 +211,12 @@ def do_cli(
confirm_changeset,
region,
profile,
resolve_s3,
):
from samcli.commands.package.package_context import PackageContext
from samcli.commands.deploy.deploy_context import DeployContext
from samcli.commands.deploy.guided_context import GuidedContext
from samcli.commands.deploy.exceptions import DeployResolveS3AndS3SetError, DeployResolveS3AndS3NotSetError

if guided:
# Allow for a guided deploy to prompt and save those details.
Expand All @@ -221,6 +233,15 @@ def do_cli(
config_section=CONFIG_SECTION,
)
guided_context.run()
elif resolve_s3 and bool(s3_bucket):
raise DeployResolveS3AndS3SetError()
elif not resolve_s3 and not bool(s3_bucket):
raise DeployResolveS3AndS3NotSetError()
elif resolve_s3:
s3_bucket = manage_stack(profile=profile, region=region)
click.echo(f"\n\t\tManaged S3 bucket: {s3_bucket}")
click.echo("\t\tA different default S3 bucket can be set in samconfig.toml")
click.echo("\t\tOr by specifying --s3-bucket explicitly.")

with osutils.tempfile_platform_independent() as output_template_file:

Expand Down
20 changes: 20 additions & 0 deletions samcli/commands/deploy/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,23 @@ def __init__(self):
)

super(DeployBucketRequiredError, self).__init__(message=message_fmt)


class DeployResolveS3AndS3SetError(UserException):
def __init__(self):
message_fmt = (
"Cannot use both --resolve-s3 and --s3-bucket parameters in non-guided deployments."
" Please use only one or use the --guided option for a guided deployment."
)

super(DeployResolveS3AndS3SetError, self).__init__(message=message_fmt)


class DeployResolveS3AndS3NotSetError(UserException):
def __init__(self):
message_fmt = (
"Cannot skip both --resolve-s3 and --s3-bucket parameters in non-guided deployments."
" Please use only one or use the --guided option for a guided deployment."
)

super(DeployResolveS3AndS3NotSetError, self).__init__(message=message_fmt)
38 changes: 36 additions & 2 deletions samcli/commands/package/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from samcli.commands._utils.options import metadata_override_option, template_click_option
from samcli.commands._utils.resources import resources_generator
from samcli.lib.telemetry.metrics import track_command
from samcli.lib.bootstrap.bootstrap import manage_stack

SHORT_HELP = "Package an AWS SAM application."

Expand Down Expand Up @@ -40,7 +41,7 @@ def resources_and_properties_help_string():
@template_click_option(include_build=True)
@click.option(
"--s3-bucket",
required=True,
required=False,
help="The name of the S3 bucket where this command uploads the artifacts that are referenced in your template.",
)
@click.option(
Expand Down Expand Up @@ -78,12 +79,30 @@ def resources_and_properties_help_string():
"in the S3 bucket. Specify this flag to upload artifacts even if they "
"match existing artifacts in the S3 bucket.",
)
@click.option(
"--resolve-s3",
required=False,
is_flag=True,
help="Automatically resolve s3 bucket for non-guided deployments."
"Do not use --s3-guided parameter with this option.",
)
@metadata_override_option
@common_options
@aws_creds_options
@pass_context
@track_command
def cli(ctx, template_file, s3_bucket, s3_prefix, kms_key_id, output_template_file, use_json, force_upload, metadata):
def cli(
ctx,
template_file,
s3_bucket,
s3_prefix,
kms_key_id,
output_template_file,
use_json,
force_upload,
metadata,
resolve_s3,
):

# All logic must be implemented in the ``do_cli`` method. This helps with easy unit testing

Expand All @@ -98,6 +117,7 @@ def cli(ctx, template_file, s3_bucket, s3_prefix, kms_key_id, output_template_fi
metadata,
ctx.region,
ctx.profile,
resolve_s3,
) # pragma: no cover


Expand All @@ -112,8 +132,22 @@ def do_cli(
metadata,
region,
profile,
resolve_s3,
):
from samcli.commands.package.package_context import PackageContext
from samcli.commands.package.exceptions import PackageResolveS3AndS3SetError, PackageResolveS3AndS3NotSetError

if resolve_s3 and bool(s3_bucket):
raise PackageResolveS3AndS3SetError()

if not resolve_s3 and not bool(s3_bucket):
raise PackageResolveS3AndS3NotSetError()

if resolve_s3:
s3_bucket = manage_stack(profile=profile, region=region)
click.echo(f"\n\t\tManaged S3 bucket: {s3_bucket}")
click.echo("\t\tA different default S3 bucket can be set in samconfig.toml")
click.echo("\t\tOr by specifying --s3-bucket explicitly.")

with PackageContext(
template_file=template_file,
Expand Down
14 changes: 14 additions & 0 deletions samcli/commands/package/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,17 @@ def __init__(self, **kwargs):
message_fmt = "\nS3 Bucket not specified, use --s3-bucket to specify a bucket name or run sam deploy --guided"

super(BucketNotSpecifiedError, self).__init__(message=message_fmt.format(**self.kwargs))


class PackageResolveS3AndS3SetError(UserException):
def __init__(self):
message_fmt = "Cannot use both --resolve-s3 and --s3-bucket parameters. Please use only one."

super(PackageResolveS3AndS3SetError, self).__init__(message=message_fmt)


class PackageResolveS3AndS3NotSetError(UserException):
def __init__(self):
message_fmt = "Cannot skip both --resolve-s3 and --s3-bucket parameters. Please provide one of these arguments."

super(PackageResolveS3AndS3NotSetError, self).__init__(message=message_fmt)
3 changes: 3 additions & 0 deletions tests/integration/deploy/deploy_integ_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def get_deploy_command_list(
profile=None,
region=None,
guided=False,
resolve_s3=False,
):
command_list = [self.base_command(), "deploy"]

Expand Down Expand Up @@ -83,6 +84,8 @@ def get_deploy_command_list(
command_list = command_list + ["--region", str(region)]
if profile:
command_list = command_list + ["--profile", str(profile)]
if resolve_s3:
command_list = command_list + ["--resolve-s3"]

return command_list

Expand Down
26 changes: 25 additions & 1 deletion tests/integration/deploy/test_deploy_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,9 @@ def test_deploy_twice_with_no_fail_on_empty_changeset(self, template_file):
}
# Package and Deploy in one go without confirming change set.
deploy_command_list = self.get_deploy_command_list(**kwargs)

print("######################################")
print(deploy_command_list)
print("######################################")
deploy_process_execute = run_command(deploy_command_list)
# Deploy should succeed
self.assertEqual(deploy_process_execute.process.returncode, 0)
Expand Down Expand Up @@ -544,6 +546,28 @@ def test_deploy_guided_set_confirm_changeset(self, template_file):
# Remove samconfig.toml
os.remove(self.test_data_path.joinpath(DEFAULT_CONFIG_FILE_NAME))

@parameterized.expand(["aws-serverless-function.yaml"])
def test_deploy_with_no_s3_bucket_set_resolve_s3(self, template_file):
template_path = self.test_data_path.joinpath(template_file)

stack_name = self._method_to_stack_name(self.id())
self.stack_names.append(stack_name)

deploy_command_list = self.get_deploy_command_list(
template_file=template_path,
stack_name=stack_name,
capabilities="CAPABILITY_IAM",
force_upload=True,
notification_arns=self.sns_arn,
parameter_overrides="Parameter=Clarity",
kms_key_id=self.kms_key,
tags="integ=true clarity=yes foo_bar=baz",
resolve_s3=True,
)

deploy_process_execute = run_command(deploy_command_list)
self.assertEqual(deploy_process_execute.process.returncode, 0)

def _method_to_stack_name(self, method_name):
"""Method expects method name which can be a full path. Eg: test.integration.test_deploy_command.method_name"""
method_name = method_name.split(".")[-1]
Expand Down
4 changes: 3 additions & 1 deletion tests/integration/package/package_integ_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def get_command_list(
force_upload=False,
kms_key_id=None,
metadata=None,
resolve_s3=False,
):
command_list = [self.base_command(), "package"]

Expand All @@ -94,5 +95,6 @@ def get_command_list(
command_list = command_list + ["--force-upload"]
if metadata:
command_list = command_list + ["--metadata", json.dumps(metadata)]

if resolve_s3:
command_list = command_list + ["--resolve-s3"]
return command_list
51 changes: 51 additions & 0 deletions tests/integration/package/test_package_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,3 +387,54 @@ def test_package_with_metadata(self, template_file):
),
process_stdout,
)

@parameterized.expand(
[
"aws-serverless-function.yaml",
"aws-serverless-api.yaml",
"aws-appsync-graphqlschema.yaml",
"aws-appsync-resolver.yaml",
"aws-appsync-functionconfiguration.yaml",
"aws-lambda-function.yaml",
"aws-apigateway-restapi.yaml",
"aws-elasticbeanstalk-applicationversion.yaml",
"aws-cloudformation-stack.yaml",
"aws-serverless-application.yaml",
"aws-lambda-layerversion.yaml",
"aws-serverless-layerversion.yaml",
"aws-glue-job.yaml",
"aws-serverlessrepo-application.yaml",
"aws-serverless-statemachine.yaml",
"aws-stepfunctions-statemachine.yaml",
]
)
def test_package_with_resolve_s3(self, template_file):
template_path = self.test_data_path.joinpath(template_file)
s3_prefix = "integ_test_prefix"

with tempfile.NamedTemporaryFile(delete=False) as output_template:
command_list = self.get_command_list(
template_file=template_path,
s3_prefix=s3_prefix,
output_template_file=output_template.name,
force_upload=True,
resolve_s3=True,
)

process = Popen(command_list, stdout=PIPE)
try:
stdout, _ = process.communicate(timeout=TIMEOUT)
except TimeoutExpired:
process.kill()
raise
process_stdout = stdout.strip()

self.assertIn(
bytes(
"Successfully packaged artifacts and wrote output template to file {output_template_file}".format(
output_template_file=str(output_template.name)
),
encoding="utf-8",
),
process_stdout,
)
Loading

0 comments on commit cc2313e

Please sign in to comment.