4444import tempfile
4545import shutil
4646import json
47+ import sys
4748import os
4849import re
4950
@@ -101,13 +102,41 @@ def help(self,command=None,stdout=True):
101102 return help
102103
103104
104- def println (self ,output ):
105- '''print will print the output, given that quiet is not True
105+ def println (self ,output ,quiet = False ):
106+ '''print will print the output, given that quiet is not True. This
107+ function also serves to convert output in bytes to utf-8
106108 '''
107- if self .quiet is False :
108- if isinstance (output ,bytes ):
109- output = output .decode ('utf-8' )
109+ if isinstance (output ,bytes ):
110+ output = output .decode ('utf-8' )
111+
112+ if self .quiet is False and quiet is False :
110113 print (output )
114+ return output
115+
116+
117+ def bootstrap (self ,image_path ,spec_path ):
118+ '''create will bootstrap an image using a spec
119+ :param image_path: full path to image
120+ :param spec_path: full path to the spec file (Singularity)
121+ '''
122+ if self .debug == True :
123+ cmd = ['singularity' ,'--debug' ,'bootstrap' ,image_path ,spec_path ]
124+ else :
125+ cmd = ['singularity' ,'bootstrap' ,image_path ,spec_path ]
126+ output = self .run_command (cmd ,sudo = True )
127+ output = self .println (output )
128+ return image_path
129+
130+
131+ def compress (self ,image_path ):
132+ '''compress will (properly) compress an image'''
133+ if os .path .exists (image_path ):
134+ compressed_image = "%s.gz" % image_path
135+ os .system ('gzip -c -9 %s > %s' % (image_path ,compressed_image ))
136+ return compressed_image
137+ else :
138+ bot .logger .error ("Cannot find image %s" ,image_path )
139+ return None
111140
112141
113142 def create (self ,image_path ,size = None ,sudo = False ):
@@ -124,24 +153,21 @@ def create(self,image_path,size=None,sudo=False):
124153 else :
125154 cmd = ['singularity' ,'create' ,'--size' ,str (size ),image_path ]
126155 output = self .run_command (cmd ,sudo = sudo )
127- self .println (output )
156+ output = self .println (output )
128157 if os .path .exists (image_path ):
129158 return image_path
130159 return None
131160
132161
133- def bootstrap ( self , image_path , spec_path ):
134- '''create will bootstrap an image using a spec
135- :param image_path: full path to image
136- :param spec_path: full path to the spec file (Singularity)
137- '''
138- if self . debug == True :
139- cmd = [ 'singularity' , '--debug' , 'bootstrap' , image_path , spec_path ]
162+
163+ def decompress ( self , image_path ):
164+ '''decompress will (properly) decompress an image'''
165+ if os . path . exists ( image_path ):
166+ extracted_file = image_path . replace ( '.gz' , '' )
167+ os . system ( 'gzip -d -f %s' % image_path )
168+ return extracted_file
140169 else :
141- cmd = ['singularity' ,'bootstrap' ,image_path ,spec_path ]
142- output = self .run_command (cmd ,sudo = True )
143- self .println (output )
144- return image_path
170+ bot .logger .error ("Cannot find image %s" ,image_path )
145171
146172
147173 def execute (self ,image_path ,command ,writable = False ,contain = False ):
@@ -205,42 +231,78 @@ def importcmd(self,image_path,input_source):
205231 '''
206232 cmd = ['singularity' ,'import' ,image_path ,input_source ]
207233 output = self .run_command (cmd ,sudo = False )
208- self .println (output )
234+ output = self .println (output )
209235 return image_path
210236
211237
212- def pull (self ,image_path ,pull_folder = None ,name_by = None ):
238+ def inspect (self ,image_path ,json = True ,labels = True ,
239+ runscript = True ,test = True ,deffile = True ,
240+ environment = True ,quiet = False ):
241+ '''inspect will show labels, defile, runscript, and tests for an image
242+ :param image_path: path of image to inspect
243+ :param json: print json instead of raw text (default True)
244+ :param labels: show labels (default True):
245+ :param runscript: show runscript (default True)
246+ :param test: show test file (default True)
247+ :param environment: show environment (default True)
248+ '''
249+ cmd = ['singularity' ,'--quiet' ,'inspect' ]
250+ options = locals ()
251+ acceptable = ['environment' ,'json' ,'deffile' ,'labels' ,'runscript' ,'test' ]
252+ for key ,option in options .items ():
253+ if key in acceptable :
254+ if option is True :
255+ cmd .append ('--%s' % (key ))
256+
257+ cmd .append (image_path )
258+ output = self .run_command (cmd )
259+ output = self .println (output ,quiet = quiet )
260+ return output
261+
262+
263+ def pull (self ,image_path ,pull_folder = None ,
264+ name_by_hash = False ,
265+ name_by_commit = False ,
266+ image_name = None ):
213267 '''pull will pull a singularity hub image
214268 :param image_path: full path to image
215269 :param name_by: can be one of commit or hash, default is by image name
216270 '''
217- if name_by is None :
218- name_by = "name"
219- name_by = name_by . lower ()
271+ if image_name is not None :
272+ name_by_hash = False
273+ name_by_commit = False
220274
221275 if pull_folder is not None :
222276 os .environ ['SINGULARITY_PULLFOLDER' ] = pull_folder
223277
224- if not image_path .startswith ('shub://' ):
225- bot .logger .error ("pull is only valid for the shub://uri , %s is invalid." ,image_name )
278+ if not image_path .startswith ('shub://' ) and not image_path . startswith ( 'docker://' ) :
279+ bot .logger .error ("pull is only valid for docker and shub, %s is invalid." ,image_name )
226280 sys .exit (1 )
227281
228282 if self .debug == True :
229283 cmd = ['singularity' ,'--debug' ,'pull' ]
230284 else :
231285 cmd = ['singularity' ,'pull' ]
232286
233- if name_by in ['name' ,'commit' ,'hash' ]:
234- bot .logger .debug ("user specified naming pulled image by %s" ,name_by )
235- name_by = "--%s " % name_by
236- cmd .append (name_by )
287+ if image_path .startswith ('shub://' ):
288+ if image_name is not None :
289+ bot .logger .debug ("user specified naming pulled image %s" ,image_name )
290+ cmd = cmd + ["--name" ,image_name ]
291+ elif name_by_commit is True :
292+ bot .logger .debug ("user specified naming by commit." )
293+ cmd .append ("--commit" )
294+ elif name_by_hash is True :
295+ bot .logger .debug ("user specified naming by hash." )
296+ cmd .append ("--hash" )
297+
298+ elif image_path .startswith ('docker://' ):
299+ if image_name is not None :
300+ bot .logger .debug ("user specified name of image as %s" ,image_name )
301+ cmd = cmd + ["--name" ,image_name ]
237302
238303 cmd .append (image_path )
239-
240304 output = self .run_command (cmd )
241- self .println (output )
242- if isinstance (output ,bytes ):
243- output = output .decode ('utf-8' )
305+ output = self .println (output ,quiet = True )
244306 return output .split ("Container is at:" )[- 1 ].strip ('\n ' ).strip ()
245307
246308
@@ -266,8 +328,7 @@ def run(self,image_path,args=None,writable=False,contain=False):
266328 cmd = cmd + args
267329
268330 result = self .run_command (cmd ,sudo = sudo )
269- if isinstance (result ,bytes ):
270- result = result .decode ('utf-8' )
331+ result = self .println (result ,quiet = True )
271332 result = result .strip ('\n ' )
272333 try :
273334 result = json .loads (result )
@@ -281,8 +342,7 @@ def get_labels(self,image_path):
281342 '''
282343 cmd = ['singularity' ,'exec' ,image_path ,'cat' ,'/.singularity/labels.json' ]
283344 labels = self .run_command (cmd )
284- if isinstance (labels ,bytes ):
285- labels = labels .decode ('utf-8' )
345+ labels = self .println (labels ,quiet = True )
286346 if len (labels ) > 0 :
287347 return json .loads (labels )
288348 return labels
@@ -302,13 +362,11 @@ def get_args(self,image_path):
302362 return args
303363
304364
305- def add_flags (self ,cmd ,writable ,contain ):
365+ def add_flags (self ,cmd ,writable = False ,contain = False ):
306366 '''check_args is a general function for adding flags to a command list
307367 :param writable: adds --writable
308368 :param contain: adds --contain
309- '''
310-
311- # Does the user want to make the container writeable?
369+ '''
312370 if writable == True :
313371 cmd .append ('--writable' )
314372
0 commit comments