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.
- checksums.yaml +4 -4
- data/.github/workflows/js_tests.yml +27 -0
- data/.github/workflows/ruby_tests.yml +74 -0
- data/.rubocop.yml +12 -4
- data/.rubocop_todo.yml +32 -25
- data/Gemfile +5 -0
- data/README.md +2 -0
- data/app/controllers/foreman_tasks/api/tasks_controller.rb +63 -58
- data/app/controllers/foreman_tasks/concerns/parameters/triggering.rb +1 -1
- data/app/controllers/foreman_tasks/recurring_logics_controller.rb +7 -0
- data/app/controllers/foreman_tasks/tasks_controller.rb +9 -14
- data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +3 -3
- data/app/lib/actions/proxy_action.rb +1 -1
- data/app/models/foreman_tasks/recurring_logic.rb +1 -1
- data/app/models/foreman_tasks/task.rb +15 -0
- data/app/models/foreman_tasks/task/dynflow_task.rb +29 -33
- data/app/models/foreman_tasks/task/status_explicator.rb +1 -1
- data/app/models/foreman_tasks/triggering.rb +1 -1
- data/app/models/setting/foreman_tasks.rb +2 -2
- data/app/services/ui_notifications/tasks/task_bulk_stop.rb +36 -0
- data/app/views/foreman_tasks/api/tasks/details.json.rabl +0 -1
- data/app/views/foreman_tasks/api/tasks/index.json.rabl +2 -0
- data/app/views/foreman_tasks/api/tasks/show.json.rabl +2 -0
- data/app/views/foreman_tasks/recurring_logics/index.html.erb +3 -1
- data/config/routes.rb +3 -1
- data/db/migrate/20200517215015_rename_bookmarks_controller.rb +35 -0
- data/db/migrate/20200519093217_drop_dynflow_allow_dangerous_actions_setting.foreman_tasks.rb +5 -0
- data/db/migrate/20200611090846_add_task_lock_index_on_resource_type_and_task_id.rb +1 -1
- data/db/seeds.d/30-notification_blueprints.rb +14 -7
- data/db/seeds.d/61-foreman_tasks_bookmarks.rb +1 -1
- data/lib/foreman_tasks/cleaner.rb +4 -6
- data/lib/foreman_tasks/dynflow/configuration.rb +1 -1
- data/lib/foreman_tasks/dynflow/persistence.rb +4 -6
- data/lib/foreman_tasks/engine.rb +3 -8
- data/lib/foreman_tasks/version.rb +1 -1
- data/locale/action_names.rb +1 -1
- data/locale/en/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/en/foreman_tasks.po +270 -54
- data/locale/foreman_tasks.pot +630 -292
- data/locale/fr/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/fr/foreman_tasks.po +817 -0
- data/locale/ja/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/ja/foreman_tasks.po +817 -0
- data/locale/zh_CN/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/zh_CN/foreman_tasks.po +816 -0
- data/package.json +1 -1
- data/script/npm_link_foreman_js.sh +26 -0
- data/test/controllers/api/recurring_logics_controller_test.rb +1 -1
- data/test/controllers/api/tasks_controller_test.rb +7 -7
- data/test/controllers/tasks_controller_test.rb +6 -6
- data/test/core/unit/runner_test.rb +20 -20
- data/test/core/unit/task_launcher_test.rb +8 -8
- data/test/helpers/foreman_tasks/foreman_tasks_helper_test.rb +7 -7
- data/test/helpers/foreman_tasks/tasks_helper_test.rb +3 -3
- data/test/lib/actions/middleware/keep_current_request_id_test.rb +3 -3
- data/test/support/history_tasks_builder.rb +1 -1
- data/test/tasks/generate_task_actions_test.rb +1 -1
- data/test/unit/actions/action_with_sub_plans_test.rb +2 -2
- data/test/unit/actions/bulk_action_test.rb +6 -6
- data/test/unit/actions/proxy_action_test.rb +20 -20
- data/test/unit/actions/recurring_action_test.rb +30 -32
- data/test/unit/cleaner_test.rb +24 -24
- data/test/unit/dashboard_table_filter_test.rb +5 -5
- data/test/unit/otp_manager_test.rb +2 -2
- data/test/unit/proxy_selector_test.rb +9 -9
- data/test/unit/recurring_logic_test.rb +32 -32
- data/test/unit/remote_task_test.rb +2 -2
- data/test/unit/task_groups_test.rb +4 -4
- data/test/unit/task_test.rb +18 -18
- data/test/unit/triggering_test.rb +8 -8
- data/test/unit/troubleshooting_help_generator_test.rb +6 -6
- data/test/unit/ui_notifications_test.rb +11 -11
- data/webpack/ForemanTasks/Components/TaskActions/TaskAction.test.js +60 -0
- data/webpack/ForemanTasks/Components/{TasksTable/TasksTableActionHelpers.js → TaskActions/TaskActionHelpers.js} +21 -6
- data/webpack/ForemanTasks/Components/{TasksTable/__tests__/TasksTableActionHelpers.test.js → TaskActions/TaskActionHelpers.test.js} +2 -2
- data/webpack/ForemanTasks/Components/TaskActions/TaskActionsConstants.js +16 -0
- data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.js +60 -0
- data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.test.js +14 -0
- data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/TaskAction.test.js.snap +233 -0
- data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/UnlockModals.test.js.snap +25 -0
- data/webpack/ForemanTasks/Components/TaskActions/index.js +115 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/RunningSteps.js +17 -3
- data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +38 -205
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.js +168 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +6 -7
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskSkeleton.js +48 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +8 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +14 -7
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskButtons.test.js +95 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +0 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/RunningSteps.test.js.snap +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +90 -189
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskButtons.test.js.snap +212 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +8 -4
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +100 -53
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.scss +3 -14
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +57 -110
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +3 -17
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +57 -37
- data/webpack/ForemanTasks/Components/TaskDetails/TasksDetailsHelper.js +6 -1
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.fixtures.js +8 -0
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +13 -1
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +6 -6
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +86 -19
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsActions.test.js.snap +25 -21
- data/webpack/ForemanTasks/Components/TaskDetails/index.js +12 -11
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardActions.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js +2 -2
- data/webpack/ForemanTasks/Components/TasksTable/Components/ActionSelectButton.js +14 -1
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModal.js +83 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalActions.js +106 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalReducer.js +38 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +46 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModal.test.js +36 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalActions.test.js +205 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalReducer.test.js +27 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +55 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModal.test.js.snap +41 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalReducer.test.js.snap +19 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +32 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/index.js +29 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ActionSelectButton.test.js +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ActionSelectButton.test.js.snap +11 -0
- data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +135 -35
- data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +13 -9
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +26 -66
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +10 -12
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +30 -96
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableSchema.js +2 -2
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +8 -4
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksBulkActions.test.js +50 -2
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +3 -12
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActions.test.js +22 -26
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTablePage.test.js +2 -1
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +3 -14
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksBulkActions.test.js.snap +155 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +3 -14
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +17 -124
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +63 -133
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/actionCellFormatter.test.js.snap +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/selectionCellFormatter.test.js.snap +2 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/actionCellFormatter.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionCellFormatter.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/formatters/actionCellFormatter.js +10 -7
- data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionCellFormatter.js +7 -0
- data/webpack/ForemanTasks/Components/TasksTable/index.js +2 -2
- data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.js +55 -19
- data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.test.js +75 -19
- data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ActionButton.test.js.snap +88 -21
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.scss +9 -0
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.test.js +44 -0
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/__snapshots__/ClickConfirmation.test.js.snap +52 -0
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/index.js +59 -66
- data/webpack/ForemanTasks/Components/common/{ToastTypesConstants.js → ToastsHelpers/ToastTypesConstants.js} +0 -0
- data/webpack/ForemanTasks/Components/common/ToastsHelpers/index.js +15 -0
- data/webpack/ForemanTasks/Components/common/urlHelpers.js +7 -0
- data/webpack/ForemanTasks/ForemanTasksReducers.js +2 -2
- data/webpack/ForemanTasks/Routes/ForemanTasksRoutes.test.js +2 -1
- data/webpack/__mocks__/foremanReact/common/helpers.js +2 -0
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalHooks.js +2 -2
- data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +17 -3
- data/webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js +3 -0
- data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +10 -0
- data/webpack/__mocks__/foremanReact/redux/API/index.js +10 -0
- data/webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware.js +5 -0
- metadata +51 -28
- data/.travis.yml +0 -5
- data/script/travis_run_js_tests.sh +0 -7
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +0 -44
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsReducer.test.js +0 -33
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsReducer.test.js.snap +0 -26
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/integration.test.js.snap +0 -122
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +0 -63
- data/webpack/ForemanTasks/Components/TasksTable/Components/CancelConfirm.js +0 -53
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmationModals.js +0 -56
- data/webpack/ForemanTasks/Components/TasksTable/Components/ResumeConfirm.js +0 -52
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/CancelConfirm.test.js +0 -26
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ConfirmationModals.test.js +0 -24
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ResumeConfirm.test.js +0 -26
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/CancelConfirm.test.js.snap +0 -65
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ConfirmationModals.test.js.snap +0 -30
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ResumeConfirm.test.js.snap +0 -63
- data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.js +0 -23
- data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.test.js +0 -26
- data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.js +0 -23
- data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.test.js +0 -27
- data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/CancelButton.test.js.snap +0 -15
- data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ResumeButton.test.js.snap +0 -15
- 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
|
data/test/unit/task_test.rb
CHANGED
@@ -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:
|
33
|
-
failed:
|
34
|
-
skipped:
|
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:
|
39
|
-
skipped:
|
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].
|
63
|
+
type: toastInfo[type].message,
|
49
64
|
}),
|
50
65
|
})
|
51
66
|
);
|
@@ -1,8 +1,8 @@
|
|
1
|
-
import { convertDashboardQuery } from '
|
1
|
+
import { convertDashboardQuery } from './TaskActionHelpers';
|
2
2
|
import {
|
3
3
|
TASKS_DASHBOARD_JS_QUERY_MODES,
|
4
4
|
TASKS_DASHBOARD_AVAILABLE_TIMES,
|
5
|
-
} from '
|
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
|
+
};
|