diff --git a/samtranslator/__init__.py b/samtranslator/__init__.py index aff1b006f..4e9b170d0 100644 --- a/samtranslator/__init__.py +++ b/samtranslator/__init__.py @@ -1 +1 @@ -__version__ = "1.54.0" +__version__ = "1.55.0" diff --git a/samtranslator/model/lambda_.py b/samtranslator/model/lambda_.py index 4a941620b..763148bfe 100644 --- a/samtranslator/model/lambda_.py +++ b/samtranslator/model/lambda_.py @@ -27,6 +27,7 @@ class LambdaFunction(Resource): "CodeSigningConfigArn": PropertyType(False, is_str()), "ImageConfig": PropertyType(False, is_type(dict)), "Architectures": PropertyType(False, list_of(one_of(is_str(), is_type(dict)))), + "SnapStart": PropertyType(False, is_type(dict)), "EphemeralStorage": PropertyType(False, is_type(dict)), } diff --git a/samtranslator/model/sam_resources.py b/samtranslator/model/sam_resources.py index d3bd06336..f9c7e98b4 100644 --- a/samtranslator/model/sam_resources.py +++ b/samtranslator/model/sam_resources.py @@ -125,6 +125,7 @@ class SamFunction(SamResourceMacro): "ImageConfig": PropertyType(False, is_type(dict)), "CodeSigningConfigArn": PropertyType(False, is_str()), "Architectures": PropertyType(False, list_of(one_of(is_str(), is_type(dict)))), + "SnapStart": PropertyType(False, is_type(dict)), "FunctionUrlConfig": PropertyType(False, is_type(dict)), } @@ -514,6 +515,7 @@ def _construct_lambda_function(self): # type: ignore[no-untyped-def] lambda_function.ImageConfig = self.ImageConfig lambda_function.PackageType = self.PackageType lambda_function.Architectures = self.Architectures + lambda_function.SnapStart = self.SnapStart # type: ignore[attr-defined] lambda_function.EphemeralStorage = self.EphemeralStorage if self.Tracing: @@ -864,6 +866,9 @@ def _construct_version(self, function, intrinsics_resolver, code_sha256=None): logical_dict.update(function.Environment) if function.MemorySize: logical_dict.update({"MemorySize": function.MemorySize}) + # If SnapStart is enabled we want to publish a new version, to have the corresponding snapshot + if function.SnapStart and function.SnapStart.get("ApplyOn", "None") != "None": + logical_dict.update({"SnapStart": function.SnapStart}) logical_id = logical_id_generator.LogicalIdGenerator(prefix, logical_dict, code_sha256).gen() attributes = self.get_passthrough_resource_attributes() # type: ignore[no-untyped-call] diff --git a/samtranslator/plugins/globals/globals.py b/samtranslator/plugins/globals/globals.py index c447a8c39..44d1f1026 100644 --- a/samtranslator/plugins/globals/globals.py +++ b/samtranslator/plugins/globals/globals.py @@ -46,6 +46,7 @@ class Globals(object): "FileSystemConfigs", "CodeSigningConfigArn", "Architectures", + "SnapStart", "EphemeralStorage", "FunctionUrlConfig", ], @@ -86,7 +87,9 @@ class Globals(object): SamResourceType.SimpleTable.value: ["SSESpecification"], } # unreleased_properties *must be* part of supported_properties too - unreleased_properties: Dict[str, List[str]] = {} + unreleased_properties: Dict[str, List[str]] = { + SamResourceType.Function.value: ["SnapStart"], + } def __init__(self, template): # type: ignore[no-untyped-def] """ diff --git a/samtranslator/schema/aws_serverless_function.py b/samtranslator/schema/aws_serverless_function.py index 880fa006b..e7ae1c2cc 100644 --- a/samtranslator/schema/aws_serverless_function.py +++ b/samtranslator/schema/aws_serverless_function.py @@ -440,6 +440,7 @@ class ScheduleV2Event(BaseModel): AssumeRolePolicyDocument = Optional[DictStrAny] Architectures = Optional[PassThrough] EphemeralStorage = Optional[PassThrough] +SnapStart = Optional[PassThrough] # TODO: check the type class Properties(BaseModel): @@ -498,6 +499,7 @@ class Properties(BaseModel): ReservedConcurrentExecutions: Optional[ReservedConcurrentExecutions] = prop("ReservedConcurrentExecutions") Role: Optional[SamIntrinsicable[str]] = prop("Role") Runtime: Optional[Runtime] = prop("Runtime") + SnapStart: Optional[SnapStart] # TODO: add prop and types Tags: Optional[Tags] = prop("Tags") Timeout: Optional[Timeout] = prop("Timeout") Tracing: Optional[Tracing] = prop("Tracing") @@ -529,6 +531,7 @@ class Globals(BaseModel): EventInvokeConfig: Optional[EventInvokeConfig] = prop("EventInvokeConfig") Architectures: Optional[Architectures] = prop("Architectures") EphemeralStorage: Optional[EphemeralStorage] = prop("EphemeralStorage") + SnapStart: Optional[SnapStart] # TODO: add prop class Resource(BaseModel): diff --git a/samtranslator/schema/schema.json b/samtranslator/schema/schema.json index 0c02416da..74dd27f26 100644 --- a/samtranslator/schema/schema.json +++ b/samtranslator/schema/schema.json @@ -529,6 +529,9 @@ "title": "EphemeralStorage", "description": "An object that specifies the disk space, in MB, available to your Lambda function in `/tmp`\\. \nFor more information about this property, see [Lambda execution environment](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html) in the *AWS Lambda Developer Guide*\\. \n*Type*: [EphemeralStorage](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-ephemeralstorage) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`EphemeralStorage`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-ephemeralstorage) property of an `AWS::Lambda::Function` resource\\.", "markdownDescription": "An object that specifies the disk space, in MB, available to your Lambda function in `/tmp`\\. \nFor more information about this property, see [Lambda execution environment](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html) in the *AWS Lambda Developer Guide*\\. \n*Type*: [EphemeralStorage](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-ephemeralstorage) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`EphemeralStorage`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-ephemeralstorage) property of an `AWS::Lambda::Function` resource\\." + }, + "SnapStart": { + "title": "Snapstart" } }, "additionalProperties": false @@ -3972,6 +3975,9 @@ "description": "The identifier of the function's [runtime](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html)\\. This property is only required if the `PackageType` property is set to `Zip`\\. \nIf you specify the `provided` identifier for this property, you can use the `Metadata` resource attribute to instruct AWS SAM to build the custom runtime that this function requires\\. For more information about building custom runtimes, see [Building custom runtimes](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/building-custom-runtimes.html)\\.\n*Type*: String \n*Required*: Conditional \n*AWS CloudFormation compatibility*: This property is passed directly to the [`Runtime`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-runtime) property of an `AWS::Lambda::Function` resource\\.", "markdownDescription": "The identifier of the function's [runtime](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html)\\. This property is only required if the `PackageType` property is set to `Zip`\\. \nIf you specify the `provided` identifier for this property, you can use the `Metadata` resource attribute to instruct AWS SAM to build the custom runtime that this function requires\\. For more information about building custom runtimes, see [Building custom runtimes](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/building-custom-runtimes.html)\\.\n*Type*: String \n*Required*: Conditional \n*AWS CloudFormation compatibility*: This property is passed directly to the [`Runtime`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-runtime) property of an `AWS::Lambda::Function` resource\\." }, + "SnapStart": { + "title": "Snapstart" + }, "Tags": { "title": "Tags", "description": "A map \\(string to string\\) that specifies the tags added to this function\\. For details about valid keys and values for tags, see [Tag Key and Value Requirements](https://docs.aws.amazon.com/lambda/latest/dg/configuration-tags.html#configuration-tags-restrictions) in the *AWS Lambda Developer Guide*\\. \nWhen the stack is created, AWS SAM automatically adds a `lambda:createdBy:SAM` tag to this Lambda function, and to the default roles that are generated for this function\\. \n*Type*: Map \n*Required*: No \n*AWS CloudFormation compatibility*: This property is similar to the [`Tags`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-tags) property of an `AWS::Lambda::Function` resource\\. The `Tags` property in AWS SAM consists of key\\-value pairs \\(whereas in AWS CloudFormation this property consists of a list of `Tag` objects\\)\\. Also, AWS SAM automatically adds a `lambda:createdBy:SAM` tag to this Lambda function, and to the default roles that are generated for this function\\.", diff --git a/tests/translator/input/function_with_snapstart.yaml b/tests/translator/input/function_with_snapstart.yaml new file mode 100644 index 000000000..4b3e08836 --- /dev/null +++ b/tests/translator/input/function_with_snapstart.yaml @@ -0,0 +1,35 @@ +%YAML 1.1 +--- +Parameters: + SnapStartParam: + Type: String + Default: None + +Resources: + SnapStartFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/hello.zip + Handler: hello.handler + Runtime: python3.9 + SnapStart: + ApplyOn: PublishedVersions + + SnapStartParameterFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/hello.zip + Handler: hello.handler + Runtime: python3.9 + SnapStart: + ApplyOn: !Ref SnapStartParam + + SnapStartFunctionWithAlias: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/hello.zip + Handler: hello.handler + Runtime: python3.9 + AutoPublishAlias: live + SnapStart: + ApplyOn: PublishedVersions diff --git a/tests/translator/input/globals_for_function.yaml b/tests/translator/input/globals_for_function.yaml index c5004f870..eb7b1e6de 100644 --- a/tests/translator/input/globals_for_function.yaml +++ b/tests/translator/input/globals_for_function.yaml @@ -24,6 +24,8 @@ Globals: ReservedConcurrentExecutions: 50 Architectures: - x86_64 + SnapStart: + ApplyOn: PublishedVersions EphemeralStorage: Size: 1024 @@ -52,4 +54,6 @@ Resources: PermissionsBoundary: arn:aws:1234:iam:boundary/OverridePermissionsBoundary Layers: - !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:layer:MyLayer2:2 + SnapStart: + ApplyOn: None ReservedConcurrentExecutions: 100 diff --git a/tests/translator/output/aws-cn/function_with_snapstart.json b/tests/translator/output/aws-cn/function_with_snapstart.json new file mode 100644 index 000000000..345a6d373 --- /dev/null +++ b/tests/translator/output/aws-cn/function_with_snapstart.json @@ -0,0 +1,204 @@ +{ + "Parameters": { + "SnapStartParam": { + "Default": "None", + "Type": "String" + } + }, + "Resources": { + "SnapStartFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "SnapStartFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.9", + "SnapStart": { + "ApplyOn": "PublishedVersions" + }, + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "SnapStartFunctionRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SnapStartFunctionWithAlias": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "SnapStartFunctionWithAliasRole", + "Arn" + ] + }, + "Runtime": "python3.9", + "SnapStart": { + "ApplyOn": "PublishedVersions" + }, + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "SnapStartFunctionWithAliasAliaslive": { + "Properties": { + "FunctionName": { + "Ref": "SnapStartFunctionWithAlias" + }, + "FunctionVersion": { + "Fn::GetAtt": [ + "SnapStartFunctionWithAliasVersion0abd29242e", + "Version" + ] + }, + "Name": "live" + }, + "Type": "AWS::Lambda::Alias" + }, + "SnapStartFunctionWithAliasRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SnapStartFunctionWithAliasVersion0abd29242e": { + "DeletionPolicy": "Retain", + "Properties": { + "FunctionName": { + "Ref": "SnapStartFunctionWithAlias" + } + }, + "Type": "AWS::Lambda::Version" + }, + "SnapStartParameterFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "SnapStartParameterFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.9", + "SnapStart": { + "ApplyOn": { + "Ref": "SnapStartParam" + } + }, + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "SnapStartParameterFunctionRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-cn/globals_for_function.json b/tests/translator/output/aws-cn/globals_for_function.json index 0b58482e8..5e3b7c066 100644 --- a/tests/translator/output/aws-cn/globals_for_function.json +++ b/tests/translator/output/aws-cn/globals_for_function.json @@ -37,6 +37,9 @@ ] }, "Runtime": "nodejs12.x", + "SnapStart": { + "ApplyOn": "None" + }, "Tags": [ { "Key": "lambda:createdBy", @@ -165,6 +168,9 @@ ] }, "Runtime": "python2.7", + "SnapStart": { + "ApplyOn": "PublishedVersions" + }, "Tags": [ { "Key": "lambda:createdBy", @@ -197,7 +203,7 @@ }, "FunctionVersion": { "Fn::GetAtt": [ - "MinimalFunctionVersion0a06fc8fb1", + "MinimalFunctionVersione7c6f56e4d", "Version" ] }, @@ -242,7 +248,7 @@ }, "Type": "AWS::IAM::Role" }, - "MinimalFunctionVersion0a06fc8fb1": { + "MinimalFunctionVersione7c6f56e4d": { "DeletionPolicy": "Retain", "Properties": { "FunctionName": { diff --git a/tests/translator/output/aws-us-gov/function_with_snapstart.json b/tests/translator/output/aws-us-gov/function_with_snapstart.json new file mode 100644 index 000000000..bc5e828c9 --- /dev/null +++ b/tests/translator/output/aws-us-gov/function_with_snapstart.json @@ -0,0 +1,204 @@ +{ + "Parameters": { + "SnapStartParam": { + "Default": "None", + "Type": "String" + } + }, + "Resources": { + "SnapStartFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "SnapStartFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.9", + "SnapStart": { + "ApplyOn": "PublishedVersions" + }, + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "SnapStartFunctionRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SnapStartFunctionWithAlias": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "SnapStartFunctionWithAliasRole", + "Arn" + ] + }, + "Runtime": "python3.9", + "SnapStart": { + "ApplyOn": "PublishedVersions" + }, + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "SnapStartFunctionWithAliasAliaslive": { + "Properties": { + "FunctionName": { + "Ref": "SnapStartFunctionWithAlias" + }, + "FunctionVersion": { + "Fn::GetAtt": [ + "SnapStartFunctionWithAliasVersion0abd29242e", + "Version" + ] + }, + "Name": "live" + }, + "Type": "AWS::Lambda::Alias" + }, + "SnapStartFunctionWithAliasRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SnapStartFunctionWithAliasVersion0abd29242e": { + "DeletionPolicy": "Retain", + "Properties": { + "FunctionName": { + "Ref": "SnapStartFunctionWithAlias" + } + }, + "Type": "AWS::Lambda::Version" + }, + "SnapStartParameterFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "SnapStartParameterFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.9", + "SnapStart": { + "ApplyOn": { + "Ref": "SnapStartParam" + } + }, + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "SnapStartParameterFunctionRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-us-gov/globals_for_function.json b/tests/translator/output/aws-us-gov/globals_for_function.json index 851c36740..1f22a2a28 100644 --- a/tests/translator/output/aws-us-gov/globals_for_function.json +++ b/tests/translator/output/aws-us-gov/globals_for_function.json @@ -37,6 +37,9 @@ ] }, "Runtime": "nodejs12.x", + "SnapStart": { + "ApplyOn": "None" + }, "Tags": [ { "Key": "lambda:createdBy", @@ -165,6 +168,9 @@ ] }, "Runtime": "python2.7", + "SnapStart": { + "ApplyOn": "PublishedVersions" + }, "Tags": [ { "Key": "lambda:createdBy", @@ -197,7 +203,7 @@ }, "FunctionVersion": { "Fn::GetAtt": [ - "MinimalFunctionVersion0a06fc8fb1", + "MinimalFunctionVersione7c6f56e4d", "Version" ] }, @@ -242,7 +248,7 @@ }, "Type": "AWS::IAM::Role" }, - "MinimalFunctionVersion0a06fc8fb1": { + "MinimalFunctionVersione7c6f56e4d": { "DeletionPolicy": "Retain", "Properties": { "FunctionName": { diff --git a/tests/translator/output/function_with_snapstart.json b/tests/translator/output/function_with_snapstart.json new file mode 100644 index 000000000..0d8fb81b9 --- /dev/null +++ b/tests/translator/output/function_with_snapstart.json @@ -0,0 +1,204 @@ +{ + "Parameters": { + "SnapStartParam": { + "Default": "None", + "Type": "String" + } + }, + "Resources": { + "SnapStartFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "SnapStartFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.9", + "SnapStart": { + "ApplyOn": "PublishedVersions" + }, + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "SnapStartFunctionRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SnapStartFunctionWithAlias": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "SnapStartFunctionWithAliasRole", + "Arn" + ] + }, + "Runtime": "python3.9", + "SnapStart": { + "ApplyOn": "PublishedVersions" + }, + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "SnapStartFunctionWithAliasAliaslive": { + "Properties": { + "FunctionName": { + "Ref": "SnapStartFunctionWithAlias" + }, + "FunctionVersion": { + "Fn::GetAtt": [ + "SnapStartFunctionWithAliasVersion0abd29242e", + "Version" + ] + }, + "Name": "live" + }, + "Type": "AWS::Lambda::Alias" + }, + "SnapStartFunctionWithAliasRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SnapStartFunctionWithAliasVersion0abd29242e": { + "DeletionPolicy": "Retain", + "Properties": { + "FunctionName": { + "Ref": "SnapStartFunctionWithAlias" + } + }, + "Type": "AWS::Lambda::Version" + }, + "SnapStartParameterFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Role": { + "Fn::GetAtt": [ + "SnapStartParameterFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.9", + "SnapStart": { + "ApplyOn": { + "Ref": "SnapStartParam" + } + }, + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "SnapStartParameterFunctionRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/globals_for_function.json b/tests/translator/output/globals_for_function.json index 6668b0fb4..7dfd8d294 100644 --- a/tests/translator/output/globals_for_function.json +++ b/tests/translator/output/globals_for_function.json @@ -37,6 +37,9 @@ ] }, "Runtime": "nodejs12.x", + "SnapStart": { + "ApplyOn": "None" + }, "Tags": [ { "Key": "lambda:createdBy", @@ -165,6 +168,9 @@ ] }, "Runtime": "python2.7", + "SnapStart": { + "ApplyOn": "PublishedVersions" + }, "Tags": [ { "Key": "lambda:createdBy", @@ -197,7 +203,7 @@ }, "FunctionVersion": { "Fn::GetAtt": [ - "MinimalFunctionVersion0a06fc8fb1", + "MinimalFunctionVersione7c6f56e4d", "Version" ] }, @@ -242,7 +248,7 @@ }, "Type": "AWS::IAM::Role" }, - "MinimalFunctionVersion0a06fc8fb1": { + "MinimalFunctionVersione7c6f56e4d": { "DeletionPolicy": "Retain", "Properties": { "FunctionName": { diff --git a/tests/translator/test_function_resources.py b/tests/translator/test_function_resources.py index bb3c8e5cc..fbfc4ebca 100644 --- a/tests/translator/test_function_resources.py +++ b/tests/translator/test_function_resources.py @@ -714,6 +714,28 @@ def test_version_logical_id_changes_with_intrinsic_functions(self, LogicalIdGene LogicalIdGeneratorMock.assert_called_with(prefix, new_code, None) self.intrinsics_resolver_mock.resolve_parameter_refs.assert_called_with(self.lambda_func.Code) + def test_version_logical_id_changes_with_snapstart(self): + id_val = "LogicalId" + lambda_func = self._make_lambda_function(id_val) + + lambda_func_snapstart = self._make_lambda_function(id_val) + lambda_func_snapstart.SnapStart = {"ApplyOn": "PublishedVersions"} + + lambda_func_snapstart_none = self._make_lambda_function(id_val) + lambda_func_snapstart_none.SnapStart = {"ApplyOn": "None"} + + self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = lambda_func.Code + + version1 = self.sam_func._construct_version(lambda_func, self.intrinsics_resolver_mock) + version_snapstart = self.sam_func._construct_version(lambda_func_snapstart, self.intrinsics_resolver_mock) + version_snapstart_none = self.sam_func._construct_version( + lambda_func_snapstart_none, + self.intrinsics_resolver_mock, + ) + # SnapStart config changes the hash, except when ApplyOn is "None" + self.assertNotEqual(version1.logical_id, version_snapstart.logical_id) + self.assertEqual(version1.logical_id, version_snapstart_none.logical_id) + def test_alias_creation(self): name = "aliasname"