Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion samcli/commands/_utils/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from botocore.utils import set_value_from_jmespath

from samcli.commands.exceptions import UserException
from samcli.lib.utils.packagetype import ZIP
from samcli.lib.utils.packagetype import ZIP, IMAGE
from samcli.yamlhelper import yaml_parse, yaml_dump
from samcli.lib.utils.resources import (
METADATA_WITH_LOCAL_PATHS,
Expand Down Expand Up @@ -155,6 +155,12 @@ def _update_relative_paths(template_dict, original_root, new_root):
for path_prop_name in RESOURCES_WITH_LOCAL_PATHS[resource_type]:
properties = resource.get("Properties", {})

if (
resource_type in [AWS_SERVERLESS_FUNCTION, AWS_LAMBDA_FUNCTION]
and properties.get("PackageType", ZIP) == IMAGE
):
continue

path = jmespath.search(path_prop_name, properties)
updated_path = _resolve_relative_to(path, original_root, new_root)

Expand Down
10 changes: 10 additions & 0 deletions tests/integration/buildcmd/build_integ_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,16 @@ def verify_pulled_image(self, runtime, architecture=X86_64):
def _make_parameter_override_arg(self, overrides):
return " ".join(["ParameterKey={},ParameterValue={}".format(key, value) for key, value in overrides.items()])

def _verify_image_build_artifact(self, template_path, image_function_logical_id, property, image_uri):
self.assertTrue(template_path.exists(), "Build directory should be created")

build_dir = template_path.parent
build_dir_files = os.listdir(str(build_dir))
self.assertNotIn(image_function_logical_id, build_dir_files)

# Make sure the template has correct CodeUri for resource
self._verify_resource_property(str(template_path), image_function_logical_id, property, image_uri)

def _verify_resource_property(self, template_path, logical_id, property, expected_value):
with open(template_path, "r") as fp:
template_dict = yaml_parse(fp.read())
Expand Down
19 changes: 11 additions & 8 deletions tests/integration/buildcmd/test_build_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import shutil
import sys
from pathlib import Path
from typing import Set
from unittest import skipIf

import pytest
Expand Down Expand Up @@ -49,31 +50,33 @@
class TestBuildCommand_PythonFunctions_Images(BuildIntegBase):
template = "template_image.yaml"

EXPECTED_FILES_PROJECT_MANIFEST = {
"__init__.py",
"main.py",
"numpy",
# 'cryptography',
"requirements.txt",
}
EXPECTED_FILES_PROJECT_MANIFEST: Set[str] = set()

FUNCTION_LOGICAL_ID_IMAGE = "ImageFunction"

@parameterized.expand([("3.6", False), ("3.7", False), ("3.8", False), ("3.9", False)])
@pytest.mark.flaky(reruns=3)
def test_with_default_requirements(self, runtime, use_container):
_tag = f"{random.randint(1,100)}"
overrides = {
"Runtime": runtime,
"Handler": "main.handler",
"DockerFile": "Dockerfile",
"Tag": f"{random.randint(1,100)}",
"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
Expand Down
80 changes: 79 additions & 1 deletion tests/unit/commands/_utils/test_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from botocore.utils import set_value_from_jmespath
from parameterized import parameterized, param

from samcli.lib.utils.resources import AWS_SERVERLESS_FUNCTION, AWS_SERVERLESS_API
from samcli.lib.utils.resources import AWS_SERVERLESS_FUNCTION, AWS_SERVERLESS_API, RESOURCES_WITH_IMAGE_COMPONENT
from samcli.commands._utils.template import (
get_template_data,
METADATA_WITH_LOCAL_PATHS,
Expand Down Expand Up @@ -140,6 +140,7 @@ def setUp(self):
self.dest = os.path.abspath(os.path.join("src", "destination")) # /path/from/root/src/destination

self.expected_result = os.path.join("..", "foo", "bar")
self.image_uri = "func12343:latest"

@parameterized.expand([(resource_type, props) for resource_type, props in METADATA_WITH_LOCAL_PATHS.items()])
def test_must_update_relative_metadata_paths(self, resource_type, properties):
Expand Down Expand Up @@ -199,6 +200,83 @@ def test_must_update_relative_resource_paths(self, resource_type, properties):
self.maxDiff = None
self.assertEqual(result, expected_template_dict)

@parameterized.expand([(resource_type, props) for resource_type, props in RESOURCES_WITH_IMAGE_COMPONENT.items()])
def test_must_skip_image_components(self, resource_type, properties):
for propname in properties:
template_dict = {
"Resources": {
"ImageResource": {"Type": resource_type, "Properties": {"PackageType": "Image"}},
}
}

set_value_from_jmespath(template_dict, f"Resources.ImageResource.Properties.{propname}", self.image_uri)

expected_template_dict = copy.deepcopy(template_dict)

result = _update_relative_paths(template_dict, self.src, self.dest)

self.maxDiff = None
self.assertEqual(result, expected_template_dict)

@parameterized.expand(
[
(image_resource_type, image_props, non_image_resource_type, non_image_props)
for image_resource_type, image_props in RESOURCES_WITH_IMAGE_COMPONENT.items()
for non_image_resource_type, non_image_props in RESOURCES_WITH_LOCAL_PATHS.items()
]
)
def test_must_skip_only_image_components_and_update_relative_resource_paths(
self, image_resource_type, image_properties, non_image_resource_type, non_image_properties
):
for non_image_propname in non_image_properties:
for image_propname in image_properties:
template_dict = {
"Resources": {
"MyResourceWithRelativePath": {"Type": non_image_resource_type, "Properties": {}},
"MyResourceWithS3Path": {
"Type": non_image_resource_type,
"Properties": {non_image_propname: self.s3path},
},
"MyResourceWithAbsolutePath": {
"Type": non_image_resource_type,
"Properties": {non_image_propname: self.abspath},
},
"MyResourceWithInvalidPath": {
"Type": non_image_resource_type,
"Properties": {
# Path is not a string
non_image_propname: {"foo": "bar"}
},
},
"MyResourceWithoutProperties": {"Type": non_image_resource_type},
"UnsupportedResourceType": {"Type": "AWS::Ec2::Instance", "Properties": {"Code": "bar"}},
"ResourceWithoutType": {"foo": "bar"},
"ImageResource": {"Type": image_resource_type, "Properties": {"PackageType": "Image"}},
},
"Parameters": {"a": "b"},
}

set_value_from_jmespath(
template_dict, f"Resources.MyResourceWithRelativePath.Properties.{non_image_propname}", self.curpath
)

set_value_from_jmespath(
template_dict, f"Resources.ImageResource.Properties.{image_propname}", self.image_uri
)

expected_template_dict = copy.deepcopy(template_dict)

set_value_from_jmespath(
expected_template_dict,
f"Resources.MyResourceWithRelativePath.Properties.{non_image_propname}",
self.expected_result,
)

result = _update_relative_paths(template_dict, self.src, self.dest)

self.maxDiff = None
self.assertEqual(result, expected_template_dict)

def test_must_update_aws_include_also(self):
template_dict = {
"Resources": {"Fn::Transform": {"Name": "AWS::Include", "Parameters": {"Location": self.curpath}}},
Expand Down