foreman-tasks 1.2.0 → 3.0.1
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 +31 -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 +36 -60
- 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 +6 -3
- 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 +11 -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 +9 -9
- data/app/services/foreman_tasks/dashboard_table_filter.rb +5 -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 +2 -1
- data/db/migrate/20200517215015_rename_bookmarks_controller.rb +2 -2
- 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 +7 -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 +2 -7
- data/lib/foreman_tasks/tasks/cleanup.rake +2 -2
- data/lib/foreman_tasks/tasks/dynflow.rake +6 -0
- data/lib/foreman_tasks/tasks/export_tasks.rake +1 -1
- data/lib/foreman_tasks/version.rb +1 -1
- data/locale/en/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/en/foreman_tasks.po +50 -20
- data/locale/foreman_tasks.pot +173 -126
- 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 +17 -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 +2 -2
- data/webpack/ForemanTasks/Components/TaskActions/index.js +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/RunningSteps.js +17 -3
- data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +8 -153
- 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 +13 -70
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskButtons.test.js +95 -0
- 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 +78 -208
- 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 -95
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +3 -12
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +57 -28
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.fixtures.js +8 -0
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +8 -1
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +6 -6
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +84 -12
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsActions.test.js.snap +25 -21
- data/webpack/ForemanTasks/Components/TaskDetails/index.js +8 -3
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.scss +4 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.js +53 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.test.js +14 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.js +27 -19
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.scss +14 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.test.js +1 -34
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/{StoppedTasksCardHelper.js → StoppedTasksCardTable.js} +28 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardTable.test.js +54 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/OtherInfo.test.js.snap +48 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCard.test.js.snap +60 -1367
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCardTable.test.js.snap +960 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/__snapshots__/TasksCardsGrid.test.js.snap +14 -11
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardActions.js +1 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardConstants.js +2 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardSelectors.js +17 -11
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js +2 -2
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardSelectors.test.js +26 -14
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboard.test.js.snap +14 -11
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardSelectors.test.js.snap +38 -22
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +2 -0
- data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +25 -8
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +3 -3
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +6 -2
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksBulkActions.test.js +15 -2
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTablePage.test.js +2 -1
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksBulkActions.test.js.snap +48 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +39 -5
- 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/common/ActionButtons/ActionButton.js +39 -31
- data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.test.js +17 -8
- data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ActionButton.test.js.snap +8 -0
- data/webpack/ForemanTasks/Components/common/urlHelpers.js +7 -0
- data/webpack/ForemanTasks/ForemanTasksReducers.js +0 -2
- data/webpack/__mocks__/foremanReact/common/helpers.js +2 -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 +29 -11
- data/.travis.yml +0 -5
- data/script/travis_run_js_tests.sh +0 -7
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +0 -38
- 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 -67
- data/webpack/__mocks__/foremanReact/API.js +0 -7
@@ -31,9 +31,12 @@ module ForemanTasks
|
|
31
31
|
|
32
32
|
def cancel_step
|
33
33
|
task = find_dynflow_task
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
result = ForemanTasks.dynflow.world.event(task.external_id, params[:step_id].to_i, ::Dynflow::Action::Cancellable::Cancel).wait
|
35
|
+
if result.rejected?
|
36
|
+
render json: { error: result.reason }, status: :bad_request
|
37
|
+
else
|
38
|
+
render json: { statusText: 'OK' }
|
39
|
+
end
|
37
40
|
end
|
38
41
|
|
39
42
|
def cancel
|
@@ -82,7 +82,7 @@ module ForemanTasks
|
|
82
82
|
' — ',
|
83
83
|
content_tag(:span, nil, :class => 'time', :style => 'white-space: nowrap;') do
|
84
84
|
fields.time_select(attr, datetime_options.merge(:ignore_date => true), html_options)
|
85
|
-
end
|
85
|
+
end,
|
86
86
|
].join
|
87
87
|
end
|
88
88
|
end
|
@@ -139,7 +139,7 @@ module ForemanTasks
|
|
139
139
|
cronline_fieldset(f, triggering),
|
140
140
|
monthly_fieldset(f, triggering),
|
141
141
|
weekly_fieldset(f, triggering),
|
142
|
-
time_picker_fieldset(f, triggering)
|
142
|
+
time_picker_fieldset(f, triggering),
|
143
143
|
]
|
144
144
|
|
145
145
|
content_tag(:fieldset, nil, :id => 'trigger_mode_recurring', :class => "trigger_mode_form #{'hidden' unless triggering.recurring?}") do
|
@@ -158,7 +158,7 @@ module ForemanTasks
|
|
158
158
|
# TRANSLATORS: this translation is referring to an option which is a time interval
|
159
159
|
_('is month (range: 1-12)'),
|
160
160
|
# TRANSLATORS: this translation is referring to an option which is a time interval
|
161
|
-
_('is day of week (range: 0-6)')
|
161
|
+
_('is day of week (range: 0-6)'),
|
162
162
|
].map { |opt| content_tag(:li, opt) }.join
|
163
163
|
|
164
164
|
help = _("Cron line format 'a b c d e', where: %s") % "<br><ol type=\"a\">#{options}</ol>".html_safe
|
@@ -257,7 +257,7 @@ module Actions
|
|
257
257
|
if failed_proxy_tasks.count < options[:retry_count]
|
258
258
|
suspend do |suspended_action|
|
259
259
|
@world.clock.ping suspended_action,
|
260
|
-
Time.
|
260
|
+
Time.now.getlocal + options[:retry_interval],
|
261
261
|
event
|
262
262
|
end
|
263
263
|
else
|
@@ -70,6 +70,17 @@ module ForemanTasks
|
|
70
70
|
end)
|
71
71
|
scope :for_action_types, (->(action_types) { where('foreman_tasks_tasks.label IN (?)', Array(action_types)) })
|
72
72
|
|
73
|
+
apipie :class, "A class representing #{model_name.human} object" do
|
74
|
+
name 'Task'
|
75
|
+
refs 'Task'
|
76
|
+
sections only: %w[all additional]
|
77
|
+
property :main_action, object_of: 'Dynflow::Action', desc: 'Returns the main action of the task, e.g. Actions::RemoteExecution::RunHostJob'
|
78
|
+
property :label, String, desc: 'Returns the label of the task'
|
79
|
+
property :state, String, desc: 'Returns state of the task execution, e.g. "stopped"'
|
80
|
+
property :result, String, desc: 'Returns result of the task execution, e.g. "success"'
|
81
|
+
property :started_at, ActiveSupport::TimeWithZone, desc: 'Returns date with time the task started at'
|
82
|
+
property :ended_at, ActiveSupport::TimeWithZone, desc: 'Returns date with time the task ended at'
|
83
|
+
end
|
73
84
|
class Jail < Safemode::Jail
|
74
85
|
allow :started_at, :ended_at, :result, :state, :label, :main_action
|
75
86
|
end
|
@@ -46,7 +46,8 @@ module ForemanTasks
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def progress
|
49
|
-
execution_plan.try(:progress) || 0
|
49
|
+
progress_raw = execution_plan.try(:progress) || 0
|
50
|
+
progress_raw.round(2)
|
50
51
|
end
|
51
52
|
|
52
53
|
def execution_plan(silence_exception = true)
|
@@ -101,31 +102,28 @@ module ForemanTasks
|
|
101
102
|
|
102
103
|
def input_output_failed_steps
|
103
104
|
failed_steps.map do |f|
|
104
|
-
|
105
|
-
|
106
|
-
{
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
}
|
113
|
-
end
|
105
|
+
f_action = f.action(execution_plan)
|
106
|
+
{
|
107
|
+
error: ({ exception_class: f.error.exception_class, message: f.error.message, backtrace: f.error.backtrace } if f.error),
|
108
|
+
action_class: f.action_class.name,
|
109
|
+
state: f.state,
|
110
|
+
input: f_action.input.pretty_inspect,
|
111
|
+
output: f_action.output.pretty_inspect,
|
112
|
+
}
|
114
113
|
end
|
115
114
|
end
|
116
115
|
|
117
116
|
def input_output_running_steps
|
118
117
|
running_steps.map do |f|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
end
|
118
|
+
f_action = f.action(execution_plan)
|
119
|
+
{
|
120
|
+
id: f_action.id,
|
121
|
+
action_class: f.action_class.name,
|
122
|
+
state: f.state,
|
123
|
+
input: f_action.input.pretty_inspect,
|
124
|
+
output: f_action.output.pretty_inspect,
|
125
|
+
cancellable: cancellable_action?(f_action),
|
126
|
+
}
|
129
127
|
end
|
130
128
|
end
|
131
129
|
|
@@ -218,19 +216,17 @@ module ForemanTasks
|
|
218
216
|
fixed_count = 0
|
219
217
|
logger = Foreman::Logging.logger('foreman-tasks')
|
220
218
|
running.each do |task|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
logger.warn('Task %s updated at consistency check: %s' % [task.id, changes.inspect])
|
226
|
-
end
|
227
|
-
rescue => e
|
228
|
-
# if we fail updating the data from dynflow, it usually means there is something
|
229
|
-
# odd with the data consistency and at this point it is not possible to resume, switching
|
230
|
-
# the task to stopped/error
|
231
|
-
task.update(:state => 'stopped', :result => 'error')
|
232
|
-
Foreman::Logging.exception("Failed at consistency check for task #{task.id}", e, :logger => 'foreman-tasks')
|
219
|
+
changes = task.update_from_dynflow(task.execution_plan.to_hash)
|
220
|
+
unless changes.empty?
|
221
|
+
fixed_count += 1
|
222
|
+
logger.warn('Task %s updated at consistency check: %s' % [task.id, changes.inspect])
|
233
223
|
end
|
224
|
+
rescue => e
|
225
|
+
# if we fail updating the data from dynflow, it usually means there is something
|
226
|
+
# odd with the data consistency and at this point it is not possible to resume, switching
|
227
|
+
# the task to stopped/error
|
228
|
+
task.update(:state => 'stopped', :result => 'error')
|
229
|
+
Foreman::Logging.exception("Failed at consistency check for task #{task.id}", e, :logger => 'foreman-tasks')
|
234
230
|
end
|
235
231
|
fixed_count
|
236
232
|
end
|
@@ -4,7 +4,7 @@ module ForemanTasks
|
|
4
4
|
ERRONEOUS_STATUSES = [
|
5
5
|
{ :state => 'paused', :result => ANY },
|
6
6
|
{ :state => ANY, :result => 'error' },
|
7
|
-
{ :state => ANY, :result => 'warning' }
|
7
|
+
{ :state => ANY, :result => 'warning' },
|
8
8
|
].freeze
|
9
9
|
def is_erroneous(task)
|
10
10
|
remainder = ERRONEOUS_STATUSES.select do |status|
|
@@ -1,23 +1,23 @@
|
|
1
1
|
class Setting::ForemanTasks < Setting
|
2
2
|
def self.default_settings
|
3
3
|
[
|
4
|
-
set('foreman_tasks_sync_task_timeout', N_('Number of seconds to wait for synchronous task to finish.'), 120),
|
5
|
-
set('dynflow_enable_console', N_('Enable the dynflow console (/foreman_tasks/dynflow) for debugging'), true),
|
6
|
-
set('dynflow_console_require_auth', N_('Require user to be authenticated as user with admin rights when accessing dynflow console'), true),
|
7
|
-
set('foreman_tasks_proxy_action_retry_count', N_('Number of attempts to start a task on the smart proxy before failing'), 4),
|
8
|
-
set('foreman_tasks_proxy_action_retry_interval', N_('Time in seconds between retries'), 15),
|
9
|
-
set('foreman_tasks_proxy_batch_trigger', N_('Allow triggering tasks on the smart proxy in batches'), true),
|
10
|
-
set('foreman_tasks_proxy_batch_size', N_('Number of tasks which should be sent to the smart proxy in one request, if foreman_tasks_proxy_batch_trigger is enabled'), 100),
|
4
|
+
set('foreman_tasks_sync_task_timeout', N_('Number of seconds to wait for synchronous task to finish.'), 120, N_('Sync task timeout')),
|
5
|
+
set('dynflow_enable_console', N_('Enable the dynflow console (/foreman_tasks/dynflow) for debugging'), true, N_('Enable dynflow console')),
|
6
|
+
set('dynflow_console_require_auth', N_('Require user to be authenticated as user with admin rights when accessing dynflow console'), true, N_('Require auth for dynflow console')),
|
7
|
+
set('foreman_tasks_proxy_action_retry_count', N_('Number of attempts to start a task on the smart proxy before failing'), 4, N_('Proxy action retry count')),
|
8
|
+
set('foreman_tasks_proxy_action_retry_interval', N_('Time in seconds between retries'), 15, N_('Proxy action retry interval')),
|
9
|
+
set('foreman_tasks_proxy_batch_trigger', N_('Allow triggering tasks on the smart proxy in batches'), true, N_('Allow proxy batch tasks')),
|
10
|
+
set('foreman_tasks_proxy_batch_size', N_('Number of tasks which should be sent to the smart proxy in one request, if foreman_tasks_proxy_batch_trigger is enabled'), 100, N_('Proxy tasks batch size')),
|
11
11
|
set('foreman_tasks_troubleshooting_url',
|
12
12
|
N_('Url pointing to the task troubleshooting documentation. '\
|
13
13
|
'It should contain %{label} placeholder, that will be replaced with normalized task label '\
|
14
14
|
'(restricted to only alphanumeric characters)). %{version} placeholder is also available.'),
|
15
|
-
nil),
|
15
|
+
nil, N_('Tasks troubleshooting URL')),
|
16
16
|
set('foreman_tasks_polling_multiplier',
|
17
17
|
N_('Polling multiplier which is used to multiply the default polling intervals. '\
|
18
18
|
'This can be used to prevent polling too frequently for long running tasks.'),
|
19
19
|
1,
|
20
|
-
N_("Polling intervals multiplier"))
|
20
|
+
N_("Polling intervals multiplier")),
|
21
21
|
]
|
22
22
|
end
|
23
23
|
|
@@ -24,7 +24,11 @@ module ForemanTasks
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def scope_by(field)
|
27
|
-
|
27
|
+
if (field == :result) && (@params[field] == 'other')
|
28
|
+
@new_scope = @new_scope.where(:result => ['cancelled', 'pending'])
|
29
|
+
elsif @params[field].present?
|
30
|
+
@new_scope = @new_scope.where(field => @params[field])
|
31
|
+
end
|
28
32
|
end
|
29
33
|
|
30
34
|
def scope_by_time
|
@@ -37,6 +37,7 @@
|
|
37
37
|
|
38
38
|
<table class="<%= table_css_classes('table-condensed table-fixed') %>">
|
39
39
|
<thead>
|
40
|
+
<th class="col-md-1"><%= N_("ID") %></th>
|
40
41
|
<th><%= N_("Cron line") %></th>
|
41
42
|
<th><%= N_("Task count") %></th>
|
42
43
|
<th><%= N_("Action") %></th>
|
@@ -50,7 +51,8 @@
|
|
50
51
|
</thead>
|
51
52
|
<% @recurring_logics.each do |recurring_logic| %>
|
52
53
|
<tr>
|
53
|
-
<td><%= link_to(recurring_logic.
|
54
|
+
<td><%= link_to(recurring_logic.id, foreman_tasks_recurring_logic_path(recurring_logic)) %></td>
|
55
|
+
<td><%= recurring_logic.cron_line %></td>
|
54
56
|
<td><%= link_to(recurring_logic.tasks.count, foreman_tasks_tasks_url(:search => "task_group.id = #{recurring_logic.task_group.id}")) %></td>
|
55
57
|
<td><%= format_task_input(recurring_logic.tasks.first) %></td>
|
56
58
|
<td><%= recurring_logic.tasks.order(:started_at).where('started_at IS NOT NULL').last.try(:started_at) || "-" %></td>
|
data/config/routes.rb
CHANGED
@@ -7,6 +7,7 @@ Foreman::Application.routes.draw do
|
|
7
7
|
put :disable
|
8
8
|
end
|
9
9
|
collection do
|
10
|
+
get 'auto_complete_search'
|
10
11
|
post :clear_cancelled
|
11
12
|
end
|
12
13
|
end
|
@@ -50,7 +51,6 @@ Foreman::Application.routes.draw do
|
|
50
51
|
resources :tasks, :only => [:show, :index] do
|
51
52
|
member do
|
52
53
|
get :details
|
53
|
-
get :sub_tasks
|
54
54
|
end
|
55
55
|
collection do
|
56
56
|
post :bulk_search
|
@@ -58,6 +58,7 @@ Foreman::Application.routes.draw do
|
|
58
58
|
post :bulk_cancel
|
59
59
|
post :bulk_stop
|
60
60
|
get :summary
|
61
|
+
get '/:parent_task_id/sub_tasks', action: 'index'
|
61
62
|
get '/summary/:id/sub_tasks/', action: 'summary_sub_tasks'
|
62
63
|
post :callback
|
63
64
|
end
|
@@ -3,7 +3,7 @@ class RenameBookmarksController < ActiveRecord::Migration[5.2]
|
|
3
3
|
original_controller = 'foreman_tasks_tasks'
|
4
4
|
original_bookmarks = Bookmark.where(controller: original_controller)
|
5
5
|
original_bookmarks_names = Hash[original_bookmarks.pluck(:name, :id)]
|
6
|
-
|
6
|
+
|
7
7
|
new_controller = 'foreman_tasks/tasks'
|
8
8
|
new_bookmarks = Bookmark.where(controller: new_controller)
|
9
9
|
new_bookmarks.find_each do |new_bookmark|
|
@@ -18,7 +18,7 @@ class RenameBookmarksController < ActiveRecord::Migration[5.2]
|
|
18
18
|
original_bookmark.public == new_bookmark.public
|
19
19
|
|
20
20
|
if is_duplicated
|
21
|
-
original_bookmark.destroy
|
21
|
+
original_bookmark.destroy
|
22
22
|
else
|
23
23
|
modified_name = "#{name}_#{generate_token}"
|
24
24
|
original_bookmark.update(name: modified_name)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class AddTaskLockIndexOnResourceTypeAndTaskId < ActiveRecord::Migration[6.0]
|
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
|
@@ -9,9 +9,9 @@ blueprints = [
|
|
9
9
|
links:
|
10
10
|
[
|
11
11
|
href: "/foreman_tasks/tasks?search=#{CGI.escape('state=paused')}",
|
12
|
-
title: N_('List of tasks')
|
13
|
-
]
|
14
|
-
}
|
12
|
+
title: N_('List of tasks'),
|
13
|
+
],
|
14
|
+
},
|
15
15
|
},
|
16
16
|
|
17
17
|
{
|
@@ -24,9 +24,9 @@ blueprints = [
|
|
24
24
|
links:
|
25
25
|
[
|
26
26
|
path_method: :foreman_tasks_task_path,
|
27
|
-
title: N_('Task Details')
|
28
|
-
]
|
29
|
-
}
|
27
|
+
title: N_('Task Details'),
|
28
|
+
],
|
29
|
+
},
|
30
30
|
},
|
31
31
|
|
32
32
|
{
|
@@ -48,7 +48,7 @@ blueprints = [
|
|
48
48
|
name: 'tasks_bulk_stop',
|
49
49
|
level: 'info',
|
50
50
|
message: "DYNAMIC",
|
51
|
-
}
|
51
|
+
},
|
52
52
|
]
|
53
53
|
|
54
54
|
blueprints.each { |blueprint| UINotifications::Seed.new(blueprint).configure }
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Bookmark.without_auditing do
|
2
2
|
[
|
3
3
|
{ :name => 'running', :query => 'state = running' },
|
4
|
-
{ :name => 'failed', :query => 'state = paused or result = error or result = warning' }
|
4
|
+
{ :name => 'failed', :query => 'state = paused or result = error or result = warning' },
|
5
5
|
|
6
6
|
].each do |item|
|
7
7
|
next if Bookmark.where(:name => item[:name]).first
|
@@ -30,12 +30,10 @@ module ForemanTasks
|
|
30
30
|
actions_with_periods = {}
|
31
31
|
if cleanup_settings[:actions]
|
32
32
|
cleanup_settings[:actions].each do |action|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
Foreman::Logging.exception("Error handling #{action} cleanup settings", e)
|
38
|
-
end
|
33
|
+
action_class = action[:name].constantize
|
34
|
+
actions_with_periods[action_class] = action[:after]
|
35
|
+
rescue => e
|
36
|
+
Foreman::Logging.exception("Error handling #{action} cleanup settings", e)
|
39
37
|
end
|
40
38
|
end
|
41
39
|
(ForemanTasks.dynflow.world.action_classes - actions_with_periods.keys).each do |action_class|
|
@@ -15,7 +15,7 @@ module ForemanTasks
|
|
15
15
|
return @backup_settings if @backup_settings
|
16
16
|
backup_options = {
|
17
17
|
:backup_deleted_plans => true,
|
18
|
-
:backup_dir => default_backup_dir
|
18
|
+
:backup_dir => default_backup_dir,
|
19
19
|
}
|
20
20
|
settings = SETTINGS[:'foreman-tasks'] && SETTINGS[:'foreman-tasks'][:backup]
|
21
21
|
backup_options.merge!(settings) if settings
|
@@ -8,12 +8,10 @@ module ForemanTasks
|
|
8
8
|
# clear connection only if not running in some active record transaction already
|
9
9
|
clear_connections = ActiveRecord::Base.connection.open_transactions.zero?
|
10
10
|
super.tap do
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
:logger => 'dynflow')
|
16
|
-
end
|
11
|
+
on_execution_plan_save(execution_plan_id, value)
|
12
|
+
rescue => e
|
13
|
+
Foreman::Logging.exception('Error on on_execution_plan_save event', e,
|
14
|
+
:logger => 'dynflow')
|
17
15
|
end
|
18
16
|
ensure
|
19
17
|
::ActiveRecord::Base.clear_active_connections! if clear_connections
|
data/lib/foreman_tasks/engine.rb
CHANGED
@@ -34,7 +34,7 @@ module ForemanTasks
|
|
34
34
|
|
35
35
|
initializer 'foreman_tasks.register_plugin', :before => :finisher_hook do |_app|
|
36
36
|
Foreman::Plugin.register :"foreman-tasks" do
|
37
|
-
requires_foreman '>= 2.
|
37
|
+
requires_foreman '>= 2.2.0'
|
38
38
|
divider :top_menu, :parent => :monitor_menu, :last => true, :caption => N_('Foreman Tasks')
|
39
39
|
menu :top_menu, :tasks,
|
40
40
|
:url_hash => { :controller => 'foreman_tasks/tasks', :action => :index },
|
@@ -57,7 +57,7 @@ module ForemanTasks
|
|
57
57
|
|
58
58
|
permission :create_recurring_logics, {}, :resource_type => ForemanTasks::RecurringLogic.name
|
59
59
|
|
60
|
-
permission :view_recurring_logics, { :'foreman_tasks/recurring_logics' => [:index, :show],
|
60
|
+
permission :view_recurring_logics, { :'foreman_tasks/recurring_logics' => [:auto_complete_search, :index, :show],
|
61
61
|
:'foreman_tasks/api/recurring_logics' => [:index, :show] }, :resource_type => ForemanTasks::RecurringLogic.name
|
62
62
|
|
63
63
|
permission :edit_recurring_logics, { :'foreman_tasks/recurring_logics' => [:cancel, :enable, :disable, :clear_cancelled],
|
@@ -79,11 +79,6 @@ module ForemanTasks
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
-
initializer 'foreman_tasks.ignore_dynflow_tables' do |_app|
|
83
|
-
# Ignore Dynflow tables when schema-dumping. Dynflow tables are handled automatically by Dynflow.
|
84
|
-
ActiveRecord::SchemaDumper.ignore_tables << /^dynflow_.*$/
|
85
|
-
end
|
86
|
-
|
87
82
|
initializer 'foreman_tasks.apipie' do
|
88
83
|
# this condition is here for compatibility reason to work with Foreman 1.4.x
|
89
84
|
if Apipie.configuration.api_controllers_matcher.is_a?(Array) &&
|
@@ -14,7 +14,7 @@ namespace :foreman_tasks do
|
|
14
14
|
If TASK_SEARCH is set then AFTER, STATES can be set and it's used for cleanup. If TASK_SEARCH is not set then
|
15
15
|
the cleanup respects the configuration file and setting AFTER or STATES will throw exception.
|
16
16
|
DESC
|
17
|
-
task :run => 'environment' do
|
17
|
+
task :run => ['environment', 'dynflow:client'] do
|
18
18
|
options = {}
|
19
19
|
|
20
20
|
options[:filter] = ENV['TASK_SEARCH'] if ENV['TASK_SEARCH']
|
@@ -38,7 +38,7 @@ namespace :foreman_tasks do
|
|
38
38
|
end
|
39
39
|
|
40
40
|
desc 'Show the current configuration for auto-cleanup'
|
41
|
-
task :config => 'environment' do
|
41
|
+
task :config => ['environment', 'dynflow:client'] do
|
42
42
|
if ForemanTasks::Cleaner.cleanup_settings[:after]
|
43
43
|
puts _('The tasks will be deleted after %{after}') % { :after => ForemanTasks::Cleaner.cleanup_settings[:after] }
|
44
44
|
else
|