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.
- checksums.yaml +4 -4
- data/Puppetfile +4 -4
- data/bolt-modules/boltlib/lib/puppet/datatypes/future.rb +25 -0
- data/bolt-modules/boltlib/lib/puppet/functions/background.rb +61 -0
- data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +5 -9
- data/bolt-modules/boltlib/lib/puppet/functions/parallelize.rb +28 -13
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +5 -15
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +5 -17
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +8 -17
- data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +8 -15
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +5 -17
- data/bolt-modules/boltlib/lib/puppet/functions/wait.rb +91 -0
- data/bolt-modules/boltlib/types/planresult.pp +1 -0
- data/guides/debugging.txt +28 -0
- data/guides/inventory.txt +5 -0
- data/lib/bolt/applicator.rb +3 -2
- data/lib/bolt/bolt_option_parser.rb +51 -4
- data/lib/bolt/cli.rb +38 -9
- data/lib/bolt/config/transport/docker.rb +1 -1
- data/lib/bolt/config/transport/lxd.rb +1 -1
- data/lib/bolt/config/transport/podman.rb +1 -1
- data/lib/bolt/error.rb +11 -1
- data/lib/bolt/executor.rb +55 -72
- data/lib/bolt/fiber_executor.rb +141 -0
- data/lib/bolt/module_installer/installer.rb +1 -1
- data/lib/bolt/outputter/human.rb +46 -2
- data/lib/bolt/outputter/json.rb +9 -0
- data/lib/bolt/pal.rb +117 -17
- data/lib/bolt/plan_future.rb +66 -0
- data/lib/bolt/plugin.rb +38 -0
- data/lib/bolt/plugin/env_var.rb +8 -1
- data/lib/bolt/plugin/module.rb +1 -1
- data/lib/bolt/plugin/prompt.rb +8 -1
- data/lib/bolt/plugin/puppet_connect_data.rb +8 -1
- data/lib/bolt/plugin/puppetdb.rb +7 -1
- data/lib/bolt/plugin/task.rb +9 -1
- data/lib/bolt/project.rb +2 -1
- data/lib/bolt/task.rb +7 -0
- data/lib/bolt/transport/docker/connection.rb +5 -2
- data/lib/bolt/transport/lxd/connection.rb +4 -0
- data/lib/bolt/transport/podman/connection.rb +4 -0
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/config.rb +1 -1
- data/lib/bolt_server/request_error.rb +11 -0
- data/lib/bolt_server/transport_app.rb +133 -95
- data/lib/bolt_spec/plans/mock_executor.rb +40 -45
- data/lib/bolt_spec/run.rb +4 -1
- data/modules/puppet_connect/plans/test_input_data.pp +8 -3
- data/resources/bolt_bash_completion.sh +214 -0
- metadata +10 -3
- data/lib/bolt/yarn.rb +0 -23
@@ -0,0 +1,28 @@
|
|
1
|
+
TOPIC
|
2
|
+
debugging
|
3
|
+
|
4
|
+
DESCRIPTION
|
5
|
+
When Bolt isn't behaving as expected, there are a few helpful commands and
|
6
|
+
logs that can help identify common issues. The first place to look is in
|
7
|
+
`<PROJECT>/bolt-debug.log`, which contains debug-level logs from the last Bolt
|
8
|
+
run. This log file includes where the Bolt project was loaded from, the
|
9
|
+
location of any configuration or inventory files that were loaded, and the
|
10
|
+
modulepath that modules were loaded from.
|
11
|
+
|
12
|
+
If you're having issues with loading targets or target configuration, you
|
13
|
+
can see the list of resolved Bolt target names by running `bolt inventory
|
14
|
+
show` on *nix systems or `Get-BoltInventory` in PowerShell. To see the
|
15
|
+
resolved configuration for each target, run the command with the `--detail` or
|
16
|
+
`-Detail` options.
|
17
|
+
|
18
|
+
Lastly, if you're having trouble loading Bolt content you can use `bolt
|
19
|
+
module show` on *nix systems or `Get-BoltModule` in PowerShell to see the list
|
20
|
+
of loaded modules, including where they were loaded from. You can also use
|
21
|
+
`bolt task show` or `Get-BoltTask` to list loaded tasks, and `bolt plan show`
|
22
|
+
or `Get-BoltPlan` to list loaded plans.
|
23
|
+
|
24
|
+
Visit the linked documentation for more in-depth troubleshooting help for
|
25
|
+
specific issues.
|
26
|
+
|
27
|
+
DOCUMENTATION
|
28
|
+
https://pup.pt/bolt-troubleshooting
|
data/guides/inventory.txt
CHANGED
@@ -14,6 +14,11 @@ DESCRIPTION
|
|
14
14
|
project configuration file named 'bolt-project.yaml' alongside the inventory
|
15
15
|
file.
|
16
16
|
|
17
|
+
When Bolt loads inventory, it loads the entire inventory, not just the
|
18
|
+
groups and targets specified on the command line. If you've defined a
|
19
|
+
target in multiple groups, this might result in target configuration that
|
20
|
+
is different than expected.
|
21
|
+
|
17
22
|
DOCUMENTATION
|
18
23
|
https://pup.pt/bolt-inventory
|
19
24
|
https://pup.pt/bolt-inventory-reference
|
data/lib/bolt/applicator.rb
CHANGED
@@ -306,11 +306,12 @@ module Bolt
|
|
306
306
|
Puppet.lookup(:current_environment).override_with(modulepath: @plugin_dirs).modules.each do |mod|
|
307
307
|
search_dirs = yield mod
|
308
308
|
|
309
|
-
|
309
|
+
tar_dir = Pathname.new(mod.name) # goes great with fish
|
310
|
+
mod_dir = Pathname.new(mod.path)
|
310
311
|
files = Find.find(*search_dirs).select { |file| File.file?(file) }
|
311
312
|
|
312
313
|
files.each do |file|
|
313
|
-
tar_path = Pathname.new(file).relative_path_from(
|
314
|
+
tar_path = tar_dir + Pathname.new(file).relative_path_from(mod_dir)
|
314
315
|
@logger.trace("Packing plugin #{file} to #{tar_path}")
|
315
316
|
stat = File.stat(file)
|
316
317
|
content = File.binread(file)
|
@@ -67,7 +67,7 @@ module Bolt
|
|
67
67
|
{ flags: OPTIONS[:global] + %w[format],
|
68
68
|
banner: GUIDE_HELP }
|
69
69
|
when 'lookup'
|
70
|
-
{ flags: ACTION_OPTS + %w[hiera-config],
|
70
|
+
{ flags: ACTION_OPTS + %w[hiera-config plan-hierarchy],
|
71
71
|
banner: LOOKUP_HELP }
|
72
72
|
when 'module'
|
73
73
|
case action
|
@@ -105,6 +105,15 @@ module Bolt
|
|
105
105
|
{ flags: OPTIONS[:global],
|
106
106
|
banner: PLAN_HELP }
|
107
107
|
end
|
108
|
+
when 'plugin'
|
109
|
+
case action
|
110
|
+
when 'show'
|
111
|
+
{ flags: OPTIONS[:global] + %w[color format modulepath project],
|
112
|
+
banner: PLUGIN_SHOW_HELP }
|
113
|
+
else
|
114
|
+
{ flags: OPTIONS[:global],
|
115
|
+
banner: PLUGIN_HELP }
|
116
|
+
end
|
108
117
|
when 'project'
|
109
118
|
case action
|
110
119
|
when 'init'
|
@@ -192,6 +201,7 @@ module Bolt
|
|
192
201
|
module Manage Bolt project modules
|
193
202
|
lookup Look up a value with Hiera
|
194
203
|
plan Convert, create, show, and run Bolt plans
|
204
|
+
plugin Show available plugins
|
195
205
|
project Create and migrate Bolt projects
|
196
206
|
script Upload a local script and run it remotely
|
197
207
|
secret Create encryption keys and encrypt and decrypt values
|
@@ -407,7 +417,7 @@ module Bolt
|
|
407
417
|
lookup
|
408
418
|
|
409
419
|
#{colorize(:cyan, 'Usage')}
|
410
|
-
bolt lookup <key> {--targets TARGETS | --query QUERY | --rerun FILTER}
|
420
|
+
bolt lookup <key> {--targets TARGETS | --query QUERY | --rerun FILTER | --plan-hierarchy}
|
411
421
|
[options]
|
412
422
|
|
413
423
|
#{colorize(:cyan, 'Description')}
|
@@ -418,6 +428,7 @@ module Bolt
|
|
418
428
|
|
419
429
|
#{colorize(:cyan, 'Examples')}
|
420
430
|
bolt lookup password --targets servers
|
431
|
+
bolt lookup password --plan-hierarchy variable=value
|
421
432
|
HELP
|
422
433
|
|
423
434
|
MODULE_HELP = <<~HELP
|
@@ -608,6 +619,37 @@ module Bolt
|
|
608
619
|
bolt plan show aggregate::count
|
609
620
|
HELP
|
610
621
|
|
622
|
+
PLUGIN_HELP = <<~HELP
|
623
|
+
#{colorize(:cyan, 'Name')}
|
624
|
+
plugin
|
625
|
+
|
626
|
+
#{colorize(:cyan, 'Usage')}
|
627
|
+
bolt plugin <action> [options]
|
628
|
+
|
629
|
+
#{colorize(:cyan, 'Description')}
|
630
|
+
Show available plugins.
|
631
|
+
|
632
|
+
#{colorize(:cyan, 'Documentation')}
|
633
|
+
Learn more about Bolt plugins at https://pup.pt/bolt-plugins.
|
634
|
+
|
635
|
+
#{colorize(:cyan, 'Actions')}
|
636
|
+
show Show available plugins
|
637
|
+
HELP
|
638
|
+
|
639
|
+
PLUGIN_SHOW_HELP = <<~HELP
|
640
|
+
#{colorize(:cyan, 'Name')}
|
641
|
+
show
|
642
|
+
|
643
|
+
#{colorize(:cyan, 'Usage')}
|
644
|
+
bolt plugin show [options]
|
645
|
+
|
646
|
+
#{colorize(:cyan, 'Description')}
|
647
|
+
Show available plugins.
|
648
|
+
|
649
|
+
#{colorize(:cyan, 'Documentation')}
|
650
|
+
Learn more about Bolt plugins at https://pup.pt/bolt-plugins.
|
651
|
+
HELP
|
652
|
+
|
611
653
|
PROJECT_HELP = <<~HELP
|
612
654
|
#{colorize(:cyan, 'Name')}
|
613
655
|
project
|
@@ -676,7 +718,7 @@ module Bolt
|
|
676
718
|
Run a script on the specified targets.
|
677
719
|
|
678
720
|
#{colorize(:cyan, 'Documentation')}
|
679
|
-
Learn more about running
|
721
|
+
Learn more about running scripts at https://pup.pt/bolt-commands.
|
680
722
|
|
681
723
|
#{colorize(:cyan, 'Actions')}
|
682
724
|
run Run a script on the specified targets.
|
@@ -698,7 +740,7 @@ module Bolt
|
|
698
740
|
be quoted.
|
699
741
|
|
700
742
|
#{colorize(:cyan, 'Documentation')}
|
701
|
-
Learn more about running
|
743
|
+
Learn more about running scripts at https://pup.pt/bolt-commands.
|
702
744
|
|
703
745
|
#{colorize(:cyan, 'Examples')}
|
704
746
|
bolt script run myscript.sh 'echo hello' --targets target1,target2
|
@@ -988,6 +1030,11 @@ module Bolt
|
|
988
1030
|
@options[:resolve] = resolve
|
989
1031
|
end
|
990
1032
|
|
1033
|
+
separator "\n#{self.class.colorize(:cyan, 'Lookup options')}"
|
1034
|
+
define('--plan-hierarchy', 'Look up a value with Hiera in the context of a specific plan.') do |_|
|
1035
|
+
@options[:plan_hierarchy] = true
|
1036
|
+
end
|
1037
|
+
|
991
1038
|
separator "\n#{self.class.colorize(:cyan, 'Plan options')}"
|
992
1039
|
define('--pp', 'Create a new Puppet language plan.') do |_|
|
993
1040
|
@options[:puppet] = true
|
data/lib/bolt/cli.rb
CHANGED
@@ -42,6 +42,7 @@ module Bolt
|
|
42
42
|
'lookup' => %w[],
|
43
43
|
'module' => %w[add generate-types install show],
|
44
44
|
'plan' => %w[show run convert new],
|
45
|
+
'plugin' => %w[show],
|
45
46
|
'project' => %w[init migrate],
|
46
47
|
'script' => %w[run],
|
47
48
|
'secret' => %w[encrypt decrypt createkeys],
|
@@ -354,12 +355,18 @@ module Bolt
|
|
354
355
|
"the project, run '#{command} #{options[:object]}'."
|
355
356
|
end
|
356
357
|
|
357
|
-
if
|
358
|
+
if !%w[file script lookup].include?(options[:subcommand]) &&
|
358
359
|
!options[:leftovers].empty?
|
359
360
|
raise Bolt::CLIError,
|
360
361
|
"Unknown argument(s) #{options[:leftovers].join(', ')}"
|
361
362
|
end
|
362
363
|
|
364
|
+
target_opts = options.keys.select { |opt| TARGETING_OPTIONS.include?(opt) }
|
365
|
+
if options[:subcommand] == 'lookup' &&
|
366
|
+
target_opts.any? && options[:plan_hierarchy]
|
367
|
+
raise Bolt::CLIError, "The 'lookup' command accepts either targeting option OR --plan-hierarchy."
|
368
|
+
end
|
369
|
+
|
363
370
|
if options[:noop] &&
|
364
371
|
!(options[:subcommand] == 'task' && options[:action] == 'run') && options[:subcommand] != 'apply'
|
365
372
|
raise Bolt::CLIError,
|
@@ -432,10 +439,11 @@ module Bolt
|
|
432
439
|
end
|
433
440
|
|
434
441
|
# Initialize inventory and targets. Errors here are better to catch early.
|
435
|
-
# options[:target_args] will contain a string/array version of the
|
442
|
+
# options[:target_args] will contain a string/array version of the targeting options this is passed to plans
|
436
443
|
# options[:targets] will contain a resolved set of Target objects
|
437
444
|
unless %w[guide module project secret].include?(options[:subcommand]) ||
|
438
|
-
%w[convert new show].include?(options[:action])
|
445
|
+
%w[convert new show].include?(options[:action]) ||
|
446
|
+
options[:plan_hierarchy]
|
439
447
|
update_targets(options)
|
440
448
|
end
|
441
449
|
|
@@ -487,6 +495,8 @@ module Bolt
|
|
487
495
|
list_groups
|
488
496
|
when 'module'
|
489
497
|
list_modules
|
498
|
+
when 'plugin'
|
499
|
+
list_plugins
|
490
500
|
end
|
491
501
|
return 0
|
492
502
|
when 'convert'
|
@@ -516,7 +526,13 @@ module Bolt
|
|
516
526
|
code = Bolt::ProjectManager.new(config, outputter, pal).migrate
|
517
527
|
end
|
518
528
|
when 'lookup'
|
519
|
-
|
529
|
+
plan_vars = Hash[options[:leftovers].map { |a| a.split('=', 2) }]
|
530
|
+
# Validate functions verifies one of these was passed
|
531
|
+
if options[:targets]
|
532
|
+
code = lookup(options[:object], options[:targets], plan_vars: plan_vars)
|
533
|
+
elsif options[:plan_hierarchy]
|
534
|
+
code = plan_lookup(options[:object], plan_vars: plan_vars)
|
535
|
+
end
|
520
536
|
when 'plan'
|
521
537
|
case options[:action]
|
522
538
|
when 'new'
|
@@ -630,7 +646,7 @@ module Bolt
|
|
630
646
|
end
|
631
647
|
|
632
648
|
def list_tasks
|
633
|
-
tasks = filter_content(pal.
|
649
|
+
tasks = filter_content(pal.list_tasks_with_cache(filter_content: true), options[:filter])
|
634
650
|
outputter.print_tasks(tasks, pal.user_modulepath)
|
635
651
|
end
|
636
652
|
|
@@ -694,10 +710,19 @@ module Bolt
|
|
694
710
|
outputter.print_groups(inventory.group_names.sort, inventory.source, config.default_inventoryfile)
|
695
711
|
end
|
696
712
|
|
713
|
+
# Looks up a value with Hiera as if in a plan outside an apply block, using
|
714
|
+
# provided variable values for interpolations
|
715
|
+
#
|
716
|
+
def plan_lookup(key, plan_vars: {})
|
717
|
+
result = pal.plan_hierarchy_lookup(key, plan_vars: plan_vars)
|
718
|
+
outputter.print_plan_lookup(result)
|
719
|
+
0
|
720
|
+
end
|
721
|
+
|
697
722
|
# Looks up a value with Hiera, using targets as the contexts to perform the
|
698
|
-
# look ups in.
|
723
|
+
# look ups in. This should return the same value as a lookup in an apply block.
|
699
724
|
#
|
700
|
-
def lookup(key, targets)
|
725
|
+
def lookup(key, targets, plan_vars: {})
|
701
726
|
executor = Bolt::Executor.new(
|
702
727
|
config.concurrency,
|
703
728
|
analytics,
|
@@ -706,7 +731,7 @@ module Bolt
|
|
706
731
|
config.future
|
707
732
|
)
|
708
733
|
|
709
|
-
executor.subscribe(outputter) if
|
734
|
+
executor.subscribe(outputter) if config.format == 'human'
|
710
735
|
executor.subscribe(log_outputter)
|
711
736
|
executor.publish_event(type: :plan_start, plan: nil)
|
712
737
|
|
@@ -716,7 +741,7 @@ module Bolt
|
|
716
741
|
targets,
|
717
742
|
inventory,
|
718
743
|
executor,
|
719
|
-
|
744
|
+
plan_vars: plan_vars
|
720
745
|
)
|
721
746
|
end
|
722
747
|
|
@@ -827,6 +852,10 @@ module Bolt
|
|
827
852
|
outputter.print_module_list(pal.list_modules)
|
828
853
|
end
|
829
854
|
|
855
|
+
def list_plugins
|
856
|
+
outputter.print_plugin_list(plugins.list_plugins, pal.user_modulepath)
|
857
|
+
end
|
858
|
+
|
830
859
|
def generate_types
|
831
860
|
# generate_types will surface a nice error with helpful message if it fails
|
832
861
|
pal.generate_types(cache: true)
|
data/lib/bolt/error.rb
CHANGED
@@ -105,6 +105,16 @@ module Bolt
|
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
|
+
class FutureTimeoutError < Bolt::Error
|
109
|
+
def initialize(name, timeout)
|
110
|
+
details = {
|
111
|
+
'future' => name
|
112
|
+
}
|
113
|
+
message = "Future '#{name}' timed out after #{timeout} seconds."
|
114
|
+
super(message, 'bolt/future-timeout-error', details)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
108
118
|
class ParallelFailure < Bolt::Error
|
109
119
|
def initialize(results, failed_indices)
|
110
120
|
details = {
|
@@ -162,7 +172,7 @@ module Bolt
|
|
162
172
|
|
163
173
|
class InvalidParallelResult < Error
|
164
174
|
def initialize(result_str, file, line)
|
165
|
-
super("
|
175
|
+
super("Background block returned an invalid result: #{result_str}",
|
166
176
|
'bolt/invalid-plan-result',
|
167
177
|
{ 'file' => file,
|
168
178
|
'line' => line,
|
data/lib/bolt/executor.rb
CHANGED
@@ -7,10 +7,11 @@ require 'logging'
|
|
7
7
|
require 'pathname'
|
8
8
|
require 'set'
|
9
9
|
require 'bolt/analytics'
|
10
|
-
require 'bolt/result'
|
11
10
|
require 'bolt/config'
|
12
|
-
require 'bolt/
|
11
|
+
require 'bolt/fiber_executor'
|
13
12
|
require 'bolt/puppetdb'
|
13
|
+
require 'bolt/result'
|
14
|
+
require 'bolt/result_set'
|
14
15
|
# Load transports
|
15
16
|
require 'bolt/transport/docker'
|
16
17
|
require 'bolt/transport/local'
|
@@ -20,7 +21,6 @@ require 'bolt/transport/podman'
|
|
20
21
|
require 'bolt/transport/remote'
|
21
22
|
require 'bolt/transport/ssh'
|
22
23
|
require 'bolt/transport/winrm'
|
23
|
-
require 'bolt/yarn'
|
24
24
|
|
25
25
|
module Bolt
|
26
26
|
TRANSPORTS = {
|
@@ -35,7 +35,7 @@ module Bolt
|
|
35
35
|
}.freeze
|
36
36
|
|
37
37
|
class Executor
|
38
|
-
attr_reader :noop, :transports, :
|
38
|
+
attr_reader :noop, :transports, :future
|
39
39
|
attr_accessor :run_as
|
40
40
|
|
41
41
|
def initialize(concurrency = 1,
|
@@ -66,7 +66,6 @@ module Bolt
|
|
66
66
|
|
67
67
|
@noop = noop
|
68
68
|
@run_as = nil
|
69
|
-
@in_parallel = false
|
70
69
|
@future = future
|
71
70
|
@pool = if concurrency > 0
|
72
71
|
Concurrent::ThreadPoolExecutor.new(name: 'exec', max_threads: concurrency)
|
@@ -77,6 +76,7 @@ module Bolt
|
|
77
76
|
|
78
77
|
@concurrency = concurrency
|
79
78
|
@warn_concurrency = modified_concurrency
|
79
|
+
@fiber_executor = Bolt::FiberExecutor.new
|
80
80
|
end
|
81
81
|
|
82
82
|
def transport(transport)
|
@@ -242,6 +242,10 @@ module Bolt
|
|
242
242
|
@analytics&.event('Plan', plan_function, label: label)
|
243
243
|
end
|
244
244
|
|
245
|
+
def report_noop_mode(noop)
|
246
|
+
@analytics&.event('Task', 'noop', label: (!!noop).to_s)
|
247
|
+
end
|
248
|
+
|
245
249
|
def report_apply(statement_count, resource_counts)
|
246
250
|
data = { statement_count: statement_count }
|
247
251
|
|
@@ -373,83 +377,62 @@ module Bolt
|
|
373
377
|
plan.call_by_name_with_scope(scope, params, true)
|
374
378
|
end
|
375
379
|
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
current_scope = scope.effective_symtable(true)
|
384
|
-
until current_scope.nil?
|
385
|
-
current_scope.instance_variable_get(:@symbols)&.each_pair { |k, v| local[k] = v }
|
386
|
-
current_scope = current_scope.parent
|
387
|
-
end
|
388
|
-
newscope.push_ephemerals([local])
|
389
|
-
|
390
|
-
begin
|
391
|
-
result = catch(:return) do
|
392
|
-
args = { block.parameters[0][1].to_s => object }
|
393
|
-
block.closure.call_by_name_with_scope(newscope, args, true)
|
394
|
-
end
|
395
|
-
|
396
|
-
# If we got a return from the block, get it's value
|
397
|
-
# Otherwise the result is the last line from the block
|
398
|
-
result = result.value if result.is_a?(Puppet::Pops::Evaluator::Return)
|
380
|
+
# Call into FiberExecutor to avoid this class getting
|
381
|
+
# overloaded while also minimizing the Puppet lookups needed from plan
|
382
|
+
# functions
|
383
|
+
#
|
384
|
+
def create_future(scope: nil, name: nil, &block)
|
385
|
+
@fiber_executor.create_future(scope: scope, name: name, &block)
|
386
|
+
end
|
399
387
|
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
end
|
388
|
+
def plan_complete?
|
389
|
+
@fiber_executor.plan_complete?
|
390
|
+
end
|
404
391
|
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
e.cause
|
409
|
-
else
|
410
|
-
raise e
|
411
|
-
end
|
412
|
-
end
|
413
|
-
end
|
392
|
+
def round_robin
|
393
|
+
@fiber_executor.round_robin
|
394
|
+
end
|
414
395
|
|
415
|
-
|
396
|
+
def in_parallel?
|
397
|
+
@fiber_executor.in_parallel?
|
416
398
|
end
|
417
399
|
|
418
|
-
def
|
419
|
-
|
420
|
-
when :node_result
|
421
|
-
@thread_completed = true
|
422
|
-
end
|
400
|
+
def wait(futures, **opts)
|
401
|
+
@fiber_executor.wait(futures, **opts)
|
423
402
|
end
|
424
403
|
|
425
|
-
def
|
426
|
-
|
427
|
-
|
428
|
-
@in_parallel = true
|
429
|
-
publish_event(type: :stop_spin)
|
404
|
+
def plan_futures
|
405
|
+
@fiber_executor.plan_futures
|
406
|
+
end
|
430
407
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
skein.delete(yarn)
|
442
|
-
end
|
443
|
-
end
|
408
|
+
# Execute a plan function concurrently. This function accepts the executor
|
409
|
+
# function to be run and the parameters to pass to it, and returns the
|
410
|
+
# result of running the executor function.
|
411
|
+
#
|
412
|
+
def run_in_thread
|
413
|
+
require 'concurrent'
|
414
|
+
require 'fiber'
|
415
|
+
future = Concurrent::Future.execute do
|
416
|
+
yield
|
417
|
+
end
|
444
418
|
|
445
|
-
|
446
|
-
|
419
|
+
# Used to track how often we resume the same executor function
|
420
|
+
still_running = 0
|
421
|
+
# While the thread is still running
|
422
|
+
while future.incomplete?
|
423
|
+
# If the Fiber gets resumed, increment the resume tracker. This means
|
424
|
+
# the tracker starts at 1 since it needs to increment before yielding,
|
425
|
+
# since it can't yield then increment.
|
426
|
+
still_running += 1
|
427
|
+
# If the Fiber has been resumed before, still_running will be 2 or
|
428
|
+
# more. Yield different values for when the same Fiber is resumed
|
429
|
+
# multiple times and when it's resumed the first time in order to know
|
430
|
+
# if progress was made in the plan.
|
431
|
+
Fiber.yield(still_running < 2 ? :something_happened : :returned_immediately)
|
447
432
|
end
|
448
433
|
|
449
|
-
|
450
|
-
|
451
|
-
unsubscribe(self, [:node_result])
|
452
|
-
results
|
434
|
+
# Once the thread completes, return the result.
|
435
|
+
future.value || future.reason
|
453
436
|
end
|
454
437
|
|
455
438
|
class TimeoutError < RuntimeError; end
|
@@ -519,7 +502,7 @@ module Bolt
|
|
519
502
|
# coupled with the orchestrator transport since the transport behaves
|
520
503
|
# differently when a plan is running. In order to limit how much this
|
521
504
|
# pollutes the transport API we only handle the orchestrator transport here.
|
522
|
-
# Since we
|
505
|
+
# Since we call this function without resolving targets this will result
|
523
506
|
# in the orchestrator transport always being initialized during plan runs.
|
524
507
|
# For now that's ok.
|
525
508
|
#
|