bolt 2.22.0 → 2.26.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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/Puppetfile +1 -1
  3. data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +2 -1
  4. data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +1 -1
  5. data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +12 -6
  6. data/bolt-modules/dir/lib/puppet/functions/dir/children.rb +1 -1
  7. data/bolt-modules/out/lib/puppet/functions/out/message.rb +1 -1
  8. data/exe/bolt +1 -0
  9. data/guides/inventory.txt +19 -0
  10. data/guides/project.txt +22 -0
  11. data/lib/bolt/analytics.rb +8 -8
  12. data/lib/bolt/applicator.rb +6 -6
  13. data/lib/bolt/bolt_option_parser.rb +47 -24
  14. data/lib/bolt/catalog.rb +4 -2
  15. data/lib/bolt/cli.rb +97 -78
  16. data/lib/bolt/config.rb +46 -24
  17. data/lib/bolt/config/options.rb +9 -6
  18. data/lib/bolt/executor.rb +10 -8
  19. data/lib/bolt/inventory.rb +8 -1
  20. data/lib/bolt/inventory/group.rb +4 -4
  21. data/lib/bolt/inventory/inventory.rb +1 -1
  22. data/lib/bolt/inventory/target.rb +1 -1
  23. data/lib/bolt/logger.rb +12 -6
  24. data/lib/bolt/outputter.rb +56 -0
  25. data/lib/bolt/outputter/human.rb +10 -9
  26. data/lib/bolt/outputter/json.rb +11 -4
  27. data/lib/bolt/outputter/logger.rb +3 -3
  28. data/lib/bolt/outputter/rainbow.rb +15 -0
  29. data/lib/bolt/pal.rb +9 -19
  30. data/lib/bolt/pal/yaml_plan/evaluator.rb +2 -2
  31. data/lib/bolt/pal/yaml_plan/transpiler.rb +11 -3
  32. data/lib/bolt/plugin/prompt.rb +3 -3
  33. data/lib/bolt/plugin/puppetdb.rb +1 -1
  34. data/lib/bolt/project.rb +32 -19
  35. data/lib/bolt/project_migrate.rb +138 -0
  36. data/lib/bolt/puppetdb/client.rb +1 -1
  37. data/lib/bolt/puppetdb/config.rb +1 -1
  38. data/lib/bolt/r10k_log_proxy.rb +1 -1
  39. data/lib/bolt/rerun.rb +1 -1
  40. data/lib/bolt/result.rb +8 -0
  41. data/lib/bolt/shell.rb +1 -1
  42. data/lib/bolt/shell/bash.rb +7 -7
  43. data/lib/bolt/task.rb +1 -1
  44. data/lib/bolt/transport/base.rb +1 -1
  45. data/lib/bolt/transport/docker/connection.rb +10 -10
  46. data/lib/bolt/transport/local/connection.rb +3 -3
  47. data/lib/bolt/transport/orch.rb +3 -3
  48. data/lib/bolt/transport/ssh.rb +1 -1
  49. data/lib/bolt/transport/ssh/connection.rb +6 -6
  50. data/lib/bolt/transport/ssh/exec_connection.rb +5 -5
  51. data/lib/bolt/transport/winrm.rb +1 -1
  52. data/lib/bolt/transport/winrm/connection.rb +9 -9
  53. data/lib/bolt/util.rb +2 -2
  54. data/lib/bolt/util/puppet_log_level.rb +4 -3
  55. data/lib/bolt/version.rb +1 -1
  56. data/lib/bolt_server/base_config.rb +1 -1
  57. data/lib/bolt_server/file_cache.rb +1 -1
  58. data/lib/bolt_server/pe/pal.rb +1 -1
  59. data/lib/bolt_server/transport_app.rb +76 -0
  60. data/lib/bolt_spec/plans.rb +1 -1
  61. data/lib/bolt_spec/plans/action_stubs.rb +1 -1
  62. data/lib/bolt_spec/run.rb +3 -0
  63. data/libexec/apply_catalog.rb +2 -2
  64. data/libexec/bolt_catalog +1 -1
  65. data/libexec/custom_facts.rb +1 -1
  66. data/libexec/query_resources.rb +1 -1
  67. metadata +9 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60e995704052fee2778474c532df844e51ca0888017e28c883866e6b61a9678f
4
- data.tar.gz: 8133b33137d67ba8880270f4ed20aa8346e13b2aa7ae2b0c390e3fbbba660172
3
+ metadata.gz: 195c9ad94788e4811c9a90accb11515fc707346106827e15ef71995b016efbcc
4
+ data.tar.gz: 7259f2a7b9af58dab4b4f8224360fe8f1570e042c43b6becb183a0dd1257d91e
5
5
  SHA512:
6
- metadata.gz: a057aebe5bd7ce01a8369f3c7a05371f0dab79143cd465f6bd2f0a0ad23fe897fcff6624d03f07ead07b86c888512166232182c294cd1188fcd8fb45b55f463d
7
- data.tar.gz: 4c30348d86636398f25568dcd77af25e6eb8e54af5c9ce44125a110b8089c15415a4a051aa8aac066f7404f9ca7faf253dd69e350780ef8d24e34f385c1dd8de
6
+ metadata.gz: 2092172d760e7a806e865a3a1315ec2687cff1835b8b44addec9de208711a16be2193ff570a9cae65a620b6d9203575ccb64c2798c71509dd2fc1a0d41ca3399
7
+ data.tar.gz: 77828dd923626abe08c0bbf8ef0f30175462aab55a8584127359dde412f37b17d7cd952a4bd1be2ce115f47db4f8d6f4269eb455f063ff01ee1297a4637c03c8
data/Puppetfile CHANGED
@@ -6,7 +6,7 @@ moduledir File.join(File.dirname(__FILE__), 'modules')
6
6
 
7
7
  # Core modules used by 'apply'
8
8
  mod 'puppetlabs-service', '1.3.0'
9
- mod 'puppetlabs-puppet_agent', '3.2.0'
9
+ mod 'puppetlabs-puppet_agent', '4.1.1'
10
10
  mod 'puppetlabs-facts', '1.0.0'
11
11
 
12
12
  # Core types and providers for Puppet 6
@@ -9,11 +9,12 @@ Puppet::DataTypes.create_type('Result') do
9
9
  functions => {
10
10
  error => Callable[[], Optional[Error]],
11
11
  message => Callable[[], Optional[String]],
12
+ sensitive => Callable[[], Optional[Sensitive[Data]]],
12
13
  action => Callable[[], String],
13
14
  status => Callable[[], String],
14
15
  to_data => Callable[[], Hash],
15
16
  ok => Callable[[], Boolean],
16
- '[]' => Callable[[String[1]], Data]
17
+ '[]' => Callable[[String[1]], Variant[Data, Sensitive[Data]]]
17
18
  }
18
19
  PUPPET
19
20
 
@@ -96,7 +96,7 @@ Puppet::Functions.create_function(:download_file, Puppet::Functions::InternalFun
96
96
 
97
97
  # Paths expand relative to the default downloads directory for the project
98
98
  # e.g. ~/.puppetlabs/bolt/downloads/
99
- destination = Puppet.lookup(:bolt_project_data).downloads + destination
99
+ destination = Puppet.lookup(:bolt_project).downloads + destination
100
100
 
101
101
  # If the destination directory already exists, delete any existing contents
102
102
  if Dir.exist?(destination)
@@ -4,30 +4,36 @@
4
4
  Puppet::Functions.create_function(:'ctrl::do_until') do
5
5
  # @param options A hash of additional options.
6
6
  # @option options [Numeric] limit The number of times to repeat the block.
7
+ # @option options [Numeric] interval The number of seconds to wait before repeating the block.
7
8
  # @example Run a task until it succeeds
8
9
  # ctrl::do_until() || {
9
- # run_task('test', $target, _catch_errors => true).ok()
10
+ # run_task('test', $target, '_catch_errors' => true).ok()
10
11
  # }
11
- #
12
12
  # @example Run a task until it succeeds or fails 10 times
13
13
  # ctrl::do_until('limit' => 10) || {
14
- # run_task('test', $target, _catch_errors => true).ok()
14
+ # run_task('test', $target, '_catch_errors' => true).ok()
15
+ # }
16
+ # @example Run a task and wait 10 seconds before running it again
17
+ # ctrl::do_until('interval' => 10) || {
18
+ # run_task('test', $target, '_catch_errors' => true).ok()
15
19
  # }
16
- #
17
20
  dispatch :do_until do
18
21
  optional_param 'Hash[String[1], Any]', :options
19
22
  block_param
20
23
  end
21
24
 
22
- def do_until(options = { 'limit' => 0 })
25
+ def do_until(options = {})
23
26
  # Send Analytics Report
24
27
  Puppet.lookup(:bolt_executor) {}&.report_function_call(self.class.name)
25
28
 
26
- limit = options['limit']
29
+ limit = options['limit'] || 0
30
+ interval = options['interval']
31
+
27
32
  i = 0
28
33
  until (x = yield)
29
34
  i += 1
30
35
  break if limit != 0 && i >= limit
36
+ Kernel.sleep(interval) if interval
31
37
  end
32
38
  x
33
39
  end
@@ -25,7 +25,7 @@ Puppet::Functions.create_function(:'dir::children', Puppet::Functions::InternalF
25
25
  full_mod_path = File.join(mod_path, subpath || '') if mod_path
26
26
 
27
27
  # Expand relative to the project directory if path is relative
28
- project = Puppet.lookup(:bolt_project_data)
28
+ project = Puppet.lookup(:bolt_project)
29
29
  pathname = Pathname.new(dirname)
30
30
  full_dir = pathname.absolute? ? dirname : File.expand_path(File.join(project.path, dirname))
31
31
 
@@ -12,7 +12,7 @@ Puppet::Functions.create_function(:'out::message') do
12
12
  # @example Print a message
13
13
  # out::message('Something went wrong')
14
14
  dispatch :output_message do
15
- param 'String', :message
15
+ param 'Any', :message
16
16
  return_type 'Undef'
17
17
  end
18
18
 
data/exe/bolt CHANGED
@@ -4,6 +4,7 @@
4
4
  require 'bolt'
5
5
  require 'bolt/cli'
6
6
 
7
+ Thread.current[:name] ||= 'main'
7
8
  cli = Bolt::CLI.new(ARGV)
8
9
  begin
9
10
  opts = cli.parse
@@ -0,0 +1,19 @@
1
+ TOPIC
2
+ inventory
3
+
4
+ DESCRIPTION
5
+ The inventory describes the targets that you run Bolt commands on, along
6
+ with any data and configuration for the targets. Targets in an inventory can
7
+ belong to one or more groups, allowing you to share data and configuration
8
+ across multiple targets and to specify multiple targets for your Bolt
9
+ commands without the need to list each target individually.
10
+
11
+ In most cases, Bolt loads the inventory from an inventory file in your Bolt
12
+ project. The inventory file is a YAML file named 'inventory.yaml'. Because
13
+ Bolt loads the inventory file from a Bolt project, you must have an existing
14
+ project configuration file named 'bolt-project.yaml' alongside the inventory
15
+ file.
16
+
17
+ DOCUMENTATION
18
+ https://pup.pt/bolt-inventory
19
+ https://pup.pt/bolt-inventory-reference
@@ -0,0 +1,22 @@
1
+ TOPIC
2
+ project
3
+
4
+ DESCRIPTION
5
+ A Bolt project is a directory that serves as the launching point for Bolt
6
+ and allows you to create a shareable orchestration application. Projects
7
+ typically include a project configuration file, an inventory file, and any
8
+ content you use in your project workflow, such as tasks and plans.
9
+
10
+ When you run Bolt, it runs in the context of a project. If the directory you
11
+ run Bolt from is not a project, Bolt attempts to find a project by
12
+ traversing the parent directories. If Bolt is unable to find a project, it
13
+ runs from the default project, located at '~/.puppetlabs/bolt'.
14
+
15
+ A directory is only considered a Bolt project when it has a project
16
+ configuration file named 'bolt-project.yaml'. Bolt doesn't load project data
17
+ and content, including inventory files, unless the data and content are part
18
+ of a project.
19
+
20
+ DOCUMENTATION
21
+ https://pup.pt/bolt-projects
22
+ https://pup.pt/bolt-project-reference
@@ -27,7 +27,7 @@ module Bolt
27
27
  }.freeze
28
28
 
29
29
  def self.build_client
30
- logger = Logging.logger[self]
30
+ logger = Bolt::Logger.logger(self)
31
31
  begin
32
32
  config_file = config_path(logger)
33
33
  config = load_config(config_file, logger)
@@ -72,7 +72,7 @@ module Bolt
72
72
 
73
73
  def self.load_config(filename, logger)
74
74
  if File.exist?(filename)
75
- YAML.load_file(filename)
75
+ Bolt::Util.read_optional_yaml_hash(filename, 'analytics')
76
76
  else
77
77
  unless ENV['BOLT_DISABLE_ANALYTICS']
78
78
  logger.warn <<~ANALYTICS
@@ -106,7 +106,7 @@ module Bolt
106
106
  require 'httpclient'
107
107
  require 'locale'
108
108
 
109
- @logger = Logging.logger[self]
109
+ @logger = Bolt::Logger.logger(self)
110
110
  @http = HTTPClient.new
111
111
  @user_id = user_id
112
112
  @executor = Concurrent.global_io_executor
@@ -161,9 +161,9 @@ module Bolt
161
161
  # Handle analytics submission in the background to avoid blocking the
162
162
  # app or polluting the log with errors
163
163
  Concurrent::Future.execute(executor: @executor) do
164
- @logger.debug "Submitting analytics: #{JSON.pretty_generate(params)}"
164
+ @logger.trace "Submitting analytics: #{JSON.pretty_generate(params)}"
165
165
  @http.post(TRACKING_URL, params)
166
- @logger.debug "Completed analytics submission"
166
+ @logger.trace "Completed analytics submission"
167
167
  end
168
168
  end
169
169
 
@@ -210,18 +210,18 @@ module Bolt
210
210
  attr_accessor :bundled_content
211
211
 
212
212
  def initialize
213
- @logger = Logging.logger[self]
213
+ @logger = Bolt::Logger.logger(self)
214
214
  @bundled_content = []
215
215
  end
216
216
 
217
217
  def screen_view(screen, **_kwargs)
218
- @logger.debug "Skipping submission of '#{screen}' screenview because analytics is disabled"
218
+ @logger.trace "Skipping submission of '#{screen}' screenview because analytics is disabled"
219
219
  end
220
220
 
221
221
  def report_bundled_content(mode, name); end
222
222
 
223
223
  def event(category, action, **_kwargs)
224
- @logger.debug "Skipping submission of '#{category} #{action}' event because analytics is disabled"
224
+ @logger.trace "Skipping submission of '#{category} #{action}' event because analytics is disabled"
225
225
  end
226
226
 
227
227
  def finish; end
@@ -27,8 +27,8 @@ module Bolt
27
27
  @hiera_config = hiera_config ? validate_hiera_config(hiera_config) : nil
28
28
  @apply_settings = apply_settings || {}
29
29
 
30
- @pool = Concurrent::ThreadPoolExecutor.new(max_threads: max_compiles)
31
- @logger = Logging.logger[self]
30
+ @pool = Concurrent::ThreadPoolExecutor.new(name: 'apply', max_threads: max_compiles)
31
+ @logger = Bolt::Logger.logger(self)
32
32
  end
33
33
 
34
34
  private def libexec
@@ -183,11 +183,10 @@ module Bolt
183
183
  type_by_reference: true,
184
184
  local_reference: true)
185
185
 
186
- bolt_project = @project if @project&.name
187
186
  scope = {
188
187
  code_ast: ast,
189
188
  modulepath: @modulepath,
190
- project: bolt_project.to_h,
189
+ project: @project.to_h,
191
190
  pdb_config: @pdb_client.config.to_hash,
192
191
  hiera_config: @hiera_config,
193
192
  plan_vars: plan_vars,
@@ -217,6 +216,7 @@ module Bolt
217
216
  r = @executor.log_action(description, targets) do
218
217
  futures = targets.map do |target|
219
218
  Concurrent::Future.execute(executor: @pool) do
219
+ Thread.current[:name] ||= Thread.current.name
220
220
  @executor.with_node_logging("Compiling manifest block", [target]) do
221
221
  compile(target, scope)
222
222
  end
@@ -300,7 +300,7 @@ module Bolt
300
300
 
301
301
  files.each do |file|
302
302
  tar_path = Pathname.new(file).relative_path_from(parent)
303
- @logger.debug("Packing plugin #{file} to #{tar_path}")
303
+ @logger.trace("Packing plugin #{file} to #{tar_path}")
304
304
  stat = File.stat(file)
305
305
  content = File.binread(file)
306
306
  output.tar.add_file_simple(
@@ -314,7 +314,7 @@ module Bolt
314
314
  end
315
315
 
316
316
  duration = Time.now - start_time
317
- @logger.debug("Packed plugins in #{duration * 1000} ms")
317
+ @logger.trace("Packed plugins in #{duration * 1000} ms")
318
318
 
319
319
  output.close
320
320
  Base64.encode64(sio.string)
@@ -61,6 +61,9 @@ module Bolt
61
61
  { flags: OPTIONS[:global],
62
62
  banner: GROUP_HELP }
63
63
  end
64
+ when 'guide'
65
+ { flags: OPTIONS[:global] + %w[format],
66
+ banner: GUIDE_HELP }
64
67
  when 'plan'
65
68
  case action
66
69
  when 'convert'
@@ -85,7 +88,7 @@ module Bolt
85
88
  { flags: OPTIONS[:global] + %w[modules],
86
89
  banner: PROJECT_INIT_HELP }
87
90
  when 'migrate'
88
- { flags: OPTIONS[:global] + %w[inventoryfile boltdir configfile],
91
+ { flags: OPTIONS[:global] + %w[inventoryfile project configfile],
89
92
  banner: PROJECT_MIGRATE_HELP }
90
93
  else
91
94
  { flags: OPTIONS[:global],
@@ -164,6 +167,7 @@ module Bolt
164
167
  command Run a command remotely
165
168
  file Copy files between the controller and targets
166
169
  group Show the list of groups in the inventory
170
+ guide View guides for Bolt concepts and features
167
171
  inventory Show the list of targets an action would run on
168
172
  plan Convert, create, show, and run Bolt plans
169
173
  project Create and migrate Bolt projects
@@ -171,6 +175,9 @@ module Bolt
171
175
  script Upload a local script and run it remotely
172
176
  secret Create encryption keys and encrypt and decrypt values
173
177
  task Show and run Bolt tasks
178
+
179
+ GUIDES
180
+ For a list of guides on Bolt's concepts and features, run 'bolt guide'.
174
181
  HELP
175
182
 
176
183
  APPLY_HELP = <<~HELP
@@ -289,6 +296,26 @@ module Bolt
289
296
  Show the list of groups in the inventory.
290
297
  HELP
291
298
 
299
+ GUIDE_HELP = <<~HELP
300
+ NAME
301
+ guide
302
+
303
+ USAGE
304
+ bolt guide [topic] [options]
305
+
306
+ DESCRIPTION
307
+ View guides for Bolt's concepts and features.
308
+
309
+ Omitting a topic will display a list of available guides,
310
+ while providing a topic will display the relevant guide.
311
+
312
+ EXAMPLES
313
+ View a list of available guides
314
+ bolt guide
315
+ View the 'project' guide page
316
+ bolt guide project
317
+ HELP
318
+
292
319
  INVENTORY_HELP = <<~HELP
293
320
  NAME
294
321
  inventory
@@ -339,11 +366,11 @@ module Bolt
339
366
  bolt plan convert <path> [options]
340
367
 
341
368
  DESCRIPTION
342
- Convert a YAML plan to a Bolt plan.
369
+ Convert a YAML plan to a Puppet language plan and print the converted plan to stdout.
343
370
 
344
371
  Converting a YAML plan may result in a plan that is syntactically
345
372
  correct but has different behavior. Always verify a converted plan's
346
- functionality.
373
+ functionality. Note that the converted plan is not written to a file.
347
374
 
348
375
  EXAMPLES
349
376
  bolt plan convert path/to/plan/myplan.yaml
@@ -394,9 +421,9 @@ module Bolt
394
421
  the plan, including a list of available parameters.
395
422
 
396
423
  EXAMPLES
397
- Display a list of available tasks
424
+ Display a list of available plans
398
425
  bolt plan show
399
- Display documentation for the canary task
426
+ Display documentation for the aggregate::count plan
400
427
  bolt plan show aggregate::count
401
428
  HELP
402
429
 
@@ -420,19 +447,18 @@ module Bolt
420
447
  init
421
448
 
422
449
  USAGE
423
- bolt project init [directory] [options]
450
+ bolt project init [name] [options]
424
451
 
425
452
  DESCRIPTION
426
- Create a new Bolt project.
453
+ Create a new Bolt project in the current working directory.
427
454
 
428
- Specify a directory to create a Bolt project in. Defaults to the
429
- curent working directory.
455
+ Specify a name for the Bolt project. Defaults to the basename of the current working directory.
430
456
 
431
457
  EXAMPLES
432
- Create a new Bolt project in the current working directory.
458
+ Create a new Bolt project using the directory as the project name.
433
459
  bolt project init
434
- Create a new Bolt project at a specified path.
435
- bolt project init ~/path/to/project
460
+ Create a new Bolt project with a specified name.
461
+ bolt project init myproject
436
462
  Create a new Bolt project with existing modules.
437
463
  bolt project init --modules puppetlabs-apt,puppetlabs-ntp
438
464
  HELP
@@ -445,10 +471,7 @@ module Bolt
445
471
  bolt project migrate [options]
446
472
 
447
473
  DESCRIPTION
448
- Migrate a Bolt project to the latest version.
449
-
450
- Loads a Bolt project's inventory file and migrates it to the latest version. The
451
- inventory file is modified in place and will not preserve comments or formatting.
474
+ Migrate a Bolt project to use current best practices and the latest version of configuration files.
452
475
  HELP
453
476
 
454
477
  PUPPETFILE_HELP = <<~HELP
@@ -694,9 +717,9 @@ module Bolt
694
717
  @options[:password] = password
695
718
  end
696
719
  define('--password-prompt', 'Prompt for user to input password') do |_password|
697
- STDERR.print "Please enter your password: "
698
- @options[:password] = STDIN.noecho(&:gets).chomp
699
- STDERR.puts
720
+ $stderr.print "Please enter your password: "
721
+ @options[:password] = $stdin.noecho(&:gets).chomp
722
+ $stderr.puts
700
723
  end
701
724
  define('--private-key KEY', 'Path to private ssh key to authenticate with') do |key|
702
725
  @options[:'private-key'] = File.expand_path(key)
@@ -720,9 +743,9 @@ module Bolt
720
743
  @options[:'sudo-password'] = password
721
744
  end
722
745
  define('--sudo-password-prompt', 'Prompt for user to input escalation password') do |_password|
723
- STDERR.print "Please enter your privilege escalation password: "
724
- @options[:'sudo-password'] = STDIN.noecho(&:gets).chomp
725
- STDERR.puts
746
+ $stderr.print "Please enter your privilege escalation password: "
747
+ @options[:'sudo-password'] = $stdin.noecho(&:gets).chomp
748
+ $stderr.puts
726
749
  end
727
750
  define('--sudo-executable EXEC', "Specify an executable for running as another user.",
728
751
  "This option is experimental.") do |exec|
@@ -864,7 +887,7 @@ module Bolt
864
887
  end
865
888
  define('--log-level LEVEL',
866
889
  "Set the log level for the console. Available options are",
867
- "debug, info, notice, warn, error, fatal, any.") do |level|
890
+ "trace, debug, info, warn, error, fatal, any.") do |level|
868
891
  @options[:log] = { 'console' => { 'level' => level } }
869
892
  end
870
893
  define('--plugin PLUGIN', 'Select the plugin to use') do |plug|
@@ -905,7 +928,7 @@ module Bolt
905
928
  file = value.sub(/^@/, '')
906
929
  read_arg_file(file)
907
930
  elsif value == '-'
908
- STDIN.read
931
+ $stdin.read
909
932
  else
910
933
  value
911
934
  end
@@ -57,8 +57,10 @@ module Bolt
57
57
 
58
58
  def compile_catalog(request)
59
59
  pdb_client = Bolt::PuppetDB::Client.new(Bolt::PuppetDB::Config.new(request['pdb_config']))
60
- project = request['project'] || {}
61
- bolt_project = Struct.new(:name, :path).new(project['name'], project['path']) unless project.empty?
60
+ project = request['project']
61
+ bolt_project = Struct.new(:name, :path, :load_as_module?).new(project['name'],
62
+ project['path'],
63
+ project['load_as_module?'])
62
64
  inv = Bolt::ApplyInventory.new(request['config'])
63
65
  puppet_overrides = {
64
66
  bolt_pdb_client: pdb_client,