foreman_remote_execution 14.1.0 → 14.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/app/models/job_template.rb +1 -0
  3. data/app/views/template_invocations/show.js.erb +1 -1
  4. data/db/migrate/20240312133027_extend_template_invocation_events.rb +9 -0
  5. data/lib/foreman_remote_execution/engine.rb +1 -1
  6. data/lib/foreman_remote_execution/version.rb +1 -1
  7. data/lib/tasks/foreman_remote_execution_tasks.rake +3 -0
  8. data/test/benchmark/run_hosts_job_benchmark.rb +70 -0
  9. data/test/benchmark/targeting_benchmark.rb +31 -0
  10. data/test/factories/foreman_remote_execution_factories.rb +147 -0
  11. data/test/functional/api/v2/foreign_input_sets_controller_test.rb +58 -0
  12. data/test/functional/api/v2/job_invocations_controller_test.rb +446 -0
  13. data/test/functional/api/v2/job_templates_controller_test.rb +110 -0
  14. data/test/functional/api/v2/registration_controller_test.rb +73 -0
  15. data/test/functional/api/v2/remote_execution_features_controller_test.rb +34 -0
  16. data/test/functional/api/v2/template_invocations_controller_test.rb +33 -0
  17. data/test/functional/cockpit_controller_test.rb +16 -0
  18. data/test/functional/job_invocations_controller_test.rb +132 -0
  19. data/test/functional/job_templates_controller_test.rb +31 -0
  20. data/test/functional/ui_job_wizard_controller_test.rb +16 -0
  21. data/test/graphql/mutations/job_invocations/create_test.rb +58 -0
  22. data/test/graphql/queries/job_invocation_query_test.rb +31 -0
  23. data/test/graphql/queries/job_invocations_query_test.rb +35 -0
  24. data/test/helpers/remote_execution_helper_test.rb +46 -0
  25. data/test/support/remote_execution_helper.rb +5 -0
  26. data/test/test_plugin_helper.rb +9 -0
  27. data/test/unit/actions/run_host_job_test.rb +115 -0
  28. data/test/unit/actions/run_hosts_job_test.rb +214 -0
  29. data/test/unit/api_params_test.rb +25 -0
  30. data/test/unit/concerns/foreman_tasks_cleaner_extensions_test.rb +29 -0
  31. data/test/unit/concerns/host_extensions_test.rb +219 -0
  32. data/test/unit/concerns/nic_extensions_test.rb +9 -0
  33. data/test/unit/execution_task_status_mapper_test.rb +92 -0
  34. data/test/unit/input_template_renderer_test.rb +503 -0
  35. data/test/unit/job_invocation_composer_test.rb +974 -0
  36. data/test/unit/job_invocation_report_template_test.rb +60 -0
  37. data/test/unit/job_invocation_test.rb +232 -0
  38. data/test/unit/job_template_effective_user_test.rb +37 -0
  39. data/test/unit/job_template_test.rb +316 -0
  40. data/test/unit/remote_execution_feature_test.rb +86 -0
  41. data/test/unit/remote_execution_provider_test.rb +298 -0
  42. data/test/unit/renderer_scope_input_test.rb +49 -0
  43. data/test/unit/targeting_test.rb +206 -0
  44. data/test/unit/template_invocation_input_value_test.rb +38 -0
  45. metadata +39 -2
@@ -0,0 +1,446 @@
1
+ require 'test_plugin_helper'
2
+
3
+ module Api
4
+ module V2
5
+ class JobInvocationsControllerTest < ActionController::TestCase
6
+ setup do
7
+ @invocation = FactoryBot.create(:job_invocation, :with_template, :with_task, :with_unplanned_host)
8
+ @template = FactoryBot.create(:job_template, :with_input)
9
+
10
+ # Without this the template in template_invocations and in pattern_template_invocations
11
+ # would belong to different job_categories, causing trouble when trying to rerun
12
+ @invocation.job_category = @invocation.pattern_template_invocations.first.template.job_category
13
+ @invocation.save!
14
+ end
15
+
16
+ test 'should get index' do
17
+ get :index
18
+ invocations = ActiveSupport::JSON.decode(@response.body)
19
+ assert_not_empty invocations, 'Should response with invocation'
20
+ assert_response :success
21
+ end
22
+
23
+ describe 'show' do
24
+ test 'should get invocation detail' do
25
+ get :show, params: { :id => @invocation.id }
26
+ assert_response :success
27
+ template = ActiveSupport::JSON.decode(@response.body)
28
+ assert_not_empty template
29
+ assert_equal template['job_category'], @invocation.job_category
30
+ assert_not_empty template['targeting']['hosts']
31
+ end
32
+
33
+ test 'should get invocation detail when taxonomies are set' do
34
+ taxonomy_params = %w(organization location).reduce({}) { |acc, cur| acc.merge("#{cur}_id" => FactoryBot.create(cur)) }
35
+ get :show, params: taxonomy_params.merge(:id => @invocation.id)
36
+ assert_response :success
37
+ end
38
+
39
+ test 'should see only permitted hosts' do
40
+ @user = FactoryBot.create(:user, admin: false)
41
+ @invocation.task.update(user: @user)
42
+ setup_user('view', 'job_invocations', nil, @user)
43
+ setup_user('view', 'hosts', 'name ~ nope.example.com', @user)
44
+
45
+ get :show, params: { :id => @invocation.id }, session: prepare_user(@user)
46
+ assert_response :success
47
+ response = ActiveSupport::JSON.decode(@response.body)
48
+ assert_equal response['targeting']['hosts'], []
49
+ end
50
+ end
51
+
52
+ context 'creation' do
53
+ setup do
54
+ @attrs = { :job_category => @template.job_category,
55
+ :name => 'RandomName',
56
+ :job_template_id => @template.id,
57
+ :targeting_type => 'static_query',
58
+ :search_query => 'foobar' }
59
+ end
60
+
61
+ test 'should create valid with job_template_id' do
62
+ post :create, params: { job_invocation: @attrs }
63
+
64
+ invocation = ActiveSupport::JSON.decode(@response.body)
65
+ assert_equal @attrs[:job_category], invocation['job_category']
66
+ assert_response :success
67
+ end
68
+
69
+ test 'should create with description format overridden' do
70
+ @attrs[:description_format] = 'format'
71
+ post :create, params: { job_invocation: @attrs }
72
+
73
+ invocation = ActiveSupport::JSON.decode(@response.body)
74
+ assert_equal @attrs[:description_format], invocation['description']
75
+ end
76
+
77
+ test 'should create with recurrence' do
78
+ @attrs[:recurrence] = { cron_line: '5 * * * *' }
79
+ post :create, params: { job_invocation: @attrs }
80
+ invocation = ActiveSupport::JSON.decode(@response.body)
81
+ assert_equal invocation['mode'], 'recurring'
82
+ assert_response :success
83
+ end
84
+
85
+ test 'should propagate errors from triggering' do
86
+ @attrs[:recurrence] = { cron_line: 'foo' }
87
+ post :create, params: { job_invocation: @attrs }
88
+ invocation = ActiveSupport::JSON.decode(@response.body)
89
+ assert_match(/foo is not valid format of cron line/, invocation['error']['message'])
90
+ assert_response 500
91
+ end
92
+
93
+ test 'should create with schedule' do
94
+ @attrs[:scheduling] = { start_at: Time.now.to_s }
95
+ post :create, params: { job_invocation: @attrs }
96
+ invocation = ActiveSupport::JSON.decode(@response.body)
97
+ assert_equal invocation['mode'], 'future'
98
+ assert_response :success
99
+ end
100
+
101
+ test 'should create with a scheduled recurrence' do
102
+ @attrs[:scheduling] = { start_at: (Time.now + 1.hour) }
103
+ @attrs[:recurrence] = { cron_line: '5 * * * *' }
104
+ post :create, params: { job_invocation: @attrs }
105
+ invocation = ActiveSupport::JSON.decode(@response.body)
106
+ assert_equal 'recurring', invocation['mode']
107
+ assert invocation['start_at']
108
+ assert_response :success
109
+ end
110
+
111
+ context 'with_feature' do
112
+ setup do
113
+ @feature = FactoryBot.create(:remote_execution_feature,
114
+ :job_template => @template)
115
+ @attrs = {
116
+ feature: @feature.label,
117
+ }
118
+ end
119
+
120
+ test 'host ids as array of FQDNs' do
121
+ host = FactoryBot.create(:host)
122
+ @attrs[:host_ids] = [host.fqdn]
123
+ post :create, params: { job_invocation: @attrs }
124
+ assert_response :success
125
+ end
126
+
127
+ test 'host ids as array of IDs' do
128
+ host = FactoryBot.create(:host)
129
+ host2 = FactoryBot.create(:host)
130
+ @attrs[:host_ids] = [host.id, host2.id]
131
+ post :create, params: { job_invocation: @attrs }
132
+ assert_response :success
133
+ end
134
+
135
+ test 'host ids as search_query' do
136
+ @attrs[:host_ids] = 'name = testfqdn'
137
+ post :create, params: { job_invocation: @attrs }
138
+ assert_response :success
139
+ end
140
+
141
+ test 'with search_query param' do
142
+ @attrs[:targeting_type] = 'static_query'
143
+ @attrs[:search_query] = 'name = testfqdn'
144
+ post :create, params: { job_invocation: @attrs }
145
+ assert_response :success
146
+ end
147
+
148
+ test 'with job_template_id param' do
149
+ @attrs[:job_template_id] = 12_345
150
+ post :create, params: { job_invocation: @attrs }
151
+ assert_response :error
152
+ end
153
+ end
154
+ end
155
+
156
+ describe '#output' do
157
+ let(:host) { @invocation.targeting.hosts.first }
158
+
159
+ test 'should provide output for delayed task' do
160
+ ForemanTasks::Task.any_instance.expects(:scheduled?).returns(true)
161
+ get :output, params: { :job_invocation_id => @invocation.id, :host_id => host.id }
162
+ result = ActiveSupport::JSON.decode(@response.body)
163
+ assert_equal result['delayed'], true
164
+ assert_equal result['refresh'], true
165
+ assert_equal result['output'], []
166
+ assert_response :success
167
+ end
168
+
169
+ test 'should provide empty output for host which does not have a task yet' do
170
+ JobInvocation.any_instance.expects(:sub_task_for_host).returns(nil)
171
+ JobInvocation.any_instance.expects(:finished?).returns(false)
172
+ get :output, params: { :job_invocation_id => @invocation.id, :host_id => host.id }
173
+ result = ActiveSupport::JSON.decode(@response.body)
174
+ assert_equal result['refresh'], true
175
+ assert_equal result['output'], []
176
+ assert_response :success
177
+ end
178
+
179
+ test 'should provide empty output marked as done for host which does not have a task when the job is finished' do
180
+ JobInvocation.any_instance.expects(:sub_task_for_host).returns(nil)
181
+ get :output, params: { :job_invocation_id => @invocation.id, :host_id => host.id }
182
+ result = ActiveSupport::JSON.decode(@response.body)
183
+ assert_equal result['refresh'], false
184
+ assert_equal result['output'], []
185
+ assert_response :success
186
+ end
187
+
188
+ test 'should fail with 404 for non-existing job invocation' do
189
+ invocation_id = @invocation.id + 1
190
+ assert_empty JobInvocation.where(:id => invocation_id)
191
+ get :output, params: { :job_invocation_id => invocation_id, :host_id => 1234 }
192
+ result = ActiveSupport::JSON.decode(@response.body)
193
+ assert_equal result['message'], "Job invocation not found by id '#{invocation_id}'"
194
+ assert_response :missing
195
+ end
196
+
197
+ test 'should get output only for host in job invocation' do
198
+ get :output, params: { job_invocation_id: @invocation.id,
199
+ host_id: FactoryBot.create(:host).id }
200
+ assert_response :missing
201
+ end
202
+
203
+ test 'should not break when taxonomy parameters are provided' do
204
+ get :output, params: { :job_invocation_id => @invocation.id, :host_id => host.id, :organization_id => host.organization_id, :location_id => host.location_id }
205
+ assert_response :success
206
+ end
207
+ end
208
+
209
+ describe '#outputs' do
210
+ test 'should provide outputs for hosts in the job' do
211
+ get :outputs, params: { :id => @invocation.id }
212
+ result = ActiveSupport::JSON.decode(@response.body)
213
+ host_output = result['outputs'].first
214
+ assert_equal host_output['host_id'], @invocation.targeting.host_ids.first
215
+ assert_equal host_output['refresh'], false
216
+ assert_equal host_output['output'], []
217
+ assert_response :success
218
+ end
219
+
220
+ test 'should provide outputs for selected hosts in the job' do
221
+ post :outputs, params: { :id => @invocation.id, :search_query => "id = #{@invocation.targeting.host_ids.first}" }, as: :json
222
+ result = ActiveSupport::JSON.decode(@response.body)
223
+ host_output = result['outputs'].first
224
+ assert_equal host_output['host_id'], @invocation.targeting.host_ids.first
225
+ assert_equal host_output['refresh'], false
226
+ assert_equal host_output['output'], []
227
+ assert_response :success
228
+ end
229
+
230
+ test 'should provide outputs for hosts in the job matching a search query' do
231
+ get :outputs, params: { :id => @invocation.id, :search_query => "name = definitely_not_in_the_job" }
232
+ result = ActiveSupport::JSON.decode(@response.body)
233
+ assert_equal result['outputs'], []
234
+ assert_response :success
235
+ end
236
+ end
237
+
238
+ describe 'raw output' do
239
+ let(:fake_output) do
240
+ (1..5).map do |i|
241
+ { 'timestamp' => (Time.now - (5 - i)).to_f, 'output' => "#{i}\n" }
242
+ end
243
+ end
244
+ let(:fake_task) do
245
+ OpenStruct.new :pending? => false, :main_action => OpenStruct.new(:live_output => fake_output)
246
+ end
247
+ let(:host) { @invocation.targeting.hosts.first }
248
+
249
+ test 'should provide raw output for a host' do
250
+ JobInvocation.any_instance.expects(:task).times(3).returns(OpenStruct.new(:scheduled? => false, :pending? => false))
251
+ JobInvocation.any_instance.expects(:sub_task_for_host).returns(fake_task)
252
+ get :raw_output, params: { :job_invocation_id => @invocation.id, :host_id => host.id }
253
+ result = ActiveSupport::JSON.decode(@response.body)
254
+ assert_equal result['complete'], true
255
+ assert_equal result['output'], (1..5).map(&:to_s).join("\n") + "\n"
256
+ assert_response :success
257
+ end
258
+
259
+ test 'should not break when taxonomy parameters are provided' do
260
+ get :raw_output, params: { :job_invocation_id => @invocation.id, :host_id => host.id, :organization_id => host.organization_id, :location_id => host.location_id }
261
+ assert_response :success
262
+ end
263
+
264
+ test 'should provide raw output for delayed task' do
265
+ start_time = Time.now
266
+ JobInvocation.any_instance
267
+ .expects(:task).twice
268
+ .returns(OpenStruct.new(:scheduled? => true, :start_at => start_time, :pending? => true))
269
+ JobInvocation.any_instance.expects(:sub_task_for_host).never
270
+ get :raw_output, params: { :job_invocation_id => @invocation.id, :host_id => host.id }
271
+ result = ActiveSupport::JSON.decode(@response.body)
272
+ assert_equal result['complete'], false
273
+ assert_equal result['delayed'], true
274
+ assert_nil result['output']
275
+ assert_in_delta start_time.to_f, Time.parse(result['start_at']).to_f, 0.001
276
+ assert_response :success
277
+ end
278
+
279
+ test 'should provide raw output for host without task' do
280
+ JobInvocation.any_instance.expects(:task).times(3).returns(OpenStruct.new(:scheduled? => false, :pending? => true))
281
+ JobInvocation.any_instance.expects(:sub_task_for_host)
282
+ get :raw_output, params: { :job_invocation_id => @invocation.id, :host_id => host.id }
283
+ result = ActiveSupport::JSON.decode(@response.body)
284
+ assert_equal result['complete'], false
285
+ assert_nil result['output']
286
+ assert_response :success
287
+ end
288
+
289
+ test 'should get raw output only for host in job invocation' do
290
+ get :raw_output, params: { job_invocation_id: @invocation.id,
291
+ host_id: FactoryBot.create(:host).id }
292
+ assert_response :missing
293
+ end
294
+ end
295
+
296
+ test 'should cancel a job' do
297
+ @invocation.task.expects(:cancellable?).returns(true)
298
+ @invocation.task.expects(:cancel).returns(true)
299
+ JobInvocation.expects(:from_param).with(@invocation.id.to_s).returns(@invocation)
300
+ post :cancel, :params => { :id => @invocation.id }
301
+ result = ActiveSupport::JSON.decode(@response.body)
302
+ assert_equal result['cancelled'], true
303
+ assert_equal result['id'], @invocation.id
304
+
305
+ assert_response :success
306
+ end
307
+
308
+ test 'should abort a job' do
309
+ @invocation.task.expects(:cancellable?).returns(true)
310
+ @invocation.task.expects(:abort).returns(true)
311
+ JobInvocation.expects(:from_param).with(@invocation.id.to_s).returns(@invocation)
312
+ post :cancel, :params => { :id => @invocation.id, :force => true }
313
+ result = ActiveSupport::JSON.decode(@response.body)
314
+ assert_equal result['cancelled'], true
315
+ assert_equal result['id'], @invocation.id
316
+
317
+ assert_response :success
318
+ end
319
+
320
+ test 'should error when trying to cancel a stopped job' do
321
+ @invocation.task.expects(:cancellable?).returns(false)
322
+ JobInvocation.expects(:from_param).with(@invocation.id.to_s).returns(@invocation)
323
+ post :cancel, :params => { :id => @invocation.id }
324
+ assert_response 422
325
+ end
326
+
327
+ test 'should rerun' do
328
+ JobInvocation.any_instance.expects(:generate_description)
329
+ JobInvocationComposer.any_instance
330
+ .expects(:validate_job_category)
331
+ .with(@invocation.job_category)
332
+ .returns(@invocation.job_category)
333
+ post :rerun, params: { :id => @invocation.id }
334
+ assert_response :success
335
+ result = ActiveSupport::JSON.decode(@response.body)
336
+ targeting = Targeting.find(result['targeting_id'])
337
+ assert_equal users(:admin).id, targeting.user_id
338
+ assert_equal @invocation.targeting.search_query, targeting.search_query
339
+ end
340
+
341
+ test 'should not raise an exception when reruning failed has no hosts' do
342
+ @invocation.targeting.hosts.first.destroy
343
+ JobInvocation.any_instance.expects(:generate_description)
344
+ JobInvocationComposer.any_instance
345
+ .expects(:validate_job_category)
346
+ .with(@invocation.job_category)
347
+ .returns(@invocation.job_category)
348
+
349
+ post :rerun, params: { :id => @invocation.id, :failed_only => true }
350
+ assert_response :success
351
+ result = ActiveSupport::JSON.decode(@response.body)
352
+ targeting = Targeting.find(result['targeting_id'])
353
+ assert_equal users(:admin).id, targeting.user_id
354
+ assert_equal 'name ^ ()', targeting.search_query
355
+ end
356
+
357
+ test 'should rerun failed only' do
358
+ @invocation = FactoryBot.create(:job_invocation, :with_template, :with_failed_task)
359
+ @invocation.job_category = @invocation.pattern_template_invocations.first.template.job_category
360
+ @invocation.targeting.hosts = @invocation.template_invocations.map(&:host)
361
+ @invocation.save!
362
+ JobInvocation.any_instance.expects(:generate_description)
363
+ JobInvocationComposer.any_instance
364
+ .expects(:validate_job_category)
365
+ .with(@invocation.job_category)
366
+ .returns(@invocation.job_category)
367
+ post :rerun, params: { :id => @invocation.id, :failed_only => true }
368
+ assert_response :success
369
+ result = ActiveSupport::JSON.decode(@response.body)
370
+ targeting = Targeting.find(result['targeting_id'])
371
+ hostnames = @invocation.template_invocations.map { |ti| ti.host.name }
372
+ assert_equal users(:admin).id, targeting.user_id
373
+ assert_equal "name ^ (#{hostnames.join(',')})", targeting.search_query
374
+ end
375
+
376
+ test 'should return 404 if template is not found' do
377
+ @invocation.job_category = 'Missing category'
378
+ @invocation.save!
379
+ post :rerun, params: { :id => @invocation.id }
380
+ assert_response 404
381
+ end
382
+
383
+ describe 'restricted access' do
384
+ setup do
385
+ @admin = FactoryBot.create(:user, mail: 'admin@test.foreman.com', admin: true)
386
+ @user = FactoryBot.create(:user, mail: 'user@test.foreman.com', admin: false)
387
+ @invocation = FactoryBot.create(:job_invocation, :with_template, :with_task, :with_unplanned_host)
388
+ @invocation2 = FactoryBot.create(:job_invocation, :with_template, :with_task, :with_unplanned_host)
389
+
390
+ @invocation.task.update(user: @admin)
391
+ @invocation2.task.update(user: @user)
392
+
393
+ setup_user 'view', 'hosts', nil, @user
394
+ setup_user 'view', 'job_invocations', 'user = current_user', @user
395
+ setup_user 'create', 'job_invocations', 'user = current_user', @user
396
+ setup_user 'cancel', 'job_invocations', 'user = current_user', @user
397
+ end
398
+
399
+ let(:host) { @invocation.targeting.hosts.first }
400
+ let(:host2) { @invocation2.targeting.hosts.first }
401
+
402
+ context 'without user filter' do
403
+ test '#index' do
404
+ get :index, session: prepare_user(@admin)
405
+ assert_response :success
406
+ assert JSON.parse(@response.body)['results'].size >= 2
407
+ end
408
+
409
+ test '#show' do
410
+ get :show, params: { id: @invocation2.id }, session: prepare_user(@admin)
411
+ assert_response :success
412
+ end
413
+
414
+ test '#output' do
415
+ get :output, params: { job_invocation_id: @invocation2.id, host_id: host2.id }, session: prepare_user(@admin)
416
+ assert_response :success
417
+ end
418
+ end
419
+
420
+ context 'with user filter' do
421
+ test '#index' do
422
+ get :index, session: prepare_user(@user)
423
+ assert_response :success
424
+ assert_equal 1, JSON.parse(@response.body)['results'].size
425
+ end
426
+
427
+ test '#show' do
428
+ get :show, params: { id: @invocation.id }, session: prepare_user(@user)
429
+ assert_response :not_found
430
+ end
431
+
432
+ test '#output' do
433
+ get :output, params: { job_invocation_id: @invocation.id, host_id: host.id }, session: prepare_user(@user)
434
+ assert_response :not_found
435
+ assert_includes @response.body, 'Job invocation not found'
436
+ end
437
+ end
438
+ end
439
+
440
+ def prepare_user(user)
441
+ User.current = user
442
+ set_session_user(user)
443
+ end
444
+ end
445
+ end
446
+ end
@@ -0,0 +1,110 @@
1
+ require 'test_plugin_helper'
2
+
3
+ module Api
4
+ module V2
5
+ class JobTemplatesControllerTest < ActionController::TestCase
6
+ setup do
7
+ @template = FactoryBot.create :job_template
8
+ end
9
+
10
+ test 'should get index' do
11
+ get :index
12
+ templates = ActiveSupport::JSON.decode(@response.body)
13
+ assert_not templates.empty?, 'Should response with template'
14
+ assert_response :success
15
+ end
16
+
17
+ test 'should get templates of give organization' do
18
+ @organization = FactoryBot.create(:organization)
19
+ @template.organizations << @organization
20
+ @template.save!
21
+ get :index, params: { :organization_id => @organization.id }
22
+ templates = ActiveSupport::JSON.decode(@response.body)
23
+ assert_not templates.empty?, 'Should respond with template'
24
+ assert_response :success
25
+ end
26
+
27
+ test 'should get template detail' do
28
+ get :show, params: { :id => @template.to_param }
29
+ assert_response :success
30
+ template = ActiveSupport::JSON.decode(@response.body)
31
+ assert_not template.empty?
32
+ assert_equal template['name'], @template.name
33
+ assert_not_nil template['created_at']
34
+ assert_not_nil template['updated_at']
35
+ end
36
+
37
+ test 'should create valid' do
38
+ JobTemplate.any_instance.stubs(:valid?).returns(true)
39
+ valid_attrs = { :template => 'This is a test template', :name => 'RandomName', :provider_type => 'ssh' }
40
+ post :create, params: { :job_template => valid_attrs }
41
+ template = ActiveSupport::JSON.decode(@response.body)
42
+ assert_equal template['name'], 'RandomName'
43
+ assert_response :success
44
+ end
45
+
46
+ test 'should not create invalid' do
47
+ post :create
48
+ assert_response :unprocessable_entity
49
+ end
50
+
51
+ test 'should update valid' do
52
+ JobTemplate.any_instance.stubs(:valid?).returns(true)
53
+ put :update, params: { :id => @template.to_param, :job_template => { :template => 'blah' } }
54
+ assert_response :ok
55
+ end
56
+
57
+ test 'should not update invalid' do
58
+ put :update, params: { :id => @template.to_param, :job_template => { :name => '' } }
59
+ assert_response :unprocessable_entity
60
+ end
61
+
62
+ test 'should update effective user' do
63
+ template = { name: @template.name, job_category: @template.job_category,
64
+ template: @template.template, provider_type: 'SSH',
65
+ effective_user_attributes: {
66
+ value: 'nobody',
67
+ overridable: true,
68
+ current_user: false,
69
+ } }
70
+ put :update, params: { id: @template.to_param, job_template: template }
71
+ assert_response :ok
72
+ end
73
+
74
+ test 'should destroy' do
75
+ delete :destroy, params: { :id => @template.to_param }
76
+ assert_response :ok
77
+ assert_not JobTemplate.exists?(@template.id)
78
+ end
79
+
80
+ test 'should clone template' do
81
+ post :clone, params: { :id => @template.to_param, :job_template => {:name => 'MyClone'} }
82
+ assert_response :success
83
+ template = ActiveSupport::JSON.decode(@response.body)
84
+ assert_equal(template['name'], 'MyClone')
85
+ assert_equal(template['template'], @template.template)
86
+ end
87
+
88
+ test 'clone name should not be blank' do
89
+ post :clone, params: { :id => @template.to_param, :job_template => {:name => ''} }
90
+ assert_response :unprocessable_entity
91
+ end
92
+
93
+ test 'should export template' do
94
+ get :export, params: { :id => @template.to_param }
95
+ User.current = users(:admin)
96
+ assert_equal @response.body, @template.to_erb
97
+ assert_response :success
98
+ end
99
+
100
+ test 'should import template' do
101
+ new_name = @template.name = "#{@template.name}_renamed"
102
+ erb_data = @template.to_erb
103
+ post :import, params: { :template => erb_data }
104
+ assert_response :success
105
+ assert JobTemplate.unscoped.find_by(name: new_name)
106
+ end
107
+ end
108
+
109
+ end
110
+ end
@@ -0,0 +1,73 @@
1
+ require 'test_plugin_helper'
2
+
3
+ module Api
4
+ module V2
5
+ # Tests for the extra methods to play roles on a Host
6
+ class RegistrationControllerTest < ActionController::TestCase
7
+ describe 'host registration' do
8
+ let(:organization) { FactoryBot.create(:organization) }
9
+ let(:tax_location) { FactoryBot.create(:location) }
10
+ let(:template) do
11
+ FactoryBot.create(
12
+ :provisioning_template,
13
+ template_kind: template_kinds(:host_init_config),
14
+ template: 'template content <%= @host.name %>',
15
+ locations: [tax_location],
16
+ organizations: [organization]
17
+ )
18
+ end
19
+ let(:os) do
20
+ FactoryBot.create(
21
+ :operatingsystem,
22
+ :with_associations,
23
+ family: 'Redhat',
24
+ provisioning_templates: [
25
+ template,
26
+ ]
27
+ )
28
+ end
29
+
30
+ let(:host_params) do
31
+ { host: { name: 'centos-test.example.com',
32
+ managed: false, build: false,
33
+ organization_id: organization.id,
34
+ location_id: tax_location.id,
35
+ operatingsystem_id: os.id } }
36
+ end
37
+
38
+ describe 'remote_execution_interface' do
39
+ setup do
40
+ Setting[:default_host_init_config_template] = template.name
41
+ @host = Host.create(host_params[:host])
42
+ @interface0 = FactoryBot.create(:nic_managed, host: @host, identifier: 'dummy0', execution: false)
43
+ end
44
+
45
+ test 'with existing interface' do
46
+ params = host_params.merge(remote_execution_interface: @interface0.identifier)
47
+
48
+ post :host, params: params, session: set_session_user
49
+ assert_response :success
50
+ assert @interface0.reload.execution
51
+ end
52
+
53
+ test 'with not-existing interface' do
54
+ params = host_params.merge(remote_execution_interface: 'dummy999')
55
+
56
+ post :host, params: params, session: set_session_user
57
+ assert_response :not_found
58
+ end
59
+
60
+ test 'with multiple interfaces' do
61
+ interface1 = FactoryBot.create(:nic_managed, host: @host, identifier: 'dummy1', execution: false)
62
+ params = host_params.merge(remote_execution_interface: interface1.identifier)
63
+
64
+ post :host, params: params, session: set_session_user
65
+ assert_response :success
66
+ refute @interface0.reload.execution
67
+ assert interface1.reload.execution
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,34 @@
1
+ require 'test_plugin_helper'
2
+
3
+ module Api
4
+ module V2
5
+ class RemoteExecutionFeaturesControllerTest < ActionController::TestCase
6
+ setup do
7
+ @remote_execution_feature = RemoteExecutionFeature.register(:my_awesome_feature, 'My awesome feature',
8
+ :description => 'You will not believe what it does',
9
+ :provided_inputs => ['awesomeness_level'])
10
+ @template = FactoryBot.create(:job_template, :with_input)
11
+ end
12
+
13
+ test 'should get index' do
14
+ get :index
15
+ remote_execution_features = ActiveSupport::JSON.decode(@response.body)
16
+ assert_not remote_execution_features.empty?, 'Should respond with input sets'
17
+ assert_response :success
18
+ end
19
+
20
+ test 'should get input set detail' do
21
+ get :show, params: { :id => @remote_execution_feature.to_param }
22
+ assert_response :success
23
+ remote_execution_feature = ActiveSupport::JSON.decode(@response.body)
24
+ assert_not remote_execution_feature.empty?
25
+ assert_equal remote_execution_feature['name'], @remote_execution_feature.name
26
+ end
27
+
28
+ test 'should update valid' do
29
+ put :update, params: { :id => @remote_execution_feature.to_param, :job_template_id => @template.id }
30
+ assert_response :ok
31
+ end
32
+ end
33
+ end
34
+ end