2121from .job import ContainerCommandLineJob
2222from .loghandler import _logger
2323from .pathmapper import PathMapper # pylint: disable=unused-import
24- from .pathmapper import ensure_writable
24+ from .pathmapper import ensure_writable , ensure_non_writable
2525from .secrets import SecretStore # pylint: disable=unused-import
2626from .utils import (DEFAULT_TMP_PREFIX , docker_windows_path_adjust , onWindows ,
2727 subprocess )
@@ -208,83 +208,84 @@ def get_from_requirements(self,
208208
209209 return None
210210
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: 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: 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: 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+ host_outdir_tgt = os .path .join (
277+ tmpdir , os .path .basename (volume .resolved ))
278+ shutil .copytree (volume .resolved , host_outdir_tgt )
279+ self .append_volume (
280+ runtime , host_outdir_tgt , volume .target ,
281+ writable = True )
278282 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 )
285285
286286 def create_runtime (self , env , runtimeContext ):
287287 # type: (MutableMapping[Text, Text], RuntimeContext) -> List
288+ any_path_okay = self .builder .get_requirement ("DockerRequirement" )[1 ]
288289 user_space_docker_cmd = runtimeContext .user_space_docker_cmd
289290 if user_space_docker_cmd :
290291 if 'udocker' in user_space_docker_cmd and not runtimeContext .debug :
@@ -302,9 +303,12 @@ def create_runtime(self, env, runtimeContext):
302303 runtime .append (u"--volume=%s:%s:rw" % (
303304 docker_windows_path_adjust (os .path .realpath (self .tmpdir )), "/tmp" ))
304305
305- self .add_volumes (self .pathmapper , runtime , secret_store = runtimeContext .secret_store )
306+ self .add_volumes (self .pathmapper , runtime , any_path_okay = True ,
307+ secret_store = runtimeContext .secret_store )
306308 if self .generatemapper :
307- self .add_volumes (self .generatemapper , runtime , secret_store = runtimeContext .secret_store )
309+ self .add_volumes (
310+ self .generatemapper , runtime , any_path_okay = any_path_okay ,
311+ secret_store = runtimeContext .secret_store )
308312
309313 if user_space_docker_cmd :
310314 runtime = [x .replace (":ro" , "" ) for x in runtime ]
0 commit comments