From fa7549f620fc51601811ce8eb1f8c4d6eaee2402 Mon Sep 17 00:00:00 2001 From: Aayush thapa <84202325+aaythapa@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:09:21 +0545 Subject: [PATCH] feat: add property to update lambda version when lambda layer is updated (#3661) --- docs/globals.rst | 5 + .../combination/test_function_with_alias.py | 36 +++++++ integration/config/file_to_s3_map.json | 4 + integration/helpers/file_resources.py | 1 + integration/resources/code/layer2.zip | Bin 0 -> 2175 bytes ...lias_all_properties_and_layer_version.json | 22 ++++ ...lias_all_properties_and_layer_version.yaml | 21 ++++ .../aws_serverless_layerversion.py | 5 + .../internal/schema_source/schema.py | 1 + samtranslator/model/sam_resources.py | 37 ++++++- samtranslator/plugins/globals/globals.py | 1 + samtranslator/schema/schema.json | 18 ++++ schema_source/sam.schema.json | 18 ++++ tests/model/test_sam_resources.py | 5 + ...and_lambda_layer_publishversion_false.yaml | 20 ++++ ..._and_lambda_layer_publishversion_true.yaml | 20 ++++ ...and_lambda_layer_publishversion_false.json | 99 ++++++++++++++++++ ..._and_lambda_layer_publishversion_true.json | 99 ++++++++++++++++++ ...and_lambda_layer_publishversion_false.json | 99 ++++++++++++++++++ ..._and_lambda_layer_publishversion_true.json | 99 ++++++++++++++++++ .../error_globals_unsupported_type.json | 6 +- ...and_lambda_layer_publishversion_false.json | 99 ++++++++++++++++++ ..._and_lambda_layer_publishversion_true.json | 99 ++++++++++++++++++ tests/translator/test_function_resources.py | 62 ++++++++--- 24 files changed, 855 insertions(+), 21 deletions(-) create mode 100644 integration/resources/code/layer2.zip create mode 100644 integration/resources/expected/combination/function_with_alias_all_properties_and_layer_version.json create mode 100644 integration/resources/templates/combination/function_with_alias_all_properties_and_layer_version.yaml create mode 100644 tests/translator/input/function_with_aliasallproperties_and_lambda_layer_publishversion_false.yaml create mode 100644 tests/translator/input/function_with_aliasallproperties_and_lambda_layer_publishversion_true.yaml create mode 100644 tests/translator/output/aws-cn/function_with_aliasallproperties_and_lambda_layer_publishversion_false.json create mode 100644 tests/translator/output/aws-cn/function_with_aliasallproperties_and_lambda_layer_publishversion_true.json create mode 100644 tests/translator/output/aws-us-gov/function_with_aliasallproperties_and_lambda_layer_publishversion_false.json create mode 100644 tests/translator/output/aws-us-gov/function_with_aliasallproperties_and_lambda_layer_publishversion_true.json create mode 100644 tests/translator/output/function_with_aliasallproperties_and_lambda_layer_publishversion_false.json create mode 100644 tests/translator/output/function_with_aliasallproperties_and_lambda_layer_publishversion_true.json diff --git a/docs/globals.rst b/docs/globals.rst index 3fe3d2275..c7615c4a0 100644 --- a/docs/globals.rst +++ b/docs/globals.rst @@ -75,6 +75,7 @@ Currently, the following resources and properties are being supported: EphemeralStorage: RuntimeManagementConfig: LoggingConfig: + FileSystemConfigs: Api: # Properties of AWS::Serverless::Api @@ -113,6 +114,10 @@ Currently, the following resources and properties are being supported: # Properties of AWS::Serverless::SimpleTable SSESpecification: + LayerVersion: + # Properties of AWS::Serverless::LayerVersion + PublishLambdaVersion: + Implicit APIs ~~~~~~~~~~~~~ diff --git a/integration/combination/test_function_with_alias.py b/integration/combination/test_function_with_alias.py index d2f6c572e..792f377a1 100644 --- a/integration/combination/test_function_with_alias.py +++ b/integration/combination/test_function_with_alias.py @@ -160,6 +160,42 @@ def test_alias_with_event_sources_get_correct_permissions(self): function_policy = json.loads(function_policy_str) self.assertEqual(len(function_policy["Statement"]), len(permission_resources)) + def test_function_with_alias_and_layer_version(self): + self.create_and_verify_stack("combination/function_with_alias_all_properties_and_layer_version") + alias_name = "Live" + function_name = self.get_physical_id_by_type("AWS::Lambda::Function") + version_ids = self.get_function_version_by_name(function_name) + self.assertEqual(["1"], version_ids) + + alias = self.get_alias(function_name, alias_name) + self.assertEqual("1", alias["FunctionVersion"]) + + # Changing Description in the LayerVersion should create a new version, and leave the existing version intact + self.set_template_resource_property("MyLayer", "Description", "test123") + self.update_stack() + + version_ids = self.get_function_version_by_name(function_name) + self.assertEqual(["1", "2"], version_ids) + + alias = self.get_alias(function_name, alias_name) + self.assertEqual("2", alias["FunctionVersion"]) + + # Changing ContentUri in LayerVersion should create a new version, and leave the existing version intact + self.set_template_resource_property("MyLayer", "ContentUri", self.file_to_s3_uri_map["layer2.zip"]["uri"]) + self.update_stack() + + version_ids = self.get_function_version_by_name(function_name) + self.assertEqual(["1", "2", "3"], version_ids) + + alias = self.get_alias(function_name, alias_name) + self.assertEqual("3", alias["FunctionVersion"]) + + # Make sure the stack has only One Version & One Alias resource + alias = self.get_stack_resources("AWS::Lambda::Alias") + versions = self.get_stack_resources("AWS::Lambda::Version") + self.assertEqual(len(alias), 1) + self.assertEqual(len(versions), 1) + def get_function_version_by_name(self, function_name): lambda_client = self.client_provider.lambda_client versions = lambda_client.list_versions_by_function(FunctionName=function_name)["Versions"] diff --git a/integration/config/file_to_s3_map.json b/integration/config/file_to_s3_map.json index 204409bbd..bdffb17e7 100644 --- a/integration/config/file_to_s3_map.json +++ b/integration/config/file_to_s3_map.json @@ -23,6 +23,10 @@ "type": "s3", "uri": "" }, + "layer2.zip": { + "type": "s3", + "uri": "" + }, "swagger1.json": { "type": "s3", "uri": "" diff --git a/integration/helpers/file_resources.py b/integration/helpers/file_resources.py index 5ee533ca8..da68e465f 100644 --- a/integration/helpers/file_resources.py +++ b/integration/helpers/file_resources.py @@ -2,6 +2,7 @@ "code.zip": {"type": "s3", "uri": ""}, "code2.zip": {"type": "s3", "uri": ""}, "layer1.zip": {"type": "s3", "uri": ""}, + "layer2.zip": {"type": "s3", "uri": ""}, "swagger1.json": {"type": "s3", "uri": ""}, "swagger2.json": {"type": "s3", "uri": ""}, "binary-media.zip": {"type": "s3", "uri": ""}, diff --git a/integration/resources/code/layer2.zip b/integration/resources/code/layer2.zip new file mode 100644 index 0000000000000000000000000000000000000000..4fa17883af5904dac4e80054aff03ac242592095 GIT binary patch literal 2175 zcmWIWW@Zs#00IA2&qy!>O0Y91FytgwrWP6LhlcPnuy23Gmc9dsL3C*aHv=Qf4@L$C zu;u`;Ash@GD26Ns8YBobBtG8P(b+#ZLSHW)VjhZdF>f)9OHL3?PESZm_~7dk_JKdF zBcOq4f&{a=fHY&FqCoSHZpjX&K1D^x05y-}JPOa;f)8~Fi2I&9f7M$@AR$q$F7+7w-7>QhuEpLx49shl9xnr7)ngKu&`=8syn#G@r{Ld|sTHTac3) zUrgnWE_W?p7Vd_2r6w>hRngYqoae9I290S*x1iEJq-JdKDCPh9p7U{EqLi7?|X zj+{IUF1Owg%x_pB@3v~gMqh=u0STqMPPt8!p+EO8)Ph~c!Ghqj=z9RsGG4S zaCpYUSy&-F0 Dict[str, An dispatch_function: Callable[..., Dict[str, Any]] = artifact_dispatch[filtered_key] return dispatch_function(artifacts[filtered_key], self.logical_id, filtered_key) - def _construct_version( - self, function: LambdaFunction, intrinsics_resolver: IntrinsicsResolver, code_sha256: Optional[str] = None + def _construct_version( # noqa: PLR0912 + self, + function: LambdaFunction, + intrinsics_resolver: IntrinsicsResolver, + resource_resolver: ResourceResolver, + code_sha256: Optional[str] = None, ) -> LambdaVersion: """Constructs a Lambda Version resource that will be auto-published when CodeUri of the function changes. Old versions will not be deleted without a direct reference from the CloudFormation template. @@ -929,6 +938,26 @@ def _construct_version( # property that when set to true would change the lambda version whenever a property in the lambda function changes if self.AutoPublishAliasAllProperties: properties = function._generate_resource_dict().get("Properties", {}) + + # When a Lambda LayerVersion resource is updated, a new Lambda layer is created. + # However, we need the Lambda function to automatically create a new version + # and use the new layer. By setting the `PublishLambdaVersion` property to true, + # a new Lambda function version will be created when the layer version is updated. + if function.Layers: + for layer in function.Layers: + layer_logical_id = get_logical_id_from_intrinsic(layer) + if not layer_logical_id: + continue + + layer_resource = resource_resolver.get_resource_by_logical_id(layer_logical_id) + if not layer_resource: + continue + + layer_properties = layer_resource.get("Properties", {}) + publish_lambda_version = layer_properties.get("PublishLambdaVersion", False) + if publish_lambda_version: + properties.update({layer_logical_id: layer_properties}) + logical_dict = properties else: with suppress(AttributeError, UnboundLocalError): @@ -1596,6 +1625,7 @@ class SamLayerVersion(SamResourceMacro): property_types = { "LayerName": PropertyType(False, one_of(IS_STR, IS_DICT)), "Description": PropertyType(False, IS_STR), + "PublishLambdaVersion": PropertyType(False, IS_BOOL), "ContentUri": PropertyType(True, one_of(IS_STR, IS_DICT)), "CompatibleArchitectures": PropertyType(False, list_of(one_of(IS_STR, IS_DICT))), "CompatibleRuntimes": PropertyType(False, list_of(one_of(IS_STR, IS_DICT))), @@ -1605,6 +1635,7 @@ class SamLayerVersion(SamResourceMacro): LayerName: Optional[Intrinsicable[str]] Description: Optional[Intrinsicable[str]] + PublishLambdaVersion: Optional[bool] ContentUri: Dict[str, Any] CompatibleArchitectures: Optional[List[Any]] CompatibleRuntimes: Optional[List[Any]] diff --git a/samtranslator/plugins/globals/globals.py b/samtranslator/plugins/globals/globals.py index d6836ff52..fdc7b3835 100644 --- a/samtranslator/plugins/globals/globals.py +++ b/samtranslator/plugins/globals/globals.py @@ -96,6 +96,7 @@ class Globals: ], SamResourceType.SimpleTable.value: ["SSESpecification"], SamResourceType.StateMachine.value: ["PropagateTags"], + SamResourceType.LambdaLayerVersion.value: ["PublishLambdaVersion"], } # unreleased_properties *must be* part of supported_properties too unreleased_properties: Dict[str, List[str]] = { diff --git a/samtranslator/schema/schema.json b/samtranslator/schema/schema.json index 063ae65b2..6d4f0dca9 100644 --- a/samtranslator/schema/schema.json +++ b/samtranslator/schema/schema.json @@ -277235,6 +277235,9 @@ "HttpApi": { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_httpapi__Globals" }, + "LayerVersion": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_layerversion__Globals" + }, "SimpleTable": { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_simpletable__Globals" }, @@ -280291,6 +280294,17 @@ "title": "Route53", "type": "object" }, + "samtranslator__internal__schema_source__aws_serverless_layerversion__Globals": { + "additionalProperties": false, + "properties": { + "PublishLambdaVersion": { + "title": "Publishlambdaversion", + "type": "boolean" + } + }, + "title": "Globals", + "type": "object" + }, "samtranslator__internal__schema_source__aws_serverless_layerversion__Properties": { "additionalProperties": false, "properties": { @@ -280341,6 +280355,10 @@ "title": "LicenseInfo", "type": "string" }, + "PublishLambdaVersion": { + "title": "Publishlambdaversion", + "type": "boolean" + }, "RetentionPolicy": { "anyOf": [ { diff --git a/schema_source/sam.schema.json b/schema_source/sam.schema.json index 60c1746ee..e1b638631 100644 --- a/schema_source/sam.schema.json +++ b/schema_source/sam.schema.json @@ -3413,6 +3413,9 @@ "HttpApi": { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_httpapi__Globals" }, + "LayerVersion": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_layerversion__Globals" + }, "SimpleTable": { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_simpletable__Globals" }, @@ -7221,6 +7224,17 @@ "title": "Route53", "type": "object" }, + "samtranslator__internal__schema_source__aws_serverless_layerversion__Globals": { + "additionalProperties": false, + "properties": { + "PublishLambdaVersion": { + "title": "Publishlambdaversion", + "type": "boolean" + } + }, + "title": "Globals", + "type": "object" + }, "samtranslator__internal__schema_source__aws_serverless_layerversion__Properties": { "additionalProperties": false, "properties": { @@ -7321,6 +7335,10 @@ ], "title": "LicenseInfo" }, + "PublishLambdaVersion": { + "title": "Publishlambdaversion", + "type": "boolean" + }, "RetentionPolicy": { "anyOf": [ { diff --git a/tests/model/test_sam_resources.py b/tests/model/test_sam_resources.py index 9aed256a2..9b6c28908 100644 --- a/tests/model/test_sam_resources.py +++ b/tests/model/test_sam_resources.py @@ -24,6 +24,7 @@ class TestArchitecture(TestCase): "intrinsics_resolver": IntrinsicsResolver({}), "event_resources": [], "managed_policy_map": {"foo": "bar"}, + "resource_resolver": ResourceResolver({}), } @patch("boto3.session.Session.region_name", "ap-southeast-1") @@ -60,6 +61,7 @@ class TestCodeUriandImageUri(TestCase): "intrinsics_resolver": IntrinsicsResolver({}), "event_resources": [], "managed_policy_map": {"foo": "bar"}, + "resource_resolver": ResourceResolver({}), } @patch("boto3.session.Session.region_name", "ap-southeast-1") @@ -143,6 +145,7 @@ class TestAssumeRolePolicyDocument(TestCase): "intrinsics_resolver": IntrinsicsResolver({}), "event_resources": [], "managed_policy_map": {"foo": "bar"}, + "resource_resolver": ResourceResolver({}), } @patch("boto3.session.Session.region_name", "ap-southeast-1") @@ -193,6 +196,7 @@ class TestVersionDescription(TestCase): "intrinsics_resolver": IntrinsicsResolver({}), "event_resources": [], "managed_policy_map": {"foo": "bar"}, + "resource_resolver": ResourceResolver({}), } @patch("boto3.session.Session.region_name", "ap-southeast-1") @@ -441,6 +445,7 @@ class TestFunctionUrlConfig(TestCase): "intrinsics_resolver": IntrinsicsResolver({}), "event_resources": [], "managed_policy_map": {"foo": "bar"}, + "resource_resolver": ResourceResolver({}), } @patch("boto3.session.Session.region_name", "ap-southeast-1") diff --git a/tests/translator/input/function_with_aliasallproperties_and_lambda_layer_publishversion_false.yaml b/tests/translator/input/function_with_aliasallproperties_and_lambda_layer_publishversion_false.yaml new file mode 100644 index 000000000..b8ba18458 --- /dev/null +++ b/tests/translator/input/function_with_aliasallproperties_and_lambda_layer_publishversion_false.yaml @@ -0,0 +1,20 @@ +Resources: + MinimalFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/hello.zip + Handler: hello.handler + Runtime: python3.10 + AutoPublishAlias: live + AutoPublishAliasAllProperties: true + VersionDescription: sam-testing + Layers: + - !Ref TestEnvLayer + + TestEnvLayer: + Type: AWS::Serverless::LayerVersion + Properties: + LayerName: test-env-dependencies + Description: Dependencies for test env implementation + ContentUri: s3://bucket/key + PublishLambdaVersion: false diff --git a/tests/translator/input/function_with_aliasallproperties_and_lambda_layer_publishversion_true.yaml b/tests/translator/input/function_with_aliasallproperties_and_lambda_layer_publishversion_true.yaml new file mode 100644 index 000000000..98a39b73a --- /dev/null +++ b/tests/translator/input/function_with_aliasallproperties_and_lambda_layer_publishversion_true.yaml @@ -0,0 +1,20 @@ +Resources: + MinimalFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/hello.zip + Handler: hello.handler + Runtime: python3.10 + AutoPublishAlias: live + AutoPublishAliasAllProperties: true + VersionDescription: sam-testing + Layers: + - !Ref TestEnvLayer + + TestEnvLayer: + Type: AWS::Serverless::LayerVersion + Properties: + LayerName: test-env-dependencies + Description: Dependencies for test env implementation + ContentUri: s3://bucket/key + PublishLambdaVersion: true diff --git a/tests/translator/output/aws-cn/function_with_aliasallproperties_and_lambda_layer_publishversion_false.json b/tests/translator/output/aws-cn/function_with_aliasallproperties_and_lambda_layer_publishversion_false.json new file mode 100644 index 000000000..bcce9a525 --- /dev/null +++ b/tests/translator/output/aws-cn/function_with_aliasallproperties_and_lambda_layer_publishversion_false.json @@ -0,0 +1,99 @@ +{ + "Resources": { + "MinimalFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Layers": [ + { + "Ref": "TestEnvLayerd122689ed9" + } + ], + "Role": { + "Fn::GetAtt": [ + "MinimalFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.10", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "MinimalFunctionAliaslive": { + "Properties": { + "FunctionName": { + "Ref": "MinimalFunction" + }, + "FunctionVersion": { + "Fn::GetAtt": [ + "MinimalFunctionVersion5346b7b9b0", + "Version" + ] + }, + "Name": "live" + }, + "Type": "AWS::Lambda::Alias" + }, + "MinimalFunctionRole": { + "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" + }, + "MinimalFunctionVersion5346b7b9b0": { + "DeletionPolicy": "Retain", + "Properties": { + "Description": "sam-testing", + "FunctionName": { + "Ref": "MinimalFunction" + } + }, + "Type": "AWS::Lambda::Version" + }, + "TestEnvLayerd122689ed9": { + "DeletionPolicy": "Retain", + "Properties": { + "Content": { + "S3Bucket": "bucket", + "S3Key": "key" + }, + "Description": "Dependencies for test env implementation", + "LayerName": "test-env-dependencies" + }, + "Type": "AWS::Lambda::LayerVersion" + } + } +} diff --git a/tests/translator/output/aws-cn/function_with_aliasallproperties_and_lambda_layer_publishversion_true.json b/tests/translator/output/aws-cn/function_with_aliasallproperties_and_lambda_layer_publishversion_true.json new file mode 100644 index 000000000..48a46c6cd --- /dev/null +++ b/tests/translator/output/aws-cn/function_with_aliasallproperties_and_lambda_layer_publishversion_true.json @@ -0,0 +1,99 @@ +{ + "Resources": { + "MinimalFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Layers": [ + { + "Ref": "TestEnvLayer856c65a2ec" + } + ], + "Role": { + "Fn::GetAtt": [ + "MinimalFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.10", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "MinimalFunctionAliaslive": { + "Properties": { + "FunctionName": { + "Ref": "MinimalFunction" + }, + "FunctionVersion": { + "Fn::GetAtt": [ + "MinimalFunctionVersion046dad86da", + "Version" + ] + }, + "Name": "live" + }, + "Type": "AWS::Lambda::Alias" + }, + "MinimalFunctionRole": { + "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" + }, + "MinimalFunctionVersion046dad86da": { + "DeletionPolicy": "Retain", + "Properties": { + "Description": "sam-testing", + "FunctionName": { + "Ref": "MinimalFunction" + } + }, + "Type": "AWS::Lambda::Version" + }, + "TestEnvLayer856c65a2ec": { + "DeletionPolicy": "Retain", + "Properties": { + "Content": { + "S3Bucket": "bucket", + "S3Key": "key" + }, + "Description": "Dependencies for test env implementation", + "LayerName": "test-env-dependencies" + }, + "Type": "AWS::Lambda::LayerVersion" + } + } +} diff --git a/tests/translator/output/aws-us-gov/function_with_aliasallproperties_and_lambda_layer_publishversion_false.json b/tests/translator/output/aws-us-gov/function_with_aliasallproperties_and_lambda_layer_publishversion_false.json new file mode 100644 index 000000000..52a2e4d83 --- /dev/null +++ b/tests/translator/output/aws-us-gov/function_with_aliasallproperties_and_lambda_layer_publishversion_false.json @@ -0,0 +1,99 @@ +{ + "Resources": { + "MinimalFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Layers": [ + { + "Ref": "TestEnvLayerd122689ed9" + } + ], + "Role": { + "Fn::GetAtt": [ + "MinimalFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.10", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "MinimalFunctionAliaslive": { + "Properties": { + "FunctionName": { + "Ref": "MinimalFunction" + }, + "FunctionVersion": { + "Fn::GetAtt": [ + "MinimalFunctionVersion5346b7b9b0", + "Version" + ] + }, + "Name": "live" + }, + "Type": "AWS::Lambda::Alias" + }, + "MinimalFunctionRole": { + "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" + }, + "MinimalFunctionVersion5346b7b9b0": { + "DeletionPolicy": "Retain", + "Properties": { + "Description": "sam-testing", + "FunctionName": { + "Ref": "MinimalFunction" + } + }, + "Type": "AWS::Lambda::Version" + }, + "TestEnvLayerd122689ed9": { + "DeletionPolicy": "Retain", + "Properties": { + "Content": { + "S3Bucket": "bucket", + "S3Key": "key" + }, + "Description": "Dependencies for test env implementation", + "LayerName": "test-env-dependencies" + }, + "Type": "AWS::Lambda::LayerVersion" + } + } +} diff --git a/tests/translator/output/aws-us-gov/function_with_aliasallproperties_and_lambda_layer_publishversion_true.json b/tests/translator/output/aws-us-gov/function_with_aliasallproperties_and_lambda_layer_publishversion_true.json new file mode 100644 index 000000000..91d328a2c --- /dev/null +++ b/tests/translator/output/aws-us-gov/function_with_aliasallproperties_and_lambda_layer_publishversion_true.json @@ -0,0 +1,99 @@ +{ + "Resources": { + "MinimalFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Layers": [ + { + "Ref": "TestEnvLayer856c65a2ec" + } + ], + "Role": { + "Fn::GetAtt": [ + "MinimalFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.10", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "MinimalFunctionAliaslive": { + "Properties": { + "FunctionName": { + "Ref": "MinimalFunction" + }, + "FunctionVersion": { + "Fn::GetAtt": [ + "MinimalFunctionVersion046dad86da", + "Version" + ] + }, + "Name": "live" + }, + "Type": "AWS::Lambda::Alias" + }, + "MinimalFunctionRole": { + "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" + }, + "MinimalFunctionVersion046dad86da": { + "DeletionPolicy": "Retain", + "Properties": { + "Description": "sam-testing", + "FunctionName": { + "Ref": "MinimalFunction" + } + }, + "Type": "AWS::Lambda::Version" + }, + "TestEnvLayer856c65a2ec": { + "DeletionPolicy": "Retain", + "Properties": { + "Content": { + "S3Bucket": "bucket", + "S3Key": "key" + }, + "Description": "Dependencies for test env implementation", + "LayerName": "test-env-dependencies" + }, + "Type": "AWS::Lambda::LayerVersion" + } + } +} diff --git a/tests/translator/output/error_globals_unsupported_type.json b/tests/translator/output/error_globals_unsupported_type.json index 40ed76b7f..9d4d7a45c 100644 --- a/tests/translator/output/error_globals_unsupported_type.json +++ b/tests/translator/output/error_globals_unsupported_type.json @@ -4,12 +4,12 @@ "Number of errors found: 1. ", "'Globals' section is invalid. ", "'NewType' is not supported. ", - "Must be one of the following values - ['Api', 'Function', 'HttpApi', 'SimpleTable', 'StateMachine']" + "Must be one of the following values - ['Api', 'Function', 'HttpApi', 'LayerVersion', 'SimpleTable', 'StateMachine']" ], - "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 - ['Api', 'Function', 'HttpApi', 'SimpleTable', 'StateMachine']", + "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 - ['Api', 'Function', 'HttpApi', 'LayerVersion', 'SimpleTable', 'StateMachine']", "errors": [ { - "errorMessage": "'Globals' section is invalid. 'NewType' is not supported. Must be one of the following values - ['Api', 'Function', 'HttpApi', 'SimpleTable', 'StateMachine']" + "errorMessage": "'Globals' section is invalid. 'NewType' is not supported. Must be one of the following values - ['Api', 'Function', 'HttpApi', 'LayerVersion', 'SimpleTable', 'StateMachine']" } ] } diff --git a/tests/translator/output/function_with_aliasallproperties_and_lambda_layer_publishversion_false.json b/tests/translator/output/function_with_aliasallproperties_and_lambda_layer_publishversion_false.json new file mode 100644 index 000000000..c47ff847b --- /dev/null +++ b/tests/translator/output/function_with_aliasallproperties_and_lambda_layer_publishversion_false.json @@ -0,0 +1,99 @@ +{ + "Resources": { + "MinimalFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Layers": [ + { + "Ref": "TestEnvLayerd122689ed9" + } + ], + "Role": { + "Fn::GetAtt": [ + "MinimalFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.10", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "MinimalFunctionAliaslive": { + "Properties": { + "FunctionName": { + "Ref": "MinimalFunction" + }, + "FunctionVersion": { + "Fn::GetAtt": [ + "MinimalFunctionVersion5346b7b9b0", + "Version" + ] + }, + "Name": "live" + }, + "Type": "AWS::Lambda::Alias" + }, + "MinimalFunctionRole": { + "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" + }, + "MinimalFunctionVersion5346b7b9b0": { + "DeletionPolicy": "Retain", + "Properties": { + "Description": "sam-testing", + "FunctionName": { + "Ref": "MinimalFunction" + } + }, + "Type": "AWS::Lambda::Version" + }, + "TestEnvLayerd122689ed9": { + "DeletionPolicy": "Retain", + "Properties": { + "Content": { + "S3Bucket": "bucket", + "S3Key": "key" + }, + "Description": "Dependencies for test env implementation", + "LayerName": "test-env-dependencies" + }, + "Type": "AWS::Lambda::LayerVersion" + } + } +} diff --git a/tests/translator/output/function_with_aliasallproperties_and_lambda_layer_publishversion_true.json b/tests/translator/output/function_with_aliasallproperties_and_lambda_layer_publishversion_true.json new file mode 100644 index 000000000..d13d47197 --- /dev/null +++ b/tests/translator/output/function_with_aliasallproperties_and_lambda_layer_publishversion_true.json @@ -0,0 +1,99 @@ +{ + "Resources": { + "MinimalFunction": { + "Properties": { + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "hello.zip" + }, + "Handler": "hello.handler", + "Layers": [ + { + "Ref": "TestEnvLayer856c65a2ec" + } + ], + "Role": { + "Fn::GetAtt": [ + "MinimalFunctionRole", + "Arn" + ] + }, + "Runtime": "python3.10", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "MinimalFunctionAliaslive": { + "Properties": { + "FunctionName": { + "Ref": "MinimalFunction" + }, + "FunctionVersion": { + "Fn::GetAtt": [ + "MinimalFunctionVersion046dad86da", + "Version" + ] + }, + "Name": "live" + }, + "Type": "AWS::Lambda::Alias" + }, + "MinimalFunctionRole": { + "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" + }, + "MinimalFunctionVersion046dad86da": { + "DeletionPolicy": "Retain", + "Properties": { + "Description": "sam-testing", + "FunctionName": { + "Ref": "MinimalFunction" + } + }, + "Type": "AWS::Lambda::Version" + }, + "TestEnvLayer856c65a2ec": { + "DeletionPolicy": "Retain", + "Properties": { + "Content": { + "S3Bucket": "bucket", + "S3Key": "key" + }, + "Description": "Dependencies for test env implementation", + "LayerName": "test-env-dependencies" + }, + "Type": "AWS::Lambda::LayerVersion" + } + } +} diff --git a/tests/translator/test_function_resources.py b/tests/translator/test_function_resources.py index 353b92c17..5fa2d0aa4 100644 --- a/tests/translator/test_function_resources.py +++ b/tests/translator/test_function_resources.py @@ -15,6 +15,8 @@ def setUp(self): self.intrinsics_resolver_mock.resolve = Mock() self.mappings_resolver_mock = Mock() self.mappings_resolver_mock.resolve = Mock() + self.resource_resolver_mock = Mock() + self.resource_resolver_mock.resolve = Mock() self.code_uri = "s3://bucket/key?versionId=version" self.func_dict = { @@ -44,6 +46,7 @@ def test_sam_function_with_code_signer(self): kwargs["managed_policy_map"] = {"a": "b"} kwargs["event_resources"] = [] kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock + kwargs["resource_resolver"] = self.resource_resolver_mock self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = { "S3Bucket": "bucket", "S3Key": "key", @@ -76,6 +79,7 @@ def test_sam_function_with_alias(self, get_resolved_alias_name_mock): kwargs["managed_policy_map"] = {"a": "b"} kwargs["event_resources"] = [] kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock + kwargs["resource_resolver"] = self.resource_resolver_mock self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = { "S3Bucket": "bucket", "S3Key": "key", @@ -131,6 +135,7 @@ def test_sam_function_with_deployment_preference(self, get_resolved_alias_name_m kwargs["event_resources"] = [] kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock kwargs["mappings_resolver"] = self.mappings_resolver_mock + kwargs["resource_resolver"] = self.resource_resolver_mock deployment_preference_collection = self._make_deployment_preference_collection() kwargs["deployment_preference_collection"] = deployment_preference_collection get_resolved_alias_name_mock.return_value = alias_name @@ -176,6 +181,7 @@ def test_sam_function_with_deployment_preference_missing_collection_raises_error kwargs["event_resources"] = [] kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock kwargs["mappings_resolver"] = self.mappings_resolver_mock + kwargs["resource_resolver"] = self.resource_resolver_mock self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = { "S3Bucket": "bucket", "S3Key": "key", @@ -212,6 +218,7 @@ def test_sam_function_with_disabled_deployment_preference_does_not_add_update_po kwargs["event_resources"] = [] kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock kwargs["mappings_resolver"] = self.mappings_resolver_mock + kwargs["resource_resolver"] = self.resource_resolver_mock preference_collection = self._make_deployment_preference_collection() preference_collection.get.return_value = DeploymentPreference.from_dict( sam_func.logical_id, deploy_preference_dict @@ -248,6 +255,7 @@ def test_sam_function_cannot_be_with_deployment_preference_without_alias(self): kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock kwargs["mappings_resolver"] = self.mappings_resolver_mock kwargs["deployment_preference_collection"] = self._make_deployment_preference_collection() + kwargs["resource_resolver"] = self.resource_resolver_mock sam_func.to_cloudformation(**kwargs) @patch("boto3.session.Session.region_name", "ap-southeast-1") @@ -271,6 +279,7 @@ def test_sam_function_without_alias_allows_disabled_deployment_preference(self): kwargs["event_resources"] = [] kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock kwargs["mappings_resolver"] = self.mappings_resolver_mock + kwargs["resource_resolver"] = self.resource_resolver_mock preference_collection = self._make_deployment_preference_collection() preference_collection.get.return_value = DeploymentPreference.from_dict( @@ -311,6 +320,7 @@ def test_sam_function_with_deployment_preference_intrinsic_ref_enabled_boolean_p kwargs["event_resources"] = [] kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock kwargs["mappings_resolver"] = self.mappings_resolver_mock + kwargs["resource_resolver"] = self.resource_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 = True @@ -355,6 +365,7 @@ def test_sam_function_with_deployment_preference_intrinsic_ref_enabled_dict_para kwargs["event_resources"] = [] kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock kwargs["mappings_resolver"] = self.mappings_resolver_mock + kwargs["resource_resolver"] = self.resource_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} @@ -389,6 +400,7 @@ def test_sam_function_with_deployment_preference_intrinsic_findinmap_enabled_dic kwargs["event_resources"] = [] kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock kwargs["mappings_resolver"] = self.mappings_resolver_mock + kwargs["resource_resolver"] = self.resource_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} @@ -424,6 +436,7 @@ def test_sam_function_with_deployment_preference_passthrough_condition_through_p kwargs["event_resources"] = [] kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock kwargs["mappings_resolver"] = self.mappings_resolver_mock + kwargs["resource_resolver"] = self.resource_resolver_mock deployment_preference_collection = self._make_deployment_preference_collection() kwargs["deployment_preference_collection"] = deployment_preference_collection get_resolved_alias_name_mock.return_value = alias_name @@ -472,6 +485,7 @@ def test_sam_function_with_deployment_preference_passthrough_condition_through_f kwargs["event_resources"] = [] kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock kwargs["mappings_resolver"] = self.mappings_resolver_mock + kwargs["resource_resolver"] = self.resource_resolver_mock deployment_preference_collection = self._make_deployment_preference_collection() kwargs["deployment_preference_collection"] = deployment_preference_collection get_resolved_alias_name_mock.return_value = alias_name @@ -531,6 +545,7 @@ def test_sam_function_with_deployment_preference_passthrough_condition_invalid_i kwargs["event_resources"] = [] kwargs["intrinsics_resolver"] = self.intrinsics_resolver_mock kwargs["mappings_resolver"] = self.mappings_resolver_mock + kwargs["resource_resolver"] = self.resource_resolver_mock deployment_preference_collection = self._make_deployment_preference_collection() kwargs["deployment_preference_collection"] = deployment_preference_collection get_resolved_alias_name_mock.return_value = alias_name @@ -560,7 +575,9 @@ def test_version_creation(self, LogicalIdGeneratorMock): generator_mock.gen.return_value = id_val self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = self.lambda_func.Code - version = self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock) + version = self.sam_func._construct_version( + self.lambda_func, self.intrinsics_resolver_mock, self.resource_resolver_mock + ) self.assertEqual(version.logical_id, id_val) self.assertEqual(version.Description, None) @@ -582,7 +599,9 @@ def test_version_creation_with_code_sha(self, LogicalIdGeneratorMock): self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = self.lambda_func.Code self.sam_func.AutoPublishCodeSha256 = hash_code - version = self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock, hash_code) + version = self.sam_func._construct_version( + self.lambda_func, self.intrinsics_resolver_mock, self.resource_resolver_mock, hash_code + ) self.assertEqual(version.logical_id, id_val) self.assertEqual(version.Description, None) @@ -603,7 +622,9 @@ def test_version_creation_without_s3_object_version(self, LogicalIdGeneratorMock del self.lambda_func.Code["S3ObjectVersion"] self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = self.lambda_func.Code - version = self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock) + version = self.sam_func._construct_version( + self.lambda_func, self.intrinsics_resolver_mock, self.resource_resolver_mock + ) self.assertEqual(version.logical_id, id_val) @@ -616,7 +637,9 @@ def test_version_creation_error(self): # Empty code dictionary self.lambda_func.Code = {} with self.assertRaises(ValueError): - self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock) + self.sam_func._construct_version( + self.lambda_func, self.intrinsics_resolver_mock, self.resource_resolver_mock + ) @patch("samtranslator.translator.logical_id_generator.LogicalIdGenerator") def test_version_creation_intrinsic_function_in_code_s3key(self, LogicalIdGeneratorMock): @@ -628,7 +651,9 @@ def test_version_creation_intrinsic_function_in_code_s3key(self, LogicalIdGenera self.lambda_func.Code = {"S3Bucket": "bucket", "S3Key": {"Ref": "keyparameter"}, "S3ObjectVersion": "version"} self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = self.lambda_func.Code - version = self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock) + version = self.sam_func._construct_version( + self.lambda_func, self.intrinsics_resolver_mock, self.resource_resolver_mock + ) self.assertEqual(version.logical_id, id_val) expected_prefix = self.sam_func.logical_id + "Version" @@ -644,7 +669,9 @@ def test_version_creation_intrinsic_function_in_code_s3bucket(self, LogicalIdGen self.lambda_func.Code = {"S3Bucket": {"Ref": "bucketparameter"}, "S3Key": "key", "S3ObjectVersion": "version"} self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = self.lambda_func.Code - version = self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock) + version = self.sam_func._construct_version( + self.lambda_func, self.intrinsics_resolver_mock, self.resource_resolver_mock + ) self.assertEqual(version.logical_id, id_val) expected_prefix = self.sam_func.logical_id + "Version" @@ -660,7 +687,9 @@ def test_version_creation_intrinsic_function_in_code_s3version(self, LogicalIdGe self.lambda_func.Code = {"S3Bucket": "bucket", "S3Key": "key", "S3ObjectVersion": {"Ref": "versionparameter"}} self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = self.lambda_func.Code - version = self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock) + version = self.sam_func._construct_version( + self.lambda_func, self.intrinsics_resolver_mock, self.resource_resolver_mock + ) self.assertEqual(version.logical_id, id_val) expected_prefix = self.sam_func.logical_id + "Version" @@ -676,7 +705,7 @@ def test_version_logical_id_changes(self, LogicalIdGeneratorMock): # Test that logicalId changes with changes to CodeSha self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = self.lambda_func.Code - self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock) + self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock, self.resource_resolver_mock) LogicalIdGeneratorMock.assert_called_once_with(prefix, self.lambda_func.Code, None) self.intrinsics_resolver_mock.resolve_parameter_refs.assert_called_with(self.lambda_func.Code) @@ -685,7 +714,7 @@ def test_version_logical_id_changes(self, LogicalIdGeneratorMock): self.lambda_func.Code["S3ObjectVersion"] = "new object version" new_code = self.lambda_func.Code.copy() self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = new_code - self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock) + self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock, self.resource_resolver_mock) LogicalIdGeneratorMock.assert_called_with(prefix, new_code, None) self.intrinsics_resolver_mock.resolve_parameter_refs.assert_called_with(new_code) @@ -699,7 +728,7 @@ def test_version_logical_id_changes_with_intrinsic_functions(self, LogicalIdGene self.lambda_func.Code = {"S3Bucket": "bucket", "S3Key": {"Ref": "someparam"}} self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = self.lambda_func.Code - self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock) + self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock, self.resource_resolver_mock) LogicalIdGeneratorMock.assert_called_once_with(prefix, self.lambda_func.Code, None) self.intrinsics_resolver_mock.resolve_parameter_refs.assert_called_with(self.lambda_func.Code) @@ -707,7 +736,7 @@ def test_version_logical_id_changes_with_intrinsic_functions(self, LogicalIdGene # Now, just let the intrinsics resolver return a different value. Let's make sure the new value gets wired up properly new_code = {"S3Bucket": "bucket", "S3Key": "some new value"} self.intrinsics_resolver_mock.resolve_parameter_refs.return_value = new_code - self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock) + self.sam_func._construct_version(self.lambda_func, self.intrinsics_resolver_mock, self.resource_resolver_mock) LogicalIdGeneratorMock.assert_called_with(prefix, new_code, None) self.intrinsics_resolver_mock.resolve_parameter_refs.assert_called_with(self.lambda_func.Code) @@ -723,11 +752,14 @@ def test_version_logical_id_changes_with_snapstart(self): 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) + version1 = self.sam_func._construct_version( + lambda_func, self.intrinsics_resolver_mock, self.resource_resolver_mock + ) + version_snapstart = self.sam_func._construct_version( + lambda_func_snapstart, self.intrinsics_resolver_mock, self.resource_resolver_mock + ) version_snapstart_none = self.sam_func._construct_version( - lambda_func_snapstart_none, - self.intrinsics_resolver_mock, + lambda_func_snapstart_none, self.intrinsics_resolver_mock, self.resource_resolver_mock ) # SnapStart config changes the hash, except when ApplyOn is "None" self.assertNotEqual(version1.logical_id, version_snapstart.logical_id)