1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: AGPL-3.0
6 require 'helpers/container_test_helper'
7 require 'helpers/docker_migration_helper'
9 class ContainerRequestTest < ActiveSupport::TestCase
10 include DockerMigrationHelper
12 include ContainerTestHelper
14 def create_minimal_req! attrs={}
16 command: ["echo", "foo"],
17 container_image: links(:docker_image_collection_tag).name,
20 mounts: {"/out" => {"kind" => "tmp", "capacity" => 1000000}},
22 runtime_constraints: {"vcpus" => 1, "ram" => 2},
26 cr = ContainerRequest.create!(defaults.merge(attrs))
31 def check_bogus_states cr
32 [nil, "Flubber"].each do |state|
33 assert_raises(ActiveRecord::RecordInvalid) do
41 test "Container request create" do
42 set_user_from_auth :active
43 cr = create_minimal_req!
45 assert_nil cr.container_uuid
46 assert_equal 0, cr.priority
50 # Ensure we can modify all attributes
51 cr.command = ["echo", "foo3"]
52 cr.container_image = "img3"
54 cr.environment = {"BUP" => "BOP"}
55 cr.mounts = {"BAR" => "BAZ"}
56 cr.output_path = "/tmp4"
58 cr.runtime_constraints = {"vcpus" => 4}
60 cr.description = "bar3"
63 assert_nil cr.container_uuid
68 {"vcpus" => 1, "ram" => nil},
69 {"vcpus" => 0, "ram" => 123},
70 {"vcpus" => "1", "ram" => "123"}
71 ].each do |invalid_constraints|
72 test "Create with #{invalid_constraints}" do
73 set_user_from_auth :active
74 assert_raises(ActiveRecord::RecordInvalid) do
75 cr = create_minimal_req!(state: "Committed",
77 runtime_constraints: invalid_constraints)
82 test "Update with #{invalid_constraints}" do
83 set_user_from_auth :active
84 cr = create_minimal_req!(state: "Uncommitted", priority: 1)
86 assert_raises(ActiveRecord::RecordInvalid) do
87 cr = ContainerRequest.find_by_uuid cr.uuid
88 cr.update_attributes!(state: "Committed",
89 runtime_constraints: invalid_constraints)
94 test "Update from fixture" do
95 set_user_from_auth :active
96 cr = ContainerRequest.find_by_uuid(container_requests(:running).uuid)
97 cr.update_attributes!(description: "New description")
98 assert_equal "New description", cr.description
101 test "Update with valid runtime constraints" do
102 set_user_from_auth :active
103 cr = create_minimal_req!(state: "Uncommitted", priority: 1)
105 cr = ContainerRequest.find_by_uuid cr.uuid
106 cr.update_attributes!(state: "Committed",
107 runtime_constraints: {"vcpus" => 1, "ram" => 23})
108 assert_not_nil cr.container_uuid
111 test "Container request priority must be non-nil" do
112 set_user_from_auth :active
113 cr = create_minimal_req!
115 cr.state = "Committed"
116 assert_raises(ActiveRecord::RecordInvalid) do
121 test "Container request commit" do
122 set_user_from_auth :active
123 cr = create_minimal_req!(runtime_constraints: {"vcpus" => 2, "ram" => 30})
125 assert_nil cr.container_uuid
128 cr.state = "Committed"
134 assert_equal({"vcpus" => 2, "ram" => 30}, cr.runtime_constraints)
136 assert_not_nil cr.container_uuid
137 c = Container.find_by_uuid cr.container_uuid
139 assert_equal ["echo", "foo"], c.command
140 assert_equal collections(:docker_image).portable_data_hash, c.container_image
141 assert_equal "/tmp", c.cwd
142 assert_equal({}, c.environment)
143 assert_equal({"/out" => {"kind"=>"tmp", "capacity"=>1000000}}, c.mounts)
144 assert_equal "/out", c.output_path
145 assert_equal({"keep_cache_ram"=>268435456, "vcpus" => 2, "ram" => 30}, c.runtime_constraints)
146 assert_equal 1, c.priority
148 assert_raises(ActiveRecord::RecordInvalid) do
158 assert_equal 0, cr.priority
159 assert_equal 0, c.priority
163 test "Container request max priority" do
164 set_user_from_auth :active
165 cr = create_minimal_req!(priority: 5, state: "Committed")
167 c = Container.find_by_uuid cr.container_uuid
168 assert_equal 5, c.priority
170 cr2 = create_minimal_req!
172 cr2.state = "Committed"
173 cr2.container_uuid = cr.container_uuid
174 act_as_system_user do
178 # cr and cr2 have priority 5 and 10, and are being satisfied by
179 # the same container c, so c's priority should be
182 assert_equal 10, c.priority
184 cr2.update_attributes!(priority: 0)
187 assert_equal 5, c.priority
189 cr.update_attributes!(priority: 0)
192 assert_equal 0, c.priority
196 test "Independent container requests" do
197 set_user_from_auth :active
198 cr1 = create_minimal_req!(command: ["foo", "1"], priority: 5, state: "Committed")
199 cr2 = create_minimal_req!(command: ["foo", "2"], priority: 10, state: "Committed")
201 c1 = Container.find_by_uuid cr1.container_uuid
202 assert_equal 5, c1.priority
204 c2 = Container.find_by_uuid cr2.container_uuid
205 assert_equal 10, c2.priority
207 cr1.update_attributes!(priority: 0)
210 assert_equal 0, c1.priority
213 assert_equal 10, c2.priority
216 test "Request is finalized when its container is cancelled" do
217 set_user_from_auth :active
218 cr = create_minimal_req!(priority: 1, state: "Committed", container_count_max: 1)
220 act_as_system_user do
221 Container.find_by_uuid(cr.container_uuid).
222 update_attributes!(state: Container::Cancelled)
226 assert_equal "Final", cr.state
229 test "Request is finalized when its container is completed" do
230 set_user_from_auth :active
231 project = groups(:private)
232 cr = create_minimal_req!(owner_uuid: project.uuid,
236 c = act_as_system_user do
237 c = Container.find_by_uuid(cr.container_uuid)
238 c.update_attributes!(state: Container::Locked)
239 c.update_attributes!(state: Container::Running)
244 assert_equal "Committed", cr.state
246 output_pdh = '1f4b0bc7583c2a7f9102c395f4ffc5e3+45'
247 log_pdh = 'fa7aeb5140e2848d39b416daeef4ffc5+45'
248 act_as_system_user do
249 c.update_attributes!(state: Container::Complete,
255 assert_equal "Final", cr.state
256 ['output', 'log'].each do |out_type|
257 pdh = Container.find_by_uuid(cr.container_uuid).send(out_type)
258 assert_equal(1, Collection.where(portable_data_hash: pdh,
259 owner_uuid: project.uuid).count,
260 "Container #{out_type} should be copied to #{project.uuid}")
262 assert_not_nil cr.output_uuid
263 assert_not_nil cr.log_uuid
264 output = Collection.find_by_uuid cr.output_uuid
265 assert_equal output_pdh, output.portable_data_hash
266 log = Collection.find_by_uuid cr.log_uuid
267 assert_equal log_pdh, log.portable_data_hash
270 test "Container makes container request, then is cancelled" do
271 set_user_from_auth :active
272 cr = create_minimal_req!(priority: 5, state: "Committed", container_count_max: 1)
274 c = Container.find_by_uuid cr.container_uuid
275 assert_equal 5, c.priority
277 cr2 = create_minimal_req!
278 cr2.update_attributes!(priority: 10, state: "Committed", requesting_container_uuid: c.uuid, command: ["echo", "foo2"], container_count_max: 1)
281 c2 = Container.find_by_uuid cr2.container_uuid
282 assert_equal 10, c2.priority
284 act_as_system_user do
285 c.state = "Cancelled"
290 assert_equal "Final", cr.state
293 assert_equal 0, cr2.priority
296 assert_equal 0, c2.priority
300 test "Container makes container request, then changes priority" do
301 set_user_from_auth :active
302 cr = create_minimal_req!(priority: 5, state: "Committed", container_count_max: 1)
304 c = Container.find_by_uuid cr.container_uuid
305 assert_equal 5, c.priority
307 cr2 = create_minimal_req!
308 cr2.update_attributes!(priority: 5, state: "Committed", requesting_container_uuid: c.uuid, command: ["echo", "foo2"], container_count_max: 1)
311 c2 = Container.find_by_uuid cr2.container_uuid
312 assert_equal 5, c2.priority
314 act_as_system_user do
322 assert_equal 10, cr2.priority
325 assert_equal 10, c2.priority
329 ['running_container_auth', 'zzzzz-dz642-runningcontainr', 12],
330 ['active_no_prefs', nil, 0],
331 ].each do |token, expected, expected_priority|
332 test "create as #{token} and expect requesting_container_uuid to be #{expected}" do
333 set_user_from_auth token
334 cr = ContainerRequest.create(container_image: "img", output_path: "/tmp", command: ["echo", "foo"])
335 assert_not_nil cr.uuid, 'uuid should be set for newly created container_request'
336 assert_equal expected, cr.requesting_container_uuid
337 assert_equal expected_priority, cr.priority
341 [[{"vcpus" => [2, nil]},
342 lambda { |resolved| resolved["vcpus"] == 2 }],
343 [{"vcpus" => [3, 7]},
344 lambda { |resolved| resolved["vcpus"] == 3 }],
346 lambda { |resolved| resolved["vcpus"] == 4 }],
347 [{"ram" => [1000000000, 2000000000]},
348 lambda { |resolved| resolved["ram"] == 1000000000 }],
349 [{"ram" => [1234234234]},
350 lambda { |resolved| resolved["ram"] == 1234234234 }],
351 ].each do |rc, okfunc|
352 test "resolve runtime constraint range #{rc} to values" do
353 resolved = Container.resolve_runtime_constraints(rc)
354 assert(okfunc.call(resolved),
355 "container runtime_constraints was #{resolved.inspect}")
360 "kind" => "collection",
361 "uuid" => "zzzzz-4zz18-znfnqtbbv4spc3w",
364 resolved["/out"] == {
365 "portable_data_hash" => "1f4b0bc7583c2a7f9102c395f4ffc5e3+45",
366 "kind" => "collection",
371 "kind" => "collection",
372 "uuid" => "zzzzz-4zz18-znfnqtbbv4spc3w",
373 "portable_data_hash" => "1f4b0bc7583c2a7f9102c395f4ffc5e3+45",
376 resolved["/out"] == {
377 "portable_data_hash" => "1f4b0bc7583c2a7f9102c395f4ffc5e3+45",
378 "kind" => "collection",
382 ].each do |mounts, okfunc|
383 test "resolve mounts #{mounts.inspect} to values" do
384 set_user_from_auth :active
385 resolved = Container.resolve_mounts(mounts)
386 assert(okfunc.call(resolved),
387 "Container.resolve_mounts returned #{resolved.inspect}")
391 test 'mount unreadable collection' do
392 set_user_from_auth :spectator
395 "kind" => "collection",
396 "uuid" => "zzzzz-4zz18-znfnqtbbv4spc3w",
400 assert_raises(ArvadosModel::UnresolvableContainerError) do
401 Container.resolve_mounts(m)
405 test 'mount collection with mismatched UUID and PDH' do
406 set_user_from_auth :active
409 "kind" => "collection",
410 "uuid" => "zzzzz-4zz18-znfnqtbbv4spc3w",
411 "portable_data_hash" => "fa7aeb5140e2848d39b416daeef4ffc5+45",
415 assert_raises(ArgumentError) do
416 Container.resolve_mounts(m)
420 ['arvados/apitestfixture:latest',
421 'arvados/apitestfixture',
422 'd8309758b8fe2c81034ffc8a10c36460b77db7bc5e7b448c4e5b684f9d95a678',
424 test "Container.resolve_container_image(#{tag.inspect})" do
425 set_user_from_auth :active
426 resolved = Container.resolve_container_image(tag)
427 assert_equal resolved, collections(:docker_image).portable_data_hash
431 test "Container.resolve_container_image(pdh)" do
432 set_user_from_auth :active
433 [[:docker_image, 'v1'], [:docker_image_1_12, 'v2']].each do |coll, ver|
434 Rails.configuration.docker_image_formats = [ver]
435 pdh = collections(coll).portable_data_hash
436 resolved = Container.resolve_container_image(pdh)
437 assert_equal resolved, pdh
441 ['acbd18db4cc2f85cedef654fccc4a4d8+3',
443 'arvados/apitestfixture:ENOEXIST',
445 test "container_image_for_container(#{img.inspect}) => 422" do
446 set_user_from_auth :active
447 assert_raises(ArvadosModel::UnresolvableContainerError) do
448 Container.resolve_container_image(img)
453 test "migrated docker image" do
454 Rails.configuration.docker_image_formats = ['v2']
455 add_docker19_migration_link
457 # Test that it returns only v2 images even though request is for v1 image.
459 set_user_from_auth :active
460 cr = create_minimal_req!(command: ["true", "1"],
461 container_image: collections(:docker_image).portable_data_hash)
462 assert_equal(Container.resolve_container_image(cr.container_image),
463 collections(:docker_image_1_12).portable_data_hash)
465 cr = create_minimal_req!(command: ["true", "2"],
466 container_image: links(:docker_image_collection_tag).name)
467 assert_equal(Container.resolve_container_image(cr.container_image),
468 collections(:docker_image_1_12).portable_data_hash)
471 test "use unmigrated docker image" do
472 Rails.configuration.docker_image_formats = ['v1']
473 add_docker19_migration_link
475 # Test that it returns only supported v1 images even though there is a
478 set_user_from_auth :active
479 cr = create_minimal_req!(command: ["true", "1"],
480 container_image: collections(:docker_image).portable_data_hash)
481 assert_equal(Container.resolve_container_image(cr.container_image),
482 collections(:docker_image).portable_data_hash)
484 cr = create_minimal_req!(command: ["true", "2"],
485 container_image: links(:docker_image_collection_tag).name)
486 assert_equal(Container.resolve_container_image(cr.container_image),
487 collections(:docker_image).portable_data_hash)
490 test "incompatible docker image v1" do
491 Rails.configuration.docker_image_formats = ['v1']
492 add_docker19_migration_link
494 # Don't return unsupported v2 image even if we ask for it directly.
495 set_user_from_auth :active
496 cr = create_minimal_req!(command: ["true", "1"],
497 container_image: collections(:docker_image_1_12).portable_data_hash)
498 assert_raises(ArvadosModel::UnresolvableContainerError) do
499 Container.resolve_container_image(cr.container_image)
503 test "incompatible docker image v2" do
504 Rails.configuration.docker_image_formats = ['v2']
505 # No migration link, don't return unsupported v1 image,
507 set_user_from_auth :active
508 cr = create_minimal_req!(command: ["true", "1"],
509 container_image: collections(:docker_image).portable_data_hash)
510 assert_raises(ArvadosModel::UnresolvableContainerError) do
511 Container.resolve_container_image(cr.container_image)
513 cr = create_minimal_req!(command: ["true", "2"],
514 container_image: links(:docker_image_collection_tag).name)
515 assert_raises(ArvadosModel::UnresolvableContainerError) do
516 Container.resolve_container_image(cr.container_image)
520 test "requestor can retrieve container owned by dispatch" do
521 assert_not_empty Container.readable_by(users(:admin)).where(uuid: containers(:running).uuid)
522 assert_not_empty Container.readable_by(users(:active)).where(uuid: containers(:running).uuid)
523 assert_empty Container.readable_by(users(:spectator)).where(uuid: containers(:running).uuid)
527 [{"var" => "value1"}, {"var" => "value1"}, nil],
528 [{"var" => "value1"}, {"var" => "value1"}, true],
529 [{"var" => "value1"}, {"var" => "value1"}, false],
530 [{"var" => "value1"}, {"var" => "value2"}, nil],
531 ].each do |env1, env2, use_existing|
532 test "Container request #{((env1 == env2) and (use_existing.nil? or use_existing == true)) ? 'does' : 'does not'} reuse container when committed#{use_existing.nil? ? '' : use_existing ? ' and use_existing == true' : ' and use_existing == false'}" do
533 common_attrs = {cwd: "test",
535 command: ["echo", "hello"],
537 runtime_constraints: {"vcpus" => 4,
538 "ram" => 12000000000},
539 mounts: {"test" => {"kind" => "json"}}}
540 set_user_from_auth :active
541 cr1 = create_minimal_req!(common_attrs.merge({state: ContainerRequest::Committed,
544 # Testing with use_existing default value
545 cr2 = create_minimal_req!(common_attrs.merge({state: ContainerRequest::Uncommitted,
549 cr2 = create_minimal_req!(common_attrs.merge({state: ContainerRequest::Uncommitted,
551 use_existing: use_existing}))
553 assert_not_nil cr1.container_uuid
554 assert_nil cr2.container_uuid
556 # Update cr2 to commited state and check for container equality on different cases:
557 # * When env1 and env2 are equal and use_existing is true, the same container
558 # should be assigned.
559 # * When use_existing is false, a different container should be assigned.
560 # * When env1 and env2 are different, a different container should be assigned.
561 cr2.update_attributes!({state: ContainerRequest::Committed})
562 assert_equal (cr2.use_existing == true and (env1 == env2)),
563 (cr1.container_uuid == cr2.container_uuid)
567 test "requesting_container_uuid at create is not allowed" do
568 set_user_from_auth :active
569 assert_raises(ActiveRecord::RecordNotSaved) do
570 create_minimal_req!(state: "Uncommitted", priority: 1, requesting_container_uuid: 'youcantdothat')
574 test "Retry on container cancelled" do
575 set_user_from_auth :active
576 cr = create_minimal_req!(priority: 1, state: "Committed", container_count_max: 2)
577 cr2 = create_minimal_req!(priority: 1, state: "Committed", container_count_max: 2, command: ["echo", "baz"])
578 prev_container_uuid = cr.container_uuid
580 c = act_as_system_user do
581 c = Container.find_by_uuid(cr.container_uuid)
582 c.update_attributes!(state: Container::Locked)
583 c.update_attributes!(state: Container::Running)
589 assert_equal "Committed", cr.state
590 assert_equal prev_container_uuid, cr.container_uuid
591 assert_not_equal cr2.container_uuid, cr.container_uuid
592 prev_container_uuid = cr.container_uuid
594 act_as_system_user do
595 c.update_attributes!(state: Container::Cancelled)
600 assert_equal "Committed", cr.state
601 assert_not_equal prev_container_uuid, cr.container_uuid
602 assert_not_equal cr2.container_uuid, cr.container_uuid
603 prev_container_uuid = cr.container_uuid
605 c = act_as_system_user do
606 c = Container.find_by_uuid(cr.container_uuid)
607 c.update_attributes!(state: Container::Cancelled)
613 assert_equal "Final", cr.state
614 assert_equal prev_container_uuid, cr.container_uuid
615 assert_not_equal cr2.container_uuid, cr.container_uuid
618 test "Output collection name setting using output_name with name collision resolution" do
619 set_user_from_auth :active
620 output_name = 'unimaginative name'
621 Collection.create!(name: output_name)
623 cr = create_minimal_req!(priority: 1,
624 state: ContainerRequest::Committed,
625 output_name: output_name)
628 assert_equal ContainerRequest::Final, cr.state
629 output_coll = Collection.find_by_uuid(cr.output_uuid)
630 # Make sure the resulting output collection name include the original name
632 assert_not_equal output_name, output_coll.name,
633 "more than one collection with the same owner and name"
634 assert output_coll.name.include?(output_name),
635 "New name should include original name"
636 assert_match /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z/, output_coll.name,
637 "New name should include ISO8601 date"
640 [[0, :check_output_ttl_0],
641 [1, :check_output_ttl_1s],
642 [365*86400, :check_output_ttl_1y],
643 ].each do |ttl, checker|
644 test "output_ttl=#{ttl}" do
645 act_as_user users(:active) do
646 cr = create_minimal_req!(priority: 1,
647 state: ContainerRequest::Committed,
652 output = Collection.find_by_uuid(cr.output_uuid)
653 send(checker, db_current_time, output.trash_at, output.delete_at)
658 def check_output_ttl_0(now, trash, delete)
663 def check_output_ttl_1s(now, trash, delete)
664 assert_not_nil(trash)
665 assert_not_nil(delete)
666 assert_in_delta(trash, now + 1.second, 10)
667 assert_in_delta(delete, now + Rails.configuration.blob_signature_ttl.second, 10)
670 def check_output_ttl_1y(now, trash, delete)
671 year = (86400*365).second
672 assert_not_nil(trash)
673 assert_not_nil(delete)
674 assert_in_delta(trash, now + year, 10)
675 assert_in_delta(delete, now + year, 10)
678 def run_container(cr)
679 act_as_system_user do
680 c = Container.find_by_uuid(cr.container_uuid)
681 c.update_attributes!(state: Container::Locked)
682 c.update_attributes!(state: Container::Running)
683 c.update_attributes!(state: Container::Complete,
685 output: '1f4b0bc7583c2a7f9102c395f4ffc5e3+45',
686 log: 'fa7aeb5140e2848d39b416daeef4ffc5+45')
691 test "Finalize committed request when reusing a finished container" do
692 set_user_from_auth :active
693 cr = create_minimal_req!(priority: 1, state: ContainerRequest::Committed)
695 assert_equal ContainerRequest::Committed, cr.state
698 assert_equal ContainerRequest::Final, cr.state
700 cr2 = create_minimal_req!(priority: 1, state: ContainerRequest::Committed)
701 assert_equal cr.container_uuid, cr2.container_uuid
702 assert_equal ContainerRequest::Final, cr2.state
704 cr3 = create_minimal_req!(priority: 1, state: ContainerRequest::Uncommitted)
705 assert_equal ContainerRequest::Uncommitted, cr3.state
706 cr3.update_attributes!(state: ContainerRequest::Committed)
707 assert_equal cr.container_uuid, cr3.container_uuid
708 assert_equal ContainerRequest::Final, cr3.state
712 [{"partitions" => ["fastcpu","vfastcpu", 100]}, ContainerRequest::Committed, ActiveRecord::RecordInvalid],
713 [{"partitions" => ["fastcpu","vfastcpu", 100]}, ContainerRequest::Uncommitted],
714 [{"partitions" => "fastcpu"}, ContainerRequest::Committed, ActiveRecord::RecordInvalid],
715 [{"partitions" => "fastcpu"}, ContainerRequest::Uncommitted],
716 [{"partitions" => ["fastcpu","vfastcpu"]}, ContainerRequest::Committed],
717 ].each do |sp, state, expected|
718 test "create container request with scheduling_parameters #{sp} in state #{state} and verify #{expected}" do
719 common_attrs = {cwd: "test",
721 command: ["echo", "hello"],
723 scheduling_parameters: sp,
724 mounts: {"test" => {"kind" => "json"}}}
725 set_user_from_auth :active
727 if expected == ActiveRecord::RecordInvalid
728 assert_raises(ActiveRecord::RecordInvalid) do
729 create_minimal_req!(common_attrs.merge({state: state}))
732 cr = create_minimal_req!(common_attrs.merge({state: state}))
733 assert_equal sp, cr.scheduling_parameters
735 if state == ContainerRequest::Committed
736 c = Container.find_by_uuid(cr.container_uuid)
737 assert_equal sp, c.scheduling_parameters
743 [['Committed', true, {name: "foobar", priority: 123}],
744 ['Committed', false, {container_count: 2}],
745 ['Committed', false, {container_count: 0}],
746 ['Committed', false, {container_count: nil}],
747 ['Final', false, {state: ContainerRequest::Committed, name: "foobar"}],
748 ['Final', false, {name: "foobar", priority: 123}],
749 ['Final', false, {name: "foobar", output_uuid: "zzzzz-4zz18-znfnqtbbv4spc3w"}],
750 ['Final', false, {name: "foobar", log_uuid: "zzzzz-4zz18-znfnqtbbv4spc3w"}],
751 ['Final', false, {log_uuid: "zzzzz-4zz18-znfnqtbbv4spc3w"}],
752 ['Final', false, {priority: 123}],
753 ['Final', false, {mounts: {}}],
754 ['Final', false, {container_count: 2}],
755 ['Final', true, {name: "foobar"}],
756 ['Final', true, {name: "foobar", description: "baz"}],
757 ].each do |state, permitted, updates|
758 test "state=#{state} can#{'not' if !permitted} update #{updates.inspect}" do
759 act_as_user users(:active) do
760 cr = create_minimal_req!(priority: 1,
762 container_count_max: 1)
767 act_as_system_user do
768 Container.find_by_uuid(cr.container_uuid).
769 update_attributes!(state: Container::Cancelled)
773 raise 'broken test case'
775 assert_equal state, cr.state
777 assert cr.update_attributes!(updates)
779 assert_raises(ActiveRecord::RecordInvalid) do
780 cr.update_attributes!(updates)
787 test "delete container_request and check its container's priority" do
788 act_as_user users(:active) do
789 cr = ContainerRequest.find_by_uuid container_requests(:running_to_be_deleted).uuid
791 # initially the cr's container has priority > 0
792 c = Container.find_by_uuid(cr.container_uuid)
793 assert_equal 1, c.priority
796 assert_nothing_raised {cr.destroy}
798 # the cr's container now has priority of 0
799 c = Container.find_by_uuid(cr.container_uuid)
800 assert_equal 0, c.priority
804 test "delete container_request in final state and expect no error due to before_destroy callback" do
805 act_as_user users(:active) do
806 cr = ContainerRequest.find_by_uuid container_requests(:completed).uuid
807 assert_nothing_raised {cr.destroy}
811 test "Container request valid priority" do
812 set_user_from_auth :active
813 cr = create_minimal_req!
815 assert_raises(ActiveRecord::RecordInvalid) do
835 assert_raises(ActiveRecord::RecordInvalid) do
841 test "reuse container with same secret_mounts" do
842 set_user_from_auth :active
843 cr1 = create_minimal_req!(state: "Committed", priority: 1)
845 cr2 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: {})
847 assert_not_nil cr1.container_uuid
848 assert_equal cr1.container_uuid, cr2.container_uuid
851 secrets = {"/foo" => {"kind" => "binary"}}
856 [true, secrets, secrets],
857 [false, nil, secrets],
858 [false, {}, secrets],
859 ].each do |expect_reuse, sm1, sm2|
860 test "container reuse secret_mounts #{sm1.inspect}, #{sm2.inspect}" do
861 set_user_from_auth :active
862 cr1 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: sm1)
863 cr2 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: sm2)
864 assert_not_nil cr1.container_uuid
865 assert_not_nil cr2.container_uuid
867 assert_equal cr1.container_uuid, cr2.container_uuid
869 assert_not_equal cr1.container_uuid, cr2.container_uuid
874 test "scrub secret_mounts but reuse container for request with identical secret_mounts" do
875 set_user_from_auth :active
876 sm = {'/secret/foo' => {'kind' => 'text', 'content' => secret_string}}
877 cr1 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: sm.dup)
881 # secret_mounts scrubbed from db
882 c = Container.where(uuid: cr1.container_uuid).first
883 assert_equal({}, c.secret_mounts)
884 assert_equal({}, cr1.secret_mounts)
886 # can reuse container if secret_mounts match
887 cr2 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: sm.dup)
888 assert_equal cr1.container_uuid, cr2.container_uuid
890 # don't reuse container if secret_mounts don't match
891 cr3 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: {})
892 assert_not_equal cr1.container_uuid, cr3.container_uuid
894 assert_no_secrets_logged
897 test "not reuse container with different secret_mounts" do
898 secrets = {"/foo" => {"kind" => "binary"}}
899 set_user_from_auth :active
900 cr1 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: secrets.dup)
902 cr2 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: secrets.dup)
904 assert_not_nil cr1.container_uuid
905 assert_equal cr1.container_uuid, cr2.container_uuid
908 test "conflicting key in mounts and secret_mounts" do
909 sm = {'/secret/foo' => {'kind' => 'text', 'content' => secret_string}}
910 set_user_from_auth :active
911 cr = create_minimal_req!
912 assert_equal false, cr.update_attributes(state: "Committed",
914 mounts: cr.mounts.merge(sm),
916 assert_equal [:secret_mounts], cr.errors.messages.keys