foreman-tasks 1.0.0 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.eslintrc +2 -22
- data/.rubocop.yml +12 -12
- data/.rubocop_todo.yml +34 -116
- data/app/controllers/foreman_tasks/api/recurring_logics_controller.rb +20 -1
- data/app/controllers/foreman_tasks/api/tasks_controller.rb +38 -11
- data/app/controllers/foreman_tasks/concerns/hosts_controller_extension.rb +1 -1
- data/app/controllers/foreman_tasks/recurring_logics_controller.rb +19 -0
- data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +1 -3
- data/app/lib/actions/helpers/humanizer.rb +1 -3
- data/app/lib/actions/proxy_action.rb +33 -12
- data/app/lib/foreman_tasks/concerns/polling_action_extensions.rb +12 -0
- data/app/models/foreman_tasks/concerns/action_triggering.rb +1 -1
- data/app/models/foreman_tasks/recurring_logic.rb +1 -0
- data/app/models/foreman_tasks/remote_task.rb +1 -0
- data/app/models/foreman_tasks/task.rb +4 -0
- data/app/models/foreman_tasks/task/dynflow_task.rb +1 -1
- data/app/models/foreman_tasks/task/search.rb +11 -1
- data/app/models/setting/foreman_tasks.rb +6 -1
- data/app/services/foreman_tasks/troubleshooting_help_generator.rb +0 -4
- data/app/services/ui_notifications/tasks/task_bulk_cancel.rb +36 -0
- data/app/services/ui_notifications/tasks/task_bulk_resume.rb +38 -0
- data/app/views/foreman_tasks/api/recurring_logics/base.json.rabl +2 -1
- data/app/views/foreman_tasks/api/tasks/details.json.rabl +1 -0
- data/app/views/foreman_tasks/api/tasks/show.json.rabl +1 -1
- data/app/views/foreman_tasks/recurring_logics/index.html.erb +30 -0
- data/app/views/foreman_tasks/tasks/show.html.erb +3 -0
- data/{.babelrc.js → babel.config.js} +0 -0
- data/config/routes.rb +7 -0
- data/db/migrate/20200611090846_add_task_lock_index_on_resource_type_and_task_id.rb +9 -0
- data/db/seeds.d/30-notification_blueprints.rb +14 -0
- data/foreman-tasks.gemspec +5 -6
- data/gemfile.d/foreman-tasks.rb +1 -0
- data/lib/foreman_tasks/dynflow/console_authorizer.rb +2 -2
- data/lib/foreman_tasks/engine.rb +17 -14
- data/lib/foreman_tasks/tasks/cleanup.rake +3 -3
- data/lib/foreman_tasks/tasks/dynflow.rake +6 -0
- data/lib/foreman_tasks/tasks/export_tasks.rake +3 -3
- data/lib/foreman_tasks/test_extensions.rb +1 -1
- data/lib/foreman_tasks/version.rb +1 -1
- data/locale/action_names.rb +1 -1
- data/package.json +18 -71
- data/script/rails +2 -2
- data/script/travis_run_js_tests.sh +2 -2
- data/test/controllers/api/tasks_controller_test.rb +9 -0
- data/test/factories/task_factory.rb +34 -2
- data/test/foreman_tasks_test_helper.rb +4 -0
- data/test/lib/concerns/polling_action_extensions_test.rb +34 -0
- data/test/unit/actions/action_with_sub_plans_test.rb +1 -1
- data/test/unit/task_test.rb +160 -74
- data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +4 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +3 -12
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Errors.test.js +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Locks.test.js +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Raw.test.js +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +2 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +3 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +3 -9
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.stories.js +6 -2
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +4 -1
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsReducer.test.js +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +1 -0
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/index.js +2 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.stories.js +44 -40
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.stories.js +45 -40
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.stories.js +27 -22
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.stories.js +61 -56
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.stories.js +40 -35
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.stories.js +21 -20
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.stories.js +40 -39
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.stories.js +16 -17
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.test.js +1 -2
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.stories.mdx +57 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.stories.js +36 -18
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardConstants.js +5 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardHelper.js +3 -2
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboard.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardReducer.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardSelectors.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/Components/CancelConfirm.js +53 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmationModals.js +56 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ResumeConfirm.js +52 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/SelectAllAlert.js +43 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ActionSelectButton.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/CancelConfirm.test.js +26 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ConfirmationModals.test.js +24 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ResumeConfirm.test.js +26 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/SelectAllAlert.test.js +29 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/TableSelectionCell.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/TableSelectionHeaderCell.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/CancelConfirm.test.js.snap +65 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ConfirmationModals.test.js.snap +30 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ResumeConfirm.test.js.snap +63 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/SelectAllAlert.test.js.snap +75 -0
- data/webpack/ForemanTasks/Components/TasksTable/SubTasksPage.js +4 -1
- data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +164 -0
- data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +46 -22
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableActionHelpers.js +52 -0
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +88 -87
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +23 -9
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableHelpers.js +4 -3
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +128 -31
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableReducer.js +26 -9
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +24 -16
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/SubTasksPage.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksBulkActions.test.js +112 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksIndexPage.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +12 -5
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActionHelpers.test.js +46 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActions.test.js +28 -52
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableHelpers.test.js +17 -1
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTablePage.test.js +10 -2
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableReducer.test.js +28 -8
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +15 -5
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksBulkActions.test.js.snap +229 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +14 -5
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +56 -85
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +158 -32
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableReducer.test.js.snap +43 -16
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionHeaderCellFormatter.test.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionHeaderCellFormatter.js +2 -2
- data/webpack/ForemanTasks/Components/TasksTable/index.js +11 -4
- data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.js +4 -4
- data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.test.js +1 -1
- data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.test.js +1 -2
- data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.test.js +2 -2
- data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ActionButton.test.js.snap +3 -3
- data/webpack/ForemanTasks/Components/common/ToastTypesConstants.js +11 -0
- data/webpack/ForemanTasks/ForemanTasks.test.js +1 -1
- data/webpack/ForemanTasks/Routes/ForemanTasksRouter.test.js +1 -1
- data/webpack/ForemanTasks/Routes/ForemanTasksRoutes.test.js +2 -3
- data/webpack/ForemanTasks/Routes/ShowTask/__tests__/ShowTask.test.js +1 -1
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalActions.js +2 -0
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalHooks.js +10 -0
- data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +4 -0
- metadata +55 -24
- data/.storybook/addons.js +0 -2
- data/.storybook/config.js +0 -7
- data/.storybook/webpack.config.js +0 -84
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.stories.js +0 -23
- data/webpack/ForemanTasks/Components/TasksTable/Components/ActionConfirmation.js +0 -49
- data/webpack/ForemanTasks/Components/TasksTable/Components/CancelResumeConfirm.js +0 -51
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ActionConfirmation.test.js +0 -18
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/CancelResumeConfirm.test.js +0 -28
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ActionConfirmation.test.js.snap +0 -89
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/CancelResumeConfirm.test.js.snap +0 -37
- data/webpack/stories/index.js +0 -10
- data/webpack/stories/index.scss +0 -7
- data/webpack/test_setup.js +0 -7
@@ -1,5 +1,4 @@
|
|
1
1
|
module ForemanTasks
|
2
|
-
# rubocop:disable Metrics/ModuleLength
|
3
2
|
module ForemanTasksHelper
|
4
3
|
def recurring_logic_state(recurring_logic)
|
5
4
|
icon, status = case recurring_logic.state
|
@@ -28,7 +27,7 @@ module ForemanTasks
|
|
28
27
|
def troubleshooting_info_text
|
29
28
|
return if @task.state != 'paused' || @task.main_action.nil?
|
30
29
|
helper = TroubleshootingHelpGenerator.new(@task.main_action)
|
31
|
-
helper.
|
30
|
+
helper.generate_html
|
32
31
|
end
|
33
32
|
|
34
33
|
def username_link_task(owner, username)
|
@@ -209,5 +208,4 @@ module ForemanTasks
|
|
209
208
|
tags.join.html_safe
|
210
209
|
end
|
211
210
|
end
|
212
|
-
# rubocop:enable Metrics/ModuleLength
|
213
211
|
end
|
@@ -41,12 +41,7 @@ module Actions
|
|
41
41
|
with_connection_error_handling(event) do |event|
|
42
42
|
case event
|
43
43
|
when nil
|
44
|
-
|
45
|
-
on_resume
|
46
|
-
else
|
47
|
-
trigger_proxy_task
|
48
|
-
end
|
49
|
-
suspend
|
44
|
+
start_or_resume
|
50
45
|
when ::Dynflow::Action::Skip
|
51
46
|
# do nothing
|
52
47
|
when ::Dynflow::Action::Cancellable::Cancel
|
@@ -77,6 +72,12 @@ module Actions
|
|
77
72
|
end
|
78
73
|
end
|
79
74
|
|
75
|
+
def trigger_remote_task
|
76
|
+
suspend do |_suspended_action|
|
77
|
+
ForemanTasks::RemoteTask.batch_trigger(remote_task.operation, [remote_task])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
80
81
|
def proxy_input(task_id = task.id)
|
81
82
|
input.merge(:callback => { :task_id => task_id,
|
82
83
|
:step_id => run_step_id })
|
@@ -88,7 +89,7 @@ module Actions
|
|
88
89
|
if response['result'] == 'error'
|
89
90
|
raise ::Foreman::Exception, _('The smart proxy task %s failed.') % proxy_task_id
|
90
91
|
else
|
91
|
-
on_data(response
|
92
|
+
on_data(get_proxy_data(response))
|
92
93
|
end
|
93
94
|
else
|
94
95
|
suspend
|
@@ -154,10 +155,8 @@ module Actions
|
|
154
155
|
if output.key?(:proxy_output) || state == :error
|
155
156
|
output.fetch(:proxy_output, {})
|
156
157
|
elsif live && proxy_task_id
|
157
|
-
|
158
|
-
|
159
|
-
end
|
160
|
-
proxy_data.fetch('output', {})
|
158
|
+
response = proxy.status_of_task(proxy_task_id)
|
159
|
+
get_proxy_data(response)
|
161
160
|
else
|
162
161
|
{}
|
163
162
|
end
|
@@ -205,6 +204,26 @@ module Actions
|
|
205
204
|
|
206
205
|
private
|
207
206
|
|
207
|
+
def start_or_resume
|
208
|
+
if remote_task
|
209
|
+
if remote_task.state == 'external'
|
210
|
+
trigger_remote_task
|
211
|
+
else
|
212
|
+
on_resume
|
213
|
+
end
|
214
|
+
else
|
215
|
+
trigger_proxy_task
|
216
|
+
end
|
217
|
+
suspend
|
218
|
+
end
|
219
|
+
|
220
|
+
def get_proxy_data(response)
|
221
|
+
proxy_data = response['actions'].detect do |action|
|
222
|
+
action['class'] == proxy_action_name || action.fetch('input', {})['proxy_operation_name'] == proxy_operation_name
|
223
|
+
end
|
224
|
+
proxy_data.fetch('output', {})
|
225
|
+
end
|
226
|
+
|
208
227
|
def proxy_version(proxy)
|
209
228
|
match = proxy.statuses[:version].version['version'].match(/(\d+)\.(\d+)\.(\d+)/)
|
210
229
|
{ :major => match[1].to_i, :minor => match[2].to_i, :patch => match[3].to_i }
|
@@ -247,10 +266,12 @@ module Actions
|
|
247
266
|
end
|
248
267
|
|
249
268
|
def prepare_remote_task
|
269
|
+
state = input[:use_concurrency_control] ? 'external' : 'new'
|
250
270
|
::ForemanTasks::RemoteTask.new(:execution_plan_id => execution_plan_id,
|
251
271
|
:proxy_url => input[:proxy_url],
|
252
272
|
:step_id => run_step_id,
|
253
|
-
:operation => proxy_operation_name
|
273
|
+
:operation => proxy_operation_name,
|
274
|
+
:state => state)
|
254
275
|
end
|
255
276
|
|
256
277
|
def proxy_task_id
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module ForemanTasks
|
2
|
+
module Concerns
|
3
|
+
module PollingActionExtensions
|
4
|
+
def poll_intervals
|
5
|
+
multiplier = Setting[:foreman_tasks_polling_multiplier] || 1
|
6
|
+
|
7
|
+
# Prevent the intervals from going below 0.5 seconds
|
8
|
+
super.map { |interval| [interval * multiplier, 0.5].max }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -14,6 +14,7 @@ module ForemanTasks
|
|
14
14
|
scoped_search :on => :max_iteration, :complete_value => false, :rename => :iteration_limit
|
15
15
|
scoped_search :on => :iteration, :complete_value => false
|
16
16
|
scoped_search :on => :cron_line, :complete_value => true
|
17
|
+
scoped_search :on => :state, :complete_value => true
|
17
18
|
|
18
19
|
before_create do
|
19
20
|
task_group.save
|
@@ -42,6 +42,10 @@ module ForemanTasks
|
|
42
42
|
scoped_search :on => :start_at, :complete_value => false
|
43
43
|
scoped_search :on => :ended_at, :complete_value => false
|
44
44
|
scoped_search :on => :parent_task_id, :complete_value => true
|
45
|
+
scoped_search :on => :duration, :complete_value => false, :ext_method => :search_by_duration, :operators => %w[> >= = <= <], :only_explicit => true
|
46
|
+
|
47
|
+
# Note: the following searches may return duplicates, this is due to
|
48
|
+
# one task maybe having multiple locks (e.g. read/write) for the same resource_id
|
45
49
|
scoped_search :relation => :locks, :on => :resource_id, :complete_value => false, :rename => 'location_id', :ext_method => :search_by_taxonomy, :only_explicit => true
|
46
50
|
scoped_search :relation => :locks, :on => :resource_id, :complete_value => false, :rename => 'organization_id', :ext_method => :search_by_taxonomy, :only_explicit => true
|
47
51
|
scoped_search :relation => :locks, :on => :resource_type, :complete_value => true, :rename => 'resource_type', :ext_method => :search_by_generic_resource, :only_explicit => true
|
@@ -228,7 +228,7 @@ module ForemanTasks
|
|
228
228
|
# if we fail updating the data from dynflow, it usually means there is something
|
229
229
|
# odd with the data consistency and at this point it is not possible to resume, switching
|
230
230
|
# the task to stopped/error
|
231
|
-
task.
|
231
|
+
task.update(:state => 'stopped', :result => 'error')
|
232
232
|
Foreman::Logging.exception("Failed at consistency check for task #{task.id}", e, :logger => 'foreman-tasks')
|
233
233
|
end
|
234
234
|
end
|
@@ -4,7 +4,8 @@ module ForemanTasks
|
|
4
4
|
def search_by_generic_resource(key, operator, value)
|
5
5
|
key = 'resource_type' if key.blank?
|
6
6
|
key_name = connection.quote_column_name(key.sub(/^.*\./, ''))
|
7
|
-
|
7
|
+
value = value.split(',') if operator.index(/IN/i)
|
8
|
+
condition = sanitize_sql_for_conditions(["foreman_tasks_locks.#{key_name} #{operator} (?)", value])
|
8
9
|
|
9
10
|
{ :conditions => condition, :joins => :locks }
|
10
11
|
end
|
@@ -22,6 +23,15 @@ module ForemanTasks
|
|
22
23
|
sql = "foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_id #{operator} ? OR foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_id IS NULL"
|
23
24
|
{ :conditions => sanitize_sql_for_conditions([sql, value]), :joins => joins }
|
24
25
|
end
|
26
|
+
|
27
|
+
# Expects the time in the format "\d+ (seconds|minutes|hours|days|months|years)"
|
28
|
+
SUPPORTED_DURATION_FORMAT = /\A\s*(\d+(\s+\b(seconds?|minutes?|hours?|days?|months?|years?)\b)?)\b\s*\z/i.freeze
|
29
|
+
def search_by_duration(_key, operator, value)
|
30
|
+
raise "Unsupported duration '#{value}' specified for searching" unless value =~ SUPPORTED_DURATION_FORMAT
|
31
|
+
value = value.strip
|
32
|
+
{ :conditions => "coalesce(ended_at, current_timestamp) - coalesce(coalesce(started_at, ended_at), current_timestamp) #{operator} ?::interval",
|
33
|
+
:parameter => [value] }
|
34
|
+
end
|
25
35
|
end
|
26
36
|
end
|
27
37
|
end
|
@@ -13,7 +13,12 @@ class Setting::ForemanTasks < Setting
|
|
13
13
|
N_('Url pointing to the task troubleshooting documentation. '\
|
14
14
|
'It should contain %{label} placeholder, that will be replaced with normalized task label '\
|
15
15
|
'(restricted to only alphanumeric characters)). %{version} placeholder is also available.'),
|
16
|
-
nil)
|
16
|
+
nil),
|
17
|
+
set('foreman_tasks_polling_multiplier',
|
18
|
+
N_('Polling multiplier which is used to multiply the default polling intervals. '\
|
19
|
+
'This can be used to prevent polling too frequently for long running tasks.'),
|
20
|
+
1,
|
21
|
+
N_("Polling intervals multiplier"))
|
17
22
|
]
|
18
23
|
end
|
19
24
|
|
@@ -44,10 +44,6 @@ module ForemanTasks
|
|
44
44
|
# rubocop:enable Rails/OutputSafety
|
45
45
|
end
|
46
46
|
|
47
|
-
def generate_text
|
48
|
-
(description + link_descriptions_html).join("\n")
|
49
|
-
end
|
50
|
-
|
51
47
|
def link_descriptions_html
|
52
48
|
links.map do |link|
|
53
49
|
link.description % { link: %(<a href="%{href}">%{title}</a>) % link.to_h }
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module UINotifications
|
2
|
+
module Tasks
|
3
|
+
class TaskBulkCancel < ::UINotifications::Base
|
4
|
+
def initialize(task, cancelled_length, skipped_length)
|
5
|
+
@subject = task
|
6
|
+
@cancelled_length = cancelled_length
|
7
|
+
@skipped_length = skipped_length
|
8
|
+
end
|
9
|
+
|
10
|
+
def create
|
11
|
+
Notification.create!(
|
12
|
+
initiator: initiator,
|
13
|
+
audience: audience,
|
14
|
+
subject: subject,
|
15
|
+
notification_blueprint: blueprint,
|
16
|
+
message: message,
|
17
|
+
notification_recipients: [NotificationRecipient.create({ :user => User.current })]
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def audience
|
22
|
+
Notification::AUDIENCE_GLOBAL
|
23
|
+
end
|
24
|
+
|
25
|
+
def message
|
26
|
+
('%{cancelled} Tasks were cancelled. %{skipped} Tasks were skipped. ' %
|
27
|
+
{ cancelled: @cancelled_length,
|
28
|
+
skipped: @skipped_length })
|
29
|
+
end
|
30
|
+
|
31
|
+
def blueprint
|
32
|
+
@blueprint ||= NotificationBlueprint.find_by(name: 'tasks_bulk_cancel')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module UINotifications
|
2
|
+
module Tasks
|
3
|
+
class TaskBulkResume < ::UINotifications::Base
|
4
|
+
def initialize(task, resumed_length, failed_length, skipped_length)
|
5
|
+
@subject = task
|
6
|
+
@resumed_length = resumed_length
|
7
|
+
@failed_length = failed_length
|
8
|
+
@skipped_length = skipped_length
|
9
|
+
end
|
10
|
+
|
11
|
+
def create
|
12
|
+
Notification.create!(
|
13
|
+
initiator: initiator,
|
14
|
+
audience: audience,
|
15
|
+
subject: subject,
|
16
|
+
notification_blueprint: blueprint,
|
17
|
+
message: message,
|
18
|
+
notification_recipients: [NotificationRecipient.create({ :user => User.current })]
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def audience
|
23
|
+
Notification::AUDIENCE_USER
|
24
|
+
end
|
25
|
+
|
26
|
+
def message
|
27
|
+
('%{resumed} Tasks were resumed. %{failed} Tasks failed to resume. %{skipped} Tasks were skipped. ' %
|
28
|
+
{ resumed: @resumed_length,
|
29
|
+
failed: @failed_length,
|
30
|
+
skipped: @skipped_length })
|
31
|
+
end
|
32
|
+
|
33
|
+
def blueprint
|
34
|
+
@blueprint ||= NotificationBlueprint.find_by(name: 'tasks_bulk_resume')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -2,5 +2,5 @@ object @task if @task
|
|
2
2
|
|
3
3
|
attributes :id, :label, :pending, :action
|
4
4
|
attributes :username, :started_at, :ended_at, :state, :result, :progress
|
5
|
-
attributes :input, :output, :humanized, :cli_example
|
5
|
+
attributes :input, :output, :humanized, :cli_example, :start_at
|
6
6
|
node(:available_actions) { |t| { cancellable: t.execution_plan&.cancellable?, resumable: t.resumable? } }
|
@@ -5,6 +5,36 @@
|
|
5
5
|
<%= alert(:class => 'alert-info', :id => 'multiple-alert', :close => false, :header => '', :text => @errors) %>
|
6
6
|
<% end %>
|
7
7
|
|
8
|
+
<% if authorized_for(:permission => :edit_recurring_logics, :auth_object => @recurring_logics) %>
|
9
|
+
<% title_actions link_to(_('Clear Cancelled'),
|
10
|
+
clear_cancelled_foreman_tasks_recurring_logics_path,
|
11
|
+
class: ['btn', 'btn-sm', 'btn-danger'],
|
12
|
+
:'data-toggle' => "modal",
|
13
|
+
:'data-target' => "#clear_modal")
|
14
|
+
%>
|
15
|
+
|
16
|
+
<div class="modal fade" id="clear_modal" tabindex="-1" role="dialog" aria-labelledby="Deploy" aria-hidden="true">
|
17
|
+
<div class="modal-dialog">
|
18
|
+
<div class="modal-content">
|
19
|
+
<div class="modal-header">
|
20
|
+
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
21
|
+
<h2 class="modal-title" id="deploy_modal_label">
|
22
|
+
<span class="glyphicon glyphicon-warning-sign"></span>
|
23
|
+
<%= _("Clear Cancelled") %>
|
24
|
+
</h2>
|
25
|
+
</div>
|
26
|
+
<div class="modal-body">
|
27
|
+
<%= _("This action will delete all cancelled recurring logics. Please note that this action can't be reversed.") %>
|
28
|
+
</div>
|
29
|
+
<div class="modal-footer">
|
30
|
+
<button type="button" class="btn btn-default" data-dismiss="modal"><%= _("Cancel") %></button>
|
31
|
+
<%= link_to(_('Clear Cancelled'), clear_cancelled_foreman_tasks_recurring_logics_path, method: :post, class: 'btn btn-danger modal-submit') %>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
<% end %>
|
37
|
+
|
8
38
|
<table class="<%= table_css_classes('table-condensed table-fixed') %>">
|
9
39
|
<thead>
|
10
40
|
<th><%= N_("Cron line") %></th>
|
File without changes
|
data/config/routes.rb
CHANGED
@@ -6,6 +6,9 @@ Foreman::Application.routes.draw do
|
|
6
6
|
put :enable
|
7
7
|
put :disable
|
8
8
|
end
|
9
|
+
collection do
|
10
|
+
post :clear_cancelled
|
11
|
+
end
|
9
12
|
end
|
10
13
|
|
11
14
|
resources :tasks, :only => [:show] do
|
@@ -39,6 +42,9 @@ Foreman::Application.routes.draw do
|
|
39
42
|
member do
|
40
43
|
post :cancel
|
41
44
|
end
|
45
|
+
collection do
|
46
|
+
post :bulk_destroy
|
47
|
+
end
|
42
48
|
end
|
43
49
|
|
44
50
|
resources :tasks, :only => [:show, :index] do
|
@@ -49,6 +55,7 @@ Foreman::Application.routes.draw do
|
|
49
55
|
collection do
|
50
56
|
post :bulk_search
|
51
57
|
post :bulk_resume
|
58
|
+
post :bulk_cancel
|
52
59
|
get :summary
|
53
60
|
get '/summary/:id/sub_tasks/', action: 'summary_sub_tasks'
|
54
61
|
post :callback
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class AddTaskLockIndexOnResourceTypeAndTaskId < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
add_index :foreman_tasks_locks, [:task_id, :resource_type, :resource_id], name: 'index_tasks_locks_on_task_id_resource_type_and_resource_id'
|
4
|
+
# These indexes are not needed as they can be gained from partial index lookups
|
5
|
+
[:task_id, :name, :resource_type].each do |index|
|
6
|
+
remove_index :foreman_tasks_locks, index if index_exists?(:foreman_tasks_locks, index)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -27,6 +27,20 @@ blueprints = [
|
|
27
27
|
title: N_('Task Details')
|
28
28
|
]
|
29
29
|
}
|
30
|
+
},
|
31
|
+
|
32
|
+
{
|
33
|
+
group: N_('Tasks'),
|
34
|
+
name: 'tasks_bulk_resume',
|
35
|
+
level: 'info',
|
36
|
+
message: "DYNAMIC",
|
37
|
+
},
|
38
|
+
|
39
|
+
{
|
40
|
+
group: N_('Tasks'),
|
41
|
+
name: 'tasks_bulk_cancel',
|
42
|
+
level: 'info',
|
43
|
+
message: "DYNAMIC",
|
30
44
|
}
|
31
45
|
]
|
32
46
|
|
data/foreman-tasks.gemspec
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
$LOAD_PATH.push File.expand_path("../lib", __FILE__)
|
1
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
4
2
|
|
5
3
|
# Maintain your gem's version:
|
6
4
|
require "foreman_tasks/version"
|
@@ -29,11 +27,12 @@ same resource. It also optionally provides Dynflow infrastructure for using it f
|
|
29
27
|
s.test_files = `git ls-files test`.split("\n")
|
30
28
|
s.extra_rdoc_files = Dir['README*', 'LICENSE']
|
31
29
|
|
32
|
-
s.add_dependency "foreman-tasks-core"
|
33
30
|
s.add_dependency "dynflow", '>= 1.2.3'
|
34
|
-
s.add_dependency "
|
35
|
-
s.add_dependency "parse-cron", '~> 0.1.4'
|
31
|
+
s.add_dependency "foreman-tasks-core"
|
36
32
|
s.add_dependency "get_process_mem" # for memory polling
|
33
|
+
s.add_dependency "parse-cron", '~> 0.1.4'
|
34
|
+
s.add_dependency "sinatra" # for Dynflow web console
|
37
35
|
|
38
36
|
s.add_development_dependency 'factory_bot_rails', '~> 4.8.0'
|
37
|
+
s.add_development_dependency 'sqlite3'
|
39
38
|
end
|