foreman_dlm 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +619 -0
  3. data/README.md +84 -0
  4. data/Rakefile +47 -0
  5. data/app/controllers/api/v2/dlmlocks_controller.rb +157 -0
  6. data/app/controllers/concerns/foreman/controller/parameters/dlmlocks.rb +15 -0
  7. data/app/controllers/concerns/foreman_dlm/find_host_by_client_cert.rb +63 -0
  8. data/app/controllers/concerns/foreman_dlm/find_host_by_ip.rb +54 -0
  9. data/app/controllers/dlmlocks_controller.rb +13 -0
  10. data/app/helpers/foreman_dlm/dlmlock_helper.rb +15 -0
  11. data/app/models/concerns/foreman_dlm/host_extensions.rb +14 -0
  12. data/app/models/concerns/foreman_dlm/host_monitoring_extensions.rb +36 -0
  13. data/app/models/dlmlock/update.rb +5 -0
  14. data/app/models/dlmlock.rb +79 -0
  15. data/app/views/api/v2/dlmlocks/acquire.json.rabl +3 -0
  16. data/app/views/api/v2/dlmlocks/base.json.rabl +3 -0
  17. data/app/views/api/v2/dlmlocks/create.json.rabl +3 -0
  18. data/app/views/api/v2/dlmlocks/index.json.rabl +3 -0
  19. data/app/views/api/v2/dlmlocks/main.json.rabl +7 -0
  20. data/app/views/api/v2/dlmlocks/release.json.rabl +3 -0
  21. data/app/views/api/v2/dlmlocks/show.json.rabl +8 -0
  22. data/app/views/api/v2/dlmlocks/update.json.rabl +3 -0
  23. data/app/views/api/v2/errors/precondition_failed.json.rabl +5 -0
  24. data/app/views/dlmlocks/_details.html.erb +35 -0
  25. data/app/views/dlmlocks/_list.html.erb +45 -0
  26. data/app/views/dlmlocks/index.html.erb +2 -0
  27. data/app/views/dlmlocks/show.html.erb +7 -0
  28. data/app/views/dlmlocks/welcome.html.erb +14 -0
  29. data/config/routes.rb +25 -0
  30. data/db/migrate/20170824084100_add_dlmlock.foreman_dlm.rb +12 -0
  31. data/lib/foreman_dlm/engine.rb +76 -0
  32. data/lib/foreman_dlm/version.rb +3 -0
  33. data/lib/foreman_dlm.rb +4 -0
  34. data/lib/tasks/foreman_dlm_tasks.rake +37 -0
  35. data/locale/Makefile +60 -0
  36. data/locale/en/foreman_dlm.po +19 -0
  37. data/locale/foreman_dlm.pot +19 -0
  38. data/locale/gemspec.rb +2 -0
  39. data/test/controllers/api/v2/dlmlocks_controller_test.rb +367 -0
  40. data/test/controllers/dlmlocks_test.rb +24 -0
  41. data/test/controllers/find_host_by_client_cert_test.rb +91 -0
  42. data/test/factories/dlmlock.rb +6 -0
  43. data/test/models/dlmlock_test.rb +201 -0
  44. data/test/models/host_monitoring_test.rb +42 -0
  45. data/test/test_plugin_helper.rb +9 -0
  46. metadata +124 -0
@@ -0,0 +1,367 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class Api::V2::DlmlocksControllerTest < ActionController::TestCase
4
+ let(:host1) { as_admin { FactoryBot.create(:host, :managed) } }
5
+ let(:host2) { as_admin { FactoryBot.create(:host, :managed) } }
6
+
7
+ context 'with user authentication' do
8
+ context '#index' do
9
+ test 'should show dlmlocks' do
10
+ dlmlock = FactoryBot.create(:dlmlock, :host => host1)
11
+ get :index
12
+ assert_response :success
13
+ body = ActiveSupport::JSON.decode(@response.body)
14
+ results = body['results']
15
+ assert results
16
+ entry = results.detect { |entry| entry['id'] == dlmlock.id }
17
+ assert entry
18
+ assert_equal dlmlock.name, entry['name']
19
+ assert_equal dlmlock.type, entry['type']
20
+ assert_equal dlmlock.enabled, entry['enabled']
21
+ assert_equal dlmlock.host_id, entry['host_id']
22
+ end
23
+ end
24
+
25
+ context '#create' do
26
+ test 'should create dlmlock' do
27
+ assert_difference('Dlmlock.unscoped.count') do
28
+ post :create, valid_attrs_with_root
29
+ end
30
+ assert_response :success
31
+ body = ActiveSupport::JSON.decode(@response.body)
32
+ dlmlock = Dlmlock.find(body['id'])
33
+ assert dlmlock
34
+ assert_equal valid_attrs['name'], dlmlock.name
35
+ assert_equal valid_attrs['type'], dlmlock.type
36
+ assert_equal true, dlmlock.enabled
37
+ assert_nil dlmlock.host
38
+ end
39
+ end
40
+
41
+ context '#show' do
42
+ test 'should show individual record with host' do
43
+ dlmlock = FactoryBot.create(:dlmlock, :host => host1)
44
+ get :show, { :id => dlmlock.to_param }
45
+ assert_response :success
46
+ body = ActiveSupport::JSON.decode(@response.body)
47
+ refute_empty body
48
+ assert_equal dlmlock.name, body['name']
49
+ assert_equal dlmlock.type, body['type']
50
+ assert_equal true, body['enabled']
51
+ assert_equal host1.id, body['host_id']
52
+ end
53
+
54
+ test 'should show individual record that is disabled' do
55
+ dlmlock = FactoryBot.create(:dlmlock, :enabled => false)
56
+ get :show, { :id => dlmlock.to_param }
57
+ assert_response :success
58
+ body = ActiveSupport::JSON.decode(@response.body)
59
+ refute_empty body
60
+ assert_equal dlmlock.name, body['name']
61
+ assert_equal dlmlock.type, body['type']
62
+ assert_equal false, body['enabled']
63
+ assert_nil body['host_id']
64
+ end
65
+
66
+ test 'should show individual record by name' do
67
+ dlmlock = FactoryBot.create(:dlmlock, :host => host1)
68
+ get :show, { :id => dlmlock.name }
69
+ assert_response :success
70
+ body = ActiveSupport::JSON.decode(@response.body)
71
+ refute_empty body
72
+ assert_equal dlmlock.id, body['id']
73
+ assert_equal dlmlock.name, body['name']
74
+ host = body['host']
75
+ assert host
76
+ assert_equal host1.name, host['name']
77
+ refute host.has_key?('self')
78
+ end
79
+
80
+ test 'should not find dlmlock with invalid id' do
81
+ get :show, { :id => 9999999 }
82
+ assert_response :not_found
83
+ end
84
+ end
85
+
86
+ context '#update' do
87
+ test 'should update dlmlock' do
88
+ dlmlock = FactoryBot.create(:dlmlock)
89
+ put :update, { :id => dlmlock.to_param, :dlmlock => valid_attrs.merge(:host_id => host1.id, :enabled => false) }
90
+ assert_response :success
91
+ dlmlock.reload
92
+ assert_equal valid_attrs['name'], dlmlock.name
93
+ assert_equal valid_attrs['type'], dlmlock.type
94
+ assert_equal false, dlmlock.enabled
95
+ assert_equal host1.id, dlmlock.host_id
96
+ end
97
+ end
98
+
99
+ context '#destroy' do
100
+ test 'should destroy dlmlock' do
101
+ dlmlock = FactoryBot.create(:dlmlock)
102
+ assert_difference('Dlmlock.unscoped.count', -1) do
103
+ delete :destroy, { :id => dlmlock.to_param }
104
+ end
105
+ assert_response :success
106
+ assert_equal 0, Dlmlock.where(:id => dlmlock.id).count
107
+ end
108
+ end
109
+
110
+ context '#acquire' do
111
+ test 'should deny access' do
112
+ dlmlock = FactoryBot.create(:dlmlock)
113
+ put :acquire, { :id => dlmlock.to_param }
114
+ assert_response :forbidden
115
+ assert_nil dlmlock.reload.host
116
+ end
117
+ end
118
+
119
+ context '#release' do
120
+ test 'should deny access' do
121
+ dlmlock = FactoryBot.create(:dlmlock, :host => host2)
122
+ delete :release, { :id => dlmlock.to_param }
123
+ assert_response :forbidden
124
+ assert_equal host2, dlmlock.reload.host
125
+ end
126
+ end
127
+ end
128
+
129
+ context 'with client cert' do
130
+ setup do
131
+ User.current = nil
132
+ reset_api_credentials
133
+
134
+ Setting[:ssl_client_dn_env] = 'SSL_CLIENT_S_DN'
135
+ Setting[:ssl_client_verify_env] = 'SSL_CLIENT_VERIFY'
136
+
137
+ @request.env['HTTPS'] = 'on'
138
+ @request.env['SSL_CLIENT_S_DN'] = "CN=#{host1.name},DN=example,DN=com"
139
+ @request.env['SSL_CLIENT_VERIFY'] = 'SUCCESS'
140
+ end
141
+
142
+ context '#index' do
143
+ test 'should deny access' do
144
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
145
+ get :index, { :id => dlmlock.to_param }
146
+ assert_response :unauthorized
147
+ end
148
+ end
149
+
150
+ context '#create' do
151
+ test 'should deny access' do
152
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
153
+ post :create, valid_attrs_with_root
154
+ assert_response :unauthorized
155
+ end
156
+ end
157
+
158
+ context '#update' do
159
+ test 'should deny access' do
160
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
161
+ put :update, { :id => dlmlock.to_param, :dlmlock => valid_attrs }
162
+ assert_response :unauthorized
163
+ end
164
+ end
165
+
166
+ context '#destroy' do
167
+ test 'should deny access' do
168
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
169
+ delete :destroy, { :id => dlmlock.to_param }
170
+ assert_response :unauthorized
171
+ assert_equal 1, as_admin { Dlmlock.where(:id => dlmlock.id).count }
172
+ end
173
+ end
174
+
175
+ context '#show' do
176
+ test 'should show individual free lock' do
177
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
178
+ get :show, { :id => dlmlock.to_param }
179
+ assert_response :success
180
+ body = ActiveSupport::JSON.decode(@response.body)
181
+ refute_empty body
182
+ assert_equal dlmlock.name, body['name']
183
+ assert_equal dlmlock.type, body['type']
184
+ assert_equal true, body['enabled']
185
+ assert_nil body['host_id']
186
+ assert_nil body['host']
187
+ end
188
+
189
+ test 'should show individual acquired lock by me' do
190
+ dlmlock = as_admin { FactoryBot.create(:dlmlock, :host => host1) }
191
+ get :show, { :id => dlmlock.to_param }
192
+ assert_response :success
193
+ body = ActiveSupport::JSON.decode(@response.body)
194
+ refute_empty body
195
+ assert_equal dlmlock.name, body['name']
196
+ assert_equal dlmlock.type, body['type']
197
+ assert_equal true, body['enabled']
198
+ assert_equal host1.id, body['host_id']
199
+ host = body['host']
200
+ assert host
201
+ assert_equal host1.name, host['name']
202
+ assert_equal true, host['self']
203
+ end
204
+
205
+ test 'should show individual acquired lock by other' do
206
+ dlmlock = as_admin { FactoryBot.create(:dlmlock, :host => host2) }
207
+ get :show, { :id => dlmlock.to_param }
208
+ assert_response :success
209
+ body = ActiveSupport::JSON.decode(@response.body)
210
+ refute_empty body
211
+ assert_equal dlmlock.name, body['name']
212
+ assert_equal dlmlock.type, body['type']
213
+ assert_equal true, body['enabled']
214
+ assert_equal host2.id, body['host_id']
215
+ host = body['host']
216
+ assert host
217
+ assert_equal host2.name, host['name']
218
+ assert_equal false, host['self']
219
+ end
220
+ end
221
+
222
+ context '#acquire' do
223
+ test 'should acquire empty dlmlock' do
224
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
225
+ put :acquire, { :id => dlmlock.to_param }
226
+ assert_response :success
227
+ assert_equal host1, as_admin { dlmlock.reload.host }
228
+ end
229
+
230
+ test 'should acquire own dlmlock' do
231
+ dlmlock = as_admin { FactoryBot.create(:dlmlock, :host => host1) }
232
+ put :acquire, { :id => dlmlock.to_param }
233
+ assert_response :success
234
+ assert_equal host1, as_admin { dlmlock.reload.host }
235
+ end
236
+
237
+ test 'should not acquire foreign dlmlock' do
238
+ dlmlock = as_admin { FactoryBot.create(:dlmlock, :host => host2) }
239
+ put :acquire, { :id => dlmlock.to_param }
240
+ assert_response :precondition_failed
241
+ assert_equal host2, as_admin { dlmlock.reload.host }
242
+ end
243
+
244
+ test 'should transparently create non-existing dlmlock' do
245
+ lockname = 'Test Lock'
246
+ assert_equal 0, as_admin { Dlmlock.where(:name => lockname).count }
247
+ put :acquire, { :id => lockname }
248
+ assert_response :success
249
+ dlmlock = as_admin { Dlmlock.find_by(:name => lockname) }
250
+ assert_equal lockname, dlmlock.name
251
+ assert_equal host1, dlmlock.host
252
+ end
253
+ end
254
+
255
+ context '#release' do
256
+ test 'should release empty dlmlock' do
257
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
258
+ delete :release, { :id => dlmlock.to_param }
259
+ assert_response :success
260
+ assert_nil as_admin { dlmlock.reload.host }
261
+ end
262
+
263
+ test 'should release own dlmlock' do
264
+ dlmlock = as_admin { FactoryBot.create(:dlmlock, :host => host1) }
265
+ delete :release, { :id => dlmlock.to_param }
266
+ assert_response :success
267
+ assert_nil as_admin { dlmlock.reload.host }
268
+ end
269
+
270
+ test 'should not acquire foreign dlmlock' do
271
+ dlmlock = as_admin { FactoryBot.create(:dlmlock, :host => host2) }
272
+ delete :release, { :id => dlmlock.to_param }
273
+ assert_response :precondition_failed
274
+ assert_equal host2, as_admin { dlmlock.reload.host }
275
+ end
276
+
277
+ test 'should transparently create non-existing dlmlock' do
278
+ lockname = 'Test Lock'
279
+ assert_equal 0, as_admin { Dlmlock.where(:name => lockname).count }
280
+ delete :release, { :id => lockname }
281
+ assert_response :success
282
+ dlmlock = as_admin { Dlmlock.find_by(:name => lockname) }
283
+ assert_equal lockname, dlmlock.name
284
+ assert_nil dlmlock.host
285
+ end
286
+ end
287
+ end
288
+
289
+ context 'without any credentials' do
290
+ setup do
291
+ User.current = nil
292
+ reset_api_credentials
293
+ end
294
+
295
+ context '#index' do
296
+ test 'should deny access' do
297
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
298
+ get :index, { :id => dlmlock.to_param }
299
+ assert_response :unauthorized
300
+ end
301
+ end
302
+
303
+ context '#show' do
304
+ test 'should deny access' do
305
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
306
+ get :show, { :id => dlmlock.to_param }
307
+ assert_response :unauthorized
308
+ end
309
+ end
310
+
311
+ context '#create' do
312
+ test 'should deny access' do
313
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
314
+ post :create, valid_attrs_with_root
315
+ assert_response :unauthorized
316
+ end
317
+ end
318
+
319
+ context '#update' do
320
+ test 'should deny access' do
321
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
322
+ put :update, { :id => dlmlock.to_param, :dlmlock => valid_attrs }
323
+ assert_response :unauthorized
324
+ end
325
+ end
326
+
327
+ context '#destroy' do
328
+ test 'should deny access' do
329
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
330
+ delete :destroy, { :id => dlmlock.to_param }
331
+ assert_response :unauthorized
332
+ assert_equal 1, as_admin { Dlmlock.where(:id => dlmlock.id).count }
333
+ end
334
+ end
335
+
336
+ context '#acquire' do
337
+ test 'should deny access' do
338
+ dlmlock = as_admin { FactoryBot.create(:dlmlock) }
339
+ put :acquire, { :id => dlmlock.to_param }
340
+ assert_response :unauthorized
341
+ assert_nil as_admin { dlmlock.reload.host }
342
+ end
343
+ end
344
+
345
+ context '#release' do
346
+ test 'should deny access' do
347
+ dlmlock = as_admin { FactoryBot.create(:dlmlock, :host => host2) }
348
+ delete :release, { :id => dlmlock.to_param }
349
+ assert_response :unauthorized
350
+ assert_equal host2, as_admin { dlmlock.reload.host }
351
+ end
352
+ end
353
+ end
354
+
355
+ private
356
+
357
+ def valid_attrs
358
+ {
359
+ 'name' => 'testlock',
360
+ 'type' => 'Dlmlock::Update'
361
+ }
362
+ end
363
+
364
+ def valid_attrs_with_root(extra_attrs = {})
365
+ { :dlmlock => valid_attrs.merge(extra_attrs) }
366
+ end
367
+ end
@@ -0,0 +1,24 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class DlmlocksControllerTest < ActionController::TestCase
4
+ test '#index' do
5
+ FactoryBot.create(:dlmlock)
6
+ get :index, {}, set_session_user
7
+ assert_response :success
8
+ assert_not_nil assigns('dlmlocks')
9
+ assert_template 'index'
10
+ end
11
+
12
+ test '#index with no lock shows welcome page' do
13
+ get :index, {}, set_session_user
14
+ assert_response :success
15
+ assert_template 'welcome'
16
+ end
17
+
18
+ test '#show' do
19
+ dlmlock = FactoryBot.create(:dlmlock)
20
+ get :show, { :id => dlmlock.id }, set_session_user
21
+ assert_response :success
22
+ assert_template 'show'
23
+ end
24
+ end
@@ -0,0 +1,91 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class FindHostByClientCertTest < ActionController::TestCase
4
+ tests "api/v2/dlmlocks"
5
+
6
+ def described_class
7
+ Api::V2::DlmlocksController
8
+ end
9
+
10
+ context 'with ssl settings' do
11
+ setup do
12
+ Setting[:ssl_client_dn_env] = 'SSL_CLIENT_S_DN'
13
+ Setting[:ssl_client_verify_env] = 'SSL_CLIENT_VERIFY'
14
+ end
15
+
16
+ let(:host) { as_admin { FactoryBot.create(:host, :managed) } }
17
+
18
+ context 'with api credentials' do
19
+ test 'certificate with dn permits access' do
20
+ @request.env['HTTPS'] = 'on'
21
+ @request.env['SSL_CLIENT_VERIFY'] = 'NONE'
22
+
23
+ get :index
24
+
25
+ assert @controller.send(:require_client_cert_or_login)
26
+ assert_nil @controller.detected_host
27
+ end
28
+
29
+ test 'certificate with dn permits access' do
30
+ @request.env['HTTPS'] = 'on'
31
+ @request.env['SSL_CLIENT_S_DN'] = "CN=#{host.name},DN=example,DN=com"
32
+ @request.env['SSL_CLIENT_VERIFY'] = 'SUCCESS'
33
+
34
+ get :index
35
+
36
+ assert @controller.send(:require_client_cert_or_login)
37
+ assert_equal host, @controller.detected_host
38
+ end
39
+ end
40
+
41
+ context 'without api credentials' do
42
+ setup do
43
+ User.current = nil
44
+ reset_api_credentials
45
+ end
46
+
47
+ test 'certificate with dn permits access' do
48
+ @request.env['HTTPS'] = 'on'
49
+ @request.env['SSL_CLIENT_S_DN'] = "CN=#{host.name},DN=example,DN=com"
50
+ @request.env['SSL_CLIENT_VERIFY'] = 'SUCCESS'
51
+
52
+ get :index
53
+
54
+ assert @controller.send(:require_client_cert_or_login)
55
+ assert_equal host, @controller.detected_host
56
+ end
57
+
58
+ test 'certificate with unknown dn denies access' do
59
+ @request.env['HTTPS'] = 'on'
60
+ @request.env['SSL_CLIENT_S_DN'] = "CN=doesnotexist.example.com,DN=example,DN=com"
61
+ @request.env['SSL_CLIENT_VERIFY'] = 'SUCCESS'
62
+
63
+ get :index
64
+
65
+ assert_equal false, @controller.send(:require_client_cert_or_login)
66
+ assert_nil @controller.detected_host
67
+ end
68
+
69
+ test 'invalid certificate denies access' do
70
+ @request.env['HTTPS'] = 'on'
71
+ @request.env['SSL_CLIENT_S_DN'] = "CN=#{host.name},DN=example,DN=com"
72
+ @request.env['SSL_CLIENT_VERIFY'] = 'GENEROUS'
73
+
74
+ get :index
75
+
76
+ assert_equal false, @controller.send(:require_client_cert_or_login)
77
+ assert_nil @controller.detected_host
78
+ end
79
+
80
+ test 'no certificate denies access' do
81
+ @request.env['HTTPS'] = 'on'
82
+ @request.env['SSL_CLIENT_VERIFY'] = 'NONE'
83
+
84
+ get :index
85
+
86
+ assert_equal false, @controller.send(:require_client_cert_or_login)
87
+ assert_nil @controller.detected_host
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,6 @@
1
+ FactoryBot.define do
2
+ factory :dlmlock do
3
+ sequence(:name) { |n| "Lock #{n}" }
4
+ type 'Dlmlock::Update'
5
+ end
6
+ end
@@ -0,0 +1,201 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class DlmlockTest < ActiveSupport::TestCase
4
+ setup do
5
+ User.current = users(:admin)
6
+ end
7
+
8
+ subject { FactoryBot.create(:dlmlock) }
9
+ should validate_presence_of(:name)
10
+ should validate_uniqueness_of(:name)
11
+
12
+ let(:host1) { FactoryBot.create(:host, :managed) }
13
+ let(:host2) { FactoryBot.create(:host, :managed) }
14
+
15
+ class HostWithCallbacks < ::Host::Managed
16
+ attr_accessor :callbacks
17
+
18
+ def initialize(*attributes, &block)
19
+ super
20
+ @callbacks = []
21
+ end
22
+
23
+ after_lock :callback1
24
+ after_unlock :callback2
25
+
26
+ def callback1
27
+ Rails.logger.debug "callback1 executed for #{self} (#{self.class})"
28
+ callbacks << 'callback1'
29
+ end
30
+
31
+ def callback2
32
+ Rails.logger.debug "callback2 executed for #{self} (#{self.class})"
33
+ callbacks << 'callback2'
34
+ end
35
+ end
36
+
37
+ let(:host1_with_callbacks) { HostWithCallbacks.create(:name => 'test1.example.com') }
38
+ let(:host2_with_callbacks) { HostWithCallbacks.create(:name => 'test2.example.com') }
39
+
40
+ context 'a free and enabled DLM lock' do
41
+ let(:dlmlock) { FactoryBot.create(:dlmlock) }
42
+
43
+ test 'should be enabled and unlocked' do
44
+ assert_equal true, dlmlock.enabled?
45
+ assert_equal false, dlmlock.disabled?
46
+ assert_equal false, dlmlock.locked?
47
+ assert_equal false, dlmlock.taken?
48
+ end
49
+
50
+ test 'can be acquired' do
51
+ assert_nil dlmlock.host
52
+ assert dlmlock.acquire!(host1)
53
+ assert_equal host1, dlmlock.reload.host
54
+ end
55
+
56
+ test 'can be released' do
57
+ assert_nil dlmlock.host
58
+ assert dlmlock.release!(host1)
59
+ assert_nil dlmlock.reload.host
60
+ end
61
+
62
+ test 'records audit change on acquisition by owner' do
63
+ assert_difference "Audit.where(auditable_type: 'Dlmlock').count" do
64
+ assert dlmlock.acquire!(host1)
65
+ end
66
+ audit_record = dlmlock.audits.last
67
+ assert_equal 'update', audit_record.action
68
+ assert_equal({:host_id => host1.id}, audit_record.audited_changes)
69
+ end
70
+
71
+ test 'records no audit change on release' do
72
+ assert_no_difference "Audit.where(auditable_type: 'Dlmlock').count" do
73
+ assert dlmlock.release!(host1)
74
+ end
75
+ end
76
+
77
+ test 'triggers after_lock callback' do
78
+ host = HostWithCallbacks.new
79
+ host.name = 'test.example.com'
80
+ host.save
81
+ assert dlmlock.acquire!(host)
82
+ assert_equal ['callback1'], host.callbacks
83
+ end
84
+ end
85
+
86
+ context 'a free and disabled DLM lock' do
87
+ let(:dlmlock) { FactoryBot.create(:dlmlock, :enabled => false) }
88
+
89
+ test 'should be disabled and unlocked' do
90
+ assert_equal false, dlmlock.enabled?
91
+ assert_equal true, dlmlock.disabled?
92
+ assert_equal false, dlmlock.locked?
93
+ assert_equal false, dlmlock.taken?
94
+ end
95
+
96
+ test 'can not be acquired' do
97
+ assert_nil dlmlock.host
98
+ assert_equal false, dlmlock.acquire!(host1)
99
+ assert_nil dlmlock.reload.host
100
+ end
101
+
102
+ test 'can not be released' do
103
+ assert_nil dlmlock.host
104
+ assert_equal false, dlmlock.release!(host1)
105
+ assert_nil dlmlock.reload.host
106
+ end
107
+
108
+ test 'triggers no callbacks' do
109
+ host = HostWithCallbacks.new
110
+ host.name = 'test.example.com'
111
+ host.save
112
+ assert_equal false, dlmlock.release!(host)
113
+ assert_equal [], host.callbacks
114
+ end
115
+ end
116
+
117
+ context 'an acquired DLM lock' do
118
+ let(:dlmlock) { FactoryBot.create(:dlmlock, :host => host1) }
119
+
120
+ test 'should be enabled and locked' do
121
+ assert_equal true, dlmlock.enabled?
122
+ assert_equal false, dlmlock.disabled?
123
+ assert_equal true, dlmlock.locked?
124
+ assert_equal true, dlmlock.taken?
125
+ assert_equal true, dlmlock.locked_by?(host1)
126
+ assert_equal true, dlmlock.acquired_by?(host1)
127
+ end
128
+
129
+ test 'can be acquired by owner' do
130
+ assert_equal host1, dlmlock.host
131
+ assert dlmlock.acquire!(host1)
132
+ assert_equal host1, dlmlock.reload.host
133
+ end
134
+
135
+ test 'can not be acquired by other host' do
136
+ assert_equal host1, dlmlock.host
137
+ assert_equal false, dlmlock.acquire!(host2)
138
+ assert_equal host1, dlmlock.reload.host
139
+ end
140
+
141
+ test 'can be released by owner' do
142
+ assert_equal host1, dlmlock.host
143
+ assert dlmlock.release!(host1)
144
+ assert_nil dlmlock.reload.host
145
+ end
146
+
147
+ test 'can not be released by other host' do
148
+ assert_equal host1, dlmlock.host
149
+ assert_equal false, dlmlock.release!(host2)
150
+ assert_equal host1, dlmlock.reload.host
151
+ end
152
+
153
+ test 'records audit change on release by owner' do
154
+ assert_difference "Audit.where(auditable_type: 'Dlmlock').count" do
155
+ assert dlmlock.release!(host1)
156
+ end
157
+ audit_record = dlmlock.audits.last
158
+ assert_equal 'update', audit_record.action
159
+ assert_equal({:host_id => nil}, audit_record.audited_changes)
160
+ end
161
+
162
+ test 'records no audit change on acquisition by owner' do
163
+ assert_no_difference "Audit.where(auditable_type: 'Dlmlock').count" do
164
+ assert dlmlock.acquire!(host1)
165
+ end
166
+ end
167
+
168
+ test 'triggers after_unlock callback on release by owner' do
169
+ host = HostWithCallbacks.new
170
+ host.name = 'test.example.com'
171
+ host.save
172
+ dlmlock.host = host
173
+ dlmlock.save
174
+ assert dlmlock.release!(host)
175
+ assert_equal ['callback2'], host.callbacks
176
+ end
177
+
178
+ test 'triggers no callbacks on release attempt by other host' do
179
+ assert host1_with_callbacks
180
+ assert host2_with_callbacks
181
+ dlmlock.update(:host => host1_with_callbacks)
182
+ assert_equal false, dlmlock.release!(host2_with_callbacks)
183
+ assert_equal [], host1_with_callbacks.callbacks
184
+ assert_equal [], host2_with_callbacks.callbacks
185
+ end
186
+
187
+ test 'triggers no callbacks on acquiry attempt by owner' do
188
+ assert host1_with_callbacks
189
+ dlmlock.update(:host => host1_with_callbacks)
190
+ assert dlmlock.acquire!(host1_with_callbacks)
191
+ assert_equal [], host1_with_callbacks.callbacks
192
+ end
193
+ end
194
+
195
+ context 'scoped search' do
196
+ test 'can be searched by name' do
197
+ dlmlock = FactoryBot.create(:dlmlock)
198
+ assert_equal Dlmlock::Update.find(dlmlock.id), Dlmlock.search_for("name ~ #{dlmlock.name}").first
199
+ end
200
+ end
201
+ end