Skip to content

Commit 6e02e3c

Browse files
committed
modified: singularity/build.py
modified: singularity/package.py modified: singularity/utils.py
1 parent 422fda8 commit 6e02e3c

File tree

3 files changed

+67
-38
lines changed

3 files changed

+67
-38
lines changed

singularity/build.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from singularity.api import api_get, api_put, api_post
99
from singularity.boutiques import get_boutiques_json
10-
from singularity.package import build_from_spec
10+
from singularity.package import build_from_spec, package
1111
from singularity.utils import get_installdir, read_file, write_file, download_repo
1212

1313
from googleapiclient.discovery import build
@@ -163,13 +163,22 @@ def run_build(build_dir=None,spec_file=None,repo_url=None,token=None,size=None,b
163163

164164
if os.path.exists(spec_file):
165165
logging.info("Found spec file %s in repository",spec_file)
166-
image_package = build_from_spec(spec=spec_file,
167-
name=params['commit'],
168-
size=params['size'],
169-
sudopw='', # with root should not need sudo
170-
output_folder=build_dir)
171166

172-
# If doesn't error, run google_drive_setup and upload image
167+
image = build_from_spec(spec=spec_file, # default will package the image
168+
size=params['size'],
169+
sudopw='', # with root should not need sudo
170+
output_folder=build_dir,
171+
build_dir=build_dir)
172+
173+
# Package the image
174+
image_package = package(image_path=image,
175+
spec_path=spec_file,
176+
output_folder=build_dir,
177+
sudopw='',
178+
remove_image=True,
179+
verbose=True)
180+
181+
# Upload image to Google Storage
173182
if os.path.exists(image_package):
174183
logging.info("Package %s successfully built",image_package)
175184
dest_dir = "%s/build" %(build_dir)
@@ -187,6 +196,7 @@ def run_build(build_dir=None,spec_file=None,repo_url=None,token=None,size=None,b
187196
bucket = get_bucket(storage_service,bucket_name)
188197

189198
# For each file, upload to storage
199+
# TODO: here we need to skip image / layerize
190200
files = []
191201
for build_file in build_files:
192202
storage_file = upload_file(storage_service,
@@ -196,6 +206,13 @@ def run_build(build_dir=None,spec_file=None,repo_url=None,token=None,size=None,b
196206
files.append(storage_file)
197207

198208

209+
# Upload the package as well
210+
package_file = upload_file(storage_service,
211+
bucket=bucket,
212+
bucket_path=image_path,
213+
file_name=image_package)
214+
files.append(package_file)
215+
199216
# If the user has specified a log file, include with data/response
200217
if logfile != None:
201218
log_file = upload_file(storage_service,

singularity/package.py

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,83 +16,79 @@
1616
import os
1717

1818

19-
def build_from_spec(spec=None,name=None,build_dir=None,size=None,sudopw=None,output_folder=None):
19+
def build_from_spec(spec=None,build_dir=None,size=None,sudopw=None,
20+
output_folder=None,build_folder=False):
2021
'''build_from_spec will build a "spec" file in a "build_dir" and return the directory
2122
:param spec: the spec file, called "Singuarity"
22-
:parma name: the name to call the image, will go under a collection for some library/name
2323
:param build_dir: the directory to build in. If not defined, will use tmpdir.
2424
:param size: the size of the image
2525
:param output_folder: where to output the image package
26+
:param build_folder: "build" the image into a folder instead. Default False
2627
'''
2728
if spec == None:
2829
spec = "Singularity"
2930
if build_dir == None:
3031
build_dir = tempfile.mkdtemp()
3132
# Copy the spec to a temporary directory
3233
spec_path = "%s/%s" %(build_dir,spec)
33-
shutil.copyfile(spec,spec_path)
34+
if not os.path.exists(spec_path):
35+
shutil.copyfile(spec,spec_path)
3436
# If name isn't provided, call it Singularity
35-
if name == None:
36-
name = "Singularity"
37-
image_path = "%s/%s.img" %(build_dir,name)
37+
image_path = "%s/image" %(build_dir)
3838
# Run create image and bootstrap with Singularity command line tool.
3939
if sudopw != None:
4040
cli = Singularity(sudopw=sudopw)
4141
else:
4242
cli = Singularity() # This command will ask the user for sudo
4343
print("\nCreating and boostrapping image...")
44-
cli.create(image_path,size=size)
44+
# Does the user want to "build" into a folder or image?
45+
if build_folder == True:
46+
os.mkdir(image_path)
47+
else:
48+
cli.create(image_path,size=size)
4549
result = cli.bootstrap(image_path=image_path,spec_path=spec_path)
4650
print(result)
47-
# Finally, package the image.
48-
print("\nPacking image...")
49-
zipfile = package(image_path=image_path,
50-
name=name,
51-
output_folder=output_folder,
52-
spec_path=spec_path,
53-
verbose=True,
54-
S=cli)
55-
return zipfile
51+
# Rename the image
52+
version = get_image_hash(image_path)
53+
final_path = "%s/%s" %(build_dir,version)
54+
os.rename(image_path,final_path)
55+
return final_path
5656

5757

58-
def package(image_path,name=None,spec_path=None,output_folder=None,runscript=True,
59-
software=True,remove_image=False,verbose=False,S=None):
58+
def package(image_path,spec_path=None,output_folder=None,runscript=True,
59+
software=True,remove_image=False,verbose=False,S=None,sudopw=None):
6060
'''package will take an image and generate a zip (including the image
6161
to a user specified output_folder.
6262
:param image_path: full path to singularity image file
63-
:param name: the name for the image to be included with the collection
6463
:param runscript: if True, will extract runscript to include in package as runscript
6564
:param software: if True, will extract files.txt and folders.txt to package
6665
:param remove_image: if True, will not include original image in package (default,False)
6766
:param verbose: be verbose when using singularity --export (default,False)
6867
:param S: the Singularity object (optional) will be created if not required.
6968
'''
69+
# Run create image and bootstrap with Singularity command line tool.
7070
if S == None:
71-
S = Singularity(verbose=verbose)
71+
if sudopw != None:
72+
S = Singularity(sudopw=sudopw,verbose=verbose)
73+
else:
74+
S = Singularity(verbose=verbose) # This command will ask the user for sudo
7275
tmptar = S.export(image_path=image_path,pipe=False)
7376
tar = tarfile.open(tmptar)
7477
members = tar.getmembers()
7578
image_name = os.path.basename(image_path)
7679
zip_name = "%s.zip" %(image_name.replace(" ","_"))
77-
7880
# Include the image in the package?
7981
if remove_image:
8082
to_package = dict()
8183
else:
8284
to_package = {"files":[image_path]}
83-
if name != None:
84-
image_name = name
85-
to_package['NAME'] = format_container_name(image_name)
86-
8785
# If the specfile is provided, it should also be packaged
8886
if spec_path != None:
8987
singularity_spec = "".join(read_file(spec_path))
9088
to_package['Singularity'] = singularity_spec
91-
9289
# Package the image with an md5 sum as VERSION
9390
version = get_image_hash(image_path)
9491
to_package["VERSION"] = version
95-
9692
# Look for runscript
9793
if runscript == True:
9894
try:
@@ -101,21 +97,17 @@ def package(image_path,name=None,spec_path=None,output_folder=None,runscript=Tru
10197
runscript = runscript_file.read()
10298
to_package["runscript"] = runscript
10399
print("Found runscript!")
104-
105100
except KeyError:
106101
print("No runscript found in image!")
107-
108102
if software == True:
109103
print("Adding software list to package!")
110104
files = [x.path for x in members if x.isfile()]
111105
folders = [x.path for x in members if x.isdir()]
112106
to_package["files.txt"] = files
113107
to_package["folders.txt"] = folders
114-
115108
# Do zip up here - let's start with basic structures
116109
zipfile = zip_up(to_package,zip_name=zip_name,output_folder=output_folder)
117110
print("Package created at %s" %(zipfile))
118-
119111
# return package to user
120112
return zipfile
121113

singularity/utils.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,26 @@ def run_command(cmd,error_message=None,sudopw=None,suppress=False):
108108
## FILE OPERATIONS #########################################################
109109
############################################################################
110110

111+
def zip_dir(zip_dir, zip_name, output_folder=None):
112+
'''zip_dir will zip up and entire zip directory
113+
:param folder_path: the folder to zip up
114+
:param zip_name: the name of the zip to return
115+
:output_folder:
116+
'''
117+
tmpdir = tempfile.mkdtemp()
118+
output_zip = "%s/%s" %(tmpdir,zip_name)
119+
zf = zipfile.ZipFile(output_zip, "w", zipfile.ZIP_DEFLATED, allowZip64=True)
120+
for root, dirs, files in os.walk(zip_dir):
121+
for file in files:
122+
zf.write(os.path.join(root, file))
123+
zf.close()
124+
if output_folder != None:
125+
shutil.copyfile(output_zip,"%s/%s"%(output_folder,zip_name))
126+
shutil.rmtree(tmpdir)
127+
output_zip = "%s/%s"%(output_folder,zip_name)
128+
return output_zip
129+
130+
111131
def zip_up(file_list,zip_name,output_folder=None):
112132
'''zip_up will zip up some list of files into a package (.zip)
113133
:param file_list: a list of files to include in the zip.

0 commit comments

Comments
 (0)