bolt 0.17.2 → 0.18.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.

Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +2 -0
  3. data/bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb +2 -0
  4. data/bolt-modules/boltlib/lib/puppet/datatypes/target.rb +2 -0
  5. data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +30 -0
  6. data/bolt-modules/boltlib/lib/puppet/functions/facts.rb +30 -0
  7. data/bolt-modules/boltlib/lib/puppet/functions/fail_plan.rb +4 -2
  8. data/bolt-modules/boltlib/lib/puppet/functions/file_upload.rb +2 -0
  9. data/bolt-modules/boltlib/lib/puppet/functions/get_targets.rb +2 -0
  10. data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +2 -0
  11. data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +3 -2
  12. data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +2 -1
  13. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +2 -0
  14. data/bolt-modules/boltlib/lib/puppet/functions/set_var.rb +8 -0
  15. data/bolt-modules/boltlib/lib/puppet/functions/vars.rb +9 -1
  16. data/exe/bolt +1 -0
  17. data/exe/bolt-inventory-pdb +1 -0
  18. data/lib/bolt.rb +2 -0
  19. data/lib/bolt/cli.rb +40 -34
  20. data/lib/bolt/config.rb +9 -2
  21. data/lib/bolt/error.rb +2 -0
  22. data/lib/bolt/executor.rb +2 -0
  23. data/lib/bolt/inventory.rb +36 -28
  24. data/lib/bolt/inventory/group.rb +14 -10
  25. data/lib/bolt/logger.rb +2 -0
  26. data/lib/bolt/node/errors.rb +2 -0
  27. data/lib/bolt/node/output.rb +2 -0
  28. data/lib/bolt/notifier.rb +2 -0
  29. data/lib/bolt/outputter.rb +2 -0
  30. data/lib/bolt/outputter/human.rb +28 -34
  31. data/lib/bolt/outputter/json.rb +7 -5
  32. data/lib/bolt/pal.rb +66 -30
  33. data/lib/bolt/puppetdb.rb +2 -0
  34. data/lib/bolt/puppetdb/client.rb +5 -3
  35. data/lib/bolt/puppetdb/config.rb +2 -0
  36. data/lib/bolt/result.rb +2 -0
  37. data/lib/bolt/result_set.rb +2 -0
  38. data/lib/bolt/target.rb +2 -0
  39. data/lib/bolt/transport/base.rb +4 -2
  40. data/lib/bolt/transport/local.rb +2 -0
  41. data/lib/bolt/transport/local/shell.rb +2 -0
  42. data/lib/bolt/transport/orch.rb +3 -1
  43. data/lib/bolt/transport/ssh.rb +3 -1
  44. data/lib/bolt/transport/ssh/connection.rb +3 -1
  45. data/lib/bolt/transport/winrm.rb +9 -2
  46. data/lib/bolt/transport/winrm/connection.rb +11 -3
  47. data/lib/bolt/util.rb +9 -7
  48. data/lib/bolt/version.rb +3 -1
  49. data/lib/bolt_ext/puppetdb_inventory.rb +3 -2
  50. data/modules/aggregate/lib/puppet/functions/aggregate/count.rb +2 -0
  51. data/modules/aggregate/lib/puppet/functions/aggregate/nodes.rb +2 -0
  52. data/modules/canary/lib/puppet/functions/canary/merge.rb +2 -0
  53. data/modules/canary/lib/puppet/functions/canary/random_split.rb +2 -0
  54. data/modules/canary/lib/puppet/functions/canary/skip.rb +2 -0
  55. metadata +37 -35
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c9ea02d63dd2b45747f5eda9d07187f39842332f
4
- data.tar.gz: 3768ff96fafe4b6cb9d05fdad94c17ce3809e2be
3
+ metadata.gz: 9b5850dae92768743f9faa35a5972efc6c3b83da
4
+ data.tar.gz: 80c524fd01e4b66c1d969e1c98fe29bbf836369d
5
5
  SHA512:
6
- metadata.gz: 26863769817e4f0b644041dc32b2eda8c961d75ab34bc805db0ff497ff8c624672c5d3d6051cdd6add2fa921e862310d9236879cacf61aa35144fd795f159c03
7
- data.tar.gz: 6b767b8e2dab9368e0bd5bc7feee4b397f18a39005eca646d2bad44e3a400bdca5009f1e6d1e51d1688ab8265e02996a2b127840e918cdd405c618a6fe00a52c
6
+ metadata.gz: 50ee00db02f62fafeb43d1553186442728db8dfc8d69ec646fd284415b6595c78445a95435d90fd894071ce5c7c39ec3d0f06dbb52337be648e237ebebb97677
7
+ data.tar.gz: bc78146c6b867e02c70fb4ea612c498a6ac1260917c490a31c0435a4978a1777fc763f34013e31d65d88dedb537a647ed2656a6a92a7d3ede3af13191b48f256
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Puppet::DataTypes.create_type('Result') do
2
4
  interface <<-PUPPET
3
5
  attributes => {
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Puppet::DataTypes.create_type('ResultSet') do
2
4
  interface <<-PUPPET
3
5
  attributes => {
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Puppet::DataTypes.create_type('Target') do
2
4
  interface <<-PUPPET
3
5
  attributes => {
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/error'
4
+
5
+ # Deep merges a hash of facts with the existing facts has on a target.
6
+
7
+ Puppet::Functions.create_function(:add_facts) do
8
+ dispatch :add_facts do
9
+ param 'Target', :target
10
+ param 'Hash', :facts
11
+ end
12
+
13
+ def add_facts(target, facts)
14
+ unless Puppet[:tasks]
15
+ raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
16
+ Puppet::Pops::Issues::TASK_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, operation: 'add_facts'
17
+ )
18
+ end
19
+
20
+ inventory = Puppet.lookup(:bolt_inventory) { nil }
21
+
22
+ unless inventory
23
+ raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
24
+ Puppet::Pops::Issues::TASK_MISSING_BOLT, action: _('add facts')
25
+ )
26
+ end
27
+
28
+ inventory.add_facts(target, facts)
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/error'
4
+
5
+ # Returns the facts hash for a target.
6
+ # This functions takes one parameter, the target to get facts for
7
+ Puppet::Functions.create_function(:facts) do
8
+ dispatch :facts do
9
+ param 'Target', :target
10
+ return_type 'Hash[String, Data]'
11
+ end
12
+
13
+ def facts(target)
14
+ unless Puppet[:tasks]
15
+ raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
16
+ Puppet::Pops::Issues::TASK_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, operation: 'facts'
17
+ )
18
+ end
19
+
20
+ inventory = Puppet.lookup(:bolt_inventory) { nil }
21
+
22
+ unless inventory
23
+ raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
24
+ Puppet::Pops::Issues::TASK_MISSING_BOLT, action: _('get facts for a target')
25
+ )
26
+ end
27
+
28
+ inventory.facts(target)
29
+ end
30
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bolt/error'
2
4
 
3
5
  # Raises a Bolt::PlanFailure exception to signal to callers that the plan failed
@@ -20,7 +22,7 @@ Puppet::Functions.create_function(:fail_plan) do
20
22
  raise Bolt::PlanFailure.new(msg, kind || 'bolt/plan-failure', details, issue_code)
21
23
  end
22
24
 
23
- def from_error(e)
24
- from_args(e.message, e.kind, e.details, e.issue_code)
25
+ def from_error(err)
26
+ from_args(err.message, err.kind, err.details, err.issue_code)
25
27
  end
26
28
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bolt/error'
2
4
 
3
5
  # Uploads the given file or directory to the given set of targets and returns the result from each upload.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bolt/error'
2
4
 
3
5
  # Parses common ways of referring to targets and returns an array of Targets.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bolt/error'
2
4
 
3
5
  # Runs a command on the given set of targets and returns the result from each command execution.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bolt/error'
2
4
 
3
5
  # Runs the `plan` referenced by its name passing giving arguments to it given as a hash of name to value mappings.
@@ -47,8 +49,7 @@ Puppet::Functions.create_function(:run_plan, Puppet::Functions::InternalFunction
47
49
  begin
48
50
  result = func.class.dispatcher.dispatchers[0].call_by_name_with_scope(scope, params, true)
49
51
  rescue Puppet::PreformattedError => err
50
- if named_args['_catch_errors'] &&
51
- err.respond_to?(:cause) && err.cause && err.cause.is_a?(Bolt::Error)
52
+ if named_args['_catch_errors'] && err.cause.is_a?(Bolt::Error)
52
53
  result = err.cause.to_puppet_error
53
54
  else
54
55
  raise err
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Uploads the given script to the given set of targets and returns the result of having each target execute the script.
2
4
  #
3
5
  # * This function does nothing if the list of targets is empty.
@@ -45,7 +47,6 @@ Puppet::Functions.create_function(:run_script, Puppet::Functions::InternalFuncti
45
47
  # Ensure that given targets are all Target instances)
46
48
  targets = inventory.get_targets(targets)
47
49
 
48
- #
49
50
  r = if targets.empty?
50
51
  Bolt::ResultSet.new([])
51
52
  else
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bolt/error'
2
4
 
3
5
  # Runs a given instance of a `Task` on the given set of targets and returns the result from each.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bolt/error'
2
4
 
3
5
  # Sets a variable { key => value } for a target.
@@ -24,6 +26,12 @@ Puppet::Functions.create_function(:set_var) do
24
26
 
25
27
  inventory = Puppet.lookup(:bolt_inventory) { nil }
26
28
 
29
+ unless inventory
30
+ raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
31
+ Puppet::Pops::Issues::TASK_MISSING_BOLT, action: _('set a var on a target')
32
+ )
33
+ end
34
+
27
35
  inventory.set_var(target, key, value)
28
36
  end
29
37
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bolt/error'
2
4
 
3
5
  # Returns a hash of the 'vars' (variables) assigned to a target through the
@@ -16,12 +18,18 @@ Puppet::Functions.create_function(:vars) do
16
18
  def vars(target)
17
19
  unless Puppet[:tasks]
18
20
  raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
19
- Puppet::Pops::Issues::TASK_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, operation: 'set_var'
21
+ Puppet::Pops::Issues::TASK_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, operation: 'vars'
20
22
  )
21
23
  end
22
24
 
23
25
  inventory = Puppet.lookup(:bolt_inventory) { nil }
24
26
 
27
+ unless inventory
28
+ raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
29
+ Puppet::Pops::Issues::TASK_MISSING_BOLT, action: _('get vars')
30
+ )
31
+ end
32
+
25
33
  inventory.vars(target)
26
34
  end
27
35
  end
data/exe/bolt CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bolt'
4
5
  require 'bolt/cli'
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bolt_ext/puppetdb_inventory'
4
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bolt
2
4
  require 'bolt/executor'
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
  require 'benchmark'
3
5
  require 'json'
@@ -26,7 +28,7 @@ module Bolt
26
28
 
27
29
  class CLI
28
30
  class BoltOptionParser < OptionParser
29
- BANNER = <<-HELP.freeze
31
+ BANNER = <<-HELP
30
32
  Usage: bolt <subcommand> <action> [options]
31
33
 
32
34
  Available subcommands:
@@ -43,7 +45,7 @@ Available subcommands:
43
45
  where [options] are:
44
46
  HELP
45
47
 
46
- TASK_HELP = <<-HELP.freeze
48
+ TASK_HELP = <<-HELP
47
49
  Usage: bolt task <action> <task> [options] [parameters]
48
50
 
49
51
  Available actions are:
@@ -56,7 +58,7 @@ Parameters are of the form <parameter>=<value>.
56
58
  Available options are:
57
59
  HELP
58
60
 
59
- COMMAND_HELP = <<-HELP.freeze
61
+ COMMAND_HELP = <<-HELP
60
62
  Usage: bolt command <action> <command> [options]
61
63
 
62
64
  Available actions are:
@@ -65,7 +67,7 @@ Available actions are:
65
67
  Available options are:
66
68
  HELP
67
69
 
68
- SCRIPT_HELP = <<-HELP.freeze
70
+ SCRIPT_HELP = <<-HELP
69
71
  Usage: bolt script <action> <script> [[arg1] ... [argN]] [options]
70
72
 
71
73
  Available actions are:
@@ -74,7 +76,7 @@ Available actions are:
74
76
  Available options are:
75
77
  HELP
76
78
 
77
- PLAN_HELP = <<-HELP.freeze
79
+ PLAN_HELP = <<-HELP
78
80
  Usage: bolt plan <action> <plan> [options] [parameters]
79
81
 
80
82
  Available actions are:
@@ -87,7 +89,7 @@ Parameters are of the form <parameter>=<value>.
87
89
  Available options are:
88
90
  HELP
89
91
 
90
- FILE_HELP = <<-HELP.freeze
92
+ FILE_HELP = <<-HELP
91
93
  Usage: bolt file <action> [options]
92
94
 
93
95
  Available actions are:
@@ -168,7 +170,7 @@ Available options are:
168
170
  end
169
171
  define('--modulepath MODULES',
170
172
  'List of directories containing modules, ' \
171
- 'separated by ' << File::PATH_SEPARATOR) do |modulepath|
173
+ "separated by #{File::PATH_SEPARATOR}") do |modulepath|
172
174
  @options[:modulepath] = modulepath.split(File::PATH_SEPARATOR)
173
175
  end
174
176
  define('--params PARAMETERS',
@@ -188,8 +190,12 @@ Available options are:
188
190
  'Use SSL with WinRM') do |ssl|
189
191
  @options[:ssl] = ssl
190
192
  end
193
+ define('--[no-]ssl-verify',
194
+ 'Verify remote host SSL certificate with WinRM') do |ssl_verify|
195
+ @options[:'ssl-verify'] = ssl_verify
196
+ end
191
197
  define('--transport TRANSPORT', TRANSPORTS.keys.map(&:to_s),
192
- 'Specify a default transport: ' << TRANSPORTS.keys.join(', ')) do |t|
198
+ "Specify a default transport: #{TRANSPORTS.keys.join(', ')}") do |t|
193
199
  @options[:transport] = t
194
200
  end
195
201
  define('--run-as USER',
@@ -317,34 +323,28 @@ Available options are:
317
323
  end
318
324
  private :inventory
319
325
 
326
+ def help?(parser, remaining)
327
+ # Set the mode
328
+ options[:mode] = remaining.shift
329
+
330
+ if options[:mode] == 'help'
331
+ options[:help] = true
332
+ options[:mode] = remaining.shift
333
+ end
334
+
335
+ # Update the parser for the new mode
336
+ parser.update
337
+
338
+ options[:help]
339
+ end
340
+ private :help?
341
+
320
342
  def parse
321
343
  parser = BoltOptionParser.new(options)
322
344
 
323
- if @argv.empty? ||
324
- begin
325
- # RuboCop apparently doesn't realize this is a block and issues
326
- # the Lint/AssignmentInCondition warning for every assignment in
327
- # it, so we disable that warning here.
328
- # rubocop:disable Lint/AssignmentInCondition
329
- remaining = handle_parser_errors do
330
- parser.permute(@argv)
331
- end
332
-
333
- # Set the mode
334
- options[:mode] = remaining.shift
335
-
336
- if options[:mode] == 'help'
337
- options[:help] = true
338
- options[:mode] = remaining.shift
339
- end
340
-
341
- # Update the parser for the new mode
342
- parser.update
343
-
344
- options[:help]
345
- # rubocop:enable Lint/AssignmentInCondition
346
- end
347
- then # rubocop:disable Style/MultilineIfThen
345
+ # This part aims to handle both `bolt <mode> --help` and `bolt help <mode>`.
346
+ remaining = handle_parser_errors { parser.permute(@argv) } unless @argv.empty?
347
+ if @argv.empty? || help?(parser, remaining)
348
348
  puts parser.help
349
349
  raise Bolt::CLIExit
350
350
  end
@@ -366,7 +366,9 @@ Available options are:
366
366
  "Parameters must be specified through either the --params " \
367
367
  "option or param=value pairs, not both"
368
368
  end
369
+ options[:params_parsed] = true
369
370
  else
371
+ options[:params_parsed] = false
370
372
  options[:task_options] = Hash[task_options.map { |a| a.split('=', 2) }]
371
373
  end
372
374
 
@@ -467,7 +469,7 @@ Available options are:
467
469
 
468
470
  handler = Signal.trap :INT do |signo|
469
471
  @logger.info(
470
- "Exiting after receiving SIG#{Signal.signame(signo)} signal." << (message ? ' ' << message : '')
472
+ "Exiting after receiving SIG#{Signal.signame(signo)} signal.#{message ? ' ' + message : ''}"
471
473
  )
472
474
  exit!
473
475
  end
@@ -499,6 +501,10 @@ Available options are:
499
501
 
500
502
  message = 'There may be processes left executing on some nodes.'
501
503
 
504
+ if options[:task_options] && !options[:params_parsed] && pal
505
+ options[:task_options] = pal.parse_params(options[:mode], options[:object], options[:task_options])
506
+ end
507
+
502
508
  if options[:mode] == 'plan'
503
509
  unless options[:nodes].empty?
504
510
  if options[:task_options]['nodes']
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
  require 'logging'
3
5
  require 'bolt/cli'
@@ -48,7 +50,8 @@ module Bolt
48
50
  'host-key-check' => true
49
51
  },
50
52
  winrm: {
51
- 'ssl' => true
53
+ 'ssl' => true,
54
+ 'ssl-verify' => true
52
55
  },
53
56
  pcp: {
54
57
  'task-environment' => 'production',
@@ -96,7 +99,7 @@ module Bolt
96
99
  def normalize_log(target)
97
100
  return target if target == 'console'
98
101
  target = target[5..-1] if target.start_with?('file:')
99
- 'file:' << File.expand_path(target)
102
+ 'file:' + File.expand_path(target)
100
103
  end
101
104
 
102
105
  def update_from_file(data)
@@ -164,6 +167,10 @@ module Bolt
164
167
  self[:transports][:winrm]['ssl'] = options[:ssl]
165
168
  end
166
169
 
170
+ if options.key?(:'ssl-verify') # this defaults to true so we need to check the presence of the key
171
+ self[:transports][:winrm]['ssl-verify'] = options[:'ssl-verify']
172
+ end
173
+
167
174
  if options.key?(:'host-key-check') # this defaults to true so we need to check the presence of the key
168
175
  self[:transports][:ssh]['host-key-check'] = options[:'host-key-check']
169
176
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bolt
2
4
  class Error < RuntimeError
3
5
  attr_reader :kind, :details, :issue_code, :error_code
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Used for $ERROR_INFO. This *must* be capitalized!
2
4
  require 'English'
3
5
  require 'json'