toil 5.12.0__py3-none-any.whl → 6.1.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 +18 -13
- toil/batchSystems/abstractBatchSystem.py +39 -13
- toil/batchSystems/abstractGridEngineBatchSystem.py +24 -24
- toil/batchSystems/awsBatch.py +14 -14
- toil/batchSystems/cleanup_support.py +7 -3
- toil/batchSystems/contained_executor.py +3 -3
- toil/batchSystems/htcondor.py +0 -1
- toil/batchSystems/kubernetes.py +34 -31
- toil/batchSystems/local_support.py +3 -1
- toil/batchSystems/lsf.py +7 -7
- toil/batchSystems/mesos/batchSystem.py +7 -7
- toil/batchSystems/options.py +32 -83
- toil/batchSystems/registry.py +104 -23
- toil/batchSystems/singleMachine.py +16 -13
- toil/batchSystems/slurm.py +87 -16
- toil/batchSystems/torque.py +0 -1
- toil/bus.py +44 -8
- toil/common.py +544 -753
- toil/cwl/__init__.py +28 -32
- toil/cwl/cwltoil.py +595 -574
- toil/cwl/utils.py +55 -10
- toil/exceptions.py +1 -1
- toil/fileStores/__init__.py +2 -2
- toil/fileStores/abstractFileStore.py +88 -14
- toil/fileStores/cachingFileStore.py +610 -549
- toil/fileStores/nonCachingFileStore.py +46 -22
- toil/job.py +182 -101
- toil/jobStores/abstractJobStore.py +161 -95
- toil/jobStores/aws/jobStore.py +23 -9
- toil/jobStores/aws/utils.py +6 -6
- toil/jobStores/fileJobStore.py +116 -18
- toil/jobStores/googleJobStore.py +16 -7
- toil/jobStores/utils.py +5 -6
- toil/leader.py +87 -56
- toil/lib/accelerators.py +10 -5
- toil/lib/aws/__init__.py +3 -14
- toil/lib/aws/ami.py +22 -9
- toil/lib/aws/iam.py +21 -13
- toil/lib/aws/session.py +2 -16
- toil/lib/aws/utils.py +4 -5
- toil/lib/compatibility.py +1 -1
- toil/lib/conversions.py +26 -3
- toil/lib/docker.py +22 -23
- toil/lib/ec2.py +10 -6
- toil/lib/ec2nodes.py +106 -100
- toil/lib/encryption/_nacl.py +2 -1
- toil/lib/generatedEC2Lists.py +325 -18
- toil/lib/io.py +49 -2
- toil/lib/misc.py +1 -1
- toil/lib/resources.py +9 -2
- toil/lib/threading.py +101 -38
- toil/options/common.py +736 -0
- toil/options/cwl.py +336 -0
- toil/options/wdl.py +37 -0
- toil/provisioners/abstractProvisioner.py +9 -4
- toil/provisioners/aws/__init__.py +3 -6
- toil/provisioners/aws/awsProvisioner.py +6 -0
- toil/provisioners/clusterScaler.py +3 -2
- toil/provisioners/gceProvisioner.py +2 -2
- toil/realtimeLogger.py +2 -1
- toil/resource.py +24 -18
- toil/server/app.py +2 -3
- toil/server/cli/wes_cwl_runner.py +4 -4
- toil/server/utils.py +1 -1
- toil/server/wes/abstract_backend.py +3 -2
- toil/server/wes/amazon_wes_utils.py +5 -4
- toil/server/wes/tasks.py +2 -3
- toil/server/wes/toil_backend.py +2 -10
- toil/server/wsgi_app.py +2 -0
- toil/serviceManager.py +12 -10
- toil/statsAndLogging.py +41 -9
- toil/test/__init__.py +29 -54
- toil/test/batchSystems/batchSystemTest.py +11 -111
- toil/test/batchSystems/test_slurm.py +24 -8
- toil/test/cactus/__init__.py +0 -0
- toil/test/cactus/test_cactus_integration.py +58 -0
- toil/test/cwl/cwlTest.py +438 -223
- toil/test/cwl/glob_dir.cwl +15 -0
- toil/test/cwl/preemptible.cwl +21 -0
- toil/test/cwl/preemptible_expression.cwl +28 -0
- toil/test/cwl/revsort.cwl +1 -1
- toil/test/cwl/revsort2.cwl +1 -1
- toil/test/docs/scriptsTest.py +2 -3
- toil/test/jobStores/jobStoreTest.py +34 -21
- toil/test/lib/aws/test_iam.py +4 -14
- toil/test/lib/aws/test_utils.py +0 -3
- toil/test/lib/dockerTest.py +4 -4
- toil/test/lib/test_ec2.py +12 -17
- toil/test/mesos/helloWorld.py +4 -5
- toil/test/mesos/stress.py +1 -1
- toil/test/{wdl/conftest.py → options/__init__.py} +0 -10
- toil/test/options/options.py +37 -0
- toil/test/provisioners/aws/awsProvisionerTest.py +9 -5
- toil/test/provisioners/clusterScalerTest.py +6 -4
- toil/test/provisioners/clusterTest.py +23 -11
- toil/test/provisioners/gceProvisionerTest.py +0 -6
- toil/test/provisioners/restartScript.py +3 -2
- toil/test/server/serverTest.py +1 -1
- toil/test/sort/restart_sort.py +2 -1
- toil/test/sort/sort.py +2 -1
- toil/test/sort/sortTest.py +2 -13
- toil/test/src/autoDeploymentTest.py +45 -45
- toil/test/src/busTest.py +5 -5
- toil/test/src/checkpointTest.py +2 -2
- toil/test/src/deferredFunctionTest.py +1 -1
- toil/test/src/fileStoreTest.py +32 -16
- toil/test/src/helloWorldTest.py +1 -1
- toil/test/src/importExportFileTest.py +1 -1
- toil/test/src/jobDescriptionTest.py +2 -1
- toil/test/src/jobServiceTest.py +1 -1
- toil/test/src/jobTest.py +18 -18
- toil/test/src/miscTests.py +5 -3
- toil/test/src/promisedRequirementTest.py +3 -3
- toil/test/src/realtimeLoggerTest.py +1 -1
- toil/test/src/resourceTest.py +2 -2
- toil/test/src/restartDAGTest.py +1 -1
- toil/test/src/resumabilityTest.py +36 -2
- toil/test/src/retainTempDirTest.py +1 -1
- toil/test/src/systemTest.py +2 -2
- toil/test/src/toilContextManagerTest.py +2 -2
- toil/test/src/userDefinedJobArgTypeTest.py +1 -1
- toil/test/utils/toilDebugTest.py +98 -32
- toil/test/utils/toilKillTest.py +2 -2
- toil/test/utils/utilsTest.py +23 -3
- toil/test/wdl/wdltoil_test.py +223 -45
- toil/toilState.py +7 -6
- toil/utils/toilClean.py +1 -1
- toil/utils/toilConfig.py +36 -0
- toil/utils/toilDebugFile.py +60 -33
- toil/utils/toilDebugJob.py +39 -12
- toil/utils/toilDestroyCluster.py +1 -1
- toil/utils/toilKill.py +1 -1
- toil/utils/toilLaunchCluster.py +13 -2
- toil/utils/toilMain.py +3 -2
- toil/utils/toilRsyncCluster.py +1 -1
- toil/utils/toilSshCluster.py +1 -1
- toil/utils/toilStats.py +445 -305
- toil/utils/toilStatus.py +2 -5
- toil/version.py +10 -10
- toil/wdl/utils.py +2 -122
- toil/wdl/wdltoil.py +1257 -492
- toil/worker.py +55 -46
- toil-6.1.0.dist-info/METADATA +124 -0
- toil-6.1.0.dist-info/RECORD +241 -0
- {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/WHEEL +1 -1
- {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/entry_points.txt +0 -1
- toil/batchSystems/parasol.py +0 -379
- toil/batchSystems/tes.py +0 -459
- toil/test/batchSystems/parasolTestSupport.py +0 -117
- toil/test/wdl/builtinTest.py +0 -506
- toil/test/wdl/toilwdlTest.py +0 -522
- toil/wdl/toilwdl.py +0 -141
- toil/wdl/versions/dev.py +0 -107
- toil/wdl/versions/draft2.py +0 -980
- toil/wdl/versions/v1.py +0 -794
- toil/wdl/wdl_analysis.py +0 -116
- toil/wdl/wdl_functions.py +0 -997
- toil/wdl/wdl_synthesis.py +0 -1011
- toil/wdl/wdl_types.py +0 -243
- toil-5.12.0.dist-info/METADATA +0 -118
- toil-5.12.0.dist-info/RECORD +0 -244
- /toil/{wdl/versions → options}/__init__.py +0 -0
- {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/LICENSE +0 -0
- {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
$namespaces:
|
|
2
|
+
arv: "http://arvados.org/cwl#"
|
|
3
|
+
|
|
4
|
+
class: CommandLineTool
|
|
5
|
+
doc: "Be preemptible"
|
|
6
|
+
cwlVersion: v1.0
|
|
7
|
+
|
|
8
|
+
inputs: []
|
|
9
|
+
|
|
10
|
+
outputs:
|
|
11
|
+
output:
|
|
12
|
+
type: File
|
|
13
|
+
outputBinding:
|
|
14
|
+
glob: output.txt
|
|
15
|
+
|
|
16
|
+
hints:
|
|
17
|
+
arv:UsePreemptible:
|
|
18
|
+
usePreemptible: true
|
|
19
|
+
|
|
20
|
+
baseCommand: ["echo", "hello"]
|
|
21
|
+
stdout: output.txt
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
$namespaces:
|
|
2
|
+
arv: "http://arvados.org/cwl#"
|
|
3
|
+
|
|
4
|
+
class: CommandLineTool
|
|
5
|
+
doc: "Be preemptible"
|
|
6
|
+
cwlVersion: v1.0
|
|
7
|
+
|
|
8
|
+
inputs:
|
|
9
|
+
- id: preemptible
|
|
10
|
+
type: boolean
|
|
11
|
+
|
|
12
|
+
outputs:
|
|
13
|
+
output:
|
|
14
|
+
type: File
|
|
15
|
+
outputBinding:
|
|
16
|
+
glob: output.txt
|
|
17
|
+
|
|
18
|
+
requirements:
|
|
19
|
+
InlineJavascriptRequirement: {}
|
|
20
|
+
|
|
21
|
+
hints:
|
|
22
|
+
arv:UsePreemptible:
|
|
23
|
+
# This isn't allowed; this always has to be a real boolean and can't be a cwl:Expression. See
|
|
24
|
+
# https://github.com/arvados/arvados/blob/48a0d575e6de34bcda91c489e4aa98df291a8cca/sdk/cwl/arvados_cwl/arv-cwl-schema-v1.1.yml#L345
|
|
25
|
+
usePreemptible: $(inputs.preemptible)
|
|
26
|
+
|
|
27
|
+
baseCommand: ["echo", "hello"]
|
|
28
|
+
stdout: output.txt
|
toil/test/cwl/revsort.cwl
CHANGED
toil/test/cwl/revsort2.cwl
CHANGED
toil/test/docs/scriptsTest.py
CHANGED
|
@@ -2,7 +2,6 @@ import os
|
|
|
2
2
|
import re
|
|
3
3
|
import shutil
|
|
4
4
|
import subprocess
|
|
5
|
-
import tempfile
|
|
6
5
|
import sys
|
|
7
6
|
import unittest
|
|
8
7
|
|
|
@@ -70,8 +69,8 @@ class ToilDocumentationTest(ToilTest):
|
|
|
70
69
|
def testCwlexample(self):
|
|
71
70
|
self.checkExitCode("tutorial_cwlexample.py")
|
|
72
71
|
|
|
73
|
-
def
|
|
74
|
-
self.checkExitCode("
|
|
72
|
+
def testStats(self):
|
|
73
|
+
self.checkExitCode("tutorial_stats.py")
|
|
75
74
|
|
|
76
75
|
def testDynamic(self):
|
|
77
76
|
self.checkExitCode("tutorial_dynamic.py")
|
|
@@ -18,7 +18,6 @@ import logging
|
|
|
18
18
|
import os
|
|
19
19
|
import shutil
|
|
20
20
|
import socketserver
|
|
21
|
-
import tempfile
|
|
22
21
|
import threading
|
|
23
22
|
import time
|
|
24
23
|
import urllib.parse as urlparse
|
|
@@ -27,6 +26,7 @@ from abc import ABCMeta, abstractmethod
|
|
|
27
26
|
from io import BytesIO
|
|
28
27
|
from itertools import chain, islice
|
|
29
28
|
from queue import Queue
|
|
29
|
+
from tempfile import mkstemp
|
|
30
30
|
from threading import Thread
|
|
31
31
|
from typing import Any, Tuple
|
|
32
32
|
from urllib.request import Request, urlopen
|
|
@@ -40,7 +40,7 @@ from toil.job import Job, JobDescription, TemporaryID
|
|
|
40
40
|
from toil.jobStores.abstractJobStore import (NoSuchFileException,
|
|
41
41
|
NoSuchJobException)
|
|
42
42
|
from toil.jobStores.fileJobStore import FileJobStore
|
|
43
|
-
from toil.lib.
|
|
43
|
+
from toil.lib.io import mkdtemp
|
|
44
44
|
from toil.lib.memoize import memoize
|
|
45
45
|
from toil.lib.retry import retry
|
|
46
46
|
from toil.statsAndLogging import StatsAndLogging
|
|
@@ -101,7 +101,8 @@ class AbstractJobStoreTest:
|
|
|
101
101
|
return super().__new__(cls)
|
|
102
102
|
|
|
103
103
|
def _createConfig(self):
|
|
104
|
-
|
|
104
|
+
config = Config()
|
|
105
|
+
return config
|
|
105
106
|
|
|
106
107
|
@abstractmethod
|
|
107
108
|
def _createJobStore(self):
|
|
@@ -224,11 +225,14 @@ class AbstractJobStoreTest:
|
|
|
224
225
|
|
|
225
226
|
def testPersistantFilesToDelete(self):
|
|
226
227
|
"""
|
|
227
|
-
Make sure that updating a job
|
|
228
|
-
|
|
229
|
-
The following demonstrates the job update pattern, where files to
|
|
230
|
-
|
|
231
|
-
|
|
228
|
+
Make sure that updating a job persists filesToDelete.
|
|
229
|
+
|
|
230
|
+
The following demonstrates the job update pattern, where files to
|
|
231
|
+
be deleted atomically with a job update are referenced in
|
|
232
|
+
"filesToDelete" array, which is persisted to disk first. If things
|
|
233
|
+
go wrong during the update, this list of files to delete is used to
|
|
234
|
+
ensure that the updated job and the files are never both visible at
|
|
235
|
+
the same time.
|
|
232
236
|
"""
|
|
233
237
|
|
|
234
238
|
# Create a job.
|
|
@@ -439,7 +443,7 @@ class AbstractJobStoreTest:
|
|
|
439
443
|
self.assertEqual(f.read(), one)
|
|
440
444
|
|
|
441
445
|
# ... and copy it to a temporary physical file on the jobstore1.
|
|
442
|
-
fh, path =
|
|
446
|
+
fh, path = mkstemp()
|
|
443
447
|
try:
|
|
444
448
|
os.close(fh)
|
|
445
449
|
tmpPath = path + '.read-only'
|
|
@@ -543,14 +547,16 @@ class AbstractJobStoreTest:
|
|
|
543
547
|
jobNames = ['testStatsAndLogging_writeLogFiles']
|
|
544
548
|
jobLogList = ['string', b'bytes', '', b'newline\n']
|
|
545
549
|
config = self._createConfig()
|
|
546
|
-
setattr(config, 'writeLogs',
|
|
550
|
+
setattr(config, 'writeLogs', self._createTempDir())
|
|
547
551
|
setattr(config, 'writeLogsGzip', None)
|
|
548
552
|
StatsAndLogging.writeLogFiles(jobNames, jobLogList, config)
|
|
549
|
-
jobLogFile = os.path.join(config.writeLogs, jobNames[0] + '
|
|
553
|
+
jobLogFile = os.path.join(config.writeLogs, jobNames[0] + '_000.log')
|
|
554
|
+
# The log directory should get exactly one file, names after this
|
|
555
|
+
# easy job name with no replacements needed.
|
|
556
|
+
self.assertEqual(os.listdir(config.writeLogs), [os.path.basename(jobLogFile)])
|
|
550
557
|
self.assertTrue(os.path.isfile(jobLogFile))
|
|
551
558
|
with open(jobLogFile) as f:
|
|
552
559
|
self.assertEqual(f.read(), 'string\nbytes\n\nnewline\n')
|
|
553
|
-
os.remove(jobLogFile)
|
|
554
560
|
|
|
555
561
|
def testBatchCreate(self):
|
|
556
562
|
"""Test creation of many jobs."""
|
|
@@ -854,7 +860,7 @@ class AbstractJobStoreTest:
|
|
|
854
860
|
|
|
855
861
|
# Multi-part upload from file
|
|
856
862
|
checksum = hashlib.md5()
|
|
857
|
-
fh, path =
|
|
863
|
+
fh, path = mkstemp()
|
|
858
864
|
try:
|
|
859
865
|
with os.fdopen(fh, 'wb+') as writable:
|
|
860
866
|
with open('/dev/urandom', 'rb') as readable:
|
|
@@ -1042,7 +1048,7 @@ class AbstractJobStoreTest:
|
|
|
1042
1048
|
def testEmptyFileStoreIDIsReadable(self):
|
|
1043
1049
|
"""Simply creates an empty fileStoreID and attempts to read from it."""
|
|
1044
1050
|
id = self.jobstore_initialized.get_empty_file_store_id()
|
|
1045
|
-
fh, path =
|
|
1051
|
+
fh, path = mkstemp()
|
|
1046
1052
|
try:
|
|
1047
1053
|
self.jobstore_initialized.read_file(id, path)
|
|
1048
1054
|
self.assertTrue(os.path.isfile(path))
|
|
@@ -1071,7 +1077,7 @@ class AbstractEncryptedJobStoreTest:
|
|
|
1071
1077
|
|
|
1072
1078
|
def setUp(self):
|
|
1073
1079
|
# noinspection PyAttributeOutsideInit
|
|
1074
|
-
self.sseKeyDir =
|
|
1080
|
+
self.sseKeyDir = mkdtemp()
|
|
1075
1081
|
super().setUp()
|
|
1076
1082
|
|
|
1077
1083
|
def tearDown(self):
|
|
@@ -1139,14 +1145,14 @@ class FileJobStoreTest(AbstractJobStoreTest.Test):
|
|
|
1139
1145
|
return hashlib.md5(f.read()).hexdigest()
|
|
1140
1146
|
|
|
1141
1147
|
def _createExternalStore(self):
|
|
1142
|
-
return
|
|
1148
|
+
return mkdtemp()
|
|
1143
1149
|
|
|
1144
1150
|
def _cleanUpExternalStore(self, dirPath):
|
|
1145
|
-
shutil.rmtree(dirPath)
|
|
1151
|
+
shutil.rmtree(dirPath, ignore_errors=True)
|
|
1146
1152
|
|
|
1147
1153
|
def testPreserveFileName(self):
|
|
1148
1154
|
"""Check that the fileID ends with the given file name."""
|
|
1149
|
-
fh, path =
|
|
1155
|
+
fh, path = mkstemp()
|
|
1150
1156
|
try:
|
|
1151
1157
|
os.close(fh)
|
|
1152
1158
|
job = self.arbitraryJob()
|
|
@@ -1458,6 +1464,8 @@ class AWSJobStoreTest(AbstractJobStoreTest.Test):
|
|
|
1458
1464
|
|
|
1459
1465
|
def _hashTestFile(self, url: str) -> str:
|
|
1460
1466
|
from toil.jobStores.aws.jobStore import AWSJobStore
|
|
1467
|
+
from toil.lib.aws.utils import get_object_for_url
|
|
1468
|
+
str(AWSJobStore) # to prevent removal of that import
|
|
1461
1469
|
key = get_object_for_url(urlparse.urlparse(url), existing=True)
|
|
1462
1470
|
contents = key.get().get('Body').read()
|
|
1463
1471
|
return hashlib.md5(contents).hexdigest()
|
|
@@ -1465,7 +1473,7 @@ class AWSJobStoreTest(AbstractJobStoreTest.Test):
|
|
|
1465
1473
|
def _createExternalStore(self):
|
|
1466
1474
|
"""A S3.Bucket instance is returned"""
|
|
1467
1475
|
from toil.jobStores.aws.jobStore import establish_boto3_session
|
|
1468
|
-
from toil.lib.aws.utils import retry_s3
|
|
1476
|
+
from toil.lib.aws.utils import retry_s3, create_s3_bucket
|
|
1469
1477
|
|
|
1470
1478
|
resource = establish_boto3_session().resource(
|
|
1471
1479
|
"s3", region_name=self.awsRegion()
|
|
@@ -1480,8 +1488,13 @@ class AWSJobStoreTest(AbstractJobStoreTest.Test):
|
|
|
1480
1488
|
return bucket
|
|
1481
1489
|
|
|
1482
1490
|
def _cleanUpExternalStore(self, bucket):
|
|
1483
|
-
|
|
1484
|
-
|
|
1491
|
+
from toil.jobStores.aws.jobStore import establish_boto3_session
|
|
1492
|
+
from toil.lib.aws.utils import delete_s3_bucket
|
|
1493
|
+
|
|
1494
|
+
resource = establish_boto3_session().resource(
|
|
1495
|
+
"s3", region_name=self.awsRegion()
|
|
1496
|
+
)
|
|
1497
|
+
delete_s3_bucket(resource, bucket.name)
|
|
1485
1498
|
|
|
1486
1499
|
def _largeLogEntrySize(self):
|
|
1487
1500
|
from toil.jobStores.aws.jobStore import AWSJobStore
|
toil/test/lib/aws/test_iam.py
CHANGED
|
@@ -11,25 +11,15 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
import json
|
|
14
15
|
import logging
|
|
15
|
-
import os
|
|
16
|
-
import uuid
|
|
17
|
-
from typing import Optional
|
|
18
|
-
|
|
19
|
-
import pytest
|
|
20
|
-
|
|
21
|
-
from toil.jobStores.aws.jobStore import AWSJobStore
|
|
22
|
-
from toil.lib.aws import iam
|
|
23
|
-
from toil.lib.aws.utils import create_s3_bucket
|
|
24
|
-
from toil.lib.ec2 import establish_boto3_session
|
|
25
|
-
from toil.test import ToilTest, needs_aws_s3
|
|
26
16
|
|
|
27
|
-
import moto
|
|
28
17
|
import boto3
|
|
29
|
-
import json
|
|
30
|
-
|
|
31
18
|
from moto import mock_iam
|
|
32
19
|
|
|
20
|
+
from toil.lib.aws import iam
|
|
21
|
+
from toil.test import ToilTest
|
|
22
|
+
|
|
33
23
|
logger = logging.getLogger(__name__)
|
|
34
24
|
logging.basicConfig(level=logging.DEBUG)
|
|
35
25
|
|
toil/test/lib/aws/test_utils.py
CHANGED
toil/test/lib/dockerTest.py
CHANGED
|
@@ -20,8 +20,8 @@ from threading import Thread
|
|
|
20
20
|
|
|
21
21
|
from docker.errors import ContainerError
|
|
22
22
|
from toil.common import Toil
|
|
23
|
-
from toil.job import Job
|
|
24
23
|
from toil.exceptions import FailedJobsException
|
|
24
|
+
from toil.job import Job
|
|
25
25
|
from toil.lib.docker import (FORGO,
|
|
26
26
|
RM,
|
|
27
27
|
STOP,
|
|
@@ -248,12 +248,12 @@ class DockerTest(ToilTest):
|
|
|
248
248
|
deferParam=None)
|
|
249
249
|
|
|
250
250
|
def testDockerPipeChain(self, caching=False):
|
|
251
|
-
"""
|
|
251
|
+
r"""
|
|
252
252
|
Test for piping API for dockerCall(). Using this API (activated when
|
|
253
253
|
list of argument lists is given as parameters), commands a piped
|
|
254
254
|
together into a chain.
|
|
255
|
-
ex: parameters=[ ['printf', 'x\n y\n'], ['wc', '-l'] ] should execute:
|
|
256
|
-
printf 'x\n y\n' | wc -l
|
|
255
|
+
ex: ``parameters=[ ['printf', 'x\n y\n'], ['wc', '-l'] ]`` should execute:
|
|
256
|
+
``printf 'x\n y\n' | wc -l``
|
|
257
257
|
"""
|
|
258
258
|
options = Job.Runner.getDefaultOptions(os.path.join(self.tempDir, 'jobstore'))
|
|
259
259
|
options.logLevel = self.dockerTestLogLevel
|
toil/test/lib/test_ec2.py
CHANGED
|
@@ -13,26 +13,29 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import logging
|
|
15
15
|
import os
|
|
16
|
+
|
|
16
17
|
import pytest
|
|
17
18
|
|
|
18
19
|
from toil.lib.aws.ami import (aws_marketplace_flatcar_ami_search,
|
|
19
|
-
get_flatcar_ami,
|
|
20
20
|
feed_flatcar_ami_release,
|
|
21
|
-
flatcar_release_feed_amis
|
|
22
|
-
|
|
23
|
-
from toil.test import ToilTest, needs_aws_ec2
|
|
21
|
+
flatcar_release_feed_amis,
|
|
22
|
+
get_flatcar_ami)
|
|
23
|
+
from toil.test import ToilTest, needs_aws_ec2, needs_online
|
|
24
24
|
|
|
25
25
|
logger = logging.getLogger(__name__)
|
|
26
26
|
logging.basicConfig(level=logging.DEBUG)
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
@needs_online
|
|
29
29
|
class FlatcarFeedTest(ToilTest):
|
|
30
|
-
"""Test accessing the
|
|
31
|
-
|
|
30
|
+
"""Test accessing the Flatcar AMI release feed, independent of the AWS API"""
|
|
31
|
+
|
|
32
|
+
# Note that we need to support getting an empty list back, because
|
|
33
|
+
# sometimes the Flatcar feeds are just down, and we can't fail CI at those
|
|
34
|
+
# times.
|
|
35
|
+
|
|
32
36
|
def test_parse_archive_feed(self):
|
|
33
37
|
"""Make sure we can get a Flatcar release from the Internet Archive."""
|
|
34
38
|
amis = list(flatcar_release_feed_amis('us-west-2', 'amd64', 'archive'))
|
|
35
|
-
self.assertTrue(len(amis) > 0)
|
|
36
39
|
for ami in amis:
|
|
37
40
|
self.assertEqual(len(ami), len('ami-02b46c73fed689d1c'))
|
|
38
41
|
self.assertTrue(ami.startswith('ami-'))
|
|
@@ -40,30 +43,22 @@ class FlatcarFeedTest(ToilTest):
|
|
|
40
43
|
def test_parse_beta_feed(self):
|
|
41
44
|
"""Make sure we can get a Flatcar release from the beta channel."""
|
|
42
45
|
amis = list(flatcar_release_feed_amis('us-west-2', 'amd64', 'beta'))
|
|
43
|
-
self.assertTrue(len(amis) > 0)
|
|
44
46
|
for ami in amis:
|
|
45
47
|
self.assertEqual(len(ami), len('ami-02b46c73fed689d1c'))
|
|
46
48
|
self.assertTrue(ami.startswith('ami-'))
|
|
47
49
|
|
|
48
|
-
# TODO: This will fail until https://github.com/flatcar/Flatcar/issues/962 is fixed
|
|
49
|
-
@pytest.mark.xfail
|
|
50
50
|
def test_parse_stable_feed(self):
|
|
51
51
|
"""Make sure we can get a Flatcar release from the stable channel."""
|
|
52
52
|
amis = list(flatcar_release_feed_amis('us-west-2', 'amd64', 'stable'))
|
|
53
|
-
self.assertTrue(len(amis) > 0)
|
|
54
53
|
for ami in amis:
|
|
55
54
|
self.assertEqual(len(ami), len('ami-02b46c73fed689d1c'))
|
|
56
55
|
self.assertTrue(ami.startswith('ami-'))
|
|
57
56
|
|
|
58
|
-
def test_bypass_stable_feed(self):
|
|
59
|
-
"""Make sure we can either get or safely not get a Flatcar release from the stable channel."""
|
|
60
|
-
list(flatcar_release_feed_amis('us-west-2', 'amd64', 'stable'))
|
|
61
|
-
# Ifd we get here we safely managed to iterate everything.
|
|
62
|
-
|
|
63
57
|
@needs_aws_ec2
|
|
64
58
|
class AMITest(ToilTest):
|
|
65
59
|
@classmethod
|
|
66
60
|
def setUpClass(cls):
|
|
61
|
+
from toil.lib.aws.session import establish_boto3_session
|
|
67
62
|
session = establish_boto3_session(region_name='us-west-2')
|
|
68
63
|
cls.ec2_client = session.client('ec2')
|
|
69
64
|
|
toil/test/mesos/helloWorld.py
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
A simple user script for Toil
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
import
|
|
18
|
+
from configargparse import ArgumentParser
|
|
19
19
|
|
|
20
20
|
from toil.common import Toil
|
|
21
21
|
from toil.job import Job
|
|
@@ -25,14 +25,13 @@ parentMessage = "The parent job is now running!"
|
|
|
25
25
|
|
|
26
26
|
def hello_world(job):
|
|
27
27
|
|
|
28
|
-
job.fileStore.
|
|
28
|
+
job.fileStore.log_to_leader(parentMessage)
|
|
29
29
|
with open('foo_bam.txt', 'w') as handle:
|
|
30
30
|
handle.write('\nThis is a triumph...\n')
|
|
31
31
|
|
|
32
32
|
# Assign FileStoreID to a given file
|
|
33
33
|
foo_bam = job.fileStore.writeGlobalFile('foo_bam.txt')
|
|
34
34
|
|
|
35
|
-
|
|
36
35
|
# Spawn child
|
|
37
36
|
job.addChildJobFn(hello_world_child, foo_bam, memory=100, cores=0.5, disk="3G")
|
|
38
37
|
|
|
@@ -40,7 +39,7 @@ def hello_world(job):
|
|
|
40
39
|
def hello_world_child(job, hw):
|
|
41
40
|
|
|
42
41
|
path = job.fileStore.readGlobalFile(hw)
|
|
43
|
-
job.fileStore.
|
|
42
|
+
job.fileStore.log_to_leader(childMessage)
|
|
44
43
|
# NOTE: path and the udpated file are stored to /tmp
|
|
45
44
|
# If we want to SAVE our changes to this tmp file, we must write it out.
|
|
46
45
|
with open(path) as r:
|
|
@@ -56,7 +55,7 @@ def hello_world_child(job, hw):
|
|
|
56
55
|
def main():
|
|
57
56
|
# Boilerplate -- startToil requires options
|
|
58
57
|
|
|
59
|
-
parser =
|
|
58
|
+
parser = ArgumentParser()
|
|
60
59
|
Job.Runner.addToilOptions(parser)
|
|
61
60
|
options = parser.parse_args()
|
|
62
61
|
|
toil/test/mesos/stress.py
CHANGED
|
@@ -11,13 +11,3 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
# https://pytest.org/latest/example/pythoncollection.html
|
|
16
|
-
|
|
17
|
-
collect_ignore = []
|
|
18
|
-
|
|
19
|
-
try:
|
|
20
|
-
import wdlparse
|
|
21
|
-
print(wdlparse.__file__) # keep this import from being removed
|
|
22
|
-
except ImportError:
|
|
23
|
-
collect_ignore.append("toilwdl.py")
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from configargparse import ArgParser
|
|
2
|
+
|
|
3
|
+
from toil.common import addOptions, Toil
|
|
4
|
+
from toil.test import ToilTest
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OptionsTest(ToilTest):
|
|
8
|
+
"""
|
|
9
|
+
Class to test functionality of all Toil options
|
|
10
|
+
"""
|
|
11
|
+
def test_default_caching_slurm(self):
|
|
12
|
+
"""
|
|
13
|
+
Test to ensure that caching will be set to false when running on Slurm
|
|
14
|
+
:return:
|
|
15
|
+
"""
|
|
16
|
+
parser = ArgParser()
|
|
17
|
+
addOptions(parser, jobstore_as_flag=True, wdl=False, cwl=False)
|
|
18
|
+
test_args = ["--jobstore=example-jobstore", "--batchSystem=slurm"]
|
|
19
|
+
options = parser.parse_args(test_args)
|
|
20
|
+
with Toil(options) as toil:
|
|
21
|
+
caching_value = toil.config.caching
|
|
22
|
+
self.assertEqual(caching_value, False)
|
|
23
|
+
|
|
24
|
+
def test_caching_option_priority(self):
|
|
25
|
+
"""
|
|
26
|
+
Test to ensure that the --caching option takes priority over the default_caching() return value
|
|
27
|
+
:return:
|
|
28
|
+
"""
|
|
29
|
+
parser = ArgParser()
|
|
30
|
+
addOptions(parser, jobstore_as_flag=True, wdl=False, cwl=False)
|
|
31
|
+
# the kubernetes batchsystem (and I think all batchsystems including singlemachine) return False
|
|
32
|
+
# for default_caching
|
|
33
|
+
test_args = ["--jobstore=example-jobstore", "--batchSystem=kubernetes", "--caching=True"]
|
|
34
|
+
options = parser.parse_args(test_args)
|
|
35
|
+
with Toil(options) as toil:
|
|
36
|
+
caching_value = toil.config.caching
|
|
37
|
+
self.assertEqual(caching_value, True)
|
|
@@ -29,6 +29,7 @@ from toil.test import (ToilTest,
|
|
|
29
29
|
integrative,
|
|
30
30
|
needs_aws_ec2,
|
|
31
31
|
needs_fetchable_appliance,
|
|
32
|
+
needs_mesos,
|
|
32
33
|
slow,
|
|
33
34
|
timeLimit)
|
|
34
35
|
from toil.test.provisioners.clusterTest import AbstractClusterTest
|
|
@@ -171,9 +172,6 @@ class AbstractAWSAutoscaleTest(AbstractClusterTest):
|
|
|
171
172
|
venv_command = ['virtualenv', '--system-site-packages', '--python', exactPython, '--never-download', self.venvDir]
|
|
172
173
|
self.sshUtil(venv_command)
|
|
173
174
|
|
|
174
|
-
upgrade_command = [self.pip(), 'install', 'setuptools==28.7.1', 'pyyaml==3.12']
|
|
175
|
-
self.sshUtil(upgrade_command)
|
|
176
|
-
|
|
177
175
|
log.info('Set up script...')
|
|
178
176
|
self._getScript()
|
|
179
177
|
|
|
@@ -214,6 +212,7 @@ class AbstractAWSAutoscaleTest(AbstractClusterTest):
|
|
|
214
212
|
|
|
215
213
|
|
|
216
214
|
@integrative
|
|
215
|
+
@needs_mesos
|
|
217
216
|
@pytest.mark.timeout(1800)
|
|
218
217
|
class AWSAutoscaleTest(AbstractAWSAutoscaleTest):
|
|
219
218
|
def __init__(self, name):
|
|
@@ -282,6 +281,7 @@ class AWSAutoscaleTest(AbstractAWSAutoscaleTest):
|
|
|
282
281
|
|
|
283
282
|
|
|
284
283
|
@integrative
|
|
284
|
+
@needs_mesos
|
|
285
285
|
@pytest.mark.timeout(2400)
|
|
286
286
|
class AWSStaticAutoscaleTest(AWSAutoscaleTest):
|
|
287
287
|
"""Runs the tests on a statically provisioned cluster with autoscaling enabled."""
|
|
@@ -357,6 +357,7 @@ class AWSManagedAutoscaleTest(AWSAutoscaleTest):
|
|
|
357
357
|
|
|
358
358
|
|
|
359
359
|
@integrative
|
|
360
|
+
@needs_mesos
|
|
360
361
|
@pytest.mark.timeout(1200)
|
|
361
362
|
class AWSAutoscaleTestMultipleNodeTypes(AbstractAWSAutoscaleTest):
|
|
362
363
|
def __init__(self, name):
|
|
@@ -396,6 +397,7 @@ class AWSAutoscaleTestMultipleNodeTypes(AbstractAWSAutoscaleTest):
|
|
|
396
397
|
|
|
397
398
|
|
|
398
399
|
@integrative
|
|
400
|
+
@needs_mesos
|
|
399
401
|
@pytest.mark.timeout(1200)
|
|
400
402
|
class AWSRestartTest(AbstractAWSAutoscaleTest):
|
|
401
403
|
"""This test insures autoscaling works on a restarted Toil run."""
|
|
@@ -412,9 +414,10 @@ class AWSRestartTest(AbstractAWSAutoscaleTest):
|
|
|
412
414
|
|
|
413
415
|
def _getScript(self):
|
|
414
416
|
def restartScript():
|
|
415
|
-
import argparse
|
|
416
417
|
import os
|
|
417
418
|
|
|
419
|
+
from configargparse import ArgumentParser
|
|
420
|
+
|
|
418
421
|
from toil.job import Job
|
|
419
422
|
|
|
420
423
|
def f0(job):
|
|
@@ -422,7 +425,7 @@ class AWSRestartTest(AbstractAWSAutoscaleTest):
|
|
|
422
425
|
raise RuntimeError('failed on purpose')
|
|
423
426
|
|
|
424
427
|
if __name__ == '__main__':
|
|
425
|
-
parser =
|
|
428
|
+
parser = ArgumentParser()
|
|
426
429
|
Job.Runner.addToilOptions(parser)
|
|
427
430
|
options = parser.parse_args()
|
|
428
431
|
rootJob = Job.wrapJobFn(f0, cores=0.5, memory='50 M', disk='50 M')
|
|
@@ -458,6 +461,7 @@ class AWSRestartTest(AbstractAWSAutoscaleTest):
|
|
|
458
461
|
|
|
459
462
|
|
|
460
463
|
@integrative
|
|
464
|
+
@needs_mesos
|
|
461
465
|
@pytest.mark.timeout(1200)
|
|
462
466
|
class PreemptibleDeficitCompensationTest(AbstractAWSAutoscaleTest):
|
|
463
467
|
def __init__(self, name):
|
|
@@ -19,16 +19,16 @@ import time
|
|
|
19
19
|
import uuid
|
|
20
20
|
from argparse import Namespace
|
|
21
21
|
from collections import defaultdict
|
|
22
|
-
from contextlib import contextmanager
|
|
23
22
|
from queue import Empty, Queue
|
|
24
23
|
from threading import Event, Thread
|
|
25
|
-
from typing import
|
|
24
|
+
from typing import List, Optional, Set, Tuple
|
|
26
25
|
from unittest.mock import MagicMock
|
|
27
26
|
|
|
28
27
|
from toil.batchSystems.abstractBatchSystem import (AbstractBatchSystem,
|
|
29
28
|
AbstractScalableBatchSystem,
|
|
30
29
|
NodeInfo)
|
|
31
|
-
from toil.common import Config
|
|
30
|
+
from toil.common import Config
|
|
31
|
+
from toil.options.common import defaultTargetTime
|
|
32
32
|
from toil.job import JobDescription
|
|
33
33
|
from toil.lib.conversions import human2bytes as h2b
|
|
34
34
|
from toil.provisioners.abstractProvisioner import AbstractProvisioner, Shape
|
|
@@ -873,7 +873,9 @@ class MockBatchSystemAndProvisioner(AbstractScalableBatchSystem, AbstractProvisi
|
|
|
873
873
|
return self.jobQueue.qsize()
|
|
874
874
|
|
|
875
875
|
def getJobs(self):
|
|
876
|
-
|
|
876
|
+
# jobBatchSystemIDToIssuedJob may be modified while we are working.
|
|
877
|
+
# So copy it.
|
|
878
|
+
return dict(self.jobBatchSystemIDToIssuedJob).values()
|
|
877
879
|
|
|
878
880
|
# AbstractScalableBatchSystem functionality
|
|
879
881
|
def getNodes(self, preemptible: Optional[bool] = False, timeout: int = 600):
|