Merge branch '8128-crunch2-auth-api'
[arvados.git] / services / api / test / unit / container_test.rb
1 require 'test_helper'
2
3 class ContainerTest < ActiveSupport::TestCase
4   include DbCurrentTime
5
6   DEFAULT_ATTRS = {
7     command: ['echo', 'foo'],
8     container_image: 'img',
9     output_path: '/tmp',
10     priority: 1,
11   }
12
13   def minimal_new attrs={}
14     cr = ContainerRequest.new DEFAULT_ATTRS.merge(attrs)
15     act_as_user users(:active) do
16       cr.save!
17     end
18     c = Container.new DEFAULT_ATTRS.merge(attrs)
19     act_as_system_user do
20       c.save!
21       assert cr.update_attributes(container_uuid: c.uuid,
22                                   state: ContainerRequest::Committed,
23                                   ), show_errors(cr)
24     end
25     return c, cr
26   end
27
28   def check_illegal_updates c, bad_updates
29     bad_updates.each do |u|
30       refute c.update_attributes(u), u.inspect
31       refute c.valid?, u.inspect
32       c.reload
33     end
34   end
35
36   def check_illegal_modify c
37     check_illegal_updates c, [{command: ["echo", "bar"]},
38                               {container_image: "img2"},
39                               {cwd: "/tmp2"},
40                               {environment: {"FOO" => "BAR"}},
41                               {mounts: {"FOO" => "BAR"}},
42                               {output_path: "/tmp3"},
43                               {locked_by_uuid: "zzzzz-gj3su-027z32aux8dg2s1"},
44                               {auth_uuid: "zzzzz-gj3su-017z32aux8dg2s1"},
45                               {runtime_constraints: {"FOO" => "BAR"}}]
46   end
47
48   def check_bogus_states c
49     check_illegal_updates c, [{state: nil},
50                               {state: "Flubber"}]
51   end
52
53   def check_no_change_from_cancelled c
54     check_illegal_modify c
55     check_bogus_states c
56     check_illegal_updates c, [{ priority: 3 },
57                               { state: Container::Queued },
58                               { state: Container::Locked },
59                               { state: Container::Running },
60                               { state: Container::Complete }]
61   end
62
63   test "Container create" do
64     act_as_system_user do
65       c, _ = minimal_new(environment: {},
66                       mounts: {"BAR" => "FOO"},
67                       output_path: "/tmp",
68                       priority: 1,
69                       runtime_constraints: {})
70
71       check_illegal_modify c
72       check_bogus_states c
73
74       c.reload
75       c.priority = 2
76       c.save!
77     end
78   end
79
80   test "Container running" do
81     c, _ = minimal_new priority: 1
82
83     set_user_from_auth :dispatch1
84     check_illegal_updates c, [{state: Container::Running},
85                               {state: Container::Complete}]
86
87     c.update_attributes! state: Container::Locked
88     c.update_attributes! state: Container::Running
89
90     check_illegal_modify c
91     check_bogus_states c
92
93     check_illegal_updates c, [{state: Container::Queued}]
94     c.reload
95
96     c.update_attributes! priority: 3
97   end
98
99   test "Lock and unlock" do
100     c, cr = minimal_new priority: 0
101
102     set_user_from_auth :dispatch1
103     assert_equal Container::Queued, c.state
104
105     refute c.update_attributes(state: Container::Locked), "no priority"
106     c.reload
107     assert cr.update_attributes priority: 1
108
109     refute c.update_attributes(state: Container::Running), "not locked"
110     c.reload
111     refute c.update_attributes(state: Container::Complete), "not locked"
112     c.reload
113
114     assert c.update_attributes(state: Container::Locked), show_errors(c)
115     assert c.locked_by_uuid
116     assert c.auth_uuid
117
118     assert c.update_attributes(state: Container::Queued), show_errors(c)
119     refute c.locked_by_uuid
120     refute c.auth_uuid
121
122     refute c.update_attributes(state: Container::Running), "not locked"
123     c.reload
124     refute c.locked_by_uuid
125     refute c.auth_uuid
126
127     assert c.update_attributes(state: Container::Locked), show_errors(c)
128     assert c.update_attributes(state: Container::Running), show_errors(c)
129     assert c.locked_by_uuid
130     assert c.auth_uuid
131
132     auth_uuid_was = c.auth_uuid
133
134     refute c.update_attributes(state: Container::Locked), "already running"
135     c.reload
136     refute c.update_attributes(state: Container::Queued), "already running"
137     c.reload
138
139     assert c.update_attributes(state: Container::Complete), show_errors(c)
140     refute c.locked_by_uuid
141     refute c.auth_uuid
142
143     auth_exp = ApiClientAuthorization.find_by_uuid(auth_uuid_was).expires_at
144     assert_operator auth_exp, :<, db_current_time
145   end
146
147   test "Container queued cancel" do
148     c, _ = minimal_new
149     set_user_from_auth :dispatch1
150     assert c.update_attributes(state: Container::Cancelled), show_errors(c)
151     check_no_change_from_cancelled c
152   end
153
154   test "Container locked cancel" do
155     c, _ = minimal_new
156     set_user_from_auth :dispatch1
157     assert c.update_attributes(state: Container::Locked), show_errors(c)
158     assert c.update_attributes(state: Container::Cancelled), show_errors(c)
159     check_no_change_from_cancelled c
160   end
161
162   test "Container running cancel" do
163     c, _ = minimal_new
164     set_user_from_auth :dispatch1
165     c.update_attributes! state: Container::Queued
166     c.update_attributes! state: Container::Locked
167     c.update_attributes! state: Container::Running
168     c.update_attributes! state: Container::Cancelled
169     check_no_change_from_cancelled c
170   end
171
172   test "Container create forbidden for non-admin" do
173     set_user_from_auth :active_trustedclient
174     c = Container.new DEFAULT_ATTRS
175     c.environment = {}
176     c.mounts = {"BAR" => "FOO"}
177     c.output_path = "/tmp"
178     c.priority = 1
179     c.runtime_constraints = {}
180     assert_raises(ArvadosModel::PermissionDeniedError) do
181       c.save!
182     end
183   end
184
185   test "Container only set exit code on complete" do
186     c, _ = minimal_new
187     set_user_from_auth :dispatch1
188     c.update_attributes! state: Container::Locked
189     c.update_attributes! state: Container::Running
190
191     check_illegal_updates c, [{exit_code: 1},
192                               {exit_code: 1, state: Container::Cancelled}]
193
194     assert c.update_attributes(exit_code: 1, state: Container::Complete)
195   end
196 end