diff --git a/lib/galaxy/tool_util/deps/container_classes.py b/lib/galaxy/tool_util/deps/container_classes.py index 769729f6bf9e..eefc3f7bf288 100644 --- a/lib/galaxy/tool_util/deps/container_classes.py +++ b/lib/galaxy/tool_util/deps/container_classes.py @@ -185,6 +185,10 @@ def parse_volume_str(rawstr: str) -> Tuple[str, str, str]: ('A', 'B', 'rw') >>> Volume.parse_volume_str('A:ro') ('A', 'A', 'ro') + >>> Volume.parse_volume_str('A:z') + ('A', 'A', 'z') + >>> Volume.parse_volume_str('A:Z') + ('A', 'A', 'Z') >>> Volume.parse_volume_str('A') ('A', 'A', 'rw') >>> Volume.parse_volume_str(' ') @@ -207,7 +211,9 @@ def parse_volume_str(rawstr: str) -> Tuple[str, str, str]: target = volume_parts[1] mode = volume_parts[2] elif len(volume_parts) == 2: - if volume_parts[1] not in ("rw", "ro", "default_ro"): + # not really parsing/checking mode here, just figuring out if the 2nd component is target or mode + mode_parts = volume_parts[1].split(",") + if any(mode_part not in ("rw", "ro", "default_ro", "z", "Z") for mode_part in mode_parts): source = volume_parts[0] target = volume_parts[1] mode = "rw" @@ -400,6 +406,18 @@ def add_var(name, value): return volumes_str +def _parse_volumes(volumes_raw: str, container_type: str) -> List[DockerVolume]: + """ + >>> volumes_raw = "$galaxy_root:ro,$tool_directory:ro,$job_directory:ro,$working_directory:z,$default_file_path:z" + >>> volumes = _parse_volumes(volumes_raw, "docker") + >>> [str(v) for v in volumes] + ['"$galaxy_root:$galaxy_root:ro"', '"$tool_directory:$tool_directory:ro"', '"$job_directory:$job_directory:ro"', '"$working_directory:$working_directory:z"', '"$default_file_path:$default_file_path:z"'] + """ + preprocessed_volumes_list = preprocess_volumes(volumes_raw, container_type) + # TODO: Remove redundant volumes... + return [DockerVolume.from_str(v) for v in preprocessed_volumes_list] + + class DockerContainer(Container, HasDockerLikeVolumes): container_type = DOCKER_CONTAINER_TYPE @@ -439,9 +457,7 @@ def containerize_command(self, command: str) -> str: raise Exception(f"Cannot containerize command [{working_directory}] without defined working directory.") volumes_raw = self._expand_volume_str(self.destination_info.get("docker_volumes", "$defaults")) - preprocessed_volumes_list = preprocess_volumes(volumes_raw, self.container_type) - # TODO: Remove redundant volumes... - volumes = [DockerVolume.from_str(v) for v in preprocessed_volumes_list] + volumes = _parse_volumes(volumes_raw, self.container_type) volumes_from = self.destination_info.get("docker_volumes_from", docker_util.DEFAULT_VOLUMES_FROM) docker_host_props = self.docker_host_props @@ -560,8 +576,7 @@ def containerize_command(self, command: str) -> str: raise Exception(f"Cannot containerize command [{working_directory}] without defined working directory.") volumes_raw = self._expand_volume_str(self.destination_info.get("singularity_volumes", "$defaults")) - preprocessed_volumes_list = preprocess_volumes(volumes_raw, self.container_type) - volumes = [DockerVolume.from_str(v) for v in preprocessed_volumes_list] + volumes = _parse_volumes(volumes_raw, self.container_type) run_command = singularity_util.build_singularity_run_command( command, diff --git a/lib/galaxy/tool_util/deps/container_volumes.py b/lib/galaxy/tool_util/deps/container_volumes.py index 2e969a3b4b63..01747bba15b8 100644 --- a/lib/galaxy/tool_util/deps/container_volumes.py +++ b/lib/galaxy/tool_util/deps/container_volumes.py @@ -7,7 +7,7 @@ class ContainerVolume(metaclass=ABCMeta): - valid_modes = frozenset({"ro", "rw"}) + valid_modes = frozenset({"ro", "rw", "z", "Z"}) def __init__(self, path: str, host_path: Optional[str] = None, mode: Optional[str] = None): self.path = path @@ -50,7 +50,7 @@ def from_str(cls, as_str: str) -> "DockerVolume": kwds["path"] = kwds["host_path"] elif len(parts) == 2: # /host_path:mode is not (or is no longer?) valid Docker volume syntax - if parts[1] in DockerVolume.valid_modes: + if all(mode_part in DockerVolume.valid_modes for mode_part in parts[1].split(",")): kwds["mode"] = parts[1] kwds["path"] = kwds["host_path"] else: