20
20
from .errors import WorkflowException
21
21
from .job import ContainerCommandLineJob
22
22
from .loghandler import _logger
23
- from .pathmapper import PathMapper # pylint: disable=unused-import
24
- from .pathmapper import ensure_writable
23
+ from .pathmapper import PathMapper , MapperEnt # pylint: disable=unused-import
24
+ from .pathmapper import ensure_writable , ensure_non_writable
25
25
from .secrets import SecretStore # pylint: disable=unused-import
26
26
from .utils import (DEFAULT_TMP_PREFIX , docker_windows_path_adjust , onWindows ,
27
27
subprocess )
@@ -208,83 +208,85 @@ def get_from_requirements(self,
208
208
209
209
return None
210
210
211
- def add_volumes (self , pathmapper , runtime , secret_store = None ):
212
- # type: (PathMapper, List[Text], SecretStore) -> None
213
- """Append volume mappings to the runtime option list."""
214
-
215
- host_outdir = self .outdir
216
- container_outdir = self .builder .outdir
217
- for _ , vol in pathmapper .items ():
218
- if not vol .staged :
219
- continue
220
- host_outdir_tgt = None # type: Optional[Text]
221
- if vol .target .startswith (container_outdir + "/" ):
222
- host_outdir_tgt = os .path .join (
223
- host_outdir , vol .target [len (container_outdir )+ 1 :])
224
-
225
- if vol .type in ("File" , "Directory" ):
226
- if not vol .resolved .startswith ("_:" ):
227
- _check_docker_machine_path (docker_windows_path_adjust (
228
- vol .resolved ))
229
- runtime .append (u"--volume=%s:%s:ro" % (
230
- docker_windows_path_adjust (vol .resolved ),
231
- docker_windows_path_adjust (vol .target )))
232
- elif vol .type == "WritableFile" :
233
- if self .inplace_update :
234
- runtime .append (u"--volume=%s:%s:rw" % (
235
- docker_windows_path_adjust (vol .resolved ),
236
- docker_windows_path_adjust (vol .target )))
237
- else :
238
- if host_outdir_tgt :
239
- shutil .copy (vol .resolved , host_outdir_tgt )
240
- ensure_writable (host_outdir_tgt )
241
- else :
242
- raise WorkflowException (
243
- "Unable to compute host_outdir_tgt for "
244
- "WriteableFile." )
245
- elif vol .type == "WritableDirectory" :
246
- if vol .resolved .startswith ("_:" ):
247
- if host_outdir_tgt :
248
- if not os .path .exists (host_outdir_tgt ):
249
- os .makedirs (host_outdir_tgt , 0o0755 )
250
- else :
251
- raise WorkflowException (
252
- "Unable to compute host_outdir_tgt for "
253
- "WritableDirectory." )
254
- else :
255
- if self .inplace_update :
256
- runtime .append (u"--volume=%s:%s:rw" % (
257
- docker_windows_path_adjust (vol .resolved ),
258
- docker_windows_path_adjust (vol .target )))
259
- else :
260
- if host_outdir_tgt :
261
- shutil .copytree (vol .resolved , host_outdir_tgt )
262
- ensure_writable (host_outdir_tgt )
263
- else :
264
- raise WorkflowException (
265
- "Unable to compute host_outdir_tgt for "
266
- "WritableDirectory." )
267
- elif vol .type == "CreateFile" :
268
- if secret_store :
269
- contents = secret_store .retrieve (vol .resolved )
270
- else :
271
- contents = vol .resolved
272
- if host_outdir_tgt :
273
- dirname = os .path .dirname (host_outdir_tgt )
274
- if not os .path .exists (dirname ):
275
- os .makedirs (dirname , 0o0755 )
276
- with open (host_outdir_tgt , "wb" ) as file_literal :
277
- file_literal .write (contents .encode ("utf-8" ))
211
+ @staticmethod
212
+ def append_volume (runtime , source , target , writable = False ):
213
+ # type: (List[Text], Text, Text, bool) -> None
214
+ """Add binding arguments to the runtime list."""
215
+ runtime .append (u"--volume={}:{}:{}" .format (
216
+ docker_windows_path_adjust (source ),
217
+ docker_windows_path_adjust (target ), "rw" if writable else "ro" ))
218
+
219
+ def add_file_or_directory_volume (self ,
220
+ runtime , # type: List[Text]
221
+ volume , # type: MapperEnt
222
+ host_outdir_tgt # type: Optional[Text]
223
+ ): # type: (...) -> None
224
+ """Append volume a file/dir mapping to the runtime option list."""
225
+ if not volume .resolved .startswith ("_:" ):
226
+ _check_docker_machine_path (docker_windows_path_adjust (
227
+ volume .resolved ))
228
+ self .append_volume (runtime , volume .resolved , volume .target )
229
+
230
+ def add_writable_file_volume (self ,
231
+ runtime , # type: List[Text]
232
+ volume , # type: MapperEnt
233
+ host_outdir_tgt # type: Optional[Text]
234
+ ): # type: (...) -> None
235
+ """Append a writable file mapping to the runtime option list."""
236
+ if self .inplace_update :
237
+ self .append_volume (runtime , volume .resolved , volume .target ,
238
+ writable = True )
239
+ else :
240
+ if host_outdir_tgt :
241
+ # shortcut, just copy to the output directory
242
+ # which is already going to be mounted
243
+ shutil .copy (volume .resolved , host_outdir_tgt )
244
+ else :
245
+ tmpdir = tempfile .mkdtemp (dir = self .tmpdir )
246
+ file_copy = os .path .join (
247
+ tmpdir , os .path .basename (volume .resolved ))
248
+ shutil .copy (volume .resolved , file_copy )
249
+ self .append_volume (runtime , file_copy , volume .target ,
250
+ writable = True )
251
+ ensure_writable (host_outdir_tgt or file_copy )
252
+
253
+ def add_writable_directory_volume (self ,
254
+ runtime , # type: List[Text]
255
+ volume , # type: MapperEnt
256
+ host_outdir_tgt # type: Optional[Text]
257
+ ): # type: (...) -> None
258
+ """Append a writable directory mapping to the runtime option list."""
259
+ if volume .resolved .startswith ("_:" ):
260
+ # Synthetic directory that needs creating first
261
+ if not host_outdir_tgt :
262
+ new_dir = os .path .join (
263
+ tempfile .mkdtemp (dir = self .tmpdir ),
264
+ os .path .basename (volume .target ))
265
+ self .append_volume (runtime , new_dir , volume .target ,
266
+ writable = True )
267
+ elif not os .path .exists (host_outdir_tgt ):
268
+ os .makedirs (host_outdir_tgt , 0o0755 )
269
+ else :
270
+ if self .inplace_update :
271
+ self .append_volume (runtime , volume .resolved , volume .target ,
272
+ writable = True )
273
+ else :
274
+ if not host_outdir_tgt :
275
+ tmpdir = tempfile .mkdtemp (dir = self .tmpdir )
276
+ new_dir = os .path .join (
277
+ tmpdir , os .path .basename (volume .resolved ))
278
+ shutil .copytree (volume .resolved , new_dir )
279
+ self .append_volume (
280
+ runtime , new_dir , volume .target ,
281
+ writable = True )
278
282
else :
279
- tmp_fd , createtmp = tempfile .mkstemp (dir = self .tmpdir )
280
- with os .fdopen (tmp_fd , "wb" ) as file_literal :
281
- file_literal .write (contents .encode ("utf-8" ))
282
- runtime .append (u"--volume=%s:%s:rw" % (
283
- docker_windows_path_adjust (os .path .realpath (createtmp )),
284
- vol .target ))
283
+ shutil .copytree (volume .resolved , host_outdir_tgt )
284
+ ensure_writable (host_outdir_tgt or new_dir )
285
285
286
286
def create_runtime (self , env , runtimeContext ):
287
287
# type: (MutableMapping[Text, Text], RuntimeContext) -> List
288
+ any_path_okay = self .builder .get_requirement ("DockerRequirement" )[1 ] \
289
+ or False
288
290
user_space_docker_cmd = runtimeContext .user_space_docker_cmd
289
291
if user_space_docker_cmd :
290
292
if 'udocker' in user_space_docker_cmd and not runtimeContext .debug :
@@ -302,9 +304,12 @@ def create_runtime(self, env, runtimeContext):
302
304
runtime .append (u"--volume=%s:%s:rw" % (
303
305
docker_windows_path_adjust (os .path .realpath (self .tmpdir )), "/tmp" ))
304
306
305
- self .add_volumes (self .pathmapper , runtime , secret_store = runtimeContext .secret_store )
307
+ self .add_volumes (self .pathmapper , runtime , any_path_okay = True ,
308
+ secret_store = runtimeContext .secret_store )
306
309
if self .generatemapper :
307
- self .add_volumes (self .generatemapper , runtime , secret_store = runtimeContext .secret_store )
310
+ self .add_volumes (
311
+ self .generatemapper , runtime , any_path_okay = any_path_okay ,
312
+ secret_store = runtimeContext .secret_store )
308
313
309
314
if user_space_docker_cmd :
310
315
runtime = [x .replace (":ro" , "" ) for x in runtime ]
0 commit comments