foreman_remote_execution 14.0.2 → 14.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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/job_invocations_controller.rb +34 -17
  3. data/app/helpers/remote_execution_helper.rb +2 -2
  4. data/app/lib/actions/remote_execution/proxy_action.rb +10 -5
  5. data/app/lib/actions/remote_execution/run_host_job.rb +1 -1
  6. data/app/lib/actions/remote_execution/template_invocation_progress_logging.rb +2 -3
  7. data/app/views/api/v2/job_invocations/hosts.json.rabl +15 -0
  8. data/config/routes.rb +1 -0
  9. data/db/migrate/20240312133027_extend_template_invocation_events.rb +19 -0
  10. data/lib/foreman_remote_execution/version.rb +1 -1
  11. data/webpack/JobInvocationDetail/JobInvocationActions.js +1 -1
  12. data/webpack/JobInvocationDetail/JobInvocationConstants.js +84 -0
  13. data/webpack/JobInvocationDetail/JobInvocationDetail.scss +0 -1
  14. data/webpack/JobInvocationDetail/JobInvocationHostTable.js +210 -0
  15. data/webpack/JobInvocationDetail/JobInvocationSelectors.js +2 -2
  16. data/webpack/JobInvocationDetail/__tests__/MainInformation.test.js +5 -1
  17. data/webpack/JobInvocationDetail/__tests__/fixtures.js +9 -0
  18. data/webpack/JobInvocationDetail/index.js +56 -34
  19. data/webpack/__mocks__/foremanReact/components/HostDetails/DetailsCard/DefaultLoaderEmptyState.js +1 -2
  20. data/webpack/react_app/components/RecentJobsCard/JobStatusIcon.js +38 -7
  21. data/webpack/react_app/components/RecentJobsCard/constants.js +4 -0
  22. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/HostStatus.test.js.snap +1 -1
  23. data/webpack/react_app/components/TargetingHosts/components/HostStatus.js +6 -6
  24. metadata +6 -94
  25. data/.babelrc.js +0 -3
  26. data/.eslintignore +0 -3
  27. data/.eslintrc +0 -13
  28. data/.github/workflows/js_ci.yml +0 -32
  29. data/.github/workflows/release.yml +0 -16
  30. data/.github/workflows/ruby_ci.yml +0 -19
  31. data/.gitignore +0 -19
  32. data/.packit.yaml +0 -45
  33. data/.prettierrc +0 -4
  34. data/.rubocop.yml +0 -105
  35. data/.rubocop_todo.yml +0 -516
  36. data/.tx/config +0 -10
  37. data/Gemfile +0 -5
  38. data/app/mailers/.gitkeep +0 -0
  39. data/app/views/dashboard/.gitkeep +0 -0
  40. data/foreman_remote_execution.gemspec +0 -33
  41. data/jsconfig.json +0 -8
  42. data/test/benchmark/run_hosts_job_benchmark.rb +0 -70
  43. data/test/benchmark/targeting_benchmark.rb +0 -31
  44. data/test/factories/foreman_remote_execution_factories.rb +0 -147
  45. data/test/functional/api/v2/foreign_input_sets_controller_test.rb +0 -58
  46. data/test/functional/api/v2/job_invocations_controller_test.rb +0 -446
  47. data/test/functional/api/v2/job_templates_controller_test.rb +0 -110
  48. data/test/functional/api/v2/registration_controller_test.rb +0 -73
  49. data/test/functional/api/v2/remote_execution_features_controller_test.rb +0 -34
  50. data/test/functional/api/v2/template_invocations_controller_test.rb +0 -33
  51. data/test/functional/cockpit_controller_test.rb +0 -16
  52. data/test/functional/job_invocations_controller_test.rb +0 -132
  53. data/test/functional/job_templates_controller_test.rb +0 -31
  54. data/test/functional/ui_job_wizard_controller_test.rb +0 -16
  55. data/test/graphql/mutations/job_invocations/create_test.rb +0 -58
  56. data/test/graphql/queries/job_invocation_query_test.rb +0 -31
  57. data/test/graphql/queries/job_invocations_query_test.rb +0 -35
  58. data/test/helpers/remote_execution_helper_test.rb +0 -46
  59. data/test/support/remote_execution_helper.rb +0 -5
  60. data/test/test_plugin_helper.rb +0 -9
  61. data/test/unit/actions/run_host_job_test.rb +0 -115
  62. data/test/unit/actions/run_hosts_job_test.rb +0 -214
  63. data/test/unit/api_params_test.rb +0 -25
  64. data/test/unit/concerns/foreman_tasks_cleaner_extensions_test.rb +0 -29
  65. data/test/unit/concerns/host_extensions_test.rb +0 -219
  66. data/test/unit/concerns/nic_extensions_test.rb +0 -9
  67. data/test/unit/execution_task_status_mapper_test.rb +0 -92
  68. data/test/unit/input_template_renderer_test.rb +0 -503
  69. data/test/unit/job_invocation_composer_test.rb +0 -974
  70. data/test/unit/job_invocation_report_template_test.rb +0 -60
  71. data/test/unit/job_invocation_test.rb +0 -232
  72. data/test/unit/job_template_effective_user_test.rb +0 -37
  73. data/test/unit/job_template_test.rb +0 -316
  74. data/test/unit/remote_execution_feature_test.rb +0 -86
  75. data/test/unit/remote_execution_provider_test.rb +0 -298
  76. data/test/unit/renderer_scope_input_test.rb +0 -49
  77. data/test/unit/targeting_test.rb +0 -206
  78. data/test/unit/template_invocation_input_value_test.rb +0 -38
@@ -1,503 +0,0 @@
1
- require 'test_plugin_helper'
2
-
3
- class InputTemplateRendererTest < ActiveSupport::TestCase
4
- let(:host) { FactoryBot.build(:host) }
5
-
6
- context 'renderer for simple template without inputs' do
7
- let(:renderer) { InputTemplateRenderer.new(FactoryBot.build(:job_template, :template => 'id <%= preview? %>')) }
8
-
9
- it 'should render the content' do
10
- assert_equal 'id false', renderer.render
11
- end
12
-
13
- it 'should render preview' do
14
- assert_equal 'id true', renderer.preview
15
- end
16
-
17
- it 'should allow accessing current_user' do
18
- setup_user(:view_job_templates)
19
- renderer = InputTemplateRenderer.new(FactoryBot.build(:job_template, :template => "They call me '<%= current_user %>'"))
20
- assert_equal "They call me '#{User.current.login}'", renderer.preview
21
- end
22
- end
23
-
24
- context 'renderer for template with user input used' do
25
- let(:template) { FactoryBot.build(:job_template, :template => 'service restart <%= input("service_name") -%>') }
26
- let(:renderer) { InputTemplateRenderer.new(template) }
27
-
28
- context 'but without input defined' do
29
- describe 'rendering' do
30
- let(:result) { renderer.render }
31
- it 'should return false' do
32
- refute result
33
- end
34
-
35
- it 'should register an error' do
36
- result # let is lazy
37
- assert_not_nil renderer.error_message
38
- assert_not_empty renderer.error_message
39
- end
40
- end
41
-
42
- describe 'preview' do
43
- let(:result) { renderer.preview }
44
- it 'should return false' do
45
- refute result
46
- end
47
-
48
- it 'should register an error' do
49
- result # let is lazy
50
- assert_not_nil renderer.error_message
51
- assert_not_empty renderer.error_message
52
- end
53
- end
54
- end
55
-
56
- context 'with matching input defined' do
57
-
58
- let(:job_invocation) { FactoryBot.create(:job_invocation) }
59
- let(:template_invocation) { FactoryBot.build(:template_invocation, :template => template) }
60
- let(:result) { renderer.render }
61
-
62
- before do
63
- template.template_inputs << FactoryBot.build(:template_input, :name => 'service_name', :input_type => 'user')
64
- job_invocation.template_invocations << template_invocation
65
- end
66
-
67
- describe 'rendering' do
68
- it 'can preview' do
69
- assert_equal 'service restart $USER_INPUT[service_name]', renderer.preview
70
- end
71
-
72
- context 'with invocation specified and a required input' do
73
- before do
74
- template.template_inputs.first.update(:required => true)
75
- template_invocation.reload
76
- renderer.invocation = template_invocation
77
- end
78
-
79
- it 'cannot render the content' do
80
- assert_not result
81
- refute_nil renderer.error_message
82
- refute_empty renderer.error_message
83
- end
84
- end
85
-
86
- context 'with invocation specified' do
87
- before do
88
- FactoryBot.create(:template_invocation_input_value,
89
- :template_invocation => template_invocation,
90
- :template_input => template.template_inputs.first,
91
- :value => 'foreman')
92
- template_invocation.reload # need to get input_values findable
93
- renderer.invocation = template_invocation
94
- end
95
-
96
- it 'can render with job invocation with corresponding value' do
97
- assert_equal 'service restart foreman', renderer.render
98
- end
99
- end
100
-
101
- it 'renders even without an input value' do
102
- renderer.invocation = template_invocation
103
- assert_equal 'service restart ', renderer.render
104
- end
105
-
106
- describe 'with circular reference' do
107
- let(:recursive_template_with_inputs) do
108
- FactoryBot.create(:job_template, :name => 'test', :template => 'test')
109
- end
110
-
111
- let(:template_with_inputs) do
112
- FactoryBot.create(:job_template, :template => 'test').tap do |template|
113
- template.foreign_input_sets << FactoryBot.build(:foreign_input_set, :target_template => recursive_template_with_inputs)
114
- end
115
- end
116
-
117
- let(:recursive_template_without_inputs) do
118
- FactoryBot.create(:job_template, :name => 'recursive template', :template => '<%= render_template("template with inputs", "action" => "install") %>')
119
- end
120
-
121
- let(:template_without_inputs) do
122
- FactoryBot.create(:job_template, :name => 'template with inputs', :template => "<%= render_template('#{recursive_template_without_inputs.name}') %>")
123
- end
124
-
125
- before do
126
- User.current = users :admin
127
- end
128
-
129
- it 'handles circular references in templates' do
130
- renderer.invocation = FactoryBot.build(:template_invocation, :template => template_without_inputs)
131
- renderer.template = template_without_inputs
132
- assert_not renderer.render
133
- assert_includes renderer.error_message, 'Recursive rendering of templates detected'
134
- end
135
-
136
- it 'handles circular references in inputs' do
137
- assert_raises(ActiveRecord::RecordInvalid) do
138
- input_set = FactoryBot.build(:foreign_input_set, :target_template => template_with_inputs, :include_all => false,
139
- :include => 'package, debug', :exclude => 'action,debug')
140
- recursive_template_with_inputs.foreign_input_sets << input_set
141
- recursive_template_with_inputs.save!
142
- end
143
- end
144
- end
145
- end
146
- end
147
-
148
- context 'renderer for template with input set and render_template' do
149
- let(:command_template) do
150
- FactoryBot.build(:job_template, :name => 'command action', :template => '<%= input("command") -%>').tap do |template|
151
- template.template_inputs << FactoryBot.build(:template_input, :name => 'command', :input_type => 'user')
152
- template.template_inputs << FactoryBot.build(:template_input, :name => 'debug', :input_type => 'user')
153
- end
154
- end
155
-
156
- let(:package_template) do
157
- FactoryBot.build(:job_template, :name => 'package action', :template => <<-TEMPLATE.strip_heredoc) do |template|
158
- <%= render_template("command action", "command" => "yum -y \#{ input("action") } \#{ input('package') }") -%>
159
- TEMPLATE
160
- template.template_inputs << FactoryBot.build(:template_input, :name => 'package', :input_type => 'user')
161
- template.template_inputs << FactoryBot.build(:template_input, :name => 'action', :input_type => 'user')
162
- template.foreign_input_sets << FactoryBot.build(:foreign_input_set, :target_template => command_template, :include_all => true, :exclude => 'command')
163
- end
164
- end
165
-
166
- let(:template) do
167
- FactoryBot.create(:job_template,
168
- :template => '<%= render_template("package action", { :action => "install" }, { :with_foreign_input_set => true }) %>').tap do |template|
169
- template.foreign_input_sets << FactoryBot.build(:foreign_input_set, :target_template => package_template, :include_all => true, :exclude => 'action')
170
- end
171
- end
172
-
173
- let(:job_invocation) { FactoryBot.create(:job_invocation) }
174
- let(:template_invocation) { FactoryBot.build(:template_invocation, :template => template) }
175
- let(:renderer) { InputTemplateRenderer.new(template) }
176
- let(:result) { renderer.render }
177
-
178
- before do
179
- User.current = users :admin
180
- command_template.save!
181
- package_template.save!
182
- job_invocation.template_invocations << template_invocation
183
- end
184
-
185
- describe 'foreign input set' do
186
- describe 'with include_all' do
187
- let(:template) do
188
- FactoryBot.create(:job_template, :template => '<%= render_template("package action", "action" => "install") %>').tap do |template|
189
- template.foreign_input_sets << FactoryBot.build(:foreign_input_set, :target_template => package_template, :include_all => true)
190
- end
191
- end
192
-
193
- let(:template_2) do
194
- FactoryBot.create(:job_template, :template => '<%= render_template("package action", "action" => "install") %>').tap do |template|
195
- template.foreign_input_sets << FactoryBot.build(:foreign_input_set,
196
- :target_template => package_template, :include_all => true, :include => '', :exclude => '')
197
- end
198
- end
199
-
200
- it 'includes all inputs from the imported template' do
201
- assert_equal ['action', 'debug', 'package'], template.template_inputs_with_foreign.map(&:name).sort
202
- assert_equal ['action', 'debug', 'package'], template_2.template_inputs_with_foreign.map(&:name).sort
203
- end
204
- end
205
-
206
- describe 'with include_all and some excludes' do
207
- let(:template) do
208
- FactoryBot.create(:job_template, :template => '<%= render_template("package action", "action" => "install") %>').tap do |template|
209
- template.foreign_input_sets << FactoryBot.build(:foreign_input_set, :target_template => package_template, :include_all => true, :exclude => 'action,debug')
210
- end
211
- end
212
-
213
- it 'includes all inputs from the imported template except the listed once' do
214
- assert_equal ['package'], template.template_inputs_with_foreign.map(&:name).sort
215
- end
216
- end
217
-
218
- describe 'with some includes and some excludes' do
219
- let(:template) do
220
- FactoryBot.create(:job_template, :template => '<%= render_template("package action", "action" => "install") %>').tap do |template|
221
- template.foreign_input_sets << FactoryBot.build(:foreign_input_set, :target_template => package_template, :include_all => false,
222
- :include => 'package, debug', :exclude => 'action,debug')
223
- end
224
- end
225
-
226
- it 'includes all inputs from the imported template' do
227
- assert_equal ['package'], template.template_inputs_with_foreign.map(&:name).sort
228
- end
229
- end
230
- end
231
-
232
- context 'with invocation specified' do
233
- before do
234
- FactoryBot.create(:template_invocation_input_value,
235
- :template_invocation => template_invocation,
236
- :template_input => template.template_inputs_with_foreign.find { |input| input.name == 'package' },
237
- :value => 'zsh')
238
- renderer.invocation = template_invocation
239
- renderer.invocation.reload
240
- end
241
-
242
- it 'can render with job invocation with corresponding value' do
243
- rendered = renderer.render
244
- assert_nil renderer.error_message
245
- assert_equal 'yum -y install zsh', rendered
246
- end
247
- end
248
-
249
- context 'with explicitly specifying inputs' do
250
- let(:template) do
251
- FactoryBot.create(:job_template,
252
- :template => '<%= render_template("package action", {"action" => "install", :package => "zsh"}) %>')
253
- end
254
-
255
- before do
256
- template_invocation.reload
257
- renderer.invocation = template_invocation
258
- end
259
-
260
- it 'can render with job invocation with corresponding value' do
261
- rendered = renderer.render
262
- assert_nil renderer.error_message
263
- assert_equal 'yum -y install zsh', rendered
264
- end
265
- end
266
-
267
- it 'renders even without an input value' do
268
- renderer.invocation = template_invocation
269
- rendered = renderer.render
270
- assert_nil renderer.error_message
271
- assert_equal 'yum -y install ', rendered
272
- end
273
- end
274
-
275
- context 'with options specified' do
276
- let(:job_invocation) { FactoryBot.create(:job_invocation) }
277
- let(:template_invocation) { FactoryBot.build(:template_invocation, :template => template) }
278
- let(:result) { renderer.render }
279
- let(:required) { false }
280
- let(:input) do
281
- FactoryBot.create(:template_invocation_input_value,
282
- :template_invocation => template_invocation,
283
- :template_input => template.template_inputs.first,
284
- :value => 'foreman')
285
- end
286
-
287
- before do
288
- template.template_inputs << FactoryBot.build(:template_input, :name => 'service_name', :input_type => 'user', :options => "httpd\nforeman", :required => required)
289
- job_invocation.template_invocations << template_invocation
290
- input
291
- template_invocation.reload
292
- renderer.invocation = template_invocation
293
- end
294
-
295
- context 'with a valid input defined' do
296
- context 'with an optional input' do
297
- it 'can render with job invocation with corresponding value' do
298
- assert_equal 'service restart foreman', result
299
- end
300
- end
301
-
302
- context 'with required input' do
303
- let(:required) { true }
304
-
305
- it 'renders the template when the input is provided' do
306
- assert_equal 'service restart foreman', result
307
- end
308
- end
309
- end
310
-
311
- context 'without provided input' do
312
- let(:input) { nil }
313
-
314
- context 'with optional input' do
315
- it 'renders the template' do
316
- assert_equal 'service restart ', result
317
- end
318
- end
319
-
320
- context 'with required input' do
321
- let(:required) { true }
322
-
323
- it 'renders the template' do
324
- result
325
- assert_match(/Value for required input '.*' was not specified/, renderer.error_message)
326
- end
327
- end
328
- end
329
- end
330
- end
331
-
332
- context 'renderer for template with fact input used' do
333
- let(:template) { FactoryBot.build(:job_template, :template => 'echo <%= input("issue") -%> > /etc/issue') }
334
- let(:renderer) { InputTemplateRenderer.new(template) }
335
-
336
- context 'with matching input defined' do
337
- before { renderer.template.template_inputs<< FactoryBot.build(:template_input, :name => 'issue', :input_type => 'fact', :fact_name => 'issue', :required => true) }
338
- let(:result) { renderer.render }
339
-
340
- describe 'rendering' do
341
- it 'can\'t render the content without host since we don\'t have facts' do
342
- assert_not result
343
- end
344
-
345
- it 'registers an error' do
346
- result # let is lazy
347
- assert_not_nil renderer.error_message
348
- assert_not_empty renderer.error_message
349
- end
350
-
351
- context 'with host specified' do
352
- before { renderer.host = FactoryBot.create(:host) }
353
-
354
- describe 'rendering' do
355
- it 'can\'t render the content without host since we don\'t have fact value' do
356
- assert_not result
357
- end
358
-
359
- it 'registers an error' do
360
- result # let is lazy
361
- assert_not_nil renderer.error_message
362
- assert_not_empty renderer.error_message
363
- end
364
- end
365
-
366
- describe 'preview' do
367
- it 'should render preview' do
368
- assert_equal 'echo $FACT_INPUT[issue] > /etc/issue', renderer.preview
369
- end
370
- end
371
-
372
- context 'with existing fact' do
373
- let(:fact) { FactoryBot.create(:fact_name, :name => 'issue') }
374
-
375
- describe 'rendering' do
376
- it 'can\'t render the content without host since we don\'t have fact value' do
377
- fact # let is lazy
378
- assert_not result
379
- end
380
-
381
- it 'registers an error' do
382
- result # let is lazy
383
- assert_not_nil renderer.error_message
384
- assert_not_empty renderer.error_message
385
- end
386
- end
387
-
388
- describe 'preview' do
389
- it 'should render preview' do
390
- assert_equal 'echo $FACT_INPUT[issue] > /etc/issue', renderer.preview
391
- end
392
- end
393
-
394
- context 'with fact issue value' do
395
- before { FactoryBot.create(:fact_value, :host => renderer.host, :fact_name => fact, :value => 'banner') }
396
-
397
- let(:result) { renderer.render }
398
-
399
- it 'can render with job invocation with corresponding value' do
400
- assert_equal 'echo banner > /etc/issue', result
401
- end
402
- end
403
- end
404
- end
405
- end
406
-
407
- describe 'preview' do
408
- it 'should render preview' do
409
- assert_equal 'echo $FACT_INPUT[issue] > /etc/issue', renderer.preview
410
- end
411
-
412
- context 'with host specified' do
413
- before do
414
- host = FactoryBot.create(:host)
415
- fact = FactoryBot.create(:fact_name, :name => 'issue')
416
- FactoryBot.create(:fact_value, :host => host, :fact_name => fact, :value => 'banner')
417
- renderer.host = host
418
- end
419
-
420
- let(:result) { renderer.render }
421
-
422
- it 'uses the value even in preview' do
423
- assert_equal 'echo banner > /etc/issue', result
424
- end
425
- end
426
- end
427
- end
428
- end
429
-
430
- context 'renderer for template with variable input used' do
431
- let(:template) { FactoryBot.build(:job_template, :template => 'echo <%= input("client_key") -%> > /etc/chef/client.pem') }
432
- let(:renderer) { InputTemplateRenderer.new(template) }
433
-
434
- context 'with matching input defined' do
435
- before { renderer.template.template_inputs<< FactoryBot.build(:template_input, :name => 'client_key', :input_type => 'variable', :variable_name => 'client_key') }
436
- let(:result) { renderer.render }
437
-
438
- describe 'rendering' do
439
- it 'can\'t render the content without host since we don\'t have host so no classification' do
440
- assert_not result
441
- end
442
-
443
- it 'registers an error' do
444
- result # let is lazy
445
- refute_nil renderer.error_message
446
- refute_empty renderer.error_message
447
- end
448
-
449
- context 'with host specified' do
450
- before { User.current = FactoryBot.build(:user, :admin) }
451
- after { User.current = nil }
452
-
453
- before { renderer.host = FactoryBot.create(:host) }
454
-
455
- describe 'rendering' do
456
- it 'can\'t render the content without host since we don\'t have variable value in classification' do
457
- assert_not result
458
- end
459
-
460
- it 'registers an error' do
461
- result # let is lazy
462
- refute_nil renderer.error_message
463
- refute_empty renderer.error_message
464
- end
465
- end
466
-
467
- describe 'preview' do
468
- it 'should render preview' do
469
- assert_equal 'echo $VARIABLE_INPUT[client_key] > /etc/chef/client.pem', renderer.preview
470
- end
471
- end
472
-
473
-
474
- context 'with existing variable implemented as host parameter' do
475
- let(:parameter) { FactoryBot.create(:host_parameter, :host => renderer.host, :name => 'client_key', :value => 'RSA KEY') }
476
-
477
- describe 'rendering' do
478
- it 'renders the value from host parameter' do
479
- parameter
480
- renderer.host.reload
481
- assert_equal 'echo RSA KEY > /etc/chef/client.pem', result
482
- end
483
- end
484
-
485
- describe 'preview' do
486
- it 'should render preview' do
487
- parameter
488
- renderer.host.reload
489
- assert_equal 'echo RSA KEY > /etc/chef/client.pem', renderer.preview
490
- end
491
- end
492
- end
493
- end
494
-
495
- describe 'preview' do
496
- it 'should render preview' do
497
- assert_equal 'echo $VARIABLE_INPUT[client_key] > /etc/chef/client.pem', renderer.preview
498
- end
499
- end
500
- end
501
- end
502
- end
503
- end