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.
Files changed (164) hide show
  1. toil/__init__.py +18 -13
  2. toil/batchSystems/abstractBatchSystem.py +39 -13
  3. toil/batchSystems/abstractGridEngineBatchSystem.py +24 -24
  4. toil/batchSystems/awsBatch.py +14 -14
  5. toil/batchSystems/cleanup_support.py +7 -3
  6. toil/batchSystems/contained_executor.py +3 -3
  7. toil/batchSystems/htcondor.py +0 -1
  8. toil/batchSystems/kubernetes.py +34 -31
  9. toil/batchSystems/local_support.py +3 -1
  10. toil/batchSystems/lsf.py +7 -7
  11. toil/batchSystems/mesos/batchSystem.py +7 -7
  12. toil/batchSystems/options.py +32 -83
  13. toil/batchSystems/registry.py +104 -23
  14. toil/batchSystems/singleMachine.py +16 -13
  15. toil/batchSystems/slurm.py +87 -16
  16. toil/batchSystems/torque.py +0 -1
  17. toil/bus.py +44 -8
  18. toil/common.py +544 -753
  19. toil/cwl/__init__.py +28 -32
  20. toil/cwl/cwltoil.py +595 -574
  21. toil/cwl/utils.py +55 -10
  22. toil/exceptions.py +1 -1
  23. toil/fileStores/__init__.py +2 -2
  24. toil/fileStores/abstractFileStore.py +88 -14
  25. toil/fileStores/cachingFileStore.py +610 -549
  26. toil/fileStores/nonCachingFileStore.py +46 -22
  27. toil/job.py +182 -101
  28. toil/jobStores/abstractJobStore.py +161 -95
  29. toil/jobStores/aws/jobStore.py +23 -9
  30. toil/jobStores/aws/utils.py +6 -6
  31. toil/jobStores/fileJobStore.py +116 -18
  32. toil/jobStores/googleJobStore.py +16 -7
  33. toil/jobStores/utils.py +5 -6
  34. toil/leader.py +87 -56
  35. toil/lib/accelerators.py +10 -5
  36. toil/lib/aws/__init__.py +3 -14
  37. toil/lib/aws/ami.py +22 -9
  38. toil/lib/aws/iam.py +21 -13
  39. toil/lib/aws/session.py +2 -16
  40. toil/lib/aws/utils.py +4 -5
  41. toil/lib/compatibility.py +1 -1
  42. toil/lib/conversions.py +26 -3
  43. toil/lib/docker.py +22 -23
  44. toil/lib/ec2.py +10 -6
  45. toil/lib/ec2nodes.py +106 -100
  46. toil/lib/encryption/_nacl.py +2 -1
  47. toil/lib/generatedEC2Lists.py +325 -18
  48. toil/lib/io.py +49 -2
  49. toil/lib/misc.py +1 -1
  50. toil/lib/resources.py +9 -2
  51. toil/lib/threading.py +101 -38
  52. toil/options/common.py +736 -0
  53. toil/options/cwl.py +336 -0
  54. toil/options/wdl.py +37 -0
  55. toil/provisioners/abstractProvisioner.py +9 -4
  56. toil/provisioners/aws/__init__.py +3 -6
  57. toil/provisioners/aws/awsProvisioner.py +6 -0
  58. toil/provisioners/clusterScaler.py +3 -2
  59. toil/provisioners/gceProvisioner.py +2 -2
  60. toil/realtimeLogger.py +2 -1
  61. toil/resource.py +24 -18
  62. toil/server/app.py +2 -3
  63. toil/server/cli/wes_cwl_runner.py +4 -4
  64. toil/server/utils.py +1 -1
  65. toil/server/wes/abstract_backend.py +3 -2
  66. toil/server/wes/amazon_wes_utils.py +5 -4
  67. toil/server/wes/tasks.py +2 -3
  68. toil/server/wes/toil_backend.py +2 -10
  69. toil/server/wsgi_app.py +2 -0
  70. toil/serviceManager.py +12 -10
  71. toil/statsAndLogging.py +41 -9
  72. toil/test/__init__.py +29 -54
  73. toil/test/batchSystems/batchSystemTest.py +11 -111
  74. toil/test/batchSystems/test_slurm.py +24 -8
  75. toil/test/cactus/__init__.py +0 -0
  76. toil/test/cactus/test_cactus_integration.py +58 -0
  77. toil/test/cwl/cwlTest.py +438 -223
  78. toil/test/cwl/glob_dir.cwl +15 -0
  79. toil/test/cwl/preemptible.cwl +21 -0
  80. toil/test/cwl/preemptible_expression.cwl +28 -0
  81. toil/test/cwl/revsort.cwl +1 -1
  82. toil/test/cwl/revsort2.cwl +1 -1
  83. toil/test/docs/scriptsTest.py +2 -3
  84. toil/test/jobStores/jobStoreTest.py +34 -21
  85. toil/test/lib/aws/test_iam.py +4 -14
  86. toil/test/lib/aws/test_utils.py +0 -3
  87. toil/test/lib/dockerTest.py +4 -4
  88. toil/test/lib/test_ec2.py +12 -17
  89. toil/test/mesos/helloWorld.py +4 -5
  90. toil/test/mesos/stress.py +1 -1
  91. toil/test/{wdl/conftest.py → options/__init__.py} +0 -10
  92. toil/test/options/options.py +37 -0
  93. toil/test/provisioners/aws/awsProvisionerTest.py +9 -5
  94. toil/test/provisioners/clusterScalerTest.py +6 -4
  95. toil/test/provisioners/clusterTest.py +23 -11
  96. toil/test/provisioners/gceProvisionerTest.py +0 -6
  97. toil/test/provisioners/restartScript.py +3 -2
  98. toil/test/server/serverTest.py +1 -1
  99. toil/test/sort/restart_sort.py +2 -1
  100. toil/test/sort/sort.py +2 -1
  101. toil/test/sort/sortTest.py +2 -13
  102. toil/test/src/autoDeploymentTest.py +45 -45
  103. toil/test/src/busTest.py +5 -5
  104. toil/test/src/checkpointTest.py +2 -2
  105. toil/test/src/deferredFunctionTest.py +1 -1
  106. toil/test/src/fileStoreTest.py +32 -16
  107. toil/test/src/helloWorldTest.py +1 -1
  108. toil/test/src/importExportFileTest.py +1 -1
  109. toil/test/src/jobDescriptionTest.py +2 -1
  110. toil/test/src/jobServiceTest.py +1 -1
  111. toil/test/src/jobTest.py +18 -18
  112. toil/test/src/miscTests.py +5 -3
  113. toil/test/src/promisedRequirementTest.py +3 -3
  114. toil/test/src/realtimeLoggerTest.py +1 -1
  115. toil/test/src/resourceTest.py +2 -2
  116. toil/test/src/restartDAGTest.py +1 -1
  117. toil/test/src/resumabilityTest.py +36 -2
  118. toil/test/src/retainTempDirTest.py +1 -1
  119. toil/test/src/systemTest.py +2 -2
  120. toil/test/src/toilContextManagerTest.py +2 -2
  121. toil/test/src/userDefinedJobArgTypeTest.py +1 -1
  122. toil/test/utils/toilDebugTest.py +98 -32
  123. toil/test/utils/toilKillTest.py +2 -2
  124. toil/test/utils/utilsTest.py +23 -3
  125. toil/test/wdl/wdltoil_test.py +223 -45
  126. toil/toilState.py +7 -6
  127. toil/utils/toilClean.py +1 -1
  128. toil/utils/toilConfig.py +36 -0
  129. toil/utils/toilDebugFile.py +60 -33
  130. toil/utils/toilDebugJob.py +39 -12
  131. toil/utils/toilDestroyCluster.py +1 -1
  132. toil/utils/toilKill.py +1 -1
  133. toil/utils/toilLaunchCluster.py +13 -2
  134. toil/utils/toilMain.py +3 -2
  135. toil/utils/toilRsyncCluster.py +1 -1
  136. toil/utils/toilSshCluster.py +1 -1
  137. toil/utils/toilStats.py +445 -305
  138. toil/utils/toilStatus.py +2 -5
  139. toil/version.py +10 -10
  140. toil/wdl/utils.py +2 -122
  141. toil/wdl/wdltoil.py +1257 -492
  142. toil/worker.py +55 -46
  143. toil-6.1.0.dist-info/METADATA +124 -0
  144. toil-6.1.0.dist-info/RECORD +241 -0
  145. {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/WHEEL +1 -1
  146. {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/entry_points.txt +0 -1
  147. toil/batchSystems/parasol.py +0 -379
  148. toil/batchSystems/tes.py +0 -459
  149. toil/test/batchSystems/parasolTestSupport.py +0 -117
  150. toil/test/wdl/builtinTest.py +0 -506
  151. toil/test/wdl/toilwdlTest.py +0 -522
  152. toil/wdl/toilwdl.py +0 -141
  153. toil/wdl/versions/dev.py +0 -107
  154. toil/wdl/versions/draft2.py +0 -980
  155. toil/wdl/versions/v1.py +0 -794
  156. toil/wdl/wdl_analysis.py +0 -116
  157. toil/wdl/wdl_functions.py +0 -997
  158. toil/wdl/wdl_synthesis.py +0 -1011
  159. toil/wdl/wdl_types.py +0 -243
  160. toil-5.12.0.dist-info/METADATA +0 -118
  161. toil-5.12.0.dist-info/RECORD +0 -244
  162. /toil/{wdl/versions → options}/__init__.py +0 -0
  163. {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/LICENSE +0 -0
  164. {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/top_level.txt +0 -0
@@ -31,10 +31,9 @@ from toil.batchSystems.abstractBatchSystem import (AbstractBatchSystem,
31
31
  # in order to import properly. Import them later, in tests
32
32
  # protected by annotations.
33
33
  from toil.batchSystems.mesos.test import MesosTestSupport
34
- from toil.batchSystems.parasol import ParasolBatchSystem
35
- from toil.batchSystems.registry import (BATCH_SYSTEM_FACTORY_REGISTRY,
36
- BATCH_SYSTEMS,
37
- addBatchSystemFactory,
34
+ from toil.batchSystems.registry import (add_batch_system_factory,
35
+ get_batch_system,
36
+ get_batch_systems,
38
37
  restore_batch_system_plugin_state,
39
38
  save_batch_system_plugin_state)
40
39
  from toil.batchSystems.singleMachine import SingleMachineBatchSystem
@@ -52,12 +51,9 @@ from toil.test import (ToilTest,
52
51
  needs_kubernetes_installed,
53
52
  needs_lsf,
54
53
  needs_mesos,
55
- needs_parasol,
56
54
  needs_slurm,
57
- needs_tes,
58
55
  needs_torque,
59
56
  slow)
60
- from toil.test.batchSystems.parasolTestSupport import ParasolTestSupport
61
57
 
62
58
  logger = logging.getLogger(__name__)
63
59
 
@@ -88,16 +84,16 @@ class BatchSystemPluginTest(ToilTest):
88
84
  restore_batch_system_plugin_state(self.__state)
89
85
  super().tearDown()
90
86
 
91
- def testAddBatchSystemFactory(self):
87
+ def test_add_batch_system_factory(self):
92
88
  def test_batch_system_factory():
93
89
  # TODO: Adding the same batch system under multiple names means we
94
90
  # can't actually create Toil options, because each version tries to
95
91
  # add its arguments.
96
92
  return SingleMachineBatchSystem
97
93
 
98
- addBatchSystemFactory('testBatchSystem', test_batch_system_factory)
99
- assert ('testBatchSystem', test_batch_system_factory) in BATCH_SYSTEM_FACTORY_REGISTRY.items()
100
- assert 'testBatchSystem' in BATCH_SYSTEMS
94
+ add_batch_system_factory('testBatchSystem', test_batch_system_factory)
95
+ assert 'testBatchSystem' in get_batch_systems()
96
+ assert get_batch_system('testBatchSystem') == SingleMachineBatchSystem
101
97
 
102
98
  class hidden:
103
99
  """
@@ -248,10 +244,6 @@ class hidden:
248
244
  self.batchSystem.killBatchJobs([10])
249
245
 
250
246
  def test_set_env(self):
251
- # Parasol disobeys shell rules and splits the command at the space
252
- # character into arguments before exec'ing it, whether the space is
253
- # quoted, escaped or not.
254
-
255
247
  # Start with a relatively safe script
256
248
  script_shell = 'if [ "x${FOO}" == "xbar" ] ; then exit 23 ; else exit 42 ; fi'
257
249
 
@@ -575,23 +567,6 @@ class KubernetesBatchSystemBenchTest(ToilTest):
575
567
  self.assertEqual(str(spec.tolerations), "None")
576
568
 
577
569
 
578
- @needs_tes
579
- @needs_fetchable_appliance
580
- class TESBatchSystemTest(hidden.AbstractBatchSystemTest):
581
- """
582
- Tests against the TES batch system
583
- """
584
-
585
- def supportsWallTime(self):
586
- return True
587
-
588
- def createBatchSystem(self):
589
- # Import the batch system when we know we have it.
590
- # Doesn't really matter for TES right now, but someday it might.
591
- from toil.batchSystems.tes import TESBatchSystem
592
- return TESBatchSystem(config=self.config,
593
- maxCores=numCores, maxMemory=1e9, maxDisk=2001)
594
-
595
570
  @needs_aws_batch
596
571
  @needs_fetchable_appliance
597
572
  class AWSBatchBatchSystemTest(hidden.AbstractBatchSystemTest):
@@ -849,7 +824,7 @@ class MaxCoresSingleMachineBatchSystemTest(ToilTest):
849
824
  if len(sys.argv) < 3:
850
825
  count(1)
851
826
  try:
852
- time.sleep(1)
827
+ time.sleep(0.5)
853
828
  finally:
854
829
  count(-1)
855
830
  else:
@@ -910,9 +885,10 @@ class MaxCoresSingleMachineBatchSystemTest(ToilTest):
910
885
  logger.info(f'maxCores: {maxCores}, '
911
886
  f'coresPerJob: {coresPerJob}, '
912
887
  f'load: {load}')
913
- # This is the key assertion:
888
+ # This is the key assertion: we shouldn't run too many jobs.
889
+ # Because of nondeterminism we can't guarantee hitting the limit.
914
890
  expectedMaxConcurrentTasks = min(maxCores // coresPerJob, jobs)
915
- self.assertEqual(maxConcurrentTasks, expectedMaxConcurrentTasks)
891
+ self.assertLessEqual(maxConcurrentTasks, expectedMaxConcurrentTasks)
916
892
  resetCounters(self.counterPath)
917
893
 
918
894
  @skipIf(SingleMachineBatchSystem.numCores < 3, 'Need at least three cores to run this test')
@@ -965,82 +941,6 @@ class Service(Job.Service):
965
941
  subprocess.check_call(self.cmd + ' -1', shell=True)
966
942
 
967
943
 
968
- @slow
969
- @needs_parasol
970
- class ParasolBatchSystemTest(hidden.AbstractBatchSystemTest, ParasolTestSupport):
971
- """
972
- Tests the Parasol batch system
973
- """
974
-
975
- def supportsWallTime(self):
976
- return True
977
-
978
- def _createConfig(self):
979
- config = super()._createConfig()
980
- # can't use _getTestJobStorePath since that method removes the directory
981
- config.jobStore = self._createTempDir('jobStore')
982
- return config
983
-
984
- def createBatchSystem(self) -> AbstractBatchSystem:
985
- memory = int(3e9)
986
- self._startParasol(numCores=numCores, memory=memory)
987
-
988
- return ParasolBatchSystem(config=self.config,
989
- maxCores=numCores,
990
- maxMemory=memory,
991
- maxDisk=1001)
992
-
993
- def tearDown(self):
994
- super().tearDown()
995
- self._stopParasol()
996
-
997
- def testBatchResourceLimits(self):
998
- jobDesc1 = JobDescription(command="sleep 1000",
999
- requirements=dict(memory=1 << 30, cores=1,
1000
- disk=1000, accelerators=[],
1001
- preemptible=preemptible),
1002
- jobName='testResourceLimits')
1003
- job1 = self.batchSystem.issueBatchJob(jobDesc1)
1004
- self.assertIsNotNone(job1)
1005
- jobDesc2 = JobDescription(command="sleep 1000",
1006
- requirements=dict(memory=2 << 30, cores=1,
1007
- disk=1000, accelerators=[],
1008
- preemptible=preemptible),
1009
- jobName='testResourceLimits')
1010
- job2 = self.batchSystem.issueBatchJob(jobDesc2)
1011
- self.assertIsNotNone(job2)
1012
- batches = self._getBatchList()
1013
- self.assertEqual(len(batches), 2)
1014
- # It would be better to directly check that the batches have the correct memory and cpu
1015
- # values, but Parasol seems to slightly change the values sometimes.
1016
- self.assertNotEqual(batches[0]['ram'], batches[1]['ram'])
1017
- # Need to kill one of the jobs because there are only two cores available
1018
- self.batchSystem.killBatchJobs([job2])
1019
- job3 = self.batchSystem.issueBatchJob(jobDesc1)
1020
- self.assertIsNotNone(job3)
1021
- batches = self._getBatchList()
1022
- self.assertEqual(len(batches), 1)
1023
-
1024
- def _parseBatchString(self, batchString):
1025
- import re
1026
- batchInfo = dict()
1027
- memPattern = re.compile(r"(\d+\.\d+)([kgmbt])")
1028
- items = batchString.split()
1029
- batchInfo["cores"] = int(items[7])
1030
- memMatch = memPattern.match(items[8])
1031
- ramValue = float(memMatch.group(1))
1032
- ramUnits = memMatch.group(2)
1033
- ramConversion = {'b': 1e0, 'k': 1e3, 'm': 1e6, 'g': 1e9, 't': 1e12}
1034
- batchInfo["ram"] = ramValue * ramConversion[ramUnits]
1035
- return batchInfo
1036
-
1037
- def _getBatchList(self):
1038
- # noinspection PyUnresolvedReferences
1039
- exitStatus, batchLines = self.batchSystem._runParasol(['list', 'batches'])
1040
- self.assertEqual(exitStatus, 0)
1041
- return [self._parseBatchString(line) for line in batchLines[1:] if line]
1042
-
1043
-
1044
944
  @slow
1045
945
  @needs_gridengine
1046
946
  class GridEngineBatchSystemTest(hidden.AbstractGridEngineBatchSystemTest):
@@ -4,6 +4,7 @@ from queue import Queue
4
4
  import pytest
5
5
 
6
6
  import toil.batchSystems.slurm
7
+ from toil.batchSystems.abstractBatchSystem import BatchJobExitReason, EXIT_STATUS_UNAVAILABLE_VALUE
7
8
  from toil.common import Config
8
9
  from toil.lib.misc import CalledProcessErrorStderr
9
10
  from toil.test import ToilTest
@@ -16,7 +17,8 @@ def call_sacct(args, **_) -> str:
16
17
  The arguments passed to `call_command` when executing `sacct` are:
17
18
  ['sacct', '-n', '-j', '<comma-separated list of job-ids>', '--format',
18
19
  'JobIDRaw,State,ExitCode', '-P', '-S', '1970-01-01']
19
- The multi-line output is something like:
20
+ The multi-line output is something like::
21
+
20
22
  1234|COMPLETED|0:0
21
23
  1234.batch|COMPLETED|0:0
22
24
  1235|PENDING|0:0
@@ -46,7 +48,7 @@ def call_sacct(args, **_) -> str:
46
48
  def call_scontrol(args, **_) -> str:
47
49
  """
48
50
  The arguments passed to `call_command` when executing `scontrol` are:
49
- ['scontrol', 'show', 'job'] or ['scontrol', 'show', 'job', '<job-id>']
51
+ ``['scontrol', 'show', 'job']`` or ``['scontrol', 'show', 'job', '<job-id>']``
50
52
  """
51
53
  job_id = int(args[3]) if len(args) > 3 else None
52
54
  # Fake output per fake job-id.
@@ -283,7 +285,7 @@ class SlurmTest(ToilTest):
283
285
  def test_getJobExitCode_job_exists(self):
284
286
  self.monkeypatch.setattr(toil.batchSystems.slurm, "call_command", call_sacct)
285
287
  job_id = '785023' # FAILED
286
- expected_result = 127
288
+ expected_result = (127, BatchJobExitReason.FAILED)
287
289
  result = self.worker.getJobExitCode(job_id)
288
290
  assert result == expected_result, f"{result} != {expected_result}"
289
291
 
@@ -302,7 +304,7 @@ class SlurmTest(ToilTest):
302
304
  self.monkeypatch.setattr(self.worker, "_getJobDetailsFromSacct", call_sacct_raises)
303
305
  self.monkeypatch.setattr(toil.batchSystems.slurm, "call_command", call_scontrol)
304
306
  job_id = '787204' # COMPLETED
305
- expected_result = 0
307
+ expected_result = (0, BatchJobExitReason.FINISHED)
306
308
  result = self.worker.getJobExitCode(job_id)
307
309
  assert result == expected_result, f"{result} != {expected_result}"
308
310
 
@@ -328,7 +330,7 @@ class SlurmTest(ToilTest):
328
330
  def test_coalesce_job_exit_codes_one_exists(self):
329
331
  self.monkeypatch.setattr(toil.batchSystems.slurm, "call_command", call_sacct)
330
332
  job_ids = ['785023'] # FAILED
331
- expected_result = [127]
333
+ expected_result = [(127, BatchJobExitReason.FAILED)]
332
334
  result = self.worker.coalesce_job_exit_codes(job_ids)
333
335
  assert result == expected_result, f"{result} != {expected_result}"
334
336
 
@@ -346,7 +348,14 @@ class SlurmTest(ToilTest):
346
348
  '789724', # RUNNING,
347
349
  '789868', # PENDING,
348
350
  '789869'] # COMPLETED
349
- expected_result = [0, 1, None, None, 0] # RUNNING and PENDING jobs should return None
351
+ # RUNNING and PENDING jobs should return None
352
+ expected_result = [
353
+ (EXIT_STATUS_UNAVAILABLE_VALUE, BatchJobExitReason.KILLED),
354
+ (1, BatchJobExitReason.FAILED),
355
+ None,
356
+ None,
357
+ (0, BatchJobExitReason.FINISHED)
358
+ ]
350
359
  result = self.worker.coalesce_job_exit_codes(job_ids)
351
360
  assert result == expected_result, f"{result} != {expected_result}"
352
361
 
@@ -357,7 +366,14 @@ class SlurmTest(ToilTest):
357
366
  '789724', # RUNNING,
358
367
  '999999', # Non-existent,
359
368
  '789869'] # COMPLETED
360
- expected_result = [130, 2, None, None, 0] # RUNNING job should return None
369
+ # RUNNING job should return None
370
+ expected_result = [
371
+ (130, BatchJobExitReason.FAILED),
372
+ (2, BatchJobExitReason.FAILED),
373
+ None,
374
+ None,
375
+ (0, BatchJobExitReason.FINISHED)
376
+ ]
361
377
  result = self.worker.coalesce_job_exit_codes(job_ids)
362
378
  assert result == expected_result, f"{result} != {expected_result}"
363
379
 
@@ -369,7 +385,7 @@ class SlurmTest(ToilTest):
369
385
  self.monkeypatch.setattr(self.worker, "_getJobDetailsFromSacct", call_sacct_raises)
370
386
  self.monkeypatch.setattr(toil.batchSystems.slurm, "call_command", call_scontrol)
371
387
  job_ids = ['787204'] # COMPLETED
372
- expected_result = [0]
388
+ expected_result = [(0, BatchJobExitReason.FINISHED)]
373
389
  result = self.worker.coalesce_job_exit_codes(job_ids)
374
390
  assert result == expected_result, f"{result} != {expected_result}"
375
391
 
File without changes
@@ -0,0 +1,58 @@
1
+ import os
2
+ import uuid
3
+
4
+ from toil.provisioners import cluster_factory
5
+ from toil.test.provisioners.clusterTest import AbstractClusterTest
6
+
7
+
8
+ class CactusIntegrationTest(AbstractClusterTest):
9
+ """
10
+ Run the Cactus Integration test on a Kubernetes AWS cluster
11
+ """
12
+
13
+ def __init__(self, methodName):
14
+ super().__init__(methodName=methodName)
15
+ self.clusterName = "cactus-test-" + str(uuid.uuid4())
16
+ self.leaderNodeType = "t2.medium"
17
+ self.clusterType = "kubernetes"
18
+
19
+ def setUp(self):
20
+ super().setUp()
21
+ self.jobStore = f"aws:{self.awsRegion()}:cluster-{uuid.uuid4()}"
22
+
23
+ def test_cactus_integration(self):
24
+ # Make a cluster with worker nodes
25
+ self.createClusterUtil(args=["--nodeTypes=t2.xlarge", "-w=1-3"])
26
+ # get the leader so we know the IP address - we don't need to wait since create cluster
27
+ # already ensures the leader is running
28
+ self.cluster = cluster_factory(
29
+ provisioner="aws", zone=self.zone, clusterName=self.clusterName
30
+ )
31
+ self.leader = self.cluster.getLeader()
32
+
33
+ CACTUS_COMMIT_SHA = os.environ["CACTUS_COMMIT_SHA"] or "f5adf4013326322ae58ef1eccb8409b71d761583" # default cactus commit
34
+
35
+ # command to install and run cactus on the cluster
36
+ cactus_command = ("python -m virtualenv --system-site-packages venv && "
37
+ ". venv/bin/activate && "
38
+ "git clone https://github.com/ComparativeGenomicsToolkit/cactus.git --recursive && "
39
+ "cd cactus && "
40
+ "git fetch origin && "
41
+ f"git checkout {CACTUS_COMMIT_SHA} && "
42
+ "git submodule update --init --recursive && "
43
+ "pip install --upgrade 'setuptools<66' pip && "
44
+ "pip install --upgrade . && "
45
+ "pip install --upgrade numpy psutil && "
46
+ "time cactus --batchSystem kubernetes --retryCount=3 "
47
+ f"--consCores 2 --binariesMode singularity --clean always {self.jobStore} "
48
+ "examples/evolverMammals.txt examples/evolverMammals.hal --root mr --defaultDisk 8G --logDebug")
49
+
50
+ # run cactus
51
+ self.sshUtil(
52
+ [
53
+ "bash",
54
+ "-c",
55
+ cactus_command
56
+ ]
57
+ )
58
+