bolt 3.8.1 → 3.11.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/Puppetfile +4 -4
  3. data/bolt-modules/boltlib/lib/puppet/datatypes/future.rb +25 -0
  4. data/bolt-modules/boltlib/lib/puppet/functions/background.rb +61 -0
  5. data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +5 -9
  6. data/bolt-modules/boltlib/lib/puppet/functions/parallelize.rb +28 -13
  7. data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +5 -15
  8. data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +5 -17
  9. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +8 -17
  10. data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +8 -15
  11. data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +5 -17
  12. data/bolt-modules/boltlib/lib/puppet/functions/wait.rb +91 -0
  13. data/bolt-modules/boltlib/types/planresult.pp +1 -0
  14. data/guides/debugging.txt +28 -0
  15. data/guides/inventory.txt +5 -0
  16. data/lib/bolt/applicator.rb +3 -2
  17. data/lib/bolt/bolt_option_parser.rb +51 -4
  18. data/lib/bolt/cli.rb +38 -9
  19. data/lib/bolt/config/transport/docker.rb +1 -1
  20. data/lib/bolt/config/transport/lxd.rb +1 -1
  21. data/lib/bolt/config/transport/podman.rb +1 -1
  22. data/lib/bolt/error.rb +11 -1
  23. data/lib/bolt/executor.rb +55 -72
  24. data/lib/bolt/fiber_executor.rb +141 -0
  25. data/lib/bolt/module_installer/installer.rb +1 -1
  26. data/lib/bolt/outputter/human.rb +46 -2
  27. data/lib/bolt/outputter/json.rb +9 -0
  28. data/lib/bolt/pal.rb +117 -17
  29. data/lib/bolt/plan_future.rb +66 -0
  30. data/lib/bolt/plugin.rb +38 -0
  31. data/lib/bolt/plugin/env_var.rb +8 -1
  32. data/lib/bolt/plugin/module.rb +1 -1
  33. data/lib/bolt/plugin/prompt.rb +8 -1
  34. data/lib/bolt/plugin/puppet_connect_data.rb +8 -1
  35. data/lib/bolt/plugin/puppetdb.rb +7 -1
  36. data/lib/bolt/plugin/task.rb +9 -1
  37. data/lib/bolt/project.rb +2 -1
  38. data/lib/bolt/task.rb +7 -0
  39. data/lib/bolt/transport/docker/connection.rb +5 -2
  40. data/lib/bolt/transport/lxd/connection.rb +4 -0
  41. data/lib/bolt/transport/podman/connection.rb +4 -0
  42. data/lib/bolt/version.rb +1 -1
  43. data/lib/bolt_server/config.rb +1 -1
  44. data/lib/bolt_server/request_error.rb +11 -0
  45. data/lib/bolt_server/transport_app.rb +133 -95
  46. data/lib/bolt_spec/plans/mock_executor.rb +40 -45
  47. data/lib/bolt_spec/run.rb +4 -1
  48. data/modules/puppet_connect/plans/test_input_data.pp +8 -3
  49. data/resources/bolt_bash_completion.sh +214 -0
  50. metadata +10 -3
  51. data/lib/bolt/yarn.rb +0 -23
@@ -17,13 +17,12 @@ module BoltSpec
17
17
 
18
18
  # Nothing on the executor is 'public'
19
19
  class MockExecutor
20
- attr_reader :noop, :error_message, :in_parallel, :transports, :future
20
+ attr_reader :noop, :error_message, :transports, :future
21
21
  attr_accessor :run_as, :transport_features, :execute_any_plan
22
22
 
23
23
  def initialize(modulepath)
24
24
  @noop = false
25
25
  @run_as = nil
26
- @in_parallel = false
27
26
  @future = {}
28
27
  @error_message = nil
29
28
  @allow_apply = false
@@ -38,6 +37,7 @@ module BoltSpec
38
37
  @execute_any_plan = true
39
38
  # plans that are allowed to be executed by the @executor_real
40
39
  @allowed_exec_plans = {}
40
+ @id = 0
41
41
  end
42
42
 
43
43
  def module_file_id(file)
@@ -257,58 +257,49 @@ module BoltSpec
257
257
  end
258
258
  # End apply_prep mocking
259
259
 
260
- # Evaluates a `parallelize()` block and returns the result. Normally,
261
- # Bolt's executor wraps this in a Yarn for each object passed to the
262
- # `parallelize()` function, and then executes them in parallel before
263
- # returning the result from the block. However, in BoltSpec the block is
264
- # executed for each object sequentially, and this function returns the
265
- # result itself.
266
- #
267
- def create_yarn(scope, block, object, _index)
268
- # Create the new scope
269
- newscope = Puppet::Parser::Scope.new(scope.compiler)
270
- local = Puppet::Parser::Scope::LocalScope.new
271
-
272
- # Compress the current scopes into a single vars hash to add to the new scope
273
- current_scope = scope.effective_symtable(true)
274
- until current_scope.nil?
275
- current_scope.instance_variable_get(:@symbols)&.each_pair { |k, v| local[k] = v }
276
- current_scope = current_scope.parent
277
- end
278
- newscope.push_ephemerals([local])
279
-
280
- begin
281
- result = catch(:return) do
282
- args = { block.parameters[0][1].to_s => object }
283
- block.closure.call_by_name_with_scope(newscope, args, true)
284
- end
260
+ # Parallel function mocking
261
+ def run_in_thread
262
+ yield
263
+ end
285
264
 
286
- # If we got a return from the block, get it's value
287
- # Otherwise the result is the last line from the block
288
- result = result.value if result.is_a?(Puppet::Pops::Evaluator::Return)
265
+ def in_parallel?
266
+ false
267
+ end
289
268
 
290
- # Validate the result is a PlanResult
291
- unless Puppet::Pops::Types::TypeParser.singleton.parse('Boltlib::PlanResult').instance?(result)
292
- raise Bolt::InvalidParallelResult.new(result.to_s, *Puppet::Pops::PuppetStack.top_of_stack)
293
- end
269
+ def create_future(scope: nil, name: nil)
270
+ newscope = nil
271
+ if scope
272
+ # Create the new scope
273
+ newscope = Puppet::Parser::Scope.new(scope.compiler)
274
+ local = Puppet::Parser::Scope::LocalScope.new
294
275
 
295
- result
296
- rescue Puppet::PreformattedError => e
297
- if e.cause.is_a?(Bolt::Error)
298
- e.cause
299
- else
300
- raise e
301
- end
276
+ # Compress the current scopes into a single vars hash to add to the new scope
277
+ scope.to_hash(true, true).each_pair { |k, v| local[k] = v }
278
+ newscope.push_ephemerals([local])
302
279
  end
280
+
281
+ # Execute "futures" serially when running in BoltSpec
282
+ result = yield newscope
283
+ @id += 1
284
+ future = Bolt::PlanFuture.new(nil, @id, name: name)
285
+ future.value = result
286
+ future
303
287
  end
304
288
 
305
- # BoltSpec already evaluated the `parallelize()` block for each object
306
- # passed to the function, so these results can be returned as-is.
307
- #
308
- def round_robin(results)
289
+ def wait(results, **_kwargs)
309
290
  results
310
291
  end
311
292
 
293
+ # Since Futures are executed immediately once created, this will always
294
+ # be true by the time it's called.
295
+ def plan_complete?
296
+ true
297
+ end
298
+
299
+ def plan_futures
300
+ []
301
+ end
302
+
312
303
  # Public methods on Bolt::Executor that need to be mocked so there aren't
313
304
  # "undefined method" errors.
314
305
 
@@ -330,6 +321,8 @@ module BoltSpec
330
321
 
331
322
  def report_yaml_plan(_plan); end
332
323
 
324
+ def report_noop_mode(_mode); end
325
+
333
326
  def shutdown; end
334
327
 
335
328
  def start_plan(_plan_context); end
@@ -337,6 +330,8 @@ module BoltSpec
337
330
  def subscribe(_subscriber, _types = nil); end
338
331
 
339
332
  def unsubscribe(_subscriber, _types = nil); end
333
+
334
+ def round_robin; end
340
335
  end
341
336
  end
342
337
  end
data/lib/bolt_spec/run.rb CHANGED
@@ -182,7 +182,10 @@ module BoltSpec
182
182
  @pal ||= Bolt::PAL.new(Bolt::Config::Modulepath.new(config.modulepath),
183
183
  config.hiera_config,
184
184
  config.project.resource_types,
185
- config.compile_concurrency)
185
+ config.compile_concurrency,
186
+ config.trusted_external,
187
+ config.apply_settings,
188
+ config.project)
186
189
  end
187
190
 
188
191
  def resolve_targets(target_spec)
@@ -1,8 +1,13 @@
1
1
  # @summary
2
2
  # Tests that the provided Puppet Connect input data is complete, meaning that all consuming inventory targets are connectable.
3
- #
4
- # This plan should only be used as part of the copy-pastable "test input data"
5
- # workflow specified in the Puppet Connect docs.
3
+ # You should run this plan with the following command:
4
+ # PUPPET_CONNECT_INPUT_DATA=/path/to/input_data.yaml bolt plan run puppet_connect::test_input_data
5
+ # where /path/to/input_data.yaml is the path to the input_data.yaml file containing the key-value input for the
6
+ # puppet_connect_data plugin. If the plan fails on some targets, then you can use Bolt's --rerun option to rerun the plan on
7
+ # just the failed targets:
8
+ # PUPPET_CONNECT_INPUT_DATA=/path/to/input_data.yaml bolt plan run puppet_connect::test_input_data --rerun failure
9
+ # Note that this plan should only be used as part of the copy-pastable "test input data" workflow specified in the Puppet
10
+ # Connect docs.
6
11
  #
7
12
  # @param targets
8
13
  # The set of targets to test. Usually this should be 'all', the default.
@@ -0,0 +1,214 @@
1
+ #####################################################################
2
+ ###
3
+ ### Bash autocompletion for bolt
4
+ ### include this file in your .bash_profile or .bashrc to use completion
5
+ ### "source bolt_bash_completion.sh"
6
+ ###
7
+ ### Marc Schoechlin ms-github@256bit.org
8
+
9
+ get_json_keys() {
10
+ /opt/puppetlabs/bolt/bin/ruby <<-EOF
11
+ require 'json'
12
+ data = JSON.parse(File.read("${1}"))
13
+ puts data.keys.uniq.sort.join(' ')
14
+ EOF
15
+ }
16
+
17
+ _bolt_complete() {
18
+ local prev
19
+ local cur
20
+ # Get the current word and previous word without colons
21
+ _get_comp_words_by_ref -n : cur
22
+ _get_comp_words_by_ref -n : prev
23
+
24
+ local next=""
25
+ local subcommand=${COMP_WORDS[1]}
26
+ [[ ${#COMP_WORDS[@]} -gt 2 ]] && local action=${COMP_WORDS[2]}
27
+ local context_opts="-m --modulepath --project"
28
+ local global_opts="--clear-cache -h --help --log-level --version"
29
+ local inventory_opts="-q --query --rerun -t --targets"
30
+ local authentication_opts="-u --user -p --password --password-prompt --private-key --host-key-check --no-host-key-check --ssl --no-ssl --ssl-verify --no-ssl-verify"
31
+ local escalation_opts="--run-as --sudo-password --sudo-password-prompt --sudo-executable"
32
+ local run_context_opts="-c --concurrency -i --inventoryfile --save-rerun --no-save-rerun --cleanup --no-cleanup"
33
+ local transport_opts="--transport --connect-timeout --tty --no-tty --native-ssh --no-native-ssh --ssh-command --copy-command"
34
+ local display_opts="--format --color --no-color -v --verbose --no-verbose --trace --stream"
35
+ local action_opts="${inventory_opts} ${context_opts} ${authentication_opts} ${escalation_opts} ${run_context_opts} ${transport_opts} ${display_opts}"
36
+ local apply_opts="--compile-concurrency --hiera-config"
37
+ local file_opts=" -m --modulepath --project --private-key -i --inventoryfile --hiera-config "
38
+
39
+ # If there's only one word and it's "bolt", tab complete the subcommand
40
+ if [ $COMP_CWORD -eq 1 ]; then
41
+ next="apply command file group guide inventory lookup module plan plugin project script secret task"
42
+ fi
43
+
44
+ # Tab complete files for options that accept files. The spaces are important!
45
+ # They make it so `bolt inventory` isn't confused with `--inventoryfile`.
46
+ if [[ $file_opts =~ " ${prev} " ]]; then
47
+ next=$(compgen -f -d "" -- $cur)
48
+ # Handle tab completing enumerable CLI options
49
+ elif [ "$prev" == "--log-level" ]; then
50
+ next="trace debug info warn error fatal any"
51
+ elif [ "$prev" == "--transport" ]; then
52
+ next="docker local lxd pcp podman remote ssh winrm"
53
+ elif [ "$prev" == "--format" ]; then
54
+ next="human json rainbow"
55
+ else
56
+ # Once we have subcommands, tab complete actions
57
+ case $subcommand in
58
+ apply)
59
+ next="${action_opts} ${apply_opts} -e --execute"
60
+ ;;
61
+ command)
62
+ if [ $COMP_CWORD -eq 2 ]; then
63
+ next="run"
64
+ elif [ $action = "run" ]; then
65
+ next="${action_opts} --env-var"
66
+ fi
67
+ ;;
68
+ file)
69
+ if [ $COMP_CWORD -eq 2 ]; then
70
+ next="download upload"
71
+ else
72
+ case $action in
73
+ download) next="${action_opts} --tmpdir";;
74
+ upload) next=$action_opts;;
75
+ esac
76
+ fi
77
+ ;;
78
+ group)
79
+ if [ $COMP_CWORD -eq 2 ]; then
80
+ next="show"
81
+ elif [ $action == 'show' ]; then
82
+ next="--project --format --inventoryfile"
83
+ fi
84
+ ;;
85
+ guide)
86
+ next="--format"
87
+ ;;
88
+ inventory)
89
+ if [ $COMP_CWORD -eq 2 ]; then
90
+ next="show"
91
+ elif [ $action == 'show' ]; then
92
+ next="${inventory_opts} --project --format --inventoryfile --detail"
93
+ fi
94
+ ;;
95
+ lookup)
96
+ next="${action_opts} --hiera-config --plan-hierarchy"
97
+ ;;
98
+ module)
99
+ if [ $COMP_CWORD -eq 2 ]; then
100
+ next="add generate-types install show"
101
+ else
102
+ case $action in
103
+ add | install) next="--project";;
104
+ generate-types) next="${context_opts}";;
105
+ show) next="${context_opts} --filter --format";;
106
+ esac
107
+ fi
108
+ ;;
109
+ plan)
110
+ if [ $COMP_CWORD -eq 2 ]; then
111
+ next="convert new run show"
112
+ elif [[ ($COMP_CWORD -eq 3 || \
113
+ ( $COMP_CWORD -eq 4 && "$cur" == *"::" ) || \
114
+ ( $COMP_CWORD -eq 5 && "$cur" == *"::"* )) &&
115
+ $action != "new" ]]; then
116
+
117
+ if [ -f "${PWD}/.plan_cache.json" ]; then
118
+ # Use Puppet's ruby instead of jq since we know it will be there.
119
+ next=$(get_json_keys "${PWD}/.plan_cache.json")
120
+ elif [ -f "${HOME}/.puppetlabs/bolt/.plan_cache.json" ]; then
121
+ next=$(get_json_keys "${HOME}/.puppetlabs/bolt/.plan_cache.json")
122
+ else
123
+ case $action in
124
+ convert) next="${context_opts}";;
125
+ new) next="--project --pp";;
126
+ run) next="${action_opts} ${apply_opts} --params --tmpdir";;
127
+ show) next="${context_opts} --filter --format";;
128
+ esac
129
+ fi
130
+ else
131
+ case $action in
132
+ convert) next="${context_opts}";;
133
+ new) next="--project --pp";;
134
+ run) next="${action_opts} ${apply_opts} --params --tmpdir";;
135
+ show) next="${context_opts} --filter --format";;
136
+ esac
137
+ fi
138
+ ;;
139
+ plugin)
140
+ if [ $COMP_CWORD -eq 2 ]; then
141
+ next="show"
142
+ else
143
+ next="${context_opts} --format --color --no-color"
144
+ fi
145
+ ;;
146
+ project)
147
+ if [ $COMP_CWORD -eq 2 ]; then
148
+ next="init migrate"
149
+ else
150
+ case $action in
151
+ init) next="--modules";;
152
+ migrate) next="--project --inventoryfile";;
153
+ esac
154
+ fi
155
+ ;;
156
+ script)
157
+ if [ $COMP_CWORD -eq 2 ]; then
158
+ next="run"
159
+ elif [[ $COMP_CWORD -eq 3 && $action == 'run' ]]; then
160
+ # List files and directories
161
+ next=$(compgen -f -d "" -- $cur)
162
+ elif [ $action == 'run' ]; then
163
+ next="${action_opts} --env-var --tmpdir"
164
+ fi
165
+ ;;
166
+ secret)
167
+ if [ $COMP_CWORD -eq 2 ]; then
168
+ next="createkeys encrypt decrypt"
169
+ else
170
+ case $action in
171
+ createkeys) next="${context_opts} --plugin --force";;
172
+ encrypt | decrypt) next="${context_opts} --plugin";;
173
+ esac
174
+ fi
175
+ ;;
176
+ task)
177
+ if [ $COMP_CWORD -eq 2 ]; then
178
+ next="run show"
179
+ elif [[ $COMP_CWORD -eq 3 || \
180
+ ( $COMP_CWORD -eq 4 && "$cur" == *"::" ) || \
181
+ ( $COMP_CWORD -eq 5 && "$cur" == *"::"* ) ]]; then
182
+ if [ -f "${PWD}/.task_cache.json" ]; then
183
+ # Use Puppet's ruby instead of jq since we know it will be there.
184
+ next=$(get_json_keys "${PWD}/.task_cache.json")
185
+ elif [ -f "${HOME}/.puppetlabs/bolt/.task_cache.json" ]; then
186
+ next=$(get_json_keys "${HOME}/.puppetlabs/bolt/.task_cache.json")
187
+ else
188
+ case $action in
189
+ run) next="${action_opts} --env-var --tmpdir";;
190
+ show) next="${context_opts} --filter --format";;
191
+ esac
192
+ fi
193
+ else
194
+ case $action in
195
+ run) next="${action_opts} --env-var --tmpdir";;
196
+ show) next="${context_opts} --filter --format";;
197
+ esac
198
+ fi
199
+ ;;
200
+ esac
201
+ fi
202
+
203
+ # If any of the next options are flags, we've reached the end of the
204
+ # building-a-Bolt-command part and can re-enable file and directory name
205
+ # completion and include Bolt's global flags.
206
+ if [[ "$next" =~ "--" ]]; then
207
+ next+=" ${global_opts}"
208
+ fi
209
+
210
+ COMPREPLY=($(compgen -W "$next" -- $cur))
211
+ __ltrim_colon_completions $cur
212
+ }
213
+
214
+ complete -F _bolt_complete bolt
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: 3.8.1
4
+ version: 3.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-05-17 00:00:00.000000000 Z
11
+ date: 2021-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -399,6 +399,7 @@ files:
399
399
  - Puppetfile
400
400
  - bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb
401
401
  - bolt-modules/boltlib/lib/puppet/datatypes/containerresult.rb
402
+ - bolt-modules/boltlib/lib/puppet/datatypes/future.rb
402
403
  - bolt-modules/boltlib/lib/puppet/datatypes/resourceinstance.rb
403
404
  - bolt-modules/boltlib/lib/puppet/datatypes/result.rb
404
405
  - bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb
@@ -406,6 +407,7 @@ files:
406
407
  - bolt-modules/boltlib/lib/puppet/functions/add_facts.rb
407
408
  - bolt-modules/boltlib/lib/puppet/functions/add_to_group.rb
408
409
  - bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb
410
+ - bolt-modules/boltlib/lib/puppet/functions/background.rb
409
411
  - bolt-modules/boltlib/lib/puppet/functions/catch_errors.rb
410
412
  - bolt-modules/boltlib/lib/puppet/functions/download_file.rb
411
413
  - bolt-modules/boltlib/lib/puppet/functions/facts.rb
@@ -432,6 +434,7 @@ files:
432
434
  - bolt-modules/boltlib/lib/puppet/functions/set_var.rb
433
435
  - bolt-modules/boltlib/lib/puppet/functions/upload_file.rb
434
436
  - bolt-modules/boltlib/lib/puppet/functions/vars.rb
437
+ - bolt-modules/boltlib/lib/puppet/functions/wait.rb
435
438
  - bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb
436
439
  - bolt-modules/boltlib/lib/puppet/functions/without_default_logging.rb
437
440
  - bolt-modules/boltlib/lib/puppet/functions/write_file.rb
@@ -450,6 +453,7 @@ files:
450
453
  - bolt-modules/prompt/lib/puppet/functions/prompt/menu.rb
451
454
  - bolt-modules/system/lib/puppet/functions/system/env.rb
452
455
  - exe/bolt
456
+ - guides/debugging.txt
453
457
  - guides/guide.txt
454
458
  - guides/inventory.txt
455
459
  - guides/links.txt
@@ -485,6 +489,7 @@ files:
485
489
  - lib/bolt/container_result.rb
486
490
  - lib/bolt/error.rb
487
491
  - lib/bolt/executor.rb
492
+ - lib/bolt/fiber_executor.rb
488
493
  - lib/bolt/inventory.rb
489
494
  - lib/bolt/inventory/group.rb
490
495
  - lib/bolt/inventory/inventory.rb
@@ -528,6 +533,7 @@ files:
528
533
  - lib/bolt/pal/yaml_plan/step/upload.rb
529
534
  - lib/bolt/pal/yaml_plan/transpiler.rb
530
535
  - lib/bolt/plan_creator.rb
536
+ - lib/bolt/plan_future.rb
531
537
  - lib/bolt/plan_result.rb
532
538
  - lib/bolt/plugin.rb
533
539
  - lib/bolt/plugin/cache.rb
@@ -583,13 +589,13 @@ files:
583
589
  - lib/bolt/util/puppet_log_level.rb
584
590
  - lib/bolt/validator.rb
585
591
  - lib/bolt/version.rb
586
- - lib/bolt/yarn.rb
587
592
  - lib/bolt_server/acl.rb
588
593
  - lib/bolt_server/base_config.rb
589
594
  - lib/bolt_server/config.rb
590
595
  - lib/bolt_server/file_cache.rb
591
596
  - lib/bolt_server/plugin.rb
592
597
  - lib/bolt_server/plugin/puppet_connect_data.rb
598
+ - lib/bolt_server/request_error.rb
593
599
  - lib/bolt_server/schemas/action-check_node_connections.json
594
600
  - lib/bolt_server/schemas/action-run_command.json
595
601
  - lib/bolt_server/schemas/action-run_script.json
@@ -631,6 +637,7 @@ files:
631
637
  - modules/canary/plans/init.pp
632
638
  - modules/puppet_connect/plans/test_input_data.pp
633
639
  - modules/puppetdb_fact/plans/init.pp
640
+ - resources/bolt_bash_completion.sh
634
641
  homepage: https://github.com/puppetlabs/bolt
635
642
  licenses:
636
643
  - Apache-2.0