openbolt 5.4.0 → 5.6.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 +8 -9
- data/bolt-modules/boltlib/lib/puppet/datatypes/target.rb +2 -2
- data/bolt-modules/boltlib/lib/puppet/functions/facts.rb +1 -1
- data/lib/bolt/application.rb +2 -4
- data/lib/bolt/bolt_option_parser.rb +63 -1
- data/lib/bolt/cli.rb +1 -1
- data/lib/bolt/config/options.rb +16 -2
- 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/outputter/human.rb +1 -1
- data/lib/bolt/outputter/json.rb +2 -2
- data/lib/bolt/outputter/rainbow.rb +5 -1
- 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 +39 -12
- 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.6.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
|
|
@@ -123,16 +137,22 @@ dependencies:
|
|
|
123
137
|
name: jwt
|
|
124
138
|
requirement: !ruby/object:Gem::Requirement
|
|
125
139
|
requirements:
|
|
126
|
-
- - "
|
|
140
|
+
- - ">="
|
|
127
141
|
- !ruby/object:Gem::Version
|
|
128
142
|
version: '2.2'
|
|
143
|
+
- - "<"
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '4.0'
|
|
129
146
|
type: :runtime
|
|
130
147
|
prerelease: false
|
|
131
148
|
version_requirements: !ruby/object:Gem::Requirement
|
|
132
149
|
requirements:
|
|
133
|
-
- - "
|
|
150
|
+
- - ">="
|
|
134
151
|
- !ruby/object:Gem::Version
|
|
135
152
|
version: '2.2'
|
|
153
|
+
- - "<"
|
|
154
|
+
- !ruby/object:Gem::Version
|
|
155
|
+
version: '4.0'
|
|
136
156
|
- !ruby/object:Gem::Dependency
|
|
137
157
|
name: logging
|
|
138
158
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -327,16 +347,16 @@ dependencies:
|
|
|
327
347
|
name: terminal-table
|
|
328
348
|
requirement: !ruby/object:Gem::Requirement
|
|
329
349
|
requirements:
|
|
330
|
-
- - "
|
|
350
|
+
- - "~>"
|
|
331
351
|
- !ruby/object:Gem::Version
|
|
332
|
-
version: '
|
|
352
|
+
version: '4.0'
|
|
333
353
|
type: :runtime
|
|
334
354
|
prerelease: false
|
|
335
355
|
version_requirements: !ruby/object:Gem::Requirement
|
|
336
356
|
requirements:
|
|
337
|
-
- - "
|
|
357
|
+
- - "~>"
|
|
338
358
|
- !ruby/object:Gem::Version
|
|
339
|
-
version: '
|
|
359
|
+
version: '4.0'
|
|
340
360
|
- !ruby/object:Gem::Dependency
|
|
341
361
|
name: winrm
|
|
342
362
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -445,14 +465,14 @@ dependencies:
|
|
|
445
465
|
requirements:
|
|
446
466
|
- - "~>"
|
|
447
467
|
- !ruby/object:Gem::Version
|
|
448
|
-
version: 5.
|
|
468
|
+
version: 5.2.0
|
|
449
469
|
type: :development
|
|
450
470
|
prerelease: false
|
|
451
471
|
version_requirements: !ruby/object:Gem::Requirement
|
|
452
472
|
requirements:
|
|
453
473
|
- - "~>"
|
|
454
474
|
- !ruby/object:Gem::Version
|
|
455
|
-
version: 5.
|
|
475
|
+
version: 5.2.0
|
|
456
476
|
description: Execute commands remotely over SSH and WinRM
|
|
457
477
|
email:
|
|
458
478
|
- openvox@voxpupuli.org
|
|
@@ -550,6 +570,7 @@ files:
|
|
|
550
570
|
- lib/bolt/config/modulepath.rb
|
|
551
571
|
- lib/bolt/config/options.rb
|
|
552
572
|
- lib/bolt/config/transport/base.rb
|
|
573
|
+
- lib/bolt/config/transport/choria.rb
|
|
553
574
|
- lib/bolt/config/transport/docker.rb
|
|
554
575
|
- lib/bolt/config/transport/jail.rb
|
|
555
576
|
- lib/bolt/config/transport/local.rb
|
|
@@ -618,7 +639,6 @@ files:
|
|
|
618
639
|
- lib/bolt/plugin/env_var.rb
|
|
619
640
|
- lib/bolt/plugin/module.rb
|
|
620
641
|
- lib/bolt/plugin/prompt.rb
|
|
621
|
-
- lib/bolt/plugin/puppet_connect_data.rb
|
|
622
642
|
- lib/bolt/plugin/puppetdb.rb
|
|
623
643
|
- lib/bolt/plugin/task.rb
|
|
624
644
|
- lib/bolt/project.rb
|
|
@@ -646,6 +666,13 @@ files:
|
|
|
646
666
|
- lib/bolt/task/puppet_server.rb
|
|
647
667
|
- lib/bolt/task/run.rb
|
|
648
668
|
- lib/bolt/transport/base.rb
|
|
669
|
+
- lib/bolt/transport/choria.rb
|
|
670
|
+
- lib/bolt/transport/choria/agent_discovery.rb
|
|
671
|
+
- lib/bolt/transport/choria/bolt_tasks.rb
|
|
672
|
+
- lib/bolt/transport/choria/client.rb
|
|
673
|
+
- lib/bolt/transport/choria/command_builders.rb
|
|
674
|
+
- lib/bolt/transport/choria/helpers.rb
|
|
675
|
+
- lib/bolt/transport/choria/shell.rb
|
|
649
676
|
- lib/bolt/transport/docker.rb
|
|
650
677
|
- lib/bolt/transport/docker/connection.rb
|
|
651
678
|
- lib/bolt/transport/jail.rb
|
|
@@ -681,6 +708,7 @@ files:
|
|
|
681
708
|
- lib/bolt_spec/plans/publish_stub.rb
|
|
682
709
|
- lib/bolt_spec/run.rb
|
|
683
710
|
- lib/logging_extensions/logging.rb
|
|
711
|
+
- lib/mcollective/agent/shell.ddl
|
|
684
712
|
- libexec/apply_catalog.rb
|
|
685
713
|
- libexec/bolt_catalog
|
|
686
714
|
- libexec/custom_facts.rb
|
|
@@ -694,7 +722,6 @@ files:
|
|
|
694
722
|
- modules/canary/lib/puppet/functions/canary/random_split.rb
|
|
695
723
|
- modules/canary/lib/puppet/functions/canary/skip.rb
|
|
696
724
|
- modules/canary/plans/init.pp
|
|
697
|
-
- modules/puppet_connect/plans/test_input_data.pp
|
|
698
725
|
- modules/puppetdb_fact/plans/init.pp
|
|
699
726
|
- resources/bolt_bash_completion.sh
|
|
700
727
|
homepage: https://github.com/OpenVoxProject/openbolt/
|
|
@@ -715,7 +742,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
715
742
|
- !ruby/object:Gem::Version
|
|
716
743
|
version: '0'
|
|
717
744
|
requirements: []
|
|
718
|
-
rubygems_version: 4.0.
|
|
745
|
+
rubygems_version: 4.0.10
|
|
719
746
|
specification_version: 4
|
|
720
747
|
summary: Execute commands remotely over SSH and WinRM
|
|
721
748
|
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
|