14075: Tweak ruamel.yaml verision range in setup.py
[arvados.git] / sdk / cwl / tests / test_container.py
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: Apache-2.0
4
5 import arvados_cwl
6 from arvados_cwl.arvdocker import arv_docker_clear_cache
7 import arvados.config
8 import logging
9 import mock
10 import unittest
11 import os
12 import functools
13 import cwltool.process
14 import cwltool.secrets
15 from schema_salad.ref_resolver import Loader
16 from schema_salad.sourceline import cmap
17
18 from .matcher import JsonDiffMatcher
19
20 if not os.getenv('ARVADOS_DEBUG'):
21     logging.getLogger('arvados.cwl-runner').setLevel(logging.WARN)
22     logging.getLogger('arvados.arv-run').setLevel(logging.WARN)
23
24
25 class CollectionMock(object):
26     def __init__(self, vwdmock, *args, **kwargs):
27         self.vwdmock = vwdmock
28         self.count = 0
29
30     def open(self, *args, **kwargs):
31         self.count += 1
32         return self.vwdmock.open(*args, **kwargs)
33
34     def copy(self, *args, **kwargs):
35         self.count += 1
36         self.vwdmock.copy(*args, **kwargs)
37
38     def save_new(self, *args, **kwargs):
39         pass
40
41     def __len__(self):
42         return self.count
43
44     def portable_data_hash(self):
45         if self.count == 0:
46             return arvados.config.EMPTY_BLOCK_LOCATOR
47         else:
48             return "99999999999999999999999999999996+99"
49
50
51 class TestContainer(unittest.TestCase):
52
53     # The test passes no builder.resources
54     # Hence the default resources will apply: {'cores': 1, 'ram': 1024, 'outdirSize': 1024, 'tmpdirSize': 1024}
55     @mock.patch("arvados.commands.keepdocker.list_images_in_arv")
56     def test_run(self, keepdocker):
57         for enable_reuse in (True, False):
58             arv_docker_clear_cache()
59
60             runner = mock.MagicMock()
61             runner.project_uuid = "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
62             runner.ignore_docker_for_reuse = False
63             runner.intermediate_output_ttl = 0
64             runner.secret_store = cwltool.secrets.SecretStore()
65
66             keepdocker.return_value = [("zzzzz-4zz18-zzzzzzzzzzzzzz3", "")]
67             runner.api.collections().get().execute.return_value = {
68                 "portable_data_hash": "99999999999999999999999999999993+99"}
69
70             document_loader, avsc_names, schema_metadata, metaschema_loader = cwltool.process.get_schema("v1.0")
71
72             tool = cmap({
73                 "inputs": [],
74                 "outputs": [],
75                 "baseCommand": "ls",
76                 "arguments": [{"valueFrom": "$(runtime.outdir)"}],
77                 "id": "#",
78                 "class": "CommandLineTool"
79             })
80             make_fs_access=functools.partial(arvados_cwl.CollectionFsAccess,
81                                          collection_cache=arvados_cwl.CollectionCache(runner.api, None, 0))
82             arvtool = arvados_cwl.ArvadosCommandTool(runner, tool, work_api="containers", avsc_names=avsc_names,
83                                                      basedir="", make_fs_access=make_fs_access, loader=Loader({}),
84                                                      metadata={"cwlVersion": "v1.0"})
85             arvtool.formatgraph = None
86             for j in arvtool.job({}, mock.MagicMock(), basedir="", name="test_run_"+str(enable_reuse),
87                                  make_fs_access=make_fs_access, tmpdir="/tmp"):
88                 j.run(enable_reuse=enable_reuse, priority=500)
89                 runner.api.container_requests().create.assert_called_with(
90                     body=JsonDiffMatcher({
91                         'environment': {
92                             'HOME': '/var/spool/cwl',
93                             'TMPDIR': '/tmp'
94                         },
95                         'name': 'test_run_'+str(enable_reuse),
96                         'runtime_constraints': {
97                             'vcpus': 1,
98                             'ram': 1073741824
99                         },
100                         'use_existing': enable_reuse,
101                         'priority': 500,
102                         'mounts': {
103                             '/tmp': {'kind': 'tmp',
104                                      "capacity": 1073741824
105                                  },
106                             '/var/spool/cwl': {'kind': 'tmp',
107                                                "capacity": 1073741824 }
108                         },
109                         'state': 'Committed',
110                         'owner_uuid': 'zzzzz-8i9sb-zzzzzzzzzzzzzzz',
111                         'output_path': '/var/spool/cwl',
112                         'output_ttl': 0,
113                         'container_image': 'arvados/jobs',
114                         'command': ['ls', '/var/spool/cwl'],
115                         'cwd': '/var/spool/cwl',
116                         'scheduling_parameters': {},
117                         'properties': {},
118                         'secret_mounts': {}
119                     }))
120
121     # The test passes some fields in builder.resources
122     # For the remaining fields, the defaults will apply: {'cores': 1, 'ram': 1024, 'outdirSize': 1024, 'tmpdirSize': 1024}
123     @mock.patch("arvados.commands.keepdocker.list_images_in_arv")
124     def test_resource_requirements(self, keepdocker):
125         arv_docker_clear_cache()
126         runner = mock.MagicMock()
127         runner.project_uuid = "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
128         runner.ignore_docker_for_reuse = False
129         runner.intermediate_output_ttl = 3600
130         runner.secret_store = cwltool.secrets.SecretStore()
131
132         document_loader, avsc_names, schema_metadata, metaschema_loader = cwltool.process.get_schema("v1.0")
133
134         keepdocker.return_value = [("zzzzz-4zz18-zzzzzzzzzzzzzz3", "")]
135         runner.api.collections().get().execute.return_value = {
136             "portable_data_hash": "99999999999999999999999999999993+99"}
137
138         tool = cmap({
139             "inputs": [],
140             "outputs": [],
141             "hints": [{
142                 "class": "ResourceRequirement",
143                 "coresMin": 3,
144                 "ramMin": 3000,
145                 "tmpdirMin": 4000,
146                 "outdirMin": 5000
147             }, {
148                 "class": "http://arvados.org/cwl#RuntimeConstraints",
149                 "keep_cache": 512
150             }, {
151                 "class": "http://arvados.org/cwl#APIRequirement",
152             }, {
153                 "class": "http://arvados.org/cwl#PartitionRequirement",
154                 "partition": "blurb"
155             }, {
156                 "class": "http://arvados.org/cwl#IntermediateOutput",
157                 "outputTTL": 7200
158             }, {
159                 "class": "http://arvados.org/cwl#ReuseRequirement",
160                 "enableReuse": False
161             }],
162             "baseCommand": "ls",
163             "id": "#",
164             "class": "CommandLineTool"
165         })
166         make_fs_access=functools.partial(arvados_cwl.CollectionFsAccess,
167                                          collection_cache=arvados_cwl.CollectionCache(runner.api, None, 0))
168         arvtool = arvados_cwl.ArvadosCommandTool(runner, tool, work_api="containers",
169                                                  avsc_names=avsc_names, make_fs_access=make_fs_access,
170                                                  loader=Loader({}), metadata={"cwlVersion": "v1.0"})
171         arvtool.formatgraph = None
172         for j in arvtool.job({}, mock.MagicMock(), basedir="", name="test_resource_requirements",
173                              make_fs_access=make_fs_access, tmpdir="/tmp"):
174             j.run(enable_reuse=True, priority=500)
175
176         call_args, call_kwargs = runner.api.container_requests().create.call_args
177
178         call_body_expected = {
179             'environment': {
180                 'HOME': '/var/spool/cwl',
181                 'TMPDIR': '/tmp'
182             },
183             'name': 'test_resource_requirements',
184             'runtime_constraints': {
185                 'vcpus': 3,
186                 'ram': 3145728000,
187                 'keep_cache_ram': 536870912,
188                 'API': True
189             },
190             'use_existing': False,
191             'priority': 500,
192             'mounts': {
193                 '/tmp': {'kind': 'tmp',
194                          "capacity": 4194304000 },
195                 '/var/spool/cwl': {'kind': 'tmp',
196                                    "capacity": 5242880000 }
197             },
198             'state': 'Committed',
199             'owner_uuid': 'zzzzz-8i9sb-zzzzzzzzzzzzzzz',
200             'output_path': '/var/spool/cwl',
201             'output_ttl': 7200,
202             'container_image': 'arvados/jobs',
203             'command': ['ls'],
204             'cwd': '/var/spool/cwl',
205             'scheduling_parameters': {
206                 'partitions': ['blurb']
207             },
208             'properties': {},
209             'secret_mounts': {}
210         }
211
212         call_body = call_kwargs.get('body', None)
213         self.assertNotEqual(None, call_body)
214         for key in call_body:
215             self.assertEqual(call_body_expected.get(key), call_body.get(key))
216
217
218     # The test passes some fields in builder.resources
219     # For the remaining fields, the defaults will apply: {'cores': 1, 'ram': 1024, 'outdirSize': 1024, 'tmpdirSize': 1024}
220     @mock.patch("arvados.commands.keepdocker.list_images_in_arv")
221     @mock.patch("arvados.collection.Collection")
222     def test_initial_work_dir(self, collection_mock, keepdocker):
223         arv_docker_clear_cache()
224         runner = mock.MagicMock()
225         runner.project_uuid = "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
226         runner.ignore_docker_for_reuse = False
227         runner.intermediate_output_ttl = 0
228         runner.secret_store = cwltool.secrets.SecretStore()
229
230         document_loader, avsc_names, schema_metadata, metaschema_loader = cwltool.process.get_schema("v1.0")
231
232         keepdocker.return_value = [("zzzzz-4zz18-zzzzzzzzzzzzzz3", "")]
233         runner.api.collections().get().execute.return_value = {
234             "portable_data_hash": "99999999999999999999999999999993+99"}
235
236         sourcemock = mock.MagicMock()
237         def get_collection_mock(p):
238             if "/" in p:
239                 return (sourcemock, p.split("/", 1)[1])
240             else:
241                 return (sourcemock, "")
242         runner.fs_access.get_collection.side_effect = get_collection_mock
243
244         vwdmock = mock.MagicMock()
245         collection_mock.side_effect = lambda *args, **kwargs: CollectionMock(vwdmock, *args, **kwargs)
246
247         tool = cmap({
248             "inputs": [],
249             "outputs": [],
250             "hints": [{
251                 "class": "InitialWorkDirRequirement",
252                 "listing": [{
253                     "class": "File",
254                     "basename": "foo",
255                     "location": "keep:99999999999999999999999999999995+99/bar"
256                 },
257                 {
258                     "class": "Directory",
259                     "basename": "foo2",
260                     "location": "keep:99999999999999999999999999999995+99"
261                 },
262                 {
263                     "class": "File",
264                     "basename": "filename",
265                     "location": "keep:99999999999999999999999999999995+99/baz/filename"
266                 },
267                 {
268                     "class": "Directory",
269                     "basename": "subdir",
270                     "location": "keep:99999999999999999999999999999995+99/subdir"
271                 }                        ]
272             }],
273             "baseCommand": "ls",
274             "id": "#",
275             "class": "CommandLineTool"
276         })
277         make_fs_access=functools.partial(arvados_cwl.CollectionFsAccess,
278                                          collection_cache=arvados_cwl.CollectionCache(runner.api, None, 0))
279         arvtool = arvados_cwl.ArvadosCommandTool(runner, tool, work_api="containers",
280                                                  avsc_names=avsc_names, make_fs_access=make_fs_access,
281                                                  loader=Loader({}), metadata={"cwlVersion": "v1.0"})
282         arvtool.formatgraph = None
283         for j in arvtool.job({}, mock.MagicMock(), basedir="", name="test_initial_work_dir",
284                              make_fs_access=make_fs_access, tmpdir="/tmp"):
285             j.run(priority=500)
286
287         call_args, call_kwargs = runner.api.container_requests().create.call_args
288
289         vwdmock.copy.assert_has_calls([mock.call('bar', 'foo', source_collection=sourcemock)])
290         vwdmock.copy.assert_has_calls([mock.call('', 'foo2', source_collection=sourcemock)])
291         vwdmock.copy.assert_has_calls([mock.call('baz/filename', 'filename', source_collection=sourcemock)])
292         vwdmock.copy.assert_has_calls([mock.call('subdir', 'subdir', source_collection=sourcemock)])
293
294         call_body_expected = {
295             'environment': {
296                 'HOME': '/var/spool/cwl',
297                 'TMPDIR': '/tmp'
298             },
299             'name': 'test_initial_work_dir',
300             'runtime_constraints': {
301                 'vcpus': 1,
302                 'ram': 1073741824
303             },
304             'use_existing': True,
305             'priority': 500,
306             'mounts': {
307                 '/tmp': {'kind': 'tmp',
308                          "capacity": 1073741824 },
309                 '/var/spool/cwl': {'kind': 'tmp',
310                                    "capacity": 1073741824 },
311                 '/var/spool/cwl/foo': {
312                     'kind': 'collection',
313                     'path': 'foo',
314                     'portable_data_hash': '99999999999999999999999999999996+99'
315                 },
316                 '/var/spool/cwl/foo2': {
317                     'kind': 'collection',
318                     'path': 'foo2',
319                     'portable_data_hash': '99999999999999999999999999999996+99'
320                 },
321                 '/var/spool/cwl/filename': {
322                     'kind': 'collection',
323                     'path': 'filename',
324                     'portable_data_hash': '99999999999999999999999999999996+99'
325                 },
326                 '/var/spool/cwl/subdir': {
327                     'kind': 'collection',
328                     'path': 'subdir',
329                     'portable_data_hash': '99999999999999999999999999999996+99'
330                 }
331             },
332             'state': 'Committed',
333             'owner_uuid': 'zzzzz-8i9sb-zzzzzzzzzzzzzzz',
334             'output_path': '/var/spool/cwl',
335             'output_ttl': 0,
336             'container_image': 'arvados/jobs',
337             'command': ['ls'],
338             'cwd': '/var/spool/cwl',
339             'scheduling_parameters': {
340             },
341             'properties': {},
342             'secret_mounts': {}
343         }
344
345         call_body = call_kwargs.get('body', None)
346         self.assertNotEqual(None, call_body)
347         for key in call_body:
348             self.assertEqual(call_body_expected.get(key), call_body.get(key))
349
350
351     # Test redirecting stdin/stdout/stderr
352     @mock.patch("arvados.commands.keepdocker.list_images_in_arv")
353     def test_redirects(self, keepdocker):
354         arv_docker_clear_cache()
355
356         runner = mock.MagicMock()
357         runner.project_uuid = "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
358         runner.ignore_docker_for_reuse = False
359         runner.intermediate_output_ttl = 0
360         runner.secret_store = cwltool.secrets.SecretStore()
361
362         keepdocker.return_value = [("zzzzz-4zz18-zzzzzzzzzzzzzz3", "")]
363         runner.api.collections().get().execute.return_value = {
364             "portable_data_hash": "99999999999999999999999999999993+99"}
365
366         document_loader, avsc_names, schema_metadata, metaschema_loader = cwltool.process.get_schema("v1.0")
367
368         tool = cmap({
369             "inputs": [],
370             "outputs": [],
371             "baseCommand": "ls",
372             "stdout": "stdout.txt",
373             "stderr": "stderr.txt",
374             "stdin": "/keep/99999999999999999999999999999996+99/file.txt",
375             "arguments": [{"valueFrom": "$(runtime.outdir)"}],
376             "id": "#",
377             "class": "CommandLineTool"
378         })
379         make_fs_access=functools.partial(arvados_cwl.CollectionFsAccess,
380                                          collection_cache=arvados_cwl.CollectionCache(runner.api, None, 0))
381         arvtool = arvados_cwl.ArvadosCommandTool(runner, tool, work_api="containers", avsc_names=avsc_names,
382                                                  basedir="", make_fs_access=make_fs_access, loader=Loader({}),
383                                                  metadata={"cwlVersion": "v1.0"})
384         arvtool.formatgraph = None
385         for j in arvtool.job({}, mock.MagicMock(), basedir="", name="test_run_redirect",
386                              make_fs_access=make_fs_access, tmpdir="/tmp"):
387             j.run(priority=500)
388             runner.api.container_requests().create.assert_called_with(
389                 body=JsonDiffMatcher({
390                     'environment': {
391                         'HOME': '/var/spool/cwl',
392                         'TMPDIR': '/tmp'
393                     },
394                     'name': 'test_run_redirect',
395                     'runtime_constraints': {
396                         'vcpus': 1,
397                         'ram': 1073741824
398                     },
399                     'use_existing': True,
400                     'priority': 500,
401                     'mounts': {
402                         '/tmp': {'kind': 'tmp',
403                                  "capacity": 1073741824 },
404                         '/var/spool/cwl': {'kind': 'tmp',
405                                            "capacity": 1073741824 },
406                         "stderr": {
407                             "kind": "file",
408                             "path": "/var/spool/cwl/stderr.txt"
409                         },
410                         "stdin": {
411                             "kind": "collection",
412                             "path": "file.txt",
413                             "portable_data_hash": "99999999999999999999999999999996+99"
414                         },
415                         "stdout": {
416                             "kind": "file",
417                             "path": "/var/spool/cwl/stdout.txt"
418                         },
419                     },
420                     'state': 'Committed',
421                     'owner_uuid': 'zzzzz-8i9sb-zzzzzzzzzzzzzzz',
422                     'output_path': '/var/spool/cwl',
423                     'output_ttl': 0,
424                     'container_image': 'arvados/jobs',
425                     'command': ['ls', '/var/spool/cwl'],
426                     'cwd': '/var/spool/cwl',
427                     'scheduling_parameters': {},
428                     'properties': {},
429                     'secret_mounts': {}
430                 }))
431
432     @mock.patch("arvados.collection.Collection")
433     def test_done(self, col):
434         api = mock.MagicMock()
435
436         runner = mock.MagicMock()
437         runner.api = api
438         runner.project_uuid = "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
439         runner.num_retries = 0
440         runner.ignore_docker_for_reuse = False
441         runner.intermediate_output_ttl = 0
442         runner.secret_store = cwltool.secrets.SecretStore()
443
444         runner.api.containers().get().execute.return_value = {"state":"Complete",
445                                                               "output": "abc+123",
446                                                               "exit_code": 0}
447
448         col().open.return_value = []
449
450         arvjob = arvados_cwl.ArvadosContainer(runner)
451         arvjob.name = "testjob"
452         arvjob.builder = mock.MagicMock()
453         arvjob.output_callback = mock.MagicMock()
454         arvjob.collect_outputs = mock.MagicMock()
455         arvjob.successCodes = [0]
456         arvjob.outdir = "/var/spool/cwl"
457         arvjob.output_ttl = 3600
458
459         arvjob.collect_outputs.return_value = {"out": "stuff"}
460
461         arvjob.done({
462             "state": "Final",
463             "log_uuid": "zzzzz-4zz18-zzzzzzzzzzzzzz1",
464             "output_uuid": "zzzzz-4zz18-zzzzzzzzzzzzzz2",
465             "uuid": "zzzzz-xvhdp-zzzzzzzzzzzzzzz",
466             "container_uuid": "zzzzz-8i9sb-zzzzzzzzzzzzzzz",
467             "modified_at": "2017-05-26T12:01:22Z"
468         })
469
470         self.assertFalse(api.collections().create.called)
471
472         arvjob.collect_outputs.assert_called_with("keep:abc+123")
473         arvjob.output_callback.assert_called_with({"out": "stuff"}, "success")
474         runner.add_intermediate_output.assert_called_with("zzzzz-4zz18-zzzzzzzzzzzzzz2")
475
476     # The test passes no builder.resources
477     # Hence the default resources will apply: {'cores': 1, 'ram': 1024, 'outdirSize': 1024, 'tmpdirSize': 1024}
478     @mock.patch("arvados.commands.keepdocker.list_images_in_arv")
479     def test_mounts(self, keepdocker):
480         arv_docker_clear_cache()
481
482         runner = mock.MagicMock()
483         runner.project_uuid = "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
484         runner.ignore_docker_for_reuse = False
485         runner.intermediate_output_ttl = 0
486         runner.secret_store = cwltool.secrets.SecretStore()
487
488         keepdocker.return_value = [("zzzzz-4zz18-zzzzzzzzzzzzzz3", "")]
489         runner.api.collections().get().execute.return_value = {
490             "portable_data_hash": "99999999999999999999999999999993+99"}
491
492         document_loader, avsc_names, schema_metadata, metaschema_loader = cwltool.process.get_schema("v1.0")
493
494         tool = cmap({
495             "inputs": [
496                 {"id": "p1",
497                  "type": "Directory"}
498             ],
499             "outputs": [],
500             "baseCommand": "ls",
501             "arguments": [{"valueFrom": "$(runtime.outdir)"}],
502             "id": "#",
503             "class": "CommandLineTool"
504         })
505         make_fs_access=functools.partial(arvados_cwl.CollectionFsAccess,
506                                      collection_cache=arvados_cwl.CollectionCache(runner.api, None, 0))
507         arvtool = arvados_cwl.ArvadosCommandTool(runner, tool, work_api="containers", avsc_names=avsc_names,
508                                                  basedir="", make_fs_access=make_fs_access, loader=Loader({}),
509                                                  metadata={"cwlVersion": "v1.0"})
510         arvtool.formatgraph = None
511         job_order = {
512             "p1": {
513                 "class": "Directory",
514                 "location": "keep:99999999999999999999999999999994+44",
515                 "listing": [
516                     {
517                         "class": "File",
518                         "location": "keep:99999999999999999999999999999994+44/file1",
519                     },
520                     {
521                         "class": "File",
522                         "location": "keep:99999999999999999999999999999994+44/file2",
523                     }
524                 ]
525             }
526         }
527         for j in arvtool.job(job_order, mock.MagicMock(), basedir="", name="test_run_mounts",
528                              make_fs_access=make_fs_access, tmpdir="/tmp"):
529             j.run(priority=500)
530             runner.api.container_requests().create.assert_called_with(
531                 body=JsonDiffMatcher({
532                     'environment': {
533                         'HOME': '/var/spool/cwl',
534                         'TMPDIR': '/tmp'
535                     },
536                     'name': 'test_run_mounts',
537                     'runtime_constraints': {
538                         'vcpus': 1,
539                         'ram': 1073741824
540                     },
541                     'use_existing': True,
542                     'priority': 500,
543                     'mounts': {
544                         "/keep/99999999999999999999999999999994+44": {
545                             "kind": "collection",
546                             "portable_data_hash": "99999999999999999999999999999994+44"
547                         },
548                         '/tmp': {'kind': 'tmp',
549                                  "capacity": 1073741824 },
550                         '/var/spool/cwl': {'kind': 'tmp',
551                                            "capacity": 1073741824 }
552                     },
553                     'state': 'Committed',
554                     'owner_uuid': 'zzzzz-8i9sb-zzzzzzzzzzzzzzz',
555                     'output_path': '/var/spool/cwl',
556                     'output_ttl': 0,
557                     'container_image': 'arvados/jobs',
558                     'command': ['ls', '/var/spool/cwl'],
559                     'cwd': '/var/spool/cwl',
560                     'scheduling_parameters': {},
561                     'properties': {},
562                     'secret_mounts': {}
563                 }))
564
565     # The test passes no builder.resources
566     # Hence the default resources will apply: {'cores': 1, 'ram': 1024, 'outdirSize': 1024, 'tmpdirSize': 1024}
567     @mock.patch("arvados.commands.keepdocker.list_images_in_arv")
568     def test_secrets(self, keepdocker):
569         arv_docker_clear_cache()
570
571         runner = mock.MagicMock()
572         runner.project_uuid = "zzzzz-8i9sb-zzzzzzzzzzzzzzz"
573         runner.ignore_docker_for_reuse = False
574         runner.intermediate_output_ttl = 0
575         runner.secret_store = cwltool.secrets.SecretStore()
576
577         keepdocker.return_value = [("zzzzz-4zz18-zzzzzzzzzzzzzz3", "")]
578         runner.api.collections().get().execute.return_value = {
579             "portable_data_hash": "99999999999999999999999999999993+99"}
580
581         document_loader, avsc_names, schema_metadata, metaschema_loader = cwltool.process.get_schema("v1.0")
582
583         tool = cmap({"arguments": ["md5sum", "example.conf"],
584                      "class": "CommandLineTool",
585                      "hints": [
586                          {
587                              "class": "http://commonwl.org/cwltool#Secrets",
588                              "secrets": [
589                                  "#secret_job.cwl/pw"
590                              ]
591                          }
592                      ],
593                      "id": "#secret_job.cwl",
594                      "inputs": [
595                          {
596                              "id": "#secret_job.cwl/pw",
597                              "type": "string"
598                          }
599                      ],
600                      "outputs": [
601                      ],
602                      "requirements": [
603                          {
604                              "class": "InitialWorkDirRequirement",
605                              "listing": [
606                                  {
607                                      "entry": "username: user\npassword: $(inputs.pw)\n",
608                                      "entryname": "example.conf"
609                                  }
610                              ]
611                          }
612                      ]})
613         make_fs_access=functools.partial(arvados_cwl.CollectionFsAccess,
614                                      collection_cache=arvados_cwl.CollectionCache(runner.api, None, 0))
615         arvtool = arvados_cwl.ArvadosCommandTool(runner, tool, work_api="containers", avsc_names=avsc_names,
616                                                  basedir="", make_fs_access=make_fs_access, loader=Loader({}),
617                                                  metadata={"cwlVersion": "v1.0"})
618         arvtool.formatgraph = None
619
620         job_order = {"pw": "blorp"}
621         runner.secret_store.store(["pw"], job_order)
622
623         for j in arvtool.job(job_order, mock.MagicMock(), basedir="", name="test_secrets",
624                              make_fs_access=make_fs_access, tmpdir="/tmp"):
625             j.run(enable_reuse=True, priority=500)
626             runner.api.container_requests().create.assert_called_with(
627                 body=JsonDiffMatcher({
628                     'environment': {
629                         'HOME': '/var/spool/cwl',
630                         'TMPDIR': '/tmp'
631                     },
632                     'name': 'test_secrets',
633                     'runtime_constraints': {
634                         'vcpus': 1,
635                         'ram': 1073741824
636                     },
637                     'use_existing': True,
638                     'priority': 500,
639                     'mounts': {
640                         '/tmp': {'kind': 'tmp',
641                                  "capacity": 1073741824
642                              },
643                         '/var/spool/cwl': {'kind': 'tmp',
644                                            "capacity": 1073741824 }
645                     },
646                     'state': 'Committed',
647                     'owner_uuid': 'zzzzz-8i9sb-zzzzzzzzzzzzzzz',
648                     'output_path': '/var/spool/cwl',
649                     'output_ttl': 0,
650                     'container_image': 'arvados/jobs',
651                     'command': ['md5sum', 'example.conf'],
652                     'cwd': '/var/spool/cwl',
653                     'scheduling_parameters': {},
654                     'properties': {},
655                     "secret_mounts": {
656                         "/var/spool/cwl/example.conf": {
657                             "content": "username: user\npassword: blorp\n",
658                             "kind": "text"
659                         }
660                     }
661                 }))