bolt 2.33.2 → 2.38.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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/Puppetfile +1 -1
  3. data/bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb +1 -0
  4. data/bolt-modules/boltlib/lib/puppet/functions/catch_errors.rb +1 -3
  5. data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +17 -6
  6. data/bolt-modules/boltlib/lib/puppet/functions/parallelize.rb +56 -0
  7. data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +24 -6
  8. data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +27 -8
  9. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +21 -1
  10. data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +18 -1
  11. data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +24 -6
  12. data/lib/bolt/analytics.rb +27 -8
  13. data/lib/bolt/apply_result.rb +3 -3
  14. data/lib/bolt/bolt_option_parser.rb +48 -16
  15. data/lib/bolt/cli.rb +154 -249
  16. data/lib/bolt/config.rb +188 -55
  17. data/lib/bolt/config/options.rb +147 -87
  18. data/lib/bolt/config/transport/base.rb +10 -19
  19. data/lib/bolt/config/transport/local.rb +1 -7
  20. data/lib/bolt/config/transport/options.rb +10 -68
  21. data/lib/bolt/config/transport/ssh.rb +8 -14
  22. data/lib/bolt/error.rb +33 -3
  23. data/lib/bolt/executor.rb +92 -6
  24. data/lib/bolt/inventory.rb +25 -0
  25. data/lib/bolt/inventory/group.rb +2 -1
  26. data/lib/bolt/inventory/options.rb +130 -0
  27. data/lib/bolt/inventory/target.rb +10 -11
  28. data/lib/bolt/module_installer.rb +21 -13
  29. data/lib/bolt/module_installer/resolver.rb +1 -1
  30. data/lib/bolt/outputter.rb +19 -5
  31. data/lib/bolt/outputter/human.rb +41 -10
  32. data/lib/bolt/outputter/json.rb +1 -1
  33. data/lib/bolt/outputter/logger.rb +1 -1
  34. data/lib/bolt/outputter/rainbow.rb +13 -2
  35. data/lib/bolt/pal.rb +19 -7
  36. data/lib/bolt/pal/yaml_plan.rb +7 -0
  37. data/lib/bolt/plan_creator.rb +160 -0
  38. data/lib/bolt/plugin.rb +42 -13
  39. data/lib/bolt/plugin/cache.rb +76 -0
  40. data/lib/bolt/plugin/module.rb +4 -4
  41. data/lib/bolt/plugin/puppetdb.rb +1 -1
  42. data/lib/bolt/project.rb +59 -40
  43. data/lib/bolt/project_manager.rb +201 -0
  44. data/lib/bolt/{project_migrator/config.rb → project_manager/config_migrator.rb} +51 -5
  45. data/lib/bolt/{project_migrator/inventory.rb → project_manager/inventory_migrator.rb} +5 -5
  46. data/lib/bolt/{project_migrator/base.rb → project_manager/migrator.rb} +2 -2
  47. data/lib/bolt/{project_migrator/modules.rb → project_manager/module_migrator.rb} +5 -3
  48. data/lib/bolt/puppetdb/client.rb +11 -2
  49. data/lib/bolt/puppetdb/config.rb +9 -8
  50. data/lib/bolt/rerun.rb +1 -5
  51. data/lib/bolt/shell/bash.rb +8 -2
  52. data/lib/bolt/shell/powershell.rb +22 -4
  53. data/lib/bolt/target.rb +4 -0
  54. data/lib/bolt/task/run.rb +1 -1
  55. data/lib/bolt/transport/local.rb +13 -0
  56. data/lib/bolt/transport/orch.rb +0 -5
  57. data/lib/bolt/transport/orch/connection.rb +10 -3
  58. data/lib/bolt/transport/remote.rb +1 -1
  59. data/lib/bolt/transport/ssh/exec_connection.rb +6 -2
  60. data/lib/bolt/util.rb +41 -7
  61. data/lib/bolt/validator.rb +226 -0
  62. data/lib/bolt/version.rb +1 -1
  63. data/lib/bolt/yarn.rb +23 -0
  64. data/lib/bolt_server/base_config.rb +3 -1
  65. data/lib/bolt_server/config.rb +3 -1
  66. data/lib/bolt_server/file_cache.rb +2 -0
  67. data/lib/bolt_server/plugin.rb +13 -0
  68. data/lib/bolt_server/plugin/puppet_connect_data.rb +37 -0
  69. data/lib/bolt_server/schemas/connect-data.json +22 -0
  70. data/lib/bolt_server/schemas/partials/task.json +2 -2
  71. data/lib/bolt_server/transport_app.rb +82 -23
  72. data/lib/bolt_spec/plans/mock_executor.rb +4 -1
  73. data/libexec/apply_catalog.rb +1 -1
  74. data/libexec/custom_facts.rb +1 -1
  75. data/libexec/query_resources.rb +1 -1
  76. metadata +22 -13
  77. data/lib/bolt/project_migrator.rb +0 -80
@@ -7,6 +7,7 @@ require 'bolt/project'
7
7
  require 'bolt/logger'
8
8
  require 'bolt/util'
9
9
  require 'bolt/config/options'
10
+ require 'bolt/validator'
10
11
 
11
12
  module Bolt
12
13
  class UnknownTransportError < Bolt::Error
@@ -32,53 +33,110 @@ module Bolt
32
33
  end
33
34
 
34
35
  def self.from_project(project, overrides = {})
35
- logs = []
36
+ logs = []
37
+ deprecations = []
38
+
36
39
  conf = if project.project_file == project.config_file
37
40
  project.data
38
41
  else
39
42
  c = Bolt::Util.read_optional_yaml_hash(project.config_file, 'config')
43
+
44
+ # Validate the config against the schema. This will raise a single error
45
+ # with all validation errors.
46
+ Bolt::Validator.new.tap do |validator|
47
+ validator.validate(c, bolt_schema, project.config_file.to_s)
48
+
49
+ validator.warnings.each { |warning| logs << { warn: warning } }
50
+
51
+ validator.deprecations.each do |dep|
52
+ deprecations << { type: "#{BOLT_CONFIG_NAME} #{dep[:option]}", msg: dep[:message] }
53
+ end
54
+ end
55
+
40
56
  logs << { debug: "Loaded configuration from #{project.config_file}" } if File.exist?(project.config_file)
41
57
  c
42
58
  end
43
-
44
59
  data = load_defaults(project).push(
45
- filepath: project.config_file,
46
- data: conf,
47
- logs: logs,
48
- deprecations: []
60
+ filepath: project.config_file,
61
+ data: conf,
62
+ logs: logs,
63
+ deprecations: deprecations
49
64
  )
50
65
 
51
66
  new(project, data, overrides)
52
67
  end
53
68
 
54
69
  def self.from_file(configfile, overrides = {})
55
- project = Bolt::Project.create_project(Pathname.new(configfile).expand_path.dirname)
56
- logs = []
70
+ project = Bolt::Project.create_project(Pathname.new(configfile).expand_path.dirname)
71
+ logs = []
72
+ deprecations = []
57
73
 
58
74
  conf = if project.project_file == project.config_file
59
75
  project.data
60
76
  else
61
77
  c = Bolt::Util.read_yaml_hash(configfile, 'config')
78
+
79
+ # Validate the config against the schema. This will raise a single error
80
+ # with all validation errors.
81
+ Bolt::Validator.new.tap do |validator|
82
+ validator.validate(c, bolt_schema, project.config_file.to_s)
83
+
84
+ validator.warnings.each { |warning| logs << { warn: warning } }
85
+
86
+ validator.deprecations.each do |dep|
87
+ deprecations << { type: "#{BOLT_CONFIG_NAME} #{dep[:option]}", msg: dep[:message] }
88
+ end
89
+ end
90
+
62
91
  logs << { debug: "Loaded configuration from #{configfile}" }
63
92
  c
64
93
  end
65
94
 
66
95
  data = load_defaults(project).push(
67
- filepath: configfile,
68
- data: conf,
69
- logs: logs,
70
- deprecations: []
96
+ filepath: configfile,
97
+ data: conf,
98
+ logs: logs,
99
+ deprecations: deprecations
71
100
  )
72
101
 
73
102
  new(project, data, overrides)
74
103
  end
75
104
 
76
- def self.system_path
77
- # Lazy-load expensive gem code
78
- require 'win32/dir' if Bolt::Util.windows?
105
+ # Builds a hash of definitions for transport configuration.
106
+ #
107
+ def self.transport_definitions
108
+ INVENTORY_OPTIONS.each_with_object({}) do |(option, definition), acc|
109
+ acc[option] = TRANSPORT_CONFIG.key?(option) ? definition.merge(TRANSPORT_CONFIG[option].schema) : definition
110
+ end
111
+ end
112
+
113
+ # Builds the schema for bolt-defaults.yaml used by the validator.
114
+ #
115
+ def self.defaults_schema
116
+ schema = {
117
+ type: Hash,
118
+ properties: BOLT_DEFAULTS_OPTIONS.map { |opt| [opt, _ref: opt] }.to_h,
119
+ definitions: OPTIONS.merge(transport_definitions)
120
+ }
121
+
122
+ schema[:definitions]['inventory-config'][:properties] = transport_definitions
79
123
 
124
+ schema
125
+ end
126
+
127
+ # Builds the schema for bolt.yaml used by the validator.
128
+ #
129
+ def self.bolt_schema
130
+ {
131
+ type: Hash,
132
+ properties: (BOLT_OPTIONS + INVENTORY_OPTIONS.keys).map { |opt| [opt, _ref: opt] }.to_h,
133
+ definitions: OPTIONS.merge(transport_definitions)
134
+ }
135
+ end
136
+
137
+ def self.system_path
80
138
  if Bolt::Util.windows?
81
- Pathname.new(File.join(Dir::COMMON_APPDATA, 'PuppetLabs', 'bolt', 'etc'))
139
+ Pathname.new(File.join(ENV['ALLUSERSPROFILE'], 'PuppetLabs', 'bolt', 'etc'))
82
140
  else
83
141
  Pathname.new(File.join('/etc', 'puppetlabs', 'bolt'))
84
142
  end
@@ -94,9 +152,10 @@ module Bolt
94
152
  # projects. This file does not allow project-specific configuration such as 'hiera-config' and
95
153
  # 'inventoryfile', and nests all default inventory configuration under an 'inventory-config' key.
96
154
  def self.load_bolt_defaults_yaml(dir)
97
- filepath = dir + BOLT_DEFAULTS_NAME
98
- data = Bolt::Util.read_yaml_hash(filepath, 'config')
99
- logs = [{ debug: "Loaded configuration from #{filepath}" }]
155
+ filepath = dir + BOLT_DEFAULTS_NAME
156
+ data = Bolt::Util.read_yaml_hash(filepath, 'config')
157
+ logs = [{ debug: "Loaded configuration from #{filepath}" }]
158
+ deprecations = []
100
159
 
101
160
  # Warn if 'bolt.yaml' detected in same directory.
102
161
  if File.exist?(bolt_yaml = dir + BOLT_CONFIG_NAME)
@@ -106,6 +165,18 @@ module Bolt
106
165
  )
107
166
  end
108
167
 
168
+ # Validate the config against the schema. This will raise a single error
169
+ # with all validation errors.
170
+ Bolt::Validator.new.tap do |validator|
171
+ validator.validate(data, defaults_schema, filepath)
172
+
173
+ validator.warnings.each { |warning| logs << { warn: warning } }
174
+
175
+ validator.deprecations.each do |dep|
176
+ deprecations << { type: "#{BOLT_DEFAULTS_NAME} #{dep[:option]}", msg: dep[:message] }
177
+ end
178
+ end
179
+
109
180
  # Remove project-specific config such as hiera-config, etc.
110
181
  project_config = data.slice(*(BOLT_PROJECT_OPTIONS - BOLT_DEFAULTS_OPTIONS))
111
182
 
@@ -148,18 +219,30 @@ module Bolt
148
219
  data = data.merge(data.delete('inventory-config'))
149
220
  end
150
221
 
151
- { filepath: filepath, data: data, logs: logs, deprecations: [] }
222
+ { filepath: filepath, data: data, logs: logs, deprecations: deprecations }
152
223
  end
153
224
 
154
225
  # Loads a 'bolt.yaml' file, the legacy configuration file. There's no special munging needed
155
226
  # here since Bolt::Config will just ignore any invalid keys.
156
227
  def self.load_bolt_yaml(dir)
157
- filepath = dir + BOLT_CONFIG_NAME
158
- data = Bolt::Util.read_yaml_hash(filepath, 'config')
159
- logs = [{ debug: "Loaded configuration from #{filepath}" }]
228
+ filepath = dir + BOLT_CONFIG_NAME
229
+ data = Bolt::Util.read_yaml_hash(filepath, 'config')
230
+ logs = [{ debug: "Loaded configuration from #{filepath}" }]
160
231
  deprecations = [{ type: 'Using bolt.yaml for system configuration',
161
- msg: "Configuration file #{filepath} is deprecated and will be removed in a future version "\
162
- "of Bolt. Use '#{dir + BOLT_DEFAULTS_NAME}' instead." }]
232
+ msg: "Configuration file #{filepath} is deprecated and will be removed in Bolt 3.0. "\
233
+ "See https://pup.pt/update-bolt-config for how to update to the latest Bolt practices." }]
234
+
235
+ # Validate the config against the schema. This will raise a single error
236
+ # with all validation errors.
237
+ Bolt::Validator.new.tap do |validator|
238
+ validator.validate(data, bolt_schema, filepath)
239
+
240
+ validator.warnings.each { |warning| logs << { warn: warning } }
241
+
242
+ validator.deprecations.each do |dep|
243
+ deprecations << { type: "#{BOLT_CONFIG_NAME} #{dep[:option]}", msg: dep[:message] }
244
+ end
245
+ end
163
246
 
164
247
  { filepath: filepath, data: data, logs: logs, deprecations: deprecations }
165
248
  end
@@ -206,17 +289,21 @@ module Bolt
206
289
  @config_files = []
207
290
 
208
291
  default_data = {
292
+ 'apply-settings' => {},
209
293
  'apply_settings' => {},
210
294
  'color' => true,
211
295
  'compile-concurrency' => Etc.nprocessors,
212
296
  'concurrency' => default_concurrency,
213
297
  'format' => 'human',
214
298
  'log' => { 'console' => {} },
299
+ 'module-install' => {},
300
+ 'plugin-hooks' => {},
215
301
  'plugin_hooks' => {},
216
302
  'plugins' => {},
217
303
  'puppetdb' => {},
218
304
  'puppetfile' => {},
219
305
  'save-rerun' => true,
306
+ 'spinner' => true,
220
307
  'transport' => 'ssh'
221
308
  }
222
309
 
@@ -271,7 +358,7 @@ module Bolt
271
358
 
272
359
  # Set console log to debug if in debug mode
273
360
  if options[:debug]
274
- overrides['log'] = { 'console' => { 'level' => :debug } }
361
+ overrides['log'] = { 'console' => { 'level' => 'debug' } }
275
362
  end
276
363
 
277
364
  if options[:puppetfile_path]
@@ -280,6 +367,9 @@ module Bolt
280
367
 
281
368
  overrides['trace'] = opts['trace'] if opts.key?('trace')
282
369
 
370
+ # Validate the overrides
371
+ Bolt::Validator.new.validate(overrides, self.class.bolt_schema, 'command line')
372
+
283
373
  overrides
284
374
  end
285
375
 
@@ -296,7 +386,7 @@ module Bolt
296
386
  when *TRANSPORT_CONFIG.keys
297
387
  Bolt::Util.deep_merge(val1, val2)
298
388
  # Hash values are shallow merged
299
- when 'puppetdb', 'plugin_hooks', 'apply_settings', 'log'
389
+ when 'puppetdb', 'plugin-hooks', 'plugin_hooks', 'apply-settings', 'apply_settings', 'log'
300
390
  val1.merge(val2)
301
391
  # All other values are overwritten
302
392
  else
@@ -333,8 +423,9 @@ module Bolt
333
423
  end
334
424
 
335
425
  # Filter hashes to only include valid options
336
- @data['apply_settings'] = @data['apply_settings'].slice(*OPTIONS['apply_settings'][:properties].keys)
337
- @data['puppetfile'] = @data['puppetfile'].slice(*OPTIONS['puppetfile'][:properties].keys)
426
+ %w[apply-settings apply_settings module-install puppetfile].each do |opt|
427
+ @data[opt] = @data[opt].slice(*OPTIONS.dig(opt, :properties).keys)
428
+ end
338
429
  end
339
430
 
340
431
  private def normalize_log(target)
@@ -372,10 +463,18 @@ module Bolt
372
463
  raise Bolt::ValidationError,
373
464
  "level of log #{name} must be a String or Symbol, received #{v.class} #{v.inspect}"
374
465
  end
466
+
375
467
  unless Bolt::Logger.valid_level?(v)
376
468
  raise Bolt::ValidationError,
377
469
  "level of log #{name} must be one of #{Bolt::Logger.levels.join(', ')}; received #{v}"
378
470
  end
471
+
472
+ if v == 'notice'
473
+ @deprecations << {
474
+ type: 'notice log level',
475
+ msg: "Log level 'notice' is deprecated and will be removed in Bolt 3.0. Use 'info' instead."
476
+ }
477
+ end
379
478
  end
380
479
 
381
480
  if (v = acc[name][:append]) && v != true && v != false
@@ -397,41 +496,41 @@ module Bolt
397
496
  "is automatically appended to the modulepath and cannot be configured."
398
497
  end
399
498
 
400
- keys = OPTIONS.keys - %w[plugins plugin_hooks puppetdb]
401
- keys.each do |key|
402
- next unless Bolt::Util.references?(@data[key])
403
- valid_keys = TRANSPORT_CONFIG.keys + %w[plugins plugin_hooks puppetdb]
404
- raise Bolt::ValidationError,
405
- "Found unsupported key _plugin in config setting #{key}. Plugins are only available in "\
406
- "#{valid_keys.join(', ')}."
407
- end
408
-
409
- unless concurrency.is_a?(Integer) && concurrency > 0
410
- raise Bolt::ValidationError,
411
- "Concurrency must be a positive Integer, received #{concurrency.class} #{concurrency}"
412
- end
413
-
414
- unless compile_concurrency.is_a?(Integer) && compile_concurrency > 0
415
- raise Bolt::ValidationError,
416
- "Compile concurrency must be a positive Integer, received #{compile_concurrency.class} "\
417
- "#{compile_concurrency}"
418
- end
419
-
420
499
  compile_limit = 2 * Etc.nprocessors
421
500
  unless compile_concurrency < compile_limit
422
501
  raise Bolt::ValidationError, "Compilation is CPU-intensive, set concurrency less than #{compile_limit}"
423
502
  end
424
503
 
425
- unless %w[human json rainbow].include? format
426
- raise Bolt::ValidationError, "Unsupported format: '#{format}'"
504
+ %w[hiera-config trusted-external-command inventoryfile].each do |opt|
505
+ Bolt::Util.validate_file(opt, @data[opt]) if @data[opt]
427
506
  end
428
507
 
429
- Bolt::Util.validate_file('hiera-config', @data['hiera-config']) if @data['hiera-config']
430
- Bolt::Util.validate_file('trusted-external-command', trusted_external) if trusted_external
508
+ if File.exist?(default_inventoryfile)
509
+ Bolt::Util.validate_file('inventory file', default_inventoryfile)
510
+ end
431
511
 
432
512
  unless TRANSPORT_CONFIG.include?(transport)
433
513
  raise UnknownTransportError, transport
434
514
  end
515
+
516
+ # Warn the user how they should be using the 'puppetfile' or
517
+ # 'module-install' config options. We don't error here since these
518
+ # settings can be set at the user or system level.
519
+ if @project.modules && puppetfile_config.any? && module_install.empty?
520
+ command = Bolt::Util.powershell? ? 'Update-BoltProject' : 'bolt project migrate'
521
+ @logs << { warn: "Detected configuration for 'puppetfile'. This setting is not "\
522
+ "used when 'modules' is configured. Use 'module-install' instead. "\
523
+ "To automatically update your project configuration, run '#{command}'." }
524
+ elsif @project.modules.nil? && puppetfile_config.empty? && module_install.any?
525
+ @logs << { warn: "Detected configuration for 'module-install'. This setting is not "\
526
+ "used when 'modules' is not configured. Use 'puppetfile' instead." }
527
+ elsif @project.modules && puppetfile_config.any? && module_install.any?
528
+ @logs << { warn: "Detected configuration for 'puppetfile' and 'module-install'. Using "\
529
+ "configuration for 'module-install' because 'modules' is also configured." }
530
+ elsif @project.modules.nil? && puppetfile_config.any? && module_install.any?
531
+ @logs << { warn: "Detected configuration for 'puppetfile' and 'module-install'. Using "\
532
+ "configuration for 'puppetfile' because 'modules' is not configured." }
533
+ end
435
534
  end
436
535
 
437
536
  def default_inventoryfile
@@ -464,6 +563,10 @@ module Bolt
464
563
  @data['modulepath'] = value
465
564
  end
466
565
 
566
+ def plugin_cache
567
+ @project.plugin_cache || @data['plugin-cache'] || {}
568
+ end
569
+
467
570
  def concurrency
468
571
  @data['concurrency']
469
572
  end
@@ -496,6 +599,10 @@ module Bolt
496
599
  @data['save-rerun']
497
600
  end
498
601
 
602
+ def spinner
603
+ @data['spinner']
604
+ end
605
+
499
606
  def inventoryfile
500
607
  @data['inventoryfile']
501
608
  end
@@ -513,7 +620,18 @@ module Bolt
513
620
  end
514
621
 
515
622
  def plugin_hooks
516
- @data['plugin_hooks']
623
+ if @data['plugin-hooks'].any? && @data['plugin_hooks'].any?
624
+ Bolt::Logger.warn_once(
625
+ "plugin-hooks and plugin_hooks set",
626
+ "Detected configuration for 'plugin-hooks' and 'plugin_hooks'. Bolt will ignore 'plugin_hooks'."
627
+ )
628
+
629
+ @data['plugin-hooks']
630
+ elsif @data['plugin-hooks'].any?
631
+ @data['plugin-hooks']
632
+ else
633
+ @data['plugin_hooks']
634
+ end
517
635
  end
518
636
 
519
637
  def trusted_external
@@ -521,13 +639,28 @@ module Bolt
521
639
  end
522
640
 
523
641
  def apply_settings
524
- @data['apply_settings']
642
+ if @data['apply-settings'].any? && @data['apply_settings'].any?
643
+ Bolt::Logger.warn_once(
644
+ "apply-settings and apply_settings set",
645
+ "Detected configuration for 'apply-settings' and 'apply_settings'. Bolt will ignore 'apply_settings'."
646
+ )
647
+
648
+ @data['apply-settings']
649
+ elsif @data['apply-settings'].any?
650
+ @data['apply-settings']
651
+ else
652
+ @data['apply_settings']
653
+ end
525
654
  end
526
655
 
527
656
  def transport
528
657
  @data['transport']
529
658
  end
530
659
 
660
+ def module_install
661
+ @project.module_install || @data['module-install']
662
+ end
663
+
531
664
  # Check if there is a case-insensitive match to the path
532
665
  def check_path_case(type, paths)
533
666
  return if paths.nil?
@@ -33,77 +33,42 @@ module Bolt
33
33
  "_plugin" => {
34
34
  description: "The name of the plugin.",
35
35
  type: "string"
36
+ },
37
+ "_cache" => {
38
+ description: "This feature is experimental. Enable plugin caching and set a time-to-live.",
39
+ type: "object",
40
+ required: ["ttl"],
41
+ properties: {
42
+ "ttl" => {
43
+ description: "Time in seconds to keep the plugin cache.",
44
+ type: "integer",
45
+ minimum: 0
46
+ }
47
+ }
36
48
  }
37
49
  }
38
50
  }
39
51
  }.freeze
40
52
 
41
- # The following constants define the various configuration options available to Bolt.
42
- # Each constant is a hash where keys are the configuration option and values are the
43
- # option's definition. These options are used in multiple locations:
44
- #
45
- # - Automatic type validation when loading and setting configuration
46
- # - Generating reference documentation for configuration files
47
- # - Generating JSON schemas for configuration files
48
- #
49
- # Data includes keys defined by JSON Schema Draft 07 as well as some metadata used
50
- # by Bolt to generate documentation. The following keys are used:
51
- #
52
- # :description String A detailed description of the option and what it does. This
53
- # field is used in both documentation and the JSON schemas,
54
- # and should provide as much detail as possible, including
55
- # links to relevant documentation.
56
- #
57
- # :type Class The expected type of a value. These should be Ruby classes,
58
- # as this field is used to perform automatic type validation.
59
- # If an option can accept more than one type, this should be
60
- # an array of types. Boolean values should set :type to
61
- # [TrueClass, FalseClass], as Ruby does not have a single
62
- # Boolean class.
63
- #
64
- # :items Hash A definition hash for items in an array. Similar to values
65
- # for top-level options, items can have a :description, :type,
66
- # or any other key in this list.
67
- #
68
- # :uniqueItems Boolean Whether or not an array should contain only unique items.
69
- #
70
- # :properties Hash A hash where keys are sub-options and values are definitions
71
- # for the sub-option. Similar to values for top-level options,
72
- # properties can have a :description, :type, or any other key
73
- # in this list.
74
- #
75
- # :additionalProperties A variation of the :properties key, where the hash is a
76
- # Hash definition for any properties not specified in :properties.
77
- # This can be used to permit arbitrary sub-options, such as
78
- # logs for the 'log' option.
79
- #
80
- # :required Array An array of properties that are required for options that
81
- # accept Hash values.
82
- #
83
- # :minimum Integer The minimum integer value for an option.
84
- #
85
- # :enum Array An array of values that the option recognizes.
86
- #
87
- # :pattern String A JSON regex pattern that the option's vaue should match.
88
- #
89
- # :format String Requires that a string value matches a format defined by the
90
- # JSON Schema draft.
91
- #
92
- # :_plugin Boolean Whether the option accepts a plugin reference. This is used
93
- # when generating the JSON schemas to determine whether or not
94
- # to include a reference to the _plugin definition. If :_plugin
95
- # is set to true, the script that generates JSON schemas will
96
- # automatically recurse through the :items and :properties keys
97
- # and add plugin references if applicable.
98
- #
99
- # :_example Any An example value for the option. This is used to generate
100
- # reference documentation for configuration files.
101
- #
102
- # :_default Any The documented default value for the option. This is only
103
- # used to generate reference documentation for configuration
104
- # files and is not used by Bolt to actually set default values.
53
+ # Definitions used to validate config options.
54
+ # https://github.com/puppetlabs/bolt/blob/main/schemas/README.md
105
55
  OPTIONS = {
106
56
  "apply_settings" => {
57
+ description: "A map of Puppet settings to use when applying Puppet code using the `apply` "\
58
+ "plan function or the `bolt apply` command.",
59
+ type: Hash,
60
+ properties: {
61
+ "show_diff" => {
62
+ description: "Whether to log and report a contextual diff.",
63
+ type: [TrueClass, FalseClass],
64
+ _example: true,
65
+ _default: false
66
+ }
67
+ },
68
+ _plugin: false,
69
+ _deprecation: "This option will be removed in Bolt 3.0. Use `apply-settings` instead."
70
+ },
71
+ "apply-settings" => {
107
72
  description: "A map of Puppet settings to use when applying Puppet code using the `apply` "\
108
73
  "plan function or the `bolt apply` command.",
109
74
  type: Hash,
@@ -169,9 +134,26 @@ module Bolt
169
134
  "files](inventory_file_v2.md).",
170
135
  type: String,
171
136
  _plugin: false,
137
+ _deprecation: "This option will be removed in Bolt 3.0. Use the `--inventoryfile` command-line option "\
138
+ "to use a non-default inventory file or move the file contents to `inventory.yaml` in the "\
139
+ "project directory.",
172
140
  _example: "~/.puppetlabs/bolt/inventory.yaml",
173
141
  _default: "project/inventory.yaml"
174
142
  },
143
+ "plugin-cache" => {
144
+ description: "This feature is experimental. Enable plugin caching and set the time-to-live.",
145
+ type: Hash,
146
+ required: ["ttl"],
147
+ properties: {
148
+ "ttl" => {
149
+ description: "Time in seconds to keep the plugin cache.",
150
+ type: Integer,
151
+ minimum: 0
152
+ }
153
+ },
154
+ _plugin: false,
155
+ _example: { "ttl" => 3600 }
156
+ },
175
157
  "log" => {
176
158
  description: "A map of configuration for the logfile output. Under `log`, you can configure log options "\
177
159
  "for `console` and add configuration for individual log files, such as "\
@@ -183,12 +165,13 @@ module Bolt
183
165
  properties: {
184
166
  "console" => {
185
167
  description: "Configuration for logs output to the console.",
186
- type: Hash,
168
+ type: [String, Hash],
169
+ enum: ['disable'],
187
170
  properties: {
188
171
  "level" => {
189
172
  description: "The type of information to log.",
190
173
  type: String,
191
- enum: %w[trace debug error info warn fatal any],
174
+ enum: %w[trace debug error info notice warn fatal any],
192
175
  _default: "warn"
193
176
  }
194
177
  }
@@ -207,7 +190,7 @@ module Bolt
207
190
  "level" => {
208
191
  description: "The type of information to log.",
209
192
  type: String,
210
- enum: %w[trace debug error info warn fatal any],
193
+ enum: %w[trace debug error info notice warn fatal any],
211
194
  _default: "warn"
212
195
  }
213
196
  }
@@ -227,6 +210,41 @@ module Bolt
227
210
  _example: ["~/.puppetlabs/bolt/modules", "~/.puppetlabs/bolt/site-modules"],
228
211
  _default: ["project/modules", "project/site-modules", "project/site"]
229
212
  },
213
+ "module-install" => {
214
+ description: "Options that configure where Bolt downloads modules from. This option is only used when "\
215
+ "installing modules using the `bolt module add|install` commands and "\
216
+ "`Add|Install-BoltModule` cmdlets.",
217
+ type: Hash,
218
+ properties: {
219
+ "forge" => {
220
+ description: "A subsection that can have its own `proxy` setting to set an HTTP proxy for Forge "\
221
+ "operations only, and a `baseurl` setting to specify a different Forge host.",
222
+ type: Hash,
223
+ properties: {
224
+ "baseurl" => {
225
+ description: "The URL to the Forge host.",
226
+ type: String,
227
+ format: "uri",
228
+ _example: "https://forge.example.com"
229
+ },
230
+ "proxy" => {
231
+ description: "The HTTP proxy to use for Forge operations.",
232
+ type: String,
233
+ format: "uri",
234
+ _example: "https://my-forge-proxy.com:8080"
235
+ }
236
+ },
237
+ _example: { "baseurl" => "https://forge.example.com", "proxy" => "https://my-forge-proxy.com:8080" }
238
+ },
239
+ "proxy" => {
240
+ description: "The HTTP proxy to use for Git and Forge operations.",
241
+ type: String,
242
+ format: "uri",
243
+ _example: "https://my-proxy.com:8080"
244
+ }
245
+ },
246
+ _plugin: false
247
+ },
230
248
  "modules" => {
231
249
  description: "A list of module dependencies for the project. Each dependency is a map of data specifying "\
232
250
  "the module to install. To install the project's module dependencies, run the `bolt module "\
@@ -276,14 +294,14 @@ module Bolt
276
294
  },
277
295
  "name" => {
278
296
  description: "The name of the Bolt project. When this option is configured, the project is considered a "\
279
- "[Bolt project](experimental_features.md#bolt-projects), allowing Bolt to load content from "\
280
- "the project directory as though it were a module.",
297
+ "[Bolt project](projects.md), allowing Bolt to load content from the project directory "\
298
+ "as though it were a module.",
281
299
  type: String,
282
300
  _plugin: false,
283
301
  _example: "myproject"
284
302
  },
285
303
  "plans" => {
286
- description: "A list of plan names to show in `bolt plan show` output, if they exist. This option is used "\
304
+ description: "A list of plan names and glob patterns to filter the project's plans by. This option is used "\
287
305
  "to limit the visibility of plans for users of the project. For example, project authors "\
288
306
  "might want to limit the visibility of plans that are bundled with Bolt or plans that should "\
289
307
  "only be run as part of another plan. When this option is not configured, all plans are "\
@@ -291,9 +309,19 @@ module Bolt
291
309
  "list.",
292
310
  type: Array,
293
311
  _plugin: false,
294
- _example: ["myproject", "myproject::foo", "myproject::bar"]
312
+ _example: ["myproject", "myproject::foo", "myproject::bar", "myproject::deploy::*"]
295
313
  },
296
314
  "plugin_hooks" => {
315
+ description: "A map of [plugin hooks](writing_plugins.md#hooks) and which plugins a hook should use. "\
316
+ "The only configurable plugin hook is `puppet_library`, which can use two possible plugins: "\
317
+ "[`puppet_agent`](https://github.com/puppetlabs/puppetlabs-puppet_agent#puppet_agentinstall) "\
318
+ "and [`task`](using_plugins.md#task).",
319
+ type: Hash,
320
+ _plugin: true,
321
+ _example: { "puppet_library" => { "plugin" => "puppet_agent", "version" => "6.15.0", "_run_as" => "root" } },
322
+ _deprecation: "This option will be removed in Bolt 3.0. Use `plugin-hooks` instead."
323
+ },
324
+ "plugin-hooks" => {
297
325
  description: "A map of [plugin hooks](writing_plugins.md#hooks) and which plugins a hook should use. "\
298
326
  "The only configurable plugin hook is `puppet_library`, which can use two possible plugins: "\
299
327
  "[`puppet_agent`](https://github.com/puppetlabs/puppetlabs-puppet_agent#puppet_agentinstall) "\
@@ -307,7 +335,11 @@ module Bolt
307
335
  "its value is a map of configuration data. Configurable options are specified by the plugin. "\
308
336
  "Read more about configuring plugins in [Using plugins](using_plugins.md#configuring-plugins).",
309
337
  type: Hash,
310
- _plugin: true,
338
+ additionalProperties: {
339
+ type: Hash,
340
+ _plugin: true
341
+ },
342
+ _plugin: false,
311
343
  _example: { "pkcs7" => { "keysize" => 1024 } }
312
344
  },
313
345
  "puppetdb" => {
@@ -318,49 +350,57 @@ module Bolt
318
350
  "cacert" => {
319
351
  description: "The path to the ca certificate for PuppetDB.",
320
352
  type: String,
321
- _example: "/etc/puppetlabs/puppet/ssl/certs/ca.pem"
353
+ _example: "/etc/puppetlabs/puppet/ssl/certs/ca.pem",
354
+ _plugin: true
322
355
  },
323
356
  "cert" => {
324
357
  description: "The path to the client certificate file to use for authentication.",
325
358
  type: String,
326
- _example: "/etc/puppetlabs/puppet/ssl/certs/my-host.example.com.pem"
359
+ _example: "/etc/puppetlabs/puppet/ssl/certs/my-host.example.com.pem",
360
+ _plugin: true
327
361
  },
328
362
  "connect_timeout" => {
329
363
  description: "How long to wait in seconds when establishing connections with PuppetDB.",
330
364
  type: Integer,
331
365
  minimum: 1,
332
366
  _default: 60,
333
- _example: 120
367
+ _example: 120,
368
+ _plugin: true
334
369
  },
335
370
  "key" => {
336
371
  description: "The private key for the certificate.",
337
372
  type: String,
338
- _example: "/etc/puppetlabs/puppet/ssl/private_keys/my-host.example.com.pem"
373
+ _example: "/etc/puppetlabs/puppet/ssl/private_keys/my-host.example.com.pem",
374
+ _plugin: true
339
375
  },
340
376
  "read_timeout" => {
341
377
  description: "How long to wait in seconds for a response from PuppetDB.",
342
378
  type: Integer,
343
379
  minimum: 1,
344
380
  _default: 60,
345
- _example: 120
381
+ _example: 120,
382
+ _plugin: true
346
383
  },
347
384
  "server_urls" => {
348
385
  description: "An array containing the PuppetDB host to connect to. Include the protocol `https` "\
349
386
  "and the port, which is usually `8081`. For example, "\
350
387
  "`https://my-puppetdb-server.com:8081`.",
351
388
  type: Array,
352
- _example: ["https://puppet.example.com:8081"]
389
+ _example: ["https://puppet.example.com:8081"],
390
+ _plugin: true
353
391
  },
354
392
  "token" => {
355
393
  description: "The path to the PE RBAC Token.",
356
394
  type: String,
357
- _example: "~/.puppetlabs/token"
395
+ _example: "~/.puppetlabs/token",
396
+ _plugin: true
358
397
  }
359
398
  },
360
399
  _plugin: true
361
400
  },
362
401
  "puppetfile" => {
363
- description: "A map containing options for the `bolt puppetfile install` command.",
402
+ description: "A map containing options for the `bolt puppetfile install` command and "\
403
+ "`Install-BoltPuppetfile` cmdlet.",
364
404
  type: Hash,
365
405
  properties: {
366
406
  "forge" => {
@@ -375,19 +415,19 @@ module Bolt
375
415
  _example: "https://forge.example.com"
376
416
  },
377
417
  "proxy" => {
378
- description: "The HTTP proxy to use for Git and Forge operations.",
418
+ description: "The HTTP proxy to use for Forge operations.",
379
419
  type: String,
380
420
  format: "uri",
381
- _example: "https://forgeapi.example.com"
421
+ _example: "https://my-forge-proxy.com:8080"
382
422
  }
383
423
  },
384
- _example: { "baseurl" => "https://forge.example.com", "proxy" => "https://forgeapi.example.com" }
424
+ _example: { "baseurl" => "https://forge.example.com", "proxy" => "https://my-forge-proxy.com:8080" }
385
425
  },
386
426
  "proxy" => {
387
427
  description: "The HTTP proxy to use for Git and Forge operations.",
388
428
  type: String,
389
429
  format: "uri",
390
- _example: "https://forgeapi.example.com"
430
+ _example: "https://my-proxy.com:8080"
391
431
  }
392
432
  },
393
433
  _plugin: false
@@ -401,8 +441,16 @@ module Bolt
401
441
  _example: false,
402
442
  _default: true
403
443
  },
444
+ "spinner" => {
445
+ description: "Whether to print a spinner to the console for long-running Bolt operations.",
446
+ type: [TrueClass, FalseClass],
447
+ _plugin: false,
448
+ _example: false,
449
+ _default: true
450
+ },
451
+
404
452
  "tasks" => {
405
- description: "A list of task names to show in `bolt task show` output, if they exist. This option is used "\
453
+ description: "A list of task names and glob patterns to filter the project's tasks by. This option is used "\
406
454
  "to limit the visibility of tasks for users of the project. For example, project authors "\
407
455
  "might want to limit the visibility of tasks that are bundled with Bolt or plans that should "\
408
456
  "only be run as part of a larger workflow. When this option is not configured, all tasks "\
@@ -413,7 +461,7 @@ module Bolt
413
461
  type: String
414
462
  },
415
463
  _plugin: false,
416
- _example: ["myproject", "myproject::foo", "myproject::bar"]
464
+ _example: ["myproject", "myproject::foo", "myproject::bar", "myproject::deploy_*"]
417
465
  },
418
466
  "trusted-external-command" => {
419
467
  description: "The path to an executable on the Bolt controller that can produce external trusted facts. "\
@@ -435,7 +483,7 @@ module Bolt
435
483
  "specified in the URI.",
436
484
  type: String,
437
485
  enum: TRANSPORT_CONFIG.keys,
438
- _plugin: false,
486
+ _plugin: true,
439
487
  _example: "winrm",
440
488
  _default: "ssh"
441
489
  },
@@ -480,6 +528,7 @@ module Bolt
480
528
 
481
529
  # Options that are available in a bolt.yaml file
482
530
  BOLT_OPTIONS = %w[
531
+ apply-settings
483
532
  apply_settings
484
533
  color
485
534
  compile-concurrency
@@ -489,11 +538,13 @@ module Bolt
489
538
  inventoryfile
490
539
  log
491
540
  modulepath
541
+ plugin-hooks
492
542
  plugin_hooks
493
543
  plugins
494
544
  puppetdb
495
545
  puppetfile
496
546
  save-rerun
547
+ spinner
497
548
  trusted-external-command
498
549
  ].freeze
499
550
 
@@ -505,15 +556,20 @@ module Bolt
505
556
  format
506
557
  inventory-config
507
558
  log
559
+ module-install
560
+ plugin-cache
561
+ plugin-hooks
508
562
  plugin_hooks
509
563
  plugins
510
564
  puppetdb
511
565
  puppetfile
512
566
  save-rerun
567
+ spinner
513
568
  ].freeze
514
569
 
515
570
  # Options that are available in a bolt-project.yaml file
516
571
  BOLT_PROJECT_OPTIONS = %w[
572
+ apply-settings
517
573
  apply_settings
518
574
  color
519
575
  compile-concurrency
@@ -523,14 +579,18 @@ module Bolt
523
579
  inventoryfile
524
580
  log
525
581
  modulepath
582
+ module-install
526
583
  modules
527
584
  name
528
585
  plans
586
+ plugin-cache
587
+ plugin-hooks
529
588
  plugin_hooks
530
589
  plugins
531
590
  puppetdb
532
591
  puppetfile
533
592
  save-rerun
593
+ spinner
534
594
  tasks
535
595
  trusted-external-command
536
596
  ].freeze