toil 6.1.0a1__py3-none-any.whl → 8.0.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 +122 -315
- toil/batchSystems/__init__.py +1 -0
- toil/batchSystems/abstractBatchSystem.py +173 -89
- toil/batchSystems/abstractGridEngineBatchSystem.py +272 -148
- toil/batchSystems/awsBatch.py +244 -135
- toil/batchSystems/cleanup_support.py +26 -16
- toil/batchSystems/contained_executor.py +31 -28
- toil/batchSystems/gridengine.py +86 -50
- toil/batchSystems/htcondor.py +166 -89
- toil/batchSystems/kubernetes.py +632 -382
- toil/batchSystems/local_support.py +20 -15
- toil/batchSystems/lsf.py +134 -81
- toil/batchSystems/lsfHelper.py +13 -11
- toil/batchSystems/mesos/__init__.py +41 -29
- toil/batchSystems/mesos/batchSystem.py +290 -151
- toil/batchSystems/mesos/executor.py +79 -50
- toil/batchSystems/mesos/test/__init__.py +31 -23
- toil/batchSystems/options.py +46 -28
- toil/batchSystems/registry.py +53 -19
- toil/batchSystems/singleMachine.py +296 -125
- toil/batchSystems/slurm.py +603 -138
- toil/batchSystems/torque.py +47 -33
- toil/bus.py +186 -76
- toil/common.py +664 -368
- toil/cwl/__init__.py +1 -1
- toil/cwl/cwltoil.py +1136 -483
- toil/cwl/utils.py +17 -22
- toil/deferred.py +63 -42
- toil/exceptions.py +5 -3
- toil/fileStores/__init__.py +5 -5
- toil/fileStores/abstractFileStore.py +140 -60
- toil/fileStores/cachingFileStore.py +717 -269
- toil/fileStores/nonCachingFileStore.py +116 -87
- toil/job.py +1225 -368
- toil/jobStores/abstractJobStore.py +416 -266
- toil/jobStores/aws/jobStore.py +863 -477
- toil/jobStores/aws/utils.py +201 -120
- toil/jobStores/conftest.py +3 -2
- toil/jobStores/fileJobStore.py +292 -154
- toil/jobStores/googleJobStore.py +140 -74
- toil/jobStores/utils.py +36 -15
- toil/leader.py +668 -272
- toil/lib/accelerators.py +115 -18
- toil/lib/aws/__init__.py +74 -31
- toil/lib/aws/ami.py +122 -87
- toil/lib/aws/iam.py +284 -108
- toil/lib/aws/s3.py +31 -0
- toil/lib/aws/session.py +214 -39
- toil/lib/aws/utils.py +287 -231
- toil/lib/bioio.py +13 -5
- toil/lib/compatibility.py +11 -6
- toil/lib/conversions.py +104 -47
- toil/lib/docker.py +131 -103
- toil/lib/ec2.py +361 -199
- toil/lib/ec2nodes.py +174 -106
- toil/lib/encryption/_dummy.py +5 -3
- toil/lib/encryption/_nacl.py +10 -6
- toil/lib/encryption/conftest.py +1 -0
- toil/lib/exceptions.py +26 -7
- toil/lib/expando.py +5 -3
- toil/lib/ftp_utils.py +217 -0
- toil/lib/generatedEC2Lists.py +127 -19
- toil/lib/humanize.py +6 -2
- toil/lib/integration.py +341 -0
- toil/lib/io.py +141 -15
- toil/lib/iterables.py +4 -2
- toil/lib/memoize.py +12 -8
- toil/lib/misc.py +66 -21
- toil/lib/objects.py +2 -2
- toil/lib/resources.py +68 -15
- toil/lib/retry.py +126 -81
- toil/lib/threading.py +299 -82
- toil/lib/throttle.py +16 -15
- toil/options/common.py +843 -409
- toil/options/cwl.py +175 -90
- toil/options/runner.py +50 -0
- toil/options/wdl.py +73 -17
- toil/provisioners/__init__.py +117 -46
- toil/provisioners/abstractProvisioner.py +332 -157
- toil/provisioners/aws/__init__.py +70 -33
- toil/provisioners/aws/awsProvisioner.py +1145 -715
- toil/provisioners/clusterScaler.py +541 -279
- toil/provisioners/gceProvisioner.py +282 -179
- toil/provisioners/node.py +155 -79
- toil/realtimeLogger.py +34 -22
- toil/resource.py +137 -75
- toil/server/app.py +128 -62
- toil/server/celery_app.py +3 -1
- toil/server/cli/wes_cwl_runner.py +82 -53
- toil/server/utils.py +54 -28
- toil/server/wes/abstract_backend.py +64 -26
- toil/server/wes/amazon_wes_utils.py +21 -15
- toil/server/wes/tasks.py +121 -63
- toil/server/wes/toil_backend.py +142 -107
- toil/server/wsgi_app.py +4 -3
- toil/serviceManager.py +58 -22
- toil/statsAndLogging.py +224 -70
- toil/test/__init__.py +282 -183
- toil/test/batchSystems/batchSystemTest.py +460 -210
- toil/test/batchSystems/batch_system_plugin_test.py +90 -0
- toil/test/batchSystems/test_gridengine.py +173 -0
- toil/test/batchSystems/test_lsf_helper.py +67 -58
- toil/test/batchSystems/test_slurm.py +110 -49
- toil/test/cactus/__init__.py +0 -0
- toil/test/cactus/test_cactus_integration.py +56 -0
- toil/test/cwl/cwlTest.py +496 -287
- toil/test/cwl/measure_default_memory.cwl +12 -0
- toil/test/cwl/not_run_required_input.cwl +29 -0
- toil/test/cwl/scatter_duplicate_outputs.cwl +40 -0
- toil/test/cwl/seqtk_seq.cwl +1 -1
- toil/test/docs/scriptsTest.py +69 -46
- toil/test/jobStores/jobStoreTest.py +427 -264
- toil/test/lib/aws/test_iam.py +118 -50
- toil/test/lib/aws/test_s3.py +16 -9
- toil/test/lib/aws/test_utils.py +5 -6
- toil/test/lib/dockerTest.py +118 -141
- toil/test/lib/test_conversions.py +113 -115
- toil/test/lib/test_ec2.py +58 -50
- toil/test/lib/test_integration.py +104 -0
- toil/test/lib/test_misc.py +12 -5
- toil/test/mesos/MesosDataStructuresTest.py +23 -10
- toil/test/mesos/helloWorld.py +7 -6
- toil/test/mesos/stress.py +25 -20
- toil/test/options/__init__.py +13 -0
- toil/test/options/options.py +42 -0
- toil/test/provisioners/aws/awsProvisionerTest.py +320 -150
- toil/test/provisioners/clusterScalerTest.py +440 -250
- toil/test/provisioners/clusterTest.py +166 -44
- toil/test/provisioners/gceProvisionerTest.py +174 -100
- toil/test/provisioners/provisionerTest.py +25 -13
- toil/test/provisioners/restartScript.py +5 -4
- toil/test/server/serverTest.py +188 -141
- toil/test/sort/restart_sort.py +137 -68
- toil/test/sort/sort.py +134 -66
- toil/test/sort/sortTest.py +91 -49
- toil/test/src/autoDeploymentTest.py +141 -101
- toil/test/src/busTest.py +20 -18
- toil/test/src/checkpointTest.py +8 -2
- toil/test/src/deferredFunctionTest.py +49 -35
- toil/test/src/dockerCheckTest.py +32 -24
- toil/test/src/environmentTest.py +135 -0
- toil/test/src/fileStoreTest.py +539 -272
- toil/test/src/helloWorldTest.py +7 -4
- toil/test/src/importExportFileTest.py +61 -31
- toil/test/src/jobDescriptionTest.py +46 -21
- toil/test/src/jobEncapsulationTest.py +2 -0
- toil/test/src/jobFileStoreTest.py +74 -50
- toil/test/src/jobServiceTest.py +187 -73
- toil/test/src/jobTest.py +121 -71
- toil/test/src/miscTests.py +19 -18
- toil/test/src/promisedRequirementTest.py +82 -36
- toil/test/src/promisesTest.py +7 -6
- toil/test/src/realtimeLoggerTest.py +10 -6
- toil/test/src/regularLogTest.py +71 -37
- toil/test/src/resourceTest.py +80 -49
- toil/test/src/restartDAGTest.py +36 -22
- toil/test/src/resumabilityTest.py +9 -2
- toil/test/src/retainTempDirTest.py +45 -14
- toil/test/src/systemTest.py +12 -8
- toil/test/src/threadingTest.py +44 -25
- toil/test/src/toilContextManagerTest.py +10 -7
- toil/test/src/userDefinedJobArgTypeTest.py +8 -5
- toil/test/src/workerTest.py +73 -23
- toil/test/utils/toilDebugTest.py +103 -33
- toil/test/utils/toilKillTest.py +4 -5
- toil/test/utils/utilsTest.py +245 -106
- toil/test/wdl/wdltoil_test.py +818 -149
- toil/test/wdl/wdltoil_test_kubernetes.py +91 -0
- toil/toilState.py +120 -35
- toil/utils/toilConfig.py +13 -4
- toil/utils/toilDebugFile.py +44 -27
- toil/utils/toilDebugJob.py +214 -27
- toil/utils/toilDestroyCluster.py +11 -6
- toil/utils/toilKill.py +8 -3
- toil/utils/toilLaunchCluster.py +256 -140
- toil/utils/toilMain.py +37 -16
- toil/utils/toilRsyncCluster.py +32 -14
- toil/utils/toilSshCluster.py +49 -22
- toil/utils/toilStats.py +356 -273
- toil/utils/toilStatus.py +292 -139
- toil/utils/toilUpdateEC2Instances.py +3 -1
- toil/version.py +12 -12
- toil/wdl/utils.py +5 -5
- toil/wdl/wdltoil.py +3913 -1033
- toil/worker.py +367 -184
- {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/LICENSE +25 -0
- toil-8.0.0.dist-info/METADATA +173 -0
- toil-8.0.0.dist-info/RECORD +253 -0
- {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/WHEEL +1 -1
- toil-6.1.0a1.dist-info/METADATA +0 -125
- toil-6.1.0a1.dist-info/RECORD +0 -237
- {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/entry_points.txt +0 -0
- {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/top_level.txt +0 -0
|
@@ -13,9 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import logging
|
|
15
15
|
|
|
16
|
-
from toil.lib.conversions import
|
|
17
|
-
hms_duration_to_seconds,
|
|
18
|
-
human2bytes)
|
|
16
|
+
from toil.lib.conversions import convert_units, hms_duration_to_seconds, human2bytes
|
|
19
17
|
from toil.test import ToilTest
|
|
20
18
|
|
|
21
19
|
logger = logging.getLogger(__name__)
|
|
@@ -79,135 +77,135 @@ class ConversionTest(ToilTest):
|
|
|
79
77
|
"11234234 KB": "0.0112 TB",
|
|
80
78
|
"11234234 MB": "11.2342 TB",
|
|
81
79
|
"11234234 GB": "11234.2340 TB",
|
|
82
|
-
"11234234 TB": "11234234.0000 TB"
|
|
80
|
+
"11234234 TB": "11234234.0000 TB",
|
|
83
81
|
}
|
|
84
82
|
results = {}
|
|
85
83
|
for i in (0, 0.1, 0.5, 0.9, 1, 7, 7.42423, 10, 100, 1000, 11234234):
|
|
86
|
-
for src_unit in [
|
|
87
|
-
for dst_unit in [
|
|
84
|
+
for src_unit in ["B", "KB", "MB", "GB", "TB"]:
|
|
85
|
+
for dst_unit in ["B", "KB", "MB", "GB", "TB"]:
|
|
88
86
|
converted = convert_units(i, src_unit, dst_unit)
|
|
89
|
-
results[f
|
|
87
|
+
results[f"{i} {src_unit}"] = f"{converted:.4f} {dst_unit}"
|
|
90
88
|
self.assertEqual(results, expected_conversions)
|
|
91
89
|
|
|
92
90
|
def test_human2bytes(self):
|
|
93
91
|
expected_results = {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
92
|
+
"0 b": 0,
|
|
93
|
+
"0 Ki": 0,
|
|
94
|
+
"0 Mi": 0,
|
|
95
|
+
"0 Gi": 0,
|
|
96
|
+
"0 Ti": 0,
|
|
97
|
+
"0 K": 0,
|
|
98
|
+
"0 M": 0,
|
|
99
|
+
"0 G": 0,
|
|
100
|
+
"0 T": 0,
|
|
101
|
+
"0.1 b": 0,
|
|
102
|
+
"0.1 Ki": 102,
|
|
103
|
+
"0.1 Mi": 104857,
|
|
104
|
+
"0.1 Gi": 107374182,
|
|
105
|
+
"0.1 Ti": 109951162777,
|
|
106
|
+
"0.1 K": 100,
|
|
107
|
+
"0.1 M": 100000,
|
|
108
|
+
"0.1 G": 100000000,
|
|
109
|
+
"0.1 T": 100000000000,
|
|
110
|
+
"0.5 b": 0,
|
|
111
|
+
"0.5 Ki": 512,
|
|
112
|
+
"0.5 Mi": 524288,
|
|
113
|
+
"0.5 Gi": 536870912,
|
|
114
|
+
"0.5 Ti": 549755813888,
|
|
115
|
+
"0.5 K": 500,
|
|
116
|
+
"0.5 M": 500000,
|
|
117
|
+
"0.5 G": 500000000,
|
|
118
|
+
"0.5 T": 500000000000,
|
|
119
|
+
"0.9 b": 0,
|
|
120
|
+
"0.9 Ki": 921,
|
|
121
|
+
"0.9 Mi": 943718,
|
|
122
|
+
"0.9 Gi": 966367641,
|
|
123
|
+
"0.9 Ti": 989560464998,
|
|
124
|
+
"0.9 K": 900,
|
|
125
|
+
"0.9 M": 900000,
|
|
126
|
+
"0.9 G": 900000000,
|
|
127
|
+
"0.9 T": 900000000000,
|
|
128
|
+
"1 b": 1,
|
|
129
|
+
"1 Ki": 1024,
|
|
130
|
+
"1 Mi": 1048576,
|
|
131
|
+
"1 Gi": 1073741824,
|
|
132
|
+
"1 Ti": 1099511627776,
|
|
133
|
+
"1 K": 1000,
|
|
134
|
+
"1 M": 1000000,
|
|
135
|
+
"1 G": 1000000000,
|
|
136
|
+
"1 T": 1000000000000,
|
|
137
|
+
"7 b": 7,
|
|
138
|
+
"7 Ki": 7168,
|
|
139
|
+
"7 Mi": 7340032,
|
|
140
|
+
"7 Gi": 7516192768,
|
|
141
|
+
"7 Ti": 7696581394432,
|
|
142
|
+
"7 K": 7000,
|
|
143
|
+
"7 M": 7000000,
|
|
144
|
+
"7 G": 7000000000,
|
|
145
|
+
"7 T": 7000000000000,
|
|
146
|
+
"7.42423 b": 7,
|
|
147
|
+
"7.42423 Ki": 7602,
|
|
148
|
+
"7.42423 Mi": 7784869,
|
|
149
|
+
"7.42423 Gi": 7971706261,
|
|
150
|
+
"7.42423 Ti": 8163027212283,
|
|
151
|
+
"7.42423 K": 7424,
|
|
152
|
+
"7.42423 M": 7424230,
|
|
153
|
+
"7.42423 G": 7424230000,
|
|
154
|
+
"7.42423 T": 7424230000000,
|
|
155
|
+
"10 b": 10,
|
|
156
|
+
"10 Ki": 10240,
|
|
157
|
+
"10 Mi": 10485760,
|
|
158
|
+
"10 Gi": 10737418240,
|
|
159
|
+
"10 Ti": 10995116277760,
|
|
160
|
+
"10 K": 10000,
|
|
161
|
+
"10 M": 10000000,
|
|
162
|
+
"10 G": 10000000000,
|
|
163
|
+
"10 T": 10000000000000,
|
|
164
|
+
"100 b": 100,
|
|
165
|
+
"100 Ki": 102400,
|
|
166
|
+
"100 Mi": 104857600,
|
|
167
|
+
"100 Gi": 107374182400,
|
|
168
|
+
"100 Ti": 109951162777600,
|
|
169
|
+
"100 K": 100000,
|
|
170
|
+
"100 M": 100000000,
|
|
171
|
+
"100 G": 100000000000,
|
|
172
|
+
"100 T": 100000000000000,
|
|
173
|
+
"1000 b": 1000,
|
|
174
|
+
"1000 Ki": 1024000,
|
|
175
|
+
"1000 Mi": 1048576000,
|
|
176
|
+
"1000 Gi": 1073741824000,
|
|
177
|
+
"1000 Ti": 1099511627776000,
|
|
178
|
+
"1000 K": 1000000,
|
|
179
|
+
"1000 M": 1000000000,
|
|
180
|
+
"1000 G": 1000000000000,
|
|
181
|
+
"1000 T": 1000000000000000,
|
|
182
|
+
"11234234 b": 11234234,
|
|
183
|
+
"11234234 Ki": 11503855616,
|
|
184
|
+
"11234234 Mi": 11779948150784,
|
|
185
|
+
"11234234 Gi": 12062666906402816,
|
|
186
|
+
"11234234 Ti": 12352170912156483584,
|
|
187
|
+
"11234234 K": 11234234000,
|
|
188
|
+
"11234234 M": 11234234000000,
|
|
189
|
+
"11234234 G": 11234234000000000,
|
|
190
|
+
"11234234 T": 11234234000000000000,
|
|
193
191
|
}
|
|
194
192
|
|
|
195
193
|
results = {}
|
|
196
194
|
for i in (0, 0.1, 0.5, 0.9, 1, 7, 7.42423, 10, 100, 1000, 11234234):
|
|
197
|
-
for src_unit in [
|
|
198
|
-
results[f
|
|
195
|
+
for src_unit in ["b", "Ki", "Mi", "Gi", "Ti", "K", "M", "G", "T"]:
|
|
196
|
+
results[f"{i} {src_unit}"] = human2bytes(f"{i} {src_unit}")
|
|
199
197
|
self.assertEqual(results, expected_results)
|
|
200
198
|
|
|
201
199
|
def test_hms_duration_to_seconds(self):
|
|
202
200
|
expected_results = {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
201
|
+
"0:0:0": 0.0,
|
|
202
|
+
"00:00:00": 0.0,
|
|
203
|
+
"1:1:1": 3661.0,
|
|
204
|
+
"20:14:33": 72873.0,
|
|
205
|
+
"72:80:112": 264112.0,
|
|
208
206
|
}
|
|
209
207
|
results = {}
|
|
210
208
|
for key in expected_results.keys():
|
|
211
|
-
results[key] = hms_duration_to_seconds(f
|
|
212
|
-
|
|
209
|
+
results[key] = hms_duration_to_seconds(f"{key}")
|
|
210
|
+
|
|
213
211
|
self.assertEqual(results, expected_results)
|
toil/test/lib/test_ec2.py
CHANGED
|
@@ -14,18 +14,21 @@
|
|
|
14
14
|
import logging
|
|
15
15
|
import os
|
|
16
16
|
|
|
17
|
-
import
|
|
17
|
+
from unittest import mock
|
|
18
18
|
|
|
19
|
-
from toil.lib.aws.ami import (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
from toil.lib.aws.ami import (
|
|
20
|
+
aws_marketplace_flatcar_ami_search,
|
|
21
|
+
feed_flatcar_ami_release,
|
|
22
|
+
flatcar_release_feed_ami,
|
|
23
|
+
get_flatcar_ami,
|
|
24
|
+
ReleaseFeedUnavailableError
|
|
25
|
+
)
|
|
24
26
|
from toil.test import ToilTest, needs_aws_ec2, needs_online
|
|
25
27
|
|
|
26
28
|
logger = logging.getLogger(__name__)
|
|
27
29
|
logging.basicConfig(level=logging.DEBUG)
|
|
28
30
|
|
|
31
|
+
|
|
29
32
|
@needs_online
|
|
30
33
|
class FlatcarFeedTest(ToilTest):
|
|
31
34
|
"""Test accessing the Flatcar AMI release feed, independent of the AWS API"""
|
|
@@ -36,61 +39,66 @@ class FlatcarFeedTest(ToilTest):
|
|
|
36
39
|
|
|
37
40
|
def test_parse_archive_feed(self):
|
|
38
41
|
"""Make sure we can get a Flatcar release from the Internet Archive."""
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
ami = flatcar_release_feed_ami("us-west-2", "amd64", "archive")
|
|
43
|
+
self.assertEqual(len(ami), len("ami-02b46c73fed689d1c"))
|
|
44
|
+
self.assertTrue(ami.startswith("ami-"))
|
|
45
|
+
|
|
44
46
|
def test_parse_beta_feed(self):
|
|
45
47
|
"""Make sure we can get a Flatcar release from the beta channel."""
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
ami = flatcar_release_feed_ami("us-west-2", "amd64", "beta")
|
|
49
|
+
self.assertEqual(len(ami), len("ami-02b46c73fed689d1c"))
|
|
50
|
+
self.assertTrue(ami.startswith("ami-"))
|
|
51
|
+
|
|
51
52
|
def test_parse_stable_feed(self):
|
|
52
53
|
"""Make sure we can get a Flatcar release from the stable channel."""
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
ami = flatcar_release_feed_ami("us-west-2", "amd64", "stable")
|
|
55
|
+
self.assertEqual(len(ami), len("ami-02b46c73fed689d1c"))
|
|
56
|
+
self.assertTrue(ami.startswith("ami-"))
|
|
57
|
+
|
|
58
|
+
|
|
58
59
|
@needs_aws_ec2
|
|
59
60
|
class AMITest(ToilTest):
|
|
60
61
|
@classmethod
|
|
61
62
|
def setUpClass(cls):
|
|
62
|
-
session
|
|
63
|
-
|
|
63
|
+
from toil.lib.aws.session import establish_boto3_session
|
|
64
|
+
|
|
65
|
+
session = establish_boto3_session(region_name="us-west-2")
|
|
66
|
+
cls.ec2_client = session.client("ec2")
|
|
64
67
|
|
|
65
68
|
def test_fetch_flatcar(self):
|
|
66
|
-
with self.subTest(
|
|
67
|
-
os.environ
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
69
|
+
with self.subTest("Test flatcar AMI from user is prioritized."):
|
|
70
|
+
with mock.patch.dict(os.environ, {"TOIL_AWS_AMI": "overridden"}):
|
|
71
|
+
ami = get_flatcar_ami(self.ec2_client)
|
|
72
|
+
self.assertEqual(ami, "overridden")
|
|
73
|
+
|
|
74
|
+
with self.subTest("Test flatcar AMI returns an AMI-looking AMI."):
|
|
75
|
+
try:
|
|
76
|
+
ami = get_flatcar_ami(self.ec2_client)
|
|
77
|
+
self.assertEqual(len(ami), len("ami-02b46c73fed689d1c"))
|
|
78
|
+
self.assertTrue(ami.startswith("ami-"))
|
|
79
|
+
except ReleaseFeedUnavailableError:
|
|
80
|
+
# Ignore any remote systems being down.
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
with self.subTest(
|
|
84
|
+
"Test feed_flatcar_ami_release() returns an AMI-looking AMI."
|
|
85
|
+
):
|
|
86
|
+
ami = feed_flatcar_ami_release(self.ec2_client, source="archive")
|
|
87
|
+
self.assertTrue(ami is None or len(ami) == len("ami-02b46c73fed689d1c"))
|
|
88
|
+
self.assertTrue(ami is None or ami.startswith("ami-"))
|
|
89
|
+
|
|
90
|
+
with self.subTest(
|
|
91
|
+
"Test aws_marketplace_flatcar_ami_search() returns an AMI-looking AMI."
|
|
92
|
+
):
|
|
83
93
|
ami = aws_marketplace_flatcar_ami_search(self.ec2_client)
|
|
84
|
-
self.
|
|
85
|
-
self.assertTrue(ami.startswith(
|
|
94
|
+
self.assertTrue(ami is None or len(ami), len("ami-02b46c73fed689d1c"))
|
|
95
|
+
self.assertTrue(ami is None or ami.startswith("ami-"))
|
|
86
96
|
|
|
87
|
-
# TODO: This will fail until https://github.com/flatcar/Flatcar/issues/962 is fixed
|
|
88
|
-
@pytest.mark.xfail
|
|
89
97
|
def test_fetch_arm_flatcar(self):
|
|
90
98
|
"""Test flatcar AMI finder architecture parameter."""
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
ami
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
try:
|
|
100
|
+
ami = get_flatcar_ami(self.ec2_client, architecture="arm64")
|
|
101
|
+
self.assertTrue(ami.startswith("ami-"))
|
|
102
|
+
except ReleaseFeedUnavailableError:
|
|
103
|
+
# Ignore any remote systems being down.
|
|
104
|
+
pass
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Copyright (C) 2015-2024 Regents of the University of California
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import io
|
|
16
|
+
import logging
|
|
17
|
+
import pytest
|
|
18
|
+
from typing import IO
|
|
19
|
+
import urllib.request
|
|
20
|
+
from urllib.error import URLError
|
|
21
|
+
|
|
22
|
+
from toil.lib.retry import retry
|
|
23
|
+
from toil.lib.integration import get_workflow_root_from_dockstore
|
|
24
|
+
from toil.test import ToilTest, needs_online
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
28
|
+
|
|
29
|
+
@pytest.mark.integrative
|
|
30
|
+
@needs_online
|
|
31
|
+
class DockstoreLookupTest(ToilTest):
|
|
32
|
+
"""
|
|
33
|
+
Make sure we can look up workflows on Dockstore.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
@retry(errors=[URLError, RuntimeError])
|
|
37
|
+
def read_result(self, url_or_path: str) -> IO[bytes]:
|
|
38
|
+
"""
|
|
39
|
+
Read a file or URL.
|
|
40
|
+
|
|
41
|
+
Binary mode to allow testing for binary file support.
|
|
42
|
+
|
|
43
|
+
This lets us test that we have the right workflow contents and not care
|
|
44
|
+
how we are being shown them.
|
|
45
|
+
"""
|
|
46
|
+
if url_or_path.startswith("http://") or url_or_path.startswith("https://"):
|
|
47
|
+
response = urllib.request.urlopen(url_or_path)
|
|
48
|
+
if response.status != 200:
|
|
49
|
+
raise RuntimeError(f"HTTP error response: {response}")
|
|
50
|
+
return response
|
|
51
|
+
else:
|
|
52
|
+
return open(url_or_path, "rb")
|
|
53
|
+
|
|
54
|
+
# TODO: Tests that definitely test a clear cache
|
|
55
|
+
|
|
56
|
+
def test_lookup_from_page_url(self) -> None:
|
|
57
|
+
PAGE_URL = "https://dockstore.org/workflows/github.com/dockstore/bcc2020-training/HelloWorld:master?tab=info"
|
|
58
|
+
# If we go in through the website we get an extra refs/heads/ on the branch name.
|
|
59
|
+
WORKFLOW_URL = "https://raw.githubusercontent.com/dockstore/bcc2020-training/master/wdl-training/exercise1/HelloWorld.wdl"
|
|
60
|
+
looked_up = get_workflow_root_from_dockstore(PAGE_URL)
|
|
61
|
+
|
|
62
|
+
data_from_lookup = self.read_result(looked_up).read()
|
|
63
|
+
data_from_source = self.read_result(WORKFLOW_URL).read()
|
|
64
|
+
self.assertEqual(data_from_lookup, data_from_source)
|
|
65
|
+
|
|
66
|
+
def test_lookup_from_trs(self) -> None:
|
|
67
|
+
TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker"
|
|
68
|
+
# Despite "-checker" in the ID, this actually refers to the base md5sum
|
|
69
|
+
# workflow that just happens to have a checker *available*, not to the
|
|
70
|
+
# checker workflow itself.
|
|
71
|
+
WORKFLOW_URL = "https://raw.githubusercontent.com/dockstore-testing/md5sum-checker/master/md5sum/md5sum-workflow.cwl"
|
|
72
|
+
looked_up = get_workflow_root_from_dockstore(TRS_ID)
|
|
73
|
+
|
|
74
|
+
data_from_lookup = self.read_result(looked_up).read()
|
|
75
|
+
data_from_source = self.read_result(WORKFLOW_URL).read()
|
|
76
|
+
self.assertEqual(data_from_lookup, data_from_source)
|
|
77
|
+
|
|
78
|
+
def test_lookup_from_trs_cached(self) -> None:
|
|
79
|
+
TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker"
|
|
80
|
+
WORKFLOW_URL = "https://raw.githubusercontent.com/dockstore-testing/md5sum-checker/master/md5sum/md5sum-workflow.cwl"
|
|
81
|
+
# This lookup may or may not be cached
|
|
82
|
+
get_workflow_root_from_dockstore(TRS_ID)
|
|
83
|
+
# This lookup is definitely cached
|
|
84
|
+
looked_up = get_workflow_root_from_dockstore(TRS_ID)
|
|
85
|
+
|
|
86
|
+
data_from_lookup = self.read_result(looked_up).read()
|
|
87
|
+
data_from_source = self.read_result(WORKFLOW_URL).read()
|
|
88
|
+
self.assertEqual(data_from_lookup, data_from_source)
|
|
89
|
+
|
|
90
|
+
def test_lookup_from_trs_with_version(self) -> None:
|
|
91
|
+
TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker:workflowWithHTTPImport"
|
|
92
|
+
WORKFLOW_URL = "https://raw.githubusercontent.com/dockstore-testing/md5sum-checker/workflowWithHTTPImport/md5sum/md5sum-workflow.cwl"
|
|
93
|
+
looked_up = get_workflow_root_from_dockstore(TRS_ID)
|
|
94
|
+
|
|
95
|
+
data_from_lookup = self.read_result(looked_up).read()
|
|
96
|
+
data_from_source = self.read_result(WORKFLOW_URL).read()
|
|
97
|
+
self.assertEqual(data_from_lookup, data_from_source)
|
|
98
|
+
|
|
99
|
+
def test_lookup_from_trs_nonexistent_version(self) -> None:
|
|
100
|
+
TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker:notARealVersion"
|
|
101
|
+
with self.assertRaises(RuntimeError):
|
|
102
|
+
looked_up = get_workflow_root_from_dockstore(TRS_ID)
|
|
103
|
+
|
|
104
|
+
|
toil/test/lib/test_misc.py
CHANGED
|
@@ -32,6 +32,7 @@ class UserNameAvailableTest(ToilTest):
|
|
|
32
32
|
apparent_user_name = get_user_name()
|
|
33
33
|
self.assertEqual(apparent_user_name, real_user_name)
|
|
34
34
|
|
|
35
|
+
|
|
35
36
|
class UserNameUnvailableTest(ToilTest):
|
|
36
37
|
"""
|
|
37
38
|
Make sure we can get something for a user name when user names are not
|
|
@@ -42,9 +43,12 @@ class UserNameUnvailableTest(ToilTest):
|
|
|
42
43
|
super().setUp()
|
|
43
44
|
# Monkey patch getpass.getuser to fail
|
|
44
45
|
self.original_getuser = getpass.getuser
|
|
46
|
+
|
|
45
47
|
def fake_getuser():
|
|
46
|
-
raise KeyError(
|
|
48
|
+
raise KeyError("Fake key error")
|
|
49
|
+
|
|
47
50
|
getpass.getuser = fake_getuser
|
|
51
|
+
|
|
48
52
|
def tearDown(self):
|
|
49
53
|
# Fix the module we hacked up
|
|
50
54
|
getpass.getuser = self.original_getuser
|
|
@@ -54,7 +58,8 @@ class UserNameUnvailableTest(ToilTest):
|
|
|
54
58
|
apparent_user_name = get_user_name()
|
|
55
59
|
# Make sure we got something
|
|
56
60
|
self.assertTrue(isinstance(apparent_user_name, str))
|
|
57
|
-
self.assertNotEqual(apparent_user_name,
|
|
61
|
+
self.assertNotEqual(apparent_user_name, "")
|
|
62
|
+
|
|
58
63
|
|
|
59
64
|
class UserNameVeryBrokenTest(ToilTest):
|
|
60
65
|
"""
|
|
@@ -66,9 +71,12 @@ class UserNameVeryBrokenTest(ToilTest):
|
|
|
66
71
|
super().setUp()
|
|
67
72
|
# Monkey patch getpass.getuser to fail
|
|
68
73
|
self.original_getuser = getpass.getuser
|
|
74
|
+
|
|
69
75
|
def fake_getuser():
|
|
70
|
-
raise RuntimeError(
|
|
76
|
+
raise RuntimeError("Fake error that we did not anticipate")
|
|
77
|
+
|
|
71
78
|
getpass.getuser = fake_getuser
|
|
79
|
+
|
|
72
80
|
def tearDown(self):
|
|
73
81
|
# Fix the module we hacked up
|
|
74
82
|
getpass.getuser = self.original_getuser
|
|
@@ -78,5 +86,4 @@ class UserNameVeryBrokenTest(ToilTest):
|
|
|
78
86
|
apparent_user_name = get_user_name()
|
|
79
87
|
# Make sure we got something
|
|
80
88
|
self.assertTrue(isinstance(apparent_user_name, str))
|
|
81
|
-
self.assertNotEqual(apparent_user_name,
|
|
82
|
-
|
|
89
|
+
self.assertNotEqual(apparent_user_name, "")
|
|
@@ -21,15 +21,19 @@ class DataStructuresTest(ToilTest):
|
|
|
21
21
|
def _getJob(self, cores=1, memory=1000, disk=5000, preemptible=True):
|
|
22
22
|
from toil.batchSystems.mesos import MesosShape, ToilJob
|
|
23
23
|
|
|
24
|
-
resources = MesosShape(
|
|
24
|
+
resources = MesosShape(
|
|
25
|
+
wallTime=0, cores=cores, memory=memory, disk=disk, preemptible=preemptible
|
|
26
|
+
)
|
|
25
27
|
|
|
26
|
-
job = ToilJob(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
job = ToilJob(
|
|
29
|
+
jobID=str(uuid.uuid4()),
|
|
30
|
+
name=str(uuid.uuid4()),
|
|
31
|
+
resources=resources,
|
|
32
|
+
command="do nothing",
|
|
33
|
+
userScript=None,
|
|
34
|
+
environment=None,
|
|
35
|
+
workerCleanupInfo=None,
|
|
36
|
+
)
|
|
33
37
|
return job
|
|
34
38
|
|
|
35
39
|
def testJobQueue(self, testJobs=1000):
|
|
@@ -39,15 +43,24 @@ class DataStructuresTest(ToilTest):
|
|
|
39
43
|
non-preemptible jobs groups first, with priority given to large jobs.
|
|
40
44
|
"""
|
|
41
45
|
from toil.batchSystems.mesos import JobQueue
|
|
46
|
+
|
|
42
47
|
jobQueue = JobQueue()
|
|
43
48
|
|
|
44
49
|
for jobNum in range(0, testJobs):
|
|
45
|
-
testJob = self._getJob(
|
|
50
|
+
testJob = self._getJob(
|
|
51
|
+
cores=random.choice(list(range(10))),
|
|
52
|
+
preemptible=random.choice([True, False]),
|
|
53
|
+
)
|
|
46
54
|
jobQueue.insertJob(testJob, testJob.resources)
|
|
47
55
|
|
|
48
56
|
sortedTypes = jobQueue.sortedTypes
|
|
49
57
|
self.assertGreaterEqual(20, len(sortedTypes))
|
|
50
|
-
self.assertTrue(
|
|
58
|
+
self.assertTrue(
|
|
59
|
+
all(
|
|
60
|
+
sortedTypes[i] <= sortedTypes[i + 1]
|
|
61
|
+
for i in range(len(sortedTypes) - 1)
|
|
62
|
+
)
|
|
63
|
+
)
|
|
51
64
|
|
|
52
65
|
preemptible = sortedTypes.pop(0).preemptible
|
|
53
66
|
for jtype in sortedTypes:
|