bolt 1.33.0 → 1.34.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8529a13b894e496846dd0720d8980e98b4fa6146216089e7792e30ece43e7e17
4
- data.tar.gz: 319d8cfe5375164d4c94868131a8b5a048d3b8b7b95e45e892e79a470ec4b8d9
3
+ metadata.gz: 37db36042df92f069108154b4a08d21095a1c84f2403b454a9a2ebf74c73fef2
4
+ data.tar.gz: ede33892ae497dd185eba5c45d4f2ca7fafb0c5c607aa6c8d50f1fb9b70d267a
5
5
  SHA512:
6
- metadata.gz: 12b4179334e1849115a5648148193c7aab3da768061ce17b4694c35fa836ccb7184258dca2a3376e0a7bca8c9edbe1439d49f5a1f3e3a30929bd67a7ea5e0930
7
- data.tar.gz: b57dc487c0ae46c76206a51f9ed27a1791595e8eab63aa9701f1dcc0785e2b52dc051900109b7f3a74d4a7d9ba1b507b879f5fca4a6b9611737e0e092588dc88
6
+ metadata.gz: a5e2af615b54b7f116c47b3b78c16776882e086f8a41cf3520336ff6e3cd0f670a3ff9e36083d2cecdc60ab9d2df14be424e57cac3a275113e1f4dddb73b2c54
7
+ data.tar.gz: 90cc1192bba5fc7e8b7b9314c05b4dc37c867fd55f2d69e09a33d8f4c9330207da8f8a646c279f956a72def157ff875991605778923c93df009351b6b9afd03b
@@ -10,6 +10,7 @@ Puppet::DataTypes.create_type('Result') do
10
10
  error => Callable[[], Optional[Error]],
11
11
  message => Callable[[], Optional[String]],
12
12
  action => Callable[[], String],
13
+ status => Callable[[], String],
13
14
  to_data => Callable[[], Hash],
14
15
  ok => Callable[[], Boolean],
15
16
  '[]' => Callable[[String[1]], Data]
@@ -8,13 +8,13 @@ require 'bolt/error'
8
8
  Puppet::Functions.create_function(:add_facts) do
9
9
  # @param target A target.
10
10
  # @param facts A hash of fact names to values that may include structured facts.
11
- # @return The target's new facts.
11
+ # @return The target's new facts or a `Target` object if the `future` flag is set to true
12
12
  # @example Adding facts to a target
13
13
  # add_facts($target, { 'os' => { 'family' => 'windows', 'name' => 'windows' } })
14
14
  dispatch :add_facts do
15
15
  param 'Target', :target
16
16
  param 'Hash', :facts
17
- return_type 'Hash[String, Data]'
17
+ return_type 'Variant[Target, Hash[String, Data]]'
18
18
  end
19
19
 
20
20
  def add_facts(target, facts)
@@ -100,8 +100,9 @@ Puppet::Functions.create_function(:apply_prep) do
100
100
 
101
101
  hooks = need_install_targets.map do |t|
102
102
  begin
103
- opts = t.plugin_hooks&.fetch('puppet_library')
104
- hook = inventory.plugins.get_hook(opts['plugin'], :puppet_library)
103
+ opts = t.plugin_hooks&.fetch('puppet_library').dup
104
+ plugin_name = opts.delete('plugin')
105
+ hook = inventory.plugins.get_hook(plugin_name, :puppet_library)
105
106
  { 'target' => t,
106
107
  'hook_proc' => hook.call(opts, t, self) }
107
108
  rescue StandardError => e
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'bolt/error'
4
4
 
5
- # Runs the `plan` referenced by its name. A plan is autoloaded from `<moduleroot>/plans`.
5
+ # Runs the `plan` referenced by its name. A plan is autoloaded from `$MODULEROOT/plans`.
6
6
  #
7
7
  # **NOTE:** Not available in apply block
8
8
  Puppet::Functions.create_function(:run_plan, Puppet::Functions::InternalFunction) do
@@ -7,7 +7,7 @@
7
7
  Puppet::Functions.create_function(:run_script, Puppet::Functions::InternalFunction) do
8
8
  # Run a script.
9
9
  # @param script Path to a script to run on target. May be an absolute path or a modulename/filename selector for a
10
- # file in <moduleroot>/files.
10
+ # file in $MODULEROOT/files.
11
11
  # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
12
12
  # @param options Specify an array of arguments to the 'arguments' key to be passed to the script.
13
13
  # Additional options: '_catch_errors', '_run_as'.
@@ -26,7 +26,7 @@ Puppet::Functions.create_function(:run_script, Puppet::Functions::InternalFuncti
26
26
 
27
27
  # Run a script, logging the provided description.
28
28
  # @param script Path to a script to run on target. May be an absolute path or a modulename/filename selector for a
29
- # file in <moduleroot>/files.
29
+ # file in $MODULEROOT/files.
30
30
  # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
31
31
  # @param description A description to be output when calling this function.
32
32
  # @param options Specify an array of arguments to the 'arguments' key to be passed to the script.
@@ -12,7 +12,7 @@ Puppet::Functions.create_function(:run_task) do
12
12
  # Run a task.
13
13
  # @param task_name The task to run.
14
14
  # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
15
- # @param args Arguments to the plan. Can also include additional options: '_catch_errors', '_run_as'.
15
+ # @param args Arguments to the plan. Can also include additional options: '_catch_errors', '_run_as', '_noop'.
16
16
  # @return A list of results, one entry per target.
17
17
  # @example Run a task as root
18
18
  # run_task('facts', $targets, '_run_as' => 'root')
@@ -27,7 +27,7 @@ Puppet::Functions.create_function(:run_task) do
27
27
  # @param task_name The task to run.
28
28
  # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
29
29
  # @param description A description to be output when calling this function.
30
- # @param args Arguments to the plan. Can also include additional options: '_catch_errors', '_run_as'.
30
+ # @param args Arguments to the plan. Can also include additional options: '_catch_errors', '_run_as', '_noop'.
31
31
  # @return A list of results, one entry per target.
32
32
  # @example Run a task
33
33
  # run_task('facts', $targets, 'Gather OS facts')
@@ -108,7 +108,9 @@ Puppet::Functions.create_function(:run_task) do
108
108
  end
109
109
  end
110
110
 
111
- if executor.noop
111
+ # executor.noop is set when run task is called from the CLI
112
+ # options[:noop] is set when it's called from a plan
113
+ if executor.noop || options[:noop]
112
114
  if task.supports_noop
113
115
  params['_noop'] = true
114
116
  else
@@ -9,7 +9,7 @@ require 'bolt/error'
9
9
  Puppet::Functions.create_function(:upload_file, Puppet::Functions::InternalFunction) do
10
10
  # Upload a file or directory.
11
11
  # @param source A source path, either an absolute path or a modulename/filename selector for a
12
- # file or directory in <moduleroot>/files.
12
+ # file or directory in $MODULEROOT/files.
13
13
  # @param destination An absolute path on the target(s).
14
14
  # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
15
15
  # @param options Additional options: '_catch_errors', '_run_as'.
@@ -29,7 +29,7 @@ Puppet::Functions.create_function(:upload_file, Puppet::Functions::InternalFunct
29
29
 
30
30
  # Upload a file or directory, logging the provided description.
31
31
  # @param source A source path, either an absolute path or a modulename/filename selector for a
32
- # file or directory in <moduleroot>/files.
32
+ # file or directory in $MODULEROOT/files.
33
33
  # @param destination An absolute path on the target(s).
34
34
  # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
35
35
  # @param description A description to be output when calling this function.
@@ -31,6 +31,9 @@ module Bolt
31
31
  when 'inventory'
32
32
  { flags: OPTIONS[:inventory] + OPTIONS[:global] + %w[format inventoryfile boltdir configfile],
33
33
  banner: INVENTORY_HELP }
34
+ when 'group'
35
+ { flags: OPTIONS[:global] + %w[format inventoryfile boltdir configfile],
36
+ banner: GROUP_HELP }
34
37
  when 'plan'
35
38
  case action
36
39
  when 'convert'
@@ -117,6 +120,7 @@ module Bolt
117
120
  bolt secret encrypt <plaintext> Encrypt a value
118
121
  bolt secret decrypt <encrypted> Decrypt a value
119
122
  bolt inventory show Show the list of targets an action would run on
123
+ bolt group show Show the list of groups in the inventory
120
124
 
121
125
  Run `bolt <subcommand> --help` to view specific examples.
122
126
 
@@ -297,6 +301,15 @@ module Bolt
297
301
  Available options are:
298
302
  INVENTORY_HELP
299
303
 
304
+ GROUP_HELP = <<~GROUP_HELP
305
+ Usage: bolt group <action>
306
+
307
+ Available actions are:
308
+ show Show the list of groups in the inventory
309
+
310
+ Available options are:
311
+ GROUP_HELP
312
+
300
313
  def initialize(options)
301
314
  super()
302
315
 
@@ -36,6 +36,7 @@ module Bolt
36
36
  'puppetfile' => %w[install show-modules generate-types],
37
37
  'secret' => %w[encrypt decrypt createkeys],
38
38
  'inventory' => %w[show],
39
+ 'group' => %w[show],
39
40
  'apply' => %w[] }.freeze
40
41
 
41
42
  attr_reader :config, :options
@@ -117,6 +118,11 @@ module Bolt
117
118
  Bolt::Config.from_boltdir(boltdir, options)
118
119
  end
119
120
 
121
+ # Set $future global if configured
122
+ # rubocop:disable Style/GlobalVars
123
+ $future = @config.future
124
+ # rubocop:enable Style/GlobalVars
125
+
120
126
  Bolt::Logger.configure(config.log, config.color)
121
127
 
122
128
  # Logger must be configured before checking path case, otherwise warnings will not display
@@ -302,6 +308,8 @@ module Bolt
302
308
  end
303
309
  elsif options[:subcommand] == 'inventory'
304
310
  list_targets
311
+ elsif options[:subcommand] == 'group'
312
+ list_groups
305
313
  end
306
314
  return 0
307
315
  elsif options[:action] == 'show-modules'
@@ -408,6 +416,11 @@ module Bolt
408
416
  outputter.print_targets(options)
409
417
  end
410
418
 
419
+ def list_groups
420
+ groups = inventory.group_names
421
+ outputter.print_groups(groups)
422
+ end
423
+
411
424
  def run_plan(plan_name, plan_arguments, nodes, options)
412
425
  unless nodes.empty?
413
426
  if plan_arguments['nodes']
@@ -419,9 +432,8 @@ module Bolt
419
432
  plan_arguments['nodes'] = nodes.join(',')
420
433
  end
421
434
 
422
- params = options[:noop] ? plan_arguments.merge('_noop' => true) : plan_arguments
423
435
  plan_context = { plan_name: plan_name,
424
- params: params }
436
+ params: plan_arguments }
425
437
  plan_context[:description] = options[:description] if options[:description]
426
438
 
427
439
  executor = Bolt::Executor.new(config.concurrency, analytics, options[:noop])
@@ -33,7 +33,7 @@ module Bolt
33
33
  class Config
34
34
  attr_accessor :concurrency, :format, :trace, :log, :puppetdb, :color, :save_rerun,
35
35
  :transport, :transports, :inventoryfile, :compile_concurrency, :boltdir,
36
- :puppetfile_config, :plugins, :plugin_hooks
36
+ :puppetfile_config, :plugins, :plugin_hooks, :future
37
37
  attr_writer :modulepath
38
38
 
39
39
  TRANSPORT_OPTIONS = %i[password run-as sudo-password extensions
@@ -164,6 +164,8 @@ module Bolt
164
164
  @plugins = data['plugins'] if data.key?('plugins')
165
165
  @plugin_hooks.merge!(data['plugin_hooks']) if data.key?('plugin_hooks')
166
166
 
167
+ @future = data['future'] == true
168
+
167
169
  %w[concurrency format puppetdb color transport].each do |key|
168
170
  send("#{key}=", data[key]) if data.key?(key)
169
171
  end
@@ -149,7 +149,10 @@ module Bolt
149
149
 
150
150
  def add_facts(target, new_facts = {})
151
151
  @logger.warn("No facts to add") if new_facts.empty?
152
- set_facts(target.name, new_facts)
152
+ facts = set_facts(target.name, new_facts)
153
+ # rubocop:disable Style/GlobalVars
154
+ $future ? target : facts
155
+ # rubocop:enable Style/GlobalVars
153
156
  end
154
157
 
155
158
  def facts(target)
@@ -145,7 +145,7 @@ module Bolt
145
145
  conf.validate
146
146
 
147
147
  # Recompute the target cached state with the merged data
148
- update_target_state(target, conf.transport_conf, data)
148
+ update_target_state(target, conf, data)
149
149
 
150
150
  unless target.transport.nil? || Bolt::TRANSPORTS.include?(target.transport.to_sym)
151
151
  raise Bolt::UnknownTransportError.new(target.transport, target.uri)
@@ -312,7 +312,9 @@ module Bolt
312
312
  def add_facts(target, new_facts = {})
313
313
  @targets[target.name]['facts'] = Bolt::Util.deep_merge(@targets[target.name]['facts'], new_facts)
314
314
  update_target(target)
315
- facts(target)
315
+ # rubocop:disable Style/GlobalVars
316
+ $future ? target : facts(target)
317
+ # rubocop:enable Style/GlobalVars
316
318
  end
317
319
 
318
320
  def facts(target)
@@ -357,8 +359,8 @@ module Bolt
357
359
  private :build_config_hash
358
360
 
359
361
  def update_target_state(target, conf, merged_data)
360
- @targets[target.name]['protocol'] = conf[:transport]
361
- t_conf = conf[:transports][target.transport.to_sym] || {}
362
+ @targets[target.name]['protocol'] = conf.transport_conf[:transport]
363
+ t_conf = conf.transport_conf[:transports][target.transport.to_sym] || {}
362
364
  @targets[target.name]['user'] = t_conf['user']
363
365
  @targets[target.name]['password'] = t_conf['password']
364
366
  @targets[target.name]['port'] = t_conf['port']
@@ -381,7 +383,8 @@ module Bolt
381
383
 
382
384
  target_plugin_hooks = @targets[target.name]['plugin_hooks'] || {}
383
385
  new_plugin_hooks = merged_data['plugin_hooks'] || {}
384
- @targets[target.name]['cached_state']['plugin_hooks'] = new_plugin_hooks.merge(target_plugin_hooks)
386
+ plugin_hooks_from_inv = new_plugin_hooks.merge(target_plugin_hooks)
387
+ @targets[target.name]['cached_state']['plugin_hooks'] = conf.plugin_hooks.merge(plugin_hooks_from_inv)
385
388
  end
386
389
  private :update_target_state
387
390
  end
@@ -318,6 +318,12 @@ module Bolt
318
318
  @stream.puts colorize(:green, count)
319
319
  end
320
320
 
321
+ def print_groups(groups)
322
+ count = "#{groups.count} group#{'s' unless groups.count == 1}"
323
+ @stream.puts groups.join("\n")
324
+ @stream.puts colorize(:green, count)
325
+ end
326
+
321
327
  # @param [Bolt::ResultSet] apply_result A ResultSet object representing the result of a `bolt apply`
322
328
  def print_apply_result(apply_result, elapsed_time)
323
329
  print_summary(apply_result, elapsed_time)
@@ -96,6 +96,12 @@ module Bolt
96
96
  "count": count }.to_json)
97
97
  end
98
98
 
99
+ def print_groups(groups)
100
+ count = groups.count
101
+ @stream.puts({ "groups": groups,
102
+ "count": count }.to_json)
103
+ end
104
+
99
105
  def fatal_error(err)
100
106
  @stream.puts "],\n" if @items_open
101
107
  @stream.puts '"_error": ' if @object_open
@@ -220,14 +220,12 @@ module Bolt
220
220
  end
221
221
 
222
222
  def puppet_library(opts, target, apply_prep)
223
- tasksig = @hook_map[:puppet_library]
223
+ task = @hook_map[:puppet_library]['task']
224
224
 
225
- # this also validates
226
- params, meta_params = process_params(tasksig, opts)
225
+ params, meta_params = process_params(task, opts)
227
226
 
228
227
  # our metaparams are meant for the task not the executor
229
228
  params = params.merge(meta_params)
230
- task = Bolt::Task.new(tasksig)
231
229
 
232
230
  proc do
233
231
  apply_prep.run_task([target], task, params).first
@@ -92,12 +92,15 @@ module Bolt
92
92
 
93
93
  def status_hash
94
94
  # DEPRECATION: node in status hashes is deprecated and should be removed in 2.0
95
- { node: @target.name,
95
+ base = {
96
96
  target: @target.name,
97
97
  action: action,
98
98
  object: object,
99
- status: ok? ? 'success' : 'failure',
100
- result: @value }
99
+ status: status
100
+ }
101
+ # rubocop:disable Style/GlobalVars
102
+ $future ? base.merge(value: @value) : base.merge(result: @value, node: @target.name)
103
+ # rubocop:enable Style/GlobalVars
101
104
  end
102
105
 
103
106
  def generic_value
@@ -132,6 +135,10 @@ module Bolt
132
135
  Bolt::Util.walk_keys(status_hash, &:to_s)
133
136
  end
134
137
 
138
+ def status
139
+ ok? ? 'success' : 'failure'
140
+ end
141
+
135
142
  def ok?
136
143
  error_hash.nil?
137
144
  end
@@ -14,7 +14,7 @@ module Bolt
14
14
  end
15
15
 
16
16
  # Target.new from a plan with just a uri
17
- # rubocop:disable UnusedMethodArgument
17
+ # rubocop:disable Lint/UnusedMethodArgument
18
18
  def self.from_asserted_args(uri = nil,
19
19
  name = nil,
20
20
  target_alias = nil,
@@ -38,7 +38,7 @@ module Bolt
38
38
  plugin_hooks = nil)
39
39
  @name = name
40
40
  end
41
- # rubocop:enable UnusedMethodArgument
41
+ # rubocop:enable Lint/UnusedMethodArgument
42
42
 
43
43
  # Used for munging target + group data
44
44
  def target_data_hash
@@ -12,6 +12,7 @@ module Bolt
12
12
  @target = target
13
13
  @logger = Logging.logger[target.safe_name]
14
14
  @docker_host = @target.options['service-url']
15
+ @logger.debug("Initializing docker connection to #{@target.safe_name}")
15
16
  end
16
17
 
17
18
  def connect
@@ -32,6 +32,7 @@ module Bolt
32
32
 
33
33
  @logger = Logging.logger[@target.safe_name]
34
34
  @transport_logger = transport_logger
35
+ @logger.debug("Initializing ssh connection to #{@target.safe_name}")
35
36
 
36
37
  if target.options['private-key']&.instance_of?(String)
37
38
  begin
@@ -24,6 +24,7 @@ module Bolt
24
24
  @extensions = DEFAULT_EXTENSIONS.to_set.merge(extensions)
25
25
 
26
26
  @logger = Logging.logger[@target.safe_name]
27
+ logger.debug("Initializing winrm connection to #{@target.safe_name}")
27
28
  @transport_logger = transport_logger
28
29
  end
29
30
 
@@ -29,10 +29,12 @@ module Bolt
29
29
  logger.debug(msg)
30
30
  nil
31
31
  end
32
- rescue Psych::Exception
33
- raise Bolt::FileError.new("Could not parse #{file_name} file: #{path}", path)
34
- rescue IOError, SystemCallError
35
- raise Bolt::FileError.new("Could not read #{file_name} file: #{path}", path)
32
+ rescue Psych::Exception => e
33
+ raise Bolt::FileError.new("Could not parse #{file_name} file: #{path}\n"\
34
+ "Error at line #{e.line} column #{e.column}", path)
35
+ rescue IOError, SystemCallError => e
36
+ raise Bolt::FileError.new("Could not read #{file_name} file: #{path}\n"\
37
+ "error: #{e}", path)
36
38
  end
37
39
 
38
40
  # Accepts a path with either 'plans' or 'tasks' in it and determines
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
- VERSION = '1.33.0'
4
+ VERSION = '1.34.0'
5
5
  end
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: 1.33.0
4
+ version: 1.34.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-10 00:00:00.000000000 Z
11
+ date: 2019-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable