def build(self, image_info: ImageInfo): log_file_path = self.prepare_log_file_path(image_info) self.logger.info( "Task %s: Build docker image %s, log file can be found here %s", self._task_id, image_info.get_target_complete_name(), log_file_path) temp_directory = tempfile.mkdtemp( prefix="script_langauge_container_tmp_dir", dir=build_config().temporary_base_directory) try: image_description = image_info.image_description build_context_creator = BuildContextCreator( temp_directory, image_info, log_file_path) build_context_creator.prepare_build_context_to_temp_dir() output_generator = \ self._low_level_client.build(path=temp_directory, nocache=docker_client_config.no_cache, tag=image_info.get_target_complete_name(), rm=True, buildargs=dict(**image_description.transparent_build_arguments, **image_description.image_changing_build_arguments, **docker_build_arguments().secret)) self._handle_output(output_generator, image_info, log_file_path) finally: shutil.rmtree(temp_directory)
def build(self, image_info: ImageInfo): image_info_json = image_info.to_json() if image_info.image_state == ImageState.NEEDS_TO_BE_BUILD.name: yield DockerBuildImageTask(image_name=self.image_name, image_info_json=image_info_json) image_info.image_state = ImageState.WAS_BUILD.name elif image_info.image_state == ImageState.CAN_BE_LOADED.name: yield DockerLoadImageTask(image_name=self.image_name, image_info_json=image_info_json) image_info.image_state = ImageState.WAS_LOADED.name elif image_info.image_state == ImageState.REMOTE_AVAILABLE.name: yield DockerPullImageTask(image_name=self.image_name, image_info_json=image_info_json) image_info.image_state = ImageState.WAS_PULLED.name elif image_info.image_state == ImageState.TARGET_LOCALLY_AVAILABLE.name: image_info.image_state = ImageState.USED_LOCAL.name elif image_info.image_state == ImageState.SOURCE_LOCALLY_AVAILABLE.name: image_info.image_state = ImageState.WAS_TAGED.name docker_client_config().get_client().images.get( image_info.get_source_complete_name()).tag( repository=image_info.target_repository_name, tag=image_info.get_target_complete_tag()) else: raise Exception( "Task %s: Image state %s not supported for image %s", self.task_id, image_info.image_state, image_info.get_target_complete_name())
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.client = docker_client_config().get_client() self.image_info = ImageInfo.from_json(self.image_info_json) self.image_target = DockerImageTarget( self.image_info.target_repository_name, self.image_info.get_target_complete_tag()) self.remove_image()
def _handle_output(self, output_generator, image_info: ImageInfo, log_file_path: luigi.LocalTarget): log_file_path = log_file_path.joinpath("docker-build.log") with BuildLogHandler(log_file_path, self.logger, self._task_id, image_info) as log_hanlder: still_running_logger = StillRunningLogger( self.logger, self._task_id, "build image %s" % image_info.get_target_complete_name()) for log_line in output_generator: still_running_logger.log() log_hanlder.handle_log_line(log_line)
def _handle_output(self, output_generator, image_info: ImageInfo): log_file_path = self.prepate_log_file_path(image_info) with PushLogHandler(log_file_path, self.logger, self.__repr__(), image_info) as log_hanlder: still_running_logger = StillRunningLogger( self.logger, self.__repr__(), "push image %s" % image_info.get_target_complete_name()) for log_line in output_generator: still_running_logger.log() log_hanlder.handle_log_line(log_line)
def write_image_to_file(self, save_file_path: pathlib.Path, image_info: ImageInfo, output_generator: Generator): self.logger.info( f"Task {self.__repr__()}: Saving image {image_info.get_target_complete_name()} to file {save_file_path}") with save_file_path.open("wb") as file: still_running_logger = StillRunningLogger( self.logger, self.__repr__(), "save image %s" % image_info.get_target_complete_name()) for chunk in output_generator: still_running_logger.log() file.write(chunk)
def create_build_task_for_image_info( self, image_info: ImageInfo, shortcut_build: bool = True) -> DockerCreateImageTask: if self.build_with_depenencies_is_requested(image_info, shortcut_build): task_for_image_info = self.create_build_task_with_dependencies(image_info, shortcut_build) return task_for_image_info else: task_for_image_info = \ DockerCreateImageTask( image_name=f"{image_info.target_repository_name}:{image_info.target_tag}", image_info_json=image_info.to_json(indent=None)) return task_for_image_info
def run_task(self): image_info_of_dependencies = DependencyImageInfoCollector( ).get_from_dict_of_inputs(self.input()) image_hash = self._build_context_hasher.generate_image_hash( image_info_of_dependencies) image_info = ImageInfo( source_repository_name=self._source_repository_name, target_repository_name=self._target_repository_name, source_tag=self._source_image_tag, target_tag=self._target_image_tag, hash=image_hash, commit=self.get_commit_id(), build_name=build_config().build_name, depends_on_images=image_info_of_dependencies, image_state=None, image_description=self.image_description) target_image_target = DockerImageTarget( self._target_repository_name, image_info.get_target_complete_tag()) source_image_target = DockerImageTarget( self._source_repository_name, image_info.get_source_complete_tag()) image_state = self.get_image_state(source_image_target, target_image_target, image_info_of_dependencies) image_info.image_state = image_state.name # TODO setter for image_state with self._image_info_target.open("w") as f: f.write(image_info.to_json())
def pull_docker_db_images_if_necassary(self): image_name = "exasol/docker-db" image_tag = "6.0.12-d1" docker_db_image_info = ImageInfo(target_repository_name=image_name, source_repository_name=image_name, source_tag=image_tag, target_tag=image_tag, hash="", commit="", image_description=None) try: self._client.images.get( docker_db_image_info.get_source_complete_name()) except docker.errors.ImageNotFound as e: self.logger.info("Task %s: Pulling docker-db image %s", self.__repr__(), docker_db_image_info.get_source_complete_name()) output_generator = self._low_level_client.pull( docker_db_image_info.source_repository_name, tag=docker_db_image_info.source_tag, stream=True) self._handle_output(output_generator, docker_db_image_info) return docker_db_image_info
def write_output(self, image_info: ImageInfo): with self._save_info_target.open("w") as file: file.write(image_info.get_target_complete_name())
def save_image(self, image_info: ImageInfo, tag_for_save: str, save_file_path: pathlib.Path): self.remove_save_file_if_necassary(save_file_path) image = self._client.images.get(image_info.get_target_complete_name()) generator = image.save(named=tag_for_save) self.write_image_to_file(save_file_path, image_info, generator)
def get_tag_for_save(self, image_info: ImageInfo): tag_for_save = re.sub(DOCKER_HUB_REGISTRY_URL_REGEX, "", image_info.get_target_complete_name()) return tag_for_save
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.image_info = ImageInfo.from_json(self.image_info_json) self._prepare_outputs()
def read_info(self, value) -> ImageInfo: with value[IMAGE_INFO].open("r") as file: return ImageInfo.from_json(file.read())