bolt 3.0.0 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bolt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Puppetfile +13 -11
- data/bolt-modules/boltlib/lib/puppet/datatypes/containerresult.rb +24 -0
- data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +20 -2
- data/bolt-modules/boltlib/lib/puppet/functions/run_container.rb +162 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +2 -2
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +44 -5
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +1 -1
- data/bolt-modules/boltlib/types/planresult.pp +1 -0
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +3 -2
- data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +20 -2
- data/bolt-modules/prompt/lib/puppet/functions/prompt/menu.rb +103 -0
- data/lib/bolt/apply_result.rb +1 -1
- data/lib/bolt/bolt_option_parser.rb +6 -3
- data/lib/bolt/cli.rb +96 -16
- data/lib/bolt/config.rb +4 -0
- data/lib/bolt/config/options.rb +21 -3
- data/lib/bolt/config/transport/lxd.rb +23 -0
- data/lib/bolt/config/transport/options.rb +8 -1
- data/lib/bolt/container_result.rb +105 -0
- data/lib/bolt/error.rb +15 -0
- data/lib/bolt/executor.rb +22 -7
- data/lib/bolt/inventory/options.rb +9 -0
- data/lib/bolt/inventory/target.rb +16 -0
- data/lib/bolt/logger.rb +8 -0
- data/lib/bolt/module_installer.rb +2 -2
- data/lib/bolt/module_installer/puppetfile.rb +2 -2
- data/lib/bolt/module_installer/specs/forge_spec.rb +2 -2
- data/lib/bolt/module_installer/specs/git_spec.rb +2 -2
- data/lib/bolt/node/output.rb +14 -4
- data/lib/bolt/outputter/human.rb +106 -23
- data/lib/bolt/outputter/logger.rb +17 -0
- data/lib/bolt/pal.rb +25 -4
- data/lib/bolt/pal/yaml_plan.rb +1 -2
- data/lib/bolt/pal/yaml_plan/evaluator.rb +5 -141
- data/lib/bolt/pal/yaml_plan/step.rb +91 -31
- data/lib/bolt/pal/yaml_plan/step/command.rb +21 -13
- data/lib/bolt/pal/yaml_plan/step/download.rb +15 -16
- data/lib/bolt/pal/yaml_plan/step/eval.rb +11 -11
- data/lib/bolt/pal/yaml_plan/step/message.rb +13 -4
- data/lib/bolt/pal/yaml_plan/step/plan.rb +19 -15
- data/lib/bolt/pal/yaml_plan/step/resources.rb +82 -21
- data/lib/bolt/pal/yaml_plan/step/script.rb +36 -17
- data/lib/bolt/pal/yaml_plan/step/task.rb +19 -16
- data/lib/bolt/pal/yaml_plan/step/upload.rb +16 -17
- data/lib/bolt/pal/yaml_plan/transpiler.rb +3 -3
- data/lib/bolt/plan_creator.rb +1 -1
- data/lib/bolt/project_manager.rb +1 -1
- data/lib/bolt/project_manager/module_migrator.rb +1 -1
- data/lib/bolt/result.rb +11 -15
- data/lib/bolt/shell.rb +16 -0
- data/lib/bolt/shell/bash.rb +61 -31
- data/lib/bolt/shell/bash/tmpdir.rb +2 -2
- data/lib/bolt/shell/powershell.rb +34 -12
- data/lib/bolt/shell/powershell/snippets.rb +30 -3
- data/lib/bolt/task.rb +1 -1
- data/lib/bolt/transport/base.rb +0 -9
- data/lib/bolt/transport/docker.rb +1 -125
- data/lib/bolt/transport/docker/connection.rb +77 -167
- data/lib/bolt/transport/lxd.rb +26 -0
- data/lib/bolt/transport/lxd/connection.rb +99 -0
- data/lib/bolt/transport/orch.rb +13 -5
- data/lib/bolt/transport/ssh/connection.rb +1 -1
- data/lib/bolt/transport/winrm/connection.rb +1 -1
- data/lib/bolt/util.rb +31 -0
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/transport_app.rb +61 -33
- data/lib/bolt_spec/bolt_context.rb +9 -4
- data/lib/bolt_spec/plans.rb +1 -109
- data/lib/bolt_spec/plans/action_stubs.rb +1 -1
- data/lib/bolt_spec/plans/action_stubs/command_stub.rb +8 -1
- data/lib/bolt_spec/plans/action_stubs/script_stub.rb +8 -1
- data/lib/bolt_spec/plans/mock_executor.rb +90 -7
- data/modules/puppet_connect/plans/test_input_data.pp +65 -7
- metadata +9 -2
@@ -177,7 +177,7 @@ module BoltSpec
|
|
177
177
|
if data['msg'] && data['kind'] && (data.keys - %w[msg kind details issue_code]).empty?
|
178
178
|
@data[:default] = clazz.new(data['msg'], data['kind'], data['details'], data['issue_code'])
|
179
179
|
else
|
180
|
-
$stderr.puts "In the future 'error_with()'
|
180
|
+
$stderr.puts "In the future 'error_with()' might require msg and kind, and " \
|
181
181
|
"optionally accept only details and issue_code."
|
182
182
|
@data[:default] = data
|
183
183
|
end
|
@@ -29,7 +29,14 @@ module BoltSpec
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def result_for(target, stdout: '', stderr: '')
|
32
|
-
|
32
|
+
value = {
|
33
|
+
'stdout' => stdout,
|
34
|
+
'stderr' => stderr,
|
35
|
+
'merged_output' => "#{stdout}\n#{stderr}".strip,
|
36
|
+
'exit_code' => 0
|
37
|
+
}
|
38
|
+
|
39
|
+
Bolt::Result.for_command(target, value, 'command', '', [])
|
33
40
|
end
|
34
41
|
|
35
42
|
# Public methods
|
@@ -35,7 +35,14 @@ module BoltSpec
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def result_for(target, stdout: '', stderr: '')
|
38
|
-
|
38
|
+
value = {
|
39
|
+
'stdout' => stdout,
|
40
|
+
'stderr' => stderr,
|
41
|
+
'merged_output' => "#{stdout}\n#{stderr}".strip,
|
42
|
+
'exit_code' => 0
|
43
|
+
}
|
44
|
+
|
45
|
+
Bolt::Result.for_command(target, value, 'script', '', [])
|
39
46
|
end
|
40
47
|
|
41
48
|
# Public methods
|
@@ -17,7 +17,7 @@ module BoltSpec
|
|
17
17
|
|
18
18
|
# Nothing on the executor is 'public'
|
19
19
|
class MockExecutor
|
20
|
-
attr_reader :noop, :error_message, :in_parallel
|
20
|
+
attr_reader :noop, :error_message, :in_parallel, :transports
|
21
21
|
attr_accessor :run_as, :transport_features, :execute_any_plan
|
22
22
|
|
23
23
|
def initialize(modulepath)
|
@@ -91,6 +91,14 @@ module BoltSpec
|
|
91
91
|
result
|
92
92
|
end
|
93
93
|
|
94
|
+
def run_task_with(target_mapping, task, options = {}, _position = [])
|
95
|
+
resultsets = target_mapping.map do |target, arguments|
|
96
|
+
run_task([target], task, arguments, options)
|
97
|
+
end.compact
|
98
|
+
|
99
|
+
Bolt::ResultSet.new(resultsets.map(&:results).flatten)
|
100
|
+
end
|
101
|
+
|
94
102
|
def download_file(targets, source, destination, options = {}, _position = [])
|
95
103
|
result = nil
|
96
104
|
if (doub = @download_doubles[source] || @download_doubles[:default])
|
@@ -210,12 +218,6 @@ module BoltSpec
|
|
210
218
|
yield
|
211
219
|
end
|
212
220
|
|
213
|
-
def report_function_call(_function); end
|
214
|
-
|
215
|
-
def report_bundled_content(_mode, _name); end
|
216
|
-
|
217
|
-
def report_apply(_statements, _resources); end
|
218
|
-
|
219
221
|
def publish_event(event)
|
220
222
|
if event[:type] == :message
|
221
223
|
unless @stub_out_message
|
@@ -253,6 +255,87 @@ module BoltSpec
|
|
253
255
|
end.new(transport_features)
|
254
256
|
end
|
255
257
|
# End apply_prep mocking
|
258
|
+
|
259
|
+
# Evaluates a `parallelize()` block and returns the result. Normally,
|
260
|
+
# Bolt's executor wraps this in a Yarn for each object passed to the
|
261
|
+
# `parallelize()` function, and then executes them in parallel before
|
262
|
+
# returning the result from the block. However, in BoltSpec the block is
|
263
|
+
# executed for each object sequentially, and this function returns the
|
264
|
+
# result itself.
|
265
|
+
#
|
266
|
+
def create_yarn(scope, block, object, _index)
|
267
|
+
# Create the new scope
|
268
|
+
newscope = Puppet::Parser::Scope.new(scope.compiler)
|
269
|
+
local = Puppet::Parser::Scope::LocalScope.new
|
270
|
+
|
271
|
+
# Compress the current scopes into a single vars hash to add to the new scope
|
272
|
+
current_scope = scope.effective_symtable(true)
|
273
|
+
until current_scope.nil?
|
274
|
+
current_scope.instance_variable_get(:@symbols)&.each_pair { |k, v| local[k] = v }
|
275
|
+
current_scope = current_scope.parent
|
276
|
+
end
|
277
|
+
newscope.push_ephemerals([local])
|
278
|
+
|
279
|
+
begin
|
280
|
+
result = catch(:return) do
|
281
|
+
args = { block.parameters[0][1].to_s => object }
|
282
|
+
block.closure.call_by_name_with_scope(newscope, args, true)
|
283
|
+
end
|
284
|
+
|
285
|
+
# If we got a return from the block, get it's value
|
286
|
+
# Otherwise the result is the last line from the block
|
287
|
+
result = result.value if result.is_a?(Puppet::Pops::Evaluator::Return)
|
288
|
+
|
289
|
+
# Validate the result is a PlanResult
|
290
|
+
unless Puppet::Pops::Types::TypeParser.singleton.parse('Boltlib::PlanResult').instance?(result)
|
291
|
+
raise Bolt::InvalidParallelResult.new(result.to_s, *Puppet::Pops::PuppetStack.top_of_stack)
|
292
|
+
end
|
293
|
+
|
294
|
+
result
|
295
|
+
rescue Puppet::PreformattedError => e
|
296
|
+
if e.cause.is_a?(Bolt::Error)
|
297
|
+
e.cause
|
298
|
+
else
|
299
|
+
raise e
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# BoltSpec already evaluated the `parallelize()` block for each object
|
305
|
+
# passed to the function, so these results can be returned as-is.
|
306
|
+
#
|
307
|
+
def round_robin(results)
|
308
|
+
results
|
309
|
+
end
|
310
|
+
|
311
|
+
# Public methods on Bolt::Executor that need to be mocked so there aren't
|
312
|
+
# "undefined method" errors.
|
313
|
+
|
314
|
+
def batch_execute(_targets); end
|
315
|
+
|
316
|
+
def finish_plan(_plan_result); end
|
317
|
+
|
318
|
+
def handle_event(_event); end
|
319
|
+
|
320
|
+
def prompt(_prompt, _options); end
|
321
|
+
|
322
|
+
def report_function_call(_function); end
|
323
|
+
|
324
|
+
def report_bundled_content(_mode, _name); end
|
325
|
+
|
326
|
+
def report_file_source(_plan_function, _source); end
|
327
|
+
|
328
|
+
def report_apply(_statements, _resources); end
|
329
|
+
|
330
|
+
def report_yaml_plan(_plan); end
|
331
|
+
|
332
|
+
def shutdown; end
|
333
|
+
|
334
|
+
def start_plan(_plan_context); end
|
335
|
+
|
336
|
+
def subscribe(_subscriber, _types = nil); end
|
337
|
+
|
338
|
+
def unsubscribe(_subscriber, _types = nil); end
|
256
339
|
end
|
257
340
|
end
|
258
341
|
end
|
@@ -13,15 +13,73 @@
|
|
13
13
|
#
|
14
14
|
plan puppet_connect::test_input_data(TargetSpec $targets = 'all') {
|
15
15
|
$targs = get_targets($targets)
|
16
|
+
$unique_plugins = $targs.group_by |$t| {$t.plugin_hooks['puppet_library']}
|
17
|
+
if ($unique_plugins.keys.length > 1) {
|
18
|
+
out::message('Multiple puppet_library plugin hooks detected')
|
19
|
+
$unique_plugins.each |$plug, $target_list| {
|
20
|
+
$target_message = if ($target_list.length > 10) {
|
21
|
+
"${target_list.length} targets"
|
22
|
+
} else {
|
23
|
+
$target_list.join(', ')
|
24
|
+
}
|
25
|
+
out::message("Plugin hook ${plug} configured for ${target_message}")
|
26
|
+
}
|
27
|
+
fail_plan("The puppet_library plugin config must be the same across all targets")
|
28
|
+
}
|
16
29
|
$targs.each |$target| {
|
17
|
-
|
18
|
-
|
30
|
+
case $target.transport {
|
31
|
+
'ssh': {
|
32
|
+
$private_key_config = dig($target.config, 'ssh', 'private-key')
|
33
|
+
if $private_key_config =~ String {
|
34
|
+
$msg = @("END")
|
35
|
+
The SSH private key of the ${$target} target points to a filepath on disk,
|
36
|
+
which is not allowed in Puppet Connect. Instead, the private key contents must
|
37
|
+
be specified and this should be done via the PuppetConnectData plugin. Below is
|
38
|
+
an example of a Puppet Connect-compatible specification of the private-key. First,
|
39
|
+
we start with the inventory file:
|
40
|
+
...
|
41
|
+
private-key:
|
42
|
+
_plugin: puppet_connect_data
|
43
|
+
key: ssh_private_key
|
44
|
+
...
|
45
|
+
|
46
|
+
Next is the corresponding entry in the input data file:
|
47
|
+
...
|
48
|
+
ssh_private_key:
|
49
|
+
key-data:
|
50
|
+
<private_key_contents>
|
51
|
+
...
|
52
|
+
| END
|
53
|
+
|
54
|
+
out::message($msg)
|
55
|
+
fail_plan("The SSH private key of the ${$target} target points to a filepath on disk")
|
56
|
+
}
|
57
|
+
|
58
|
+
# Disable SSH autoloading to prevent false positive results
|
59
|
+
# (input data is wrong but target is still connectable due
|
60
|
+
# to autoloaded config)
|
61
|
+
set_config($target, ['ssh', 'load-config'], false)
|
62
|
+
# Maintain configuration parity with Puppet Connect to improve
|
63
|
+
# the reliability of our test
|
64
|
+
set_config($target, ['ssh', 'host-key-check'], false)
|
65
|
+
}
|
66
|
+
'winrm': {
|
67
|
+
# Maintain configuration parity with Puppet Connect
|
68
|
+
set_config($target, ['winrm', 'ssl'], false)
|
69
|
+
set_config($target, ['winrm', 'ssl-verify'], false)
|
70
|
+
}
|
71
|
+
default: {
|
72
|
+
fail_plan("Inventory contains target ${target} with unsupported transport, must be ssh or winrm")
|
73
|
+
}
|
19
74
|
}
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
75
|
+
|
76
|
+
# Bolt defaults to using the "module" based form of the puppet_agent plugin. Connect defaults
|
77
|
+
# to using the "task" based form as *only* the task based form in supported in Connect. This check
|
78
|
+
# ensures that if the default is not being used, only task based plugins are allowed.
|
79
|
+
$plugin = $target.plugin_hooks["puppet_library"]
|
80
|
+
$user_configured_plugin = $plugin != { "plugin"=> "puppet_agent", "stop_service"=> true }
|
81
|
+
if ($user_configured_plugin and $plugin["plugin"] != "task"){
|
82
|
+
fail_plan("Only task plugins are acceptable for puppet_library hook")
|
25
83
|
}
|
26
84
|
}
|
27
85
|
# The SSH/WinRM transports will report an 'unknown host' error for targets where
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bolt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppet
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-03-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -398,6 +398,7 @@ extra_rdoc_files: []
|
|
398
398
|
files:
|
399
399
|
- Puppetfile
|
400
400
|
- bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb
|
401
|
+
- bolt-modules/boltlib/lib/puppet/datatypes/containerresult.rb
|
401
402
|
- bolt-modules/boltlib/lib/puppet/datatypes/resourceinstance.rb
|
402
403
|
- bolt-modules/boltlib/lib/puppet/datatypes/result.rb
|
403
404
|
- bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb
|
@@ -419,6 +420,7 @@ files:
|
|
419
420
|
- bolt-modules/boltlib/lib/puppet/functions/resolve_references.rb
|
420
421
|
- bolt-modules/boltlib/lib/puppet/functions/resource.rb
|
421
422
|
- bolt-modules/boltlib/lib/puppet/functions/run_command.rb
|
423
|
+
- bolt-modules/boltlib/lib/puppet/functions/run_container.rb
|
422
424
|
- bolt-modules/boltlib/lib/puppet/functions/run_plan.rb
|
423
425
|
- bolt-modules/boltlib/lib/puppet/functions/run_script.rb
|
424
426
|
- bolt-modules/boltlib/lib/puppet/functions/run_task.rb
|
@@ -444,6 +446,7 @@ files:
|
|
444
446
|
- bolt-modules/file/lib/puppet/functions/file/write.rb
|
445
447
|
- bolt-modules/out/lib/puppet/functions/out/message.rb
|
446
448
|
- bolt-modules/prompt/lib/puppet/functions/prompt.rb
|
449
|
+
- bolt-modules/prompt/lib/puppet/functions/prompt/menu.rb
|
447
450
|
- bolt-modules/system/lib/puppet/functions/system/env.rb
|
448
451
|
- exe/bolt
|
449
452
|
- guides/inventory.txt
|
@@ -467,11 +470,13 @@ files:
|
|
467
470
|
- lib/bolt/config/transport/base.rb
|
468
471
|
- lib/bolt/config/transport/docker.rb
|
469
472
|
- lib/bolt/config/transport/local.rb
|
473
|
+
- lib/bolt/config/transport/lxd.rb
|
470
474
|
- lib/bolt/config/transport/options.rb
|
471
475
|
- lib/bolt/config/transport/orch.rb
|
472
476
|
- lib/bolt/config/transport/remote.rb
|
473
477
|
- lib/bolt/config/transport/ssh.rb
|
474
478
|
- lib/bolt/config/transport/winrm.rb
|
479
|
+
- lib/bolt/container_result.rb
|
475
480
|
- lib/bolt/error.rb
|
476
481
|
- lib/bolt/executor.rb
|
477
482
|
- lib/bolt/inventory.rb
|
@@ -555,6 +560,8 @@ files:
|
|
555
560
|
- lib/bolt/transport/docker/connection.rb
|
556
561
|
- lib/bolt/transport/local.rb
|
557
562
|
- lib/bolt/transport/local/connection.rb
|
563
|
+
- lib/bolt/transport/lxd.rb
|
564
|
+
- lib/bolt/transport/lxd/connection.rb
|
558
565
|
- lib/bolt/transport/orch.rb
|
559
566
|
- lib/bolt/transport/orch/connection.rb
|
560
567
|
- lib/bolt/transport/remote.rb
|