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
4 changes: 2 additions & 2 deletions docs/safe_lambda_deployments.rst
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ resource:
Runtime: nodejs8.10
FunctionName: 'CodeDeployHook_preTrafficHook'
DeploymentPreference:
Enabled: false
Enabled: False
Role: ""
Environment:
Variables:
Expand Down Expand Up @@ -273,7 +273,7 @@ Hooks are extremely powerful because:

FunctionName: 'CodeDeployHook_preTrafficHook'
DeploymentPreference:
Enabled: false
Enabled: False
Policies:
- Version: "2012-10-17"
Statement:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Resources:
Runtime: nodejs8.10
FunctionName: 'CodeDeployHook_preTrafficHook'
DeploymentPreference:
Enabled: false
Enabled: False
Environment:
Variables:
CurrentVersion: !Ref safeTest.Version
9 changes: 5 additions & 4 deletions samtranslator/model/sam_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,10 +421,11 @@ def _construct_alias(self, name, function, version):
def _validate_deployment_preference_and_add_update_policy(self, deployment_preference_collection, lambda_alias,
intrinsics_resolver, mappings_resolver):
if 'Enabled' in self.DeploymentPreference:
self.DeploymentPreference['Enabled'] = intrinsics_resolver.resolve_parameter_refs(
self.DeploymentPreference['Enabled'])
if isinstance(self.DeploymentPreference['Enabled'], dict):
raise InvalidResourceException(self.logical_id, "'Enabled' must be a boolean value")
# resolve intrinsics and mappings for Type
enabled = self.DeploymentPreference['Enabled']
enabled = intrinsics_resolver.resolve_parameter_refs(enabled)
enabled = mappings_resolver.resolve_parameter_refs(enabled)
self.DeploymentPreference['Enabled'] = enabled

if 'Type' in self.DeploymentPreference:
# resolve intrinsics and mappings for Type
Expand Down
11 changes: 11 additions & 0 deletions samtranslator/sdk/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,14 @@ def add_pseudo_parameter_values(self):
"""
if 'AWS::Region' not in self.parameter_values:
self.parameter_values['AWS::Region'] = boto3.session.Session().region_name

if 'AWS::Partition' not in self.parameter_values:
region = boto3.session.Session().region_name

# neither boto nor botocore has any way of returning the partition value yet
if region.startswith('cn-'):
self.parameter_values['AWS::Partition'] = 'aws-cn'
elif region.startswith('us-gov-'):
self.parameter_values['AWS::Partition'] = 'aws-us-gov'
else:
self.parameter_values['AWS::Partition'] = 'aws'
37 changes: 35 additions & 2 deletions tests/sdk/test_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ def test_add_pseudo_parameter_values_aws_region(self):

expected = {
"Param1": "value1",
"AWS::Region": "ap-southeast-1"
"AWS::Region": "ap-southeast-1",
"AWS::Partition": "aws"
}

sam_parameter_values = SamParameterValues(parameter_values)
Expand All @@ -128,7 +129,39 @@ def test_add_pseudo_parameter_values_aws_region_not_override(self):
}

expected = {
"AWS::Region": "value1"
"AWS::Region": "value1",
"AWS::Partition": "aws"
}

sam_parameter_values = SamParameterValues(parameter_values)
sam_parameter_values.add_pseudo_parameter_values()
self.assertEqual(expected, sam_parameter_values.parameter_values)

@patch('boto3.session.Session.region_name', 'us-gov-west-1')
def test_add_pseudo_parameter_values_aws_partition(self):
parameter_values = {
"Param1": "value1"
}

expected = {
"Param1": "value1",
"AWS::Region": "us-gov-west-1",
"AWS::Partition": "aws-us-gov"
}

sam_parameter_values = SamParameterValues(parameter_values)
sam_parameter_values.add_pseudo_parameter_values()
self.assertEqual(expected, sam_parameter_values.parameter_values)

@patch('boto3.session.Session.region_name', 'us-gov-west-1')
def test_add_pseudo_parameter_values_aws_partition_not_override(self):
parameter_values = {
"AWS::Partition": "aws"
}

expected = {
"AWS::Partition": "aws",
"AWS::Region": "us-gov-west-1"
}

sam_parameter_values = SamParameterValues(parameter_values)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Resources:
Runtime: python2.7
AutoPublishAlias: live
DeploymentPreference:
Enabled: true
Enabled: True
Type: Linear10PercentEvery1Minute
Hooks:
PreTraffic: !Ref MySanityTestFunction
Expand All @@ -22,7 +22,7 @@ Resources:
Runtime: python2.7
CodeUri: s3://my-bucket/mySanityTestFunction.zip
DeploymentPreference:
Enabled: false
Enabled: False

MyValidationTestFunction:
Type: 'AWS::Serverless::Function'
Expand All @@ -31,7 +31,7 @@ Resources:
Runtime: python2.7
CodeUri: s3://my-bucket/myValidationTestFunction.zip
DeploymentPreference:
Enabled: false
Enabled: False

MyCloudWatchAlarm:
Type: AWS::CloudWatch::Alarm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Resources:
Runtime: python2.7
CodeUri: s3://my-bucket/mySanityTestFunction.zip
DeploymentPreference:
Enabled: false
Enabled: False

MyValidationTestFunction:
Type: 'AWS::Serverless::Function'
Expand All @@ -48,7 +48,7 @@ Resources:
Runtime: python2.7
CodeUri: s3://my-bucket/myValidationTestFunction.zip
DeploymentPreference:
Enabled: false
Enabled: False

MyCloudWatchAlarm:
Type: AWS::CloudWatch::Alarm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ Resources:
Runtime: python2.7
AutoPublishAlias: live
DeploymentPreference:
Enabled: false
Type: AllAtOnce
Enabled: False
Type: AllAtOnce
46 changes: 42 additions & 4 deletions tests/translator/test_function_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ def test_sam_function_with_disabled_deployment_preference_does_not_add_update_po
kwargs["managed_policy_map"] = {"a": "b"}
kwargs["event_resources"] = []
kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock
kwargs["mappings_resolver"] = self.mappings_resolver_mock
preference_collection = self._make_deployment_preference_collection()
preference_collection.get.return_value = DeploymentPreference.from_dict(sam_func.logical_id,
deploy_preference_dict)
Expand Down Expand Up @@ -227,6 +228,8 @@ def test_sam_function_without_alias_allows_disabled_deployment_preference(self):
kwargs["managed_policy_map"] = {"a": "b"}
kwargs["event_resources"] = []
kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock
kwargs["mappings_resolver"] = self.mappings_resolver_mock

preference_collection = self._make_deployment_preference_collection()
preference_collection.get.return_value = DeploymentPreference.from_dict(sam_func.logical_id,
deploy_preference_dict)
Expand Down Expand Up @@ -280,8 +283,9 @@ def test_sam_function_with_deployment_preference_intrinsic_ref_enabled_boolean_p
self.assertTrue("UpdatePolicy" in list(aliases[0].values())[0])
self.assertEqual(list(aliases[0].values())[0]["UpdatePolicy"], self.update_policy().to_dict())

@patch('boto3.session.Session.region_name', 'ap-southeast-1')
@patch.object(SamFunction, "_get_resolved_alias_name")
def test_sam_function_with_deployment_preference_instrinsic_ref_enabled_dict_parameter(self, get_resolved_alias_name_mock):
def test_sam_function_with_deployment_preference_intrinsic_ref_enabled_dict_parameter(self, get_resolved_alias_name_mock):
alias_name = "AliasName"
enabled = {"Ref": "MyEnabledFlag"}
deploy_preference_dict = {"Type": "LINEAR", "Enabled": enabled}
Expand All @@ -302,13 +306,47 @@ def test_sam_function_with_deployment_preference_instrinsic_ref_enabled_dict_par
kwargs["managed_policy_map"] = {"a": "b"}
kwargs["event_resources"] = []
kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock
kwargs["mappings_resolver"] = self.mappings_resolver_mock
deployment_preference_collection = self._make_deployment_preference_collection()
kwargs['deployment_preference_collection'] = deployment_preference_collection
self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = {"key": "value"}
self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = {"MyEnabledFlag": True}
get_resolved_alias_name_mock.return_value = alias_name

with self.assertRaises(InvalidResourceException):
sam_func.to_cloudformation(**kwargs)
sam_func.to_cloudformation(**kwargs)
self.assertTrue(sam_func.DeploymentPreference['Enabled'])

@patch('boto3.session.Session.region_name', 'ap-southeast-1')
@patch.object(SamFunction, "_get_resolved_alias_name")
def test_sam_function_with_deployment_preference_intrinsic_findinmap_enabled_dict_parameter(self, get_resolved_alias_name_mock):
alias_name = "AliasName"
enabled = {"Fn::FindInMap": ["FooMap", "FooKey", "Enabled"]}
deploy_preference_dict = {"Type": "LINEAR", "Enabled": enabled}
func = {
"Type": "AWS::Serverless::Function",
"Properties": {
"CodeUri": self.code_uri,
"Runtime": "nodejs4.3",
"Handler": "index.handler",
"AutoPublishAlias": alias_name,
"DeploymentPreference": deploy_preference_dict
}
}

sam_func = SamFunction.from_dict(logical_id="foo", resource_dict=func)

kwargs = dict()
kwargs["managed_policy_map"] = {"a": "b"}
kwargs["event_resources"] = []
kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock
kwargs["mappings_resolver"] = self.mappings_resolver_mock
deployment_preference_collection = self._make_deployment_preference_collection()
kwargs['deployment_preference_collection'] = deployment_preference_collection
self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = {"MyEnabledFlag": True}
self.mappings_resolver_mock.resolve_parameter_refs.return_value = True
get_resolved_alias_name_mock.return_value = alias_name

sam_func.to_cloudformation(**kwargs)
self.assertTrue(sam_func.DeploymentPreference['Enabled'])

@patch("samtranslator.translator.logical_id_generator.LogicalIdGenerator")
def test_version_creation(self, LogicalIdGeneratorMock):
Expand Down
6 changes: 5 additions & 1 deletion tests/translator/test_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,7 @@ def _do_transform(self, document, parameter_values=get_template_parameter_values

class TestTemplateValidation(TestCase):

@patch('boto3.session.Session.region_name', 'ap-southeast-1')
@patch('botocore.client.ClientEndpointBridge._check_default_region', mock_get_region)
def test_throws_when_resource_not_found(self):
template = {
Expand All @@ -790,6 +791,7 @@ def test_throws_when_resource_not_found(self):
translator = Translator({}, sam_parser)
translator.translate(template, {})

@patch('boto3.session.Session.region_name', 'ap-southeast-1')
@patch('botocore.client.ClientEndpointBridge._check_default_region', mock_get_region)
def test_throws_when_resource_is_empty(self):
template = {
Expand All @@ -802,6 +804,7 @@ def test_throws_when_resource_is_empty(self):
translator.translate(template, {})


@patch('boto3.session.Session.region_name', 'ap-southeast-1')
@patch('botocore.client.ClientEndpointBridge._check_default_region', mock_get_region)
def test_throws_when_resource_is_not_dict(self):
template = {
Expand All @@ -814,6 +817,7 @@ def test_throws_when_resource_is_not_dict(self):
translator.translate(template, {})


@patch('boto3.session.Session.region_name', 'ap-southeast-1')
@patch('botocore.client.ClientEndpointBridge._check_default_region', mock_get_region)
def test_throws_when_resources_not_all_dicts(self):
template = {
Expand Down Expand Up @@ -915,7 +919,7 @@ def test_transform_method_must_inject_plugins_when_creating_resources(self,
resource_from_dict_mock.assert_called_with("MyTable",
manifest["Resources"]["MyTable"],
sam_plugins=sam_plugins_object_mock)
prepare_plugins_mock.assert_called_once_with(initial_plugins, {"AWS::Region": "ap-southeast-1"})
prepare_plugins_mock.assert_called_once_with(initial_plugins, {"AWS::Region": "ap-southeast-1", "AWS::Partition": "aws"})

def get_policy_mock():
mock_policy_loader = MagicMock()
Expand Down
2 changes: 1 addition & 1 deletion versions/2016-10-31.md
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ Specifies the configurations to enable Safe Lambda Deployments. Read the [usage

```yaml
DeploymentPreference:
Enabled: true
Enabled: True # Set to False to disable. Supports all intrinsics.
Type: Linear10PercentEvery10Minutes
Alarms:
# A list of alarms that you want to monitor
Expand Down