foreman-tasks-core 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/foreman_tasks_core.rb +1 -0
- data/lib/foreman_tasks_core/runner.rb +1 -0
- data/lib/foreman_tasks_core/runner/base.rb +20 -8
- data/lib/foreman_tasks_core/runner/dispatcher.rb +8 -4
- data/lib/foreman_tasks_core/runner/parent.rb +48 -0
- data/lib/foreman_tasks_core/task_launcher.rb +8 -0
- data/lib/foreman_tasks_core/task_launcher/abstract.rb +42 -0
- data/lib/foreman_tasks_core/task_launcher/batch.rb +37 -0
- data/lib/foreman_tasks_core/task_launcher/single.rb +14 -0
- data/lib/foreman_tasks_core/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c46d9f3def1bf8405c45eb6a32331437dede8c68071d0c0c8a0159a2e489f007
|
4
|
+
data.tar.gz: 24e606e5743d4694c607514b25bbff6492153290d9d3c99546a91b6ce75967d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a3c8a38e39d80a3f5f9bc1deebdcf7e4b082838e687ae78846a17448302dddff4c00c24e81235ad455133c12bfd7112d657b7ca630210ce79bddd1f4d04e13f
|
7
|
+
data.tar.gz: c4777a0ca2d8d7562e3b2f0ab02293e7af5039753adcd9c7d0fabe1955726b60cf15e2c9664376410aff9e08de45054459ce9e2ac7a0d4a94ce49e02b3a61936
|
data/lib/foreman_tasks_core.rb
CHANGED
@@ -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,7 @@ module ForemanTasksCore
|
|
18
19
|
def run_refresh
|
19
20
|
logger.debug('refreshing runner')
|
20
21
|
refresh
|
21
|
-
|
22
|
-
@continuous_output = ForemanTasksCore::ContinuousOutput.new
|
23
|
-
if !new_data.empty? || @exit_status
|
24
|
-
return Runner::Update.new(new_data, @exit_status)
|
25
|
-
end
|
22
|
+
generate_updates
|
26
23
|
end
|
27
24
|
|
28
25
|
def start
|
@@ -59,13 +56,28 @@ module ForemanTasksCore
|
|
59
56
|
def publish_exception(context, exception, fatal = true)
|
60
57
|
logger.error("#{context} - #{exception.class} #{exception.message}:\n" + \
|
61
58
|
exception.backtrace.join("\n"))
|
62
|
-
|
59
|
+
dispatch_exception context, exception
|
63
60
|
publish_exit_status('EXCEPTION') if fatal
|
64
61
|
end
|
65
62
|
|
66
63
|
def publish_exit_status(status)
|
67
64
|
@exit_status = status
|
68
65
|
end
|
66
|
+
|
67
|
+
def dispatch_exception(context, exception)
|
68
|
+
@continuous_output.add_exception(context, exception)
|
69
|
+
end
|
70
|
+
|
71
|
+
def generate_updates
|
72
|
+
return {} if @continuous_output.empty? && @exit_status.nil?
|
73
|
+
new_data = @continuous_output
|
74
|
+
@continuous_output = ForemanTasksCore::ContinuousOutput.new
|
75
|
+
{ @suspended_action => Runner::Update.new(new_data, @exit_status) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def initialize_continuous_outputs
|
79
|
+
@continuous_output = ::ForemanTasksCore::ContinuousOutput.new
|
80
|
+
end
|
69
81
|
end
|
70
82
|
end
|
71
83
|
end
|
@@ -37,10 +37,14 @@ module ForemanTasksCore
|
|
37
37
|
|
38
38
|
def refresh_runner
|
39
39
|
@logger.debug("refresh runner #{@runner.id}")
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
updates = @runner.run_refresh
|
41
|
+
|
42
|
+
updates.each { |receiver, update| (receiver || @suspended_action) << update }
|
43
|
+
|
44
|
+
# This is a workaround when the runner does not accept the suspended action
|
45
|
+
main_key = updates.keys.any?(&:nil?) ? nil : @suspended_action
|
46
|
+
main_process = updates[main_key]
|
47
|
+
finish if main_process && main_process.exit_status
|
44
48
|
ensure
|
45
49
|
@refresh_planned = false
|
46
50
|
plan_next_refresh
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module ForemanTasksCore
|
2
|
+
module Runner
|
3
|
+
class Parent < Base
|
4
|
+
# targets = { hostname => { :execution_plan_id => "...", :run_step_id => id,
|
5
|
+
# :input => { ... } }
|
6
|
+
def initialize(targets = {}, suspended_action: nil)
|
7
|
+
@targets = targets
|
8
|
+
super suspended_action: suspended_action
|
9
|
+
end
|
10
|
+
|
11
|
+
def generate_updates
|
12
|
+
@outputs.reduce({}) do |acc, (key, value)|
|
13
|
+
if value.empty? && @exit_status.nil?
|
14
|
+
acc
|
15
|
+
else
|
16
|
+
@outputs[key] = ForemanTasksCore::ContinuousOutput.new
|
17
|
+
key = host_action(key) unless key == @suspended_action
|
18
|
+
acc.merge(key => Runner::Update.new(value, @exit_status))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize_continuous_outputs
|
24
|
+
@outputs = ([@suspended_action] + @targets.keys).reduce({}) do |acc, target|
|
25
|
+
acc.merge(target => ForemanTasksCore::ContinuousOutput.new)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def host_action(hostname)
|
30
|
+
options = @targets[hostname].slice('execution_plan_id', 'run_step_id')
|
31
|
+
.merge(:world => ForemanTasksCore.dynflow_world)
|
32
|
+
Dynflow::Action::Suspended.new OpenStruct.new(options)
|
33
|
+
end
|
34
|
+
|
35
|
+
def broadcast_data(data, type)
|
36
|
+
@outputs.each { |_k, output| output.add_output(data, type) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def publish_data_for(hostname, data, type)
|
40
|
+
@outputs[hostname].add_output(data, type)
|
41
|
+
end
|
42
|
+
|
43
|
+
def dispatch_exception(context, exception)
|
44
|
+
@outputs.values.each { |output| output.add_exception(context, exception) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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
|
+
private
|
17
|
+
|
18
|
+
def format_result(result)
|
19
|
+
if result.triggered?
|
20
|
+
{ :result => 'success', :task_id => result.execution_plan_id }
|
21
|
+
else
|
22
|
+
plan = world.persistence.load_execution_plan(result.id)
|
23
|
+
{ :result => 'error', :errors => plan.errors }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def action_class(input)
|
28
|
+
::Dynflow::Utils.constantize(input['action_class'])
|
29
|
+
end
|
30
|
+
|
31
|
+
def with_callback(input)
|
32
|
+
input.merge(:callback_host => callback)
|
33
|
+
end
|
34
|
+
|
35
|
+
def trigger(parent, klass, *input)
|
36
|
+
world.trigger do
|
37
|
+
world.plan_with_options(caller_action: parent, action_class: klass, args: input)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ForemanTasksCore
|
2
|
+
module TaskLauncher
|
3
|
+
class ParentAction < ::Dynflow::Action
|
4
|
+
include Dynflow::Action::WithSubPlans
|
5
|
+
include Dynflow::Action::WithPollingSubPlans
|
6
|
+
|
7
|
+
# { task_id => { :action_class => Klass, :input => input } }
|
8
|
+
def plan(launcher, input_hash)
|
9
|
+
launcher.launch_children(self, input_hash)
|
10
|
+
plan_self
|
11
|
+
end
|
12
|
+
|
13
|
+
def initiate
|
14
|
+
ping suspended_action
|
15
|
+
wait_for_sub_plans sub_plans
|
16
|
+
end
|
17
|
+
|
18
|
+
def rescue_strategy
|
19
|
+
Dynflow::Action::Rescue::Fail
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Batch < Abstract
|
24
|
+
def launch!(input)
|
25
|
+
trigger(nil, ParentAction, self, input)
|
26
|
+
end
|
27
|
+
|
28
|
+
def launch_children(parent, input_hash)
|
29
|
+
input_hash.each do |task_id, input|
|
30
|
+
launcher = Single.new(world, callback, :parent => parent)
|
31
|
+
launcher.launch!(input)
|
32
|
+
results[task_id] = launcher.results
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ForemanTasksCore
|
2
|
+
module TaskLauncher
|
3
|
+
class Single < Abstract
|
4
|
+
# { :action_class => "MyActionClass", :action_input => {} }
|
5
|
+
def launch!(input)
|
6
|
+
triggered = trigger(options[:parent],
|
7
|
+
action_class(input),
|
8
|
+
with_callback(input.fetch('action_input', {})))
|
9
|
+
@results = format_result(triggered)
|
10
|
+
triggered
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
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.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Nečas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dynflow
|
@@ -42,9 +42,14 @@ files:
|
|
42
42
|
- lib/foreman_tasks_core/runner/base.rb
|
43
43
|
- lib/foreman_tasks_core/runner/command_runner.rb
|
44
44
|
- lib/foreman_tasks_core/runner/dispatcher.rb
|
45
|
+
- lib/foreman_tasks_core/runner/parent.rb
|
45
46
|
- lib/foreman_tasks_core/runner/update.rb
|
46
47
|
- lib/foreman_tasks_core/settings_loader.rb
|
47
48
|
- lib/foreman_tasks_core/shareable_action.rb
|
49
|
+
- lib/foreman_tasks_core/task_launcher.rb
|
50
|
+
- lib/foreman_tasks_core/task_launcher/abstract.rb
|
51
|
+
- lib/foreman_tasks_core/task_launcher/batch.rb
|
52
|
+
- lib/foreman_tasks_core/task_launcher/single.rb
|
48
53
|
- lib/foreman_tasks_core/ticker.rb
|
49
54
|
- lib/foreman_tasks_core/version.rb
|
50
55
|
homepage: https://github.com/theforeman/foreman-tasks
|