1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: Apache-2.0
5 from future import standard_library
6 standard_library.install_aliases()
7 from builtins import object
8 from builtins import str
9 from future.utils import viewvalues
20 import cwltool.process
22 from io import BytesIO
24 # StringIO.StringIO and io.StringIO have different behavior write() is
25 # called with both python2 (byte) strings and unicode strings
26 # (specifically there's some logging in cwltool that causes trouble).
27 # This isn't a problem on python3 because all string are unicode.
28 if sys.version_info[0] < 3:
29 from StringIO import StringIO
31 from io import StringIO
34 import arvados.collection
36 import arvados_cwl.executor
37 import arvados_cwl.runner
40 from .matcher import JsonDiffMatcher, StripYAMLComments
41 from .mock_discovery import get_rootDesc
43 import ruamel.yaml as yaml
48 @functools.wraps(func)
49 @mock.patch("arvados.commands.keepdocker.list_images_in_arv")
50 @mock.patch("arvados.collection.KeepClient")
51 @mock.patch("arvados.keep.KeepClient")
52 @mock.patch("arvados.events.subscribe")
53 def wrapped(self, events, keep_client1, keep_client2, keepdocker, *args, **kwargs):
58 stubs.keepdocker = keepdocker
60 def putstub(p, **kwargs):
61 return "%s+%i" % (hashlib.md5(p).hexdigest(), len(p))
62 keep_client1().put.side_effect = putstub
63 keep_client1.put.side_effect = putstub
64 keep_client2().put.side_effect = putstub
65 keep_client2.put.side_effect = putstub
67 stubs.keep_client = keep_client2
68 stubs.docker_images = {
69 "arvados/jobs:"+arvados_cwl.__version__: [("zzzzz-4zz18-zzzzzzzzzzzzzd3", "")],
70 "debian:8": [("zzzzz-4zz18-zzzzzzzzzzzzzd4", "")],
71 "arvados/jobs:123": [("zzzzz-4zz18-zzzzzzzzzzzzzd5", "")],
72 "arvados/jobs:latest": [("zzzzz-4zz18-zzzzzzzzzzzzzd6", "")],
74 def kd(a, b, image_name=None, image_tag=None):
75 return stubs.docker_images.get("%s:%s" % (image_name, image_tag), [])
76 stubs.keepdocker.side_effect = kd
78 stubs.fake_user_uuid = "zzzzz-tpzed-zzzzzzzzzzzzzzz"
79 stubs.fake_container_uuid = "zzzzz-dz642-zzzzzzzzzzzzzzz"
81 if sys.version_info[0] < 3:
82 stubs.capture_stdout = BytesIO()
84 stubs.capture_stdout = StringIO()
86 stubs.api = mock.MagicMock()
87 stubs.api._rootDesc = get_rootDesc()
88 stubs.api._rootDesc["uuidPrefix"] = "zzzzz"
90 stubs.api.users().current().execute.return_value = {
91 "uuid": stubs.fake_user_uuid,
93 stubs.api.collections().list().execute.return_value = {"items": []}
94 stubs.api.containers().current().execute.return_value = {
95 "uuid": stubs.fake_container_uuid,
98 class CollectionExecute(object):
99 def __init__(self, exe):
101 def execute(self, num_retries=None):
104 def collection_createstub(created_collections, body, ensure_unique_name=None):
105 mt = body["manifest_text"].encode('utf-8')
106 uuid = "zzzzz-4zz18-zzzzzzzzzzzzzx%d" % len(created_collections)
107 pdh = "%s+%i" % (hashlib.md5(mt).hexdigest(), len(mt))
108 created_collections[uuid] = {
110 "portable_data_hash": pdh,
111 "manifest_text": mt.decode('utf-8')
113 return CollectionExecute(created_collections[uuid])
115 def collection_getstub(created_collections, uuid):
116 for v in viewvalues(created_collections):
117 if uuid in (v["uuid"], v["portable_data_hash"]):
118 return CollectionExecute(v)
120 created_collections = {
121 "99999999999999999999999999999998+99": {
123 "portable_data_hash": "99999999999999999999999999999998+99",
124 "manifest_text": ". 99999999999999999999999999999998+99 0:0:file1.txt"
126 "99999999999999999999999999999997+99": {
128 "portable_data_hash": "99999999999999999999999999999997+99",
129 "manifest_text": ". 99999999999999999999999999999997+99 0:0:file1.txt"
131 "99999999999999999999999999999994+99": {
133 "portable_data_hash": "99999999999999999999999999999994+99",
134 "manifest_text": ". 99999999999999999999999999999994+99 0:0:expect_arvworkflow.cwl"
136 "zzzzz-4zz18-zzzzzzzzzzzzzd3": {
137 "uuid": "zzzzz-4zz18-zzzzzzzzzzzzzd3",
138 "portable_data_hash": "999999999999999999999999999999d3+99",
141 "zzzzz-4zz18-zzzzzzzzzzzzzd4": {
142 "uuid": "zzzzz-4zz18-zzzzzzzzzzzzzd4",
143 "portable_data_hash": "999999999999999999999999999999d4+99",
146 "zzzzz-4zz18-zzzzzzzzzzzzzd5": {
147 "uuid": "zzzzz-4zz18-zzzzzzzzzzzzzd5",
148 "portable_data_hash": "999999999999999999999999999999d5+99",
151 "zzzzz-4zz18-zzzzzzzzzzzzzd6": {
152 "uuid": "zzzzz-4zz18-zzzzzzzzzzzzzd6",
153 "portable_data_hash": "999999999999999999999999999999d6+99",
157 stubs.api.collections().create.side_effect = functools.partial(collection_createstub, created_collections)
158 stubs.api.collections().get.side_effect = functools.partial(collection_getstub, created_collections)
160 stubs.expect_job_uuid = "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
161 stubs.api.jobs().create().execute.return_value = {
162 "uuid": stubs.expect_job_uuid,
166 stubs.expect_container_request_uuid = "zzzzz-xvhdp-zzzzzzzzzzzzzzz"
167 stubs.api.container_requests().create().execute.return_value = {
168 "uuid": stubs.expect_container_request_uuid,
169 "container_uuid": "zzzzz-dz642-zzzzzzzzzzzzzzz",
173 stubs.expect_pipeline_template_uuid = "zzzzz-d1hrv-zzzzzzzzzzzzzzz"
174 stubs.api.pipeline_templates().create().execute.return_value = {
175 "uuid": stubs.expect_pipeline_template_uuid,
177 stubs.expect_job_spec = {
178 'runtime_constraints': {
179 'docker_image': '999999999999999999999999999999d3+99',
180 'min_ram_mb_per_node': 1024
182 'script_parameters': {
184 'basename': 'blorp.txt',
185 'location': 'keep:169f39d466a5438ac4a90e779bf750c7+53/blorp.txt',
189 'basename': '99999999999999999999999999999998+99',
190 'location': 'keep:99999999999999999999999999999998+99',
194 'basename': 'anonymous',
196 "basename": "renamed.txt",
198 "location": "keep:99999999999999999999999999999998+99/file1.txt",
203 'cwl:tool': '57ad063d64c60dbddc027791f0649211+60/workflow.cwl#main'
205 'repository': 'arvados',
206 'script_version': 'master',
207 'minimum_script_version': '570509ab4d2ef93d870fd2b1f2eab178afb1bad9',
208 'script': 'cwl-runner'
210 stubs.pipeline_component = stubs.expect_job_spec.copy()
211 stubs.expect_pipeline_instance = {
212 'name': 'submit_wf.cwl',
213 'state': 'RunningOnServer',
217 'runtime_constraints': {'docker_image': '999999999999999999999999999999d3+99', 'min_ram_mb_per_node': 1024},
218 'script_parameters': {
219 'y': {"value": {'basename': '99999999999999999999999999999998+99', 'location': 'keep:99999999999999999999999999999998+99', 'class': 'Directory'}},
221 'basename': 'blorp.txt',
223 'location': 'keep:169f39d466a5438ac4a90e779bf750c7+53/blorp.txt',
226 'z': {"value": {'basename': 'anonymous', 'class': 'Directory',
229 'basename': 'renamed.txt',
230 'class': 'File', 'location':
231 'keep:99999999999999999999999999999998+99/file1.txt',
235 'cwl:tool': '57ad063d64c60dbddc027791f0649211+60/workflow.cwl#main',
237 'arv:enable_reuse': True,
238 'arv:on_error': 'continue'
240 'repository': 'arvados',
241 'script_version': 'master',
242 'minimum_script_version': '570509ab4d2ef93d870fd2b1f2eab178afb1bad9',
243 'script': 'cwl-runner',
244 'job': {'state': 'Queued', 'uuid': 'zzzzz-8i9sb-zzzzzzzzzzzzzzz'}
248 stubs.pipeline_create = copy.deepcopy(stubs.expect_pipeline_instance)
249 stubs.expect_pipeline_uuid = "zzzzz-d1hrv-zzzzzzzzzzzzzzz"
250 stubs.pipeline_create["uuid"] = stubs.expect_pipeline_uuid
251 stubs.pipeline_with_job = copy.deepcopy(stubs.pipeline_create)
252 stubs.pipeline_with_job["components"]["cwl-runner"]["job"] = {
253 "uuid": "zzzzz-8i9sb-zzzzzzzzzzzzzzz",
256 stubs.api.pipeline_instances().create().execute.return_value = stubs.pipeline_create
257 stubs.api.pipeline_instances().get().execute.return_value = stubs.pipeline_with_job
259 with open("tests/wf/submit_wf_packed.cwl") as f:
260 expect_packed_workflow = yaml.round_trip_load(f)
262 stubs.expect_container_spec = {
269 '/var/lib/cwl/workflow.json': {
270 'content': expect_packed_workflow,
274 'path': '/var/spool/cwl/cwl.output.json',
277 '/var/lib/cwl/cwl.input.json': {
281 'basename': '99999999999999999999999999999998+99',
282 'location': 'keep:99999999999999999999999999999998+99',
283 'class': 'Directory'},
285 'basename': u'blorp.txt',
287 'location': u'keep:169f39d466a5438ac4a90e779bf750c7+53/blorp.txt',
290 'z': {'basename': 'anonymous', 'class': 'Directory', 'listing': [
291 {'basename': 'renamed.txt',
293 'location': 'keep:99999999999999999999999999999998+99/file1.txt',
302 'state': 'Committed',
303 'command': ['arvados-cwl-runner', '--local', '--api=containers',
304 '--no-log-timestamps', '--disable-validate',
305 '--eval-timeout=20', '--thread-count=1',
306 '--enable-reuse', "--collection-cache-size=256", '--debug', '--on-error=continue',
307 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json'],
308 'name': 'submit_wf.cwl',
309 'container_image': '999999999999999999999999999999d3+99',
310 'output_path': '/var/spool/cwl',
311 'cwd': '/var/spool/cwl',
312 'runtime_constraints': {
315 'ram': (1024+256)*1024*1024
317 'use_existing': True,
322 stubs.expect_workflow_uuid = "zzzzz-7fd4e-zzzzzzzzzzzzzzz"
323 stubs.api.workflows().create().execute.return_value = {
324 "uuid": stubs.expect_workflow_uuid,
326 def update_mock(**kwargs):
327 stubs.updated_uuid = kwargs.get('uuid')
329 stubs.api.workflows().update.side_effect = update_mock
330 stubs.api.workflows().update().execute.side_effect = lambda **kwargs: {
331 "uuid": stubs.updated_uuid,
334 return func(self, stubs, *args, **kwargs)
338 class TestSubmit(unittest.TestCase):
341 cwltool.process._names = set()
343 @mock.patch("arvados_cwl.arvdocker.arv_docker_get_image")
344 @mock.patch("time.sleep")
346 def test_submit(self, stubs, tm, arvdock):
347 def get_image(api_client, dockerRequirement, pull_image, project_uuid):
348 if dockerRequirement["dockerPull"] == 'arvados/jobs:'+arvados_cwl.__version__:
349 return '999999999999999999999999999999d3+99'
350 elif dockerRequirement["dockerPull"] == "debian:8":
351 return '999999999999999999999999999999d4+99'
352 arvdock.side_effect = get_image
354 exited = arvados_cwl.main(
355 ["--submit", "--no-wait", "--api=jobs", "--debug",
356 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
357 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
359 stubs.api.collections().create.assert_has_calls([
360 mock.call(body=JsonDiffMatcher({
362 '. 979af1245a12a1fed634d4222473bfdc+16 0:16:blorp.txt\n',
363 'replication_desired': None,
364 'name': 'submit_wf.cwl input (169f39d466a5438ac4a90e779bf750c7+53)',
365 }), ensure_unique_name=False),
366 mock.call(body=JsonDiffMatcher({
368 '. 5bcc9fe8f8d5992e6cf418dc7ce4dbb3+16 0:16:blub.txt\n',
369 'replication_desired': None,
370 'name': 'submit_tool.cwl dependencies (5d373e7629203ce39e7c22af98a0f881+52)',
371 }), ensure_unique_name=False),
372 mock.call(body=JsonDiffMatcher({
374 ". 68089141fbf7e020ac90a9d6a575bc8f+1312 0:1312:workflow.cwl\n",
375 'replication_desired': None,
376 'name': 'submit_wf.cwl',
377 }), ensure_unique_name=True) ])
379 arvdock.assert_has_calls([
380 mock.call(stubs.api, {"class": "DockerRequirement", "dockerPull": "debian:8"}, True, None),
381 mock.call(stubs.api, {"class": "DockerRequirement", "dockerPull": "debian:8", 'http://arvados.org/cwl#dockerCollectionPDH': '999999999999999999999999999999d4+99'}, True, None),
382 mock.call(stubs.api, {'dockerPull': 'arvados/jobs:'+arvados_cwl.__version__}, True, None)
385 expect_pipeline = copy.deepcopy(stubs.expect_pipeline_instance)
386 stubs.api.pipeline_instances().create.assert_called_with(
387 body=JsonDiffMatcher(expect_pipeline))
388 self.assertEqual(stubs.capture_stdout.getvalue(),
389 stubs.expect_pipeline_uuid + '\n')
390 self.assertEqual(exited, 0)
392 @mock.patch("time.sleep")
394 def test_submit_no_reuse(self, stubs, tm):
395 exited = arvados_cwl.main(
396 ["--submit", "--no-wait", "--api=jobs", "--debug", "--disable-reuse",
397 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
398 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
400 expect_pipeline = copy.deepcopy(stubs.expect_pipeline_instance)
401 expect_pipeline["components"]["cwl-runner"]["script_parameters"]["arv:enable_reuse"] = {"value": False}
402 expect_pipeline["properties"] = {"run_options": {"enable_job_reuse": False}}
404 stubs.api.pipeline_instances().create.assert_called_with(
405 body=JsonDiffMatcher(expect_pipeline))
406 self.assertEqual(stubs.capture_stdout.getvalue(),
407 stubs.expect_pipeline_uuid + '\n')
408 self.assertEqual(exited, 0)
411 def test_error_when_multiple_storage_classes_specified(self, stubs):
412 storage_classes = "foo,bar"
413 exited = arvados_cwl.main(
414 ["--debug", "--storage-classes", storage_classes,
415 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
416 sys.stdin, sys.stderr, api_client=stubs.api)
417 self.assertEqual(exited, 1)
419 @mock.patch("time.sleep")
421 def test_submit_on_error(self, stubs, tm):
422 exited = arvados_cwl.main(
423 ["--submit", "--no-wait", "--api=jobs", "--debug", "--on-error=stop",
424 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
425 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
427 expect_pipeline = copy.deepcopy(stubs.expect_pipeline_instance)
428 expect_pipeline["components"]["cwl-runner"]["script_parameters"]["arv:on_error"] = "stop"
430 stubs.api.pipeline_instances().create.assert_called_with(
431 body=JsonDiffMatcher(expect_pipeline))
432 self.assertEqual(stubs.capture_stdout.getvalue(),
433 stubs.expect_pipeline_uuid + '\n')
434 self.assertEqual(exited, 0)
436 @mock.patch("time.sleep")
438 def test_submit_runner_ram(self, stubs, tm):
439 exited = arvados_cwl.main(
440 ["--submit", "--no-wait", "--debug", "--submit-runner-ram=2048",
442 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
443 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
445 expect_pipeline = copy.deepcopy(stubs.expect_pipeline_instance)
446 expect_pipeline["components"]["cwl-runner"]["runtime_constraints"]["min_ram_mb_per_node"] = 2048
448 stubs.api.pipeline_instances().create.assert_called_with(
449 body=JsonDiffMatcher(expect_pipeline))
450 self.assertEqual(stubs.capture_stdout.getvalue(),
451 stubs.expect_pipeline_uuid + '\n')
452 self.assertEqual(exited, 0)
454 @mock.patch("time.sleep")
456 def test_submit_invalid_runner_ram(self, stubs, tm):
457 exited = arvados_cwl.main(
458 ["--submit", "--no-wait", "--debug", "--submit-runner-ram=-2048",
459 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
460 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
461 self.assertEqual(exited, 1)
463 @mock.patch("time.sleep")
465 def test_submit_output_name(self, stubs, tm):
466 output_name = "test_output_name"
468 exited = arvados_cwl.main(
469 ["--submit", "--no-wait", "--debug", "--output-name", output_name,
471 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
472 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
474 expect_pipeline = copy.deepcopy(stubs.expect_pipeline_instance)
475 expect_pipeline["components"]["cwl-runner"]["script_parameters"]["arv:output_name"] = output_name
477 stubs.api.pipeline_instances().create.assert_called_with(
478 body=JsonDiffMatcher(expect_pipeline))
479 self.assertEqual(stubs.capture_stdout.getvalue(),
480 stubs.expect_pipeline_uuid + '\n')
481 self.assertEqual(exited, 0)
483 @mock.patch("time.sleep")
485 def test_submit_pipeline_name(self, stubs, tm):
486 exited = arvados_cwl.main(
487 ["--submit", "--no-wait", "--debug", "--name=hello job 123",
489 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
490 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
491 self.assertEqual(exited, 0)
493 expect_pipeline = copy.deepcopy(stubs.expect_pipeline_instance)
494 expect_pipeline["name"] = "hello job 123"
496 stubs.api.pipeline_instances().create.assert_called_with(
497 body=JsonDiffMatcher(expect_pipeline))
498 self.assertEqual(stubs.capture_stdout.getvalue(),
499 stubs.expect_pipeline_uuid + '\n')
501 @mock.patch("time.sleep")
503 def test_submit_output_tags(self, stubs, tm):
504 output_tags = "tag0,tag1,tag2"
506 exited = arvados_cwl.main(
507 ["--submit", "--no-wait", "--debug", "--output-tags", output_tags,
509 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
510 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
511 self.assertEqual(exited, 0)
513 expect_pipeline = copy.deepcopy(stubs.expect_pipeline_instance)
514 expect_pipeline["components"]["cwl-runner"]["script_parameters"]["arv:output_tags"] = output_tags
516 stubs.api.pipeline_instances().create.assert_called_with(
517 body=JsonDiffMatcher(expect_pipeline))
518 self.assertEqual(stubs.capture_stdout.getvalue(),
519 stubs.expect_pipeline_uuid + '\n')
521 @mock.patch("time.sleep")
523 def test_submit_with_project_uuid(self, stubs, tm):
524 project_uuid = 'zzzzz-j7d0g-zzzzzzzzzzzzzzz'
526 exited = arvados_cwl.main(
527 ["--submit", "--no-wait", "--debug",
528 "--project-uuid", project_uuid,
530 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
531 sys.stdout, sys.stderr, api_client=stubs.api)
532 self.assertEqual(exited, 0)
534 expect_pipeline = copy.deepcopy(stubs.expect_pipeline_instance)
535 expect_pipeline["owner_uuid"] = project_uuid
536 stubs.api.pipeline_instances().create.assert_called_with(
537 body=JsonDiffMatcher(expect_pipeline))
540 def test_submit_container(self, stubs):
541 exited = arvados_cwl.main(
542 ["--submit", "--no-wait", "--api=containers", "--debug",
543 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
544 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
546 stubs.api.collections().create.assert_has_calls([
547 mock.call(body=JsonDiffMatcher({
549 '. 979af1245a12a1fed634d4222473bfdc+16 0:16:blorp.txt\n',
550 'replication_desired': None,
551 'name': 'submit_wf.cwl input (169f39d466a5438ac4a90e779bf750c7+53)',
552 }), ensure_unique_name=False),
553 mock.call(body=JsonDiffMatcher({
555 '. 5bcc9fe8f8d5992e6cf418dc7ce4dbb3+16 0:16:blub.txt\n',
556 'replication_desired': None,
557 'name': 'submit_tool.cwl dependencies (5d373e7629203ce39e7c22af98a0f881+52)',
558 }), ensure_unique_name=False),
561 expect_container = copy.deepcopy(stubs.expect_container_spec)
562 stubs.api.container_requests().create.assert_called_with(
563 body=JsonDiffMatcher(expect_container))
564 self.assertEqual(stubs.capture_stdout.getvalue(),
565 stubs.expect_container_request_uuid + '\n')
566 self.assertEqual(exited, 0)
569 def test_submit_container_no_reuse(self, stubs):
570 exited = arvados_cwl.main(
571 ["--submit", "--no-wait", "--api=containers", "--debug", "--disable-reuse",
572 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
573 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
575 expect_container = copy.deepcopy(stubs.expect_container_spec)
576 expect_container["command"] = [
577 'arvados-cwl-runner', '--local', '--api=containers',
578 '--no-log-timestamps', '--disable-validate',
579 '--eval-timeout=20', '--thread-count=1',
580 '--disable-reuse', "--collection-cache-size=256",
581 '--debug', '--on-error=continue',
582 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
583 expect_container["use_existing"] = False
585 stubs.api.container_requests().create.assert_called_with(
586 body=JsonDiffMatcher(expect_container))
587 self.assertEqual(stubs.capture_stdout.getvalue(),
588 stubs.expect_container_request_uuid + '\n')
589 self.assertEqual(exited, 0)
592 def test_submit_container_reuse_disabled_by_workflow(self, stubs):
593 exited = arvados_cwl.main(
594 ["--submit", "--no-wait", "--api=containers", "--debug",
595 "tests/wf/submit_wf_no_reuse.cwl", "tests/submit_test_job.json"],
596 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
597 self.assertEqual(exited, 0)
599 expect_container = copy.deepcopy(stubs.expect_container_spec)
600 expect_container["command"] = [
601 'arvados-cwl-runner', '--local', '--api=containers',
602 '--no-log-timestamps', '--disable-validate',
603 '--eval-timeout=20', '--thread-count=1',
604 '--disable-reuse', "--collection-cache-size=256", '--debug', '--on-error=continue',
605 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
606 expect_container["use_existing"] = False
607 expect_container["name"] = "submit_wf_no_reuse.cwl"
608 expect_container["mounts"]["/var/lib/cwl/workflow.json"]["content"]["$graph"][1]["hints"] = [
610 "class": "http://arvados.org/cwl#ReuseRequirement",
611 "enableReuse": False,
614 expect_container["mounts"]["/var/lib/cwl/workflow.json"]["content"]["$graph"][0]["$namespaces"] = {
615 "arv": "http://arvados.org/cwl#",
616 "cwltool": "http://commonwl.org/cwltool#"
619 stubs.api.container_requests().create.assert_called_with(
620 body=JsonDiffMatcher(expect_container))
621 self.assertEqual(stubs.capture_stdout.getvalue(),
622 stubs.expect_container_request_uuid + '\n')
626 def test_submit_container_on_error(self, stubs):
627 exited = arvados_cwl.main(
628 ["--submit", "--no-wait", "--api=containers", "--debug", "--on-error=stop",
629 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
630 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
632 expect_container = copy.deepcopy(stubs.expect_container_spec)
633 expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
634 '--no-log-timestamps', '--disable-validate',
635 '--eval-timeout=20', '--thread-count=1',
636 '--enable-reuse', "--collection-cache-size=256",
637 '--debug', '--on-error=stop',
638 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
640 stubs.api.container_requests().create.assert_called_with(
641 body=JsonDiffMatcher(expect_container))
642 self.assertEqual(stubs.capture_stdout.getvalue(),
643 stubs.expect_container_request_uuid + '\n')
644 self.assertEqual(exited, 0)
647 def test_submit_container_output_name(self, stubs):
648 output_name = "test_output_name"
650 exited = arvados_cwl.main(
651 ["--submit", "--no-wait", "--api=containers", "--debug", "--output-name", output_name,
652 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
653 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
655 expect_container = copy.deepcopy(stubs.expect_container_spec)
656 expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
657 '--no-log-timestamps', '--disable-validate',
658 '--eval-timeout=20', '--thread-count=1',
659 '--enable-reuse', "--collection-cache-size=256",
660 "--output-name="+output_name, '--debug', '--on-error=continue',
661 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
662 expect_container["output_name"] = output_name
664 stubs.api.container_requests().create.assert_called_with(
665 body=JsonDiffMatcher(expect_container))
666 self.assertEqual(stubs.capture_stdout.getvalue(),
667 stubs.expect_container_request_uuid + '\n')
668 self.assertEqual(exited, 0)
671 def test_submit_storage_classes(self, stubs):
672 exited = arvados_cwl.main(
673 ["--debug", "--submit", "--no-wait", "--api=containers", "--storage-classes=foo",
674 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
675 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
677 expect_container = copy.deepcopy(stubs.expect_container_spec)
678 expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
679 '--no-log-timestamps', '--disable-validate',
680 '--eval-timeout=20', '--thread-count=1',
681 '--enable-reuse', "--collection-cache-size=256", "--debug",
682 "--storage-classes=foo", '--on-error=continue',
683 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
685 stubs.api.container_requests().create.assert_called_with(
686 body=JsonDiffMatcher(expect_container))
687 self.assertEqual(stubs.capture_stdout.getvalue(),
688 stubs.expect_container_request_uuid + '\n')
689 self.assertEqual(exited, 0)
691 @mock.patch("arvados_cwl.task_queue.TaskQueue")
692 @mock.patch("arvados_cwl.arvworkflow.ArvadosWorkflow.job")
693 @mock.patch("arvados_cwl.executor.ArvCwlExecutor.make_output_collection", return_value = (None, None))
695 def test_storage_classes_correctly_propagate_to_make_output_collection(self, stubs, make_output, job, tq):
696 def set_final_output(job_order, output_callback, runtimeContext):
697 output_callback("zzzzz-4zz18-zzzzzzzzzzzzzzzz", "success")
699 job.side_effect = set_final_output
701 exited = arvados_cwl.main(
702 ["--debug", "--local", "--storage-classes=foo",
703 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
704 sys.stdin, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
706 make_output.assert_called_with(u'Output of submit_wf.cwl', ['foo'], '', 'zzzzz-4zz18-zzzzzzzzzzzzzzzz')
707 self.assertEqual(exited, 0)
709 @mock.patch("arvados_cwl.task_queue.TaskQueue")
710 @mock.patch("arvados_cwl.arvworkflow.ArvadosWorkflow.job")
711 @mock.patch("arvados_cwl.executor.ArvCwlExecutor.make_output_collection", return_value = (None, None))
713 def test_default_storage_classes_correctly_propagate_to_make_output_collection(self, stubs, make_output, job, tq):
714 def set_final_output(job_order, output_callback, runtimeContext):
715 output_callback("zzzzz-4zz18-zzzzzzzzzzzzzzzz", "success")
717 job.side_effect = set_final_output
719 exited = arvados_cwl.main(
720 ["--debug", "--local",
721 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
722 sys.stdin, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
724 make_output.assert_called_with(u'Output of submit_wf.cwl', ['default'], '', 'zzzzz-4zz18-zzzzzzzzzzzzzzzz')
725 self.assertEqual(exited, 0)
728 def test_submit_container_output_ttl(self, stubs):
729 exited = arvados_cwl.main(
730 ["--submit", "--no-wait", "--api=containers", "--debug", "--intermediate-output-ttl", "3600",
731 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
732 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
734 expect_container = copy.deepcopy(stubs.expect_container_spec)
735 expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
736 '--no-log-timestamps', '--disable-validate',
737 '--eval-timeout=20', '--thread-count=1',
738 '--enable-reuse', "--collection-cache-size=256", '--debug',
739 '--on-error=continue',
740 "--intermediate-output-ttl=3600",
741 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
743 stubs.api.container_requests().create.assert_called_with(
744 body=JsonDiffMatcher(expect_container))
745 self.assertEqual(stubs.capture_stdout.getvalue(),
746 stubs.expect_container_request_uuid + '\n')
747 self.assertEqual(exited, 0)
750 def test_submit_container_trash_intermediate(self, stubs):
751 exited = arvados_cwl.main(
752 ["--submit", "--no-wait", "--api=containers", "--debug", "--trash-intermediate",
753 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
754 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
757 expect_container = copy.deepcopy(stubs.expect_container_spec)
758 expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
759 '--no-log-timestamps', '--disable-validate',
760 '--eval-timeout=20', '--thread-count=1',
761 '--enable-reuse', "--collection-cache-size=256",
762 '--debug', '--on-error=continue',
763 "--trash-intermediate",
764 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
766 stubs.api.container_requests().create.assert_called_with(
767 body=JsonDiffMatcher(expect_container))
768 self.assertEqual(stubs.capture_stdout.getvalue(),
769 stubs.expect_container_request_uuid + '\n')
770 self.assertEqual(exited, 0)
773 def test_submit_container_output_tags(self, stubs):
774 output_tags = "tag0,tag1,tag2"
776 exited = arvados_cwl.main(
777 ["--submit", "--no-wait", "--api=containers", "--debug", "--output-tags", output_tags,
778 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
779 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
781 expect_container = copy.deepcopy(stubs.expect_container_spec)
782 expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
783 '--no-log-timestamps', '--disable-validate',
784 '--eval-timeout=20', '--thread-count=1',
785 '--enable-reuse', "--collection-cache-size=256",
786 "--output-tags="+output_tags, '--debug', '--on-error=continue',
787 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
789 stubs.api.container_requests().create.assert_called_with(
790 body=JsonDiffMatcher(expect_container))
791 self.assertEqual(stubs.capture_stdout.getvalue(),
792 stubs.expect_container_request_uuid + '\n')
793 self.assertEqual(exited, 0)
796 def test_submit_container_runner_ram(self, stubs):
797 exited = arvados_cwl.main(
798 ["--submit", "--no-wait", "--api=containers", "--debug", "--submit-runner-ram=2048",
799 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
800 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
802 expect_container = copy.deepcopy(stubs.expect_container_spec)
803 expect_container["runtime_constraints"]["ram"] = (2048+256)*1024*1024
805 stubs.api.container_requests().create.assert_called_with(
806 body=JsonDiffMatcher(expect_container))
807 self.assertEqual(stubs.capture_stdout.getvalue(),
808 stubs.expect_container_request_uuid + '\n')
809 self.assertEqual(exited, 0)
811 @mock.patch("arvados.collection.CollectionReader")
812 @mock.patch("time.sleep")
814 def test_submit_file_keepref(self, stubs, tm, collectionReader):
815 collectionReader().find.return_value = arvados.arvfile.ArvadosFile(mock.MagicMock(), "blorp.txt")
816 exited = arvados_cwl.main(
817 ["--submit", "--no-wait", "--api=containers", "--debug",
818 "tests/wf/submit_keepref_wf.cwl"],
819 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
820 self.assertEqual(exited, 0)
822 @mock.patch("arvados.collection.CollectionReader")
823 @mock.patch("time.sleep")
825 def test_submit_keepref(self, stubs, tm, reader):
826 with open("tests/wf/expect_arvworkflow.cwl") as f:
827 reader().open().__enter__().read.return_value = f.read()
829 exited = arvados_cwl.main(
830 ["--submit", "--no-wait", "--api=containers", "--debug",
831 "keep:99999999999999999999999999999994+99/expect_arvworkflow.cwl#main", "-x", "XxX"],
832 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
842 'path': '/var/spool/cwl/cwl.output.json',
845 '/var/lib/cwl/workflow': {
846 'portable_data_hash': '99999999999999999999999999999994+99',
849 '/var/lib/cwl/cwl.input.json': {
855 }, 'state': 'Committed',
856 'output_path': '/var/spool/cwl',
857 'name': 'expect_arvworkflow.cwl#main',
858 'container_image': '999999999999999999999999999999d3+99',
859 'command': ['arvados-cwl-runner', '--local', '--api=containers',
860 '--no-log-timestamps', '--disable-validate',
861 '--eval-timeout=20', '--thread-count=1',
862 '--enable-reuse', "--collection-cache-size=256", '--debug', '--on-error=continue',
863 '/var/lib/cwl/workflow/expect_arvworkflow.cwl#main', '/var/lib/cwl/cwl.input.json'],
864 'cwd': '/var/spool/cwl',
865 'runtime_constraints': {
870 'use_existing': True,
875 stubs.api.container_requests().create.assert_called_with(
876 body=JsonDiffMatcher(expect_container))
877 self.assertEqual(stubs.capture_stdout.getvalue(),
878 stubs.expect_container_request_uuid + '\n')
879 self.assertEqual(exited, 0)
881 @mock.patch("arvados.collection.CollectionReader")
882 @mock.patch("time.sleep")
884 def test_submit_jobs_keepref(self, stubs, tm, reader):
885 with open("tests/wf/expect_arvworkflow.cwl") as f:
886 reader().open().__enter__().read.return_value = f.read()
888 exited = arvados_cwl.main(
889 ["--submit", "--no-wait", "--api=jobs", "--debug",
890 "keep:99999999999999999999999999999994+99/expect_arvworkflow.cwl#main", "-x", "XxX"],
891 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
893 expect_pipeline = copy.deepcopy(stubs.expect_pipeline_instance)
894 expect_pipeline["components"]["cwl-runner"]["script_parameters"]["x"] = "XxX"
895 del expect_pipeline["components"]["cwl-runner"]["script_parameters"]["y"]
896 del expect_pipeline["components"]["cwl-runner"]["script_parameters"]["z"]
897 expect_pipeline["components"]["cwl-runner"]["script_parameters"]["cwl:tool"] = "99999999999999999999999999999994+99/expect_arvworkflow.cwl#main"
898 expect_pipeline["name"] = "expect_arvworkflow.cwl#main"
899 stubs.api.pipeline_instances().create.assert_called_with(
900 body=JsonDiffMatcher(expect_pipeline))
901 self.assertEqual(exited, 0)
903 @mock.patch("time.sleep")
905 def test_submit_arvworkflow(self, stubs, tm):
906 with open("tests/wf/expect_arvworkflow.cwl") as f:
907 stubs.api.workflows().get().execute.return_value = {"definition": f.read(), "name": "a test workflow"}
909 exited = arvados_cwl.main(
910 ["--submit", "--no-wait", "--api=containers", "--debug",
911 "962eh-7fd4e-gkbzl62qqtfig37", "-x", "XxX"],
912 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
922 'path': '/var/spool/cwl/cwl.output.json',
925 '/var/lib/cwl/workflow.json': {
928 'cwlVersion': 'v1.0',
933 {'type': 'string', 'id': '#main/x'}
936 {'in': [{'source': '#main/x', 'id': '#main/step1/x'}],
937 'run': '#submit_tool.cwl',
947 'inputBinding': {'position': 1},
949 'id': '#submit_tool.cwl/x'}
953 'dockerPull': 'debian:8',
954 'class': 'DockerRequirement',
955 "http://arvados.org/cwl#dockerCollectionPDH": "999999999999999999999999999999d4+99"
958 'id': '#submit_tool.cwl',
960 'baseCommand': 'cat',
961 'class': 'CommandLineTool'
966 '/var/lib/cwl/cwl.input.json': {
972 }, 'state': 'Committed',
973 'output_path': '/var/spool/cwl',
974 'name': 'a test workflow',
975 'container_image': "999999999999999999999999999999d3+99",
976 'command': ['arvados-cwl-runner', '--local', '--api=containers',
977 '--no-log-timestamps', '--disable-validate',
978 '--eval-timeout=20', '--thread-count=1',
979 '--enable-reuse', "--collection-cache-size=256", '--debug', '--on-error=continue',
980 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json'],
981 'cwd': '/var/spool/cwl',
982 'runtime_constraints': {
987 'use_existing': True,
989 "template_uuid": "962eh-7fd4e-gkbzl62qqtfig37"
994 stubs.api.container_requests().create.assert_called_with(
995 body=JsonDiffMatcher(expect_container))
996 self.assertEqual(stubs.capture_stdout.getvalue(),
997 stubs.expect_container_request_uuid + '\n')
998 self.assertEqual(exited, 0)
1001 def test_submit_container_name(self, stubs):
1002 exited = arvados_cwl.main(
1003 ["--submit", "--no-wait", "--api=containers", "--debug", "--name=hello container 123",
1004 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1005 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1007 expect_container = copy.deepcopy(stubs.expect_container_spec)
1008 expect_container["name"] = "hello container 123"
1010 stubs.api.container_requests().create.assert_called_with(
1011 body=JsonDiffMatcher(expect_container))
1012 self.assertEqual(stubs.capture_stdout.getvalue(),
1013 stubs.expect_container_request_uuid + '\n')
1014 self.assertEqual(exited, 0)
1017 def test_submit_missing_input(self, stubs):
1018 exited = arvados_cwl.main(
1019 ["--submit", "--no-wait", "--api=containers", "--debug",
1020 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1021 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1022 self.assertEqual(exited, 0)
1024 exited = arvados_cwl.main(
1025 ["--submit", "--no-wait", "--api=containers", "--debug",
1026 "tests/wf/submit_wf.cwl", "tests/submit_test_job_missing.json"],
1027 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1028 self.assertEqual(exited, 1)
1031 def test_submit_container_project(self, stubs):
1032 project_uuid = 'zzzzz-j7d0g-zzzzzzzzzzzzzzz'
1033 exited = arvados_cwl.main(
1034 ["--submit", "--no-wait", "--api=containers", "--debug", "--project-uuid="+project_uuid,
1035 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1036 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1038 expect_container = copy.deepcopy(stubs.expect_container_spec)
1039 expect_container["owner_uuid"] = project_uuid
1040 expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
1041 '--no-log-timestamps', '--disable-validate',
1042 "--eval-timeout=20", "--thread-count=1",
1043 '--enable-reuse', "--collection-cache-size=256", '--debug',
1044 '--on-error=continue',
1045 '--project-uuid='+project_uuid,
1046 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
1048 stubs.api.container_requests().create.assert_called_with(
1049 body=JsonDiffMatcher(expect_container))
1050 self.assertEqual(stubs.capture_stdout.getvalue(),
1051 stubs.expect_container_request_uuid + '\n')
1052 self.assertEqual(exited, 0)
1055 def test_submit_container_eval_timeout(self, stubs):
1056 exited = arvados_cwl.main(
1057 ["--submit", "--no-wait", "--api=containers", "--debug", "--eval-timeout=60",
1058 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1059 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1061 expect_container = copy.deepcopy(stubs.expect_container_spec)
1062 expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
1063 '--no-log-timestamps', '--disable-validate',
1064 '--eval-timeout=60.0', '--thread-count=1',
1065 '--enable-reuse', "--collection-cache-size=256",
1066 '--debug', '--on-error=continue',
1067 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
1069 stubs.api.container_requests().create.assert_called_with(
1070 body=JsonDiffMatcher(expect_container))
1071 self.assertEqual(stubs.capture_stdout.getvalue(),
1072 stubs.expect_container_request_uuid + '\n')
1073 self.assertEqual(exited, 0)
1076 def test_submit_container_collection_cache(self, stubs):
1077 exited = arvados_cwl.main(
1078 ["--submit", "--no-wait", "--api=containers", "--debug", "--collection-cache-size=500",
1079 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1080 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1082 expect_container = copy.deepcopy(stubs.expect_container_spec)
1083 expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
1084 '--no-log-timestamps', '--disable-validate',
1085 '--eval-timeout=20', '--thread-count=1',
1086 '--enable-reuse', "--collection-cache-size=500",
1087 '--debug', '--on-error=continue',
1088 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
1089 expect_container["runtime_constraints"]["ram"] = (1024+500)*1024*1024
1091 stubs.api.container_requests().create.assert_called_with(
1092 body=JsonDiffMatcher(expect_container))
1093 self.assertEqual(stubs.capture_stdout.getvalue(),
1094 stubs.expect_container_request_uuid + '\n')
1095 self.assertEqual(exited, 0)
1098 def test_submit_container_thread_count(self, stubs):
1099 exited = arvados_cwl.main(
1100 ["--submit", "--no-wait", "--api=containers", "--debug", "--thread-count=20",
1101 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1102 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1104 expect_container = copy.deepcopy(stubs.expect_container_spec)
1105 expect_container["command"] = ['arvados-cwl-runner', '--local', '--api=containers',
1106 '--no-log-timestamps', '--disable-validate',
1107 '--eval-timeout=20', '--thread-count=20',
1108 '--enable-reuse', "--collection-cache-size=256",
1109 '--debug', '--on-error=continue',
1110 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
1112 stubs.api.container_requests().create.assert_called_with(
1113 body=JsonDiffMatcher(expect_container))
1114 self.assertEqual(stubs.capture_stdout.getvalue(),
1115 stubs.expect_container_request_uuid + '\n')
1116 self.assertEqual(exited, 0)
1119 def test_submit_job_runner_image(self, stubs):
1120 exited = arvados_cwl.main(
1121 ["--submit", "--no-wait", "--api=jobs", "--debug", "--submit-runner-image=arvados/jobs:123",
1122 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1123 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1125 stubs.expect_pipeline_instance["components"]["cwl-runner"]["runtime_constraints"]["docker_image"] = "999999999999999999999999999999d5+99"
1127 expect_pipeline = copy.deepcopy(stubs.expect_pipeline_instance)
1128 stubs.api.pipeline_instances().create.assert_called_with(
1129 body=JsonDiffMatcher(expect_pipeline))
1130 self.assertEqual(stubs.capture_stdout.getvalue(),
1131 stubs.expect_pipeline_uuid + '\n')
1132 self.assertEqual(exited, 0)
1135 def test_submit_container_runner_image(self, stubs):
1136 exited = arvados_cwl.main(
1137 ["--submit", "--no-wait", "--api=containers", "--debug", "--submit-runner-image=arvados/jobs:123",
1138 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1139 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1141 stubs.expect_container_spec["container_image"] = "999999999999999999999999999999d5+99"
1143 expect_container = copy.deepcopy(stubs.expect_container_spec)
1144 stubs.api.container_requests().create.assert_called_with(
1145 body=JsonDiffMatcher(expect_container))
1146 self.assertEqual(stubs.capture_stdout.getvalue(),
1147 stubs.expect_container_request_uuid + '\n')
1148 self.assertEqual(exited, 0)
1151 def test_submit_priority(self, stubs):
1152 exited = arvados_cwl.main(
1153 ["--submit", "--no-wait", "--api=containers", "--debug", "--priority=669",
1154 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1155 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1157 stubs.expect_container_spec["priority"] = 669
1159 expect_container = copy.deepcopy(stubs.expect_container_spec)
1160 stubs.api.container_requests().create.assert_called_with(
1161 body=JsonDiffMatcher(expect_container))
1162 self.assertEqual(stubs.capture_stdout.getvalue(),
1163 stubs.expect_container_request_uuid + '\n')
1164 self.assertEqual(exited, 0)
1167 def test_submit_wf_runner_resources(self, stubs):
1168 exited = arvados_cwl.main(
1169 ["--submit", "--no-wait", "--api=containers", "--debug",
1170 "tests/wf/submit_wf_runner_resources.cwl", "tests/submit_test_job.json"],
1171 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1173 expect_container = copy.deepcopy(stubs.expect_container_spec)
1174 expect_container["runtime_constraints"] = {
1177 "ram": (2000+512) * 2**20
1179 expect_container["name"] = "submit_wf_runner_resources.cwl"
1180 expect_container["mounts"]["/var/lib/cwl/workflow.json"]["content"]["$graph"][1]["hints"] = [
1182 "class": "http://arvados.org/cwl#WorkflowRunnerResources",
1188 expect_container["mounts"]["/var/lib/cwl/workflow.json"]["content"]["$graph"][0]["$namespaces"] = {
1189 "arv": "http://arvados.org/cwl#",
1191 expect_container['command'] = ['arvados-cwl-runner', '--local', '--api=containers',
1192 '--no-log-timestamps', '--disable-validate',
1193 '--eval-timeout=20', '--thread-count=1',
1194 '--enable-reuse', "--collection-cache-size=512", '--debug', '--on-error=continue',
1195 '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json']
1197 stubs.api.container_requests().create.assert_called_with(
1198 body=JsonDiffMatcher(expect_container))
1199 self.assertEqual(stubs.capture_stdout.getvalue(),
1200 stubs.expect_container_request_uuid + '\n')
1201 self.assertEqual(exited, 0)
1204 arvados_cwl.arvdocker.arv_docker_clear_cache()
1206 @mock.patch("arvados.commands.keepdocker.find_one_image_hash")
1207 @mock.patch("cwltool.docker.DockerCommandLineJob.get_image")
1208 @mock.patch("arvados.api")
1209 def test_arvados_jobs_image(self, api, get_image, find_one_image_hash):
1210 arvados_cwl.arvdocker.arv_docker_clear_cache()
1212 arvrunner = mock.MagicMock()
1213 arvrunner.project_uuid = ""
1214 api.return_value = mock.MagicMock()
1215 arvrunner.api = api.return_value
1216 arvrunner.api.links().list().execute.side_effect = ({"items": [{"created_at": "",
1217 "head_uuid": "zzzzz-4zz18-zzzzzzzzzzzzzzb",
1218 "link_class": "docker_image_repo+tag",
1219 "name": "arvados/jobs:"+arvados_cwl.__version__,
1221 "properties": {"image_timestamp": ""}}], "items_available": 1, "offset": 0},
1222 {"items": [{"created_at": "",
1224 "link_class": "docker_image_hash",
1227 "properties": {"image_timestamp": ""}}], "items_available": 1, "offset": 0}
1229 find_one_image_hash.return_value = "123456"
1231 arvrunner.api.collections().list().execute.side_effect = ({"items": [{"uuid": "zzzzz-4zz18-zzzzzzzzzzzzzzb",
1233 "manifest_text": "",
1235 }], "items_available": 1, "offset": 0},)
1236 arvrunner.api.collections().create().execute.return_value = {"uuid": ""}
1237 arvrunner.api.collections().get().execute.return_value = {"uuid": "zzzzz-4zz18-zzzzzzzzzzzzzzb",
1238 "portable_data_hash": "9999999999999999999999999999999b+99"}
1239 self.assertEqual("9999999999999999999999999999999b+99",
1240 arvados_cwl.runner.arvados_jobs_image(arvrunner, "arvados/jobs:"+arvados_cwl.__version__))
1244 def test_submit_secrets(self, stubs):
1245 exited = arvados_cwl.main(
1246 ["--submit", "--no-wait", "--api=containers", "--debug",
1247 "tests/wf/secret_wf.cwl", "tests/secret_test_job.yml"],
1248 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1250 expect_container = {
1252 "arvados-cwl-runner",
1255 "--no-log-timestamps",
1256 "--disable-validate",
1257 "--eval-timeout=20",
1260 "--collection-cache-size=256",
1262 "--on-error=continue",
1263 "/var/lib/cwl/workflow.json#main",
1264 "/var/lib/cwl/cwl.input.json"
1266 "container_image": "999999999999999999999999999999d3+99",
1267 "cwd": "/var/spool/cwl",
1269 "/var/lib/cwl/cwl.input.json": {
1272 "$include": "/secrets/s0"
1277 "/var/lib/cwl/workflow.json": {
1282 "cwltool": "http://commonwl.org/cwltool#"
1288 "class": "CommandLineTool",
1291 "class": "http://commonwl.org/cwltool#Secrets",
1293 "#secret_job.cwl/pw"
1297 "id": "#secret_job.cwl",
1300 "id": "#secret_job.cwl/pw",
1306 "id": "#secret_job.cwl/out",
1310 "stdout": "hashed_example.txt",
1313 "class": "InitialWorkDirRequirement",
1316 "entry": "username: user\npassword: $(inputs.pw)\n",
1317 "entryname": "example.conf"
1324 "class": "Workflow",
1327 "class": "DockerRequirement",
1328 "dockerPull": "debian:8",
1329 "http://arvados.org/cwl#dockerCollectionPDH": "999999999999999999999999999999d4+99"
1332 "class": "http://commonwl.org/cwltool#Secrets",
1348 "outputSource": "#main/step1/out",
1354 "id": "#main/step1",
1357 "id": "#main/step1/pw",
1358 "source": "#main/pw"
1364 "run": "#secret_job.cwl"
1369 "cwlVersion": "v1.0"
1374 "kind": "collection",
1379 "path": "/var/spool/cwl/cwl.output.json"
1382 "name": "secret_wf.cwl",
1383 "output_path": "/var/spool/cwl",
1386 "runtime_constraints": {
1397 "state": "Committed",
1398 "use_existing": True
1401 stubs.api.container_requests().create.assert_called_with(
1402 body=JsonDiffMatcher(expect_container))
1403 self.assertEqual(stubs.capture_stdout.getvalue(),
1404 stubs.expect_container_request_uuid + '\n')
1405 self.assertEqual(exited, 0)
1408 def test_submit_request_uuid(self, stubs):
1409 stubs.api._rootDesc["remoteHosts"]["zzzzz"] = "123"
1410 stubs.expect_container_request_uuid = "zzzzz-xvhdp-yyyyyyyyyyyyyyy"
1412 stubs.api.container_requests().update().execute.return_value = {
1413 "uuid": stubs.expect_container_request_uuid,
1414 "container_uuid": "zzzzz-dz642-zzzzzzzzzzzzzzz",
1418 exited = arvados_cwl.main(
1419 ["--submit", "--no-wait", "--api=containers", "--debug", "--submit-request-uuid=zzzzz-xvhdp-yyyyyyyyyyyyyyy",
1420 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1421 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1423 stubs.api.container_requests().update.assert_called_with(
1424 uuid="zzzzz-xvhdp-yyyyyyyyyyyyyyy", body=JsonDiffMatcher(stubs.expect_container_spec))
1425 self.assertEqual(stubs.capture_stdout.getvalue(),
1426 stubs.expect_container_request_uuid + '\n')
1427 self.assertEqual(exited, 0)
1430 def test_submit_container_cluster_id(self, stubs):
1431 stubs.api._rootDesc["remoteHosts"]["zbbbb"] = "123"
1433 exited = arvados_cwl.main(
1434 ["--submit", "--no-wait", "--api=containers", "--debug", "--submit-runner-cluster=zbbbb",
1435 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1436 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1438 expect_container = copy.deepcopy(stubs.expect_container_spec)
1440 stubs.api.container_requests().create.assert_called_with(
1441 body=JsonDiffMatcher(expect_container), cluster_id="zbbbb")
1442 self.assertEqual(stubs.capture_stdout.getvalue(),
1443 stubs.expect_container_request_uuid + '\n')
1444 self.assertEqual(exited, 0)
1447 def test_submit_validate_cluster_id(self, stubs):
1448 stubs.api._rootDesc["remoteHosts"]["zbbbb"] = "123"
1449 exited = arvados_cwl.main(
1450 ["--submit", "--no-wait", "--api=containers", "--debug", "--submit-runner-cluster=zcccc",
1451 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1452 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1453 self.assertEqual(exited, 1)
1455 @mock.patch("arvados.collection.CollectionReader")
1457 def test_submit_uuid_inputs(self, stubs, collectionReader):
1458 collectionReader().find.return_value = arvados.arvfile.ArvadosFile(mock.MagicMock(), "file1.txt")
1459 def list_side_effect(**kwargs):
1460 m = mock.MagicMock()
1461 if "count" in kwargs:
1462 m.execute.return_value = {"items": [
1463 {"uuid": "zzzzz-4zz18-zzzzzzzzzzzzzzz", "portable_data_hash": "99999999999999999999999999999998+99"}
1466 m.execute.return_value = {"items": []}
1468 stubs.api.collections().list.side_effect = list_side_effect
1470 exited = arvados_cwl.main(
1471 ["--submit", "--no-wait", "--api=containers", "--debug",
1472 "tests/wf/submit_wf.cwl", "tests/submit_test_job_with_uuids.json"],
1473 stubs.capture_stdout, sys.stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1475 expect_container = copy.deepcopy(stubs.expect_container_spec)
1476 expect_container['mounts']['/var/lib/cwl/cwl.input.json']['content']['y']['basename'] = 'zzzzz-4zz18-zzzzzzzzzzzzzzz'
1477 expect_container['mounts']['/var/lib/cwl/cwl.input.json']['content']['y']['http://arvados.org/cwl#collectionUUID'] = 'zzzzz-4zz18-zzzzzzzzzzzzzzz'
1478 expect_container['mounts']['/var/lib/cwl/cwl.input.json']['content']['z']['listing'][0]['http://arvados.org/cwl#collectionUUID'] = 'zzzzz-4zz18-zzzzzzzzzzzzzzz'
1480 stubs.api.collections().list.assert_has_calls([
1481 mock.call(count='none',
1482 filters=[['uuid', 'in', ['zzzzz-4zz18-zzzzzzzzzzzzzzz']]],
1483 select=['uuid', 'portable_data_hash'])])
1484 stubs.api.container_requests().create.assert_called_with(
1485 body=JsonDiffMatcher(expect_container))
1486 self.assertEqual(stubs.capture_stdout.getvalue(),
1487 stubs.expect_container_request_uuid + '\n')
1488 self.assertEqual(exited, 0)
1491 def test_submit_mismatched_uuid_inputs(self, stubs):
1492 def list_side_effect(**kwargs):
1493 m = mock.MagicMock()
1494 if "count" in kwargs:
1495 m.execute.return_value = {"items": [
1496 {"uuid": "zzzzz-4zz18-zzzzzzzzzzzzzzz", "portable_data_hash": "99999999999999999999999999999997+99"}
1499 m.execute.return_value = {"items": []}
1501 stubs.api.collections().list.side_effect = list_side_effect
1503 for infile in ("tests/submit_test_job_with_mismatched_uuids.json", "tests/submit_test_job_with_inconsistent_uuids.json"):
1504 capture_stderr = StringIO()
1505 cwltool_logger = logging.getLogger('cwltool')
1506 stderr_logger = logging.StreamHandler(capture_stderr)
1507 cwltool_logger.addHandler(stderr_logger)
1510 exited = arvados_cwl.main(
1511 ["--submit", "--no-wait", "--api=containers", "--debug",
1512 "tests/wf/submit_wf.cwl", infile],
1513 stubs.capture_stdout, capture_stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1515 self.assertEqual(exited, 1)
1516 self.assertRegexpMatches(
1517 capture_stderr.getvalue(),
1518 r"Expected collection uuid zzzzz-4zz18-zzzzzzzzzzzzzzz to be 99999999999999999999999999999998\+99 but API server reported 99999999999999999999999999999997\+99")
1520 cwltool_logger.removeHandler(stderr_logger)
1522 @mock.patch("arvados.collection.CollectionReader")
1524 def test_submit_unknown_uuid_inputs(self, stubs, collectionReader):
1525 collectionReader().find.return_value = arvados.arvfile.ArvadosFile(mock.MagicMock(), "file1.txt")
1526 capture_stderr = StringIO()
1528 cwltool_logger = logging.getLogger('cwltool')
1529 stderr_logger = logging.StreamHandler(capture_stderr)
1530 cwltool_logger.addHandler(stderr_logger)
1532 exited = arvados_cwl.main(
1533 ["--submit", "--no-wait", "--api=containers", "--debug",
1534 "tests/wf/submit_wf.cwl", "tests/submit_test_job_with_uuids.json"],
1535 stubs.capture_stdout, capture_stderr, api_client=stubs.api, keep_client=stubs.keep_client)
1538 self.assertEqual(exited, 1)
1539 self.assertRegexpMatches(
1540 capture_stderr.getvalue(),
1541 r"Collection uuid zzzzz-4zz18-zzzzzzzzzzzzzzz not found")
1543 cwltool_logger.removeHandler(stderr_logger)
1546 class TestCreateTemplate(unittest.TestCase):
1547 existing_template_uuid = "zzzzz-p5p6p-validworkfloyml"
1549 def _adjust_script_params(self, expect_component):
1550 expect_component['script_parameters']['x'] = {
1551 'dataclass': 'File',
1554 'value': '169f39d466a5438ac4a90e779bf750c7+53/blorp.txt',
1556 expect_component['script_parameters']['y'] = {
1557 'dataclass': 'Collection',
1559 'type': 'Directory',
1560 'value': '99999999999999999999999999999998+99',
1562 expect_component['script_parameters']['z'] = {
1563 'dataclass': 'Collection',
1565 'type': 'Directory',
1569 def test_create(self, stubs):
1570 project_uuid = 'zzzzz-j7d0g-zzzzzzzzzzzzzzz'
1572 exited = arvados_cwl.main(
1573 ["--create-workflow", "--debug",
1575 "--project-uuid", project_uuid,
1576 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1577 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
1579 stubs.api.pipeline_instances().create.refute_called()
1580 stubs.api.jobs().create.refute_called()
1582 expect_component = copy.deepcopy(stubs.expect_job_spec)
1583 self._adjust_script_params(expect_component)
1586 "submit_wf.cwl": expect_component,
1588 "name": "submit_wf.cwl",
1589 "owner_uuid": project_uuid,
1591 stubs.api.pipeline_templates().create.assert_called_with(
1592 body=JsonDiffMatcher(expect_template), ensure_unique_name=True)
1594 self.assertEqual(stubs.capture_stdout.getvalue(),
1595 stubs.expect_pipeline_template_uuid + '\n')
1596 self.assertEqual(exited, 0)
1599 def test_create_name(self, stubs):
1600 project_uuid = 'zzzzz-j7d0g-zzzzzzzzzzzzzzz'
1602 exited = arvados_cwl.main(
1603 ["--create-workflow", "--debug",
1604 "--project-uuid", project_uuid,
1606 "--name", "testing 123",
1607 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1608 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
1610 stubs.api.pipeline_instances().create.refute_called()
1611 stubs.api.jobs().create.refute_called()
1613 expect_component = copy.deepcopy(stubs.expect_job_spec)
1614 self._adjust_script_params(expect_component)
1617 "testing 123": expect_component,
1619 "name": "testing 123",
1620 "owner_uuid": project_uuid,
1622 stubs.api.pipeline_templates().create.assert_called_with(
1623 body=JsonDiffMatcher(expect_template), ensure_unique_name=True)
1625 self.assertEqual(stubs.capture_stdout.getvalue(),
1626 stubs.expect_pipeline_template_uuid + '\n')
1627 self.assertEqual(exited, 0)
1630 def test_update_name(self, stubs):
1631 project_uuid = 'zzzzz-j7d0g-zzzzzzzzzzzzzzz'
1633 exited = arvados_cwl.main(
1634 ["--update-workflow", self.existing_template_uuid,
1636 "--project-uuid", project_uuid,
1638 "--name", "testing 123",
1639 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1640 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
1642 stubs.api.pipeline_instances().create.refute_called()
1643 stubs.api.jobs().create.refute_called()
1645 expect_component = copy.deepcopy(stubs.expect_job_spec)
1646 self._adjust_script_params(expect_component)
1649 "testing 123": expect_component,
1651 "name": "testing 123",
1652 "owner_uuid": project_uuid,
1654 stubs.api.pipeline_templates().create.refute_called()
1655 stubs.api.pipeline_templates().update.assert_called_with(
1656 body=JsonDiffMatcher(expect_template), uuid=self.existing_template_uuid)
1658 self.assertEqual(stubs.capture_stdout.getvalue(),
1659 self.existing_template_uuid + '\n')
1660 self.assertEqual(exited, 0)
1663 class TestCreateWorkflow(unittest.TestCase):
1664 existing_workflow_uuid = "zzzzz-7fd4e-validworkfloyml"
1665 expect_workflow = StripYAMLComments(
1666 open("tests/wf/expect_packed.cwl").read())
1669 def test_create(self, stubs):
1670 project_uuid = 'zzzzz-j7d0g-zzzzzzzzzzzzzzz'
1672 exited = arvados_cwl.main(
1673 ["--create-workflow", "--debug",
1675 "--project-uuid", project_uuid,
1676 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1677 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
1679 stubs.api.pipeline_templates().create.refute_called()
1680 stubs.api.container_requests().create.refute_called()
1684 "owner_uuid": project_uuid,
1685 "name": "submit_wf.cwl",
1687 "definition": self.expect_workflow,
1690 stubs.api.workflows().create.assert_called_with(
1691 body=JsonDiffMatcher(body))
1693 self.assertEqual(stubs.capture_stdout.getvalue(),
1694 stubs.expect_workflow_uuid + '\n')
1695 self.assertEqual(exited, 0)
1698 def test_create_name(self, stubs):
1699 project_uuid = 'zzzzz-j7d0g-zzzzzzzzzzzzzzz'
1701 exited = arvados_cwl.main(
1702 ["--create-workflow", "--debug",
1704 "--project-uuid", project_uuid,
1705 "--name", "testing 123",
1706 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1707 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
1709 stubs.api.pipeline_templates().create.refute_called()
1710 stubs.api.container_requests().create.refute_called()
1714 "owner_uuid": project_uuid,
1715 "name": "testing 123",
1717 "definition": self.expect_workflow,
1720 stubs.api.workflows().create.assert_called_with(
1721 body=JsonDiffMatcher(body))
1723 self.assertEqual(stubs.capture_stdout.getvalue(),
1724 stubs.expect_workflow_uuid + '\n')
1725 self.assertEqual(exited, 0)
1728 def test_incompatible_api(self, stubs):
1729 capture_stderr = StringIO()
1730 acr_logger = logging.getLogger('arvados.cwl-runner')
1731 stderr_logger = logging.StreamHandler(capture_stderr)
1732 acr_logger.addHandler(stderr_logger)
1735 exited = arvados_cwl.main(
1736 ["--update-workflow", self.existing_workflow_uuid,
1739 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1740 sys.stderr, sys.stderr, api_client=stubs.api)
1741 self.assertEqual(exited, 1)
1742 self.assertRegexpMatches(
1743 capture_stderr.getvalue(),
1744 "--update-workflow arg '{}' uses 'containers' API, but --api='jobs' specified".format(self.existing_workflow_uuid))
1746 acr_logger.removeHandler(stderr_logger)
1749 def test_update(self, stubs):
1750 exited = arvados_cwl.main(
1751 ["--update-workflow", self.existing_workflow_uuid,
1753 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1754 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
1758 "name": "submit_wf.cwl",
1760 "definition": self.expect_workflow,
1763 stubs.api.workflows().update.assert_called_with(
1764 uuid=self.existing_workflow_uuid,
1765 body=JsonDiffMatcher(body))
1766 self.assertEqual(stubs.capture_stdout.getvalue(),
1767 self.existing_workflow_uuid + '\n')
1768 self.assertEqual(exited, 0)
1771 def test_update_name(self, stubs):
1772 exited = arvados_cwl.main(
1773 ["--update-workflow", self.existing_workflow_uuid,
1774 "--debug", "--name", "testing 123",
1775 "tests/wf/submit_wf.cwl", "tests/submit_test_job.json"],
1776 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
1780 "name": "testing 123",
1782 "definition": self.expect_workflow,
1785 stubs.api.workflows().update.assert_called_with(
1786 uuid=self.existing_workflow_uuid,
1787 body=JsonDiffMatcher(body))
1788 self.assertEqual(stubs.capture_stdout.getvalue(),
1789 self.existing_workflow_uuid + '\n')
1790 self.assertEqual(exited, 0)
1793 def test_create_collection_per_tool(self, stubs):
1794 project_uuid = 'zzzzz-j7d0g-zzzzzzzzzzzzzzz'
1796 exited = arvados_cwl.main(
1797 ["--create-workflow", "--debug",
1799 "--project-uuid", project_uuid,
1800 "tests/collection_per_tool/collection_per_tool.cwl"],
1801 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
1803 toolfile = "tests/collection_per_tool/collection_per_tool_packed.cwl"
1804 expect_workflow = StripYAMLComments(open(toolfile).read())
1808 "owner_uuid": project_uuid,
1809 "name": "collection_per_tool.cwl",
1811 "definition": expect_workflow,
1814 stubs.api.workflows().create.assert_called_with(
1815 body=JsonDiffMatcher(body))
1817 self.assertEqual(stubs.capture_stdout.getvalue(),
1818 stubs.expect_workflow_uuid + '\n')
1819 self.assertEqual(exited, 0)
1821 class TestTemplateInputs(unittest.TestCase):
1824 "inputs_test.cwl": {
1825 'runtime_constraints': {
1826 'docker_image': '999999999999999999999999999999d3+99',
1827 'min_ram_mb_per_node': 1024
1829 'script_parameters': {
1831 'a2de777156fb700f1363b1f2e370adca+60/workflow.cwl#main',
1832 'optionalFloatInput': None,
1835 'dataclass': 'File',
1837 'title': "It's a file; we expect to find some characters in it.",
1838 'description': 'If there were anything further to say, it would be said here,\nor here.'
1842 'dataclass': 'number',
1844 'title': 'Floats like a duck',
1848 'optionalFloatInput': {
1849 'type': ['null', 'float'],
1850 'dataclass': 'number',
1855 'dataclass': 'boolean',
1857 'title': 'True or false?',
1860 'repository': 'arvados',
1861 'script_version': 'master',
1862 'minimum_script_version': '570509ab4d2ef93d870fd2b1f2eab178afb1bad9',
1863 'script': 'cwl-runner',
1866 "name": "inputs_test.cwl",
1870 def test_inputs_empty(self, stubs):
1871 exited = arvados_cwl.main(
1872 ["--debug", "--api=jobs", "--create-template",
1873 "tests/wf/inputs_test.cwl", "tests/order/empty_order.json"],
1874 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
1876 stubs.api.pipeline_templates().create.assert_called_with(
1877 body=JsonDiffMatcher(self.expect_template), ensure_unique_name=True)
1879 self.assertEqual(exited, 0)
1882 def test_inputs(self, stubs):
1883 exited = arvados_cwl.main(
1884 ["--api=jobs", "--create-template",
1885 "tests/wf/inputs_test.cwl", "tests/order/inputs_test_order.json"],
1886 stubs.capture_stdout, sys.stderr, api_client=stubs.api)
1888 expect_template = copy.deepcopy(self.expect_template)
1889 params = expect_template[
1890 "components"]["inputs_test.cwl"]["script_parameters"]
1891 params["fileInput"]["value"] = '169f39d466a5438ac4a90e779bf750c7+53/blorp.txt'
1892 params["cwl:tool"] = 'a2de777156fb700f1363b1f2e370adca+60/workflow.cwl#main'
1893 params["floatInput"]["value"] = 1.234
1894 params["boolInput"]["value"] = True
1896 stubs.api.pipeline_templates().create.assert_called_with(
1897 body=JsonDiffMatcher(expect_template), ensure_unique_name=True)
1898 self.assertEqual(exited, 0)