bolt 3.1.0 → 3.6.1

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.

Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/Puppetfile +11 -11
  3. data/bolt-modules/boltlib/lib/puppet/datatypes/containerresult.rb +24 -0
  4. data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +1 -1
  5. data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +20 -2
  6. data/bolt-modules/boltlib/lib/puppet/functions/run_container.rb +162 -0
  7. data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +2 -2
  8. data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +44 -5
  9. data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +1 -1
  10. data/bolt-modules/boltlib/types/planresult.pp +1 -0
  11. data/bolt-modules/file/lib/puppet/functions/file/read.rb +3 -2
  12. data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +20 -2
  13. data/bolt-modules/prompt/lib/puppet/functions/prompt/menu.rb +103 -0
  14. data/lib/bolt/analytics.rb +4 -8
  15. data/lib/bolt/apply_result.rb +1 -1
  16. data/lib/bolt/bolt_option_parser.rb +6 -3
  17. data/lib/bolt/cli.rb +121 -36
  18. data/lib/bolt/config.rb +15 -7
  19. data/lib/bolt/config/options.rb +62 -12
  20. data/lib/bolt/config/transport/lxd.rb +23 -0
  21. data/lib/bolt/config/transport/options.rb +8 -1
  22. data/lib/bolt/config/transport/podman.rb +33 -0
  23. data/lib/bolt/container_result.rb +105 -0
  24. data/lib/bolt/error.rb +15 -0
  25. data/lib/bolt/executor.rb +37 -18
  26. data/lib/bolt/inventory/options.rb +9 -0
  27. data/lib/bolt/inventory/target.rb +16 -0
  28. data/lib/bolt/logger.rb +8 -0
  29. data/lib/bolt/module_installer.rb +2 -2
  30. data/lib/bolt/module_installer/puppetfile.rb +2 -2
  31. data/lib/bolt/module_installer/specs/forge_spec.rb +2 -2
  32. data/lib/bolt/module_installer/specs/git_spec.rb +2 -2
  33. data/lib/bolt/node/output.rb +14 -4
  34. data/lib/bolt/outputter/human.rb +259 -90
  35. data/lib/bolt/outputter/json.rb +3 -1
  36. data/lib/bolt/outputter/logger.rb +17 -0
  37. data/lib/bolt/pal.rb +24 -4
  38. data/lib/bolt/pal/yaml_plan.rb +1 -2
  39. data/lib/bolt/pal/yaml_plan/evaluator.rb +5 -141
  40. data/lib/bolt/pal/yaml_plan/step.rb +91 -31
  41. data/lib/bolt/pal/yaml_plan/step/command.rb +21 -13
  42. data/lib/bolt/pal/yaml_plan/step/download.rb +15 -16
  43. data/lib/bolt/pal/yaml_plan/step/eval.rb +11 -11
  44. data/lib/bolt/pal/yaml_plan/step/message.rb +13 -4
  45. data/lib/bolt/pal/yaml_plan/step/plan.rb +19 -15
  46. data/lib/bolt/pal/yaml_plan/step/resources.rb +82 -21
  47. data/lib/bolt/pal/yaml_plan/step/script.rb +36 -17
  48. data/lib/bolt/pal/yaml_plan/step/task.rb +19 -16
  49. data/lib/bolt/pal/yaml_plan/step/upload.rb +16 -17
  50. data/lib/bolt/pal/yaml_plan/transpiler.rb +3 -3
  51. data/lib/bolt/plan_creator.rb +1 -1
  52. data/lib/bolt/plugin.rb +13 -11
  53. data/lib/bolt/project_manager.rb +1 -1
  54. data/lib/bolt/project_manager/module_migrator.rb +1 -1
  55. data/lib/bolt/result.rb +5 -14
  56. data/lib/bolt/shell.rb +16 -0
  57. data/lib/bolt/shell/bash.rb +68 -30
  58. data/lib/bolt/shell/bash/tmpdir.rb +2 -2
  59. data/lib/bolt/shell/powershell.rb +28 -11
  60. data/lib/bolt/task.rb +1 -1
  61. data/lib/bolt/transport/docker.rb +1 -1
  62. data/lib/bolt/transport/docker/connection.rb +21 -32
  63. data/lib/bolt/transport/lxd.rb +26 -0
  64. data/lib/bolt/transport/lxd/connection.rb +99 -0
  65. data/lib/bolt/transport/orch.rb +13 -5
  66. data/lib/bolt/transport/podman.rb +19 -0
  67. data/lib/bolt/transport/podman/connection.rb +98 -0
  68. data/lib/bolt/transport/ssh/connection.rb +1 -1
  69. data/lib/bolt/transport/winrm/connection.rb +1 -1
  70. data/lib/bolt/util.rb +42 -0
  71. data/lib/bolt/version.rb +1 -1
  72. data/lib/bolt_server/transport_app.rb +16 -1
  73. data/lib/bolt_spec/plans/action_stubs.rb +1 -1
  74. data/lib/bolt_spec/plans/action_stubs/command_stub.rb +8 -1
  75. data/lib/bolt_spec/plans/action_stubs/script_stub.rb +8 -1
  76. data/lib/bolt_spec/plans/mock_executor.rb +91 -7
  77. data/modules/puppet_connect/plans/test_input_data.pp +22 -0
  78. metadata +12 -2
data/lib/bolt/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
- VERSION = '3.1.0'
4
+ VERSION = '3.6.1'
5
5
  end
@@ -690,11 +690,26 @@ module BoltServer
690
690
  Bolt::Util.validate_file('inventory file', context[:config].project.inventory_file)
691
691
 
692
692
  begin
693
+ # Set the default puppet_library plugin hook if it has not already been
694
+ # set
695
+ context[:config].data['plugin-hooks']['puppet_library'] ||= {
696
+ 'plugin' => 'task',
697
+ 'task' => 'puppet_agent::install',
698
+ 'parameters' => {
699
+ 'stop_service' => true
700
+ }
701
+ }
702
+
693
703
  connect_plugin = BoltServer::Plugin::PuppetConnectData.new(body['puppet_connect_data'])
694
704
  plugins = Bolt::Plugin.setup(context[:config], context[:pal], load_plugins: false)
695
705
  plugins.add_plugin(connect_plugin)
706
+ %w[aws_inventory azure_inventory gcloud_inventory].each do |plugin_name|
707
+ plugins.add_module_plugin(plugin_name) if plugins.known_plugin?(plugin_name)
708
+ end
696
709
  inventory = Bolt::Inventory.from_config(context[:config], plugins)
697
- target_list = inventory.get_targets('all').map { |targ| targ.to_h.merge({ 'transport' => targ.transport }) }
710
+ target_list = inventory.get_targets('all').map do |targ|
711
+ targ.to_h.merge({ 'transport' => targ.transport, 'plugin_hooks' => targ.plugin_hooks })
712
+ end
698
713
  rescue Bolt::Plugin::PluginError::LoadingDisabled => e
699
714
  msg = "Cannot load plugin #{e.details['plugin_name']}: plugin not supported"
700
715
  raise BoltServer::Plugin::PluginNotSupported.new(msg, e.details['plugin_name'])
@@ -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()' may require msg and kind, and " \
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
- Bolt::Result.for_command(target, stdout, stderr, 0, 'command', '', [])
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
- Bolt::Result.for_command(target, stdout, stderr, 0, 'script', '', [])
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,13 +17,14 @@ 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, :future
21
21
  attr_accessor :run_as, :transport_features, :execute_any_plan
22
22
 
23
23
  def initialize(modulepath)
24
24
  @noop = false
25
25
  @run_as = nil
26
26
  @in_parallel = false
27
+ @future = {}
27
28
  @error_message = nil
28
29
  @allow_apply = false
29
30
  @modulepath = [modulepath].flatten.map { |path| File.absolute_path(path) }
@@ -91,6 +92,14 @@ module BoltSpec
91
92
  result
92
93
  end
93
94
 
95
+ def run_task_with(target_mapping, task, options = {}, _position = [])
96
+ resultsets = target_mapping.map do |target, arguments|
97
+ run_task([target], task, arguments, options)
98
+ end.compact
99
+
100
+ Bolt::ResultSet.new(resultsets.map(&:results).flatten)
101
+ end
102
+
94
103
  def download_file(targets, source, destination, options = {}, _position = [])
95
104
  result = nil
96
105
  if (doub = @download_doubles[source] || @download_doubles[:default])
@@ -210,12 +219,6 @@ module BoltSpec
210
219
  yield
211
220
  end
212
221
 
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
222
  def publish_event(event)
220
223
  if event[:type] == :message
221
224
  unless @stub_out_message
@@ -253,6 +256,87 @@ module BoltSpec
253
256
  end.new(transport_features)
254
257
  end
255
258
  # End apply_prep mocking
259
+
260
+ # Evaluates a `parallelize()` block and returns the result. Normally,
261
+ # Bolt's executor wraps this in a Yarn for each object passed to the
262
+ # `parallelize()` function, and then executes them in parallel before
263
+ # returning the result from the block. However, in BoltSpec the block is
264
+ # executed for each object sequentially, and this function returns the
265
+ # result itself.
266
+ #
267
+ def create_yarn(scope, block, object, _index)
268
+ # Create the new scope
269
+ newscope = Puppet::Parser::Scope.new(scope.compiler)
270
+ local = Puppet::Parser::Scope::LocalScope.new
271
+
272
+ # Compress the current scopes into a single vars hash to add to the new scope
273
+ current_scope = scope.effective_symtable(true)
274
+ until current_scope.nil?
275
+ current_scope.instance_variable_get(:@symbols)&.each_pair { |k, v| local[k] = v }
276
+ current_scope = current_scope.parent
277
+ end
278
+ newscope.push_ephemerals([local])
279
+
280
+ begin
281
+ result = catch(:return) do
282
+ args = { block.parameters[0][1].to_s => object }
283
+ block.closure.call_by_name_with_scope(newscope, args, true)
284
+ end
285
+
286
+ # If we got a return from the block, get it's value
287
+ # Otherwise the result is the last line from the block
288
+ result = result.value if result.is_a?(Puppet::Pops::Evaluator::Return)
289
+
290
+ # Validate the result is a PlanResult
291
+ unless Puppet::Pops::Types::TypeParser.singleton.parse('Boltlib::PlanResult').instance?(result)
292
+ raise Bolt::InvalidParallelResult.new(result.to_s, *Puppet::Pops::PuppetStack.top_of_stack)
293
+ end
294
+
295
+ result
296
+ rescue Puppet::PreformattedError => e
297
+ if e.cause.is_a?(Bolt::Error)
298
+ e.cause
299
+ else
300
+ raise e
301
+ end
302
+ end
303
+ end
304
+
305
+ # BoltSpec already evaluated the `parallelize()` block for each object
306
+ # passed to the function, so these results can be returned as-is.
307
+ #
308
+ def round_robin(results)
309
+ results
310
+ end
311
+
312
+ # Public methods on Bolt::Executor that need to be mocked so there aren't
313
+ # "undefined method" errors.
314
+
315
+ def batch_execute(_targets); end
316
+
317
+ def finish_plan(_plan_result); end
318
+
319
+ def handle_event(_event); end
320
+
321
+ def prompt(_prompt, _options); end
322
+
323
+ def report_function_call(_function); end
324
+
325
+ def report_bundled_content(_mode, _name); end
326
+
327
+ def report_file_source(_plan_function, _source); end
328
+
329
+ def report_apply(_statements, _resources); end
330
+
331
+ def report_yaml_plan(_plan); end
332
+
333
+ def shutdown; end
334
+
335
+ def start_plan(_plan_context); end
336
+
337
+ def subscribe(_subscriber, _types = nil); end
338
+
339
+ def unsubscribe(_subscriber, _types = nil); end
256
340
  end
257
341
  end
258
342
  end
@@ -13,6 +13,19 @@
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
30
  case $target.transport {
18
31
  'ssh': {
@@ -59,6 +72,15 @@ plan puppet_connect::test_input_data(TargetSpec $targets = 'all') {
59
72
  fail_plan("Inventory contains target ${target} with unsupported transport, must be ssh or winrm")
60
73
  }
61
74
  }
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")
83
+ }
62
84
  }
63
85
  # The SSH/WinRM transports will report an 'unknown host' error for targets where
64
86
  # 'host' is unknown so run_command's implementation will take care of raising that
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.1.0
4
+ version: 3.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-01 00:00:00.000000000 Z
11
+ date: 2021-04-07 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,14 @@ 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
476
+ - lib/bolt/config/transport/podman.rb
472
477
  - lib/bolt/config/transport/remote.rb
473
478
  - lib/bolt/config/transport/ssh.rb
474
479
  - lib/bolt/config/transport/winrm.rb
480
+ - lib/bolt/container_result.rb
475
481
  - lib/bolt/error.rb
476
482
  - lib/bolt/executor.rb
477
483
  - lib/bolt/inventory.rb
@@ -555,8 +561,12 @@ files:
555
561
  - lib/bolt/transport/docker/connection.rb
556
562
  - lib/bolt/transport/local.rb
557
563
  - lib/bolt/transport/local/connection.rb
564
+ - lib/bolt/transport/lxd.rb
565
+ - lib/bolt/transport/lxd/connection.rb
558
566
  - lib/bolt/transport/orch.rb
559
567
  - lib/bolt/transport/orch/connection.rb
568
+ - lib/bolt/transport/podman.rb
569
+ - lib/bolt/transport/podman/connection.rb
560
570
  - lib/bolt/transport/remote.rb
561
571
  - lib/bolt/transport/simple.rb
562
572
  - lib/bolt/transport/ssh.rb