From 8496cbd9ae46aa1131c6952597f1df83edee964e Mon Sep 17 00:00:00 2001 From: _sam <3804518+aahung@users.noreply.github.com> Date: Tue, 14 Sep 2021 14:42:08 -0700 Subject: [PATCH] fix: Revert the behavior when both ImageUri and Metadata exist for image func (#3272) --- samcli/lib/providers/sam_function_provider.py | 24 +++++- .../local/lib/test_sam_function_provider.py | 74 +++++++++++++++++++ 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/samcli/lib/providers/sam_function_provider.py b/samcli/lib/providers/sam_function_provider.py index 6bffc4bf75..acdc9d91f1 100644 --- a/samcli/lib/providers/sam_function_provider.py +++ b/samcli/lib/providers/sam_function_provider.py @@ -144,8 +144,12 @@ def _extract_functions( SamFunctionProvider._warn_code_extraction(resource_type, name, code_property_key) continue - if resource_package_type == IMAGE and SamBaseProvider._is_ecr_uri( - resource_properties.get(image_property_key) + if ( + resource_package_type == IMAGE + and SamBaseProvider._is_ecr_uri(resource_properties.get(image_property_key)) + and not SamFunctionProvider._metadata_has_necessary_entries_for_image_function_to_be_built( + resource_metadata + ) ): # ImageUri can be an ECR uri, which is not supported if not ignore_code_extraction_warnings: @@ -460,3 +464,19 @@ def get_resources_by_stack_path(self, stack_path: str) -> Dict: if not candidates: raise RuntimeError(f"Cannot find resources with stack_path = {stack_path}") return candidates[0] + + @staticmethod + def _metadata_has_necessary_entries_for_image_function_to_be_built(metadata: Optional[Dict[str, Any]]) -> bool: + """ + > Note: If the PackageType property is set to Image, then either ImageUri is required, + or you must build your application with necessary Metadata entries in the AWS SAM template file. + https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-imageuri + + When ImageUri and Metadata are both provided, we will try to determine whether to treat the function + as to be built or to be skipped. When we skip it whenever "ImageUri" is provided, + we introduced a breaking change https://github.com/aws/aws-sam-cli/issues/3239 + + This function is used to check whether there are the customers have "intention" to + let AWS SAM CLI to build this image function. + """ + return isinstance(metadata, dict) and bool(metadata.get("DockerContext")) diff --git a/tests/unit/commands/local/lib/test_sam_function_provider.py b/tests/unit/commands/local/lib/test_sam_function_provider.py index 9daf92abc0..fe75569e7f 100644 --- a/tests/unit/commands/local/lib/test_sam_function_provider.py +++ b/tests/unit/commands/local/lib/test_sam_function_provider.py @@ -95,6 +95,15 @@ class TestSamFunctionProviderEndToEnd(TestCase): "PackageType": IMAGE, }, }, + "SamFuncWithImage4": { + # ImageUri is unsupported ECR location, but metadata is still provided, build + "Type": "AWS::Serverless::Function", + "Properties": { + "ImageUri": "123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo:myimage", + "PackageType": IMAGE, + }, + "Metadata": {"DockerTag": "tag", "DockerContext": "./image", "Dockerfile": "Dockerfile"}, + }, "LambdaFunc1": { "Type": "AWS::Lambda::Function", "Properties": { @@ -126,6 +135,15 @@ class TestSamFunctionProviderEndToEnd(TestCase): "PackageType": IMAGE, }, }, + "LambdaFuncWithImage4": { + # ImageUri is unsupported ECR location, but metadata is still provided, build + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": {"ImageUri": "123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo"}, + "PackageType": IMAGE, + }, + "Metadata": {"DockerTag": "tag", "DockerContext": "./image", "Dockerfile": "Dockerfile"}, + }, "LambdaFuncWithInlineCode": { "Type": "AWS::Lambda::Function", "Properties": { @@ -337,6 +355,33 @@ def setUp(self): ), ), ("SamFuncWithImage3", None), # imageuri is ecr location, ignored + ( + "SamFuncWithImage4", # despite imageuri is ecr location, the necessary metadata is still provided, build + Function( + name="SamFuncWithImage4", + functionname="SamFuncWithImage4", + runtime=None, + handler=None, + codeuri=".", + memory=None, + timeout=None, + environment=None, + rolearn=None, + layers=[], + events=None, + inlinecode=None, + imageuri="123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo:myimage", + imageconfig=None, + packagetype=IMAGE, + metadata={ + "DockerTag": "tag", + "DockerContext": os.path.join("image"), + "Dockerfile": "Dockerfile", + }, + codesign_config_arn=None, + stack_path="", + ), + ), ( "SamFuncWithFunctionNameOverride-x", Function( @@ -416,6 +461,33 @@ def setUp(self): ), ), ("LambdaFuncWithImage3", None), # imageuri is a ecr location, ignored + ( + "LambdaFuncWithImage4", # despite imageuri is ecr location, the necessary metadata is still provided, build + Function( + name="LambdaFuncWithImage4", + functionname="LambdaFuncWithImage4", + runtime=None, + handler=None, + codeuri=".", + memory=None, + timeout=None, + environment=None, + rolearn=None, + layers=[], + events=None, + metadata={ + "DockerTag": "tag", + "DockerContext": os.path.join("image"), + "Dockerfile": "Dockerfile", + }, + inlinecode=None, + imageuri="123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo", + imageconfig=None, + packagetype=IMAGE, + codesign_config_arn=None, + stack_path="", + ), + ), ( "LambdaFuncWithInlineCode", Function( @@ -595,10 +667,12 @@ def test_get_all_must_return_all_functions(self): "SamFunctions", "SamFuncWithImage1", "SamFuncWithImage2", + "SamFuncWithImage4", "SamFuncWithInlineCode", "SamFuncWithFunctionNameOverride", "LambdaFuncWithImage1", "LambdaFuncWithImage2", + "LambdaFuncWithImage4", "LambdaFuncWithInlineCode", "LambdaFuncWithLocalPath", "LambdaFuncWithFunctionNameOverride",