Skip to content

Commit 90a510f

Browse files
committed
updating tests to include inspect, this will close #67
1 parent 3174a9b commit 90a510f

File tree

2 files changed

+120
-42
lines changed

2 files changed

+120
-42
lines changed

singularity/cli.py

Lines changed: 92 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,41 @@ def help(self,command=None,stdout=True):
101101
return help
102102

103103

104-
def println(self,output):
105-
'''print will print the output, given that quiet is not True
104+
def println(self,output,quiet=False):
105+
'''print will print the output, given that quiet is not True. This
106+
function also serves to convert output in bytes to utf-8
106107
'''
107-
if self.quiet is False:
108-
if isinstance(output,bytes):
109-
output = output.decode('utf-8')
108+
if isinstance(output,bytes):
109+
output = output.decode('utf-8')
110+
111+
if self.quiet is False and quiet is False:
110112
print(output)
113+
return output
114+
115+
116+
def bootstrap(self,image_path,spec_path):
117+
'''create will bootstrap an image using a spec
118+
:param image_path: full path to image
119+
:param spec_path: full path to the spec file (Singularity)
120+
'''
121+
if self.debug == True:
122+
cmd = ['singularity','--debug','bootstrap',image_path,spec_path]
123+
else:
124+
cmd = ['singularity','bootstrap',image_path,spec_path]
125+
output = self.run_command(cmd,sudo=True)
126+
output = self.println(output)
127+
return image_path
128+
129+
130+
def compress(self,image_path):
131+
'''compress will (properly) compress an image'''
132+
if os.path.exists(image_path):
133+
compressed_image = "%s.gz" %image_path
134+
os.system('gzip -c -9 %s > %s' %(image_path,compressed_image))
135+
return compressed_image
136+
else:
137+
bot.logger.error("Cannot find image %s",image_path)
138+
return None
111139

112140

113141
def create(self,image_path,size=None,sudo=False):
@@ -124,24 +152,21 @@ def create(self,image_path,size=None,sudo=False):
124152
else:
125153
cmd = ['singularity','create','--size',str(size),image_path]
126154
output = self.run_command(cmd,sudo=sudo)
127-
self.println(output)
155+
output = self.println(output)
128156
if os.path.exists(image_path):
129157
return image_path
130158
return None
131159

132160

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]
161+
162+
def decompress(self,image_path):
163+
'''decompress will (properly) decompress an image'''
164+
if os.path.exists(image_path):
165+
extracted_file = image_path.replace('.gz','')
166+
os.system('gzip -d -f %s' %image_path)
167+
return extracted_file
140168
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
169+
bot.logger.error("Cannot find image %s",image_path)
145170

146171

147172
def execute(self,image_path,command,writable=False,contain=False):
@@ -205,42 +230,74 @@ def importcmd(self,image_path,input_source):
205230
'''
206231
cmd = ['singularity','import',image_path,input_source]
207232
output = self.run_command(cmd,sudo=False)
208-
self.println(output)
233+
output = self.println(output)
209234
return image_path
210235

211236

212-
def pull(self,image_path,pull_folder=None,name_by=None):
237+
def inspect(self,image_path,json=True,labels=True,
238+
runscript=True,test=True,deffile=True,
239+
environment=True,quiet=False):
240+
'''inspect will show labels, defile, runscript, and tests for an image
241+
:param image_path: path of image to inspect
242+
:param json: print json instead of raw text (default True)
243+
:param labels: show labels (default True):
244+
:param runscript: show runscript (default True)
245+
:param test: show test file (default True)
246+
:param environment: show environment (default True)
247+
'''
248+
cmd = ['singularity','--quiet','inspect']
249+
options = locals()
250+
acceptable = ['environment','json','deffile','labels','runscript','test']
251+
for key,option in options.items():
252+
if key in acceptable:
253+
if option is True:
254+
cmd.append('--%s' %(key))
255+
256+
cmd.append(image_path)
257+
output = self.run_command(cmd)
258+
output = self.println(output,quiet=quiet)
259+
return output
260+
261+
262+
def pull(self,image_path,pull_folder=None,name_by=None,image_name=None):
213263
'''pull will pull a singularity hub image
214264
:param image_path: full path to image
215265
:param name_by: can be one of commit or hash, default is by image name
216266
'''
217-
if name_by is None:
218-
name_by = "name"
219-
name_by = name_by.lower()
267+
if image_name is not None:
268+
name_by = None
269+
if name_by is not None:
270+
name_by = name_by.lower()
220271

221272
if pull_folder is not None:
222273
os.environ['SINGULARITY_PULLFOLDER'] = pull_folder
223274

224-
if not image_path.startswith('shub://'):
225-
bot.logger.error("pull is only valid for the shub://uri, %s is invalid.",image_name)
275+
if not image_path.startswith('shub://') or not image_path.startswith('docker://'):
276+
bot.logger.error("pull is only valid for docker and shub, %s is invalid.",image_name)
226277
sys.exit(1)
227278

228279
if self.debug == True:
229280
cmd = ['singularity','--debug','pull']
230281
else:
231282
cmd = ['singularity','pull']
232283

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)
284+
if image_path.startswith('shub://'):
285+
if name_by in ['commit','hash']:
286+
bot.logger.debug("user specified naming pulled image by %s",name_by)
287+
name_by = "--%s " %name_by
288+
cmd.append(name_by)
289+
elif image_name is not None:
290+
name_by = "--name %s" %(image_name)
291+
292+
elif image_path.startswith('docker://'):
293+
if image_name is not None:
294+
bot.logger.debug("user specified name of image as %s",image_name)
295+
name_by = "--name %s" %(image_name)
237296

238297
cmd.append(image_path)
239298

240299
output = self.run_command(cmd)
241-
self.println(output)
242-
if isinstance(output,bytes):
243-
output = output.decode('utf-8')
300+
output = self.println(output,quiet=True)
244301
return output.split("Container is at:")[-1].strip('\n').strip()
245302

246303

@@ -266,8 +323,7 @@ def run(self,image_path,args=None,writable=False,contain=False):
266323
cmd = cmd + args
267324

268325
result = self.run_command(cmd,sudo=sudo)
269-
if isinstance(result,bytes):
270-
result = result.decode('utf-8')
326+
result = self.println(result,quiet=True)
271327
result = result.strip('\n')
272328
try:
273329
result = json.loads(result)
@@ -281,8 +337,7 @@ def get_labels(self,image_path):
281337
'''
282338
cmd = ['singularity','exec',image_path,'cat','/.singularity/labels.json']
283339
labels = self.run_command(cmd)
284-
if isinstance(labels,bytes):
285-
labels = labels.decode('utf-8')
340+
labels = self.println(labels,quiet=True)
286341
if len(labels) > 0:
287342
return json.loads(labels)
288343
return labels
@@ -302,13 +357,11 @@ def get_args(self,image_path):
302357
return args
303358

304359

305-
def add_flags(self,cmd,writable,contain):
360+
def add_flags(self,cmd,writable=False,contain=False):
306361
'''check_args is a general function for adding flags to a command list
307362
:param writable: adds --writable
308363
:param contain: adds --contain
309-
'''
310-
311-
# Does the user want to make the container writeable?
364+
'''
312365
if writable == True:
313366
cmd.append('--writable')
314367

singularity/tests/test_client.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ def setUp(self):
4747
self.pwd = get_installdir()
4848
self.cli = Singularity()
4949
self.tmpdir = tempfile.mkdtemp()
50-
self.image1 = "%s/tests/data/busybox-2016-02-16.img" %(self.pwd)
51-
self.image2 = "%s/tests/data/cirros-2016-01-04.img" %(self.pwd)
5250

5351
def tearDown(self):
5452
shutil.rmtree(self.tmpdir)
@@ -92,6 +90,32 @@ def test_exec(self):
9290
#self.assertTrue(len(result)>0)
9391

9492

93+
def test_inspect(self):
94+
print("Testing client.inspect command")
95+
container = create_container(do_import=True)
96+
result = self.cli.inspect(container,quiet=True)
97+
labels = json.loads(result)
98+
self.assertTrue('data' in labels)
99+
100+
101+
def test_run(self):
102+
print("Testing client.run command")
103+
container = create_container(do_import=True)
104+
result = self.cli.run(container)
105+
self.assertEqual(result,'')
106+
107+
108+
def test_exec(self):
109+
print('Testing client.execute command')
110+
container = create_container(do_import=True)
111+
result = self.cli.execute(container,'ls /')
112+
print(result)
113+
#if isinstance(result,bytes):
114+
# result = result.decode('utf-8')
115+
#self.assertTrue(len(result)>0)
116+
117+
118+
95119
def test_pull(self):
96120
print("Testing client.pull command")
97121

@@ -125,9 +149,10 @@ def create_container(container=None,do_import=False):
125149
tmpdir = tempfile.mkdtemp()
126150
if container is None:
127151
container = "%s/container.img" %(tmpdir)
152+
container = cli.create(container)
128153
if do_import is True:
129154
cli.importcmd(container,'docker://ubuntu')
130-
return cli.create(container)
155+
return container
131156

132157

133158
if __name__ == '__main__':

0 commit comments

Comments
 (0)