Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 36 additions & 13 deletions samcli/commands/deploy/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ def do_cli(
force_upload=force_upload,
s3_prefix=s3_prefix,
kms_key_id=kms_key_id,
parameter_overrides=_parameter_overrides if guided else parameter_overrides,
parameter_overrides=sanitize_parameter_overrides(_parameter_overrides) if guided else parameter_overrides,
capabilities=_capabilities if guided else capabilities,
no_execute_changeset=no_execute_changeset,
role_arn=role_arn,
Expand Down Expand Up @@ -305,13 +305,21 @@ def guided_deploy(
region = click.prompt(f"\t{start_bold}AWS Region{end_bold}", default=default_region, type=click.STRING)
if parameter_override_keys:
for parameter_key, parameter_properties in parameter_override_keys.items():
input_parameter_overrides[parameter_key] = click.prompt(
f"\t{start_bold}Parameter {parameter_key}{end_bold}",
default=parameter_overrides.get(
parameter_key, parameter_properties.get("Default", "No default specified")
),
type=click.STRING,
)
no_echo = parameter_properties.get("NoEcho", False)
if no_echo:
parameter = click.prompt(
f"\t{start_bold}Parameter {parameter_key}{end_bold}", type=click.STRING, hide_input=True
)
input_parameter_overrides[parameter_key] = {"Value": parameter, "Hidden": True}
else:
parameter = click.prompt(
f"\t{start_bold}Parameter {parameter_key}{end_bold}",
default=parameter_overrides.get(
parameter_key, parameter_properties.get("Default", "No default specified")
),
type=click.STRING,
)
input_parameter_overrides[parameter_key] = {"Value": parameter, "Hidden": False}

click.secho("\t#Shows you resources changes to be deployed and require a 'Y' to initiate deploy")
confirm_changeset = click.confirm(
Expand All @@ -332,7 +340,7 @@ def guided_deploy(
click.echo(color.yellow("\n\tS3 bucket for deployments\n\t========================="))
s3_bucket = manage_stack(profile=profile, region=region)
click.echo(f"\tS3 bucket: {s3_bucket}")
click.echo("\tA different default S3 bucket can be set in /.samconfig.toml")
click.echo("\tA different default S3 bucket can be set in samconfig.toml")

return (
stack_name,
Expand All @@ -348,7 +356,11 @@ def guided_deploy(

def print_deploy_args(stack_name, s3_bucket, region, capabilities, parameter_overrides, confirm_changeset):

param_overrides_string = parameter_overrides
_parameters = parameter_overrides.copy()
for key, value in _parameters.items():
if isinstance(value, dict):
_parameters[key] = value.get("Value", value) if not value.get("Hidden") else "*" * len(value.get("Value"))

capabilities_string = json.dumps(capabilities)

click.secho("\n\tDeploying with following values\n\t===============================", fg="yellow")
Expand All @@ -357,7 +369,7 @@ def print_deploy_args(stack_name, s3_bucket, region, capabilities, parameter_ove
click.echo(f"\tConfirm changeset : {confirm_changeset}")
click.echo(f"\tDeployment s3 bucket : {s3_bucket}")
click.echo(f"\tCapabilities : {capabilities_string}")
click.echo(f"\tParameter overrides : {param_overrides_string}")
click.echo(f"\tParameter overrides : {_parameters}")

click.secho("\nInitiating deployment\n=====================", fg="yellow")

Expand Down Expand Up @@ -394,8 +406,15 @@ def save_config(template_file, parameter_overrides, **kwargs):
samconfig.put(cmd_names, section, key, value)

if parameter_overrides:
parameter_overrides_value = " ".join([f"{key}={value}" for key, value in parameter_overrides.items()])
samconfig.put(cmd_names, section, "parameter_overrides", parameter_overrides_value)
_params = []
for key, value in parameter_overrides.items():
if isinstance(value, dict):
if not value.get("Hidden"):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not write to file if the param is hidden

_params.append(f"{key}={value.get('Value')}")
else:
_params.append(f"{key}={value}")
if _params:
samconfig.put(cmd_names, section, "parameter_overrides", " ".join(_params))

samconfig.flush()

Expand All @@ -413,3 +432,7 @@ def get_config_ctx(template_file):
config_dir=samconfig_dir if samconfig_dir else SamConfig.config_dir(template_file_path=template_file)
)
return ctx, samconfig


def sanitize_parameter_overrides(parameter_overrides):
return {key: value.get("Value") if isinstance(value, dict) else value for key, value in parameter_overrides.items()}
2 changes: 1 addition & 1 deletion samcli/lib/bootstrap/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def _create_stack(cloudformation_client):

def _get_stack_template():
gc = GlobalConfig()
info = {"version": __version__, "installationId": gc.installation_id}
info = {"version": __version__, "installationId": gc.installation_id if gc.installation_id else "unknown"}

template = """
AWSTemplateFormatVersion : '2010-09-09'
Expand Down
109 changes: 104 additions & 5 deletions tests/unit/commands/deploy/test_command.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from unittest import TestCase
from unittest.mock import patch, Mock, ANY, MagicMock
from unittest.mock import patch, Mock, ANY, MagicMock, call

from samcli.commands.deploy.command import do_cli
from tests.unit.cli.test_cli_config_file import MockContext


class TestDeployliCommand(TestCase):
Expand Down Expand Up @@ -105,10 +106,13 @@ def test_all_args_guided(
mock_sam_config = MagicMock()
mock_sam_config.exists = MagicMock(return_value=True)
mock_get_config_ctx.return_value = (None, mock_sam_config)
mock_get_template_parameters.return_value = {"Myparameter": {"Type": "String"}}
mock_get_template_parameters.return_value = {
"Myparameter": {"Type": "String"},
"MyNoEchoParameter": {"Type": "String", "NoEcho": True},
}
mock_deploy_context.return_value.__enter__.return_value = context_mock
mock_deploy_click.prompt = MagicMock(
side_effect=["sam-app", "us-east-1", "guidedParameter", ("CAPABILITY_IAM",)]
side_effect=["sam-app", "us-east-1", "guidedParameter", "secure", ("CAPABILITY_IAM",)]
)
mock_deploy_click.confirm = MagicMock(side_effect=[True, False, True])

Expand Down Expand Up @@ -144,7 +148,7 @@ def test_all_args_guided(
force_upload=self.force_upload,
s3_prefix=self.s3_prefix,
kms_key_id=self.kms_key_id,
parameter_overrides={"Myparameter": "guidedParameter"},
parameter_overrides={"Myparameter": "guidedParameter", "MyNoEchoParameter": "secure"},
capabilities=self.capabilities,
no_execute_changeset=self.no_execute_changeset,
role_arn=self.role_arn,
Expand All @@ -165,11 +169,106 @@ def test_all_args_guided(
region="us-east-1",
s3_bucket="managed-s3-bucket",
stack_name="sam-app",
parameter_overrides={"Myparameter": "guidedParameter"},
parameter_overrides={
"Myparameter": {"Value": "guidedParameter", "Hidden": False},
"MyNoEchoParameter": {"Value": "secure", "Hidden": True},
},
)
mock_managed_stack.assert_called_with(profile=self.profile, region="us-east-1")
self.assertEqual(context_mock.run.call_count, 1)

@patch("samcli.commands.package.command.click")
@patch("samcli.commands.package.package_context.PackageContext")
@patch("samcli.commands.deploy.command.click")
@patch("samcli.commands.deploy.deploy_context.DeployContext")
@patch("samcli.commands.deploy.command.manage_stack")
@patch("samcli.commands.deploy.command.get_template_parameters")
@patch("samcli.commands.deploy.command.get_config_ctx")
def test_all_args_guided_no_save_echo_param_to_config(
self,
mock_get_config_ctx,
mock_get_template_parameters,
mock_managed_stack,
mock_deploy_context,
mock_deploy_click,
mock_package_context,
mock_package_click,
):

context_mock = Mock()
mock_sam_config = MagicMock()
mock_sam_config.exists = MagicMock(return_value=True)
mock_get_config_ctx.return_value = (MockContext(info_name="deploy", parent=None), mock_sam_config)
mock_get_template_parameters.return_value = {
"Myparameter": {"Type": "String"},
"MyNoEchoParameter": {"Type": "String", "NoEcho": True},
}
mock_deploy_context.return_value.__enter__.return_value = context_mock
mock_deploy_click.prompt = MagicMock(
side_effect=["sam-app", "us-east-1", "guidedParameter", "secure", ("CAPABILITY_IAM",)]
)
mock_deploy_click.confirm = MagicMock(side_effect=[True, False, True])

mock_managed_stack.return_value = "managed-s3-bucket"

do_cli(
template_file=self.template_file,
stack_name=self.stack_name,
s3_bucket=None,
force_upload=self.force_upload,
s3_prefix=self.s3_prefix,
kms_key_id=self.kms_key_id,
parameter_overrides=self.parameter_overrides,
capabilities=self.capabilities,
no_execute_changeset=self.no_execute_changeset,
role_arn=self.role_arn,
notification_arns=self.notification_arns,
fail_on_empty_changeset=self.fail_on_empty_changset,
tags=self.tags,
region=self.region,
profile=self.profile,
use_json=self.use_json,
metadata=self.metadata,
guided=True,
confirm_changeset=True,
)

mock_deploy_context.assert_called_with(
template_file=ANY,
stack_name="sam-app",
s3_bucket="managed-s3-bucket",
force_upload=self.force_upload,
s3_prefix=self.s3_prefix,
kms_key_id=self.kms_key_id,
parameter_overrides={"Myparameter": "guidedParameter", "MyNoEchoParameter": "secure"},
capabilities=self.capabilities,
no_execute_changeset=self.no_execute_changeset,
role_arn=self.role_arn,
notification_arns=self.notification_arns,
fail_on_empty_changeset=self.fail_on_empty_changset,
tags=self.tags,
region="us-east-1",
profile=self.profile,
confirm_changeset=True,
)

context_mock.run.assert_called_with()
mock_managed_stack.assert_called_with(profile=self.profile, region="us-east-1")
self.assertEqual(context_mock.run.call_count, 1)

self.assertEqual(mock_sam_config.put.call_count, 6)
self.assertEqual(
mock_sam_config.put.call_args_list,
[
call(["deploy"], "parameters", "stack_name", "sam-app"),
call(["deploy"], "parameters", "s3_bucket", "managed-s3-bucket"),
call(["deploy"], "parameters", "region", "us-east-1"),
call(["deploy"], "parameters", "confirm_changeset", True),
call(["deploy"], "parameters", "capabilities", "CAPABILITY_IAM"),
call(["deploy"], "parameters", "parameter_overrides", "Myparameter=guidedParameter"),
],
)

@patch("samcli.commands.package.command.click")
@patch("samcli.commands.package.package_context.PackageContext")
@patch("samcli.commands.deploy.command.click")
Expand Down