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 000000000..4fa17883a Binary files /dev/null and b/integration/resources/code/layer2.zip differ diff --git a/integration/resources/expected/combination/function_with_alias_all_properties_and_layer_version.json b/integration/resources/expected/combination/function_with_alias_all_properties_and_layer_version.json new file mode 100644 index 000000000..be1a9f96d --- /dev/null +++ b/integration/resources/expected/combination/function_with_alias_all_properties_and_layer_version.json @@ -0,0 +1,22 @@ +[ + { + "LogicalResourceId": "MyLambdaFunction", + "ResourceType": "AWS::Lambda::Function" + }, + { + "LogicalResourceId": "MyLambdaFunctionRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "MyLambdaFunctionAliasLive", + "ResourceType": "AWS::Lambda::Alias" + }, + { + "LogicalResourceId": "MyLambdaFunctionVersion", + "ResourceType": "AWS::Lambda::Version" + }, + { + "LogicalResourceId": "MyLayer", + "ResourceType": "AWS::Lambda::LayerVersion" + } +] diff --git a/integration/resources/templates/combination/function_with_alias_all_properties_and_layer_version.yaml b/integration/resources/templates/combination/function_with_alias_all_properties_and_layer_version.yaml new file mode 100644 index 000000000..89cf5d7ee --- /dev/null +++ b/integration/resources/templates/combination/function_with_alias_all_properties_and_layer_version.yaml @@ -0,0 +1,21 @@ +Resources: + MyLambdaFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: ${codeuri} + Handler: index.handler + Runtime: nodejs20.x + AutoPublishAlias: Live + AutoPublishAliasAllProperties: true + Layers: + - !Ref MyLayer + + MyLayer: + Type: AWS::Serverless::LayerVersion + Properties: + ContentUri: ${contenturi} + RetentionPolicy: Delete + PublishLambdaVersion: true + Description: test +Metadata: + SamTransformTest: true diff --git a/samtranslator/internal/schema_source/aws_serverless_layerversion.py b/samtranslator/internal/schema_source/aws_serverless_layerversion.py index 96523fd56..298ecf8de 100644 --- a/samtranslator/internal/schema_source/aws_serverless_layerversion.py +++ b/samtranslator/internal/schema_source/aws_serverless_layerversion.py @@ -47,6 +47,7 @@ class Properties(BaseModel): "CompatibleRuntimes", ["AWS::Lambda::LayerVersion", "Properties", "CompatibleRuntimes"], ) + PublishLambdaVersion: Optional[bool] # TODO: add docs ContentUri: Union[str, ContentUri] = properties("ContentUri") Description: Optional[PassThroughProp] = passthrough_prop( PROPERTIES_STEM, @@ -65,3 +66,7 @@ class Properties(BaseModel): class Resource(ResourceAttributes): Type: Literal["AWS::Serverless::LayerVersion"] Properties: Properties + + +class Globals(BaseModel): + PublishLambdaVersion: Optional[bool] # TODO: add docs diff --git a/samtranslator/internal/schema_source/schema.py b/samtranslator/internal/schema_source/schema.py index 0be4f8512..02ff7f903 100644 --- a/samtranslator/internal/schema_source/schema.py +++ b/samtranslator/internal/schema_source/schema.py @@ -28,6 +28,7 @@ class Globals(BaseModel): HttpApi: Optional[aws_serverless_httpapi.Globals] SimpleTable: Optional[aws_serverless_simpletable.Globals] StateMachine: Optional[aws_serverless_statemachine.Globals] + LayerVersion: Optional[aws_serverless_layerversion.Globals] Resources = Union[ diff --git a/samtranslator/model/sam_resources.py b/samtranslator/model/sam_resources.py index 8f3b6492f..fffca961e 100644 --- a/samtranslator/model/sam_resources.py +++ b/samtranslator/model/sam_resources.py @@ -81,6 +81,7 @@ from samtranslator.model.intrinsics import ( fnGetAtt, fnSub, + get_logical_id_from_intrinsic, is_intrinsic, is_intrinsic_if, is_intrinsic_no_value, @@ -265,6 +266,7 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def] # noqa: P """ resources: List[Any] = [] intrinsics_resolver: IntrinsicsResolver = kwargs["intrinsics_resolver"] + resource_resolver: ResourceResolver = kwargs["resource_resolver"] mappings_resolver: Optional[IntrinsicsResolver] = kwargs.get("mappings_resolver") conditions = kwargs.get("conditions", {}) feature_toggle = kwargs.get("feature_toggle") @@ -303,7 +305,10 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def] # noqa: P else: lambda_function.Description = {"Fn::Join": [" ", [description, code_sha256]]} lambda_version = self._construct_version( - lambda_function, intrinsics_resolver=intrinsics_resolver, code_sha256=code_sha256 + lambda_function, + intrinsics_resolver=intrinsics_resolver, + resource_resolver=resource_resolver, + code_sha256=code_sha256, ) lambda_alias = self._construct_alias(alias_name, lambda_function, lambda_version) resources.append(lambda_version) @@ -882,8 +887,12 @@ def _construct_inline_code(*args: Any, **kwargs: Dict[str, Any]) -> 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)