openbolt 5.4.0 → 5.5.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/Puppetfile +1 -2
- data/lib/bolt/bolt_option_parser.rb +63 -1
- data/lib/bolt/cli.rb +1 -1
- data/lib/bolt/config/options.rb +14 -0
- data/lib/bolt/config/transport/choria.rb +74 -0
- data/lib/bolt/config/transport/options.rb +108 -0
- data/lib/bolt/executor.rb +2 -0
- data/lib/bolt/pal/yaml_plan/transpiler.rb +1 -1
- data/lib/bolt/plugin/puppetdb.rb +1 -1
- data/lib/bolt/plugin.rb +1 -4
- data/lib/bolt/puppetdb/config.rb +8 -0
- data/lib/bolt/puppetdb/instance.rb +1 -0
- data/lib/bolt/result_set.rb +1 -1
- data/lib/bolt/transport/choria/agent_discovery.rb +137 -0
- data/lib/bolt/transport/choria/bolt_tasks.rb +248 -0
- data/lib/bolt/transport/choria/client.rb +281 -0
- data/lib/bolt/transport/choria/command_builders.rb +199 -0
- data/lib/bolt/transport/choria/helpers.rb +197 -0
- data/lib/bolt/transport/choria/shell.rb +560 -0
- data/lib/bolt/transport/choria.rb +218 -0
- data/lib/bolt/transport/winrm/connection.rb +13 -3
- data/lib/bolt/version.rb +1 -1
- data/lib/mcollective/agent/shell.ddl +154 -0
- metadata +31 -10
- data/lib/bolt/plugin/puppet_connect_data.rb +0 -85
- data/modules/puppet_connect/plans/test_input_data.pp +0 -94
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'base64'
|
|
4
|
+
require 'concurrent/map'
|
|
5
|
+
require 'digest/sha2'
|
|
6
|
+
require 'json'
|
|
7
|
+
require 'securerandom'
|
|
8
|
+
require 'shellwords'
|
|
9
|
+
require_relative '../../bolt/transport/base'
|
|
10
|
+
|
|
11
|
+
module Bolt
|
|
12
|
+
module Transport
|
|
13
|
+
# Choria transport for OpenBolt. Communicates with nodes via Choria's NATS
|
|
14
|
+
# pub/sub messaging infrastructure using the choria-mcorpc-support gem as
|
|
15
|
+
# the client library. Extends Transport::Base directly (not Simple) because
|
|
16
|
+
# Choria's pub/sub model doesn't fit the persistent connection/shell
|
|
17
|
+
# abstraction that Simple assumes.
|
|
18
|
+
#
|
|
19
|
+
# Available capabilities depend on which agents are installed on the
|
|
20
|
+
# target node:
|
|
21
|
+
#
|
|
22
|
+
# bolt_tasks agent only: Only run_task works, via the bolt_tasks agent
|
|
23
|
+
# which downloads task files from an OpenVox/Puppet Server and executes
|
|
24
|
+
# them via task_wrapper. All other operations fail with an actionable
|
|
25
|
+
# error directing the user to install the shell agent.
|
|
26
|
+
#
|
|
27
|
+
# shell agent installed (>= 1.2.1): run_command, run_script, and
|
|
28
|
+
# run_task work. run_task uses the bolt_tasks agent by default.
|
|
29
|
+
# To run local tasks via the shell agent, set task-agent to 'shell'
|
|
30
|
+
# in project config or specify --choria-task-agent shell.
|
|
31
|
+
#
|
|
32
|
+
# Upload, download, and plans are not yet supported.
|
|
33
|
+
class Choria < Base
|
|
34
|
+
def initialize
|
|
35
|
+
super
|
|
36
|
+
@config_mutex = Mutex.new
|
|
37
|
+
@config_error = nil
|
|
38
|
+
@client_configured = false
|
|
39
|
+
# Serializes RPC calls across batch threads. See the comment on
|
|
40
|
+
# rpc_request in helpers.rb for why this is necessary.
|
|
41
|
+
@rpc_mutex = Mutex.new
|
|
42
|
+
# Multiple batch threads write to this map concurrently when we
|
|
43
|
+
# have more than one collective.
|
|
44
|
+
@agent_cache = Concurrent::Map.new
|
|
45
|
+
@default_collective = nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Advertise both shell and powershell so tasks with either requirement
|
|
49
|
+
# can be selected. The per-target selection happens in
|
|
50
|
+
# select_implementation below, which picks the right feature set based
|
|
51
|
+
# on the target's detected OS.
|
|
52
|
+
def provided_features
|
|
53
|
+
%w[shell powershell]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Override to select task implementation based on the target's OS.
|
|
57
|
+
# Other transports rely on inventory features to pick the right
|
|
58
|
+
# implementation, but Choria discovers the OS at runtime via the
|
|
59
|
+
# os.family fact. We pass only the detected platform's feature so
|
|
60
|
+
# task.select_implementation picks the correct .ps1 or .sh file.
|
|
61
|
+
#
|
|
62
|
+
# @param target [Bolt::Target] Target whose OS determines the implementation
|
|
63
|
+
# @param task [Bolt::Task] Task with platform-specific implementations
|
|
64
|
+
# @return [Hash] Selected implementation hash with 'path', 'name', 'input_method', 'files' keys
|
|
65
|
+
def select_implementation(target, task)
|
|
66
|
+
features = windows_target?(target) ? ['powershell'] : ['shell']
|
|
67
|
+
impl = task.select_implementation(target, features)
|
|
68
|
+
impl['input_method'] ||= default_input_method(impl['path'])
|
|
69
|
+
impl
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Group targets by collective so each batch uses a single RPC client
|
|
73
|
+
# scope. MCollective RPC calls are published to a collective-specific
|
|
74
|
+
# NATS subject, so targets in different collectives must be in separate
|
|
75
|
+
# batches. Most deployments have one collective, yielding one batch.
|
|
76
|
+
# Bolt runs each batch in its own thread and @rpc_mutex serializes
|
|
77
|
+
# the RPC calls across threads to prevent response misrouting.
|
|
78
|
+
#
|
|
79
|
+
# @param targets [Array<Bolt::Target>] All targets for this operation
|
|
80
|
+
# @return [Array<Array<Bolt::Target>>] Targets grouped by collective
|
|
81
|
+
def batches(targets)
|
|
82
|
+
# Populates @default_collective from the Choria config so targets
|
|
83
|
+
# without an explicit collective are grouped correctly.
|
|
84
|
+
configure_client(targets.first)
|
|
85
|
+
targets.group_by { |target| collective_for(target) }.values
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Override batch_task to handle multiple targets in one thread using the RPC.
|
|
89
|
+
# Implementation grouping (mixed-platform support) is handled internally
|
|
90
|
+
# by run_task_via_bolt_tasks and run_task_via_shell.
|
|
91
|
+
#
|
|
92
|
+
# @param targets [Array<Bolt::Target>] Targets in a single collective batch
|
|
93
|
+
# @param task [Bolt::Task] Task to execute
|
|
94
|
+
# @param arguments [Hash] Task parameter names to values
|
|
95
|
+
# @param options [Hash] Execution options (unused currently, passed through from Base)
|
|
96
|
+
# @param position [Array] Positional info for result tracking
|
|
97
|
+
# @param callback [Proc] Called with :node_start and :node_result events
|
|
98
|
+
# @return [Array<Bolt::Result>] Results for all targets (successes and failures)
|
|
99
|
+
def batch_task(targets, task, arguments, _options = {}, position = [], &callback)
|
|
100
|
+
chosen_agent = targets.first.options['task-agent'] || 'bolt_tasks'
|
|
101
|
+
result_opts = { action: 'task', name: task.name, position: position }
|
|
102
|
+
|
|
103
|
+
# The results var here is the error results for incapable targets, to which we'll add in
|
|
104
|
+
# the successful results from the capable targets as we go.
|
|
105
|
+
capable, results = prepare_targets(targets, chosen_agent, result_opts, &callback)
|
|
106
|
+
|
|
107
|
+
logger.debug { "Task #{task.name} routing: agent: #{chosen_agent}, #{capable.size} capable / #{targets.size - capable.size} incapable" }
|
|
108
|
+
|
|
109
|
+
unless capable.empty?
|
|
110
|
+
capable.each { |target| callback&.call(type: :node_start, target: target) }
|
|
111
|
+
arguments = unwrap_sensitive_args(arguments)
|
|
112
|
+
|
|
113
|
+
results += case chosen_agent
|
|
114
|
+
when 'bolt_tasks'
|
|
115
|
+
run_task_via_bolt_tasks(capable, task, arguments, result_opts, &callback)
|
|
116
|
+
when 'shell'
|
|
117
|
+
run_task_via_shell(capable, task, arguments, result_opts, &callback)
|
|
118
|
+
else
|
|
119
|
+
raise Bolt::Error.new(
|
|
120
|
+
"Unsupported task-agent '#{chosen_agent}'",
|
|
121
|
+
'bolt/choria-unsupported-agent'
|
|
122
|
+
)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
results
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Override batch_task_with for per-target arguments. Only called
|
|
130
|
+
# from the run_task_with Puppet plan function (no CLI or Ruby API
|
|
131
|
+
# path uses this). Discovery is batched upfront, but execution is
|
|
132
|
+
# sequential per-target because MCollective RPC calls send the
|
|
133
|
+
# same arguments to all targets. A future optimization could batch
|
|
134
|
+
# the download/infra-setup/polling steps while keeping only the
|
|
135
|
+
# start step per-target.
|
|
136
|
+
#
|
|
137
|
+
# THIS IS NOT YET READY FOR PRODUCTION. The API is stable, but we don't
|
|
138
|
+
# yet have full plan support and this runs the task sequentially across
|
|
139
|
+
# targets, which is very inefficient. It had to be implemented now, though,
|
|
140
|
+
# in order to prevent the assert_batch_size_one from the Base interface
|
|
141
|
+
# from blowing things up.
|
|
142
|
+
#
|
|
143
|
+
# @param targets [Array<Bolt::Target>] Targets in a single collective batch
|
|
144
|
+
# @param task [Bolt::Task] Task to execute
|
|
145
|
+
# @param target_mapping [Hash{Bolt::Target => Hash}] Per-target argument hashes
|
|
146
|
+
# @param options [Hash] Execution options (passed through from Base)
|
|
147
|
+
# @param position [Array] Positional info for result tracking
|
|
148
|
+
# @param callback [Proc] Called with :node_start and :node_result events
|
|
149
|
+
# @return [Array<Bolt::Result>] Results for all targets
|
|
150
|
+
def batch_task_with(targets, task, target_mapping, options = {}, position = [], &callback)
|
|
151
|
+
# Pre-warm the agent cache so individual batch_task calls are cache hits
|
|
152
|
+
configure_client(targets.first)
|
|
153
|
+
discover_agents(targets)
|
|
154
|
+
|
|
155
|
+
results = []
|
|
156
|
+
targets.each do |target|
|
|
157
|
+
results += batch_task([target], task, target_mapping[target], options, position, &callback)
|
|
158
|
+
end
|
|
159
|
+
results
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Override batch_connected? to check all targets in one RPC call. Only
|
|
163
|
+
# used for wait_until_available in plans.
|
|
164
|
+
#
|
|
165
|
+
# @param targets [Array<Bolt::Target>] Targets to check connectivity for
|
|
166
|
+
# @return [Boolean] True if all targets responded to ping
|
|
167
|
+
def batch_connected?(targets)
|
|
168
|
+
logger.debug { "Checking connectivity for #{target_count(targets)}" }
|
|
169
|
+
first_target = targets.first
|
|
170
|
+
configure_client(first_target)
|
|
171
|
+
|
|
172
|
+
response = rpc_request('rpcutil', targets, 'rpcutil.ping') do |client|
|
|
173
|
+
client.ping
|
|
174
|
+
end
|
|
175
|
+
response[:responded].length == targets.length
|
|
176
|
+
rescue StandardError => e
|
|
177
|
+
raise if e.is_a?(Bolt::Error)
|
|
178
|
+
|
|
179
|
+
logger.warn { "Batch connectivity check failed: #{e.class}: #{e.message}" }
|
|
180
|
+
false
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def upload(_target, _source, _destination, _options = {}, _position = [])
|
|
184
|
+
raise Bolt::Error.new(
|
|
185
|
+
'The Choria transport does not yet support upload.',
|
|
186
|
+
'bolt/choria-unsupported-operation'
|
|
187
|
+
)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def download(_target, _source, _destination, _options = {}, _position = [])
|
|
191
|
+
raise Bolt::Error.new(
|
|
192
|
+
'The Choria transport does not yet support download.',
|
|
193
|
+
'bolt/choria-unsupported-operation'
|
|
194
|
+
)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Returns the Choria node identity for a target. Uses the transport
|
|
198
|
+
# 'host' config if set, falling back to target.host (which Bolt
|
|
199
|
+
# derives from the URI or target name).
|
|
200
|
+
def choria_identity(target)
|
|
201
|
+
target.options['host'] || target.host
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Returns the collective for a target, used by batches() to group
|
|
205
|
+
# targets. Falls back to the default collective from the loaded config.
|
|
206
|
+
def collective_for(target)
|
|
207
|
+
target.options['collective'] || @default_collective
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
require_relative 'choria/agent_discovery'
|
|
214
|
+
require_relative 'choria/bolt_tasks'
|
|
215
|
+
require_relative 'choria/client'
|
|
216
|
+
require_relative 'choria/command_builders'
|
|
217
|
+
require_relative 'choria/helpers'
|
|
218
|
+
require_relative 'choria/shell'
|
|
@@ -162,9 +162,20 @@ module Bolt
|
|
|
162
162
|
raise Bolt::Node::FileError.new(e.message, 'WRITE_ERROR')
|
|
163
163
|
end
|
|
164
164
|
|
|
165
|
-
def
|
|
165
|
+
def require_ruby_smb
|
|
166
166
|
# lazy-load expensive gem code
|
|
167
|
+
# In BinData 2.5.0+, the below commit makes things VERY noisy when loading RubySMB, so
|
|
168
|
+
# we temporarily disable warnings while we load it. If this ever gets fixed, get rid
|
|
169
|
+
# of this function and restore the plain 'require' where this function is called.
|
|
170
|
+
# https://github.com/dmendel/bindata/commit/2c8588a1ae5959080fffa429e07027f2ff20161c
|
|
171
|
+
prev = $VERBOSE
|
|
172
|
+
$VERBOSE = nil
|
|
167
173
|
require 'ruby_smb'
|
|
174
|
+
$VERBOSE = prev
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def upload_file_smb(source, destination)
|
|
178
|
+
require_ruby_smb
|
|
168
179
|
|
|
169
180
|
win_dest = destination.tr('/', '\\')
|
|
170
181
|
if (md = win_dest.match(/^([a-z]):\\(.*)/i))
|
|
@@ -215,8 +226,7 @@ module Bolt
|
|
|
215
226
|
end
|
|
216
227
|
|
|
217
228
|
def download_file_smb(source, destination)
|
|
218
|
-
|
|
219
|
-
require 'ruby_smb'
|
|
229
|
+
require_ruby_smb
|
|
220
230
|
|
|
221
231
|
win_source = source.tr('/', '\\')
|
|
222
232
|
if (md = win_source.match(/^([a-z]):\\(.*)/i))
|
data/lib/bolt/version.rb
CHANGED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
metadata :name => "shell",
|
|
2
|
+
:description => "Run commands with the local shell",
|
|
3
|
+
:author => "Puppet Labs",
|
|
4
|
+
:license => "Apache-2.0",
|
|
5
|
+
:version => "1.2.1",
|
|
6
|
+
:url => "https://github.com/choria-plugins/shell-agent",
|
|
7
|
+
:timeout => 180
|
|
8
|
+
|
|
9
|
+
action "run", :description => "Run a command" do
|
|
10
|
+
display :always
|
|
11
|
+
|
|
12
|
+
input :command,
|
|
13
|
+
:prompt => "Command",
|
|
14
|
+
:description => "Command to run",
|
|
15
|
+
:type => :string,
|
|
16
|
+
:validation => '.*',
|
|
17
|
+
:maxlength => 10 * 1024,
|
|
18
|
+
:optional => false
|
|
19
|
+
|
|
20
|
+
input :user,
|
|
21
|
+
:prompt => "User",
|
|
22
|
+
:description => "User to run command as",
|
|
23
|
+
:type => :string,
|
|
24
|
+
:validation => '.*',
|
|
25
|
+
:maxlength => 1024,
|
|
26
|
+
:optional => true
|
|
27
|
+
|
|
28
|
+
input :timeout,
|
|
29
|
+
:prompt => "Timeout",
|
|
30
|
+
:description => "Timeout to wait for the command to complete",
|
|
31
|
+
:type => :float,
|
|
32
|
+
:optional => true
|
|
33
|
+
# TODO(richardc): validate positive. May need another validator class
|
|
34
|
+
|
|
35
|
+
output :stdout,
|
|
36
|
+
:description => "stdout from the command",
|
|
37
|
+
:display_as => "stdout"
|
|
38
|
+
|
|
39
|
+
output :stderr,
|
|
40
|
+
:description => "stderr from the command",
|
|
41
|
+
:display_as => "stderr"
|
|
42
|
+
|
|
43
|
+
output :success,
|
|
44
|
+
:description => "did the process exit successfully",
|
|
45
|
+
:display_as => "success"
|
|
46
|
+
|
|
47
|
+
output :exitcode,
|
|
48
|
+
:description => "exit code of the command",
|
|
49
|
+
:display_as => "exitcode"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
action "start", :description => "Spawn a command" do
|
|
53
|
+
display :always
|
|
54
|
+
|
|
55
|
+
input :command,
|
|
56
|
+
:prompt => "Command",
|
|
57
|
+
:description => "Command to run",
|
|
58
|
+
:type => :string,
|
|
59
|
+
:validation => '.*',
|
|
60
|
+
:maxlength => 10 * 1024,
|
|
61
|
+
:optional => false
|
|
62
|
+
|
|
63
|
+
input :user,
|
|
64
|
+
:prompt => "User",
|
|
65
|
+
:description => "User to run command as",
|
|
66
|
+
:type => :string,
|
|
67
|
+
:validation => '.*',
|
|
68
|
+
:maxlength => 1024,
|
|
69
|
+
:optional => true
|
|
70
|
+
|
|
71
|
+
output :handle,
|
|
72
|
+
:description => "identifier to a running command",
|
|
73
|
+
:display_as => "handle"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
action "status", :description => "Get status of managed command" do
|
|
77
|
+
display :always
|
|
78
|
+
|
|
79
|
+
input :handle,
|
|
80
|
+
:prompt => "Handle",
|
|
81
|
+
:description => "Handle of the command",
|
|
82
|
+
:type => :string,
|
|
83
|
+
:validation => '^[0-9a-z\-]*$',
|
|
84
|
+
:maxlength => 36,
|
|
85
|
+
:optional => false
|
|
86
|
+
|
|
87
|
+
input :stdout_offset,
|
|
88
|
+
:prompt => "stdout_offset",
|
|
89
|
+
:description => "stdout_offset",
|
|
90
|
+
:type => :integer,
|
|
91
|
+
:optional => true
|
|
92
|
+
|
|
93
|
+
input :stderr_offset,
|
|
94
|
+
:prompt => "stderr_offset",
|
|
95
|
+
:description => "stderr_offset",
|
|
96
|
+
:type => :integer,
|
|
97
|
+
:optional => true
|
|
98
|
+
|
|
99
|
+
# Running, Exited
|
|
100
|
+
output :status,
|
|
101
|
+
:description => "status of the command",
|
|
102
|
+
:display_as => "status"
|
|
103
|
+
|
|
104
|
+
# Stdout to this point - resets internal state
|
|
105
|
+
output :stdout,
|
|
106
|
+
:description => "stdout of the command",
|
|
107
|
+
:display_as => "stdout"
|
|
108
|
+
|
|
109
|
+
# Stderr to this point - resets internal state
|
|
110
|
+
output :stderr,
|
|
111
|
+
:description => "stderr of the command",
|
|
112
|
+
:display_as => "stderr"
|
|
113
|
+
|
|
114
|
+
# Only meaningful if status == Exited
|
|
115
|
+
output :exitcode,
|
|
116
|
+
:description => "exitcode of the command",
|
|
117
|
+
:display_as => "exitcode"
|
|
118
|
+
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
action "list", :description => "Get a list of all running commands" do
|
|
122
|
+
display :always
|
|
123
|
+
|
|
124
|
+
output :jobs,
|
|
125
|
+
:description => "state of managed jobs",
|
|
126
|
+
:display_as => "jobs"
|
|
127
|
+
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
action "statuses", :description => "Get status and output of multiple managed commands" do
|
|
131
|
+
display :always
|
|
132
|
+
|
|
133
|
+
input :handles,
|
|
134
|
+
:prompt => "Handles",
|
|
135
|
+
:description => "Array of command handles to query",
|
|
136
|
+
:type => :array,
|
|
137
|
+
:optional => false
|
|
138
|
+
|
|
139
|
+
output :statuses,
|
|
140
|
+
:description => "status and output keyed by handle",
|
|
141
|
+
:display_as => "statuses"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
action "kill", :description => "Kill a command by handle" do
|
|
145
|
+
display :always
|
|
146
|
+
|
|
147
|
+
input :handle,
|
|
148
|
+
:prompt => "Handle",
|
|
149
|
+
:description => "Handle of the command",
|
|
150
|
+
:type => :string,
|
|
151
|
+
:validation => '^[0-9a-z\-]*$',
|
|
152
|
+
:maxlength => 36,
|
|
153
|
+
:optional => false
|
|
154
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: openbolt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- OpenVox Project
|
|
@@ -51,6 +51,20 @@ dependencies:
|
|
|
51
51
|
- - ">="
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
53
|
version: '2.2'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: choria-mcorpc-support
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '2.26'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '2.26'
|
|
54
68
|
- !ruby/object:Gem::Dependency
|
|
55
69
|
name: concurrent-ruby
|
|
56
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -327,16 +341,16 @@ dependencies:
|
|
|
327
341
|
name: terminal-table
|
|
328
342
|
requirement: !ruby/object:Gem::Requirement
|
|
329
343
|
requirements:
|
|
330
|
-
- - "
|
|
344
|
+
- - "~>"
|
|
331
345
|
- !ruby/object:Gem::Version
|
|
332
|
-
version: '
|
|
346
|
+
version: '4.0'
|
|
333
347
|
type: :runtime
|
|
334
348
|
prerelease: false
|
|
335
349
|
version_requirements: !ruby/object:Gem::Requirement
|
|
336
350
|
requirements:
|
|
337
|
-
- - "
|
|
351
|
+
- - "~>"
|
|
338
352
|
- !ruby/object:Gem::Version
|
|
339
|
-
version: '
|
|
353
|
+
version: '4.0'
|
|
340
354
|
- !ruby/object:Gem::Dependency
|
|
341
355
|
name: winrm
|
|
342
356
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -445,14 +459,14 @@ dependencies:
|
|
|
445
459
|
requirements:
|
|
446
460
|
- - "~>"
|
|
447
461
|
- !ruby/object:Gem::Version
|
|
448
|
-
version: 5.
|
|
462
|
+
version: 5.2.0
|
|
449
463
|
type: :development
|
|
450
464
|
prerelease: false
|
|
451
465
|
version_requirements: !ruby/object:Gem::Requirement
|
|
452
466
|
requirements:
|
|
453
467
|
- - "~>"
|
|
454
468
|
- !ruby/object:Gem::Version
|
|
455
|
-
version: 5.
|
|
469
|
+
version: 5.2.0
|
|
456
470
|
description: Execute commands remotely over SSH and WinRM
|
|
457
471
|
email:
|
|
458
472
|
- openvox@voxpupuli.org
|
|
@@ -550,6 +564,7 @@ files:
|
|
|
550
564
|
- lib/bolt/config/modulepath.rb
|
|
551
565
|
- lib/bolt/config/options.rb
|
|
552
566
|
- lib/bolt/config/transport/base.rb
|
|
567
|
+
- lib/bolt/config/transport/choria.rb
|
|
553
568
|
- lib/bolt/config/transport/docker.rb
|
|
554
569
|
- lib/bolt/config/transport/jail.rb
|
|
555
570
|
- lib/bolt/config/transport/local.rb
|
|
@@ -618,7 +633,6 @@ files:
|
|
|
618
633
|
- lib/bolt/plugin/env_var.rb
|
|
619
634
|
- lib/bolt/plugin/module.rb
|
|
620
635
|
- lib/bolt/plugin/prompt.rb
|
|
621
|
-
- lib/bolt/plugin/puppet_connect_data.rb
|
|
622
636
|
- lib/bolt/plugin/puppetdb.rb
|
|
623
637
|
- lib/bolt/plugin/task.rb
|
|
624
638
|
- lib/bolt/project.rb
|
|
@@ -646,6 +660,13 @@ files:
|
|
|
646
660
|
- lib/bolt/task/puppet_server.rb
|
|
647
661
|
- lib/bolt/task/run.rb
|
|
648
662
|
- lib/bolt/transport/base.rb
|
|
663
|
+
- lib/bolt/transport/choria.rb
|
|
664
|
+
- lib/bolt/transport/choria/agent_discovery.rb
|
|
665
|
+
- lib/bolt/transport/choria/bolt_tasks.rb
|
|
666
|
+
- lib/bolt/transport/choria/client.rb
|
|
667
|
+
- lib/bolt/transport/choria/command_builders.rb
|
|
668
|
+
- lib/bolt/transport/choria/helpers.rb
|
|
669
|
+
- lib/bolt/transport/choria/shell.rb
|
|
649
670
|
- lib/bolt/transport/docker.rb
|
|
650
671
|
- lib/bolt/transport/docker/connection.rb
|
|
651
672
|
- lib/bolt/transport/jail.rb
|
|
@@ -681,6 +702,7 @@ files:
|
|
|
681
702
|
- lib/bolt_spec/plans/publish_stub.rb
|
|
682
703
|
- lib/bolt_spec/run.rb
|
|
683
704
|
- lib/logging_extensions/logging.rb
|
|
705
|
+
- lib/mcollective/agent/shell.ddl
|
|
684
706
|
- libexec/apply_catalog.rb
|
|
685
707
|
- libexec/bolt_catalog
|
|
686
708
|
- libexec/custom_facts.rb
|
|
@@ -694,7 +716,6 @@ files:
|
|
|
694
716
|
- modules/canary/lib/puppet/functions/canary/random_split.rb
|
|
695
717
|
- modules/canary/lib/puppet/functions/canary/skip.rb
|
|
696
718
|
- modules/canary/plans/init.pp
|
|
697
|
-
- modules/puppet_connect/plans/test_input_data.pp
|
|
698
719
|
- modules/puppetdb_fact/plans/init.pp
|
|
699
720
|
- resources/bolt_bash_completion.sh
|
|
700
721
|
homepage: https://github.com/OpenVoxProject/openbolt/
|
|
@@ -715,7 +736,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
715
736
|
- !ruby/object:Gem::Version
|
|
716
737
|
version: '0'
|
|
717
738
|
requirements: []
|
|
718
|
-
rubygems_version: 4.0.
|
|
739
|
+
rubygems_version: 4.0.6
|
|
719
740
|
specification_version: 4
|
|
720
741
|
summary: Execute commands remotely over SSH and WinRM
|
|
721
742
|
test_files: []
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Bolt
|
|
4
|
-
class Plugin
|
|
5
|
-
class PuppetConnectData
|
|
6
|
-
INPUT_DATA_VAR = 'PUPPET_CONNECT_INPUT_DATA'
|
|
7
|
-
|
|
8
|
-
def initialize(context:, **_opts)
|
|
9
|
-
if ENV.key?(INPUT_DATA_VAR)
|
|
10
|
-
# The user provided input data that they will copy-paste into the Puppet Connect UI
|
|
11
|
-
# for inventory syncing. This environment variable will likely be set when invoking a
|
|
12
|
-
# general "test Puppet Connect input data" command. That command tests that parsing
|
|
13
|
-
# the inventory with the given input data results in connectable targets. Part of
|
|
14
|
-
# that requires validating that the input data contains all of the referenced keys,
|
|
15
|
-
# which is what this plugin will do in validate_resolve_reference.
|
|
16
|
-
@input_data_path = ENV[INPUT_DATA_VAR]
|
|
17
|
-
data_path = @input_data_path
|
|
18
|
-
else
|
|
19
|
-
# The user is using this plugin during a regular Bolt invocation, so fetch the (minimal)
|
|
20
|
-
# required data from the default location. This data should typically be non-autoloadable
|
|
21
|
-
# secrets like WinRM passwords.
|
|
22
|
-
#
|
|
23
|
-
# Note that any unspecified keys will be resolved to nil.
|
|
24
|
-
data_path = File.join(context.boltdir, 'puppet_connect_data.yaml')
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
@data = Bolt::Util.read_optional_yaml_hash(
|
|
28
|
-
data_path,
|
|
29
|
-
File.basename(data_path)
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
if @input_data_path
|
|
33
|
-
# Validate that the data does not contain any plugin-reference
|
|
34
|
-
# values
|
|
35
|
-
@data.each do |key, toplevel_value|
|
|
36
|
-
# Use walk_vals to check for nested plugin references
|
|
37
|
-
Bolt::Util.walk_vals(toplevel_value) do |current_value|
|
|
38
|
-
if current_value.is_a?(Hash) && current_value.key?('_plugin')
|
|
39
|
-
raise invalid_input_data_err("the #{key} key's value contains a plugin reference")
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
current_value
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def name
|
|
49
|
-
'puppet_connect_data'
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def hooks
|
|
53
|
-
hook_descriptions.keys
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def hook_descriptions
|
|
57
|
-
{
|
|
58
|
-
resolve_reference: nil,
|
|
59
|
-
validate_resolve_reference: nil
|
|
60
|
-
}
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def resolve_reference(opts)
|
|
64
|
-
key = opts['key']
|
|
65
|
-
@data[key]
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def validate_resolve_reference(opts)
|
|
69
|
-
unless opts['key']
|
|
70
|
-
raise Bolt::ValidationError,
|
|
71
|
-
"puppet_connect_data plugin requires that 'key' be specified"
|
|
72
|
-
end
|
|
73
|
-
if @input_data_path && !@data.key?(opts['key'])
|
|
74
|
-
# Input data for Puppet Connect was provided and opts['key'] does not have a
|
|
75
|
-
# value specified. Raise an error for this case.
|
|
76
|
-
raise invalid_input_data_err("a value for the #{opts['key']} key is not specified")
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def invalid_input_data_err(msg)
|
|
81
|
-
Bolt::ValidationError.new("invalid input data #{@input_data_path}: #{msg}")
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|