diff --git a/docs/cloudformation_compatibility.rst b/docs/cloudformation_compatibility.rst index 96ec4fdb0..187feb531 100644 --- a/docs/cloudformation_compatibility.rst +++ b/docs/cloudformation_compatibility.rst @@ -103,6 +103,7 @@ DynamoDB Stream All StartingPosition All BatchSize All +SSESpecification All ======================== ================================== ======================== Api diff --git a/docs/globals.rst b/docs/globals.rst index eec9dfa59..563f5768c 100644 --- a/docs/globals.rst +++ b/docs/globals.rst @@ -80,6 +80,9 @@ presently. BinaryMediaTypes: Cors: + SimpleTable: + SSESpecification + Implicit APIs ~~~~~~~~~~~~~ diff --git a/samtranslator/model/dynamodb.py b/samtranslator/model/dynamodb.py index 0564180c9..8a9fa5416 100644 --- a/samtranslator/model/dynamodb.py +++ b/samtranslator/model/dynamodb.py @@ -13,8 +13,9 @@ class DynamoDBTable(Resource): 'ProvisionedThroughput': PropertyType(True, dict_of(is_str(), one_of(is_type(int), is_type(dict)))), 'StreamSpecification': PropertyType(False, is_type(dict)), 'TableName': PropertyType(False, one_of(is_str(), is_type(dict))), - 'Tags': PropertyType(False, list_of(is_type(dict))) - } + 'Tags': PropertyType(False, list_of(is_type(dict))), + 'SSESpecification': PropertyType(False, is_type(dict)) + } runtime_attrs = { "name": lambda self: ref(self.logical_id), diff --git a/samtranslator/model/sam_resources.py b/samtranslator/model/sam_resources.py index 03e0bcff4..fa26dd441 100644 --- a/samtranslator/model/sam_resources.py +++ b/samtranslator/model/sam_resources.py @@ -1,6 +1,4 @@ """ SAM macro definitions """ -from copy import deepcopy - from six import string_types from tags.resource_tagging import get_tag_list import samtranslator.model.eventsources @@ -56,7 +54,8 @@ class SamFunction(SamResourceMacro): 'AutoPublishAlias': PropertyType(False, one_of(is_str())) } event_resolver = ResourceTypeResolver(samtranslator.model.eventsources, samtranslator.model.eventsources.pull, - samtranslator.model.eventsources.push, samtranslator.model.eventsources.cloudwatchlogs) + samtranslator.model.eventsources.push, + samtranslator.model.eventsources.cloudwatchlogs) # DeadLetterQueue dead_letter_queue_policy_actions = {'SQS': 'sqs:SendMessage', 'SNS': 'sns:Publish'} @@ -67,7 +66,6 @@ class SamFunction(SamResourceMacro): "Version": LambdaVersion.resource_type, } - def resources_to_link(self, resources): try: return { @@ -148,7 +146,6 @@ def _get_resolved_alias_name(self, property_name, original_alias_value, intrinsi return resolved_alias_name - def _construct_lambda_function(self): """Constructs and returns the Lambda function. @@ -216,7 +213,9 @@ def _construct_role(self, managed_policy_map): policy_documents = [] if self.DeadLetterQueue: - policy_documents.append(IAMRolePolicies.dead_letter_queue_policy(self.dead_letter_queue_policy_actions[self.DeadLetterQueue['Type']], self.DeadLetterQueue['TargetArn'])) + policy_documents.append(IAMRolePolicies.dead_letter_queue_policy( + self.dead_letter_queue_policy_actions[self.DeadLetterQueue['Type']], + self.DeadLetterQueue['TargetArn'])) for index, policy_entry in enumerate(function_policies.get()): @@ -247,8 +246,9 @@ def _construct_role(self, managed_policy_map): managed_policy_arns.append(policy_arn) else: # Policy Templates are not supported here in the "core" - raise InvalidResourceException(self.logical_id, - "Policy at index {} in the 'Policies' property is not valid".format(index)) + raise InvalidResourceException( + self.logical_id, + "Policy at index {} in the 'Policies' property is not valid".format(index)) execution_role.ManagedPolicyArns = list(managed_policy_arns) execution_role.Policies = policy_documents or None @@ -420,7 +420,8 @@ def _construct_alias(self, name, function, version): def _validate_deployment_preference_and_add_update_policy(self, deployment_preference_collection, lambda_alias, intrinsics_resolver): if 'Enabled' in self.DeploymentPreference: - self.DeploymentPreference['Enabled'] = intrinsics_resolver.resolve_parameter_refs(self.DeploymentPreference['Enabled']) + 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") @@ -431,8 +432,9 @@ def _validate_deployment_preference_and_add_update_policy(self, deployment_prefe if deployment_preference_collection.get(self.logical_id).enabled: if self.AutoPublishAlias is None: - raise InvalidResourceException(self.logical_id, - "'DeploymentPreference' requires AutoPublishAlias property to be specified") + raise InvalidResourceException( + self.logical_id, + "'DeploymentPreference' requires AutoPublishAlias property to be specified") if lambda_alias is None: raise ValueError('lambda_alias expected for updating it with the appropriate update policy') @@ -510,7 +512,8 @@ class SamSimpleTable(SamResourceMacro): 'PrimaryKey': PropertyType(False, dict_of(is_str(), is_str())), 'ProvisionedThroughput': PropertyType(False, dict_of(is_str(), one_of(is_type(int), is_type(dict)))), 'TableName': PropertyType(False, one_of(is_str(), is_type(dict))), - 'Tags': PropertyType(False, is_type(dict)) + 'Tags': PropertyType(False, is_type(dict)), + 'SSESpecification': PropertyType(False, is_type(dict)) } attribute_type_conversions = { 'String': 'S', @@ -523,7 +526,6 @@ def to_cloudformation(self, **kwargs): return [dynamodb_resources] - def _construct_dynamodb_table(self): dynamodb_table = DynamoDBTable(self.logical_id, depends_on=self.depends_on) @@ -549,6 +551,9 @@ def _construct_dynamodb_table(self): dynamodb_table.ProvisionedThroughput = provisioned_throughput + if self.SSESpecification: + dynamodb_table.SSESpecification = self.SSESpecification + if self.TableName: dynamodb_table.TableName = self.TableName diff --git a/samtranslator/plugins/globals/globals.py b/samtranslator/plugins/globals/globals.py index c7c150f4f..b50e697be 100644 --- a/samtranslator/plugins/globals/globals.py +++ b/samtranslator/plugins/globals/globals.py @@ -1,6 +1,7 @@ from samtranslator.public.sdk.resource import SamResourceType from samtranslator.public.intrinsics import is_intrinsics + class Globals(object): """ Class to parse and process Globals section in SAM template. If a property is specified at Global section for @@ -44,6 +45,10 @@ class Globals(object): "MethodSettings", "BinaryMediaTypes", "Cors" + ], + + SamResourceType.SimpleTable.value: [ + "SSESpecification" ] } @@ -125,7 +130,6 @@ def _parse(self, globals_dict): "Must be one of the following values - {supported}" .format(key=key, section=section_name, supported=supported)) - # Store all Global properties in a map with key being the AWS::Serverless::* resource type globals[resource_type] = GlobalProperties(properties) @@ -135,8 +139,6 @@ def _make_resource_type(self, key): return self._RESOURCE_PREFIX + key - - class GlobalProperties(object): """ Object holding the global properties of given type. It also contains methods to perform a merge between @@ -298,7 +300,6 @@ def _do_merge(self, global_value, local_value): raise TypeError( "Unsupported type of objects. GlobalType={}, LocalType={}".format(token_global, token_local)) - def _merge_lists(self, global_list, local_list): """ Merges the global list with the local list. List merging is simply a concatenation = global + local @@ -369,7 +370,6 @@ def _token_of(self, input): else: return self.TOKEN.PRIMITIVE - class TOKEN: """ Enum of tokens used in the merging @@ -385,7 +385,7 @@ class InvalidGlobalsSectionException(Exception): Attributes: message -- explanation of the error """ - def __init__(self, logical_id, message): + def __init__(self, logical_id, message): self._logical_id = logical_id self._message = message diff --git a/samtranslator/plugins/globals/globals_plugin.py b/samtranslator/plugins/globals/globals_plugin.py index 6f2012145..086bfb81b 100644 --- a/samtranslator/plugins/globals/globals_plugin.py +++ b/samtranslator/plugins/globals/globals_plugin.py @@ -5,6 +5,7 @@ from samtranslator.plugins.globals.globals import Globals, InvalidGlobalsSectionException + class GlobalsPlugin(BasePlugin): """ Plugin to process Globals section of a SAM template before the template is translated to CloudFormation. diff --git a/samtranslator/validator/sam_schema/schema.json b/samtranslator/validator/sam_schema/schema.json index b4afcd499..cdcb08d4b 100644 --- a/samtranslator/validator/sam_schema/schema.json +++ b/samtranslator/validator/sam_schema/schema.json @@ -641,6 +641,9 @@ }, "ProvisionedThroughput": { "$ref": "#/definitions/AWS::Serverless::SimpleTable.ProvisionedThroughput" + }, + "SSESpecification": { + "$ref": "#/definitions/AWS::Serverless::SimpleTable.SSESpecification" } }, "type": "object" @@ -687,6 +690,18 @@ ], "type": "object" }, + "AWS::Serverless::SimpleTable.SSESpecification": { + "additionalProperties": false, + "properties": { + "SSEEnabled": { + "type": "boolean" + } + }, + "required": [ + "SSEEnabled" + ], + "type": "object" + }, "CloudFormationResource": { "additionalProperties": true, "properties": { diff --git a/tests/translator/input/globals_for_simpletable.yaml b/tests/translator/input/globals_for_simpletable.yaml new file mode 100644 index 000000000..6a03a75ed --- /dev/null +++ b/tests/translator/input/globals_for_simpletable.yaml @@ -0,0 +1,8 @@ +Globals: + SimpleTable: + SSESpecification: + SSEEnabled: true + +Resources: + MinimalTable: + Type: AWS::Serverless::SimpleTable \ No newline at end of file diff --git a/tests/translator/input/simple_table_ref_parameter_intrinsic.yaml b/tests/translator/input/simple_table_ref_parameter_intrinsic.yaml index dc36a42f3..f76765d2e 100644 --- a/tests/translator/input/simple_table_ref_parameter_intrinsic.yaml +++ b/tests/translator/input/simple_table_ref_parameter_intrinsic.yaml @@ -6,4 +6,7 @@ Resources: ReadCapacityUnits: Ref: ReadCapacity WriteCapacityUnits: - Ref: WriteCapacity \ No newline at end of file + Ref: WriteCapacity + SSESpecification: + SSEEnabled: + Ref: EnableSSE \ No newline at end of file diff --git a/tests/translator/input/simpletable_with_sse.yaml b/tests/translator/input/simpletable_with_sse.yaml new file mode 100644 index 000000000..b9c6560e8 --- /dev/null +++ b/tests/translator/input/simpletable_with_sse.yaml @@ -0,0 +1,6 @@ +Resources: + TableWithSSE: + Type: 'AWS::Serverless::SimpleTable' + Properties: + SSESpecification: + SSEEnabled: true \ No newline at end of file diff --git a/tests/translator/output/aws-cn/globals_for_simpletable.json b/tests/translator/output/aws-cn/globals_for_simpletable.json new file mode 100644 index 000000000..43392496b --- /dev/null +++ b/tests/translator/output/aws-cn/globals_for_simpletable.json @@ -0,0 +1,28 @@ +{ + "Resources": { + "MinimalTable": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "ProvisionedThroughput": { + "WriteCapacityUnits": 5, + "ReadCapacityUnits": 5 + }, + "SSESpecification": { + "SSEEnabled": true + }, + "AttributeDefinitions": [ + { + "AttributeName": "id", + "AttributeType": "S" + } + ], + "KeySchema": [ + { + "KeyType": "HASH", + "AttributeName": "id" + } + ] + } + } + } + } \ No newline at end of file diff --git a/tests/translator/output/aws-cn/simple_table_ref_parameter_intrinsic.json b/tests/translator/output/aws-cn/simple_table_ref_parameter_intrinsic.json index b097373e3..d158adc9f 100644 --- a/tests/translator/output/aws-cn/simple_table_ref_parameter_intrinsic.json +++ b/tests/translator/output/aws-cn/simple_table_ref_parameter_intrinsic.json @@ -17,6 +17,11 @@ "AttributeType": "S" } ], + "SSESpecification": { + "SSEEnabled": { + "Ref": "EnableSSE" + } + }, "KeySchema": [ { "KeyType": "HASH", diff --git a/tests/translator/output/aws-cn/simpletable_with_sse.json b/tests/translator/output/aws-cn/simpletable_with_sse.json new file mode 100644 index 000000000..aea4473e5 --- /dev/null +++ b/tests/translator/output/aws-cn/simpletable_with_sse.json @@ -0,0 +1,28 @@ +{ + "Resources": { + "TableWithSSE": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "ProvisionedThroughput": { + "WriteCapacityUnits": 5, + "ReadCapacityUnits": 5 + }, + "SSESpecification": { + "SSEEnabled": true + }, + "AttributeDefinitions": [ + { + "AttributeName": "id", + "AttributeType": "S" + } + ], + "KeySchema": [ + { + "KeyType": "HASH", + "AttributeName": "id" + } + ] + } + } + } + } \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/globals_for_simpletable.json b/tests/translator/output/aws-us-gov/globals_for_simpletable.json new file mode 100644 index 000000000..43392496b --- /dev/null +++ b/tests/translator/output/aws-us-gov/globals_for_simpletable.json @@ -0,0 +1,28 @@ +{ + "Resources": { + "MinimalTable": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "ProvisionedThroughput": { + "WriteCapacityUnits": 5, + "ReadCapacityUnits": 5 + }, + "SSESpecification": { + "SSEEnabled": true + }, + "AttributeDefinitions": [ + { + "AttributeName": "id", + "AttributeType": "S" + } + ], + "KeySchema": [ + { + "KeyType": "HASH", + "AttributeName": "id" + } + ] + } + } + } + } \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/simple_table_ref_parameter_intrinsic.json b/tests/translator/output/aws-us-gov/simple_table_ref_parameter_intrinsic.json index b097373e3..667ce5351 100644 --- a/tests/translator/output/aws-us-gov/simple_table_ref_parameter_intrinsic.json +++ b/tests/translator/output/aws-us-gov/simple_table_ref_parameter_intrinsic.json @@ -11,6 +11,11 @@ "Ref": "ReadCapacity" } }, + "SSESpecification": { + "SSEEnabled": { + "Ref": "EnableSSE" + } + }, "AttributeDefinitions": [ { "AttributeName": "id", diff --git a/tests/translator/output/aws-us-gov/simpletable_with_sse.json b/tests/translator/output/aws-us-gov/simpletable_with_sse.json new file mode 100644 index 000000000..aea4473e5 --- /dev/null +++ b/tests/translator/output/aws-us-gov/simpletable_with_sse.json @@ -0,0 +1,28 @@ +{ + "Resources": { + "TableWithSSE": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "ProvisionedThroughput": { + "WriteCapacityUnits": 5, + "ReadCapacityUnits": 5 + }, + "SSESpecification": { + "SSEEnabled": true + }, + "AttributeDefinitions": [ + { + "AttributeName": "id", + "AttributeType": "S" + } + ], + "KeySchema": [ + { + "KeyType": "HASH", + "AttributeName": "id" + } + ] + } + } + } + } \ No newline at end of file diff --git a/tests/translator/output/error_globals_unsupported_type.json b/tests/translator/output/error_globals_unsupported_type.json index e47e8949d..d49924ddc 100644 --- a/tests/translator/output/error_globals_unsupported_type.json +++ b/tests/translator/output/error_globals_unsupported_type.json @@ -1,8 +1,8 @@ { "errors": [ { - "errorMessage": "'Globals' section is invalid. 'NewType' is not supported. Must be one of the following values - ['Function', 'Api']" + "errorMessage": "'Globals' section is invalid. 'NewType' is not supported. Must be one of the following values - ['Function', 'SimpleTable', Api']" } ], - "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. 'Globals' section is invalid. 'NewType' is not supported. Must be one of the following values - ['Function', 'Api']" + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. 'Globals' section is invalid. 'NewType' is not supported. Must be one of the following values - ['Function', 'SimpleTable', 'Api']" } \ No newline at end of file diff --git a/tests/translator/output/globals_for_simpletable.json b/tests/translator/output/globals_for_simpletable.json new file mode 100644 index 000000000..43392496b --- /dev/null +++ b/tests/translator/output/globals_for_simpletable.json @@ -0,0 +1,28 @@ +{ + "Resources": { + "MinimalTable": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "ProvisionedThroughput": { + "WriteCapacityUnits": 5, + "ReadCapacityUnits": 5 + }, + "SSESpecification": { + "SSEEnabled": true + }, + "AttributeDefinitions": [ + { + "AttributeName": "id", + "AttributeType": "S" + } + ], + "KeySchema": [ + { + "KeyType": "HASH", + "AttributeName": "id" + } + ] + } + } + } + } \ No newline at end of file diff --git a/tests/translator/output/simple_table_ref_parameter_intrinsic.json b/tests/translator/output/simple_table_ref_parameter_intrinsic.json index b097373e3..667ce5351 100644 --- a/tests/translator/output/simple_table_ref_parameter_intrinsic.json +++ b/tests/translator/output/simple_table_ref_parameter_intrinsic.json @@ -11,6 +11,11 @@ "Ref": "ReadCapacity" } }, + "SSESpecification": { + "SSEEnabled": { + "Ref": "EnableSSE" + } + }, "AttributeDefinitions": [ { "AttributeName": "id", diff --git a/tests/translator/output/simpletable_with_sse.json b/tests/translator/output/simpletable_with_sse.json new file mode 100644 index 000000000..aea4473e5 --- /dev/null +++ b/tests/translator/output/simpletable_with_sse.json @@ -0,0 +1,28 @@ +{ + "Resources": { + "TableWithSSE": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "ProvisionedThroughput": { + "WriteCapacityUnits": 5, + "ReadCapacityUnits": 5 + }, + "SSESpecification": { + "SSEEnabled": true + }, + "AttributeDefinitions": [ + { + "AttributeName": "id", + "AttributeType": "S" + } + ], + "KeySchema": [ + { + "KeyType": "HASH", + "AttributeName": "id" + } + ] + } + } + } + } \ No newline at end of file diff --git a/tests/translator/test_translator.py b/tests/translator/test_translator.py index 9a5b368aa..664dba5be 100644 --- a/tests/translator/test_translator.py +++ b/tests/translator/test_translator.py @@ -47,6 +47,7 @@ class TestTranslatorEndToEnd(TestCase): 'cloudwatchlog', 'streams', 'simpletable', + 'simpletable_with_sse', 'implicit_api', 'explicit_api', 'api_endpoint_configuration', @@ -91,6 +92,7 @@ class TestTranslatorEndToEnd(TestCase): 'function_with_policy_templates', 'globals_for_function', 'globals_for_api', + 'globals_for_simpletable', 'all_policy_templates', 'simple_table_ref_parameter_intrinsic', 'simple_table_with_table_name', diff --git a/tests/translator/validator/test_validator.py b/tests/translator/validator/test_validator.py index ce4a98e8b..a7dd8a0c0 100644 --- a/tests/translator/validator/test_validator.py +++ b/tests/translator/validator/test_validator.py @@ -13,6 +13,7 @@ 'cloudwatchlog', 'streams', 'simpletable', + 'simpletable_with_sse', 'implicit_api', 'explicit_api', 'api_endpoint_configuration', @@ -57,6 +58,7 @@ 'function_with_policy_templates', 'globals_for_function', 'globals_for_api', + 'globals_for_simpletable', 'all_policy_templates', 'simple_table_ref_parameter_intrinsic', 'simple_table_with_table_name', diff --git a/versions/2016-10-31.md b/versions/2016-10-31.md index 98225c0e6..4c742eae6 100644 --- a/versions/2016-10-31.md +++ b/versions/2016-10-31.md @@ -81,6 +81,10 @@ Globals: Api: EndpointConfiguration: REGIONAL Cors: "'www.example.com'" + + SimpleTable: + SSESpecification: + SSEEnabled: true ``` @@ -244,6 +248,7 @@ PrimaryKey | [Primary Key Object](#primary-key-object) | Attribute name and type ProvisionedThroughput | [Provisioned Throughput Object](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html) | Read and write throughput provisioning information. Defaults to 5 read and 5 write capacity units per second. Tags | Map of `string` to `string` | A map (string to string) that specifies the tags to be added to this table. Keys and values are limited to alphanumeric characters. TableName | `string` | Name for the DynamoDB Table +SSESpecification | [DynamoDB SSESpecification](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html) | Specifies the settings to enable server-side encryption. ##### Return values @@ -265,6 +270,8 @@ Properties: Tags: Department: Engineering AppType: Serverless + SSESpecification: + SSEEnabled: true ``` ### Event source types