foreman-tasks-core 0.3.0 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/foreman_tasks_core.rb +6 -0
- data/lib/foreman_tasks_core/batch_action.rb +21 -0
- data/lib/foreman_tasks_core/batch_callback_action.rb +20 -0
- data/lib/foreman_tasks_core/batch_runner_action.rb +14 -0
- data/lib/foreman_tasks_core/otp_manager.rb +7 -2
- data/lib/foreman_tasks_core/output_collector_action.rb +8 -0
- data/lib/foreman_tasks_core/runner.rb +1 -0
- data/lib/foreman_tasks_core/runner/base.rb +35 -8
- data/lib/foreman_tasks_core/runner/command.rb +40 -0
- data/lib/foreman_tasks_core/runner/command_runner.rb +3 -33
- data/lib/foreman_tasks_core/runner/dispatcher.rb +29 -29
- data/lib/foreman_tasks_core/runner/parent.rb +57 -0
- data/lib/foreman_tasks_core/single_runner_batch_action.rb +39 -0
- data/lib/foreman_tasks_core/task_launcher.rb +9 -0
- data/lib/foreman_tasks_core/task_launcher/abstract.rb +44 -0
- data/lib/foreman_tasks_core/task_launcher/batch.rb +37 -0
- data/lib/foreman_tasks_core/task_launcher/group.rb +47 -0
- data/lib/foreman_tasks_core/task_launcher/single.rb +17 -0
- data/lib/foreman_tasks_core/ticker.rb +2 -0
- data/lib/foreman_tasks_core/version.rb +1 -1
- metadata +21 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9eeba72428b030c0bcec9f51c7b58cbfb7e046eb7279b68b6030b46aaa72a434
|
4
|
+
data.tar.gz: 9a40808da08504914c856d9407a7d454a5c5045125a768ee5d6b54424444bd93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9cd9a1e5c8f247bd5b3f335998d2cba76d2a17ba6edfae529713f6eaaa60de6133d61125e76175544a8248f259f48bfa715de46cd4f1ff5132844d1c5c0250d
|
7
|
+
data.tar.gz: 2ddb3a83487315cdbc6ecf32886d67f599badb47f61f02019122fed0103602af72f0c8e5f999016dfec36a3caa56c17202fb3ce0426f5814084d5703bd702991
|
data/lib/foreman_tasks_core.rb
CHANGED
@@ -4,6 +4,12 @@
|
|
4
4
|
require 'foreman_tasks_core/settings_loader'
|
5
5
|
require 'foreman_tasks_core/otp_manager'
|
6
6
|
require 'foreman_tasks_core/ticker'
|
7
|
+
require 'foreman_tasks_core/batch_action'
|
8
|
+
require 'foreman_tasks_core/batch_callback_action'
|
9
|
+
require 'foreman_tasks_core/batch_runner_action'
|
10
|
+
require 'foreman_tasks_core/output_collector_action'
|
11
|
+
require 'foreman_tasks_core/single_runner_batch_action'
|
12
|
+
require 'foreman_tasks_core/task_launcher'
|
7
13
|
|
8
14
|
module ForemanTasksCore
|
9
15
|
def self.dynflow_world
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ForemanTasksCore
|
2
|
+
class BatchAction < ::Dynflow::Action
|
3
|
+
include Dynflow::Action::WithSubPlans
|
4
|
+
include Dynflow::Action::WithPollingSubPlans
|
5
|
+
|
6
|
+
# { task_id => { :action_class => Klass, :input => input } }
|
7
|
+
def plan(launcher, input_hash)
|
8
|
+
launcher.launch_children(self, input_hash)
|
9
|
+
plan_self
|
10
|
+
end
|
11
|
+
|
12
|
+
def initiate
|
13
|
+
ping suspended_action
|
14
|
+
wait_for_sub_plans sub_plans
|
15
|
+
end
|
16
|
+
|
17
|
+
def rescue_strategy
|
18
|
+
Dynflow::Action::Rescue::Fail
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ForemanTasksCore
|
2
|
+
class BatchCallback < ::Dynflow::Action
|
3
|
+
def plan(input_hash, results)
|
4
|
+
plan_self :targets => input_hash, :results => results
|
5
|
+
end
|
6
|
+
|
7
|
+
def run
|
8
|
+
payload = format_payload(input['targets'], input['results'])
|
9
|
+
SmartProxyDynflowCore::Callback::Request.new.callback({ :callbacks => payload }.to_json)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def format_payload(input_hash, results)
|
15
|
+
input_hash.map do |task_id, callback|
|
16
|
+
{ :callback => callback, :data => results[task_id] }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'foreman_tasks_core/runner/action'
|
2
|
+
|
3
|
+
module ForemanTasksCore
|
4
|
+
class BatchRunnerAction < ::ForemanTasksCore::Runner::Action
|
5
|
+
def plan(launcher, input)
|
6
|
+
plan_self :targets => launcher.runner_input(input), :operation => launcher.operation
|
7
|
+
end
|
8
|
+
|
9
|
+
def initiate_runner
|
10
|
+
launcher = SmartProxyDynflowCore::TaskLauncherRegistry.fetch(input[:operation])
|
11
|
+
launcher.runner_class.new(input[:targets], suspended_action: suspended_action)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -17,10 +17,15 @@ module ForemanTasksCore
|
|
17
17
|
@password ||= {}
|
18
18
|
end
|
19
19
|
|
20
|
-
def authenticate(hash)
|
20
|
+
def authenticate(hash, expected_user: nil, clear: true)
|
21
21
|
plain = Base64.decode64(hash)
|
22
22
|
username, otp = plain.split(':', 2)
|
23
|
-
|
23
|
+
if expected_user
|
24
|
+
return false unless expected_user == username
|
25
|
+
end
|
26
|
+
password_matches = passwords[username] == otp
|
27
|
+
passwords.delete(username) if clear && password_matches
|
28
|
+
password_matches
|
24
29
|
end
|
25
30
|
|
26
31
|
def tokenize(username, password)
|
@@ -6,9 +6,10 @@ module ForemanTasksCore
|
|
6
6
|
attr_reader :id
|
7
7
|
attr_writer :logger
|
8
8
|
|
9
|
-
def initialize(*_args)
|
9
|
+
def initialize(*_args, suspended_action: nil)
|
10
|
+
@suspended_action = suspended_action
|
10
11
|
@id = SecureRandom.uuid
|
11
|
-
|
12
|
+
initialize_continuous_outputs
|
12
13
|
end
|
13
14
|
|
14
15
|
def logger
|
@@ -18,11 +19,14 @@ module ForemanTasksCore
|
|
18
19
|
def run_refresh
|
19
20
|
logger.debug('refreshing runner')
|
20
21
|
refresh
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
generate_updates
|
23
|
+
end
|
24
|
+
|
25
|
+
# by default, external event just causes the refresh to be triggered: this allows the descendants
|
26
|
+
# of the Base to add custom logic to process the external events.
|
27
|
+
# Similarly as `run_refresh`, it's expected to return updates to be dispatched.
|
28
|
+
def external_event(_event)
|
29
|
+
run_refresh
|
26
30
|
end
|
27
31
|
|
28
32
|
def start
|
@@ -59,13 +63,36 @@ module ForemanTasksCore
|
|
59
63
|
def publish_exception(context, exception, fatal = true)
|
60
64
|
logger.error("#{context} - #{exception.class} #{exception.message}:\n" + \
|
61
65
|
exception.backtrace.join("\n"))
|
62
|
-
|
66
|
+
dispatch_exception context, exception
|
63
67
|
publish_exit_status('EXCEPTION') if fatal
|
64
68
|
end
|
65
69
|
|
66
70
|
def publish_exit_status(status)
|
67
71
|
@exit_status = status
|
68
72
|
end
|
73
|
+
|
74
|
+
def dispatch_exception(context, exception)
|
75
|
+
@continuous_output.add_exception(context, exception)
|
76
|
+
end
|
77
|
+
|
78
|
+
def generate_updates
|
79
|
+
return no_update if @continuous_output.empty? && @exit_status.nil?
|
80
|
+
new_data = @continuous_output
|
81
|
+
@continuous_output = ForemanTasksCore::ContinuousOutput.new
|
82
|
+
new_update(new_data, @exit_status)
|
83
|
+
end
|
84
|
+
|
85
|
+
def no_update
|
86
|
+
{}
|
87
|
+
end
|
88
|
+
|
89
|
+
def new_update(data, exit_status)
|
90
|
+
{ @suspended_action => Runner::Update.new(data, exit_status) }
|
91
|
+
end
|
92
|
+
|
93
|
+
def initialize_continuous_outputs
|
94
|
+
@continuous_output = ::ForemanTasksCore::ContinuousOutput.new
|
95
|
+
end
|
69
96
|
end
|
70
97
|
end
|
71
98
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ForemanTasksCore
|
2
|
+
module Runner
|
3
|
+
module Command
|
4
|
+
def initialize_command(*command)
|
5
|
+
@command_out, @command_in, @command_pid = PTY.spawn(*command)
|
6
|
+
rescue Errno::ENOENT => e
|
7
|
+
publish_exception("Error running command '#{command.join(' ')}'", e)
|
8
|
+
end
|
9
|
+
|
10
|
+
def refresh
|
11
|
+
return if @command_out.nil?
|
12
|
+
ready_outputs, * = IO.select([@command_out], nil, nil, 0.1)
|
13
|
+
if ready_outputs
|
14
|
+
if @command_out.nread > 0
|
15
|
+
lines = @command_out.read_nonblock(@command_out.nread)
|
16
|
+
else
|
17
|
+
close_io
|
18
|
+
Process.wait(@command_pid)
|
19
|
+
publish_exit_status($CHILD_STATUS.exitstatus)
|
20
|
+
end
|
21
|
+
publish_data(lines, 'stdout') if lines && !lines.empty?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def close
|
26
|
+
close_io
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def close_io
|
32
|
+
@command_out.close if @command_out && !@command_out.closed?
|
33
|
+
@command_out = nil
|
34
|
+
|
35
|
+
@command_in.close if @command_in && !@command_in.closed?
|
36
|
+
@command_in = nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,41 +1,11 @@
|
|
1
1
|
require 'io/wait'
|
2
2
|
require 'pty'
|
3
|
+
require 'foreman_tasks_core/runner/command'
|
3
4
|
|
4
5
|
module ForemanTasksCore
|
5
6
|
module Runner
|
6
|
-
class CommandRunner <
|
7
|
-
|
8
|
-
@command_out, @command_in, @command_pid = PTY.spawn(*command)
|
9
|
-
end
|
10
|
-
|
11
|
-
def refresh
|
12
|
-
return if @command_out.nil?
|
13
|
-
ready_outputs, * = IO.select([@command_out], nil, nil, 0.1)
|
14
|
-
if ready_outputs
|
15
|
-
if @command_out.nread > 0
|
16
|
-
lines = @command_out.read_nonblock(@command_out.nread)
|
17
|
-
else
|
18
|
-
close_io
|
19
|
-
Process.wait(@command_pid)
|
20
|
-
publish_exit_status($CHILD_STATUS.exitstatus)
|
21
|
-
end
|
22
|
-
publish_data(lines, 'stdout') if lines && !lines.empty?
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def close
|
27
|
-
close_io
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def close_io
|
33
|
-
@command_out.close if @command_out && !@command_out.closed?
|
34
|
-
@command_out = nil
|
35
|
-
|
36
|
-
@command_in.close if @command_in && !@command_in.closed?
|
37
|
-
@command_in = nil
|
38
|
-
end
|
7
|
+
class CommandRunner < Base
|
8
|
+
include Command
|
39
9
|
end
|
40
10
|
end
|
41
11
|
end
|
@@ -37,15 +37,21 @@ module ForemanTasksCore
|
|
37
37
|
|
38
38
|
def refresh_runner
|
39
39
|
@logger.debug("refresh runner #{@runner.id}")
|
40
|
-
|
41
|
-
@suspended_action << update
|
42
|
-
finish if update.exit_status
|
43
|
-
end
|
40
|
+
dispatch_updates(@runner.run_refresh)
|
44
41
|
ensure
|
45
42
|
@refresh_planned = false
|
46
43
|
plan_next_refresh
|
47
44
|
end
|
48
45
|
|
46
|
+
def dispatch_updates(updates)
|
47
|
+
updates.each { |receiver, update| (receiver || @suspended_action) << update }
|
48
|
+
|
49
|
+
# This is a workaround when the runner does not accept the suspended action
|
50
|
+
main_key = updates.keys.any?(&:nil?) ? nil : @suspended_action
|
51
|
+
main_process = updates[main_key]
|
52
|
+
finish if main_process && main_process.exit_status
|
53
|
+
end
|
54
|
+
|
49
55
|
def timeout_runner
|
50
56
|
@logger.debug("timeout runner #{@runner.id}")
|
51
57
|
@runner.timeout
|
@@ -73,8 +79,8 @@ module ForemanTasksCore
|
|
73
79
|
finish_termination
|
74
80
|
end
|
75
81
|
|
76
|
-
def external_event(
|
77
|
-
|
82
|
+
def external_event(event)
|
83
|
+
dispatch_updates(@runner.external_event(event))
|
78
84
|
end
|
79
85
|
|
80
86
|
private
|
@@ -114,39 +120,33 @@ module ForemanTasksCore
|
|
114
120
|
|
115
121
|
def start(suspended_action, runner)
|
116
122
|
synchronize do
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
return nil
|
128
|
-
end
|
123
|
+
raise "Actor with runner id #{runner.id} already exists" if @runner_actors[runner.id]
|
124
|
+
runner.logger = @logger
|
125
|
+
runner_actor = RunnerActor.spawn("runner-actor-#{runner.id}", self, suspended_action, runner, @clock, @logger)
|
126
|
+
@runner_actors[runner.id] = runner_actor
|
127
|
+
@runner_suspended_actions[runner.id] = suspended_action
|
128
|
+
runner_actor.tell(:start_runner)
|
129
|
+
return runner.id
|
130
|
+
rescue => exception
|
131
|
+
_handle_command_exception(runner.id, exception)
|
132
|
+
return nil
|
129
133
|
end
|
130
134
|
end
|
131
135
|
|
132
136
|
def kill(runner_id)
|
133
137
|
synchronize do
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
_handle_command_exception(runner_id, exception, false)
|
139
|
-
end
|
138
|
+
runner_actor = @runner_actors[runner_id]
|
139
|
+
runner_actor.tell(:kill) if runner_actor
|
140
|
+
rescue => exception
|
141
|
+
_handle_command_exception(runner_id, exception, false)
|
140
142
|
end
|
141
143
|
end
|
142
144
|
|
143
145
|
def finish(runner_id)
|
144
146
|
synchronize do
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
_handle_command_exception(runner_id, exception, false)
|
149
|
-
end
|
147
|
+
_finish(runner_id)
|
148
|
+
rescue => exception
|
149
|
+
_handle_command_exception(runner_id, exception, false)
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module ForemanTasksCore
|
2
|
+
module Runner
|
3
|
+
class Parent < Base
|
4
|
+
# targets = { identifier => { :execution_plan_id => "...", :run_step_id => id,
|
5
|
+
# :input => { ... } }
|
6
|
+
def initialize(targets = {}, suspended_action: nil)
|
7
|
+
@targets = targets
|
8
|
+
@exit_statuses = {}
|
9
|
+
super suspended_action: suspended_action
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate_updates
|
13
|
+
base = {}
|
14
|
+
base[@suspended_action] = Runner::Update.new(ForemanTasksCore::ContinuousOutput.new, @exit_status) if @exit_status
|
15
|
+
# Operate on all hosts if the main process ended or only on hosts for which we have updates
|
16
|
+
@outputs.reject { |_, output| @exit_status.nil? && output.empty? }
|
17
|
+
.reduce(base) do |acc, (identifier, output)|
|
18
|
+
@outputs[identifier] = ForemanTasksCore::ContinuousOutput.new # Create a new ContinuousOutput for next round of updates
|
19
|
+
exit_status = @exit_statuses[identifier] || @exit_status if @exit_status
|
20
|
+
acc.merge(host_action(identifier) => Runner::Update.new(output, exit_status))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize_continuous_outputs
|
25
|
+
@outputs = @targets.keys.reduce({}) do |acc, target|
|
26
|
+
acc.merge(target => ForemanTasksCore::ContinuousOutput.new)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def host_action(identifier)
|
31
|
+
options = @targets[identifier].slice('execution_plan_id', 'run_step_id')
|
32
|
+
.merge(:world => ForemanTasksCore.dynflow_world)
|
33
|
+
Dynflow::Action::Suspended.new OpenStruct.new(options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def broadcast_data(data, type)
|
37
|
+
@outputs.each { |_k, output| output.add_output(data, type) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def publish_data(_data, _type)
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
def publish_data_for(identifier, data, type)
|
45
|
+
@outputs[identifier].add_output(data, type)
|
46
|
+
end
|
47
|
+
|
48
|
+
def dispatch_exception(context, exception)
|
49
|
+
@outputs.values.each { |output| output.add_exception(context, exception) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def publish_exit_status_for(identifier, exit_status)
|
53
|
+
@exit_statuses[identifier] = exit_status
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ForemanTasksCore
|
2
|
+
class SingleRunnerBatchAction < ForemanTasksCore::BatchAction
|
3
|
+
def plan(launcher, input_hash)
|
4
|
+
launcher.launch_children(self, input_hash)
|
5
|
+
sequence do
|
6
|
+
results = plan_self
|
7
|
+
plan_action BatchCallback, launcher.prepare_batch(input_hash), results.output[:results]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(event = nil)
|
12
|
+
super unless event == Dynflow::Action::Skip
|
13
|
+
end
|
14
|
+
|
15
|
+
def initiate
|
16
|
+
ping suspended_action
|
17
|
+
wait_for_sub_plans sub_plans
|
18
|
+
end
|
19
|
+
|
20
|
+
def check_for_errors!(optional = true)
|
21
|
+
super unless optional
|
22
|
+
end
|
23
|
+
|
24
|
+
def on_finish
|
25
|
+
output[:results] = sub_plans.map(&:entry_action).reduce({}) do |acc, cur|
|
26
|
+
acc.merge(cur.execution_plan_id => cur.output)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def finalize
|
31
|
+
output.delete(:results)
|
32
|
+
check_for_errors!
|
33
|
+
end
|
34
|
+
|
35
|
+
def rescue_strategy_for_self
|
36
|
+
Dynflow::Action::Rescue::Skip
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module ForemanTasksCore
|
2
|
+
module TaskLauncher
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'foreman_tasks_core/task_launcher/abstract'
|
7
|
+
require 'foreman_tasks_core/task_launcher/single'
|
8
|
+
require 'foreman_tasks_core/task_launcher/batch'
|
9
|
+
require 'foreman_tasks_core/task_launcher/group'
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ForemanTasksCore
|
2
|
+
module TaskLauncher
|
3
|
+
class Abstract
|
4
|
+
attr_reader :callback, :options, :results, :world
|
5
|
+
def initialize(world, callback, options = {})
|
6
|
+
@world = world
|
7
|
+
@callback = callback
|
8
|
+
@options = options
|
9
|
+
@results = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def launch!(_input)
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.input_format; end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def format_result(result)
|
21
|
+
if result.triggered?
|
22
|
+
{ :result => 'success', :task_id => result.execution_plan_id }
|
23
|
+
else
|
24
|
+
plan = world.persistence.load_execution_plan(result.id)
|
25
|
+
{ :result => 'error', :errors => plan.errors }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def action_class(input)
|
30
|
+
options[:action_class_override] || ::Dynflow::Utils.constantize(input['action_class'])
|
31
|
+
end
|
32
|
+
|
33
|
+
def with_callback(input)
|
34
|
+
input.merge(:callback_host => callback)
|
35
|
+
end
|
36
|
+
|
37
|
+
def trigger(parent, klass, *input)
|
38
|
+
world.trigger do
|
39
|
+
world.plan_with_options(caller_action: parent, action_class: klass, args: input)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ForemanTasksCore
|
2
|
+
module TaskLauncher
|
3
|
+
class Batch < Abstract
|
4
|
+
def launch!(input)
|
5
|
+
trigger(nil, BatchAction, self, input)
|
6
|
+
end
|
7
|
+
|
8
|
+
def launch_children(parent, input_hash)
|
9
|
+
input_hash.each do |task_id, input|
|
10
|
+
launcher = child_launcher(parent)
|
11
|
+
launcher.launch!(transform_input(input))
|
12
|
+
results[task_id] = launcher.results
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def prepare_batch(input_hash)
|
17
|
+
success_tasks = input_hash.select do |task_id, _input|
|
18
|
+
results[task_id][:result] == 'success'
|
19
|
+
end
|
20
|
+
success_tasks.reduce({}) do |acc, (key, value)|
|
21
|
+
acc.merge(results[key][:task_id] => value['action_input']['callback'])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def child_launcher(parent)
|
28
|
+
Single.new(world, callback, :parent => parent)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Identity by default
|
32
|
+
def transform_input(input)
|
33
|
+
input
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'foreman_tasks_core/runner'
|
2
|
+
|
3
|
+
module ForemanTasksCore
|
4
|
+
module TaskLauncher
|
5
|
+
class AbstractGroup < Batch
|
6
|
+
def self.runner_class
|
7
|
+
raise NotImplementedError
|
8
|
+
end
|
9
|
+
|
10
|
+
def launch!(input)
|
11
|
+
trigger(nil, SingleRunnerBatchAction, self, input)
|
12
|
+
end
|
13
|
+
|
14
|
+
def launch_children(parent, input_hash)
|
15
|
+
super(parent, input_hash)
|
16
|
+
trigger(parent, BatchRunnerAction, self, input_hash)
|
17
|
+
end
|
18
|
+
|
19
|
+
def operation
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
def runner_input(input)
|
24
|
+
input.reduce({}) do |acc, (id, input)|
|
25
|
+
input = { :execution_plan_id => results[id][:task_id],
|
26
|
+
:run_step_id => 2,
|
27
|
+
:input => input }
|
28
|
+
acc.merge(id => input)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def child_launcher(parent)
|
35
|
+
Single.new(world, callback, :parent => parent, :action_class_override => OutputCollectorAction)
|
36
|
+
end
|
37
|
+
|
38
|
+
def transform_input(input)
|
39
|
+
wipe_callback(input)
|
40
|
+
end
|
41
|
+
|
42
|
+
def wipe_callback(input)
|
43
|
+
input.merge('action_input' => input['action_input'].merge('callback' => nil))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ForemanTasksCore
|
2
|
+
module TaskLauncher
|
3
|
+
class Single < Abstract
|
4
|
+
def self.input_format
|
5
|
+
{ :action_class => "MyActionClass", :action_input => {} }
|
6
|
+
end
|
7
|
+
|
8
|
+
def launch!(input)
|
9
|
+
triggered = trigger(options[:parent],
|
10
|
+
action_class(input),
|
11
|
+
with_callback(input.fetch('action_input', {})))
|
12
|
+
@results = format_result(triggered)
|
13
|
+
triggered
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman-tasks-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Nečas
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dynflow
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
version: 1.2.0
|
27
27
|
description: 'Common code used both at Forman and Foreman proxy regarding tasks
|
28
28
|
|
29
|
-
'
|
29
|
+
'
|
30
30
|
email:
|
31
31
|
- inecas@redhat.com
|
32
32
|
executables: []
|
@@ -35,22 +35,35 @@ extra_rdoc_files: []
|
|
35
35
|
files:
|
36
36
|
- LICENSE
|
37
37
|
- lib/foreman_tasks_core.rb
|
38
|
+
- lib/foreman_tasks_core/batch_action.rb
|
39
|
+
- lib/foreman_tasks_core/batch_callback_action.rb
|
40
|
+
- lib/foreman_tasks_core/batch_runner_action.rb
|
38
41
|
- lib/foreman_tasks_core/continuous_output.rb
|
39
42
|
- lib/foreman_tasks_core/otp_manager.rb
|
43
|
+
- lib/foreman_tasks_core/output_collector_action.rb
|
40
44
|
- lib/foreman_tasks_core/runner.rb
|
41
45
|
- lib/foreman_tasks_core/runner/action.rb
|
42
46
|
- lib/foreman_tasks_core/runner/base.rb
|
47
|
+
- lib/foreman_tasks_core/runner/command.rb
|
43
48
|
- lib/foreman_tasks_core/runner/command_runner.rb
|
44
49
|
- lib/foreman_tasks_core/runner/dispatcher.rb
|
50
|
+
- lib/foreman_tasks_core/runner/parent.rb
|
45
51
|
- lib/foreman_tasks_core/runner/update.rb
|
46
52
|
- lib/foreman_tasks_core/settings_loader.rb
|
47
53
|
- lib/foreman_tasks_core/shareable_action.rb
|
54
|
+
- lib/foreman_tasks_core/single_runner_batch_action.rb
|
55
|
+
- lib/foreman_tasks_core/task_launcher.rb
|
56
|
+
- lib/foreman_tasks_core/task_launcher/abstract.rb
|
57
|
+
- lib/foreman_tasks_core/task_launcher/batch.rb
|
58
|
+
- lib/foreman_tasks_core/task_launcher/group.rb
|
59
|
+
- lib/foreman_tasks_core/task_launcher/single.rb
|
48
60
|
- lib/foreman_tasks_core/ticker.rb
|
49
61
|
- lib/foreman_tasks_core/version.rb
|
50
62
|
homepage: https://github.com/theforeman/foreman-tasks
|
51
|
-
licenses:
|
63
|
+
licenses:
|
64
|
+
- GPL-3.0
|
52
65
|
metadata: {}
|
53
|
-
post_install_message:
|
66
|
+
post_install_message:
|
54
67
|
rdoc_options: []
|
55
68
|
require_paths:
|
56
69
|
- lib
|
@@ -65,9 +78,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
78
|
- !ruby/object:Gem::Version
|
66
79
|
version: '0'
|
67
80
|
requirements: []
|
68
|
-
|
69
|
-
|
70
|
-
signing_key:
|
81
|
+
rubygems_version: 3.1.2
|
82
|
+
signing_key:
|
71
83
|
specification_version: 4
|
72
84
|
summary: Common code used both at Forman and Foreman proxy regarding tasks
|
73
85
|
test_files: []
|