<s> from harpoon . option_spec . image_objs import Volumes , Context <EOL> from harpoon . ship . builders . normal import NormalBuilder <EOL> from harpoon . ship . builders . base import BuilderBase <EOL> from harpoon . ship . runner import Runner <EOL> from docker . errors import APIError as DockerAPIError <EOL> from input_algorithms . spec_base import NotSpecified <EOL> from contextlib import contextmanager <EOL> import logging <EOL> import uuid <EOL> import sys <EOL> import six <EOL> log = logging . getLogger ( "<STR_LIT>" ) <EOL> class PersistenceBuilder ( BuilderBase ) : <EOL> def build ( self , conf , context , stream ) : <EOL> """<STR_LIT>""" <EOL> existing_image = None <EOL> for image in conf . harpoon . docker_context . images ( ) : <EOL> if "<STR_LIT>" . format ( conf . image_name ) in image [ "<STR_LIT>" ] : <EOL> existing_image = image [ '<STR_LIT>' ] <EOL> test_image_name = None <EOL> if existing_image : <EOL> log . info ( "<STR_LIT>" ) <EOL> cached , test_image_name = self . make_test_image ( conf , context , stream ) <EOL> if cached : <EOL> log . info ( "<STR_LIT>" . format ( existing_image ) ) <EOL> return True <EOL> try : <EOL> self . make_image ( conf , context , stream , existing_image ) <EOL> except Exception as error : <EOL> exc_info = sys . exc_info ( ) <EOL> try : <EOL> if test_image_name : <EOL> conf . harpoon . docker_context . remove_image ( test_image_name ) <EOL> except Exception as inner_error : <EOL> log . exception ( inner_error ) <EOL> six . reraise ( * exc_info ) <EOL> return False <EOL> def make_test_image ( self , conf , context , stream ) : <EOL> docker_file = conf . persistence . make_test_dockerfile ( conf . docker_file ) <EOL> with self . build_with_altered_context ( "<STR_LIT>" , conf , context , stream , docker_file , tag = True ) as ( test_conf , cached ) : <EOL> pass <EOL> return cached , test_conf . image_name <EOL> @ contextmanager <EOL> def build_with_altered_context ( self , name , conf , context , stream , dockerfile , volumes_from = None , command = None , tag = False ) : <EOL> conf_image_name = conf . prefixed_image_name <EOL> new_conf = conf . clone ( ) <EOL> if name is not None : <EOL> if tag : <EOL> new_name = "<STR_LIT>" . format ( conf . prefixed_image_name , name ) <EOL> else : <EOL> new_name = None <EOL> new_conf . name = name <EOL> new_conf . image_name = new_name <EOL> new_conf . container_id = None <EOL> new_conf . container_name = "<STR_LIT>" . format ( new_name , str ( uuid . uuid1 ( ) ) ) . replace ( "<STR_LIT:/>" , "<STR_LIT>" ) <EOL> else : <EOL> new_name = conf . image_name <EOL> new_conf . bash = NotSpecified <EOL> new_conf . command = NotSpecified <EOL> if command is not None : <EOL> new_conf . bash = command <EOL> if volumes_from : <EOL> new_conf . volumes = new_conf . volumes . clone ( ) <EOL> new_conf . volumes . share_with = list ( conf . volumes . share_with ) + volumes_from <EOL> if context is not None : <EOL> maker = context . clone_with_new_dockerfile ( conf , dockerfile ) <EOL> else : <EOL> new_conf . context = Context ( enabled = False , parent_dir = new_conf . context . parent_dir ) <EOL> maker = new_conf . make_context ( docker_file = dockerfile ) <EOL> @ contextmanager <EOL> def remover ( conf ) : <EOL> yield <EOL> if new_name is not None : <EOL> remover = self . remove_replaced_images <EOL> with remover ( new_conf ) : <EOL> cached = False <EOL> with maker as new_context : <EOL> cached = NormalBuilder ( new_name ) . build ( new_conf , new_context , stream ) <EOL> new_conf . image_name = stream . current_container <EOL> yield new_conf , cached <EOL> def run_with_altered_context ( self , name , conf , context , stream , dockerfile , volumes_from = None , tag = None , detach = False , command = None ) : <EOL> """<STR_LIT>""" <EOL> with self . build_with_altered_context ( name , conf , context , stream , dockerfile , volumes_from = volumes_from , command = command ) as ( new_conf , _ ) : <EOL> if detach : <EOL> Runner ( ) . run_container ( new_conf , { } , detach = True , dependency = True ) <EOL> else : <EOL> Runner ( ) . run_container ( new_conf , { } , detach = False , dependency = False , tag = True ) <EOL> new_conf . image_name = new_conf . committed <EOL> return new_conf <EOL> def make_image ( self , conf , context , stream , existing_image ) : <EOL> """<STR_LIT>""" <EOL> if not existing_image : <EOL> docker_file = conf . persistence . make_first_dockerfile ( conf . docker_file ) <EOL> with self . build_with_altered_context ( None , conf , context , stream , docker_file ) : <EOL> pass <EOL> self . make_test_image ( conf , context , stream ) <EOL> return <EOL> first_conf = None <EOL> try : <EOL> docker_file = conf . persistence . make_rerunner_prep_dockerfile ( conf . docker_file , existing_image ) <EOL> first_conf = self . run_with_altered_context ( "<STR_LIT>" <EOL> , conf , context , stream , docker_file , detach = True , command = "<STR_LIT>" <EOL> ) <EOL> log . info ( "<STR_LIT>" . format ( first_conf . image_name ) ) <EOL> docker_file = conf . persistence . make_second_dockerfile ( conf . docker_file ) <EOL> second_image_conf = self . run_with_altered_context ( "<STR_LIT>" <EOL> , conf , context , stream , docker_file , volumes_from = [ first_conf . container_id ] <EOL> ) <EOL> log . info ( "<STR_LIT>" . format ( second_image_conf . image_name ) ) <EOL> docker_file = conf . persistence . make_final_dockerfile ( conf . docker_file , second_image_conf . image_name ) <EOL> with self . build_with_altered_context ( None , conf , None , stream , docker_file ) : <EOL> pass <EOL> finally : <EOL> if first_conf : <EOL> Runner ( ) . stop_container ( first_conf , remove_volumes = True ) <EOL> try : <EOL> conf . harpoon . docker_context . remove_image ( first_conf . image_name ) <EOL> except DockerAPIError as error : <EOL> log . error ( error ) </s>
