1414
1515from samcli .lib .utils import osutils
1616from samcli .local .docker .utils import get_validated_container_client
17+ from samcli .local .docker .image_build_client import CLIBuildClient
18+ from samcli .local .docker .container_client_factory import ContainerClientFactory
1719from samcli .yamlhelper import yaml_parse
1820from tests .testing_utils import (
1921 IS_WINDOWS ,
4648
4749
4850@skipIf (SKIP_DOCKER_TESTS , SKIP_DOCKER_MESSAGE )
51+ @parameterized_class (
52+ ("use_buildkit" ,),
53+ [
54+ (False ,),
55+ (True ,),
56+ ],
57+ )
58+ @pytest .mark .filterwarnings ("ignore::ResourceWarning" )
4959class TestBuildingImageTypeLambdaDockerFileFailuresContainer (BuildIntegBase ):
5060 template = "template_image.yaml"
5161
62+ def setUp (self ):
63+ super ().setUp ()
64+ if self .use_buildkit :
65+ client = ContainerClientFactory .create_client ()
66+ is_available , error_msg = CLIBuildClient .is_available (client .get_runtime_type ())
67+ if not is_available :
68+ self .skipTest (f"Buildkit not available: { error_msg } " )
69+
5270 def test_with_invalid_dockerfile_location (self ):
5371 overrides = {
5472 "Runtime" : "3.10" ,
5573 "Handler" : "handler" ,
5674 "DockerFile" : "ThisDockerfileDoesNotExist" ,
5775 "Tag" : uuid4 ().hex ,
5876 }
59- cmdlist = self .get_command_list (parameter_overrides = overrides )
77+ cmdlist = self .get_command_list (parameter_overrides = overrides , use_buildkit = self . use_buildkit )
6078 command_result = run_command (cmdlist , cwd = self .working_dir )
6179
6280 # confirm build failed
@@ -77,7 +95,7 @@ def test_with_invalid_dockerfile_definition(self):
7795 "DockerFile" : "InvalidDockerfile" ,
7896 "Tag" : uuid4 ().hex ,
7997 }
80- cmdlist = self .get_command_list (parameter_overrides = overrides )
98+ cmdlist = self .get_command_list (parameter_overrides = overrides , use_buildkit = self . use_buildkit )
8199 command_result = run_command (cmdlist , cwd = self .working_dir )
82100
83101 # confirm build failed
@@ -86,29 +104,45 @@ def test_with_invalid_dockerfile_definition(self):
86104
87105
88106@skipIf (SKIP_DOCKER_TESTS , SKIP_DOCKER_MESSAGE )
107+ @parameterized_class (
108+ ("use_buildkit" ,),
109+ [
110+ (False ,),
111+ (True ,),
112+ ],
113+ )
114+ @pytest .mark .filterwarnings ("ignore::ResourceWarning" )
89115class TestLoadingImagesFromArchiveContainer (BuildIntegBase ):
90116 template = "template_loadable_image.yaml"
91117
92118 FUNCTION_LOGICAL_ID = "ImageFunction"
93119
120+ def setUp (self ):
121+ super ().setUp ()
122+ if self .use_buildkit :
123+ client = ContainerClientFactory .create_client ()
124+ is_available , error_msg = CLIBuildClient .is_available (client .get_runtime_type ())
125+ if not is_available :
126+ self .skipTest (f"Buildkit not available: { error_msg } " )
127+
94128 def test_load_not_an_archive_passthrough (self ):
95129 overrides = {"ImageUri" : "./load_image_archive/this_file_does_not_exist.tar.gz" }
96- cmdlist = self .get_command_list (parameter_overrides = overrides )
130+ cmdlist = self .get_command_list (parameter_overrides = overrides , use_buildkit = self . use_buildkit )
97131 command_result = run_command (cmdlist , cwd = self .working_dir )
98132
99133 self .assertEqual (command_result .process .returncode , 0 )
100134
101135 def test_bad_image_archive_fails (self ):
102136 overrides = {"ImageUri" : "./load_image_archive/error.tar.gz" }
103- cmdlist = self .get_command_list (parameter_overrides = overrides )
137+ cmdlist = self .get_command_list (parameter_overrides = overrides , use_buildkit = self . use_buildkit )
104138 command_result = run_command (cmdlist , cwd = self .working_dir )
105139
106140 self .assertEqual (command_result .process .returncode , 1 )
107141 self .assertIn ("unexpected EOF" , command_result .stderr .decode ())
108142
109143 def test_load_success (self ):
110144 overrides = {"ImageUri" : "./load_image_archive/archive.tar.gz" }
111- cmdlist = self .get_command_list (parameter_overrides = overrides )
145+ cmdlist = self .get_command_list (parameter_overrides = overrides , use_buildkit = self . use_buildkit )
112146 command_result = run_command (cmdlist , cwd = self .working_dir )
113147
114148 self .assertEqual (command_result .process .returncode , 0 )
@@ -139,17 +173,28 @@ def test_load_success(self):
139173 "Skip build tests on windows when running in CI unless overridden" ,
140174)
141175@parameterized_class (
142- ("template" , "prop" ),
176+ ("template" , "prop" , "use_buildkit" ),
143177 [
144- ("template_local_prebuilt_image.yaml" , "ImageUri" ),
145- ("template_cfn_local_prebuilt_image.yaml" , "Code.ImageUri" ),
178+ ("template_local_prebuilt_image.yaml" , "ImageUri" , False ),
179+ ("template_cfn_local_prebuilt_image.yaml" , "Code.ImageUri" , False ),
180+ ("template_local_prebuilt_image.yaml" , "ImageUri" , True ),
181+ ("template_cfn_local_prebuilt_image.yaml" , "Code.ImageUri" , True ),
146182 ],
147183)
184+ @pytest .mark .filterwarnings ("ignore::ResourceWarning" )
148185class TestSkipBuildingFunctionsWithLocalImageUriContainer (BuildIntegBase ):
149186 EXPECTED_FILES_PROJECT_MANIFEST : Set [str ] = set ()
150187
151188 FUNCTION_LOGICAL_ID_IMAGE = "ImageFunction"
152189
190+ def setUp (self ):
191+ super ().setUp ()
192+ if self .use_buildkit :
193+ client = ContainerClientFactory .create_client ()
194+ is_available , error_msg = CLIBuildClient .is_available (client .get_runtime_type ())
195+ if not is_available :
196+ self .skipTest (f"Buildkit not available: { error_msg } " )
197+
153198 @parameterized .expand (["3.8" , "3.9" , "3.10" , "3.11" , "3.12" , "3.13" , "3.14" ])
154199 def test_with_default_requirements (self , runtime ):
155200 _tag = uuid4 ().hex
@@ -165,7 +210,7 @@ def test_with_default_requirements(self, runtime):
165210 "ImageUri" : image_uri ,
166211 "Handler" : "main.handler" ,
167212 }
168- cmdlist = self .get_command_list (parameter_overrides = overrides )
213+ cmdlist = self .get_command_list (parameter_overrides = overrides , use_buildkit = self . use_buildkit )
169214
170215 command_result = run_command (cmdlist , cwd = self .working_dir )
171216 self .assertEqual (command_result .process .returncode , 0 )
@@ -1879,6 +1924,74 @@ def _verify_build_succeeds(self, build_dir):
18791924 self .assertIn ("BuildImageFunction" , build_dir_files )
18801925
18811926
1927+ @skipIf (SKIP_DOCKER_TESTS , SKIP_DOCKER_MESSAGE )
1928+ @parameterized_class (
1929+ ("cached" , "parallel" , "use_custom_build_dir" ),
1930+ [
1931+ (False , False , False ), # Basic
1932+ (True , False , False ), # With Caching
1933+ (False , True , False ), # With parallelism
1934+ (False , False , True ), # With custom build dir
1935+ ],
1936+ )
1937+ @pytest .mark .filterwarnings ("ignore::ResourceWarning" )
1938+ @pytest .mark .tier1
1939+ class TestBuildImageWithBuildkit (BuildIntegBase ):
1940+ """Test building image functions with buildkit"""
1941+
1942+ template = "template_image.yaml"
1943+ function_logical_id = "ImageFunction"
1944+
1945+ def test_build_image_function_with_buildkit (self ):
1946+ client = ContainerClientFactory .create_client ()
1947+ is_available , error_msg = CLIBuildClient .is_available (client .get_runtime_type ())
1948+
1949+ if not is_available :
1950+ self .skipTest (f"Buildkit not available: { error_msg } " )
1951+
1952+ build_dir = self .custom_build_dir if self .use_custom_build_dir else None
1953+
1954+ tag = uuid4 ().hex
1955+ overrides = {
1956+ "Runtime" : "3.12" ,
1957+ "Handler" : "main.handler" ,
1958+ "DockerFile" : "Dockerfile" ,
1959+ "Tag" : tag ,
1960+ }
1961+ cmdlist = self .get_command_list (
1962+ parameter_overrides = overrides ,
1963+ use_buildkit = True ,
1964+ cached = self .cached ,
1965+ parallel = self .parallel ,
1966+ build_dir = build_dir ,
1967+ )
1968+
1969+ command_result = run_command (cmdlist , cwd = self .working_dir )
1970+ self .assertEqual (command_result .process .returncode , 0 )
1971+
1972+ if self .use_custom_build_dir :
1973+ built_template = Path (self .custom_build_dir , "template.yaml" )
1974+ else :
1975+ built_template = self .built_template
1976+
1977+ # Verify image was built
1978+ self ._verify_image_build_artifact (
1979+ built_template ,
1980+ self .function_logical_id ,
1981+ "ImageUri" ,
1982+ f"{ self .function_logical_id .lower ()} :{ tag } " ,
1983+ )
1984+
1985+ # Verify image works
1986+ expected = {"pi" : "3.14" }
1987+ self ._verify_invoke_built_function (
1988+ built_template ,
1989+ self .function_logical_id ,
1990+ self ._make_parameter_override_arg (overrides ),
1991+ expected ,
1992+ )
1993+
1994+
18821995@parameterized_class (
18831996 ("template" , "stack_paths" , "layer_full_path" , "function_full_paths" , "invoke_error_message" ),
18841997 [
0 commit comments