1717import sys
1818import shutil
1919import abc
20+ from pathlib import Path
2021
2122import docker
22- from tqdm import tqdm
2323from emu .utils import mkdir_p
24-
25-
26- class ProgressTracker (object ):
27- """Tracks progress using tqdm for a set of layers that are pushed."""
28-
29- def __init__ (self ):
30- # This tracks the information for a given layer id.
31- self .progress = {}
32- self .idx = - 1
33-
34- def __del__ (self ):
35- for k in self .progress :
36- self .progress [k ]["tqdm" ].close ()
37-
38- def update (self , entry ):
39- """Update the progress bars given a an entry.."""
40- if "id" not in entry :
41- return
42-
43- identity = entry ["id" ]
44- if identity not in self .progress :
45- self .idx += 1
46- self .progress [identity ] = {
47- "tqdm" : tqdm (total = 0 , position = self .idx , unit = "B" , unit_scale = True ), # The progress bar
48- "total" : 0 , # Total of bytes we are shipping
49- "status" : "" , # Status message.
50- "current" : 0 , # Current of total already send.
51- }
52- prog = self .progress [identity ]
53-
54- total = int (entry .get ("progressDetail" , {}).get ("total" , - 1 ))
55- current = int (entry .get ("progressDetail" , {}).get ("current" , 0 ))
56- if prog ["total" ] != total and total != - 1 :
57- prog ["total" ] = total
58- prog ["tqdm" ].reset (total = total )
59- if prog ["status" ] != entry ["status" ]:
60- prog ["tqdm" ].set_description ("{0} {1}" .format (entry .get ("status" ), identity ))
61- if current != 0 :
62- diff = current - prog ["current" ]
63- prog ["current" ] = current
64- prog ["tqdm" ].update (diff )
24+ from emu .containers .progress_tracker import ProgressTracker
6525
6626
6727class DockerContainer (object ):
@@ -86,25 +46,30 @@ def get_api_client(self):
8646 api_client = docker .APIClient ()
8747 logging .info (api_client .version ())
8848 return api_client
89- except :
90- logging .exception ("Failed to create default client, trying domain socket." , exc_info = True )
49+ except Exception as _err :
50+ logging .exception (
51+ "Failed to create default client, trying domain socket." , exc_info = True
52+ )
9153
9254 api_client = docker .APIClient (base_url = "unix://var/run/docker.sock" )
9355 logging .info (api_client .version ())
9456 return api_client
9557
9658 def push (self ):
9759 image = self .full_name ()
98- print ("Pushing docker image: {}.. be patient this can take a while!" .format (self .full_name ()))
60+ print (
61+ f"Pushing docker image: { self .full_name ()} .. be patient this can take a while!"
62+ )
63+
9964 tracker = ProgressTracker ()
10065 try :
10166 client = docker .from_env ()
10267 result = client .images .push (image , "latest" , stream = True , decode = True )
10368 for entry in result :
10469 tracker .update (entry )
105- self .docker_image ().tag ("{}{}:latest" . format ( self .repo , self .image_name ()) )
106- except :
107- logging .exception ("Failed to push image." , exc_info = True )
70+ self .docker_image ().tag (f" { self .repo } { self .image_name ()} :latest" )
71+ except Exception as err :
72+ logging .error ("Failed to push image due to %s" , err , exc_info = True )
10873 logging .warning ("You can manually push the image as follows:" )
10974 logging .warning ("docker push %s" , image )
11075
@@ -123,24 +88,26 @@ def launch(self, port_map):
12388 detach = True ,
12489 ports = port_map ,
12590 )
126- print ("Launched {} (id:{})" . format ( container .name , container . id ) )
127- print ("docker logs -f {}" . format ( container .name ) )
128- print ("docker stop {}" . format ( container .name ) )
91+ print (f "Launched { container . name } (id:{ container .id } )" )
92+ print (f "docker logs -f { container .name } " )
93+ print (f "docker stop { container .name } " )
12994 return container
130- except :
131- logging .exception ("Unable to run the %s" , image_sha )
95+ except Exception as err :
96+ logging .exception ("Unable to run the %s due to %s " , image . id , err )
13297 print ("Unable to start the container, try running it as:" )
133- print ("./run.sh " , image_sha )
98+ print (f "./run.sh { image . id } " )
13499
135- def create_container (self , dest ):
100+ def create_container (self , dest : Path ):
136101 """Creates the docker container, returning the sha of the container, or None in case of failure."""
137102 identity = None
138103 image_tag = self .full_name ()
139- print ("docker build {} -t {}" . format ( dest , image_tag ) )
104+ print (f "docker build { dest } -t { image_tag } " )
140105 try :
141106 api_client = self .get_api_client ()
142- logging .info ("build(path=%s, tag=%s, rm=True, decode=True)" , dest , image_tag )
143- result = api_client .build (path = dest , tag = image_tag , rm = True , decode = True )
107+ logging .info (
108+ "build(path=%s, tag=%s, rm=True, decode=True)" , dest , image_tag
109+ )
110+ result = api_client .build (path = str (dest .absolute ()), tag = image_tag , rm = True , decode = True )
144111 for entry in result :
145112 if "stream" in entry :
146113 sys .stdout .write (entry ["stream" ])
@@ -149,17 +116,18 @@ def create_container(self, dest):
149116 client = docker .from_env ()
150117 image = client .images .get (identity )
151118 image .tag (self .repo + self .image_name (), "latest" )
152- except :
153- logging .exception ("Failed to create container." , exc_info = True )
119+ except Exception as err :
120+ logging .error ("Failed to create container due to %s." , err , exc_info = True )
154121 logging .warning ("You can manually create the container as follows:" )
155122 logging .warning ("docker build -t %s %s" , image_tag , dest )
156123
157124 return identity
158125
159- def clean (self , dest ):
160- if os . path . exists (dest ):
126+ def clean (self , dest : Path ):
127+ if dest . exists ():
161128 shutil .rmtree (dest )
162- mkdir_p (dest )
129+
130+ dest .mkdir (parents = True )
163131
164132 def pull (self , image , tag ):
165133 """Tries to retrieve the given image and tag.
@@ -173,22 +141,24 @@ def pull(self, image, tag):
173141 for entry in result :
174142 tracker .update (entry )
175143 except :
176- logging .info ("Failed to retrieve image, this is not uncommon." , exc_info = True )
144+ logging .info (
145+ "Failed to retrieve image, this is not uncommon." , exc_info = True
146+ )
177147 return False
178148
179149 return True
180150
181151 def full_name (self ):
182152 if self .repo :
183- return "{}{}:{}" . format ( self .repo , self .image_name (), self .docker_tag ())
153+ return f" { self .repo } { self .image_name ()} : { self .docker_tag ()} "
184154 return (self .image_name (), self .docker_tag ())
185155
186156 def latest_name (self ):
187157 if self .repo :
188- return "{}{ }:{}" . format ( self .repo , self . image_name (), "latest" )
158+ return f" { self . repo } { self . image_name () } :{ self .docker_tag () } "
189159 return (self .image_name (), "latest" )
190160
191- def create_cloud_build_step (self , dest ):
161+ def create_cloud_build_step (self , dest : Path ):
192162 return {
193163 "name" : "gcr.io/cloud-builders/docker" ,
194164 "args" : [
@@ -197,7 +167,7 @@ def create_cloud_build_step(self, dest):
197167 self .full_name (),
198168 "-t" ,
199169 self .latest_name (),
200- os . path . basename ( dest ) ,
170+ dest . absolute (). parent ,
201171 ],
202172 }
203173
@@ -218,7 +188,7 @@ def available(self):
218188 """True if this container image is locally available."""
219189 return self .docker_image () != None
220190
221- def build (self , dest ):
191+ def build (self , dest : Path ):
222192 self .write (dest )
223193 return self .create_container (dest )
224194
@@ -227,7 +197,7 @@ def can_pull(self):
227197 return self .pull (self .image_name (), self .docker_tag ())
228198
229199 @abc .abstractmethod
230- def write (self , destination ):
200+ def write (self , destination : Path ):
231201 """Method responsible for writing the Dockerfile and all necessary files to build a container.
232202
233203 Args:
0 commit comments