foreman-tasks 1.1.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (189) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/js_tests.yml +27 -0
  3. data/.github/workflows/ruby_tests.yml +74 -0
  4. data/.rubocop.yml +12 -4
  5. data/.rubocop_todo.yml +32 -25
  6. data/Gemfile +5 -0
  7. data/README.md +2 -0
  8. data/app/controllers/foreman_tasks/api/tasks_controller.rb +63 -58
  9. data/app/controllers/foreman_tasks/concerns/parameters/triggering.rb +1 -1
  10. data/app/controllers/foreman_tasks/recurring_logics_controller.rb +7 -0
  11. data/app/controllers/foreman_tasks/tasks_controller.rb +9 -14
  12. data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +3 -3
  13. data/app/lib/actions/proxy_action.rb +1 -1
  14. data/app/models/foreman_tasks/recurring_logic.rb +1 -1
  15. data/app/models/foreman_tasks/task.rb +15 -0
  16. data/app/models/foreman_tasks/task/dynflow_task.rb +29 -33
  17. data/app/models/foreman_tasks/task/status_explicator.rb +1 -1
  18. data/app/models/foreman_tasks/triggering.rb +1 -1
  19. data/app/models/setting/foreman_tasks.rb +2 -2
  20. data/app/services/ui_notifications/tasks/task_bulk_stop.rb +36 -0
  21. data/app/views/foreman_tasks/api/tasks/details.json.rabl +0 -1
  22. data/app/views/foreman_tasks/api/tasks/index.json.rabl +2 -0
  23. data/app/views/foreman_tasks/api/tasks/show.json.rabl +2 -0
  24. data/app/views/foreman_tasks/recurring_logics/index.html.erb +3 -1
  25. data/config/routes.rb +3 -1
  26. data/db/migrate/20200517215015_rename_bookmarks_controller.rb +35 -0
  27. data/db/migrate/20200519093217_drop_dynflow_allow_dangerous_actions_setting.foreman_tasks.rb +5 -0
  28. data/db/migrate/20200611090846_add_task_lock_index_on_resource_type_and_task_id.rb +1 -1
  29. data/db/seeds.d/30-notification_blueprints.rb +14 -7
  30. data/db/seeds.d/61-foreman_tasks_bookmarks.rb +1 -1
  31. data/lib/foreman_tasks/cleaner.rb +4 -6
  32. data/lib/foreman_tasks/dynflow/configuration.rb +1 -1
  33. data/lib/foreman_tasks/dynflow/persistence.rb +4 -6
  34. data/lib/foreman_tasks/engine.rb +3 -8
  35. data/lib/foreman_tasks/version.rb +1 -1
  36. data/locale/action_names.rb +1 -1
  37. data/locale/en/LC_MESSAGES/foreman_tasks.mo +0 -0
  38. data/locale/en/foreman_tasks.po +270 -54
  39. data/locale/foreman_tasks.pot +630 -292
  40. data/locale/fr/LC_MESSAGES/foreman_tasks.mo +0 -0
  41. data/locale/fr/foreman_tasks.po +817 -0
  42. data/locale/ja/LC_MESSAGES/foreman_tasks.mo +0 -0
  43. data/locale/ja/foreman_tasks.po +817 -0
  44. data/locale/zh_CN/LC_MESSAGES/foreman_tasks.mo +0 -0
  45. data/locale/zh_CN/foreman_tasks.po +816 -0
  46. data/package.json +1 -1
  47. data/script/npm_link_foreman_js.sh +26 -0
  48. data/test/controllers/api/recurring_logics_controller_test.rb +1 -1
  49. data/test/controllers/api/tasks_controller_test.rb +7 -7
  50. data/test/controllers/tasks_controller_test.rb +6 -6
  51. data/test/core/unit/runner_test.rb +20 -20
  52. data/test/core/unit/task_launcher_test.rb +8 -8
  53. data/test/helpers/foreman_tasks/foreman_tasks_helper_test.rb +7 -7
  54. data/test/helpers/foreman_tasks/tasks_helper_test.rb +3 -3
  55. data/test/lib/actions/middleware/keep_current_request_id_test.rb +3 -3
  56. data/test/support/history_tasks_builder.rb +1 -1
  57. data/test/tasks/generate_task_actions_test.rb +1 -1
  58. data/test/unit/actions/action_with_sub_plans_test.rb +2 -2
  59. data/test/unit/actions/bulk_action_test.rb +6 -6
  60. data/test/unit/actions/proxy_action_test.rb +20 -20
  61. data/test/unit/actions/recurring_action_test.rb +30 -32
  62. data/test/unit/cleaner_test.rb +24 -24
  63. data/test/unit/dashboard_table_filter_test.rb +5 -5
  64. data/test/unit/otp_manager_test.rb +2 -2
  65. data/test/unit/proxy_selector_test.rb +9 -9
  66. data/test/unit/recurring_logic_test.rb +32 -32
  67. data/test/unit/remote_task_test.rb +2 -2
  68. data/test/unit/task_groups_test.rb +4 -4
  69. data/test/unit/task_test.rb +18 -18
  70. data/test/unit/triggering_test.rb +8 -8
  71. data/test/unit/troubleshooting_help_generator_test.rb +6 -6
  72. data/test/unit/ui_notifications_test.rb +11 -11
  73. data/webpack/ForemanTasks/Components/TaskActions/TaskAction.test.js +60 -0
  74. data/webpack/ForemanTasks/Components/{TasksTable/TasksTableActionHelpers.js → TaskActions/TaskActionHelpers.js} +21 -6
  75. data/webpack/ForemanTasks/Components/{TasksTable/__tests__/TasksTableActionHelpers.test.js → TaskActions/TaskActionHelpers.test.js} +2 -2
  76. data/webpack/ForemanTasks/Components/TaskActions/TaskActionsConstants.js +16 -0
  77. data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.js +60 -0
  78. data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.test.js +14 -0
  79. data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/TaskAction.test.js.snap +233 -0
  80. data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/UnlockModals.test.js.snap +25 -0
  81. data/webpack/ForemanTasks/Components/TaskActions/index.js +115 -0
  82. data/webpack/ForemanTasks/Components/TaskDetails/Components/RunningSteps.js +17 -3
  83. data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +38 -205
  84. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.js +168 -0
  85. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +6 -7
  86. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskSkeleton.js +48 -0
  87. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +8 -1
  88. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +14 -7
  89. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskButtons.test.js +95 -0
  90. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +0 -1
  91. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/RunningSteps.test.js.snap +1 -1
  92. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +90 -189
  93. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskButtons.test.js.snap +212 -0
  94. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +8 -4
  95. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +100 -53
  96. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.scss +3 -14
  97. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +57 -110
  98. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +3 -17
  99. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +57 -37
  100. data/webpack/ForemanTasks/Components/TaskDetails/TasksDetailsHelper.js +6 -1
  101. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.fixtures.js +8 -0
  102. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +13 -1
  103. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +6 -6
  104. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +86 -19
  105. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsActions.test.js.snap +25 -21
  106. data/webpack/ForemanTasks/Components/TaskDetails/index.js +12 -11
  107. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardActions.js +1 -1
  108. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js +2 -2
  109. data/webpack/ForemanTasks/Components/TasksTable/Components/ActionSelectButton.js +14 -1
  110. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModal.js +83 -0
  111. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalActions.js +106 -0
  112. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalReducer.js +38 -0
  113. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +46 -0
  114. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModal.test.js +36 -0
  115. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalActions.test.js +205 -0
  116. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalReducer.test.js +27 -0
  117. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +55 -0
  118. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModal.test.js.snap +41 -0
  119. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalReducer.test.js.snap +19 -0
  120. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +32 -0
  121. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/index.js +29 -0
  122. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ActionSelectButton.test.js +1 -0
  123. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ActionSelectButton.test.js.snap +11 -0
  124. data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +135 -35
  125. data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +13 -9
  126. data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +26 -66
  127. data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +10 -12
  128. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +30 -96
  129. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSchema.js +2 -2
  130. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +8 -4
  131. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksBulkActions.test.js +50 -2
  132. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +3 -12
  133. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActions.test.js +22 -26
  134. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTablePage.test.js +2 -1
  135. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +3 -14
  136. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksBulkActions.test.js.snap +155 -0
  137. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +3 -14
  138. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +17 -124
  139. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +63 -133
  140. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/actionCellFormatter.test.js.snap +1 -0
  141. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/selectionCellFormatter.test.js.snap +2 -0
  142. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/actionCellFormatter.test.js +1 -1
  143. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionCellFormatter.test.js +1 -1
  144. data/webpack/ForemanTasks/Components/TasksTable/formatters/actionCellFormatter.js +10 -7
  145. data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionCellFormatter.js +7 -0
  146. data/webpack/ForemanTasks/Components/TasksTable/index.js +2 -2
  147. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.js +55 -19
  148. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.test.js +75 -19
  149. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ActionButton.test.js.snap +88 -21
  150. data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.scss +9 -0
  151. data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.test.js +44 -0
  152. data/webpack/ForemanTasks/Components/common/ClickConfirmation/__snapshots__/ClickConfirmation.test.js.snap +52 -0
  153. data/webpack/ForemanTasks/Components/common/ClickConfirmation/index.js +59 -66
  154. data/webpack/ForemanTasks/Components/common/{ToastTypesConstants.js → ToastsHelpers/ToastTypesConstants.js} +0 -0
  155. data/webpack/ForemanTasks/Components/common/ToastsHelpers/index.js +15 -0
  156. data/webpack/ForemanTasks/Components/common/urlHelpers.js +7 -0
  157. data/webpack/ForemanTasks/ForemanTasksReducers.js +2 -2
  158. data/webpack/ForemanTasks/Routes/ForemanTasksRoutes.test.js +2 -1
  159. data/webpack/__mocks__/foremanReact/common/helpers.js +2 -0
  160. data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalHooks.js +2 -2
  161. data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +17 -3
  162. data/webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js +3 -0
  163. data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +10 -0
  164. data/webpack/__mocks__/foremanReact/redux/API/index.js +10 -0
  165. data/webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware.js +5 -0
  166. metadata +51 -28
  167. data/.travis.yml +0 -5
  168. data/script/travis_run_js_tests.sh +0 -7
  169. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +0 -44
  170. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsReducer.test.js +0 -33
  171. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsReducer.test.js.snap +0 -26
  172. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/integration.test.js.snap +0 -122
  173. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +0 -63
  174. data/webpack/ForemanTasks/Components/TasksTable/Components/CancelConfirm.js +0 -53
  175. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmationModals.js +0 -56
  176. data/webpack/ForemanTasks/Components/TasksTable/Components/ResumeConfirm.js +0 -52
  177. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/CancelConfirm.test.js +0 -26
  178. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ConfirmationModals.test.js +0 -24
  179. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ResumeConfirm.test.js +0 -26
  180. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/CancelConfirm.test.js.snap +0 -65
  181. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ConfirmationModals.test.js.snap +0 -30
  182. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ResumeConfirm.test.js.snap +0 -63
  183. data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.js +0 -23
  184. data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.test.js +0 -26
  185. data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.js +0 -23
  186. data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.test.js +0 -27
  187. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/CancelButton.test.js.snap +0 -15
  188. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ResumeButton.test.js.snap +0 -15
  189. data/webpack/__mocks__/foremanReact/API.js +0 -7
@@ -24,8 +24,8 @@ module ForemanTasks
24
24
  RemoteTask.batch_trigger('a_operation', remote_tasks)
25
25
  remote_tasks.each do |remote_task|
26
26
  remote_task.reload
27
- remote_task.state.must_equal 'triggered'
28
- remote_task.remote_task_id.must_equal((remote_task.id + 5).to_s)
27
+ _(remote_task.state).must_equal 'triggered'
28
+ _(remote_task.remote_task_id).must_equal((remote_task.id + 5).to_s)
29
29
  end
30
30
  end
31
31
 
@@ -55,18 +55,18 @@ module ForemanTasks
55
55
 
56
56
  it 'has the task group assigned' do
57
57
  task = spawn_task.call ChildAction
58
- task.task_groups.map(&:id).must_equal [1]
58
+ _(task.task_groups.map(&:id)).must_equal [1]
59
59
  end
60
60
 
61
61
  it 'tasks inherit task groups correctly' do
62
62
  children_count = 3
63
63
  task = spawn_task.call ParentAction, children_count
64
64
  # Parent task has task groups of its children
65
- task.task_groups.map(&:id).sort.must_equal [1, 2, 3, 4]
65
+ _(task.task_groups.map(&:id).sort).must_equal [1, 2, 3, 4]
66
66
  # Children have the parent's and their own, they don't have their siblings' task groups
67
- task.sub_tasks.count.must_equal children_count
67
+ _(task.sub_tasks.count).must_equal children_count
68
68
  task.sub_tasks.each do |sub_task|
69
- sub_task.task_groups.map(&:id).sort.must_equal [1, sub_task.input[:id]].sort
69
+ _(sub_task.task_groups.map(&:id).sort).must_equal [1, sub_task.input[:id]].sort
70
70
  end
71
71
  end
72
72
  end
@@ -32,8 +32,8 @@ class TasksTest < ActiveSupport::TestCase
32
32
  end
33
33
 
34
34
  test 'cannot search by arbitrary key' do
35
- proc { ForemanTasks::Task.search_for('user.my_key ~ 5') }.must_raise(ScopedSearch::QueryNotSupported)
36
- proc { ForemanTasks::Task.search_for('user. = 5') }.must_raise(ScopedSearch::QueryNotSupported)
35
+ _ { proc { ForemanTasks::Task.search_for('user.my_key ~ 5') } }.must_raise(ScopedSearch::QueryNotSupported)
36
+ _ { proc { ForemanTasks::Task.search_for('user. = 5') } }.must_raise(ScopedSearch::QueryNotSupported)
37
37
  end
38
38
 
39
39
  test 'can search the tasks by negated user' do
@@ -59,8 +59,8 @@ class TasksTest < ActiveSupport::TestCase
59
59
  end
60
60
 
61
61
  test 'cannot glob on user\'s id' do
62
- proc { ForemanTasks::Task.search_for("user.id ~ something") }.must_raise(ScopedSearch::QueryNotSupported)
63
- proc { ForemanTasks::Task.search_for("user.id ~ 5") }.must_raise(ScopedSearch::QueryNotSupported)
62
+ _ { proc { ForemanTasks::Task.search_for("user.id ~ something") } }.must_raise(ScopedSearch::QueryNotSupported)
63
+ _ { proc { ForemanTasks::Task.search_for("user.id ~ 5") } }.must_raise(ScopedSearch::QueryNotSupported)
64
64
  end
65
65
 
66
66
  test 'can search the tasks by user with wildcards' do
@@ -126,7 +126,7 @@ class TasksTest < ActiveSupport::TestCase
126
126
  end
127
127
 
128
128
  it 'raises an exception if duration is unknown' do
129
- proc { ForemanTasks::Task.search_for('duration = "25 potatoes"') }.must_raise ScopedSearch::QueryNotSupported
129
+ _ { proc { ForemanTasks::Task.search_for('duration = "25 potatoes"') } }.must_raise ScopedSearch::QueryNotSupported
130
130
  end
131
131
  end
132
132
  end
@@ -176,13 +176,13 @@ class TasksTest < ActiveSupport::TestCase
176
176
  let(:inconsistent_task) { FactoryBot.create(:dynflow_task, :inconsistent_dynflow_task) }
177
177
 
178
178
  it 'ensures the tasks marked as running are really running in Dynflow' do
179
- consistent_task.state.must_equal 'planned'
180
- inconsistent_task.state.must_equal 'running'
179
+ _(consistent_task.state).must_equal 'planned'
180
+ _(inconsistent_task.state).must_equal 'running'
181
181
 
182
182
  ForemanTasks::Task::DynflowTask.consistency_check
183
183
 
184
- consistent_task.reload.state.must_equal 'planned'
185
- inconsistent_task.reload.state.must_equal 'planned'
184
+ _(consistent_task.reload.state).must_equal 'planned'
185
+ _(inconsistent_task.reload.state).must_equal 'planned'
186
186
  end
187
187
  end
188
188
 
@@ -190,8 +190,8 @@ class TasksTest < ActiveSupport::TestCase
190
190
  it 'when scheduled to the future, the label and action is set properly' do
191
191
  job = Support::DummyActiveJob.set(:wait => 12.hours).perform_later
192
192
  task = ForemanTasks::Task.find_by!(:external_id => job.provider_job_id)
193
- task.action.must_equal "Dummy action"
194
- task.label.must_equal "Support::DummyActiveJob"
193
+ _(task.action).must_equal "Dummy action"
194
+ _(task.label).must_equal "Support::DummyActiveJob"
195
195
  end
196
196
  end
197
197
 
@@ -224,14 +224,14 @@ class TasksTest < ActiveSupport::TestCase
224
224
  :total => 0,
225
225
  :success => 0,
226
226
  :cancelled => 0,
227
- :pending => 0
227
+ :pending => 0,
228
228
  }
229
229
  end
230
230
  let(:task) { FactoryBot.create(:dynflow_task) }
231
231
 
232
232
  describe 'without sub tasks' do
233
233
  it 'calculates the progress report correctly' do
234
- task.sub_tasks_counts.must_equal result_base
234
+ _(task.sub_tasks_counts).must_equal result_base
235
235
  end
236
236
  end
237
237
 
@@ -242,7 +242,7 @@ class TasksTest < ActiveSupport::TestCase
242
242
 
243
243
  it 'calculate the progress report correctly' do
244
244
  expected_result = result_base.merge(:success => 1, :error => 1, :total => 2)
245
- task.sub_tasks_counts.must_equal expected_result
245
+ _(task.sub_tasks_counts).must_equal expected_result
246
246
  end
247
247
 
248
248
  it 'calculates the progress report correctly when using batch planning' do
@@ -252,11 +252,11 @@ class TasksTest < ActiveSupport::TestCase
252
252
 
253
253
  task.state = 'stopped'
254
254
  expected_result = result_base.merge(:cancelled => 23)
255
- task.sub_tasks_counts.must_equal expected_result
255
+ _(task.sub_tasks_counts).must_equal expected_result
256
256
 
257
257
  task.state = 'pending'
258
258
  expected_result = result_base.merge(:pending => 23)
259
- task.sub_tasks_counts.must_equal expected_result
259
+ _(task.sub_tasks_counts).must_equal expected_result
260
260
  end
261
261
  end
262
262
  end
@@ -278,10 +278,10 @@ class TasksTest < ActiveSupport::TestCase
278
278
 
279
279
  it 'can indicate it is delayed' do
280
280
  assert_not task.delayed?
281
- task.execution_type.must_equal 'Immediate'
281
+ _(task.execution_type).must_equal 'Immediate'
282
282
  task.start_at = Time.now.utc + 100
283
283
  assert task.delayed?
284
- task.execution_type.must_equal 'Delayed'
284
+ _(task.execution_type).must_equal 'Delayed'
285
285
  end
286
286
  end
287
287
 
@@ -3,28 +3,28 @@ require 'foreman_tasks_test_helper'
3
3
  class TriggeringTest < ActiveSupport::TestCase
4
4
  describe 'validation' do
5
5
  it 'is valid when immediate' do
6
- FactoryBot.build(:triggering).must_be :valid?
6
+ _(FactoryBot.build(:triggering)).must_be :valid?
7
7
  end
8
8
 
9
9
  it 'is validates future execution' do
10
10
  triggering = FactoryBot.build(:triggering, :future)
11
- triggering.must_be :valid?
11
+ _(triggering).must_be :valid?
12
12
  triggering.start_before = triggering.start_at - 120
13
- triggering.wont_be :valid?
13
+ _(triggering).wont_be :valid?
14
14
  end
15
15
 
16
16
  it 'is invalid when recurring logic is invalid' do
17
17
  triggering = FactoryBot.build(:triggering, :recurring)
18
- triggering.must_be :valid?
18
+ _(triggering).must_be :valid?
19
19
  triggering.recurring_logic.stubs(:valid?).returns(false)
20
- triggering.wont_be :valid?
20
+ _(triggering).wont_be :valid?
21
21
  end
22
22
  end
23
23
 
24
24
  it 'cannot have mode set to arbitrary value' do
25
25
  triggering = FactoryBot.build(:triggering)
26
- triggering.must_be :valid?
27
- proc { triggering.mode = 'bogus' }.must_raise ArgumentError
28
- proc { triggering.mode = 27 }.must_raise ArgumentError
26
+ _(triggering).must_be :valid?
27
+ _ { proc { triggering.mode = 'bogus' } }.must_raise ArgumentError
28
+ _ { proc { triggering.mode = 27 } }.must_raise ArgumentError
29
29
  end
30
30
  end
@@ -29,8 +29,8 @@ module ForemanTasks
29
29
 
30
30
  it 'generates html from the main action troubleshooting_info' do
31
31
  generated_html = subject.generate_html
32
- generated_html.must_include "A paused task represents a process that has not finished properly"
33
- generated_html.must_include %(See <a href="#{expected_troubleshooting_url}">troubleshooting documentation</a> for more details on how to resolve the issue)
32
+ _(generated_html).must_include "A paused task represents a process that has not finished properly"
33
+ _(generated_html).must_include %(See <a href="#{expected_troubleshooting_url}">troubleshooting documentation</a> for more details on how to resolve the issue)
34
34
  end
35
35
 
36
36
  it 'exposes link details' do
@@ -48,10 +48,10 @@ module ForemanTasks
48
48
 
49
49
  it 'includes additional description in generated html' do
50
50
  generated_html = subject.generate_html
51
- generated_html.must_include 'A paused task represents a process that has not finished properly'
52
- generated_html.must_match %r{See <a href=".*">troubleshooting documentation</a> for more details on how to resolve the issue}
53
- generated_html.must_include 'This task requires special handling'
54
- generated_html.must_include 'Investigate <a href="/additional_troubleshooting_page">custom link</a> on more details for this custom error'
51
+ _(generated_html).must_include 'A paused task represents a process that has not finished properly'
52
+ _(generated_html).must_match %r{See <a href=".*">troubleshooting documentation</a> for more details on how to resolve the issue}
53
+ _(generated_html).must_include 'This task requires special handling'
54
+ _(generated_html).must_include 'Investigate <a href="/additional_troubleshooting_page">custom link</a> on more details for this custom error'
55
55
  end
56
56
 
57
57
  it 'includes additional links' do
@@ -23,11 +23,11 @@ module ForemanTasks
23
23
  it 'notifies all admins about current amount of paused tasks when some paused task occurs' do
24
24
  trigger_task
25
25
  notification = user_notifications(admin_user).first
26
- notification.message.must_equal "There is 1 paused task in the system that need attention"
26
+ _(notification.message).must_equal "There is 1 paused task in the system that need attention"
27
27
  links = notification.actions['links']
28
- links.must_include('href' => '/foreman_tasks/tasks?search=state%3Dpaused',
28
+ _(links).must_include('href' => '/foreman_tasks/tasks?search=state%3Dpaused',
29
29
  'title' => 'List of tasks')
30
- links.must_include('name' => 'troubleshooting',
30
+ _(links).must_include('name' => 'troubleshooting',
31
31
  'title' => 'Troubleshooting Documentation',
32
32
  'description' => 'See %{link} for more details on how to resolve the issue',
33
33
  'href' => "https://theforeman.org/manuals/#{SETTINGS[:version].short}/tasks_troubleshooting.html#",
@@ -37,19 +37,19 @@ module ForemanTasks
37
37
  it 'aggregates the notification when multiple tasks get paused' do
38
38
  trigger_task
39
39
  recipient1 = NotificationRecipient.find_by(user_id: admin_user)
40
- recipient1.notification.message.must_match(/1 paused task/)
40
+ _(recipient1.notification.message).must_match(/1 paused task/)
41
41
 
42
42
  new_admin_user = FactoryBot.create(:user, :admin)
43
43
 
44
44
  trigger_task
45
45
 
46
- NotificationRecipient.find_by(id: recipient1.id).must_be_nil
47
- Notification.find_by(id: recipient1.notification.id).must_be_nil
46
+ _(NotificationRecipient.find_by(id: recipient1.id)).must_be_nil
47
+ _(Notification.find_by(id: recipient1.notification.id)).must_be_nil
48
48
  recipient2 = NotificationRecipient.find_by(user_id: admin_user)
49
- recipient2.notification.message.must_match(/2 paused tasks/)
49
+ _(recipient2.notification.message).must_match(/2 paused tasks/)
50
50
 
51
51
  new_recipient = NotificationRecipient.find_by(user_id: new_admin_user)
52
- new_recipient.notification.must_equal recipient2.notification
52
+ _(new_recipient.notification).must_equal recipient2.notification
53
53
  end
54
54
  end
55
55
 
@@ -59,11 +59,11 @@ module ForemanTasks
59
59
  notifications = user_notifications(task_owner)
60
60
  assert_equal 1, notifications.size, 'Only notification for the main action should be triggered'
61
61
  notification = notifications.first
62
- notification.message.must_equal "The task 'Dummy pause action' got paused"
62
+ _(notification.message).must_equal "The task 'Dummy pause action' got paused"
63
63
  links = notification.actions['links']
64
- links.must_include("href" => "/foreman_tasks/tasks/#{task.id}",
64
+ _(links).must_include("href" => "/foreman_tasks/tasks/#{task.id}",
65
65
  "title" => "Task Details")
66
- links.must_include('name' => 'troubleshooting',
66
+ _(links).must_include('name' => 'troubleshooting',
67
67
  'title' => 'Troubleshooting Documentation',
68
68
  'description' => 'See %{link} for more details on how to resolve the issue',
69
69
  'href' => "https://theforeman.org/manuals/#{SETTINGS[:version].short}/tasks_troubleshooting.html#Support::DummyPauseAction",
@@ -0,0 +1,60 @@
1
+ import { testActionSnapshotWithFixtures } from '@theforeman/test';
2
+ import { API } from 'foremanReact/redux/API';
3
+ import {
4
+ cancelTaskRequest,
5
+ resumeTaskRequest,
6
+ forceCancelTaskRequest,
7
+ unlockTaskRequest,
8
+ } from './';
9
+
10
+ jest.mock('foremanReact/components/common/table', () => ({
11
+ getTableItemsAction: jest.fn(controller => controller),
12
+ }));
13
+
14
+ jest.mock('foremanReact/redux/API');
15
+
16
+ const task = ['some-id', 'some-name'];
17
+
18
+ const fixtures = {
19
+ 'should cancelTaskRequest and succeed': () => cancelTaskRequest(...task),
20
+ 'should cancelTaskRequest and fail': () => {
21
+ API.post.mockImplementation(() =>
22
+ Promise.reject(new Error('Network Error'))
23
+ );
24
+ return cancelTaskRequest(...task);
25
+ },
26
+
27
+ 'should resumeTaskRequest and succeed': () => {
28
+ API.post.mockImplementation(() => ({ data: 'some-data' }));
29
+ return resumeTaskRequest(...task);
30
+ },
31
+ 'should resumeTaskRequest and fail': () => {
32
+ API.post.mockImplementation(() =>
33
+ Promise.reject(new Error('Network Error'))
34
+ );
35
+ return resumeTaskRequest(...task);
36
+ },
37
+ 'should forceCancelTaskRequest and succeed': () => {
38
+ API.post.mockImplementation(() => ({ data: 'some-data' }));
39
+ return forceCancelTaskRequest(...task);
40
+ },
41
+ 'should forceCancelTaskRequest and fail': () => {
42
+ API.post.mockImplementation(() =>
43
+ Promise.reject(new Error('Network Error'))
44
+ );
45
+ return forceCancelTaskRequest(...task);
46
+ },
47
+ 'should unlockTaskRequest and succeed': () => {
48
+ API.post.mockImplementation(() => ({ data: 'some-data' }));
49
+ return unlockTaskRequest(...task);
50
+ },
51
+ 'should unlockTaskRequest and fail': () => {
52
+ API.post.mockImplementation(() =>
53
+ Promise.reject(new Error('Network Error'))
54
+ );
55
+ return forceCancelTaskRequest(...task);
56
+ },
57
+ };
58
+ describe('Tasks actions', () => {
59
+ testActionSnapshotWithFixtures(fixtures);
60
+ });
@@ -2,6 +2,11 @@ import { translate as __, sprintf } from 'foremanReact/common/I18n';
2
2
  import { addToast } from 'foremanReact/redux/actions/toasts';
3
3
  import { TASKS_DASHBOARD_JS_QUERY_MODES } from '../TasksDashboard/TasksDashboardConstants';
4
4
  import { timeToHoursNumber } from '../TasksDashboard/TasksDashboardHelper';
5
+ import {
6
+ successToastData,
7
+ errorToastData,
8
+ warningToastData,
9
+ } from '../common/ToastsHelpers';
5
10
 
6
11
  export const convertDashboardQuery = query => {
7
12
  const {
@@ -29,14 +34,24 @@ export const convertDashboardQuery = query => {
29
34
  };
30
35
 
31
36
  export const resumeToastInfo = {
32
- resumed: { type: 'success', text: __('was resumed') },
33
- failed: { type: 'error', text: __('could not be resumed') },
34
- skipped: { type: 'warning', text: __('task has to be resumable') },
37
+ resumed: successToastData(__('was resumed')),
38
+ failed: errorToastData(__('could not be resumed')),
39
+ skipped: warningToastData(__('task has to be resumable')),
35
40
  };
36
41
 
37
42
  export const cancelToastInfo = {
38
- cancelled: { type: 'success', text: __('was cancelled') },
39
- skipped: { type: 'warning', text: __('task has to be cancellable') },
43
+ cancelled: successToastData(__('was cancelled')),
44
+ skipped: warningToastData(__('task has to be cancellable')),
45
+ };
46
+
47
+ export const forceCancelToastInfo = {
48
+ forceCancelled: successToastData(__('resources were unlocked with force.')),
49
+ failed: warningToastData(__('cannot be cancelled with force at the moment.')),
50
+ };
51
+
52
+ export const unlockToastInfo = {
53
+ unlocked: successToastData(__('resources were unlocked ')),
54
+ failed: warningToastData(__('resources cannot be unlocked at the moment.')),
40
55
  };
41
56
 
42
57
  export const toastDispatch = ({ type, name, toastInfo, dispatch }) => {
@@ -45,7 +60,7 @@ export const toastDispatch = ({ type, name, toastInfo, dispatch }) => {
45
60
  type: toastInfo[type].type,
46
61
  message: sprintf('%(name)s Task execution %(type)s', {
47
62
  name,
48
- type: toastInfo[type].text,
63
+ type: toastInfo[type].message,
49
64
  }),
50
65
  })
51
66
  );
@@ -1,8 +1,8 @@
1
- import { convertDashboardQuery } from '../TasksTableActionHelpers';
1
+ import { convertDashboardQuery } from './TaskActionHelpers';
2
2
  import {
3
3
  TASKS_DASHBOARD_JS_QUERY_MODES,
4
4
  TASKS_DASHBOARD_AVAILABLE_TIMES,
5
- } from '../../TasksDashboard/TasksDashboardConstants';
5
+ } from '../TasksDashboard/TasksDashboardConstants';
6
6
 
7
7
  let realDate;
8
8
 
@@ -0,0 +1,16 @@
1
+ export const UNLOCK_MODAL = 'unlockModal';
2
+ export const FORCE_UNLOCK_MODAL = 'forceUnlockModal';
3
+
4
+ export const TASKS_RESUME_REQUEST = 'TASKS_RESUME_REQUEST';
5
+ export const TASKS_RESUME_SUCCESS = 'TASKS_RESUME_SUCCESS';
6
+ export const TASKS_RESUME_FAILURE = 'TASKS_RESUME_FAILURE';
7
+ export const TASKS_CANCEL_REQUEST = 'TASKS_CANCEL_REQUEST';
8
+ export const TASKS_CANCEL_SUCCESS = 'TASKS_CANCEL_SUCCESS';
9
+ export const TASKS_CANCEL_FAILURE = 'TASKS_CANCEL_FAILURE';
10
+
11
+ export const TASKS_FORCE_CANCEL_REQUEST = 'TASKS_FORCE_CANCEL_REQUEST';
12
+ export const TASKS_FORCE_CANCEL_SUCCESS = 'TASKS_FORCE_CANCEL_SUCCESS';
13
+ export const TASKS_FORCE_CANCEL_FAILURE = 'TASKS_FORCE_CANCEL_FAILURE';
14
+ export const TASKS_UNLOCK_REQUEST = 'TASKS_UNLOCK_REQUEST';
15
+ export const TASKS_UNLOCK_SUCCESS = 'TASKS_UNLOCK_SUCCESS';
16
+ export const TASKS_UNLOCK_FAILURE = 'TASKS_UNLOCK_FAILURE';
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { translate as __, sprintf } from 'foremanReact/common/I18n';
4
+ import { ClickConfirmation } from '../common/ClickConfirmation';
5
+ import { UNLOCK_MODAL, FORCE_UNLOCK_MODAL } from './TaskActionsConstants';
6
+
7
+ const confirmationMessage = __(
8
+ 'I understand that this may cause harm and have working database backups of all backend services.'
9
+ );
10
+
11
+ export const UnlockModal = ({ onClick, id }) => (
12
+ <ClickConfirmation
13
+ id={id}
14
+ title={__('Unlock')}
15
+ body={__(
16
+ "This will unlock the resources that the task is running against. Please note that this might lead to inconsistent state and should be used with caution, after making sure that the task can't be resumed."
17
+ )}
18
+ confirmationMessage={confirmationMessage}
19
+ confirmAction={__('Unlock')}
20
+ onClick={onClick}
21
+ confirmType="warning"
22
+ />
23
+ );
24
+
25
+ export const ForceUnlockModal = ({ onClick, id, selectedRowsLen }) => (
26
+ <ClickConfirmation
27
+ id={id}
28
+ title={__('Force Unlock')}
29
+ body={sprintf(
30
+ __(
31
+ `Resources for %s task(s) will be unlocked and will not prevent other tasks from being run. As the task(s) might be still running, it should be avoided to use this unless you are really sure the task(s) got stuck.`
32
+ ),
33
+ selectedRowsLen
34
+ )}
35
+ confirmationMessage={confirmationMessage}
36
+ confirmAction={__('Force Unlock')}
37
+ onClick={onClick}
38
+ confirmType="danger"
39
+ />
40
+ );
41
+
42
+ UnlockModal.propTypes = {
43
+ onClick: PropTypes.func.isRequired,
44
+ id: PropTypes.string,
45
+ };
46
+
47
+ ForceUnlockModal.propTypes = {
48
+ onClick: PropTypes.func.isRequired,
49
+ id: PropTypes.string,
50
+ selectedRowsLen: PropTypes.number,
51
+ };
52
+
53
+ UnlockModal.defaultProps = {
54
+ id: UNLOCK_MODAL,
55
+ };
56
+
57
+ ForceUnlockModal.defaultProps = {
58
+ id: FORCE_UNLOCK_MODAL,
59
+ selectedRowsLen: 1,
60
+ };