Skip to content

Commit 119ff7e

Browse files
committed
MPI: move hints/reqs + DockerRequirement checking into Process._init_job()
Move cache tests to their own file and add a new test
1 parent 93ce06b commit 119ff7e

7 files changed

+90
-65
lines changed

build-cwltool-docker.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ ${engine} run -t -v /var/run/docker.sock:/var/run/docker.sock \
88
-v /tmp:/tmp \
99
-v "$PWD":/tmp/cwltool \
1010
quay.io/commonwl/cwltool_module /bin/sh -c \
11-
"apk add gcc bash git && pip install -r/tmp/cwltool/test-requirements.txt ; pytest -k 'not (test_bioconda or test_double_overwrite or test_env_filtering or test_biocontainers or test_disable_file_overwrite_without_ext or test_disable_file_creation_in_outdir_with_ext or test_write_write_conflict or test_directory_literal_with_real_inputs_inside or test_revsort_workflow or test_stdin_with_id_preset or test_no_compute_chcksum or test_packed_workflow_execution[tests/wf/count-lines1-wf.cwl-tests/wf/wc-job.json-False] or test_sequential_workflow or test_single_process_subwf_subwf_inline_step)' --ignore-glob '*test_udocker.py' -n 0 -v -rs --pyargs cwltool"
11+
"apk add gcc bash git && pip install -r/tmp/cwltool/test-requirements.txt ; pytest -k 'not (test_bioconda or test_double_overwrite or test_env_filtering or test_biocontainers or test_disable_file_overwrite_without_ext or test_disable_file_creation_in_outdir_with_ext or test_write_write_conflict or test_directory_literal_with_real_inputs_inside or test_revsort_workflow or test_stdin_with_id_preset or test_no_compute_chcksum or test_packed_workflow_execution[tests/wf/count-lines1-wf.cwl-tests/wf/wc-job.json-False] or test_sequential_workflow or test_single_process_subwf_subwf_inline_step or test_cache_dockerreq_hint_instead_of_req)' --ignore-glob '*test_udocker.py' -n 0 -v -rs --pyargs cwltool"

cwltool/command_line_tool.py

-22
Original file line numberDiff line numberDiff line change
@@ -431,28 +431,6 @@ def make_job_runner(self, runtimeContext: RuntimeContext) -> type[JobBase]:
431431
return SingularityCommandLineJob
432432
elif runtimeContext.user_space_docker_cmd:
433433
return UDockerCommandLineJob
434-
if mpiReq is not None:
435-
if mpiRequired:
436-
if dockerRequired:
437-
raise UnsupportedRequirement(
438-
"No support for Docker and MPIRequirement both being required"
439-
)
440-
else:
441-
_logger.warning(
442-
"MPI has been required while Docker is hinted, discarding Docker hint(s)"
443-
)
444-
self.hints = [h for h in self.hints if h["class"] != "DockerRequirement"]
445-
return CommandLineJob
446-
else:
447-
if dockerRequired:
448-
_logger.warning(
449-
"Docker has been required while MPI is hinted, discarding MPI hint(s)"
450-
)
451-
self.hints = [h for h in self.hints if h["class"] != MPIRequirementName]
452-
else:
453-
raise UnsupportedRequirement(
454-
"Both Docker and MPI have been hinted - don't know what to do"
455-
)
456434
if runtimeContext.podman:
457435
return PodmanCommandLineJob
458436
return DockerCommandLineJob

cwltool/process.py

+36-1
Original file line numberDiff line numberDiff line change
@@ -810,12 +810,47 @@ def inc(d: list[int]) -> None:
810810
tmpdir = ""
811811
stagedir = ""
812812

813-
docker_req, _ = self.get_requirement("DockerRequirement")
813+
docker_req, docker_required = self.get_requirement("DockerRequirement")
814814
default_docker = None
815+
mpi_req, mpi_required = self.get_requirement(MPIRequirementName)
815816

816817
if docker_req is None and runtime_context.default_container:
817818
default_docker = runtime_context.default_container
818819

820+
if (
821+
docker_req is not None
822+
and runtime_context.use_container
823+
and not runtime_context.singularity
824+
and not runtime_context.user_space_docker_cmd
825+
and mpi_req is not None
826+
):
827+
if mpi_required:
828+
if docker_required:
829+
raise UnsupportedRequirement(
830+
"No support for DockerRequirement and MPIRequirement "
831+
"both being required, unless Singularity or uDocker is being used."
832+
)
833+
else:
834+
_logger.warning(
835+
"MPI has been required while DockerRequirement is hinted "
836+
"and neither Singularity nor uDocker is being used, discarding Docker hint(s)."
837+
)
838+
self.hints = [h for h in self.hints if h["class"] != "DockerRequirement"]
839+
docker_req = None
840+
docker_required = False
841+
else:
842+
if docker_required:
843+
_logger.warning(
844+
"Docker has been required (and neither Singularity nor "
845+
"uDocker is being used) while MPI is hinted, discarding MPI hint(s)/"
846+
)
847+
self.hints = [h for h in self.hints if h["class"] != MPIRequirementName]
848+
else:
849+
raise UnsupportedRequirement(
850+
"Both Docker and MPI have been hinted and neither "
851+
"Singularity nor uDocker are being used - don't know what to do."
852+
)
853+
819854
if (docker_req or default_docker) and runtime_context.use_container:
820855
if docker_req is not None:
821856
# Check if docker output directory is absolute

tests/test_caching.py

-21
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,6 @@
88
test_factors = [(""), ("--parallel"), ("--debug"), ("--parallel --debug")]
99

1010

11-
@needs_docker
12-
@pytest.mark.parametrize("factor", test_factors)
13-
def test_cid_file_non_existing_dir(tmp_path: Path, factor: str) -> None:
14-
"""Test that --cachedir with a bad path should produce a specific error."""
15-
test_file = "cache_test_workflow.cwl"
16-
bad_cidfile_dir = tmp_path / "cidfile-dir-badpath"
17-
commands = factor.split()
18-
commands.extend(
19-
[
20-
"--record-container-id",
21-
"--cidfile-dir",
22-
str(bad_cidfile_dir),
23-
get_data("tests/wf/" + test_file),
24-
]
25-
)
26-
error_code, _, stderr = get_main_output(commands)
27-
stderr = re.sub(r"\s\s+", " ", stderr)
28-
assert "directory doesn't exist, please create it first" in stderr, stderr
29-
assert error_code == 2 or error_code == 1, stderr
30-
31-
3211
@needs_docker
3312
@pytest.mark.parametrize("factor", test_factors)
3413
def test_wf_without_container(tmp_path: Path, factor: str) -> None:

tests/test_environment.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ def test_basic(crt_params: CheckHolder, tmp_path: Path, monkeypatch: pytest.Monk
204204
"USEDVAR": "VARVAL",
205205
"UNUSEDVAR": "VARVAL",
206206
}
207-
args = crt_params.flags + [f"--tmpdir-prefix={tmp_prefix}"]
207+
args = crt_params.flags + [f"--tmpdir-prefix={tmp_prefix}", "--debug"]
208208
env = get_tool_env(
209209
tmp_path,
210210
args,

tests/test_examples.py

+21
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,27 @@ def test_cid_file_dir_arg_is_file_instead_of_dir(tmp_path: Path, factor: str) ->
11151115
assert error_code == 2 or error_code == 1, stderr
11161116

11171117

1118+
@needs_docker
1119+
@pytest.mark.parametrize("factor", test_factors)
1120+
def test_cid_file_non_existing_dir(tmp_path: Path, factor: str) -> None:
1121+
"""Test that --cidefile-dir with a bad path should produce a specific error."""
1122+
test_file = "cache_test_workflow.cwl"
1123+
bad_cidfile_dir = tmp_path / "cidfile-dir-badpath"
1124+
commands = factor.split()
1125+
commands.extend(
1126+
[
1127+
"--record-container-id",
1128+
"--cidfile-dir",
1129+
str(bad_cidfile_dir),
1130+
get_data("tests/wf/" + test_file),
1131+
]
1132+
)
1133+
error_code, _, stderr = get_main_output(commands)
1134+
stderr = re.sub(r"\s\s+", " ", stderr)
1135+
assert "directory doesn't exist, please create it first" in stderr, stderr
1136+
assert error_code == 2 or error_code == 1, stderr
1137+
1138+
11181139
@needs_docker
11191140
@pytest.mark.parametrize("factor", test_factors)
11201141
def test_cid_file_w_prefix(tmp_path: Path, factor: str) -> None:

tests/test_mpi.py

+31-19
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,19 @@
77
from importlib.resources import files
88
from io import StringIO
99
from pathlib import Path
10-
from typing import Any, Optional
10+
from typing import Any, Optional, cast
1111

1212
import pytest
1313
from ruamel.yaml.comments import CommentedMap, CommentedSeq
1414
from schema_salad.avro.schema import Names
15+
from schema_salad.ref_resolver import file_uri
1516
from schema_salad.utils import yaml_no_ts
1617

1718
import cwltool.load_tool
1819
import cwltool.singularity
1920
import cwltool.udocker
2021
from cwltool.command_line_tool import CommandLineTool
21-
from cwltool.context import LoadingContext, RuntimeContext
22+
from cwltool.context import RuntimeContext
2223
from cwltool.main import main
2324
from cwltool.mpi import MpiConfig, MPIRequirementName
2425

@@ -292,15 +293,22 @@ def schema_ext11() -> Generator[Names, None, None]:
292293

293294
mpiReq = CommentedMap({"class": MPIRequirementName, "processes": 1})
294295
containerReq = CommentedMap({"class": "DockerRequirement"})
295-
basetool = CommentedMap({"cwlVersion": "v1.1", "inputs": CommentedSeq(), "outputs": CommentedSeq()})
296+
basetool = CommentedMap(
297+
{
298+
"cwlVersion": "v1.1",
299+
"class": "CommandLineTool",
300+
"inputs": CommentedSeq(),
301+
"outputs": CommentedSeq(),
302+
}
303+
)
296304

297305

298306
def mk_tool(
299307
schema: Names,
300308
opts: list[str],
301309
reqs: Optional[list[CommentedMap]] = None,
302310
hints: Optional[list[CommentedMap]] = None,
303-
) -> tuple[LoadingContext, RuntimeContext, CommentedMap]:
311+
) -> tuple[RuntimeContext, CommandLineTool]:
304312
tool = basetool.copy()
305313

306314
if reqs is not None:
@@ -310,53 +318,57 @@ def mk_tool(
310318

311319
args = cwltool.argparser.arg_parser().parse_args(opts)
312320
args.enable_ext = True
321+
args.basedir = os.path.dirname(os.path.abspath("."))
313322
rc = RuntimeContext(vars(args))
314323
lc = cwltool.main.setup_loadingContext(None, rc, args)
315324
lc.avsc_names = schema
316-
return lc, rc, tool
325+
tool["id"] = file_uri(os.path.abspath("./mktool.cwl"))
326+
assert lc.loader is not None
327+
lc.loader.idx[tool["id"]] = tool
328+
return rc, cast(CommandLineTool, cwltool.load_tool.load_tool(tool, lc))
317329

318330

319331
def test_singularity(schema_ext11: Names) -> None:
320-
lc, rc, tool = mk_tool(schema_ext11, ["--singularity"], reqs=[mpiReq, containerReq])
321-
clt = CommandLineTool(tool, lc)
332+
rc, clt = mk_tool(schema_ext11, ["--singularity"], reqs=[mpiReq, containerReq])
333+
clt._init_job({}, rc)
322334
jr = clt.make_job_runner(rc)
323335
assert jr is cwltool.singularity.SingularityCommandLineJob
324336

325337

326338
def test_udocker(schema_ext11: Names) -> None:
327-
lc, rc, tool = mk_tool(schema_ext11, ["--udocker"], reqs=[mpiReq, containerReq])
328-
clt = CommandLineTool(tool, lc)
339+
rc, clt = mk_tool(schema_ext11, ["--udocker"], reqs=[mpiReq, containerReq])
340+
clt._init_job({}, rc)
329341
jr = clt.make_job_runner(rc)
330342
assert jr is cwltool.udocker.UDockerCommandLineJob
331343

332344

333345
def test_docker_hint(schema_ext11: Names) -> None:
334346
# Docker hint, MPI required
335-
lc, rc, tool = mk_tool(schema_ext11, [], hints=[containerReq], reqs=[mpiReq])
336-
clt = CommandLineTool(tool, lc)
347+
rc, clt = mk_tool(schema_ext11, [], hints=[containerReq], reqs=[mpiReq])
348+
clt._init_job({}, rc)
337349
jr = clt.make_job_runner(rc)
338350
assert jr is cwltool.job.CommandLineJob
339351

340352

341353
def test_docker_required(schema_ext11: Names) -> None:
342354
# Docker required, MPI hinted
343-
lc, rc, tool = mk_tool(schema_ext11, [], reqs=[containerReq], hints=[mpiReq])
344-
clt = CommandLineTool(tool, lc)
355+
rc, clt = mk_tool(schema_ext11, [], reqs=[containerReq], hints=[mpiReq])
356+
clt._init_job({}, rc)
345357
jr = clt.make_job_runner(rc)
346358
assert jr is cwltool.docker.DockerCommandLineJob
347359

348360

349361
def test_docker_mpi_both_required(schema_ext11: Names) -> None:
350362
# Both required - error
351-
lc, rc, tool = mk_tool(schema_ext11, [], reqs=[mpiReq, containerReq])
352-
clt = CommandLineTool(tool, lc)
363+
rc, clt = mk_tool(schema_ext11, [], reqs=[mpiReq, containerReq])
353364
with pytest.raises(cwltool.errors.UnsupportedRequirement):
354-
clt.make_job_runner(rc)
365+
clt._init_job({}, rc)
366+
clt.make_job_runner(rc)
355367

356368

357369
def test_docker_mpi_both_hinted(schema_ext11: Names) -> None:
358370
# Both hinted - error
359-
lc, rc, tool = mk_tool(schema_ext11, [], hints=[mpiReq, containerReq])
360-
clt = CommandLineTool(tool, lc)
371+
rc, clt = mk_tool(schema_ext11, [], hints=[mpiReq, containerReq])
361372
with pytest.raises(cwltool.errors.UnsupportedRequirement):
362-
clt.make_job_runner(rc)
373+
clt._init_job({}, rc)
374+
clt.make_job_runner(rc)

0 commit comments

Comments
 (0)