toil 8.0.0__py3-none-any.whl → 8.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- toil/__init__.py +4 -39
- toil/batchSystems/abstractBatchSystem.py +1 -1
- toil/batchSystems/abstractGridEngineBatchSystem.py +1 -1
- toil/batchSystems/awsBatch.py +1 -1
- toil/batchSystems/cleanup_support.py +1 -1
- toil/batchSystems/kubernetes.py +53 -7
- toil/batchSystems/local_support.py +1 -1
- toil/batchSystems/mesos/batchSystem.py +13 -8
- toil/batchSystems/mesos/test/__init__.py +3 -2
- toil/batchSystems/options.py +1 -0
- toil/batchSystems/singleMachine.py +1 -1
- toil/batchSystems/slurm.py +229 -84
- toil/bus.py +5 -3
- toil/common.py +198 -54
- toil/cwl/cwltoil.py +32 -11
- toil/job.py +110 -86
- toil/jobStores/abstractJobStore.py +24 -3
- toil/jobStores/aws/jobStore.py +46 -10
- toil/jobStores/fileJobStore.py +25 -1
- toil/jobStores/googleJobStore.py +104 -30
- toil/leader.py +9 -0
- toil/lib/accelerators.py +3 -1
- toil/lib/aws/session.py +14 -3
- toil/lib/aws/utils.py +92 -35
- toil/lib/aws/utils.py.orig +504 -0
- toil/lib/bioio.py +1 -1
- toil/lib/docker.py +252 -91
- toil/lib/dockstore.py +387 -0
- toil/lib/ec2nodes.py +3 -2
- toil/lib/exceptions.py +5 -3
- toil/lib/history.py +1345 -0
- toil/lib/history_submission.py +695 -0
- toil/lib/io.py +56 -23
- toil/lib/misc.py +25 -1
- toil/lib/resources.py +2 -1
- toil/lib/retry.py +10 -10
- toil/lib/threading.py +11 -10
- toil/lib/{integration.py → trs.py} +95 -46
- toil/lib/web.py +38 -0
- toil/options/common.py +25 -2
- toil/options/cwl.py +10 -0
- toil/options/wdl.py +11 -0
- toil/provisioners/gceProvisioner.py +4 -4
- toil/server/api_spec/LICENSE +201 -0
- toil/server/api_spec/README.rst +5 -0
- toil/server/cli/wes_cwl_runner.py +5 -4
- toil/server/utils.py +2 -3
- toil/statsAndLogging.py +35 -1
- toil/test/__init__.py +275 -115
- toil/test/batchSystems/batchSystemTest.py +227 -205
- toil/test/batchSystems/test_slurm.py +199 -2
- toil/test/cactus/pestis.tar.gz +0 -0
- toil/test/conftest.py +7 -0
- toil/test/cwl/2.fasta +11 -0
- toil/test/cwl/2.fastq +12 -0
- toil/test/cwl/conftest.py +39 -0
- toil/test/cwl/cwlTest.py +1015 -780
- toil/test/cwl/directory/directory/file.txt +15 -0
- toil/test/cwl/download_directory_file.json +4 -0
- toil/test/cwl/download_directory_s3.json +4 -0
- toil/test/cwl/download_file.json +6 -0
- toil/test/cwl/download_http.json +6 -0
- toil/test/cwl/download_https.json +6 -0
- toil/test/cwl/download_s3.json +6 -0
- toil/test/cwl/download_subdirectory_file.json +5 -0
- toil/test/cwl/download_subdirectory_s3.json +5 -0
- toil/test/cwl/empty.json +1 -0
- toil/test/cwl/mock_mpi/fake_mpi.yml +8 -0
- toil/test/cwl/mock_mpi/fake_mpi_run.py +42 -0
- toil/test/cwl/optional-file-exists.json +6 -0
- toil/test/cwl/optional-file-missing.json +6 -0
- toil/test/cwl/optional-file.cwl +18 -0
- toil/test/cwl/preemptible_expression.json +1 -0
- toil/test/cwl/revsort-job-missing.json +6 -0
- toil/test/cwl/revsort-job.json +6 -0
- toil/test/cwl/s3_secondary_file.json +16 -0
- toil/test/cwl/seqtk_seq_job.json +6 -0
- toil/test/cwl/stream.json +6 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.dat +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f0 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f1 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f1i +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f2 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f2_TSM0 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f3 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f3_TSM0 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f4 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f4_TSM0 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f5 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.info +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.lock +0 -0
- toil/test/cwl/whale.txt +16 -0
- toil/test/docs/scripts/example_alwaysfail.py +38 -0
- toil/test/docs/scripts/example_alwaysfail_with_files.wdl +33 -0
- toil/test/docs/scripts/example_cachingbenchmark.py +117 -0
- toil/test/docs/scripts/stagingExampleFiles/in.txt +1 -0
- toil/test/docs/scripts/stagingExampleFiles/out.txt +2 -0
- toil/test/docs/scripts/tutorial_arguments.py +23 -0
- toil/test/docs/scripts/tutorial_debugging.patch +12 -0
- toil/test/docs/scripts/tutorial_debugging_hangs.wdl +126 -0
- toil/test/docs/scripts/tutorial_debugging_works.wdl +129 -0
- toil/test/docs/scripts/tutorial_docker.py +20 -0
- toil/test/docs/scripts/tutorial_dynamic.py +24 -0
- toil/test/docs/scripts/tutorial_encapsulation.py +28 -0
- toil/test/docs/scripts/tutorial_encapsulation2.py +29 -0
- toil/test/docs/scripts/tutorial_helloworld.py +15 -0
- toil/test/docs/scripts/tutorial_invokeworkflow.py +27 -0
- toil/test/docs/scripts/tutorial_invokeworkflow2.py +30 -0
- toil/test/docs/scripts/tutorial_jobfunctions.py +22 -0
- toil/test/docs/scripts/tutorial_managing.py +29 -0
- toil/test/docs/scripts/tutorial_managing2.py +56 -0
- toil/test/docs/scripts/tutorial_multiplejobs.py +25 -0
- toil/test/docs/scripts/tutorial_multiplejobs2.py +21 -0
- toil/test/docs/scripts/tutorial_multiplejobs3.py +22 -0
- toil/test/docs/scripts/tutorial_promises.py +25 -0
- toil/test/docs/scripts/tutorial_promises2.py +30 -0
- toil/test/docs/scripts/tutorial_quickstart.py +22 -0
- toil/test/docs/scripts/tutorial_requirements.py +44 -0
- toil/test/docs/scripts/tutorial_services.py +45 -0
- toil/test/docs/scripts/tutorial_staging.py +45 -0
- toil/test/docs/scripts/tutorial_stats.py +64 -0
- toil/test/lib/aws/test_iam.py +3 -1
- toil/test/lib/dockerTest.py +205 -122
- toil/test/lib/test_history.py +236 -0
- toil/test/lib/test_trs.py +161 -0
- toil/test/provisioners/aws/awsProvisionerTest.py +12 -9
- toil/test/provisioners/clusterTest.py +4 -4
- toil/test/provisioners/gceProvisionerTest.py +16 -14
- toil/test/sort/sort.py +4 -1
- toil/test/src/busTest.py +17 -17
- toil/test/src/deferredFunctionTest.py +145 -132
- toil/test/src/importExportFileTest.py +71 -63
- toil/test/src/jobEncapsulationTest.py +27 -28
- toil/test/src/jobServiceTest.py +149 -133
- toil/test/src/jobTest.py +219 -211
- toil/test/src/miscTests.py +66 -60
- toil/test/src/promisedRequirementTest.py +163 -169
- toil/test/src/regularLogTest.py +24 -24
- toil/test/src/resourceTest.py +82 -76
- toil/test/src/restartDAGTest.py +51 -47
- toil/test/src/resumabilityTest.py +24 -19
- toil/test/src/retainTempDirTest.py +60 -57
- toil/test/src/systemTest.py +17 -13
- toil/test/src/threadingTest.py +29 -32
- toil/test/utils/ABCWorkflowDebug/B_file.txt +1 -0
- toil/test/utils/ABCWorkflowDebug/debugWorkflow.py +204 -0
- toil/test/utils/ABCWorkflowDebug/mkFile.py +16 -0
- toil/test/utils/ABCWorkflowDebug/sleep.cwl +12 -0
- toil/test/utils/ABCWorkflowDebug/sleep.yaml +1 -0
- toil/test/utils/toilDebugTest.py +117 -102
- toil/test/utils/toilKillTest.py +54 -53
- toil/test/utils/utilsTest.py +303 -229
- toil/test/wdl/lint_error.wdl +9 -0
- toil/test/wdl/md5sum/empty_file.json +1 -0
- toil/test/wdl/md5sum/md5sum-gs.json +1 -0
- toil/test/wdl/md5sum/md5sum.1.0.wdl +32 -0
- toil/test/wdl/md5sum/md5sum.input +1 -0
- toil/test/wdl/md5sum/md5sum.json +1 -0
- toil/test/wdl/md5sum/md5sum.wdl +25 -0
- toil/test/wdl/miniwdl_self_test/inputs-namespaced.json +1 -0
- toil/test/wdl/miniwdl_self_test/inputs.json +1 -0
- toil/test/wdl/miniwdl_self_test/self_test.wdl +40 -0
- toil/test/wdl/standard_library/as_map.json +16 -0
- toil/test/wdl/standard_library/as_map_as_input.wdl +23 -0
- toil/test/wdl/standard_library/as_pairs.json +7 -0
- toil/test/wdl/standard_library/as_pairs_as_input.wdl +23 -0
- toil/test/wdl/standard_library/ceil.json +3 -0
- toil/test/wdl/standard_library/ceil_as_command.wdl +16 -0
- toil/test/wdl/standard_library/ceil_as_input.wdl +16 -0
- toil/test/wdl/standard_library/collect_by_key.json +1 -0
- toil/test/wdl/standard_library/collect_by_key_as_input.wdl +23 -0
- toil/test/wdl/standard_library/cross.json +11 -0
- toil/test/wdl/standard_library/cross_as_input.wdl +19 -0
- toil/test/wdl/standard_library/flatten.json +7 -0
- toil/test/wdl/standard_library/flatten_as_input.wdl +18 -0
- toil/test/wdl/standard_library/floor.json +3 -0
- toil/test/wdl/standard_library/floor_as_command.wdl +16 -0
- toil/test/wdl/standard_library/floor_as_input.wdl +16 -0
- toil/test/wdl/standard_library/keys.json +8 -0
- toil/test/wdl/standard_library/keys_as_input.wdl +24 -0
- toil/test/wdl/standard_library/length.json +7 -0
- toil/test/wdl/standard_library/length_as_input.wdl +16 -0
- toil/test/wdl/standard_library/length_as_input_with_map.json +7 -0
- toil/test/wdl/standard_library/length_as_input_with_map.wdl +17 -0
- toil/test/wdl/standard_library/length_invalid.json +3 -0
- toil/test/wdl/standard_library/range.json +3 -0
- toil/test/wdl/standard_library/range_0.json +3 -0
- toil/test/wdl/standard_library/range_as_input.wdl +17 -0
- toil/test/wdl/standard_library/range_invalid.json +3 -0
- toil/test/wdl/standard_library/read_boolean.json +3 -0
- toil/test/wdl/standard_library/read_boolean_as_command.wdl +17 -0
- toil/test/wdl/standard_library/read_float.json +3 -0
- toil/test/wdl/standard_library/read_float_as_command.wdl +17 -0
- toil/test/wdl/standard_library/read_int.json +3 -0
- toil/test/wdl/standard_library/read_int_as_command.wdl +17 -0
- toil/test/wdl/standard_library/read_json.json +3 -0
- toil/test/wdl/standard_library/read_json_as_output.wdl +31 -0
- toil/test/wdl/standard_library/read_lines.json +3 -0
- toil/test/wdl/standard_library/read_lines_as_output.wdl +31 -0
- toil/test/wdl/standard_library/read_map.json +3 -0
- toil/test/wdl/standard_library/read_map_as_output.wdl +31 -0
- toil/test/wdl/standard_library/read_string.json +3 -0
- toil/test/wdl/standard_library/read_string_as_command.wdl +17 -0
- toil/test/wdl/standard_library/read_tsv.json +3 -0
- toil/test/wdl/standard_library/read_tsv_as_output.wdl +31 -0
- toil/test/wdl/standard_library/round.json +3 -0
- toil/test/wdl/standard_library/round_as_command.wdl +16 -0
- toil/test/wdl/standard_library/round_as_input.wdl +16 -0
- toil/test/wdl/standard_library/size.json +3 -0
- toil/test/wdl/standard_library/size_as_command.wdl +17 -0
- toil/test/wdl/standard_library/size_as_output.wdl +36 -0
- toil/test/wdl/standard_library/stderr.json +3 -0
- toil/test/wdl/standard_library/stderr_as_output.wdl +30 -0
- toil/test/wdl/standard_library/stdout.json +3 -0
- toil/test/wdl/standard_library/stdout_as_output.wdl +30 -0
- toil/test/wdl/standard_library/sub.json +3 -0
- toil/test/wdl/standard_library/sub_as_input.wdl +17 -0
- toil/test/wdl/standard_library/sub_as_input_with_file.wdl +17 -0
- toil/test/wdl/standard_library/transpose.json +6 -0
- toil/test/wdl/standard_library/transpose_as_input.wdl +18 -0
- toil/test/wdl/standard_library/write_json.json +6 -0
- toil/test/wdl/standard_library/write_json_as_command.wdl +17 -0
- toil/test/wdl/standard_library/write_lines.json +7 -0
- toil/test/wdl/standard_library/write_lines_as_command.wdl +17 -0
- toil/test/wdl/standard_library/write_map.json +6 -0
- toil/test/wdl/standard_library/write_map_as_command.wdl +17 -0
- toil/test/wdl/standard_library/write_tsv.json +6 -0
- toil/test/wdl/standard_library/write_tsv_as_command.wdl +17 -0
- toil/test/wdl/standard_library/zip.json +12 -0
- toil/test/wdl/standard_library/zip_as_input.wdl +19 -0
- toil/test/wdl/test.csv +3 -0
- toil/test/wdl/test.tsv +3 -0
- toil/test/wdl/testfiles/croo.wdl +38 -0
- toil/test/wdl/testfiles/drop_files.wdl +62 -0
- toil/test/wdl/testfiles/drop_files_subworkflow.wdl +13 -0
- toil/test/wdl/testfiles/empty.txt +0 -0
- toil/test/wdl/testfiles/not_enough_outputs.wdl +33 -0
- toil/test/wdl/testfiles/random.wdl +66 -0
- toil/test/wdl/testfiles/string_file_coercion.json +1 -0
- toil/test/wdl/testfiles/string_file_coercion.wdl +35 -0
- toil/test/wdl/testfiles/test.json +4 -0
- toil/test/wdl/testfiles/test_boolean.txt +1 -0
- toil/test/wdl/testfiles/test_float.txt +1 -0
- toil/test/wdl/testfiles/test_int.txt +1 -0
- toil/test/wdl/testfiles/test_lines.txt +5 -0
- toil/test/wdl/testfiles/test_map.txt +2 -0
- toil/test/wdl/testfiles/test_string.txt +1 -0
- toil/test/wdl/testfiles/url_to_file.wdl +13 -0
- toil/test/wdl/testfiles/url_to_optional_file.wdl +13 -0
- toil/test/wdl/testfiles/vocab.json +1 -0
- toil/test/wdl/testfiles/vocab.wdl +66 -0
- toil/test/wdl/testfiles/wait.wdl +34 -0
- toil/test/wdl/wdl_specification/type_pair.json +23 -0
- toil/test/wdl/wdl_specification/type_pair_basic.wdl +36 -0
- toil/test/wdl/wdl_specification/type_pair_with_files.wdl +36 -0
- toil/test/wdl/wdl_specification/v1_spec.json +1 -0
- toil/test/wdl/wdl_specification/v1_spec_declaration.wdl +39 -0
- toil/test/wdl/wdltoil_test.py +681 -408
- toil/test/wdl/wdltoil_test_kubernetes.py +2 -2
- toil/version.py +10 -10
- toil/wdl/wdltoil.py +350 -123
- toil/worker.py +113 -33
- {toil-8.0.0.dist-info → toil-8.2.0.dist-info}/METADATA +13 -7
- toil-8.2.0.dist-info/RECORD +439 -0
- {toil-8.0.0.dist-info → toil-8.2.0.dist-info}/WHEEL +1 -1
- toil/test/lib/test_integration.py +0 -104
- toil-8.0.0.dist-info/RECORD +0 -253
- {toil-8.0.0.dist-info → toil-8.2.0.dist-info}/entry_points.txt +0 -0
- {toil-8.0.0.dist-info → toil-8.2.0.dist-info/licenses}/LICENSE +0 -0
- {toil-8.0.0.dist-info → toil-8.2.0.dist-info}/top_level.txt +0 -0
toil/__init__.py
CHANGED
|
@@ -19,7 +19,7 @@ import sys
|
|
|
19
19
|
from datetime import datetime
|
|
20
20
|
from typing import TYPE_CHECKING, Optional
|
|
21
21
|
|
|
22
|
-
import
|
|
22
|
+
from toil.lib.web import web_session
|
|
23
23
|
|
|
24
24
|
from docker.errors import ImageNotFound
|
|
25
25
|
from toil.lib.memoize import memoize
|
|
@@ -425,7 +425,7 @@ def requestCheckRegularDocker(
|
|
|
425
425
|
ioURL = "https://{webhost}/v2/{pathName}/manifests/{tag}" "".format(
|
|
426
426
|
webhost=registryName, pathName=imageName, tag=tag
|
|
427
427
|
)
|
|
428
|
-
response =
|
|
428
|
+
response = web_session.head(ioURL)
|
|
429
429
|
if not response.ok:
|
|
430
430
|
raise ApplianceImageNotFound(origAppliance, ioURL, response.status_code)
|
|
431
431
|
else:
|
|
@@ -459,10 +459,10 @@ def requestCheckDockerIo(origAppliance: str, imageName: str, tag: str) -> bool:
|
|
|
459
459
|
)
|
|
460
460
|
requests_url = f"https://registry-1.docker.io/v2/{imageName}/manifests/{tag}"
|
|
461
461
|
|
|
462
|
-
token =
|
|
462
|
+
token = web_session.get(token_url)
|
|
463
463
|
jsonToken = token.json()
|
|
464
464
|
bearer = jsonToken["token"]
|
|
465
|
-
response =
|
|
465
|
+
response = web_session.head(
|
|
466
466
|
requests_url, headers={"Authorization": f"Bearer {bearer}"}
|
|
467
467
|
)
|
|
468
468
|
if not response.ok:
|
|
@@ -480,38 +480,3 @@ def logProcessContext(config: "Config") -> None:
|
|
|
480
480
|
log.info("Running Toil version %s on host %s.", version, socket.gethostname())
|
|
481
481
|
log.debug("Configuration: %s", config.__dict__)
|
|
482
482
|
|
|
483
|
-
|
|
484
|
-
try:
|
|
485
|
-
cache_path = "~/.cache/aws/cached_temporary_credentials"
|
|
486
|
-
datetime_format = (
|
|
487
|
-
"%Y-%m-%dT%H:%M:%SZ" # incidentally the same as the format used by AWS
|
|
488
|
-
)
|
|
489
|
-
log = logging.getLogger(__name__)
|
|
490
|
-
|
|
491
|
-
# But in addition to our manual cache, we also are going to turn on boto3's
|
|
492
|
-
# new built-in caching layer.
|
|
493
|
-
|
|
494
|
-
def datetime_to_str(dt):
|
|
495
|
-
"""
|
|
496
|
-
Convert a naive (implicitly UTC) datetime object into a string, explicitly UTC.
|
|
497
|
-
|
|
498
|
-
>>> datetime_to_str(datetime(1970, 1, 1, 0, 0, 0))
|
|
499
|
-
'1970-01-01T00:00:00Z'
|
|
500
|
-
"""
|
|
501
|
-
return dt.strftime(datetime_format)
|
|
502
|
-
|
|
503
|
-
def str_to_datetime(s):
|
|
504
|
-
"""
|
|
505
|
-
Convert a string, explicitly UTC into a naive (implicitly UTC) datetime object.
|
|
506
|
-
|
|
507
|
-
>>> str_to_datetime( '1970-01-01T00:00:00Z' )
|
|
508
|
-
datetime.datetime(1970, 1, 1, 0, 0)
|
|
509
|
-
|
|
510
|
-
Just to show that the constructor args for seconds and microseconds are optional:
|
|
511
|
-
>>> datetime(1970, 1, 1, 0, 0, 0)
|
|
512
|
-
datetime.datetime(1970, 1, 1, 0, 0)
|
|
513
|
-
"""
|
|
514
|
-
return datetime.strptime(s, datetime_format)
|
|
515
|
-
|
|
516
|
-
except ImportError:
|
|
517
|
-
pass
|
|
@@ -310,7 +310,7 @@ class BatchSystemSupport(AbstractBatchSystem):
|
|
|
310
310
|
"""Partial implementation of AbstractBatchSystem, support methods."""
|
|
311
311
|
|
|
312
312
|
def __init__(
|
|
313
|
-
self, config: Config, maxCores: float, maxMemory:
|
|
313
|
+
self, config: Config, maxCores: float, maxMemory: float, maxDisk: int
|
|
314
314
|
) -> None:
|
|
315
315
|
"""
|
|
316
316
|
Initialize initial state of the object.
|
|
@@ -421,7 +421,7 @@ class AbstractGridEngineBatchSystem(BatchSystemCleanupSupport):
|
|
|
421
421
|
raise NotImplementedError()
|
|
422
422
|
|
|
423
423
|
def __init__(
|
|
424
|
-
self, config: Config, maxCores: float, maxMemory:
|
|
424
|
+
self, config: Config, maxCores: float, maxMemory: float, maxDisk: float
|
|
425
425
|
) -> None:
|
|
426
426
|
super().__init__(config, maxCores, maxMemory, maxDisk)
|
|
427
427
|
self.config = config
|
toil/batchSystems/awsBatch.py
CHANGED
|
@@ -83,7 +83,7 @@ class AWSBatchBatchSystem(BatchSystemCleanupSupport):
|
|
|
83
83
|
return True
|
|
84
84
|
|
|
85
85
|
def __init__(
|
|
86
|
-
self, config: Config, maxCores: float, maxMemory:
|
|
86
|
+
self, config: Config, maxCores: float, maxMemory: float, maxDisk: int
|
|
87
87
|
) -> None:
|
|
88
88
|
super().__init__(config, maxCores, maxMemory, maxDisk)
|
|
89
89
|
|
|
@@ -45,7 +45,7 @@ class BatchSystemCleanupSupport(BatchSystemLocalSupport):
|
|
|
45
45
|
return contexts
|
|
46
46
|
|
|
47
47
|
def __init__(
|
|
48
|
-
self, config: Config, maxCores: float, maxMemory:
|
|
48
|
+
self, config: Config, maxCores: float, maxMemory: float, maxDisk: int
|
|
49
49
|
) -> None:
|
|
50
50
|
super().__init__(config, maxCores, maxMemory, maxDisk)
|
|
51
51
|
|
toil/batchSystems/kubernetes.py
CHANGED
|
@@ -21,6 +21,7 @@ cannot yet be launched. That functionality will need to wait for user-mode
|
|
|
21
21
|
Docker
|
|
22
22
|
"""
|
|
23
23
|
import datetime
|
|
24
|
+
import io
|
|
24
25
|
import logging
|
|
25
26
|
import math
|
|
26
27
|
import os
|
|
@@ -50,7 +51,8 @@ else:
|
|
|
50
51
|
from typing import Protocol, TypedDict, runtime_checkable
|
|
51
52
|
|
|
52
53
|
import urllib3
|
|
53
|
-
import yaml
|
|
54
|
+
import ruamel.yaml as yaml
|
|
55
|
+
import json
|
|
54
56
|
|
|
55
57
|
# The Right Way to use the Kubernetes module is to `import kubernetes` and then you get all your stuff as like ApiClient. But this doesn't work for the stubs: the stubs seem to only support importing things from the internal modules in `kubernetes` where they are actually defined. See for example <https://github.com/MaterializeInc/kubernetes-stubs/issues/9 and <https://github.com/MaterializeInc/kubernetes-stubs/issues/10>. So we just import all the things we use into our global namespace here.
|
|
56
58
|
from kubernetes.client import (
|
|
@@ -77,6 +79,7 @@ from kubernetes.client import (
|
|
|
77
79
|
V1ResourceRequirements,
|
|
78
80
|
V1SecretVolumeSource,
|
|
79
81
|
V1SecurityContext,
|
|
82
|
+
V1PodSecurityContext,
|
|
80
83
|
V1Toleration,
|
|
81
84
|
V1Volume,
|
|
82
85
|
V1VolumeMount,
|
|
@@ -148,7 +151,7 @@ class KubernetesBatchSystem(BatchSystemCleanupSupport):
|
|
|
148
151
|
customObjects: NotRequired[CustomObjectsApi]
|
|
149
152
|
|
|
150
153
|
def __init__(
|
|
151
|
-
self, config: Config, maxCores: int, maxMemory:
|
|
154
|
+
self, config: Config, maxCores: int, maxMemory: float, maxDisk: int
|
|
152
155
|
) -> None:
|
|
153
156
|
super().__init__(config, maxCores, maxMemory, maxDisk)
|
|
154
157
|
|
|
@@ -314,7 +317,10 @@ class KubernetesBatchSystem(BatchSystemCleanupSupport):
|
|
|
314
317
|
del here[k]
|
|
315
318
|
|
|
316
319
|
drop_boring(root_dict)
|
|
317
|
-
|
|
320
|
+
s = io.StringIO()
|
|
321
|
+
YAML = yaml.YAML(typ='safe')
|
|
322
|
+
YAML.dump(root_dict, s)
|
|
323
|
+
return s.getvalue()
|
|
318
324
|
|
|
319
325
|
@overload
|
|
320
326
|
def _api(
|
|
@@ -803,6 +809,26 @@ class KubernetesBatchSystem(BatchSystemCleanupSupport):
|
|
|
803
809
|
],
|
|
804
810
|
)
|
|
805
811
|
|
|
812
|
+
class FakeResponse:
|
|
813
|
+
data: str
|
|
814
|
+
|
|
815
|
+
T = TypeVar('T')
|
|
816
|
+
def _load_kubernetes_object(self, file: str, cls: type[T]) -> T:
|
|
817
|
+
"""
|
|
818
|
+
Deserialize a YAML representation into a Kubernetes object
|
|
819
|
+
:param file: Path to YAML file
|
|
820
|
+
:param cls: Kubernetes API model type for deserialized object
|
|
821
|
+
:return: Deserialized object
|
|
822
|
+
"""
|
|
823
|
+
YAML = yaml.YAML(typ='safe')
|
|
824
|
+
object_def = YAML.load(open('container.yaml').read())
|
|
825
|
+
# The kubernetes API does not have an actual deserializer, so this is a workaround
|
|
826
|
+
# See: https://github.com/kubernetes-client/python/issues/977
|
|
827
|
+
faked_response = self.FakeResponse()
|
|
828
|
+
faked_response.data = json.dumps(object_def)
|
|
829
|
+
return ApiClient().deserialize(faked_response, cls)
|
|
830
|
+
|
|
831
|
+
|
|
806
832
|
def _create_pod_spec(
|
|
807
833
|
self,
|
|
808
834
|
command: str,
|
|
@@ -946,17 +972,24 @@ class KubernetesBatchSystem(BatchSystemCleanupSupport):
|
|
|
946
972
|
volume_mounts=mounts,
|
|
947
973
|
)
|
|
948
974
|
|
|
975
|
+
if self.config.kubernetes_security_context:
|
|
976
|
+
container.security_context = self._load_kubernetes_object(self.config.kubernetes_security_context, V1SecurityContext)
|
|
977
|
+
|
|
949
978
|
# In case security context rules are not allowed to be set, we only apply
|
|
950
979
|
# a security context at all if we need to turn on privileged mode.
|
|
951
980
|
if self.config.kubernetes_privileged:
|
|
952
|
-
container.security_context
|
|
953
|
-
|
|
954
|
-
|
|
981
|
+
if container.security_context is None:
|
|
982
|
+
container.security_context = V1SecurityContext()
|
|
983
|
+
container.security_context.privileged = self.config.kubernetes_privileged
|
|
955
984
|
|
|
956
985
|
# Wrap the container in a spec
|
|
957
986
|
pod_spec = V1PodSpec(
|
|
958
987
|
containers=[container], volumes=volumes, restart_policy="Never"
|
|
959
988
|
)
|
|
989
|
+
|
|
990
|
+
if self.config.kubernetes_pod_security_context:
|
|
991
|
+
pod_spec.security_context = self._load_kubernetes_object(self.config.kubernetes_pod_security_context, V1PodSecurityContext)
|
|
992
|
+
|
|
960
993
|
# Tell the spec where to land
|
|
961
994
|
placement.apply(pod_spec)
|
|
962
995
|
|
|
@@ -2126,7 +2159,18 @@ class KubernetesBatchSystem(BatchSystemCleanupSupport):
|
|
|
2126
2159
|
"privileged operations, such as FUSE. On Toil-managed clusters with --enableFuse, "
|
|
2127
2160
|
"this is set to True. (default: %(default)s)",
|
|
2128
2161
|
)
|
|
2129
|
-
|
|
2162
|
+
parser.add_argument("--kubernetesPodSecurityContext",
|
|
2163
|
+
dest='kubernetes_pod_security_context',
|
|
2164
|
+
type=str,
|
|
2165
|
+
env_var="TOIL_KUBERNETES_POD_SECURITY_CONTEXT",
|
|
2166
|
+
default=None,
|
|
2167
|
+
help="Path to a YAML defining a pod security context to apply to all pods.")
|
|
2168
|
+
parser.add_argument("--kubernetesSecurityContext",
|
|
2169
|
+
dest='kubernetes_security_context',
|
|
2170
|
+
type=str,
|
|
2171
|
+
env_var="TOIL_KUBERNETES_SECURITY_CONTEXT",
|
|
2172
|
+
default=None,
|
|
2173
|
+
help="Path to a YAML defining a security context to apply to all containers.")
|
|
2130
2174
|
OptionType = TypeVar("OptionType")
|
|
2131
2175
|
|
|
2132
2176
|
@classmethod
|
|
@@ -2138,3 +2182,5 @@ class KubernetesBatchSystem(BatchSystemCleanupSupport):
|
|
|
2138
2182
|
)
|
|
2139
2183
|
setOption("kubernetes_pod_timeout")
|
|
2140
2184
|
setOption("kubernetes_privileged")
|
|
2185
|
+
setOption("kubernetes_pod_security_context")
|
|
2186
|
+
setOption("kubernetes_security_context")
|
|
@@ -30,7 +30,7 @@ class BatchSystemLocalSupport(BatchSystemSupport):
|
|
|
30
30
|
"""Adds a local queue for helper jobs, useful for CWL & others."""
|
|
31
31
|
|
|
32
32
|
def __init__(
|
|
33
|
-
self, config: Config, maxCores: float, maxMemory:
|
|
33
|
+
self, config: Config, maxCores: float, maxMemory: float, maxDisk: int
|
|
34
34
|
) -> None:
|
|
35
35
|
super().__init__(config, maxCores, maxMemory, maxDisk)
|
|
36
36
|
max_local_jobs = (
|
|
@@ -40,6 +40,7 @@ from toil.batchSystems.abstractBatchSystem import (
|
|
|
40
40
|
from toil.batchSystems.local_support import BatchSystemLocalSupport
|
|
41
41
|
from toil.batchSystems.mesos import JobQueue, MesosShape, TaskData, ToilJob
|
|
42
42
|
from toil.batchSystems.options import OptionSetter
|
|
43
|
+
from toil.common import Config
|
|
43
44
|
from toil.job import JobDescription
|
|
44
45
|
from toil.lib.conversions import b_to_mib, mib_to_b
|
|
45
46
|
from toil.lib.memoize import strict_bool
|
|
@@ -61,22 +62,26 @@ class MesosBatchSystem(BatchSystemLocalSupport, AbstractScalableBatchSystem, Sch
|
|
|
61
62
|
"""
|
|
62
63
|
|
|
63
64
|
@classmethod
|
|
64
|
-
def supportsAutoDeployment(cls):
|
|
65
|
+
def supportsAutoDeployment(cls) -> bool:
|
|
65
66
|
return True
|
|
66
67
|
|
|
67
68
|
@classmethod
|
|
68
|
-
def supportsWorkerCleanup(cls):
|
|
69
|
+
def supportsWorkerCleanup(cls) -> bool:
|
|
69
70
|
return True
|
|
70
71
|
|
|
71
72
|
class ExecutorInfo:
|
|
72
|
-
def __init__(
|
|
73
|
+
def __init__(
|
|
74
|
+
self, nodeAddress: str, agentId: str, nodeInfo: str, lastSeen: str
|
|
75
|
+
) -> None:
|
|
73
76
|
super().__init__()
|
|
74
77
|
self.nodeAddress = nodeAddress
|
|
75
78
|
self.agentId = agentId
|
|
76
79
|
self.nodeInfo = nodeInfo
|
|
77
80
|
self.lastSeen = lastSeen
|
|
78
81
|
|
|
79
|
-
def __init__(
|
|
82
|
+
def __init__(
|
|
83
|
+
self, config: Config, maxCores: float, maxMemory: float, maxDisk: int
|
|
84
|
+
) -> None:
|
|
80
85
|
super().__init__(config, maxCores, maxMemory, maxDisk)
|
|
81
86
|
|
|
82
87
|
# The auto-deployed resource representing the user script. Will be passed along in every
|
|
@@ -165,13 +170,13 @@ class MesosBatchSystem(BatchSystemLocalSupport, AbstractScalableBatchSystem, Sch
|
|
|
165
170
|
|
|
166
171
|
self._startDriver(config)
|
|
167
172
|
|
|
168
|
-
def setUserScript(self, userScript):
|
|
173
|
+
def setUserScript(self, userScript: str) -> None:
|
|
169
174
|
self.userScript = userScript
|
|
170
175
|
|
|
171
|
-
def ignoreNode(self, nodeAddress):
|
|
176
|
+
def ignoreNode(self, nodeAddress: str) -> None:
|
|
172
177
|
self.ignoredNodes.add(nodeAddress)
|
|
173
178
|
|
|
174
|
-
def unignoreNode(self, nodeAddress):
|
|
179
|
+
def unignoreNode(self, nodeAddress: str) -> None:
|
|
175
180
|
self.ignoredNodes.remove(nodeAddress)
|
|
176
181
|
|
|
177
182
|
def issueBatchJob(
|
|
@@ -179,7 +184,7 @@ class MesosBatchSystem(BatchSystemLocalSupport, AbstractScalableBatchSystem, Sch
|
|
|
179
184
|
command: str,
|
|
180
185
|
jobNode: JobDescription,
|
|
181
186
|
job_environment: Optional[dict[str, str]] = None,
|
|
182
|
-
):
|
|
187
|
+
) -> str:
|
|
183
188
|
"""
|
|
184
189
|
Issues the following command returning a unique jobID. Command is the string to run, memory
|
|
185
190
|
is an int giving the number of bytes the job needs to run in and cores is the number of cpus
|
|
@@ -7,6 +7,7 @@ from abc import ABCMeta, abstractmethod
|
|
|
7
7
|
from contextlib import closing
|
|
8
8
|
from shutil import which
|
|
9
9
|
from urllib.request import urlopen
|
|
10
|
+
from typing import Optional
|
|
10
11
|
|
|
11
12
|
from toil.lib.retry import retry
|
|
12
13
|
from toil.lib.threading import ExceptionalThread, cpu_count
|
|
@@ -25,7 +26,7 @@ class MesosTestSupport:
|
|
|
25
26
|
with closing(urlopen("http://127.0.0.1:5050/version")) as content:
|
|
26
27
|
content.read()
|
|
27
28
|
|
|
28
|
-
def _startMesos(self, numCores=None):
|
|
29
|
+
def _startMesos(self, numCores: Optional[int] = None) -> None:
|
|
29
30
|
if numCores is None:
|
|
30
31
|
numCores = cpu_count()
|
|
31
32
|
shutil.rmtree("/tmp/mesos", ignore_errors=True)
|
|
@@ -52,7 +53,7 @@ class MesosTestSupport:
|
|
|
52
53
|
log.warning("Forcibly killing child which ignored SIGTERM")
|
|
53
54
|
process.kill()
|
|
54
55
|
|
|
55
|
-
def _stopMesos(self):
|
|
56
|
+
def _stopMesos(self) -> None:
|
|
56
57
|
self._stopProcess(self.agent.popen)
|
|
57
58
|
self.agent.join()
|
|
58
59
|
self._stopProcess(self.master.popen)
|
toil/batchSystems/options.py
CHANGED
|
@@ -185,6 +185,7 @@ def add_all_batchsystem_options(parser: Union[ArgumentParser, _ArgumentGroup]) -
|
|
|
185
185
|
"systems such as gridengine, htcondor, torque, slurm, and lsf.",
|
|
186
186
|
)
|
|
187
187
|
|
|
188
|
+
# TODO: Move this to Slurm specifically.
|
|
188
189
|
parser.add_argument(
|
|
189
190
|
"--memoryIsProduct",
|
|
190
191
|
dest="memory_is_product",
|