def test_generating_tarball(self, temporary_file_patch, tarfile_open_patch): temp_file_mock = Mock() temporary_file_patch.return_value = temp_file_mock tarfile_file_mock = Mock() tarfile_open_patch.return_value.__enter__.return_value = tarfile_file_mock with create_tarball({ "/some/path": "/layer1", "/some/dockerfile/path": "/Dockerfile" }) as acutal: self.assertEqual(acutal, temp_file_mock) tarfile_file_mock.add.assert_called() tarfile_file_mock.add.assert_has_calls( [ call("/some/path", arcname="/layer1"), call("/some/dockerfile/path", arcname="/Dockerfile") ], any_order=True, ) temp_file_mock.flush.assert_called_once() temp_file_mock.seek.assert_called_once_with(0) temp_file_mock.close.assert_called_once() tarfile_open_patch.assert_called_once_with(fileobj=temp_file_mock, mode="w")
def _build_image(self, base_image, docker_tag, layers): """ Builds the image Parameters ---------- base_image str Base Image to use for the new image docker_tag Docker tag (REPOSITORY:TAG) to use when building the image layers list(samcli.commands.local.lib.provider.Layer) List of Layers to be use to mount in the image Returns ------- None Raises ------ samcli.commands.local.cli_common.user_exceptions.ImageBuildException When docker fails to build the image """ dockerfile_content = self._generate_dockerfile(base_image, layers) # Create dockerfile in the same directory of the layer cache dockerfile_name = "dockerfile_" + str(uuid.uuid4()) full_dockerfile_path = Path(self.layer_downloader.layer_cache, dockerfile_name) try: with open(str(full_dockerfile_path), "w") as dockerfile: dockerfile.write(dockerfile_content) tar_paths = {str(full_dockerfile_path): "Dockerfile"} for layer in layers: tar_paths[layer.codeuri] = "/" + layer.name with create_tarball(tar_paths) as tarballfile: try: self.docker_client.images.build( fileobj=tarballfile, custom_context=True, rm=True, tag=docker_tag, pull=not self.skip_pull_image) except (docker.errors.BuildError, docker.errors.APIError): LOG.exception("Failed to build Docker Image") raise ImageBuildException("Building Image failed.") finally: if full_dockerfile_path.exists(): full_dockerfile_path.unlink()
def _build_image(self, base_image, docker_tag, layers, is_debug_go, stream=None): """ Builds the image Parameters ---------- base_image str Base Image to use for the new image docker_tag Docker tag (REPOSITORY:TAG) to use when building the image layers list(samcli.commands.local.lib.provider.Layer) List of Layers to be use to mount in the image Returns ------- None Raises ------ samcli.commands.local.cli_common.user_exceptions.ImageBuildException When docker fails to build the image """ dockerfile_content = self._generate_dockerfile(base_image, layers, is_debug_go) # Create dockerfile in the same directory of the layer cache dockerfile_name = "dockerfile_" + str(uuid.uuid4()) full_dockerfile_path = Path(self.layer_downloader.layer_cache, dockerfile_name) stream_writer = stream or StreamWriter(sys.stderr) try: with open(str(full_dockerfile_path), "w") as dockerfile: dockerfile.write(dockerfile_content) # add dockerfile and rapid source paths tar_paths = {str(full_dockerfile_path): "Dockerfile", self._RAPID_SOURCE_PATH: "/init"} if self._extensions_preview_enabled: tar_paths = {str(full_dockerfile_path): "Dockerfile", self._RAPID_PREVIEW_SOURCE_PATH: "/init"} if is_debug_go: LOG.debug("Adding custom GO Bootstrap to support debugging") tar_paths[self._GO_BOOTSTRAP_PATH] = "/aws-lambda-go" for layer in layers: tar_paths[layer.codeuri] = "/" + layer.name # Set permission for all the files in the tarball to 500(Read and Execute Only) # This is need for systems without unix like permission bits(Windows) while creating a unix image # Without setting this explicitly, tar will default the permission to 666 which gives no execute permission def set_item_permission(tar_info): tar_info.mode = 0o500 return tar_info # Set only on Windows, unix systems will preserve the host permission into the tarball tar_filter = set_item_permission if platform.system().lower() == "windows" else None with create_tarball(tar_paths, tar_filter=tar_filter) as tarballfile: try: resp_stream = self.docker_client.api.build( fileobj=tarballfile, custom_context=True, rm=True, tag=docker_tag, pull=not self.skip_pull_image ) for _ in resp_stream: stream_writer.write(".") stream_writer.flush() stream_writer.write("\n") except (docker.errors.BuildError, docker.errors.APIError) as ex: stream_writer.write("\n") LOG.exception("Failed to build Docker Image") raise ImageBuildException("Building Image failed.") from ex finally: if full_dockerfile_path.exists(): full_dockerfile_path.unlink()
def _build_image(self, base_image, docker_tag, layers, is_debug_go, stream=None): """ Builds the image Parameters ---------- base_image str Base Image to use for the new image docker_tag Docker tag (REPOSITORY:TAG) to use when building the image layers list(samcli.commands.local.lib.provider.Layer) List of Layers to be use to mount in the image Returns ------- None Raises ------ samcli.commands.local.cli_common.user_exceptions.ImageBuildException When docker fails to build the image """ dockerfile_content = self._generate_dockerfile(base_image, layers, is_debug_go) # Create dockerfile in the same directory of the layer cache dockerfile_name = "dockerfile_" + str(uuid.uuid4()) full_dockerfile_path = Path(self.layer_downloader.layer_cache, dockerfile_name) stream_writer = stream or StreamWriter(sys.stderr) try: with open(str(full_dockerfile_path), "w") as dockerfile: dockerfile.write(dockerfile_content) # add dockerfile and rapid source paths tar_paths = { str(full_dockerfile_path): "Dockerfile", self._RAPID_SOURCE_PATH: "/init" } if is_debug_go: LOG.debug("Adding custom GO Bootstrap to support debugging") tar_paths[self._GO_BOOTSTRAP_PATH] = "/aws-lambda-go" for layer in layers: tar_paths[layer.codeuri] = "/" + layer.name with create_tarball(tar_paths) as tarballfile: try: resp_stream = self.docker_client.api.build( fileobj=tarballfile, custom_context=True, rm=True, tag=docker_tag, pull=not self.skip_pull_image) for _ in resp_stream: stream_writer.write(".") stream_writer.flush() stream_writer.write("\n") except (docker.errors.BuildError, docker.errors.APIError): stream_writer.write("\n") LOG.exception("Failed to build Docker Image") raise ImageBuildException("Building Image failed.") finally: if full_dockerfile_path.exists(): full_dockerfile_path.unlink()