foreman_remote_execution 4.6.0 → 5.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby_ci.yml +7 -0
  3. data/.rubocop_todo.yml +1 -0
  4. data/app/controllers/api/v2/job_invocations_controller.rb +16 -1
  5. data/app/controllers/job_invocations_controller.rb +1 -1
  6. data/app/controllers/ui_job_wizard_controller.rb +21 -2
  7. data/app/graphql/mutations/job_invocations/create.rb +43 -0
  8. data/app/graphql/types/job_invocation.rb +16 -0
  9. data/app/graphql/types/job_invocation_input.rb +13 -0
  10. data/app/graphql/types/recurrence_input.rb +8 -0
  11. data/app/graphql/types/scheduling_input.rb +6 -0
  12. data/app/graphql/types/targeting_enum.rb +7 -0
  13. data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +5 -1
  14. data/app/helpers/remote_execution_helper.rb +9 -3
  15. data/app/lib/actions/remote_execution/run_host_job.rb +10 -1
  16. data/app/lib/actions/remote_execution/run_hosts_job.rb +58 -4
  17. data/app/mailers/rex_job_mailer.rb +15 -0
  18. data/app/models/concerns/foreman_remote_execution/host_extensions.rb +10 -0
  19. data/app/models/concerns/foreman_remote_execution/smart_proxy_extensions.rb +6 -0
  20. data/app/models/host_proxy_invocation.rb +4 -0
  21. data/app/models/host_status/execution_status.rb +3 -3
  22. data/app/models/job_invocation.rb +12 -5
  23. data/app/models/job_invocation_composer.rb +25 -17
  24. data/app/models/job_template.rb +1 -1
  25. data/app/models/remote_execution_feature.rb +5 -1
  26. data/app/models/remote_execution_provider.rb +18 -2
  27. data/app/models/rex_mail_notification.rb +13 -0
  28. data/app/models/targeting.rb +7 -3
  29. data/app/services/ui_notifications/remote_execution_jobs/base_job_finish.rb +2 -1
  30. data/app/views/dashboard/_latest-jobs.html.erb +21 -0
  31. data/app/views/job_invocations/index.html.erb +1 -1
  32. data/app/views/job_invocations/refresh.js.erb +1 -0
  33. data/app/views/rex_job_mailer/job_finished.html.erb +24 -0
  34. data/app/views/rex_job_mailer/job_finished.text.erb +9 -0
  35. data/app/views/template_invocations/show.html.erb +2 -1
  36. data/app/views/templates/ssh/module_action.erb +1 -0
  37. data/app/views/templates/ssh/power_action.erb +2 -0
  38. data/app/views/templates/ssh/puppet_run_once.erb +1 -0
  39. data/config/routes.rb +1 -0
  40. data/db/migrate/2021051713291621250977_add_host_proxy_invocations.rb +12 -0
  41. data/db/migrate/20210816100932_rex_setting_category_to_dsl.rb +5 -0
  42. data/db/seeds.d/50-notification_blueprints.rb +14 -0
  43. data/db/seeds.d/95-mail_notifications.rb +24 -0
  44. data/foreman_remote_execution.gemspec +2 -3
  45. data/lib/foreman_remote_execution/engine.rb +114 -8
  46. data/lib/foreman_remote_execution/version.rb +1 -1
  47. data/package.json +9 -7
  48. data/test/functional/api/v2/job_invocations_controller_test.rb +20 -0
  49. data/test/functional/cockpit_controller_test.rb +0 -1
  50. data/test/graphql/mutations/job_invocations/create.rb +58 -0
  51. data/test/graphql/queries/job_invocation_query_test.rb +31 -0
  52. data/test/graphql/queries/job_invocations_query_test.rb +35 -0
  53. data/test/helpers/remote_execution_helper_test.rb +0 -1
  54. data/test/unit/actions/run_host_job_test.rb +21 -0
  55. data/test/unit/actions/run_hosts_job_test.rb +99 -4
  56. data/test/unit/concerns/host_extensions_test.rb +40 -7
  57. data/test/unit/input_template_renderer_test.rb +1 -89
  58. data/test/unit/job_invocation_composer_test.rb +18 -18
  59. data/test/unit/job_invocation_report_template_test.rb +16 -13
  60. data/test/unit/job_invocation_test.rb +1 -1
  61. data/test/unit/job_template_effective_user_test.rb +0 -4
  62. data/test/unit/remote_execution_provider_test.rb +46 -4
  63. data/test/unit/targeting_test.rb +68 -1
  64. data/webpack/JobWizard/JobWizard.js +158 -24
  65. data/webpack/JobWizard/JobWizard.scss +93 -1
  66. data/webpack/JobWizard/JobWizardConstants.js +54 -0
  67. data/webpack/JobWizard/JobWizardSelectors.js +41 -0
  68. data/webpack/JobWizard/__tests__/fixtures.js +188 -3
  69. data/webpack/JobWizard/__tests__/integration.test.js +41 -106
  70. data/webpack/JobWizard/__tests__/validation.test.js +141 -0
  71. data/webpack/JobWizard/autofill.js +38 -0
  72. data/webpack/JobWizard/index.js +7 -0
  73. data/webpack/JobWizard/steps/AdvancedFields/AdvancedFields.js +41 -10
  74. data/webpack/JobWizard/steps/AdvancedFields/DescriptionField.js +90 -0
  75. data/webpack/JobWizard/steps/AdvancedFields/Fields.js +116 -55
  76. data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +354 -16
  77. data/webpack/JobWizard/steps/AdvancedFields/__tests__/__snapshots__/AdvancedFields.test.js.snap +79 -246
  78. data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.js +5 -2
  79. data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.test.js +123 -51
  80. data/webpack/JobWizard/steps/CategoryAndTemplate/index.js +3 -2
  81. data/webpack/JobWizard/steps/HostsAndInputs/HostPreviewModal.js +62 -0
  82. data/webpack/JobWizard/steps/HostsAndInputs/HostSearch.js +54 -0
  83. data/webpack/JobWizard/steps/HostsAndInputs/SelectAPI.js +33 -0
  84. data/webpack/JobWizard/steps/HostsAndInputs/SelectGQL.js +52 -0
  85. data/webpack/JobWizard/steps/HostsAndInputs/SelectedChips.js +100 -0
  86. data/webpack/JobWizard/steps/HostsAndInputs/TemplateInputs.js +23 -0
  87. data/webpack/JobWizard/steps/HostsAndInputs/__tests__/HostsAndInputs.test.js +151 -0
  88. data/webpack/JobWizard/steps/HostsAndInputs/__tests__/TemplateInputs.test.js +53 -0
  89. data/webpack/JobWizard/steps/HostsAndInputs/buildHostQuery.js +18 -0
  90. data/webpack/JobWizard/steps/HostsAndInputs/hostgroups.gql +8 -0
  91. data/webpack/JobWizard/steps/HostsAndInputs/hosts.gql +8 -0
  92. data/webpack/JobWizard/steps/HostsAndInputs/index.js +214 -0
  93. data/webpack/JobWizard/steps/ReviewDetails/index.js +193 -0
  94. data/webpack/JobWizard/steps/Schedule/PurposeField.js +31 -0
  95. data/webpack/JobWizard/steps/Schedule/QueryType.js +51 -0
  96. data/webpack/JobWizard/steps/Schedule/RepeatCron.js +53 -0
  97. data/webpack/JobWizard/steps/Schedule/RepeatDaily.js +37 -0
  98. data/webpack/JobWizard/steps/Schedule/RepeatHour.js +54 -0
  99. data/webpack/JobWizard/steps/Schedule/RepeatMonth.js +46 -0
  100. data/webpack/JobWizard/steps/Schedule/RepeatOn.js +125 -0
  101. data/webpack/JobWizard/steps/Schedule/RepeatWeek.js +70 -0
  102. data/webpack/JobWizard/steps/Schedule/ScheduleType.js +28 -0
  103. data/webpack/JobWizard/steps/Schedule/StartEndDates.js +106 -0
  104. data/webpack/JobWizard/steps/Schedule/__tests__/Schedule.test.js +402 -0
  105. data/webpack/JobWizard/steps/Schedule/__tests__/StartEndDates.test.js +32 -0
  106. data/webpack/JobWizard/steps/Schedule/index.js +178 -0
  107. data/webpack/JobWizard/steps/form/DateTimePicker.js +126 -0
  108. data/webpack/JobWizard/steps/form/FormHelpers.js +5 -0
  109. data/webpack/JobWizard/steps/form/Formatter.js +181 -0
  110. data/webpack/JobWizard/steps/form/NumberInput.js +36 -0
  111. data/webpack/JobWizard/steps/form/ResourceSelect.js +29 -0
  112. data/webpack/JobWizard/steps/form/SearchSelect.js +121 -0
  113. data/webpack/JobWizard/steps/form/SelectField.js +28 -5
  114. data/webpack/JobWizard/steps/form/WizardTitle.js +14 -0
  115. data/webpack/JobWizard/steps/form/__tests__/SelectSearch.test.js +33 -0
  116. data/webpack/JobWizard/submit.js +120 -0
  117. data/webpack/JobWizard/validation.js +53 -0
  118. data/webpack/__mocks__/foremanReact/Root/Context/ForemanContext/index.js +2 -0
  119. data/webpack/__mocks__/foremanReact/common/I18n.js +2 -0
  120. data/webpack/__mocks__/foremanReact/components/AutoComplete/AutoCompleteActions.js +1 -0
  121. data/webpack/__mocks__/foremanReact/components/AutoComplete/AutoCompleteConstants.js +1 -0
  122. data/webpack/__mocks__/foremanReact/components/SearchBar.js +18 -1
  123. data/webpack/__mocks__/foremanReact/routes/RouterSelector.js +1 -0
  124. data/webpack/helpers.js +1 -0
  125. data/webpack/react_app/components/RecentJobsCard/JobStatusIcon.js +43 -0
  126. data/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js +73 -66
  127. data/webpack/react_app/components/RecentJobsCard/RecentJobsTable.js +98 -0
  128. data/webpack/react_app/components/RecentJobsCard/constants.js +11 -0
  129. data/webpack/react_app/components/RecentJobsCard/styles.scss +11 -0
  130. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap +1 -0
  131. data/webpack/react_app/extend/fillRecentJobsCard.js +1 -1
  132. metadata +71 -16
  133. data/app/models/concerns/foreman_remote_execution/orchestration/ssh.rb +0 -70
  134. data/app/models/setting/remote_execution.rb +0 -88
  135. data/test/models/orchestration/ssh_test.rb +0 -56
  136. data/webpack/JobWizard/__tests__/JobWizard.test.js +0 -13
  137. data/webpack/JobWizard/__tests__/__snapshots__/JobWizard.test.js.snap +0 -32
  138. data/webpack/JobWizard/steps/CategoryAndTemplate/__snapshots__/CategoryAndTemplate.test.js.snap +0 -113
  139. data/webpack/JobWizard/steps/form/__tests__/GroupedSelectField.test.js +0 -38
  140. data/webpack/JobWizard/steps/form/__tests__/SelectField.test.js +0 -23
  141. data/webpack/JobWizard/steps/form/__tests__/__snapshots__/GroupedSelectField.test.js.snap +0 -37
  142. data/webpack/JobWizard/steps/form/__tests__/__snapshots__/SelectField.test.js.snap +0 -23
  143. data/webpack/react_app/components/RecentJobsCard/styles.css +0 -15
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_remote_execution
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.6.0
4
+ version: 5.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Remote Execution team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-07 00:00:00.000000000 Z
11
+ date: 2021-12-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: 4.1.0
53
+ version: 5.1.0
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 4.1.0
60
+ version: 5.1.0
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: factory_bot_rails
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +136,12 @@ files:
136
136
  - app/controllers/remote_execution_features_controller.rb
137
137
  - app/controllers/template_invocations_controller.rb
138
138
  - app/controllers/ui_job_wizard_controller.rb
139
+ - app/graphql/mutations/job_invocations/create.rb
140
+ - app/graphql/types/job_invocation.rb
141
+ - app/graphql/types/job_invocation_input.rb
142
+ - app/graphql/types/recurrence_input.rb
143
+ - app/graphql/types/scheduling_input.rb
144
+ - app/graphql/types/targeting_enum.rb
139
145
  - app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb
140
146
  - app/helpers/concerns/foreman_remote_execution/job_templates_extensions.rb
141
147
  - app/helpers/job_invocation_output_helper.rb
@@ -149,6 +155,7 @@ files:
149
155
  - app/lib/foreman_remote_execution/renderer/scope/input.rb
150
156
  - app/lib/proxy_api/remote_execution_ssh.rb
151
157
  - app/mailers/.gitkeep
158
+ - app/mailers/rex_job_mailer.rb
152
159
  - app/models/concerns/api/v2/interfaces_controller_extensions.rb
153
160
  - app/models/concerns/foreman_remote_execution/bookmark_extensions.rb
154
161
  - app/models/concerns/foreman_remote_execution/errors_flattener.rb
@@ -157,7 +164,6 @@ files:
157
164
  - app/models/concerns/foreman_remote_execution/foreman_tasks_triggering_extensions.rb
158
165
  - app/models/concerns/foreman_remote_execution/host_extensions.rb
159
166
  - app/models/concerns/foreman_remote_execution/nic_extensions.rb
160
- - app/models/concerns/foreman_remote_execution/orchestration/ssh.rb
161
167
  - app/models/concerns/foreman_remote_execution/smart_proxy_extensions.rb
162
168
  - app/models/concerns/foreman_remote_execution/subnet_extensions.rb
163
169
  - app/models/concerns/foreman_remote_execution/taxonomy_extensions.rb
@@ -166,6 +172,7 @@ files:
166
172
  - app/models/concerns/foreman_remote_execution/template_overrides.rb
167
173
  - app/models/concerns/foreman_remote_execution/user_extensions.rb
168
174
  - app/models/foreign_input_set.rb
175
+ - app/models/host_proxy_invocation.rb
169
176
  - app/models/host_status/execution_status.rb
170
177
  - app/models/input_template_renderer.rb
171
178
  - app/models/invocation_provider_input_value.rb
@@ -176,7 +183,7 @@ files:
176
183
  - app/models/job_template_effective_user.rb
177
184
  - app/models/remote_execution_feature.rb
178
185
  - app/models/remote_execution_provider.rb
179
- - app/models/setting/remote_execution.rb
186
+ - app/models/rex_mail_notification.rb
180
187
  - app/models/ssh_execution_provider.rb
181
188
  - app/models/target_remote_execution_proxy.rb
182
189
  - app/models/targeting.rb
@@ -215,6 +222,7 @@ files:
215
222
  - app/views/api/v2/template_invocations/base.json.rabl
216
223
  - app/views/api/v2/template_invocations/template_invocations.json.rabl
217
224
  - app/views/dashboard/.gitkeep
225
+ - app/views/dashboard/_latest-jobs.html.erb
218
226
  - app/views/job_invocation_task_groups/_job_invocation_task_groups.html.erb
219
227
  - app/views/job_invocations/_card_results.html.erb
220
228
  - app/views/job_invocations/_card_schedule.html.erb
@@ -248,6 +256,8 @@ files:
248
256
  - app/views/remote_execution_features/_form.html.erb
249
257
  - app/views/remote_execution_features/index.html.erb
250
258
  - app/views/remote_execution_features/show.html.erb
259
+ - app/views/rex_job_mailer/job_finished.html.erb
260
+ - app/views/rex_job_mailer/job_finished.text.erb
251
261
  - app/views/template_inputs/_foreign_input_set_form.html.erb
252
262
  - app/views/template_invocations/_output_line_set.html.erb
253
263
  - app/views/template_invocations/_refresh.js.erb
@@ -310,12 +320,15 @@ files:
310
320
  - db/migrate/20200623073022_rename_sudo_password_to_effective_user_password.rb
311
321
  - db/migrate/20200820122057_add_proxy_selector_override_to_remote_execution_feature.rb
312
322
  - db/migrate/20210312074713_add_provider_inputs.rb
323
+ - db/migrate/2021051713291621250977_add_host_proxy_invocations.rb
324
+ - db/migrate/20210816100932_rex_setting_category_to_dsl.rb
313
325
  - db/seeds.d/100-assign_features_with_templates.rb
314
326
  - db/seeds.d/20-permissions.rb
315
327
  - db/seeds.d/50-notification_blueprints.rb
316
328
  - db/seeds.d/60-ssh_proxy_feature.rb
317
329
  - db/seeds.d/70-job_templates.rb
318
330
  - db/seeds.d/90-bookmarks.rb
331
+ - db/seeds.d/95-mail_notifications.rb
319
332
  - extra/cockpit/cockpit.conf.example
320
333
  - extra/cockpit/foreman-cockpit-session
321
334
  - extra/cockpit/foreman-cockpit.service
@@ -365,8 +378,10 @@ files:
365
378
  - test/functional/job_invocations_controller_test.rb
366
379
  - test/functional/job_templates_controller_test.rb
367
380
  - test/functional/ui_job_wizard_controller_test.rb
381
+ - test/graphql/mutations/job_invocations/create.rb
382
+ - test/graphql/queries/job_invocation_query_test.rb
383
+ - test/graphql/queries/job_invocations_query_test.rb
368
384
  - test/helpers/remote_execution_helper_test.rb
369
- - test/models/orchestration/ssh_test.rb
370
385
  - test/support/remote_execution_helper.rb
371
386
  - test/test_plugin_helper.rb
372
387
  - test/unit/actions/run_host_job_test.rb
@@ -390,30 +405,64 @@ files:
390
405
  - webpack/JobWizard/JobWizard.scss
391
406
  - webpack/JobWizard/JobWizardConstants.js
392
407
  - webpack/JobWizard/JobWizardSelectors.js
393
- - webpack/JobWizard/__tests__/JobWizard.test.js
394
- - webpack/JobWizard/__tests__/__snapshots__/JobWizard.test.js.snap
395
408
  - webpack/JobWizard/__tests__/__snapshots__/integration.test.js.snap
396
409
  - webpack/JobWizard/__tests__/fixtures.js
397
410
  - webpack/JobWizard/__tests__/integration.test.js
411
+ - webpack/JobWizard/__tests__/validation.test.js
412
+ - webpack/JobWizard/autofill.js
398
413
  - webpack/JobWizard/index.js
399
414
  - webpack/JobWizard/steps/AdvancedFields/AdvancedFields.js
415
+ - webpack/JobWizard/steps/AdvancedFields/DescriptionField.js
400
416
  - webpack/JobWizard/steps/AdvancedFields/Fields.js
401
417
  - webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js
402
418
  - webpack/JobWizard/steps/AdvancedFields/__tests__/__snapshots__/AdvancedFields.test.js.snap
403
419
  - webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.js
404
420
  - webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.test.js
405
- - webpack/JobWizard/steps/CategoryAndTemplate/__snapshots__/CategoryAndTemplate.test.js.snap
406
421
  - webpack/JobWizard/steps/CategoryAndTemplate/index.js
422
+ - webpack/JobWizard/steps/HostsAndInputs/HostPreviewModal.js
423
+ - webpack/JobWizard/steps/HostsAndInputs/HostSearch.js
424
+ - webpack/JobWizard/steps/HostsAndInputs/SelectAPI.js
425
+ - webpack/JobWizard/steps/HostsAndInputs/SelectGQL.js
426
+ - webpack/JobWizard/steps/HostsAndInputs/SelectedChips.js
427
+ - webpack/JobWizard/steps/HostsAndInputs/TemplateInputs.js
428
+ - webpack/JobWizard/steps/HostsAndInputs/__tests__/HostsAndInputs.test.js
429
+ - webpack/JobWizard/steps/HostsAndInputs/__tests__/TemplateInputs.test.js
430
+ - webpack/JobWizard/steps/HostsAndInputs/buildHostQuery.js
431
+ - webpack/JobWizard/steps/HostsAndInputs/hostgroups.gql
432
+ - webpack/JobWizard/steps/HostsAndInputs/hosts.gql
433
+ - webpack/JobWizard/steps/HostsAndInputs/index.js
434
+ - webpack/JobWizard/steps/ReviewDetails/index.js
435
+ - webpack/JobWizard/steps/Schedule/PurposeField.js
436
+ - webpack/JobWizard/steps/Schedule/QueryType.js
437
+ - webpack/JobWizard/steps/Schedule/RepeatCron.js
438
+ - webpack/JobWizard/steps/Schedule/RepeatDaily.js
439
+ - webpack/JobWizard/steps/Schedule/RepeatHour.js
440
+ - webpack/JobWizard/steps/Schedule/RepeatMonth.js
441
+ - webpack/JobWizard/steps/Schedule/RepeatOn.js
442
+ - webpack/JobWizard/steps/Schedule/RepeatWeek.js
443
+ - webpack/JobWizard/steps/Schedule/ScheduleType.js
444
+ - webpack/JobWizard/steps/Schedule/StartEndDates.js
445
+ - webpack/JobWizard/steps/Schedule/__tests__/Schedule.test.js
446
+ - webpack/JobWizard/steps/Schedule/__tests__/StartEndDates.test.js
447
+ - webpack/JobWizard/steps/Schedule/index.js
448
+ - webpack/JobWizard/steps/form/DateTimePicker.js
407
449
  - webpack/JobWizard/steps/form/FormHelpers.js
450
+ - webpack/JobWizard/steps/form/Formatter.js
408
451
  - webpack/JobWizard/steps/form/GroupedSelectField.js
452
+ - webpack/JobWizard/steps/form/NumberInput.js
453
+ - webpack/JobWizard/steps/form/ResourceSelect.js
454
+ - webpack/JobWizard/steps/form/SearchSelect.js
409
455
  - webpack/JobWizard/steps/form/SelectField.js
410
- - webpack/JobWizard/steps/form/__tests__/GroupedSelectField.test.js
411
- - webpack/JobWizard/steps/form/__tests__/SelectField.test.js
412
- - webpack/JobWizard/steps/form/__tests__/__snapshots__/GroupedSelectField.test.js.snap
413
- - webpack/JobWizard/steps/form/__tests__/__snapshots__/SelectField.test.js.snap
456
+ - webpack/JobWizard/steps/form/WizardTitle.js
457
+ - webpack/JobWizard/steps/form/__tests__/SelectSearch.test.js
458
+ - webpack/JobWizard/submit.js
459
+ - webpack/JobWizard/validation.js
414
460
  - webpack/Routes/routes.js
461
+ - webpack/__mocks__/foremanReact/Root/Context/ForemanContext/index.js
415
462
  - webpack/__mocks__/foremanReact/common/I18n.js
416
463
  - webpack/__mocks__/foremanReact/common/helpers.js
464
+ - webpack/__mocks__/foremanReact/components/AutoComplete/AutoCompleteActions.js
465
+ - webpack/__mocks__/foremanReact/components/AutoComplete/AutoCompleteConstants.js
417
466
  - webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js
418
467
  - webpack/__mocks__/foremanReact/components/SearchBar.js
419
468
  - webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js
@@ -422,13 +471,17 @@ files:
422
471
  - webpack/__mocks__/foremanReact/redux/API/APISelectors.js
423
472
  - webpack/__mocks__/foremanReact/redux/API/index.js
424
473
  - webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware/IntervalSelectors.js
474
+ - webpack/__mocks__/foremanReact/routes/RouterSelector.js
425
475
  - webpack/__mocks__/foremanReact/routes/common/PageLayout/PageLayout.js
426
476
  - webpack/global_index.js
477
+ - webpack/helpers.js
427
478
  - webpack/index.js
479
+ - webpack/react_app/components/RecentJobsCard/JobStatusIcon.js
428
480
  - webpack/react_app/components/RecentJobsCard/RecentJobsCard.js
481
+ - webpack/react_app/components/RecentJobsCard/RecentJobsTable.js
429
482
  - webpack/react_app/components/RecentJobsCard/constants.js
430
483
  - webpack/react_app/components/RecentJobsCard/index.js
431
- - webpack/react_app/components/RecentJobsCard/styles.css
484
+ - webpack/react_app/components/RecentJobsCard/styles.scss
432
485
  - webpack/react_app/components/RegistrationExtension/RexInterface.js
433
486
  - webpack/react_app/components/RegistrationExtension/__tests__/RexInterface.test.js
434
487
  - webpack/react_app/components/RegistrationExtension/__tests__/__snapshots__/RexInterface.test.js.snap
@@ -503,8 +556,10 @@ test_files:
503
556
  - test/functional/job_invocations_controller_test.rb
504
557
  - test/functional/job_templates_controller_test.rb
505
558
  - test/functional/ui_job_wizard_controller_test.rb
559
+ - test/graphql/mutations/job_invocations/create.rb
560
+ - test/graphql/queries/job_invocation_query_test.rb
561
+ - test/graphql/queries/job_invocations_query_test.rb
506
562
  - test/helpers/remote_execution_helper_test.rb
507
- - test/models/orchestration/ssh_test.rb
508
563
  - test/support/remote_execution_helper.rb
509
564
  - test/test_plugin_helper.rb
510
565
  - test/unit/actions/run_host_job_test.rb
@@ -1,70 +0,0 @@
1
- module ForemanRemoteExecution
2
- module Orchestration::SSH
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- before_destroy :ssh_destroy
7
- after_validation :queue_ssh_destroy
8
- register_rebuild(:queue_ssh_destroy, N_("SSH_#{self.to_s.split('::').first}"))
9
- end
10
-
11
- def drop_from_known_hosts(proxy_id)
12
- _, _, target = host_kind_target
13
- return true if target.nil?
14
-
15
- proxy = ::SmartProxy.find(proxy_id)
16
- begin
17
- proxy.drop_host_from_known_hosts(target)
18
- rescue ::ProxyAPI::ProxyException => e
19
- if e.wrapped_exception.is_a?(RestClient::NotFound)
20
- # ignore 404 when known_hosts entry is missing or the module was not enabled
21
- Foreman::Logging.exception "Proxy failed to delete SSH known_hosts for #{name}, #{ip}", e, :level => :error
22
- else
23
- raise e
24
- end
25
- rescue => e
26
- Rails.logger.warn e.message
27
- return false
28
- end
29
- true
30
- end
31
-
32
- def ssh_destroy
33
- logger.debug "Scheduling SSH known_hosts cleanup"
34
-
35
- host, _kind, _target = host_kind_target
36
- # #remote_execution_proxies may not be defined on the host object in some case
37
- # for example Host::Discovered does not have it defined, even though these hosts
38
- # have Nic::Managed interfaces associated with them
39
- proxies = (host.try(:remote_execution_proxies, 'SSH') || {}).values
40
- proxies.flatten.uniq.each do |proxy|
41
- queue.create(id: queue_id(proxy.id), name: _("Remove SSH known hosts for %s") % self,
42
- priority: 200, action: [self, :drop_from_known_hosts, proxy.id])
43
- end
44
- end
45
-
46
- def queue_ssh_destroy
47
- should_drop_from_known_hosts? && ssh_destroy
48
- end
49
-
50
- def should_drop_from_known_hosts?
51
- host, = host_kind_target
52
- host && !host.new_record? && host.build && host.changes.key?('build')
53
- end
54
-
55
- private
56
-
57
- def host_kind_target
58
- if self.is_a?(::Host::Base)
59
- [self, 'host', name]
60
- else
61
- [self.host, 'interface', ip]
62
- end
63
- end
64
-
65
- def queue_id(proxy_id)
66
- _, kind, id = host_kind_target
67
- "ssh_remove_known_hosts_#{kind}_#{id}_#{proxy_id}"
68
- end
69
- end
70
- end
@@ -1,88 +0,0 @@
1
- class Setting::RemoteExecution < Setting
2
-
3
- ::Setting::BLANK_ATTRS.concat %w{remote_execution_ssh_password remote_execution_ssh_key_passphrase remote_execution_sudo_password remote_execution_effective_user_password remote_execution_cockpit_url remote_execution_form_job_template}
4
-
5
- def self.default_settings
6
- [
7
- self.set('remote_execution_fallback_proxy',
8
- N_('Search the host for any proxy with Remote Execution, useful when the host has no subnet or the subnet does not have an execution proxy'),
9
- false,
10
- N_('Fallback to Any Proxy')),
11
- self.set('remote_execution_global_proxy',
12
- N_('Search for remote execution proxy outside of the proxies assigned to the host. ' +
13
- "The search will be limited to the host's organization and location."),
14
- true,
15
- N_('Enable Global Proxy')),
16
- self.set('remote_execution_ssh_user',
17
- N_('Default user to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_user.'),
18
- 'root',
19
- N_('SSH User')),
20
- self.set('remote_execution_effective_user',
21
- N_('Default user to use for executing the script. If the user differs from the SSH user, su or sudo is used to switch the user.'),
22
- 'root',
23
- N_('Effective User')),
24
- self.set('remote_execution_effective_user_method',
25
- N_('What command should be used to switch to the effective user. One of %s') % SSHExecutionProvider::EFFECTIVE_USER_METHODS.inspect,
26
- 'sudo',
27
- N_('Effective User Method'),
28
- nil,
29
- { :collection => proc { Hash[SSHExecutionProvider::EFFECTIVE_USER_METHODS.map { |method| [method, method] }] } }),
30
- self.set('remote_execution_effective_user_password', N_("Effective user password"), '', N_("Effective user password"), nil, {:encrypted => true}),
31
- self.set('remote_execution_sync_templates',
32
- N_('Whether we should sync templates from disk when running db:seed.'),
33
- true,
34
- N_('Sync Job Templates')),
35
- self.set('remote_execution_ssh_port',
36
- N_('Port to use for SSH communication. Default port 22. You may override per host by setting a parameter called remote_execution_ssh_port.'),
37
- '22',
38
- N_('SSH Port')),
39
- self.set('remote_execution_connect_by_ip',
40
- N_('Should the ip addresses on host interfaces be preferred over the fqdn? '\
41
- 'It is useful when DNS not resolving the fqdns properly. You may override this per host by setting a parameter called remote_execution_connect_by_ip. '\
42
- 'This setting only applies to IPv4. When the host has only an IPv6 address on the interface used for remote execution, hostname will be used even if this setting is set to true.'),
43
- false,
44
- N_('Connect by IP')),
45
- self.set('remote_execution_ssh_password',
46
- N_('Default password to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_password'),
47
- nil,
48
- N_('Default SSH password'),
49
- nil,
50
- { :encrypted => true }),
51
- self.set('remote_execution_ssh_key_passphrase',
52
- N_('Default key passphrase to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_key_passphrase'),
53
- nil,
54
- N_('Default SSH key passphrase'),
55
- nil,
56
- { :encrypted => true }),
57
- self.set('remote_execution_workers_pool_size',
58
- N_('Amount of workers in the pool to handle the execution of the remote execution jobs. Restart of the dynflowd/foreman-tasks service is required.'),
59
- 5,
60
- N_('Workers pool size')),
61
- self.set('remote_execution_cleanup_working_dirs',
62
- N_('When enabled, working directories will be removed after task completion. You may override this per host by setting a parameter called remote_execution_cleanup_working_dirs.'),
63
- true,
64
- N_('Cleanup working directories')),
65
- self.set('remote_execution_cockpit_url',
66
- N_('Where to find the Cockpit instance for the Web Console button. By default, no button is shown.'),
67
- nil,
68
- N_('Cockpit URL'),
69
- nil),
70
- self.set('remote_execution_form_job_template',
71
- N_('Choose a job template that is pre-selected in job invocation form'),
72
- 'Run Command - SSH Default',
73
- _('Form Job Template'),
74
- nil,
75
- { :collection => proc { Hash[JobTemplate.unscoped.map { |template| [template.name, template.name] }] } }),
76
- self.set('remote_execution_job_invocation_report_template',
77
- N_('Select a report template used for generating a report for a particular remote execution job'),
78
- 'Jobs - Invocation report template',
79
- _('Job Invocation Report Template'),
80
- nil,
81
- { :collection => proc { self.job_invocation_report_templates_select } }),
82
- ]
83
- end
84
-
85
- def self.job_invocation_report_templates_select
86
- Hash[ReportTemplate.unscoped.joins(:template_inputs).where(template_inputs: TemplateInput.where(name: 'job_id')).map { |template| [template.name, template.name] }]
87
- end
88
- end
@@ -1,56 +0,0 @@
1
- require 'test_plugin_helper'
2
-
3
- class SSHOrchestrationTest < ActiveSupport::TestCase
4
- let(:host) { FactoryBot.create(:host, :managed, :with_subnet) }
5
- let(:proxy) { FactoryBot.create(:smart_proxy, :ssh) }
6
- let(:interface) { host.interfaces.first }
7
-
8
- before { interface.subnet.remote_execution_proxies = [proxy] }
9
-
10
- it 'attempts to drop IP address and hostname from smart proxies on destroy' do
11
- host.stubs(:skip_orchestration?).returns false
12
- SmartProxy.any_instance.expects(:drop_host_from_known_hosts).with(interface.ip)
13
- SmartProxy.any_instance.expects(:drop_host_from_known_hosts).with(host.name)
14
- host.destroy
15
- end
16
-
17
- it 'attempts to drop IP address and hostname from smart proxies on rebuild' do
18
- host.stubs(:skip_orchestration?).returns false
19
- SmartProxy.any_instance.expects(:drop_host_from_known_hosts).with(interface.ip)
20
- SmartProxy.any_instance.expects(:drop_host_from_known_hosts).with(host.name)
21
-
22
- host.build = true
23
- host.save!
24
-
25
- ids = ["ssh_remove_known_hosts_interface_#{interface.ip}_#{proxy.id}",
26
- "ssh_remove_known_hosts_host_#{host.name}_#{proxy.id}"]
27
- _(host.queue.task_ids).must_equal ids
28
- _(host.queue.items.map(&:status)).must_equal %w(completed completed)
29
- end
30
-
31
- it 'does not fail on 404 from the smart proxy' do
32
- host.stubs(:skip_orchestration?).returns false
33
- ::ProxyAPI::RemoteExecutionSSH.any_instance.expects(:delete).raises(RestClient::ResourceNotFound).twice
34
- host.build = true
35
- host.save!
36
- ids = ["ssh_remove_known_hosts_interface_#{interface.ip}_#{proxy.id}",
37
- "ssh_remove_known_hosts_host_#{host.name}_#{proxy.id}"]
38
- _(host.queue.task_ids).must_equal ids
39
- _(host.queue.items.map(&:status)).must_equal %w(completed completed)
40
- end
41
-
42
- it 'does not trigger the removal when creating a new host' do
43
- SmartProxy.any_instance.expects(:drop_host_from_known_hosts).never
44
- host = Host::Managed.new(:name => 'test', :ip => '127.0.0.1')
45
- host.stubs(:skip_orchestration?).returns false
46
- _(host.queue.task_ids).must_equal []
47
- end
48
-
49
- it 'does not call to the proxy when target is nil' do
50
- host.stubs(:skip_orchestration?).returns false
51
- SmartProxy.any_instance.expects(:drop_host_from_known_hosts).with(host.name)
52
- host.interfaces.first.stubs(:ip)
53
- host.destroy
54
- _(host.queue.items.map(&:status)).must_equal %w(completed completed)
55
- end
56
- end
@@ -1,13 +0,0 @@
1
- import React from 'react';
2
- import * as patternfly from '@patternfly/react-core';
3
- import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
4
- import JobWizardPage from '../index';
5
-
6
- jest.spyOn(patternfly, 'Wizard');
7
- patternfly.Wizard.mockImplementation(props => <div>{props.navAriaLabel}</div>);
8
-
9
- const fixtures = {
10
- 'renders ': {},
11
- };
12
- describe('JobWizardPage rendering', () =>
13
- testComponentSnapshotsWithFixtures(JobWizardPage, fixtures));
@@ -1,32 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`JobWizardPage rendering renders 1`] = `
4
- <PageLayout
5
- breadcrumbOptions={
6
- Object {
7
- "breadcrumbItems": Array [
8
- Object {
9
- "caption": "Jobs",
10
- "url": "/jobs",
11
- },
12
- Object {
13
- "caption": "Run job",
14
- },
15
- ],
16
- }
17
- }
18
- header="Run job"
19
- searchable={false}
20
- >
21
- <Title
22
- headingLevel="h2"
23
- size="2xl"
24
- >
25
- Run job
26
- </Title>
27
- <Divider
28
- component="div"
29
- />
30
- <JobWizard />
31
- </PageLayout>
32
- `;
@@ -1,113 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`CategoryAndTemplate rendering render with error 1`] = `
4
- <Fragment>
5
- <Title
6
- headingLevel="h2"
7
- >
8
- Category and Template
9
- </Title>
10
- <Text
11
- component="p"
12
- >
13
- All fields are required.
14
- </Text>
15
- <Form>
16
- <SelectField
17
- fieldId="job_category"
18
- isDisabled={false}
19
- label="Job category"
20
- options={Array []}
21
- placeholderText=""
22
- setValue={[Function]}
23
- value={null}
24
- />
25
- <GroupedSelectField
26
- fieldId="job_template"
27
- groups={Array []}
28
- isDisabled={true}
29
- label="Job template"
30
- placeholderText="Error"
31
- selected={null}
32
- setSelected={[MockFunction]}
33
- />
34
- <Alert
35
- title="Errors:"
36
- variant="danger"
37
- >
38
- <span>
39
- Templates list failed with:
40
-
41
- I have an error
42
- </span>
43
- </Alert>
44
- </Form>
45
- </Fragment>
46
- `;
47
-
48
- exports[`CategoryAndTemplate rendering renders with props 1`] = `
49
- <Fragment>
50
- <Title
51
- headingLevel="h2"
52
- >
53
- Category and Template
54
- </Title>
55
- <Text
56
- component="p"
57
- >
58
- All fields are required.
59
- </Text>
60
- <Form>
61
- <SelectField
62
- fieldId="job_category"
63
- isDisabled={false}
64
- label="Job category"
65
- options={
66
- Array [
67
- "Commands",
68
- "Ansible Playbook",
69
- "Ansible Galaxy",
70
- "Ansible Roles Installation",
71
- ]
72
- }
73
- placeholderText=""
74
- setValue={[Function]}
75
- value="I am a category"
76
- />
77
- <GroupedSelectField
78
- fieldId="job_template"
79
- groups={
80
- Array [
81
- Object {
82
- "groupLabel": "SSH",
83
- "options": Array [
84
- Object {
85
- "label": "ab Run Command - SSH Default clone",
86
- "value": 190,
87
- },
88
- ],
89
- },
90
- Object {
91
- "groupLabel": "Ansible",
92
- "options": Array [
93
- Object {
94
- "label": "Ansible Roles - Ansible Default",
95
- "value": 168,
96
- },
97
- Object {
98
- "label": "Ansible Roles - Install from git",
99
- "value": 170,
100
- },
101
- ],
102
- },
103
- ]
104
- }
105
- isDisabled={false}
106
- label="Job template"
107
- placeholderText=""
108
- selected="ab Run Command - SSH Default clone"
109
- setSelected={[MockFunction]}
110
- />
111
- </Form>
112
- </Fragment>
113
- `;
@@ -1,38 +0,0 @@
1
- import React from 'react';
2
- import * as patternfly from '@patternfly/react-core';
3
- import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
4
- import { GroupedSelectField } from '../GroupedSelectField';
5
-
6
- jest.spyOn(patternfly, 'Select');
7
- jest.spyOn(patternfly, 'SelectOption');
8
- patternfly.Select.mockImplementation(props => <div>{props}</div>);
9
- patternfly.SelectOption.mockImplementation(props => <div>{props}</div>);
10
-
11
- const fixtures = {
12
- 'renders with props': {
13
- label: 'grouped select',
14
- fieldId: 'field-id',
15
- groups: [
16
- {
17
- groupLabel: 'Ansible',
18
- options: [
19
- {
20
- label: 'Ansible Roles - Ansible Default',
21
- value: 168,
22
- },
23
- {
24
- label: 'Ansible Roles - Install from git',
25
- value: 170,
26
- },
27
- ],
28
- },
29
- ],
30
- selected: 170,
31
- setSelected: jest.fn(),
32
- },
33
- };
34
-
35
- describe('GroupedSelectField', () => {
36
- describe('rendering', () =>
37
- testComponentSnapshotsWithFixtures(GroupedSelectField, fixtures));
38
- });
@@ -1,23 +0,0 @@
1
- import React from 'react';
2
- import * as patternfly from '@patternfly/react-core';
3
- import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
4
- import { SelectField } from '../SelectField';
5
-
6
- jest.spyOn(patternfly, 'Select');
7
- jest.spyOn(patternfly, 'SelectOption');
8
- patternfly.Select.mockImplementation(props => <div>{props}</div>);
9
- patternfly.SelectOption.mockImplementation(props => <div>{props}</div>);
10
- const fixtures = {
11
- 'renders with props': {
12
- label: 'grouped select',
13
- fieldId: 'field-id',
14
- options: ['Commands'],
15
- value: 'Commands',
16
- setValue: jest.fn(),
17
- },
18
- };
19
-
20
- describe('SelectField', () => {
21
- describe('rendering', () =>
22
- testComponentSnapshotsWithFixtures(SelectField, fixtures));
23
- });