From fa26bff1415485e3603f8f3d59ff1234af54c5b7 Mon Sep 17 00:00:00 2001 From: Christian Gaetano <95438786+christiangaetano@users.noreply.github.com> Date: Tue, 1 Nov 2022 17:02:53 -0700 Subject: [PATCH] Extract full file name from Dockerfile path (#4360) * Extract full file name from Dockerfile path Using `.name` here instead of `.stem` will ensure that the entire file name is returned including any and all extensions. * Add unit test for Dockerfile with extension * Add dockerfile extension integration test This test will verify that a function can be built and invoked when the Dockerfile contains a suffix/extension in the file name. Co-authored-by: Wing Fung Lau <4760060+hawflau@users.noreply.github.com> --- .../samlib/resource_metadata_normalizer.py | 2 +- tests/integration/buildcmd/test_build_cmd.py | 28 +++++++++++++++ .../PythonImage/Dockerfile.production | 15 ++++++++ .../test_resource_metadata_normalizer.py | 35 +++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 tests/integration/testdata/buildcmd/PythonImage/Dockerfile.production diff --git a/samcli/lib/samlib/resource_metadata_normalizer.py b/samcli/lib/samlib/resource_metadata_normalizer.py index 1ed5a43be1..995d67306e 100644 --- a/samcli/lib/samlib/resource_metadata_normalizer.py +++ b/samcli/lib/samlib/resource_metadata_normalizer.py @@ -186,7 +186,7 @@ def _extract_image_asset_metadata(metadata): """ asset_path = Path(metadata.get(ASSET_PATH_METADATA_KEY, "")) dockerfile_path = Path(metadata.get(ASSET_DOCKERFILE_PATH_KEY), "") - dockerfile, path_from_asset = dockerfile_path.stem, dockerfile_path.parent + dockerfile, path_from_asset = dockerfile_path.name, dockerfile_path.parent dockerfile_context = str(Path(asset_path.joinpath(path_from_asset))) return { SAM_METADATA_DOCKERFILE_KEY: dockerfile, diff --git a/tests/integration/buildcmd/test_build_cmd.py b/tests/integration/buildcmd/test_build_cmd.py index c5afc184e8..683972e07a 100644 --- a/tests/integration/buildcmd/test_build_cmd.py +++ b/tests/integration/buildcmd/test_build_cmd.py @@ -86,6 +86,34 @@ def test_with_default_requirements(self, runtime, use_container): self.built_template, self.FUNCTION_LOGICAL_ID_IMAGE, self._make_parameter_override_arg(overrides), expected ) + @parameterized.expand([("3.6", False), ("3.7", False), ("3.8", False), ("3.9", False)]) + @pytest.mark.flaky(reruns=3) + def test_with_dockerfile_extension(self, runtime, use_container): + _tag = f"{random.randint(1,100)}" + overrides = { + "Runtime": runtime, + "Handler": "main.handler", + "DockerFile": "Dockerfile.production", + "Tag": _tag, + } + cmdlist = self.get_command_list(use_container=use_container, parameter_overrides=overrides) + + LOG.info("Running Command: ") + LOG.info(cmdlist) + run_command(cmdlist, cwd=self.working_dir) + + self._verify_image_build_artifact( + self.built_template, + self.FUNCTION_LOGICAL_ID_IMAGE, + "ImageUri", + f"{self.FUNCTION_LOGICAL_ID_IMAGE.lower()}:{_tag}", + ) + + expected = {"pi": "3.14"} + self._verify_invoke_built_function( + self.built_template, self.FUNCTION_LOGICAL_ID_IMAGE, self._make_parameter_override_arg(overrides), expected + ) + @pytest.mark.flaky(reruns=3) def test_intermediate_container_deleted(self): _tag = f"{random.randint(1, 100)}" diff --git a/tests/integration/testdata/buildcmd/PythonImage/Dockerfile.production b/tests/integration/testdata/buildcmd/PythonImage/Dockerfile.production new file mode 100644 index 0000000000..bd617ce1f0 --- /dev/null +++ b/tests/integration/testdata/buildcmd/PythonImage/Dockerfile.production @@ -0,0 +1,15 @@ +ARG BASE_RUNTIME + +FROM public.ecr.aws/lambda/python:$BASE_RUNTIME + +ARG FUNCTION_DIR="/var/task" + +RUN mkdir -p $FUNCTION_DIR + +COPY main.py $FUNCTION_DIR + +COPY __init__.py $FUNCTION_DIR +COPY requirements.txt $FUNCTION_DIR + +RUN python -m pip install -r $FUNCTION_DIR/requirements.txt -t $FUNCTION_DIR + diff --git a/tests/unit/lib/samlib/test_resource_metadata_normalizer.py b/tests/unit/lib/samlib/test_resource_metadata_normalizer.py index c4c0c2e877..5600fbc507 100644 --- a/tests/unit/lib/samlib/test_resource_metadata_normalizer.py +++ b/tests/unit/lib/samlib/test_resource_metadata_normalizer.py @@ -112,6 +112,41 @@ def test_replace_all_resources_that_contain_image_metadata(self): self.assertEqual(docker_build_args, template_data["Resources"]["Function1"]["Metadata"]["DockerBuildArgs"]) self.assertEqual("Function1", template_data["Resources"]["Function1"]["Metadata"]["SamResourceId"]) + def test_replace_all_resources_that_contain_image_metadata_dockerfile_extensions(self): + docker_build_args = {"arg1": "val1", "arg2": "val2"} + asset_path = pathlib.Path("/path", "to", "asset") + dockerfile_path = pathlib.Path("path", "to", "Dockerfile.production") + template_data = { + "Resources": { + "Function1": { + "Properties": { + "Code": { + "ImageUri": { + "Fn::Sub": "${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}:b5d75370ccc2882b90f701c8f98952aae957e85e1928adac8860222960209056" + } + } + }, + "Metadata": { + "aws:asset:path": asset_path, + "aws:asset:property": "Code.ImageUri", + "aws:asset:dockerfile-path": dockerfile_path, + "aws:asset:docker-build-args": docker_build_args, + }, + }, + } + } + + ResourceMetadataNormalizer.normalize(template_data) + + expected_docker_context_path = str(pathlib.Path("/path", "to", "asset", "path", "to")) + self.assertEqual("function1", template_data["Resources"]["Function1"]["Properties"]["Code"]["ImageUri"]) + self.assertEqual( + expected_docker_context_path, template_data["Resources"]["Function1"]["Metadata"]["DockerContext"] + ) + self.assertEqual("Dockerfile.production", template_data["Resources"]["Function1"]["Metadata"]["Dockerfile"]) + self.assertEqual(docker_build_args, template_data["Resources"]["Function1"]["Metadata"]["DockerBuildArgs"]) + self.assertEqual("Function1", template_data["Resources"]["Function1"]["Metadata"]["SamResourceId"]) + def test_replace_all_resources_that_contain_image_metadata_windows_paths(self): docker_build_args = {"arg1": "val1", "arg2": "val2"} asset_path = "C:\\path\\to\\asset"