foreman-tasks 5.2.2 → 6.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/ruby_tests.yml +7 -18
- data/.rubocop.yml +1 -0
- data/app/lib/actions/base.rb +1 -0
- data/app/lib/actions/foreman/host/import_facts.rb +1 -1
- data/app/lib/actions/helpers/lifecycle_logging.rb +1 -1
- data/app/lib/actions/middleware/rails_executor_wrap.rb +2 -2
- data/app/lib/actions/middleware/watch_delegated_proxy_sub_tasks.rb +18 -11
- data/app/lib/actions/proxy_action.rb +2 -2
- data/app/lib/actions/task_synchronization.rb +65 -0
- data/app/lib/actions/trigger_proxy_batch.rb +1 -1
- data/app/models/foreman_tasks/lock.rb +1 -1
- data/app/models/foreman_tasks/remote_task.rb +10 -3
- data/app/models/foreman_tasks/task/dynflow_task.rb +20 -21
- data/app/views/foreman_tasks/api/locks/show.json.rabl +4 -0
- data/config/routes.rb +1 -1
- data/db/migrate/20210708123832_add_parent_task_id_to_remote_tasks.foreman_tasks.rb +5 -0
- data/db/migrate/20211123170430_tasks_settings_to_dsl_category.rb +5 -0
- data/foreman-tasks.gemspec +1 -1
- data/lib/foreman_tasks/dynflow/configuration.rb +1 -6
- data/lib/foreman_tasks/dynflow.rb +1 -1
- data/lib/foreman_tasks/engine.rb +56 -9
- data/lib/foreman_tasks/test_helpers.rb +1 -1
- data/lib/foreman_tasks/version.rb +1 -1
- data/locale/action_names.rb +2 -3
- data/locale/en/foreman_tasks.po +27 -3
- data/locale/foreman_tasks.pot +230 -176
- data/locale/fr/foreman_tasks.po +27 -3
- data/locale/ja/foreman_tasks.po +27 -3
- data/locale/zh_CN/foreman_tasks.po +27 -3
- data/test/controllers/api/tasks_controller_test.rb +1 -2
- data/test/factories/task_factory.rb +1 -1
- data/test/lib/actions/middleware/keep_current_taxonomies_test.rb +9 -1
- data/test/support/dummy_dynflow_action.rb +1 -1
- data/test/support/dummy_proxy_action.rb +1 -1
- data/test/unit/actions/proxy_action_test.rb +19 -13
- data/test/unit/actions/trigger_proxy_batch_test.rb +0 -1
- data/test/unit/troubleshooting_help_generator_test.rb +0 -1
- data/test/unit/ui_notifications_test.rb +0 -1
- data/webpack/ForemanTasks/Components/TaskActions/TaskActionHelpers.js +1 -1
- data/webpack/ForemanTasks/Components/TaskActions/index.js +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/Locks.js +28 -14
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Locks.test.js.snap +50 -42
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +2 -28
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +5 -9
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableReducer.js +1 -5
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +2 -2
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +1 -4
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +1 -6
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +1 -6
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTable.test.js.snap +2 -22
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +2 -12
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableReducer.test.js.snap +1 -4
- data/webpack/ForemanTasks/Components/TasksTable/index.js +2 -2
- data/webpack/__mocks__/foremanReact/components/Pagination/index.js +2 -0
- data/webpack/__mocks__/foremanReact/{redux/actions/toasts.js → components/ToastsList/index.js} +0 -0
- metadata +8 -7
- data/app/models/setting/foreman_tasks.rb +0 -29
- data/lib/foreman_tasks/dynflow/persistence.rb +0 -46
- data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7fe4afd0fbe9eaa5cb5587310ddddd1538453e733b48b6f927e6bc14fa4ad42e
|
4
|
+
data.tar.gz: 27591131ac0329e66625a15c4b512fa7a24b23b3623abdc1eaef40fee7bdea9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 042c221e1f3c01b2d38b2011165479282165846d9b46923b5ef7cc4fc8f91c3ab6ff5921bd229a4a26dbf661dccff3a9d0f0d474e11eb18b074880fc8fc25870
|
7
|
+
data.tar.gz: 4fdf7dfc1836bd8b4ea0490f8c7a894569c7ccf9eca811945b517f7aedface6b04c0c6bbe9c7f34a7b7bbea77328edaadd27ebb624bc29c4acae2eb86bc25624
|
@@ -4,6 +4,7 @@ env:
|
|
4
4
|
RAILS_ENV: test
|
5
5
|
DATABASE_URL: postgresql://postgres:@localhost/test
|
6
6
|
DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL: true
|
7
|
+
BUNDLE_WITHOUT: "journald:development:console:mysql2:sqlite:libvirt"
|
7
8
|
jobs:
|
8
9
|
rubocop:
|
9
10
|
runs-on: ubuntu-latest
|
@@ -13,10 +14,7 @@ jobs:
|
|
13
14
|
uses: ruby/setup-ruby@v1
|
14
15
|
with:
|
15
16
|
ruby-version: 2.7
|
16
|
-
|
17
|
-
run: |
|
18
|
-
gem install bundler
|
19
|
-
bundle install --jobs=3 --retry=3
|
17
|
+
bundler-cache: true
|
20
18
|
- name: Run rubocop
|
21
19
|
run: bundle exec rubocop
|
22
20
|
test_ruby:
|
@@ -43,30 +41,21 @@ jobs:
|
|
43
41
|
- uses: actions/checkout@v2
|
44
42
|
with:
|
45
43
|
path: foreman-tasks
|
44
|
+
- name: Setup Plugin in Foreman
|
45
|
+
run: |
|
46
|
+
echo "gem 'foreman-tasks', path: './foreman-tasks'" > bundler.d/foreman-tasks.local.rb
|
47
|
+
echo "gem 'sqlite3'" >> bundler.d/foreman-tasks.local.rb
|
46
48
|
- name: Setup Ruby
|
47
49
|
uses: ruby/setup-ruby@v1
|
48
50
|
with:
|
49
51
|
ruby-version: ${{ matrix.ruby-version }}
|
52
|
+
bundler-cache: true
|
50
53
|
- name: Setup Node
|
51
54
|
uses: actions/setup-node@v1
|
52
55
|
with:
|
53
56
|
node-version: ${{ matrix.node-version }}
|
54
|
-
- uses: actions/cache@v2
|
55
|
-
with:
|
56
|
-
path: vendor/bundle
|
57
|
-
key: ${{ runner.os }}-fgems-${{ matrix.ruby-version }}-${{ hashFiles('Gemfile.lock') }}
|
58
|
-
restore-keys: |
|
59
|
-
${{ runner.os }}-fgems-${{ matrix.ruby-version }}-
|
60
|
-
- name: Setup Bundler
|
61
|
-
run: |
|
62
|
-
echo "gem 'foreman-tasks', path: './foreman-tasks'" > bundler.d/foreman-tasks.local.rb
|
63
|
-
echo "gem 'sqlite3'" >> bundler.d/foreman-tasks.local.rb
|
64
|
-
gem install bundler
|
65
|
-
bundle config set without journald development console libvirt
|
66
|
-
bundle config set path vendor/bundle
|
67
57
|
- name: Prepare test env
|
68
58
|
run: |
|
69
|
-
bundle install --jobs=3 --retry=3
|
70
59
|
bundle exec rake db:create
|
71
60
|
bundle exec rake db:migrate
|
72
61
|
- name: Run plugin tests
|
data/.rubocop.yml
CHANGED
data/app/lib/actions/base.rb
CHANGED
@@ -26,7 +26,7 @@ module Actions
|
|
26
26
|
def run
|
27
27
|
::User.as :admin do
|
28
28
|
host = ::Host.find(input[:host][:id])
|
29
|
-
state = host.import_facts(input[:facts], proxy)
|
29
|
+
state = ::HostFactImporter.new(host).import_facts(input[:facts], proxy)
|
30
30
|
output[:state] = state
|
31
31
|
end
|
32
32
|
rescue ::Foreman::Exception => e
|
@@ -7,7 +7,7 @@ module Actions
|
|
7
7
|
|
8
8
|
def log_task_state_change(execution_plan)
|
9
9
|
return unless root_action?
|
10
|
-
logger = Rails.application.dynflow.world.action_logger
|
10
|
+
logger = ::Rails.application.dynflow.world.action_logger
|
11
11
|
task_id = ForemanTasks::Task::DynflowTask.where(external_id: execution_plan.id).pluck(:id).first
|
12
12
|
|
13
13
|
task_id_parts = []
|
@@ -10,13 +10,13 @@ module Actions
|
|
10
10
|
# for more details.
|
11
11
|
class RailsExecutorWrap < Dynflow::Middleware
|
12
12
|
def run(*args)
|
13
|
-
Rails.application.executor.wrap do
|
13
|
+
::Rails.application.executor.wrap do
|
14
14
|
pass(*args)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
def finalize
|
19
|
-
Rails.application.executor.wrap do
|
19
|
+
::Rails.application.executor.wrap do
|
20
20
|
pass
|
21
21
|
end
|
22
22
|
end
|
@@ -26,17 +26,26 @@ module Actions
|
|
26
26
|
def check_triggered
|
27
27
|
in_remote_task_batches(remote_tasks.triggered) do |batch|
|
28
28
|
batch.group_by(&:proxy_url).each do |(url, tasks)|
|
29
|
-
|
30
|
-
process_task_results tasks
|
29
|
+
results = poll_proxy_tasks(url, tasks)
|
30
|
+
process_task_results tasks, results
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
def process_task_results(tasks)
|
36
|
-
|
35
|
+
def process_task_results(tasks, results)
|
36
|
+
possibly_missing, present = tasks.partition { |task| !results.key?(task.remote_task_id) }
|
37
|
+
missing = possibly_missing.select do |task|
|
38
|
+
# Really missing are tasks which are missing and:
|
39
|
+
# don't have a remote parent
|
40
|
+
# had a remote parent but the proxy doesn't have the remote parent anymore
|
41
|
+
# has a remote parent, proxy has the remote parent but it is stopped or paused
|
42
|
+
task.parent_task_id.nil? ||
|
43
|
+
!results.key?(task.parent_task_id) ||
|
44
|
+
%(stopped paused).include?(results[task.parent_task_id]['state'])
|
45
|
+
end
|
37
46
|
notify ::Actions::ProxyAction::ProxyActionMissing.new, missing if missing.any?
|
38
47
|
|
39
|
-
stopped = present.select { |task| %w[stopped paused].include? task.
|
48
|
+
stopped = present.select { |task| %w[stopped paused].include? results.dig(task.remote_task_id, 'state') }
|
40
49
|
notify ::Actions::ProxyAction::ProxyActionStopped.new, stopped if stopped.any?
|
41
50
|
end
|
42
51
|
|
@@ -52,15 +61,13 @@ module Actions
|
|
52
61
|
|
53
62
|
def poll_proxy_tasks(url, tasks)
|
54
63
|
proxy = ProxyAPI::ForemanDynflow::DynflowProxy.new(:url => url)
|
55
|
-
|
56
|
-
tasks.map
|
57
|
-
|
58
|
-
task
|
59
|
-
end
|
64
|
+
# Get statuses of tasks and their optional parent tasks
|
65
|
+
ids = (tasks.map(&:remote_task_id) + tasks.map(&:parent_task_id)).uniq
|
66
|
+
proxy.task_states(ids)
|
60
67
|
rescue => e
|
61
68
|
# We could not reach the remote task, we'll try again next time
|
62
69
|
action.action_logger.warn(_('Failed to check on tasks on proxy at %{url}: %{exception}') % { :url => url, :exception => e.message })
|
63
|
-
|
70
|
+
{}
|
64
71
|
end
|
65
72
|
|
66
73
|
def in_remote_task_batches(scope)
|
@@ -67,7 +67,7 @@ module Actions
|
|
67
67
|
def trigger_proxy_task
|
68
68
|
suspend do |_suspended_action|
|
69
69
|
remote_task = prepare_remote_task
|
70
|
-
remote_task.
|
70
|
+
ForemanTasks::RemoteTask.batch_trigger(remote_task.operation, [remote_task])
|
71
71
|
output[:proxy_task_id] = remote_task.remote_task_id
|
72
72
|
end
|
73
73
|
end
|
@@ -263,7 +263,7 @@ module Actions
|
|
263
263
|
end
|
264
264
|
|
265
265
|
def proxy_task_id
|
266
|
-
output[:proxy_task_id]
|
266
|
+
output[:proxy_task_id] || remote_task.try(:remote_task_id) || @execution_plan_id
|
267
267
|
end
|
268
268
|
end
|
269
269
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Actions
|
2
|
+
# Examples:
|
3
|
+
|
4
|
+
# # Action A which emits an event when it successfully finishes.
|
5
|
+
# class A
|
6
|
+
# include ::Actions::ObservableAction
|
7
|
+
# # ... rest ...
|
8
|
+
# end
|
9
|
+
|
10
|
+
# # Action B which emits an event when it successfully finishes or fails.
|
11
|
+
# class B
|
12
|
+
# include ::Actions::ObservableAction
|
13
|
+
#
|
14
|
+
# execution_plan_hooks.use :emit_event_failure, :on => [:failure]
|
15
|
+
#
|
16
|
+
# def self.event_names
|
17
|
+
# super + [event_name_base + '_' + event_name_suffix(:failure)]
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def emit_event_failure(plan)
|
21
|
+
# emit_event(plan, :failure)
|
22
|
+
# end
|
23
|
+
# # ... rest ...
|
24
|
+
# end
|
25
|
+
module TaskSynchronization
|
26
|
+
def self.included(base)
|
27
|
+
base.execution_plan_hooks.use :sync_execution_plan_to_task, on: ::Dynflow::ExecutionPlan.states
|
28
|
+
end
|
29
|
+
|
30
|
+
def sync_execution_plan_to_task(plan)
|
31
|
+
return unless root_action?
|
32
|
+
on_execution_plan_save(plan)
|
33
|
+
rescue => e
|
34
|
+
::Foreman::Logging.exception('Error on on_execution_plan_save event', e,
|
35
|
+
:logger => 'dynflow')
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def on_execution_plan_save(execution_plan)
|
41
|
+
# We can load the data unless the execution plan was properly planned and saved
|
42
|
+
# including its steps
|
43
|
+
case execution_plan.state
|
44
|
+
when :pending
|
45
|
+
task = ForemanTasks::Task::DynflowTask.new_for_execution_plan(execution_plan)
|
46
|
+
task.start_at ||= Time.zone.now
|
47
|
+
task.save!
|
48
|
+
when :scheduled
|
49
|
+
delayed_plan = world.persistence.load_delayed_plan(execution_plan.id)
|
50
|
+
raise ::Foreman::Exception, 'Plan is delayed but the delay record is missing' if delayed_plan.nil?
|
51
|
+
task = ::ForemanTasks::Task::DynflowTask.find_by!(:external_id => execution_plan.id)
|
52
|
+
task.update_from_dynflow(execution_plan, delayed_plan)
|
53
|
+
when :planning
|
54
|
+
task = ::ForemanTasks::Task::DynflowTask.where(:external_id => execution_plan.id).first
|
55
|
+
task.update_from_dynflow(execution_plan)
|
56
|
+
else
|
57
|
+
if (task = ::ForemanTasks::Task::DynflowTask.where(:external_id => execution_plan.id).first)
|
58
|
+
unless task.state.to_s == execution_plan.state.to_s
|
59
|
+
task.update_from_dynflow(execution_plan)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -37,8 +37,8 @@ module Actions
|
|
37
37
|
# Group the tasks by operation, in theory there should be only one operation
|
38
38
|
batch.group_by(&:operation).each do |operation, group|
|
39
39
|
ForemanTasks::RemoteTask.batch_trigger(operation, group)
|
40
|
+
output[:planned_count] += group.size
|
40
41
|
end
|
41
|
-
output[:planned_count] += batch.size
|
42
42
|
rescue => e
|
43
43
|
action_logger.warn "Could not trigger task on the smart proxy"
|
44
44
|
action_logger.warn e
|
@@ -33,20 +33,27 @@ module ForemanTasks
|
|
33
33
|
:action_class => remote_task.proxy_action_name })
|
34
34
|
end
|
35
35
|
results = group.first.proxy.launch_tasks(operation, input_hash)
|
36
|
-
group.each
|
36
|
+
group.each do |remote_task|
|
37
|
+
remote_task.update_from_batch_trigger results.fetch(remote_task.execution_plan_id, {}),
|
38
|
+
results.fetch('parent', {})
|
39
|
+
end
|
37
40
|
end
|
38
41
|
remote_tasks
|
39
42
|
end
|
40
43
|
|
41
|
-
def update_from_batch_trigger(data)
|
44
|
+
def update_from_batch_trigger(data, parent = {})
|
42
45
|
if data['result'] == 'success'
|
43
46
|
self.remote_task_id = data['task_id']
|
44
47
|
self.state = 'triggered'
|
48
|
+
elsif !parent.empty?
|
49
|
+
self.parent_task_id = parent['task_id']
|
50
|
+
self.state = 'parent-triggered'
|
45
51
|
else
|
46
52
|
# Tell the action the task on the smart proxy stopped
|
47
53
|
ForemanTasks.dynflow.world.event execution_plan_id,
|
48
54
|
step_id,
|
49
|
-
::Actions::ProxyAction::ProxyActionStopped.new
|
55
|
+
::Actions::ProxyAction::ProxyActionStopped.new,
|
56
|
+
optional: true
|
50
57
|
end
|
51
58
|
save!
|
52
59
|
end
|
@@ -5,15 +5,14 @@ module ForemanTasks
|
|
5
5
|
scope :for_action, ->(action_class) { where(label: action_class.name) }
|
6
6
|
after_validation :set_action_field
|
7
7
|
|
8
|
-
def update_from_dynflow(
|
9
|
-
|
10
|
-
self.
|
11
|
-
self.
|
12
|
-
self.
|
13
|
-
self.
|
14
|
-
self.
|
15
|
-
self.
|
16
|
-
self.start_before = string_to_time(utc_zone, data[:start_before]) if data[:start_before]
|
8
|
+
def update_from_dynflow(plan, delayed_plan = nil)
|
9
|
+
self.external_id = plan.id
|
10
|
+
self.result = map_result(plan).to_s
|
11
|
+
self.state = plan.state.to_s
|
12
|
+
self.started_at = plan.started_at unless plan.started_at.nil?
|
13
|
+
self.ended_at = plan.ended_at unless plan.ended_at.nil?
|
14
|
+
self.start_at = delayed_plan.start_at if delayed_plan
|
15
|
+
self.start_before = delayed_plan.start_before if delayed_plan
|
17
16
|
self.parent_task_id ||= begin
|
18
17
|
if main_action.try(:caller_execution_plan_id)
|
19
18
|
DynflowTask.where(:external_id => main_action.caller_execution_plan_id).first!.id
|
@@ -221,7 +220,7 @@ module ForemanTasks
|
|
221
220
|
fixed_count = 0
|
222
221
|
logger = Foreman::Logging.logger('foreman-tasks')
|
223
222
|
running.each do |task|
|
224
|
-
changes = task.update_from_dynflow(task.execution_plan
|
223
|
+
changes = task.update_from_dynflow(task.execution_plan)
|
225
224
|
unless changes.empty?
|
226
225
|
fixed_count += 1
|
227
226
|
logger.warn('Task %s updated at consistency check: %s' % [task.id, changes.inspect])
|
@@ -236,10 +235,10 @@ module ForemanTasks
|
|
236
235
|
fixed_count
|
237
236
|
end
|
238
237
|
|
239
|
-
def self.new_for_execution_plan(
|
240
|
-
new(:external_id =>
|
241
|
-
:state =>
|
242
|
-
:result =>
|
238
|
+
def self.new_for_execution_plan(execution_plan)
|
239
|
+
new(:external_id => execution_plan.id,
|
240
|
+
:state => execution_plan.state.to_s,
|
241
|
+
:result => execution_plan.result.to_s,
|
243
242
|
:user_id => User.current.try(:id))
|
244
243
|
end
|
245
244
|
|
@@ -258,20 +257,20 @@ module ForemanTasks
|
|
258
257
|
self.action = to_label
|
259
258
|
end
|
260
259
|
|
261
|
-
def map_result(
|
262
|
-
if state_result_transitioned?(%w[planned pending], %w[stopped error],
|
263
|
-
(
|
260
|
+
def map_result(plan)
|
261
|
+
if state_result_transitioned?(%w[planned pending], %w[stopped error], plan) ||
|
262
|
+
(plan.result == :error && cancelled?)
|
264
263
|
:cancelled
|
265
264
|
else
|
266
|
-
|
265
|
+
plan.result
|
267
266
|
end
|
268
267
|
end
|
269
268
|
|
270
|
-
def state_result_transitioned?(from, to,
|
269
|
+
def state_result_transitioned?(from, to, plan)
|
271
270
|
oldstate, oldresult = from
|
272
271
|
newstate, newresult = to
|
273
|
-
state == oldstate &&
|
274
|
-
result == oldresult &&
|
272
|
+
state == oldstate && plan.state.to_s == newstate &&
|
273
|
+
result == oldresult && plan.result.to_s == newresult
|
275
274
|
end
|
276
275
|
|
277
276
|
def cancelled?
|
data/config/routes.rb
CHANGED
@@ -70,7 +70,7 @@ Foreman::Application.routes.draw do
|
|
70
70
|
mount ForemanTasks.dynflow.web_console => '/dynflow'
|
71
71
|
if defined? ::Sidekiq
|
72
72
|
require 'sidekiq/web'
|
73
|
-
redis_url = SETTINGS.dig(:dynflow, :redis_url)
|
73
|
+
redis_url = ENV['DYNFLOW_REDIS_URL'] || SETTINGS.dig(:dynflow, :redis_url)
|
74
74
|
Sidekiq.redis = { url: redis_url }
|
75
75
|
Sidekiq::Web.set :sessions, false
|
76
76
|
mount Sidekiq::Web => '/sidekiq', :constraints => ForemanTasks::Dynflow::SidekiqConsoleConstraint.new
|
data/foreman-tasks.gemspec
CHANGED
@@ -26,7 +26,7 @@ same resource. It also optionally provides Dynflow infrastructure for using it f
|
|
26
26
|
s.test_files = `git ls-files test`.split("\n")
|
27
27
|
s.extra_rdoc_files = Dir['README*', 'LICENSE']
|
28
28
|
|
29
|
-
s.add_dependency "dynflow", '>= 1.
|
29
|
+
s.add_dependency "dynflow", '>= 1.6.0'
|
30
30
|
s.add_dependency "get_process_mem" # for memory polling
|
31
31
|
s.add_dependency "parse-cron", '~> 0.1.4'
|
32
32
|
s.add_dependency "sinatra" # for Dynflow web console
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require File.expand_path('lib/foreman/dynflow/configuration', Rails.root)
|
2
|
-
require 'foreman_tasks/dynflow/persistence'
|
1
|
+
require File.expand_path('lib/foreman/dynflow/configuration', ::Rails.root)
|
3
2
|
|
4
3
|
module ForemanTasks
|
5
4
|
# Import all Dynflow configuration from Foreman, and add our own for Tasks
|
@@ -34,9 +33,5 @@ module ForemanTasks
|
|
34
33
|
end
|
35
34
|
options
|
36
35
|
end
|
37
|
-
|
38
|
-
def persistence_class
|
39
|
-
ForemanTasks::Dynflow::Persistence
|
40
|
-
end
|
41
36
|
end
|
42
37
|
end
|
@@ -17,7 +17,7 @@ module ForemanTasks
|
|
17
17
|
set(:custom_navigation) do
|
18
18
|
{ _('Back to tasks') => "/#{ForemanTasks::TasksController.controller_path}" }
|
19
19
|
end
|
20
|
-
set(:world) { Rails.application.dynflow.world }
|
20
|
+
set(:world) { ::Rails.application.dynflow.world }
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
data/lib/foreman_tasks/engine.rb
CHANGED
@@ -5,14 +5,6 @@ module ForemanTasks
|
|
5
5
|
class Engine < ::Rails::Engine
|
6
6
|
engine_name 'foreman_tasks'
|
7
7
|
|
8
|
-
initializer 'foreman_tasks.load_default_settings', :before => :load_config_initializers do
|
9
|
-
require_dependency File.expand_path('../../app/models/setting/foreman_tasks.rb', __dir__) if begin
|
10
|
-
Setting.table_exists?
|
11
|
-
rescue
|
12
|
-
false
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
8
|
assets_to_precompile = %w[foreman_tasks/foreman_tasks.css
|
17
9
|
foreman_tasks/foreman_tasks.js]
|
18
10
|
|
@@ -33,7 +25,7 @@ module ForemanTasks
|
|
33
25
|
|
34
26
|
initializer 'foreman_tasks.register_plugin', :before => :finisher_hook do |_app|
|
35
27
|
Foreman::Plugin.register :"foreman-tasks" do
|
36
|
-
requires_foreman '>= 2.
|
28
|
+
requires_foreman '>= 3.2.0'
|
37
29
|
divider :top_menu, :parent => :monitor_menu, :last => true, :caption => N_('Foreman Tasks')
|
38
30
|
menu :top_menu, :tasks,
|
39
31
|
:url_hash => { :controller => 'foreman_tasks/tasks', :action => :index },
|
@@ -65,6 +57,60 @@ module ForemanTasks
|
|
65
57
|
|
66
58
|
add_all_permissions_to_default_roles
|
67
59
|
|
60
|
+
settings do
|
61
|
+
category(:tasks, N_('Tasks')) do
|
62
|
+
setting('foreman_tasks_sync_task_timeout',
|
63
|
+
type: :integer,
|
64
|
+
description: N_('Number of seconds to wait for synchronous task to finish.'),
|
65
|
+
default: 120,
|
66
|
+
full_name: N_('Sync task timeout'))
|
67
|
+
setting('dynflow_enable_console',
|
68
|
+
type: :boolean,
|
69
|
+
description: N_('Enable the dynflow console (/foreman_tasks/dynflow) for debugging'),
|
70
|
+
default: true,
|
71
|
+
full_name: N_('Enable dynflow console'))
|
72
|
+
setting('dynflow_console_require_auth',
|
73
|
+
type: :boolean,
|
74
|
+
description: N_('Require user to be authenticated as user with admin rights when accessing dynflow console'),
|
75
|
+
default: true,
|
76
|
+
full_name: N_('Require auth for dynflow console'))
|
77
|
+
setting('foreman_tasks_proxy_action_retry_count',
|
78
|
+
type: :integer,
|
79
|
+
description: N_('Number of attempts to start a task on the smart proxy before failing'),
|
80
|
+
default: 4,
|
81
|
+
full_name: N_('Proxy action retry count'))
|
82
|
+
setting('foreman_tasks_proxy_action_retry_interval',
|
83
|
+
type: :integer,
|
84
|
+
description: N_('Time in seconds between retries'),
|
85
|
+
default: 15,
|
86
|
+
full_name: N_('Proxy action retry interval'))
|
87
|
+
setting('foreman_tasks_proxy_batch_trigger',
|
88
|
+
type: :boolean,
|
89
|
+
description: N_('Allow triggering tasks on the smart proxy in batches'),
|
90
|
+
default: true,
|
91
|
+
full_name: N_('Allow proxy batch tasks'))
|
92
|
+
setting('foreman_tasks_proxy_batch_size',
|
93
|
+
type: :integer,
|
94
|
+
description: N_('Number of tasks which should be sent to the smart proxy in one request, if foreman_tasks_proxy_batch_trigger is enabled'),
|
95
|
+
default: 100,
|
96
|
+
full_name: N_('Proxy tasks batch size'))
|
97
|
+
setting('foreman_tasks_troubleshooting_url',
|
98
|
+
type: :string,
|
99
|
+
description: N_('Url pointing to the task troubleshooting documentation. '\
|
100
|
+
'It should contain %{label} placeholder, that will be replaced with normalized task label '\
|
101
|
+
'(restricted to only alphanumeric characters)). %{version} placeholder is also available.'),
|
102
|
+
default: nil,
|
103
|
+
full_name: N_('Tasks troubleshooting URL'))
|
104
|
+
setting('foreman_tasks_polling_multiplier',
|
105
|
+
type: :integer,
|
106
|
+
description: N_('Polling multiplier which is used to multiply the default polling intervals. '\
|
107
|
+
'This can be used to prevent polling too frequently for long running tasks.'),
|
108
|
+
default: 1,
|
109
|
+
full_name: N_("Polling intervals multiplier"),
|
110
|
+
validate: { numericality: { greater_than: 0 } })
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
68
114
|
register_graphql_query_field :task, '::Types::Task', :record_field
|
69
115
|
register_graphql_query_field :tasks, '::Types::Task', :collection_field
|
70
116
|
register_graphql_query_field :recurring_logic, '::Types::RecurringLogic', :record_field
|
@@ -138,6 +184,7 @@ module ForemanTasks
|
|
138
184
|
Authorizer.prepend AuthorizerExt
|
139
185
|
User.include ForemanTasks::Concerns::UserExtensions
|
140
186
|
::Dynflow::Action::Polling.prepend ForemanTasks::Concerns::PollingActionExtensions
|
187
|
+
::Dynflow::ActiveJob::QueueAdapters::JobWrapper.include Actions::TaskSynchronization
|
141
188
|
end
|
142
189
|
|
143
190
|
rake_tasks do
|
@@ -11,7 +11,7 @@ module ForemanTasks
|
|
11
11
|
world_config = ForemanTasks.dynflow.config.world_config
|
12
12
|
if @use_in_memory_sqlite
|
13
13
|
world_config.persistence_adapter = lambda do |*_args|
|
14
|
-
::
|
14
|
+
::Dynflow::PersistenceAdapters::Sequel.new('adapter' => 'sqlite', 'database' => ':memory:')
|
15
15
|
end
|
16
16
|
end
|
17
17
|
@test_in_thread_world = ::Dynflow::Testing::InThreadWorld.new(world_config)
|