bolt 2.20.0 → 2.24.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/Puppetfile +3 -1
  3. data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +6 -0
  4. data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +12 -6
  5. data/bolt-modules/dir/lib/puppet/functions/dir/children.rb +35 -0
  6. data/bolt-modules/out/lib/puppet/functions/out/message.rb +1 -1
  7. data/exe/bolt +1 -0
  8. data/guides/inventory.txt +19 -0
  9. data/guides/project.txt +22 -0
  10. data/lib/bolt/analytics.rb +5 -5
  11. data/lib/bolt/applicator.rb +4 -3
  12. data/lib/bolt/bolt_option_parser.rb +75 -25
  13. data/lib/bolt/catalog.rb +9 -1
  14. data/lib/bolt/cli.rb +226 -73
  15. data/lib/bolt/config.rb +7 -0
  16. data/lib/bolt/config/options.rb +4 -4
  17. data/lib/bolt/executor.rb +16 -8
  18. data/lib/bolt/inventory/group.rb +3 -3
  19. data/lib/bolt/logger.rb +3 -4
  20. data/lib/bolt/module.rb +2 -1
  21. data/lib/bolt/outputter.rb +56 -0
  22. data/lib/bolt/outputter/human.rb +10 -9
  23. data/lib/bolt/outputter/json.rb +11 -4
  24. data/lib/bolt/outputter/logger.rb +2 -2
  25. data/lib/bolt/outputter/rainbow.rb +15 -0
  26. data/lib/bolt/pal.rb +5 -9
  27. data/lib/bolt/pal/yaml_plan/evaluator.rb +4 -0
  28. data/lib/bolt/pal/yaml_plan/step.rb +14 -1
  29. data/lib/bolt/pal/yaml_plan/step/message.rb +30 -0
  30. data/lib/bolt/pal/yaml_plan/transpiler.rb +11 -3
  31. data/lib/bolt/plugin/prompt.rb +3 -3
  32. data/lib/bolt/project.rb +6 -4
  33. data/lib/bolt/project_migrate.rb +138 -0
  34. data/lib/bolt/shell/bash.rb +7 -7
  35. data/lib/bolt/transport/docker/connection.rb +9 -9
  36. data/lib/bolt/transport/local/connection.rb +2 -2
  37. data/lib/bolt/transport/orch.rb +3 -3
  38. data/lib/bolt/transport/ssh/connection.rb +5 -5
  39. data/lib/bolt/transport/ssh/exec_connection.rb +4 -4
  40. data/lib/bolt/transport/winrm/connection.rb +17 -8
  41. data/lib/bolt/util.rb +1 -1
  42. data/lib/bolt/util/puppet_log_level.rb +4 -3
  43. data/lib/bolt/version.rb +1 -1
  44. data/lib/bolt_server/base_config.rb +1 -1
  45. data/lib/bolt_server/pe/pal.rb +1 -1
  46. data/lib/bolt_server/transport_app.rb +76 -0
  47. data/lib/bolt_spec/plans.rb +1 -1
  48. data/lib/bolt_spec/plans/action_stubs.rb +1 -1
  49. data/libexec/apply_catalog.rb +2 -2
  50. data/libexec/bolt_catalog +1 -1
  51. data/libexec/custom_facts.rb +1 -1
  52. data/libexec/query_resources.rb +1 -1
  53. data/modules/secure_env_vars/plans/init.pp +20 -0
  54. metadata +8 -2
@@ -19,7 +19,7 @@ module Bolt
19
19
  # Build set of extensions from extensions config as well as interpreters
20
20
 
21
21
  @logger = Logging.logger[@target.safe_name]
22
- logger.debug("Initializing winrm connection to #{@target.safe_name}")
22
+ logger.trace("Initializing winrm connection to #{@target.safe_name}")
23
23
  @transport_logger = transport_logger
24
24
  end
25
25
 
@@ -55,7 +55,7 @@ module Bolt
55
55
 
56
56
  @session = @connection.shell(:powershell)
57
57
  @session.run('$PSVersionTable.PSVersion')
58
- @logger.debug { "Opened session" }
58
+ @logger.trace { "Opened session" }
59
59
  end
60
60
  rescue Timeout::Error
61
61
  # If we're using the default port with SSL, a timeout probably means the
@@ -97,11 +97,11 @@ module Bolt
97
97
  def disconnect
98
98
  @session&.close
99
99
  @client&.disconnect!
100
- @logger.debug { "Closed session" }
100
+ @logger.trace { "Closed session" }
101
101
  end
102
102
 
103
103
  def execute(command)
104
- @logger.debug { "Executing command: #{command}" }
104
+ @logger.trace { "Executing command: #{command}" }
105
105
 
106
106
  inp = StringIO.new
107
107
  # This transport doesn't accept stdin, so close the stream to ensure
@@ -111,12 +111,21 @@ module Bolt
111
111
  out_rd, out_wr = IO.pipe('UTF-8')
112
112
  err_rd, err_wr = IO.pipe('UTF-8')
113
113
  th = Thread.new do
114
+ # By default, any exception raised in a thread will be reported to
115
+ # stderr as a stacktrace. Since we know these errors are going to
116
+ # propagate to the main thread via the shell, there's no chance
117
+ # they will be unhandled, so the default stack trace is unneeded.
118
+ Thread.current.report_on_exception = false
114
119
  result = @session.run(command)
115
120
  out_wr << result.stdout
116
121
  err_wr << result.stderr
117
122
  out_wr.close
118
123
  err_wr.close
119
124
  result.exitcode
125
+ ensure
126
+ # Close the streams to avoid the caller deadlocking
127
+ out_wr.close
128
+ err_wr.close
120
129
  end
121
130
 
122
131
  [inp, out_rd, err_rd, th]
@@ -125,12 +134,12 @@ module Bolt
125
134
  "with 'ulimit -n 1024'. See https://puppet.com/docs/bolt/latest/bolt_known_issues.html for details."
126
135
  raise Bolt::Error.new(msg, 'bolt/too-many-files')
127
136
  rescue StandardError
128
- @logger.debug { "Command aborted" }
137
+ @logger.trace { "Command aborted" }
129
138
  raise
130
139
  end
131
140
 
132
141
  def upload_file(source, destination)
133
- @logger.debug { "Uploading #{source}, to #{destination}" }
142
+ @logger.trace { "Uploading #{source} to #{destination}" }
134
143
  if target.options['file-protocol'] == 'smb'
135
144
  upload_file_smb(source, destination)
136
145
  else
@@ -176,7 +185,7 @@ module Bolt
176
185
  end
177
186
 
178
187
  def download_file(source, destination, download)
179
- @logger.debug { "Downloading #{source} to #{destination}" }
188
+ @logger.trace { "Downloading #{source} to #{destination}" }
180
189
  if target.options['file-protocol'] == 'smb'
181
190
  download_file_smb(source, destination)
182
191
  else
@@ -248,7 +257,7 @@ module Bolt
248
257
  status = @client.login
249
258
  case status
250
259
  when WindowsError::NTStatus::STATUS_SUCCESS
251
- @logger.debug { "Connected to #{@client.dns_host_name}" }
260
+ @logger.trace { "Connected to #{@client.dns_host_name}" }
252
261
  when WindowsError::NTStatus::STATUS_LOGON_FAILURE
253
262
  raise Bolt::Node::ConnectError.new(
254
263
  "SMB authentication failed for #{target.safe_name}",
@@ -13,7 +13,7 @@ module Bolt
13
13
  msg = "Invalid content for #{file_name} file: #{path} should be a Hash or empty, not #{content.class}"
14
14
  raise Bolt::FileError.new(msg, path)
15
15
  end
16
- logger.debug("Loaded #{file_name} from #{path}")
16
+ logger.trace("Loaded #{file_name} from #{path}")
17
17
  content
18
18
  rescue Errno::ENOENT
19
19
  raise Bolt::FileError.new("Could not read #{file_name} file: #{path}", path)
@@ -4,9 +4,10 @@ module Bolt
4
4
  module Util
5
5
  module PuppetLogLevel
6
6
  MAPPING = {
7
- debug: :debug,
8
- info: :info,
9
- notice: :notice,
7
+ # Demote Puppet's logs by one level, since Puppet is an implementation detail of Bolt
8
+ debug: :trace,
9
+ info: :debug,
10
+ notice: :info,
10
11
  warning: :warn,
11
12
  err: :error,
12
13
  # The following are used by Puppet functions of the same name, and are all treated as
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
- VERSION = '2.20.0'
4
+ VERSION = '2.24.1'
5
5
  end
@@ -16,7 +16,7 @@ module BoltServer
16
16
 
17
17
  def defaults
18
18
  { 'host' => '127.0.0.1',
19
- 'loglevel' => 'notice',
19
+ 'loglevel' => 'warn',
20
20
  'ssl-cipher-suites' => %w[ECDHE-ECDSA-AES256-GCM-SHA384
21
21
  ECDHE-RSA-AES256-GCM-SHA384
22
22
  ECDHE-ECDSA-CHACHA20-POLY1305
@@ -58,7 +58,7 @@ module BoltServer
58
58
  # Bolt::PAL::MODULES_PATH which would be more complex if we tried to use @modulepath since
59
59
  # we need to append our modulepaths and exclude modules shiped in bolt gem code
60
60
  modulepath_dirs = environment.modulepath
61
- @original_modulepath = modulepath_dirs
61
+ @user_modulepath = modulepath_dirs
62
62
  @modulepath = [PE_BOLTLIB_PATH, Bolt::PAL::BOLTLIB_PATH, *modulepath_dirs]
63
63
  end
64
64
  end
@@ -221,6 +221,56 @@ module BoltServer
221
221
  plan_info
222
222
  end
223
223
 
224
+ def build_puppetserver_uri(file_identifier, module_name, environment)
225
+ segments = file_identifier.split('/', 3)
226
+ if segments.size == 1
227
+ {
228
+ 'path' => "/puppet/v3/file_content/tasks/#{module_name}/#{file_identifier}",
229
+ 'params' => {
230
+ 'environment' => environment
231
+ }
232
+ }
233
+ else
234
+ module_segment, mount_segment, name_segment = *segments
235
+ {
236
+ 'path' => case mount_segment
237
+ when 'files'
238
+ "/puppet/v3/file_content/modules/#{module_segment}/#{name_segment}"
239
+ when 'tasks'
240
+ "/puppet/v3/file_content/tasks/#{module_segment}/#{name_segment}"
241
+ when 'lib'
242
+ "/puppet/v3/file_content/plugins/#{name_segment}"
243
+ end,
244
+ 'params' => {
245
+ 'environment' => environment
246
+ }
247
+ }
248
+ end
249
+ end
250
+
251
+ def pe_task_info(pal, module_name, task_name, environment)
252
+ # Handle case where task name is simply module name with special `init` task
253
+ task_name = if task_name == 'init' || task_name.nil?
254
+ module_name
255
+ else
256
+ "#{module_name}::#{task_name}"
257
+ end
258
+ task = pal.get_task(task_name)
259
+ files = task.files.map do |file_hash|
260
+ {
261
+ 'filename' => file_hash['name'],
262
+ 'sha256' => Digest::SHA256.hexdigest(File.read(file_hash['path'])),
263
+ 'size_bytes' => File.size(file_hash['path']),
264
+ 'uri' => build_puppetserver_uri(file_hash['name'], module_name, environment)
265
+ }
266
+ end
267
+ {
268
+ 'metadata' => task.metadata,
269
+ 'name' => task.name,
270
+ 'files' => files
271
+ }
272
+ end
273
+
224
274
  get '/' do
225
275
  200
226
276
  end
@@ -351,6 +401,16 @@ module BoltServer
351
401
  end
352
402
  end
353
403
 
404
+ # Fetches the metadata for a single task
405
+ #
406
+ # @param environment [String] the environment to fetch the task from
407
+ get '/tasks/:module_name/:task_name' do
408
+ in_pe_pal_env(params['environment']) do |pal|
409
+ task_info = pe_task_info(pal, params[:module_name], params[:task_name], params['environment'])
410
+ [200, task_info.to_json]
411
+ end
412
+ end
413
+
354
414
  # Fetches the list of plans for an environment, optionally fetching all metadata for each plan
355
415
  #
356
416
  # @param environment [String] the environment to fetch the list of plans from
@@ -375,6 +435,22 @@ module BoltServer
375
435
  end
376
436
  end
377
437
 
438
+ # Fetches the list of tasks for an environment
439
+ #
440
+ # @param environment [String] the environment to fetch the list of tasks from
441
+ get '/tasks' do
442
+ in_pe_pal_env(params['environment']) do |pal|
443
+ tasks = pal.list_tasks
444
+ tasks_response = tasks.map { |task_name, _description| { 'name' => task_name } }.to_json
445
+
446
+ # We structure this array of tasks to be an array of hashes so that it matches the structure
447
+ # returned by the puppetserver API that serves data like this. Structuring the output this way
448
+ # makes switching between puppetserver and bolt-server easier, which makes changes to switch
449
+ # to bolt-server smaller/simpler.
450
+ [200, tasks_response]
451
+ end
452
+ end
453
+
378
454
  error 404 do
379
455
  err = Bolt::Error.new("Could not find route #{request.path}",
380
456
  'boltserver/not-found')
@@ -206,7 +206,7 @@ module BoltSpec
206
206
  Puppet[:tasks] = true
207
207
 
208
208
  # Ensure logger is initialized with Puppet levels so 'notice' works when running plan specs.
209
- Logging.init :debug, :info, :notice, :warn, :error, :fatal, :any
209
+ Logging.init :trace, :debug, :info, :notice, :warn, :error, :fatal, :any
210
210
  end
211
211
 
212
212
  # Provided as a class so expectations can be placed on it.
@@ -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()' may require msg and kind, and " \
181
181
  "optionally accept only details and issue_code."
182
182
  @data[:default] = data
183
183
  end
@@ -9,7 +9,7 @@ require 'puppet/module_tool/tar'
9
9
  require 'securerandom'
10
10
  require 'tempfile'
11
11
 
12
- args = JSON.parse(ARGV[0] ? File.read(ARGV[0]) : STDIN.read)
12
+ args = JSON.parse(ARGV[0] ? File.read(ARGV[0]) : $stdin.read)
13
13
 
14
14
  # Create temporary directories for all core Puppet settings so we don't clobber
15
15
  # existing state or read from puppet.conf. Also create a temporary modulepath.
@@ -110,7 +110,7 @@ ensure
110
110
  begin
111
111
  FileUtils.remove_dir(puppet_root)
112
112
  rescue Errno::ENOTEMPTY => e
113
- STDERR.puts("Could not cleanup temporary directory: #{e}")
113
+ $stderr.puts("Could not cleanup temporary directory: #{e}")
114
114
  end
115
115
  end
116
116
 
@@ -40,7 +40,7 @@ when "compile"
40
40
  request = if ARGV[1]
41
41
  File.open(ARGV[1]) { |fh| JSON.parse(fh.read) }
42
42
  else
43
- JSON.parse(STDIN.read)
43
+ JSON.parse($stdin.read)
44
44
  end
45
45
  begin
46
46
  catalog = Bolt::Catalog.new.compile_catalog(request)
@@ -6,7 +6,7 @@ require 'puppet'
6
6
  require 'puppet/module_tool/tar'
7
7
  require 'tempfile'
8
8
 
9
- args = JSON.parse(STDIN.read)
9
+ args = JSON.parse($stdin.read)
10
10
 
11
11
  Dir.mktmpdir do |puppet_root|
12
12
  # Create temporary directories for all core Puppet settings so we don't clobber
@@ -6,7 +6,7 @@ require 'puppet'
6
6
  require 'puppet/module_tool/tar'
7
7
  require 'tempfile'
8
8
 
9
- args = JSON.parse(STDIN.read)
9
+ args = JSON.parse($stdin.read)
10
10
 
11
11
  RESOURCE_INSTANCE = /^([^\[]+)\[([^\]]+)\]$/.freeze
12
12
 
@@ -0,0 +1,20 @@
1
+ plan secure_env_vars(
2
+ TargetSpec $targets,
3
+ Optional[String] $command = undef,
4
+ Optional[String] $script = undef
5
+ ) {
6
+ $env_vars = parsejson(system::env('BOLT_ENV_VARS'))
7
+ unless type($command) == Undef or type($script) == Undef {
8
+ fail_plan('Cannot specify both script and command for secure_env_vars')
9
+ }
10
+
11
+ return if $command {
12
+ run_command($command, $targets, '_env_vars' => $env_vars)
13
+ }
14
+ elsif $script {
15
+ run_script($script, $targets, '_env_vars' => $env_vars)
16
+ }
17
+ else {
18
+ fail_plan('Must specify either script or command for secure_env_vars')
19
+ }
20
+ }
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: 2.20.0
4
+ version: 2.24.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-27 00:00:00.000000000 Z
11
+ date: 2020-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -427,6 +427,7 @@ files:
427
427
  - bolt-modules/boltlib/types/targetspec.pp
428
428
  - bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb
429
429
  - bolt-modules/ctrl/lib/puppet/functions/ctrl/sleep.rb
430
+ - bolt-modules/dir/lib/puppet/functions/dir/children.rb
430
431
  - bolt-modules/file/lib/puppet/functions/file/exists.rb
431
432
  - bolt-modules/file/lib/puppet/functions/file/join.rb
432
433
  - bolt-modules/file/lib/puppet/functions/file/read.rb
@@ -436,6 +437,8 @@ files:
436
437
  - bolt-modules/prompt/lib/puppet/functions/prompt.rb
437
438
  - bolt-modules/system/lib/puppet/functions/system/env.rb
438
439
  - exe/bolt
440
+ - guides/inventory.txt
441
+ - guides/project.txt
439
442
  - lib/bolt.rb
440
443
  - lib/bolt/analytics.rb
441
444
  - lib/bolt/applicator.rb
@@ -482,6 +485,7 @@ files:
482
485
  - lib/bolt/pal/yaml_plan/step/command.rb
483
486
  - lib/bolt/pal/yaml_plan/step/download.rb
484
487
  - lib/bolt/pal/yaml_plan/step/eval.rb
488
+ - lib/bolt/pal/yaml_plan/step/message.rb
485
489
  - lib/bolt/pal/yaml_plan/step/plan.rb
486
490
  - lib/bolt/pal/yaml_plan/step/resources.rb
487
491
  - lib/bolt/pal/yaml_plan/step/script.rb
@@ -496,6 +500,7 @@ files:
496
500
  - lib/bolt/plugin/puppetdb.rb
497
501
  - lib/bolt/plugin/task.rb
498
502
  - lib/bolt/project.rb
503
+ - lib/bolt/project_migrate.rb
499
504
  - lib/bolt/puppetdb.rb
500
505
  - lib/bolt/puppetdb/client.rb
501
506
  - lib/bolt/puppetdb/config.rb
@@ -576,6 +581,7 @@ files:
576
581
  - modules/canary/lib/puppet/functions/canary/skip.rb
577
582
  - modules/canary/plans/init.pp
578
583
  - modules/puppetdb_fact/plans/init.pp
584
+ - modules/secure_env_vars/plans/init.pp
579
585
  homepage: https://github.com/puppetlabs/bolt
580
586
  licenses:
581
587
  - Apache-2.0