bolt 0.11.0 → 0.12.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 (165) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bolt/cli.rb +127 -31
  3. data/lib/bolt/config.rb +39 -6
  4. data/lib/bolt/execution_result.rb +109 -0
  5. data/lib/bolt/executor.rb +4 -1
  6. data/lib/bolt/node.rb +6 -1
  7. data/lib/bolt/node/orch.rb +20 -2
  8. data/lib/bolt/node/winrm.rb +22 -10
  9. data/lib/bolt/node_uri.rb +5 -7
  10. data/lib/bolt/outputter/human.rb +60 -1
  11. data/lib/bolt/outputter/json.rb +11 -0
  12. data/lib/bolt/target.rb +32 -0
  13. data/lib/bolt/version.rb +1 -1
  14. data/modules/boltlib/lib/puppet/datatypes/executionresult.rb +30 -0
  15. data/modules/boltlib/lib/puppet/datatypes/target.rb +12 -0
  16. data/modules/boltlib/lib/puppet/functions/file_upload.rb +3 -3
  17. data/modules/boltlib/lib/puppet/functions/run_command.rb +3 -3
  18. data/modules/boltlib/lib/puppet/functions/run_script.rb +3 -3
  19. data/modules/boltlib/lib/puppet/functions/run_task.rb +10 -2
  20. data/vendored/puppet/lib/puppet/application/describe.rb +0 -1
  21. data/vendored/puppet/lib/puppet/configurer.rb +1 -1
  22. data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +15 -9
  23. data/vendored/puppet/lib/puppet/datatypes.rb +213 -0
  24. data/vendored/puppet/lib/puppet/datatypes/error.rb +19 -0
  25. data/vendored/puppet/lib/puppet/datatypes/impl/error.rb +42 -0
  26. data/vendored/puppet/lib/puppet/error.rb +1 -1
  27. data/vendored/puppet/lib/puppet/face/catalog.rb +1 -1
  28. data/vendored/puppet/lib/puppet/face/epp.rb +3 -3
  29. data/vendored/puppet/lib/puppet/face/help.rb +12 -14
  30. data/vendored/puppet/lib/puppet/face/man.rb +1 -0
  31. data/vendored/puppet/lib/puppet/face/module/search.rb +1 -1
  32. data/vendored/puppet/lib/puppet/face/node.rb +1 -0
  33. data/vendored/puppet/lib/puppet/face/parser.rb +0 -1
  34. data/vendored/puppet/lib/puppet/face/status.rb +1 -0
  35. data/vendored/puppet/lib/puppet/feature/base.rb +1 -1
  36. data/vendored/puppet/lib/puppet/file_bucket/dipper.rb +0 -1
  37. data/vendored/puppet/lib/puppet/file_system/uniquefile.rb +2 -2
  38. data/vendored/puppet/lib/puppet/forge/errors.rb +21 -29
  39. data/vendored/puppet/lib/puppet/functions.rb +64 -84
  40. data/vendored/puppet/lib/puppet/functions/defined.rb +0 -3
  41. data/vendored/puppet/lib/puppet/functions/find_file.rb +0 -1
  42. data/vendored/puppet/lib/puppet/functions/map.rb +0 -1
  43. data/vendored/puppet/lib/puppet/functions/regsubst.rb +1 -1
  44. data/vendored/puppet/lib/puppet/graph/simple_graph.rb +6 -10
  45. data/vendored/puppet/lib/puppet/indirector/catalog/compiler.rb +37 -25
  46. data/vendored/puppet/lib/puppet/indirector/file_server.rb +1 -1
  47. data/vendored/puppet/lib/puppet/indirector/indirection.rb +0 -2
  48. data/vendored/puppet/lib/puppet/indirector/rest.rb +9 -8
  49. data/vendored/puppet/lib/puppet/info_service/class_information_service.rb +1 -1
  50. data/vendored/puppet/lib/puppet/interface/option_manager.rb +1 -1
  51. data/vendored/puppet/lib/puppet/loaders.rb +1 -0
  52. data/vendored/puppet/lib/puppet/module.rb +6 -2
  53. data/vendored/puppet/lib/puppet/module_tool/applications/unpacker.rb +1 -1
  54. data/vendored/puppet/lib/puppet/module_tool/errors/installer.rb +29 -41
  55. data/vendored/puppet/lib/puppet/module_tool/errors/shared.rb +63 -138
  56. data/vendored/puppet/lib/puppet/module_tool/errors/uninstaller.rb +15 -37
  57. data/vendored/puppet/lib/puppet/module_tool/errors/upgrader.rb +18 -30
  58. data/vendored/puppet/lib/puppet/module_tool/installed_modules.rb +1 -1
  59. data/vendored/puppet/lib/puppet/module_tool/metadata.rb +0 -1
  60. data/vendored/puppet/lib/puppet/network/http/api/indirected_routes.rb +1 -1
  61. data/vendored/puppet/lib/puppet/network/rights.rb +1 -1
  62. data/vendored/puppet/lib/puppet/node.rb +1 -1
  63. data/vendored/puppet/lib/puppet/node/environment.rb +1 -1
  64. data/vendored/puppet/lib/puppet/parameter/value_collection.rb +4 -17
  65. data/vendored/puppet/lib/puppet/parser/compiler.rb +1 -0
  66. data/vendored/puppet/lib/puppet/parser/functions.rb +0 -1
  67. data/vendored/puppet/lib/puppet/parser/functions/scanf.rb +1 -1
  68. data/vendored/puppet/lib/puppet/parser/scope.rb +4 -3
  69. data/vendored/puppet/lib/puppet/parser/script_compiler.rb +1 -0
  70. data/vendored/puppet/lib/puppet/parser/templatewrapper.rb +3 -2
  71. data/vendored/puppet/lib/puppet/parser/type_loader.rb +1 -1
  72. data/vendored/puppet/lib/puppet/pops.rb +1 -0
  73. data/vendored/puppet/lib/puppet/pops/evaluator/access_operator.rb +3 -2
  74. data/vendored/puppet/lib/puppet/pops/evaluator/closure.rb +1 -1
  75. data/vendored/puppet/lib/puppet/pops/evaluator/evaluator_impl.rb +2 -2
  76. data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +6 -5
  77. data/vendored/puppet/lib/puppet/pops/functions/function.rb +2 -2
  78. data/vendored/puppet/lib/puppet/pops/loader/loader.rb +1 -1
  79. data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +40 -4
  80. data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +6 -2
  81. data/vendored/puppet/lib/puppet/pops/loader/puppet_resource_type_impl_instantiator.rb +8 -8
  82. data/vendored/puppet/lib/puppet/pops/loader/ruby_data_type_instantiator.rb +40 -0
  83. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +6 -26
  84. data/vendored/puppet/lib/puppet/pops/loaders.rb +11 -2
  85. data/vendored/puppet/lib/puppet/pops/lookup/data_dig_function_provider.rb +1 -1
  86. data/vendored/puppet/lib/puppet/pops/lookup/lookup_adapter.rb +4 -14
  87. data/vendored/puppet/lib/puppet/pops/model/model_tree_dumper.rb +1 -1
  88. data/vendored/puppet/lib/puppet/pops/parser/code_merger.rb +2 -2
  89. data/vendored/puppet/lib/puppet/pops/parser/eparser.rb +1471 -1501
  90. data/vendored/puppet/lib/puppet/pops/parser/epp_support.rb +0 -2
  91. data/vendored/puppet/lib/puppet/pops/parser/evaluating_parser.rb +1 -1
  92. data/vendored/puppet/lib/puppet/pops/parser/interpolation_support.rb +1 -1
  93. data/vendored/puppet/lib/puppet/pops/parser/lexer2.rb +2 -26
  94. data/vendored/puppet/lib/puppet/pops/parser/locator.rb +5 -7
  95. data/vendored/puppet/lib/puppet/pops/parser/parser_support.rb +2 -2
  96. data/vendored/puppet/lib/puppet/pops/parser/slurp_support.rb +0 -3
  97. data/vendored/puppet/lib/puppet/pops/pcore.rb +0 -11
  98. data/vendored/puppet/lib/puppet/pops/serialization/object.rb +3 -4
  99. data/vendored/puppet/lib/puppet/pops/serialization/to_data_converter.rb +1 -1
  100. data/vendored/puppet/lib/puppet/pops/time/timespan.rb +1 -1
  101. data/vendored/puppet/lib/puppet/pops/types/iterable.rb +14 -7
  102. data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +38 -7
  103. data/vendored/puppet/lib/puppet/pops/types/p_object_type_extension.rb +21 -22
  104. data/vendored/puppet/lib/puppet/pops/types/p_sem_ver_range_type.rb +0 -1
  105. data/vendored/puppet/lib/puppet/pops/types/p_type_set_type.rb +0 -1
  106. data/vendored/puppet/lib/puppet/pops/types/p_uri_type.rb +0 -1
  107. data/vendored/puppet/lib/puppet/pops/types/puppet_object.rb +1 -1
  108. data/vendored/puppet/lib/puppet/pops/types/string_converter.rb +5 -1
  109. data/vendored/puppet/lib/puppet/pops/types/type_calculator.rb +5 -1
  110. data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +1 -5
  111. data/vendored/puppet/lib/puppet/pops/types/type_formatter.rb +21 -0
  112. data/vendored/puppet/lib/puppet/pops/types/types.rb +2 -7
  113. data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +1 -3
  114. data/vendored/puppet/lib/puppet/property.rb +1 -1
  115. data/vendored/puppet/lib/puppet/provider/augeas/augeas.rb +3 -4
  116. data/vendored/puppet/lib/puppet/provider/exec.rb +0 -2
  117. data/vendored/puppet/lib/puppet/provider/nameservice.rb +6 -1
  118. data/vendored/puppet/lib/puppet/provider/nameservice/directoryservice.rb +3 -3
  119. data/vendored/puppet/lib/puppet/provider/package/appdmg.rb +0 -1
  120. data/vendored/puppet/lib/puppet/provider/package/apple.rb +0 -1
  121. data/vendored/puppet/lib/puppet/provider/package/macports.rb +2 -2
  122. data/vendored/puppet/lib/puppet/provider/package/pkgdmg.rb +0 -1
  123. data/vendored/puppet/lib/puppet/provider/package/portage.rb +0 -1
  124. data/vendored/puppet/lib/puppet/provider/package/zypper.rb +2 -2
  125. data/vendored/puppet/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +2 -2
  126. data/vendored/puppet/lib/puppet/provider/service/init.rb +1 -0
  127. data/vendored/puppet/lib/puppet/provider/service/launchd.rb +3 -3
  128. data/vendored/puppet/lib/puppet/provider/user/aix.rb +1 -1
  129. data/vendored/puppet/lib/puppet/provider/user/openbsd.rb +1 -1
  130. data/vendored/puppet/lib/puppet/provider/user/pw.rb +1 -1
  131. data/vendored/puppet/lib/puppet/provider/yumrepo/inifile.rb +2 -4
  132. data/vendored/puppet/lib/puppet/provider/zfs/zfs.rb +1 -1
  133. data/vendored/puppet/lib/puppet/provider/zpool/zpool.rb +1 -1
  134. data/vendored/puppet/lib/puppet/reference/type.rb +0 -1
  135. data/vendored/puppet/lib/puppet/resource.rb +1 -2
  136. data/vendored/puppet/lib/puppet/resource/status.rb +0 -1
  137. data/vendored/puppet/lib/puppet/resource/type.rb +3 -3
  138. data/vendored/puppet/lib/puppet/resource/type_collection.rb +1 -1
  139. data/vendored/puppet/lib/puppet/settings/environment_conf.rb +0 -1
  140. data/vendored/puppet/lib/puppet/ssl/host.rb +1 -1
  141. data/vendored/puppet/lib/puppet/syntax_checkers/base64.rb +1 -1
  142. data/vendored/puppet/lib/puppet/transaction/persistence.rb +1 -1
  143. data/vendored/puppet/lib/puppet/type.rb +17 -4
  144. data/vendored/puppet/lib/puppet/type/file.rb +3 -3
  145. data/vendored/puppet/lib/puppet/type/mount.rb +9 -0
  146. data/vendored/puppet/lib/puppet/type/schedule.rb +25 -13
  147. data/vendored/puppet/lib/puppet/type/tidy.rb +2 -2
  148. data/vendored/puppet/lib/puppet/type/user.rb +1 -1
  149. data/vendored/puppet/lib/puppet/util.rb +19 -14
  150. data/vendored/puppet/lib/puppet/util/filetype.rb +2 -2
  151. data/vendored/puppet/lib/puppet/util/json_lockfile.rb +1 -1
  152. data/vendored/puppet/lib/puppet/util/log.rb +5 -3
  153. data/vendored/puppet/lib/puppet/util/log/destinations.rb +0 -1
  154. data/vendored/puppet/lib/puppet/util/monkey_patches.rb +1 -1
  155. data/vendored/puppet/lib/puppet/util/network_device/config.rb +2 -2
  156. data/vendored/puppet/lib/puppet/util/plist.rb +6 -4
  157. data/vendored/puppet/lib/puppet/util/rdoc/generators/puppet_generator.rb +1 -1
  158. data/vendored/puppet/lib/puppet/util/rdoc/parser/puppet_parser_rdoc2.rb +1 -1
  159. data/vendored/puppet/lib/puppet/util/storage.rb +2 -2
  160. data/vendored/puppet/lib/puppet/util/windows/registry.rb +2 -2
  161. data/vendored/puppet/lib/puppet/util/windows/sid.rb +0 -2
  162. data/vendored/puppet/lib/puppet/version.rb +1 -1
  163. data/vendored/puppet/lib/puppet_pal.rb +30 -17
  164. metadata +28 -7
  165. data/vendored/puppet/lib/puppet/pops/types/execution_result.rb +0 -137
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4990187d4d2da77d515fdbe3d840b415683d7082
4
- data.tar.gz: 1eebdfd02969958314e3fa1b4ce0e03b6efc208c
3
+ metadata.gz: 4bf0d0dd4615b52385ed0e9322d17ecaee392951
4
+ data.tar.gz: 6d5c006a8e472c547a99a24c90769b041730c24f
5
5
  SHA512:
6
- metadata.gz: 97ae71fbb805bc96980f1353eebcb458e528c74e9a9c1c94a33ffe0f7c6256058080e6052cee0909dcb06a84fea6cb764a59f47de86e1027df2ff06c9ac3e1f4
7
- data.tar.gz: 4fa7f06bf895ab837451077997aa05bbc4b0291116a3be254cb9e4c600d5eb35da98b48fa349a32ca902b8f4849fa5d79d9bc44b05754a4dc6b46050d088b87b
6
+ metadata.gz: ec8f8eb029f0b7a35ee7bce810859c3d2c143ec25bf5ad08544e9a79a8dc28831f721d2fa6037c188ec874d57678eb80e6ae4d1c681e70a7a998d8f07f627e08
7
+ data.tar.gz: '09ea1f87c8b36045fd6e55837d89977a1106efec8882797dcd9a11297518ab845feedc766fb8a957b87f6c427168992695808eb5fea173c06878715b0e1379f9'
data/lib/bolt/cli.rb CHANGED
@@ -30,7 +30,10 @@ Usage: bolt <subcommand> <action> [options]
30
30
  Available subcommands:
31
31
  bolt command run <command> Run a command remotely
32
32
  bolt script run <script> Upload a local script and run it remotely
33
+ bolt task show Show list of available tasks
34
+ bolt task show <task> Show documentation for task
33
35
  bolt task run <task> [params] Run a Puppet task
36
+ bolt plan show Show list of available plans
34
37
  bolt plan run <plan> [params] Run a Puppet task plan
35
38
  bolt file upload <src> <dest> Upload a local file
36
39
 
@@ -41,6 +44,7 @@ HELP
41
44
  Usage: bolt task <action> <task> [options] [parameters]
42
45
 
43
46
  Available actions are:
47
+ show Show list of available tasks
44
48
  run Run a Puppet task
45
49
 
46
50
  Parameters are of the form <parameter>=<value>.
@@ -70,6 +74,7 @@ HELP
70
74
  Usage: bolt plan <action> <plan> [options] [parameters]
71
75
 
72
76
  Available actions are:
77
+ show Show list of available plans
73
78
  run Run a Puppet task plan
74
79
 
75
80
  Parameters are of the form <parameter>=<value>.
@@ -86,8 +91,11 @@ Available actions are:
86
91
  Available options are:
87
92
  HELP
88
93
 
89
- MODES = %w[command script task plan file].freeze
90
- ACTIONS = %w[run upload download].freeze
94
+ COMMANDS = { 'command' => %w[run],
95
+ 'script' => %w[run],
96
+ 'task' => %w[show run],
97
+ 'plan' => %w[show run],
98
+ 'file' => %w[upload] }.freeze
91
99
  TRANSPORTS = %w[ssh winrm pcp].freeze
92
100
  BOLTLIB_PATH = File.join(__FILE__, '../../../modules')
93
101
 
@@ -172,16 +180,16 @@ HELP
172
180
  end
173
181
  opts.on('--transport TRANSPORT', TRANSPORTS,
174
182
  "Specify a default transport: #{TRANSPORTS.join(', ')}") do |t|
175
- options[:transport] = t
183
+ results[:transport] = t
176
184
  end
177
185
  opts.on('--run-as USER',
178
186
  "User to run as using privilege escalation") do |user|
179
- options[:run_as] = user
187
+ results[:run_as] = user
180
188
  end
181
189
  opts.on('--sudo [PROGRAM]',
182
190
  "Program to execute for privilege escalation. " \
183
191
  "Currently only sudo is supported.") do |program|
184
- options[:sudo] = program || 'sudo'
192
+ results[:sudo] = program || 'sudo'
185
193
  end
186
194
  opts.on('--sudo-password [PASSWORD]',
187
195
  'Password for privilege escalation') do |password|
@@ -201,6 +209,10 @@ HELP
201
209
  "Request a pseudo TTY on nodes that support it") do |tty|
202
210
  results[:tty] = tty
203
211
  end
212
+ opts.on_tail('--noop',
213
+ "Execute a task that supports it in noop mode") do |_|
214
+ results[:noop] = true
215
+ end
204
216
  opts.on_tail('-h', '--help', 'Display help') do |_|
205
217
  results[:help] = true
206
218
  end
@@ -314,10 +326,10 @@ HELP
314
326
  end
315
327
 
316
328
  def validate(options)
317
- unless MODES.include?(options[:mode])
329
+ unless COMMANDS.include?(options[:mode])
318
330
  raise Bolt::CLIError,
319
331
  "Expected subcommand '#{options[:mode]}' to be one of " \
320
- "#{MODES.join(', ')}"
332
+ "#{COMMANDS.keys.join(', ')}"
321
333
  end
322
334
 
323
335
  if options[:action].nil?
@@ -325,10 +337,11 @@ HELP
325
337
  "Expected an action of the form 'bolt #{options[:mode]} <action>'"
326
338
  end
327
339
 
328
- unless ACTIONS.include?(options[:action])
340
+ actions = COMMANDS[options[:mode]]
341
+ unless actions.include?(options[:action])
329
342
  raise Bolt::CLIError,
330
343
  "Expected action '#{options[:action]}' to be one of " \
331
- "#{ACTIONS.join(', ')}"
344
+ "#{actions.join(', ')}"
332
345
  end
333
346
 
334
347
  if options[:mode] != 'file' && options[:mode] != 'script' &&
@@ -337,7 +350,7 @@ HELP
337
350
  "Unknown argument(s) #{options[:leftovers].join(', ')}"
338
351
  end
339
352
 
340
- if %w[task plan].include?(options[:mode])
353
+ if %w[task plan].include?(options[:mode]) && options[:action] == 'run'
341
354
  if options[:object].nil?
342
355
  raise Bolt::CLIError, "Must specify a #{options[:mode]} to run"
343
356
  end
@@ -348,15 +361,20 @@ HELP
348
361
  end
349
362
  end
350
363
 
351
- unless !options[:nodes].empty? || options[:mode] == 'plan'
364
+ if options[:nodes].empty? && options[:mode] != 'plan' && options[:action] != 'show'
352
365
  raise Bolt::CLIError, "Option '--nodes' must be specified"
353
366
  end
354
367
 
355
368
  if %w[task plan].include?(options[:mode]) && @config[:modulepath].nil?
356
369
  raise Bolt::CLIError,
357
- "Option '--modulepath' must be specified when running" \
370
+ "Option '--modulepath' must be specified when using" \
358
371
  " a task or plan"
359
372
  end
373
+
374
+ if options[:noop] && (options[:mode] != 'task' || options[:action] != 'run')
375
+ raise Bolt::CLIError,
376
+ "Option '--noop' may only be specified when running a task"
377
+ end
360
378
  end
361
379
 
362
380
  def handle_parser_errors
@@ -383,7 +401,27 @@ HELP
383
401
  end
384
402
  end
385
403
 
386
- executor = Bolt::Executor.new(@config)
404
+ # ExecutionResult loaded here so that it can get puppet features if
405
+ # puppet is present
406
+ require 'bolt/execution_result'
407
+
408
+ if options[:action] == 'show'
409
+ if options[:mode] == 'task'
410
+ if options[:object]
411
+ outputter.print_task_info(get_task_info(options[:object]))
412
+ else
413
+ outputter.print_table(list_tasks)
414
+ outputter.print_message("\nUse `bolt task show <task-name>` to view "\
415
+ "details and parameters for a specific "\
416
+ "task.")
417
+ end
418
+ elsif options[:mode] == 'plan'
419
+ outputter.print_table(list_plans)
420
+ end
421
+ return
422
+ end
423
+
424
+ executor = Bolt::Executor.new(@config, options[:noop])
387
425
 
388
426
  if options[:mode] == 'plan'
389
427
  execute_plan(executor, options)
@@ -483,24 +521,82 @@ HELP
483
521
  @outputter ||= Bolt::Outputter.for_format(@config[:format])
484
522
  end
485
523
 
486
- def run_task(name, nodes, args, &block)
487
- parse_error = nil
488
- Puppet.initialize_settings
524
+ def in_bolt_compiler(opts = [])
525
+ Puppet.initialize_settings(opts)
489
526
  Puppet::Pal.in_tmp_environment('bolt', modulepath: [BOLTLIB_PATH] + @config[:modulepath], facts: {}) do |pal|
490
527
  pal.with_script_compiler do |compiler|
491
- begin
492
- return compiler.call_function('run_task', name, nodes, args, &block)
493
- rescue Puppet::ParseError => e
494
- # we assume that the Puppet::ParseError is due to a problem with
495
- # the task and/or its parameters, but since the with_script_compiler
496
- # method rescues these errors and raises different ones instead,
497
- # we save it in a local variable and raise it as Bolt::CLIError
498
- # outside of the block
499
- parse_error = e
528
+ yield compiler
529
+ end
530
+ end
531
+ end
532
+
533
+ def list_tasks
534
+ in_bolt_compiler do |compiler|
535
+ tasks = compiler.list_tasks
536
+ tasks.map(&:name).sort.map do |task_name|
537
+ task_sig = compiler.task_signature(task_name)
538
+ [task_name, task_sig.task.description]
539
+ end
540
+ end
541
+ rescue Puppet::Error
542
+ raise Bolt::CLIError, "Failure while reading task metadata"
543
+ end
544
+
545
+ def list_plans
546
+ in_bolt_compiler do |compiler|
547
+ compiler.list_plans.map { |plan| [plan.name] }.sort
548
+ end
549
+ rescue Puppet::Error
550
+ raise Bolt::CLIError, "Failure while reading plans"
551
+ end
552
+
553
+ def get_task_info(task_name)
554
+ task = in_bolt_compiler do |compiler|
555
+ compiler.task_signature(task_name)
556
+ end
557
+ raise Bolt::CLIError, "Could not find task #{task_name} in your modulepath" if task.nil?
558
+ task.task_hash
559
+ rescue Puppet::Error
560
+ raise Bolt::CLIError, "Failure while reading task metadata"
561
+ end
562
+
563
+ def run_task(name, nodes, args, &block)
564
+ parse_error = nil
565
+ result = in_bolt_compiler do |compiler|
566
+ begin
567
+ compiler.call_function('run_task', name, nodes, args, &block)
568
+ rescue Puppet::ParseError => e
569
+ # we assume that the Puppet::ParseError is due to a problem with
570
+ # the task and/or its parameters, but since the with_script_compiler
571
+ # method rescues these errors and raises different ones instead,
572
+ # we save it in a local variable and raise it as Bolt::CLIError
573
+ # outside of the block
574
+ parse_error = e
575
+ end
576
+ end
577
+ raise Bolt::CLIError, parse_error.message if parse_error
578
+ result
579
+ end
580
+
581
+ # Expects to be called with a configured Puppet compiler or error.instance? will fail
582
+ def unwrap_execution_result(result)
583
+ if result.instance_of? Bolt::ExecutionResult
584
+ result.iterator.map do |node, output|
585
+ if output.is_a?(Puppet::DataTypes::Error)
586
+ # Get the original error hash used to initialize the Error type object.
587
+ result = output.partial_result || {}
588
+ result[:_error] = { msg: output.message,
589
+ kind: output.kind,
590
+ details: output.details,
591
+ issue_code: output.issue_code }
592
+ { node: node, status: 'failed', result: result }
593
+ else
594
+ { node: node, status: 'finished', result: output }
500
595
  end
501
596
  end
597
+ else
598
+ result
502
599
  end
503
- raise Bolt::CLIError, parse_error.message
504
600
  end
505
601
 
506
602
  def run_plan(plan, args)
@@ -509,11 +605,11 @@ HELP
509
605
  Puppet::Settings::REQUIRED_APP_SETTINGS.each do |setting|
510
606
  cli << "--#{setting}" << dir
511
607
  end
512
- Puppet.initialize_settings(cli)
513
- Puppet::Pal.in_tmp_environment('bolt', modulepath: [BOLTLIB_PATH] + @config[:modulepath], facts: {}) do |pal|
514
- pal.with_script_compiler do |compiler|
515
- compiler.call_function('run_plan', plan, args)
516
- end
608
+ in_bolt_compiler(cli) do |compiler|
609
+ result = compiler.call_function('run_plan', plan, args)
610
+ # Querying ExecutionResult for failures currently requires a script compiler.
611
+ # Convert from an ExecutionResult to structured output that we can print.
612
+ unwrap_execution_result(result)
517
613
  end
518
614
  end
519
615
  end
data/lib/bolt/config.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'logger'
2
2
  require 'yaml'
3
+ require 'bolt/cli'
3
4
 
4
5
  module Bolt
5
6
  Config = Struct.new(
@@ -20,10 +21,13 @@ module Bolt
20
21
  log_destination: STDERR
21
22
  }.freeze
22
23
 
23
- TRANSPORT_OPTIONS = %i[insecure password run_as sudo sudo_password key tty tmpdir user connect_timeout].freeze
24
+ TRANSPORT_OPTIONS = %i[insecure password run_as sudo sudo_password
25
+ key tty tmpdir user connect_timeout cacert
26
+ token_file orch_task_environment service_url].freeze
24
27
 
25
28
  TRANSPORT_DEFAULTS = {
26
29
  connect_timeout: 10,
30
+ orch_task_environment: 'production',
27
31
  insecure: false,
28
32
  tty: false
29
33
  }.freeze
@@ -47,15 +51,23 @@ module Bolt
47
51
  end
48
52
  end
49
53
 
50
- def default_path
51
- path = ['.puppetlabs', 'bolt.yml']
52
- root_path = '~'
53
- File.join(root_path, *path)
54
+ def default_paths
55
+ root_path = File.expand_path(File.join('~', '.puppetlabs'))
56
+ [File.join(root_path, 'bolt.yaml'), File.join(root_path, 'bolt.yml')]
54
57
  end
55
58
 
56
59
  def read_config_file(path)
57
60
  path_passed = path
58
- path ||= default_path
61
+ if path.nil?
62
+ found_default = default_paths.select { |p| File.exist?(p) }
63
+ if found_default.size > 1
64
+ logger = Logger.new(self[:log_destination])
65
+ logger.warn "Config files found at #{found_default.join(', ')}, using the first"
66
+ end
67
+ # Use first found, fall back to first default and try to load even if it didn't exist
68
+ path = found_default.first || default_paths.first
69
+ end
70
+
59
71
  path = File.expand_path(path)
60
72
  # safe_load doesn't work with psych in ruby 2.0
61
73
  # The user controls the configfile so this isn't a problem
@@ -106,9 +118,30 @@ module Bolt
106
118
  if data['winrm']['connect-timeout']
107
119
  self[:transports][:winrm][:connect_timeout] = data['winrm']['connect-timeout']
108
120
  end
121
+ if data['winrm']['insecure']
122
+ self[:transports][:winrm][:insecure] = data['winrm']['insecure']
123
+ end
109
124
  if data['winrm']['tmpdir']
110
125
  self[:transports][:winrm][:tmpdir] = data['winrm']['tmpdir']
111
126
  end
127
+ if data['winrm']['cacert']
128
+ self[:transports][:winrm][:cacert] = data['winrm']['cacert']
129
+ end
130
+ end
131
+
132
+ if data['pcp']
133
+ if data['pcp']['service-url']
134
+ self[:transports][:pcp][:service_url] = data['pcp']['service-url']
135
+ end
136
+ if data['pcp']['cacert']
137
+ self[:transports][:pcp][:cacert] = data['pcp']['cacert']
138
+ end
139
+ if data['pcp']['token-file']
140
+ self[:transports][:pcp][:token_file] = data['pcp']['token-file']
141
+ end
142
+ if data['pcp']['task-environment']
143
+ self[:transports][:pcp][:orch_task_environment] = data['pcp']['task-environment']
144
+ end
112
145
  end
113
146
  end
114
147
 
@@ -0,0 +1,109 @@
1
+ module Bolt
2
+ class ExecutionResult
3
+ if Object.const_defined?(:Puppet) && Puppet.const_defined?(:Pops)
4
+ include Puppet::Pops::Types::Iterable
5
+ include Puppet::Pops::Types::IteratorProducer
6
+
7
+ def iterator
8
+ tc = Puppet::Pops::Types::TypeFactory
9
+ Puppet::Pops::Types::Iterable.on(
10
+ @result_hash,
11
+ tc.tuple([tc.string, tc.data], Puppet::Pops::Types::PHashType::KEY_PAIR_TUPLE_SIZE)
12
+ )
13
+ end
14
+
15
+ def to_s
16
+ Puppet::Pops::Types::StringConverter.singleton.convert(self)
17
+ end
18
+ else
19
+ def iterator
20
+ @result_hash.each
21
+ end
22
+ end
23
+
24
+ # Creates a pure Data hash from a result hash returned from the Bolt::Executor
25
+ # @return [Hash{String => Data}] The data hash
26
+ def self.from_bolt(result_hash)
27
+ data_result = {}
28
+ result_hash.each_pair { |k, v| data_result[k.uri] = v.to_h }
29
+ new(data_result)
30
+ end
31
+
32
+ attr_reader :result_hash
33
+
34
+ def initialize(result_hash, final = false)
35
+ result_hash = convert_errors(result_hash) unless final
36
+ @result_hash = result_hash
37
+ end
38
+
39
+ def count
40
+ @result_hash.size
41
+ end
42
+
43
+ def empty
44
+ @result_hash.empty?
45
+ end
46
+ alias empty? empty
47
+
48
+ def error_nodes
49
+ result = {}
50
+ @result_hash.each_pair { |k, v| result[k] = v if v.is_a?(Error) }
51
+ self.class.new(result, true)
52
+ end
53
+
54
+ def names
55
+ @result_hash.keys
56
+ end
57
+
58
+ def ok
59
+ @result_hash.values.none? { |v| v.is_a?(Error) }
60
+ end
61
+ alias ok? ok
62
+
63
+ def ok_nodes
64
+ result = {}
65
+ @result_hash.each_pair { |k, v| result[k] = v unless v.is_a?(Error) }
66
+ self.class.new(result, true)
67
+ end
68
+
69
+ def [](node_uri)
70
+ @result_hash[node_uri]
71
+ end
72
+
73
+ def value(node_uri)
74
+ self[node_uri]
75
+ end
76
+
77
+ def values
78
+ @result_hash.values
79
+ end
80
+
81
+ def _pcore_init_hash
82
+ @result_hash
83
+ end
84
+
85
+ def eql?(other)
86
+ self.class == other.class && @result_hash == other.result_hash
87
+ end
88
+
89
+ def ==(other)
90
+ eql?(other)
91
+ end
92
+
93
+ private
94
+
95
+ def convert_errors(result_hash)
96
+ converted = {}
97
+ result_hash.each_pair { |k, v| converted[k] = convert_error(v) }
98
+ converted
99
+ end
100
+
101
+ def convert_error(value_or_error)
102
+ e = value_or_error['error']
103
+ v = value_or_error['value']
104
+ e.nil? ? v : Puppet::DataTypes::Error.new(e['msg'], e['kind'], e['issue_code'], v, e['details'])
105
+ end
106
+
107
+ EMPTY_RESULT = new({})
108
+ end
109
+ end