smart_proxy_dynflow 0.5.1 → 0.7.0
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/Gemfile +4 -2
- data/bundler.d/inspect_anything.rb +1 -0
- data/bundler.d/x.local.rb +1 -0
- data/lib/smart_proxy_dynflow/action/batch.rb +7 -6
- data/lib/smart_proxy_dynflow/action/batch_callback.rb +7 -2
- data/lib/smart_proxy_dynflow/action/batch_runner.rb +1 -1
- data/lib/smart_proxy_dynflow/action/external_polling.rb +17 -0
- data/lib/smart_proxy_dynflow/action/output_collector.rb +1 -1
- data/lib/smart_proxy_dynflow/action/runner.rb +6 -1
- data/lib/smart_proxy_dynflow/action/shareable.rb +2 -2
- data/lib/smart_proxy_dynflow/action/single_runner_batch.rb +2 -14
- data/lib/smart_proxy_dynflow/callback.rb +7 -43
- data/lib/smart_proxy_dynflow/helpers.rb +6 -1
- data/lib/smart_proxy_dynflow/plugin.rb +9 -0
- data/lib/smart_proxy_dynflow/process_manager.rbs +46 -0
- data/lib/smart_proxy_dynflow/task_launcher/abstract.rb +10 -2
- data/lib/smart_proxy_dynflow/task_launcher/batch.rb +12 -11
- data/lib/smart_proxy_dynflow/task_launcher/group.rb +2 -2
- data/lib/smart_proxy_dynflow/task_launcher/single.rb +3 -2
- data/lib/smart_proxy_dynflow/version.rb +1 -1
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d19598abd3ab23ee44430f2e5c2207c6ac11d9c7919769ed5885408ee2e39f1c
|
4
|
+
data.tar.gz: 39d351c883a1f3c5d9402462961591d7bd4bd70e4ae0ca04d8c7095a710c70d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a557af273f69dda522cd9236d4f99cce270fd66d71c3b09150df6ba37eecbb0ddd2663e670b81c5ba806dd1af6927740c66f70b02551a42468d8e39f296f9e0f
|
7
|
+
data.tar.gz: 37a46da28658e4b26eceb19a86bdd2849cc387caf004213166bfd16580ec603a3f035fe797a7892423fad9e97129fcfeb95c82a789522d3088bf2a0dc3a3eefd
|
data/Gemfile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
gemspec :name => '
|
3
|
+
gemspec :name => 'smart_proxy_dynflow'
|
4
4
|
|
5
5
|
group :development do
|
6
6
|
gem 'pry'
|
@@ -8,10 +8,12 @@ end
|
|
8
8
|
|
9
9
|
group :test do
|
10
10
|
gem 'smart_proxy', :git => "https://github.com/theforeman/smart-proxy", :branch => "develop"
|
11
|
-
gem 'smart_proxy_dynflow', :path => '.'
|
12
11
|
|
12
|
+
gem 'minitest'
|
13
|
+
gem 'mocha'
|
13
14
|
gem 'public_suffix'
|
14
15
|
gem 'rack-test'
|
16
|
+
gem 'rake'
|
15
17
|
gem 'rubocop', '~> 0.52.1'
|
16
18
|
end
|
17
19
|
|
@@ -0,0 +1 @@
|
|
1
|
+
# gem 'inspect_anything'
|
@@ -0,0 +1 @@
|
|
1
|
+
# gem 'dynflow', :path => '../dynflow'
|
@@ -3,15 +3,16 @@ module Proxy::Dynflow::Action
|
|
3
3
|
include Dynflow::Action::WithSubPlans
|
4
4
|
include Dynflow::Action::WithPollingSubPlans
|
5
5
|
|
6
|
-
# {
|
6
|
+
# { execution_plan_uuid => { :action_class => Klass, :input => input } }
|
7
7
|
def plan(launcher, input_hash)
|
8
|
-
|
9
|
-
|
8
|
+
plan_self :input_hash => input_hash,
|
9
|
+
:launcher => launcher.to_hash
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
12
|
+
def create_sub_plans
|
13
|
+
Proxy::Dynflow::TaskLauncher::Abstract
|
14
|
+
.new_from_hash(world, input[:launcher])
|
15
|
+
.launch_children(self, input[:input_hash])
|
15
16
|
end
|
16
17
|
|
17
18
|
def rescue_strategy
|
@@ -1,12 +1,17 @@
|
|
1
1
|
module Proxy::Dynflow::Action
|
2
2
|
class BatchCallback < ::Dynflow::Action
|
3
3
|
def plan(input_hash, results)
|
4
|
-
|
4
|
+
# In input_hash there are complete inputs for all the actions for which this is reporting
|
5
|
+
# Trim it down to only the bare minimum we actually need
|
6
|
+
callbacks = input_hash.reduce({}) do |acc, (key, value)|
|
7
|
+
acc.merge(key => value['action_input']['callback'])
|
8
|
+
end
|
9
|
+
plan_self :targets => callbacks, :results => results
|
5
10
|
end
|
6
11
|
|
7
12
|
def run
|
8
13
|
payload = format_payload(input['targets'], input['results'])
|
9
|
-
|
14
|
+
Proxy::Dynflow::Callback::Request.new.callback({ :callbacks => payload }.to_json)
|
10
15
|
end
|
11
16
|
|
12
17
|
private
|
@@ -7,7 +7,7 @@ module Proxy::Dynflow::Action
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def initiate_runner
|
10
|
-
launcher =
|
10
|
+
launcher = Proxy::Dynflow::TaskLauncherRegistry.fetch(input[:operation])
|
11
11
|
launcher.runner_class.new(input[:targets], suspended_action: suspended_action)
|
12
12
|
end
|
13
13
|
end
|
@@ -52,6 +52,7 @@ module Proxy::Dynflow
|
|
52
52
|
|
53
53
|
def finish_run(update)
|
54
54
|
output[:exit_status] = update.exit_status
|
55
|
+
output[:result] = output_result
|
55
56
|
end
|
56
57
|
|
57
58
|
def process_external_event(event)
|
@@ -60,7 +61,7 @@ module Proxy::Dynflow
|
|
60
61
|
end
|
61
62
|
|
62
63
|
def process_update(update)
|
63
|
-
|
64
|
+
output_chunk(update.continuous_output.raw_outputs) unless update.continuous_output.raw_outputs.empty?
|
64
65
|
if update.exit_status
|
65
66
|
finish_run(update)
|
66
67
|
else
|
@@ -71,6 +72,10 @@ module Proxy::Dynflow
|
|
71
72
|
def failed_run?
|
72
73
|
output[:exit_status] != 0
|
73
74
|
end
|
75
|
+
|
76
|
+
def output_result
|
77
|
+
(stored_output_chunks + (@pending_output_chunks || [])).map { |c| c[:chunk] }.reduce([], &:concat)
|
78
|
+
end
|
74
79
|
end
|
75
80
|
end
|
76
81
|
end
|
@@ -12,14 +12,14 @@ module Proxy::Dynflow::Action
|
|
12
12
|
planned_action = plan_self(input)
|
13
13
|
# code only applicable, when run with SmartProxyDynflowCore in place
|
14
14
|
if on_proxy? && callback
|
15
|
-
plan_action(
|
15
|
+
plan_action(Proxy::Dynflow::Callback::Action, callback, planned_action.output)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
private
|
20
20
|
|
21
21
|
def on_proxy?
|
22
|
-
|
22
|
+
true
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -1,20 +1,8 @@
|
|
1
1
|
module Proxy::Dynflow::Action
|
2
2
|
class SingleRunnerBatch < Batch
|
3
3
|
def plan(launcher, input_hash)
|
4
|
-
|
5
|
-
|
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
|
4
|
+
results = super
|
5
|
+
plan_action BatchCallback, input_hash, results.output[:results]
|
18
6
|
end
|
19
7
|
|
20
8
|
def check_for_errors!(optional = true)
|
@@ -2,57 +2,21 @@ require 'rest-client'
|
|
2
2
|
|
3
3
|
module Proxy::Dynflow
|
4
4
|
module Callback
|
5
|
-
class Request
|
6
|
-
|
7
|
-
|
8
|
-
self.new.callback(prepare_payload(callback_info, data))
|
9
|
-
end
|
10
|
-
|
11
|
-
def ssl_options
|
12
|
-
return @ssl_options if defined? @ssl_options
|
13
|
-
@ssl_options = {}
|
14
|
-
settings = Proxy::SETTINGS
|
15
|
-
return @ssl_options unless URI.parse(settings.foreman_url).scheme == 'https'
|
16
|
-
|
17
|
-
@ssl_options[:verify_ssl] = OpenSSL::SSL::VERIFY_PEER
|
18
|
-
|
19
|
-
private_key_file = settings.foreman_ssl_key || settings.ssl_private_key
|
20
|
-
if private_key_file
|
21
|
-
private_key = File.read(private_key_file)
|
22
|
-
@ssl_options[:ssl_client_key] = OpenSSL::PKey::RSA.new(private_key)
|
23
|
-
end
|
24
|
-
certificate_file = settings.foreman_ssl_cert || settings.ssl_certificate
|
25
|
-
if certificate_file
|
26
|
-
certificate = File.read(certificate_file)
|
27
|
-
@ssl_options[:ssl_client_cert] = OpenSSL::X509::Certificate.new(certificate)
|
28
|
-
end
|
29
|
-
ca_file = settings.foreman_ssl_ca || settings.ssl_ca_file
|
30
|
-
@ssl_options[:ssl_ca_file] = ca_file if ca_file
|
31
|
-
@ssl_options
|
32
|
-
end
|
33
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def prepare_payload(callback, data)
|
38
|
-
{ :callback => callback, :data => data }.to_json
|
39
|
-
end
|
5
|
+
class Request < ::Proxy::HttpRequest::ForemanRequest
|
6
|
+
def self.send_to_foreman_tasks(callback_info, data)
|
7
|
+
self.new.callback({ :callback => callback_info, :data => data }.to_json)
|
40
8
|
end
|
41
9
|
|
42
10
|
def callback(payload)
|
43
|
-
|
11
|
+
request = request_factory.create_post '/foreman_tasks/api/tasks/callback',
|
12
|
+
payload
|
13
|
+
response = send_request(request)
|
14
|
+
|
44
15
|
if response.code.to_s != "200"
|
45
16
|
raise "Failed performing callback to Foreman server: #{response.code} #{response.body}"
|
46
17
|
end
|
47
18
|
response
|
48
19
|
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def callback_resource
|
53
|
-
@resource ||= RestClient::Resource.new(Proxy::SETTINGS.foreman_url + '/foreman_tasks/api/tasks/callback',
|
54
|
-
self.class.ssl_options)
|
55
|
-
end
|
56
20
|
end
|
57
21
|
|
58
22
|
class Action < ::Dynflow::Action
|
@@ -35,7 +35,12 @@ module Proxy
|
|
35
35
|
|
36
36
|
def task_status(task_id)
|
37
37
|
ep = world.persistence.load_execution_plan(task_id)
|
38
|
-
|
38
|
+
actions = ep.actions.map do |action|
|
39
|
+
hash = action.to_hash
|
40
|
+
hash[:output][:result] = action.output_result if action.is_a?(Proxy::Dynflow::Action::Runner)
|
41
|
+
hash
|
42
|
+
end
|
43
|
+
ep.to_hash.merge(:actions => actions)
|
39
44
|
rescue KeyError => _e
|
40
45
|
status 404
|
41
46
|
{}
|
@@ -14,13 +14,22 @@ module Proxy::Dynflow
|
|
14
14
|
:execution_plan_cleaner_age => 60 * 60 * 24
|
15
15
|
plugin :dynflow, Proxy::Dynflow::VERSION
|
16
16
|
|
17
|
+
capability(proc { self.available_operations })
|
18
|
+
|
17
19
|
after_activation do
|
18
20
|
require 'smart_proxy_dynflow/settings_loader'
|
19
21
|
require 'smart_proxy_dynflow/otp_manager'
|
20
22
|
require 'smart_proxy_dynflow/action'
|
21
23
|
require 'smart_proxy_dynflow/task_launcher'
|
22
24
|
|
25
|
+
Proxy::Dynflow::TaskLauncherRegistry.register('single',
|
26
|
+
Proxy::Dynflow::TaskLauncher::Single)
|
27
|
+
|
23
28
|
Proxy::Dynflow::Core.ensure_initialized
|
24
29
|
end
|
30
|
+
|
31
|
+
def self.available_operations
|
32
|
+
TaskLauncherRegistry.operations
|
33
|
+
end
|
25
34
|
end
|
26
35
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# TypeProf 0.21.2
|
2
|
+
|
3
|
+
# Classes
|
4
|
+
module Proxy
|
5
|
+
module Dynflow
|
6
|
+
class IOBuffer
|
7
|
+
@callback: nil
|
8
|
+
|
9
|
+
attr_accessor io: nil
|
10
|
+
attr_reader buffer: String
|
11
|
+
def initialize: (nil io) -> void
|
12
|
+
def on_data: -> nil
|
13
|
+
def to_io: -> IO
|
14
|
+
def to_s: -> String
|
15
|
+
def empty?: -> bool
|
16
|
+
def closed?: -> untyped
|
17
|
+
def close: -> nil
|
18
|
+
def read_available!: -> nil
|
19
|
+
def write_available!: -> nil
|
20
|
+
def add_data: (untyped data) -> String
|
21
|
+
|
22
|
+
private
|
23
|
+
def with_callback: (String? data) -> String?
|
24
|
+
end
|
25
|
+
|
26
|
+
class ProcessManager
|
27
|
+
@command: untyped
|
28
|
+
|
29
|
+
attr_reader stdin: IOBuffer
|
30
|
+
attr_reader stdout: IOBuffer
|
31
|
+
attr_reader stderr: IOBuffer
|
32
|
+
attr_reader pid: Integer
|
33
|
+
attr_reader status: Integer?
|
34
|
+
def initialize: (untyped command) -> void
|
35
|
+
def run!: -> ProcessManager
|
36
|
+
def start!: -> String
|
37
|
+
def started?: -> bool
|
38
|
+
def done?: -> bool
|
39
|
+
def close: -> [IOBuffer, IOBuffer, IOBuffer]
|
40
|
+
def process: (?timeout: nil) -> Array[untyped]?
|
41
|
+
def finish: -> Integer?
|
42
|
+
def on_stdout: -> nil
|
43
|
+
def on_stderr: -> nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -15,6 +15,14 @@ module Proxy::Dynflow
|
|
15
15
|
|
16
16
|
def self.input_format; end
|
17
17
|
|
18
|
+
def to_hash
|
19
|
+
{ :class => self.class.to_s, :callback => callback, :options => options }
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.new_from_hash(world, hash)
|
23
|
+
::Dynflow::Utils.constantize(hash[:class]).new(world, hash[:callback], hash[:options])
|
24
|
+
end
|
25
|
+
|
18
26
|
private
|
19
27
|
|
20
28
|
def format_result(result)
|
@@ -34,9 +42,9 @@ module Proxy::Dynflow
|
|
34
42
|
input.merge(:callback_host => callback)
|
35
43
|
end
|
36
44
|
|
37
|
-
def trigger(parent, klass, *input)
|
45
|
+
def trigger(parent, klass, *input, id: nil)
|
38
46
|
world.trigger do
|
39
|
-
world.plan_with_options(caller_action: parent, action_class: klass, args: input)
|
47
|
+
world.plan_with_options(caller_action: parent, action_class: klass, args: input, id: id)
|
40
48
|
end
|
41
49
|
end
|
42
50
|
end
|
@@ -2,36 +2,37 @@ module Proxy::Dynflow
|
|
2
2
|
module TaskLauncher
|
3
3
|
class Batch < Abstract
|
4
4
|
def launch!(input)
|
5
|
-
trigger(nil,
|
5
|
+
plan = trigger(nil, action_class, self, input)
|
6
|
+
results[:parent] = format_result(plan)
|
6
7
|
end
|
7
8
|
|
8
9
|
def launch_children(parent, input_hash)
|
9
|
-
input_hash.
|
10
|
+
input_hash.map do |task_id, input|
|
10
11
|
launcher = child_launcher(parent)
|
11
|
-
launcher.launch!(transform_input(input))
|
12
|
+
triggered = launcher.launch!(transform_input(input), id: task_id)
|
12
13
|
results[task_id] = launcher.results
|
14
|
+
triggered
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
16
18
|
def prepare_batch(input_hash)
|
17
|
-
|
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
|
19
|
+
input_hash
|
23
20
|
end
|
24
21
|
|
25
|
-
private
|
26
|
-
|
27
22
|
def child_launcher(parent)
|
28
23
|
Single.new(world, callback, :parent => parent)
|
29
24
|
end
|
30
25
|
|
26
|
+
private
|
27
|
+
|
31
28
|
# Identity by default
|
32
29
|
def transform_input(input)
|
33
30
|
input
|
34
31
|
end
|
32
|
+
|
33
|
+
def action_class
|
34
|
+
Proxy::Dynflow::Action::Batch
|
35
|
+
end
|
35
36
|
end
|
36
37
|
end
|
37
38
|
end
|
@@ -5,10 +5,11 @@ module Proxy::Dynflow
|
|
5
5
|
{ :action_class => "MyActionClass", :action_input => {} }
|
6
6
|
end
|
7
7
|
|
8
|
-
def launch!(input)
|
8
|
+
def launch!(input, id: nil)
|
9
9
|
triggered = trigger(options[:parent],
|
10
10
|
action_class(input),
|
11
|
-
with_callback(input.fetch('action_input', {}))
|
11
|
+
with_callback(input.fetch('action_input', {})),
|
12
|
+
id: id)
|
12
13
|
@results = format_result(triggered)
|
13
14
|
triggered
|
14
15
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smart_proxy_dynflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
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:
|
11
|
+
date: 2022-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dynflow
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.6'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.6'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rest-client
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -146,11 +146,14 @@ files:
|
|
146
146
|
- Gemfile
|
147
147
|
- LICENSE
|
148
148
|
- bundler.d/dynflow.rb
|
149
|
+
- bundler.d/inspect_anything.rb
|
150
|
+
- bundler.d/x.local.rb
|
149
151
|
- lib/smart_proxy_dynflow.rb
|
150
152
|
- lib/smart_proxy_dynflow/action.rb
|
151
153
|
- lib/smart_proxy_dynflow/action/batch.rb
|
152
154
|
- lib/smart_proxy_dynflow/action/batch_callback.rb
|
153
155
|
- lib/smart_proxy_dynflow/action/batch_runner.rb
|
156
|
+
- lib/smart_proxy_dynflow/action/external_polling.rb
|
154
157
|
- lib/smart_proxy_dynflow/action/output_collector.rb
|
155
158
|
- lib/smart_proxy_dynflow/action/runner.rb
|
156
159
|
- lib/smart_proxy_dynflow/action/shareable.rb
|
@@ -165,6 +168,7 @@ files:
|
|
165
168
|
- lib/smart_proxy_dynflow/middleware/keep_current_request_id.rb
|
166
169
|
- lib/smart_proxy_dynflow/otp_manager.rb
|
167
170
|
- lib/smart_proxy_dynflow/plugin.rb
|
171
|
+
- lib/smart_proxy_dynflow/process_manager.rbs
|
168
172
|
- lib/smart_proxy_dynflow/proxy_adapter.rb
|
169
173
|
- lib/smart_proxy_dynflow/runner.rb
|
170
174
|
- lib/smart_proxy_dynflow/runner/base.rb
|
@@ -195,7 +199,7 @@ require_paths:
|
|
195
199
|
- lib
|
196
200
|
required_ruby_version: !ruby/object:Gem::Requirement
|
197
201
|
requirements:
|
198
|
-
- - "
|
202
|
+
- - ">="
|
199
203
|
- !ruby/object:Gem::Version
|
200
204
|
version: '2.5'
|
201
205
|
required_rubygems_version: !ruby/object:Gem::Requirement
|