bolt 3.6.1 → 3.9.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 +3 -3
- data/bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb +26 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/containerresult.rb +27 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/future.rb +25 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resourceinstance.rb +43 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +29 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb +34 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/target.rb +55 -0
- data/bolt-modules/boltlib/lib/puppet/functions/add_to_group.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +10 -6
- 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 +29 -13
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_command.rb +66 -0
- data/bolt-modules/boltlib/lib/puppet/functions/remove_from_group.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +5 -15
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +10 -18
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +5 -17
- data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +5 -15
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +10 -18
- data/bolt-modules/boltlib/lib/puppet/functions/wait.rb +91 -0
- data/bolt-modules/boltlib/lib/puppet/functions/write_file.rb +1 -0
- data/bolt-modules/boltlib/types/planresult.pp +1 -0
- data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +2 -0
- data/bolt-modules/file/lib/puppet/functions/file/exists.rb +9 -3
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +6 -2
- data/bolt-modules/file/lib/puppet/functions/file/readable.rb +8 -3
- data/guides/guide.txt +17 -0
- data/guides/inventory.txt +5 -0
- data/guides/links.txt +13 -0
- data/guides/targets.txt +29 -0
- data/guides/transports.txt +23 -0
- data/lib/bolt/applicator.rb +4 -3
- data/lib/bolt/bolt_option_parser.rb +353 -227
- data/lib/bolt/catalog.rb +2 -1
- data/lib/bolt/cli.rb +94 -36
- data/lib/bolt/config/options.rb +2 -1
- data/lib/bolt/config/transport/docker.rb +5 -1
- data/lib/bolt/config/transport/lxd.rb +1 -1
- data/lib/bolt/config/transport/options.rb +2 -1
- data/lib/bolt/config/transport/podman.rb +5 -1
- data/lib/bolt/error.rb +11 -1
- data/lib/bolt/executor.rb +51 -72
- data/lib/bolt/fiber_executor.rb +141 -0
- data/lib/bolt/inventory.rb +5 -4
- data/lib/bolt/inventory/inventory.rb +3 -2
- data/lib/bolt/logger.rb +1 -1
- data/lib/bolt/module_installer/specs.rb +1 -1
- data/lib/bolt/module_installer/specs/git_spec.rb +10 -6
- data/lib/bolt/outputter/human.rb +59 -29
- data/lib/bolt/outputter/json.rb +8 -4
- data/lib/bolt/pal.rb +64 -3
- data/lib/bolt/pal/yaml_plan/step.rb +4 -2
- data/lib/bolt/plan_creator.rb +2 -2
- data/lib/bolt/plan_future.rb +66 -0
- data/lib/bolt/puppetdb/client.rb +54 -0
- data/lib/bolt/result.rb +5 -0
- data/lib/bolt/transport/docker/connection.rb +7 -4
- data/lib/bolt/transport/lxd/connection.rb +4 -0
- data/lib/bolt/transport/podman/connection.rb +4 -0
- data/lib/bolt/transport/ssh/connection.rb +3 -6
- data/lib/bolt/util.rb +73 -1
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_spec/plans/mock_executor.rb +42 -45
- metadata +12 -3
- data/lib/bolt/yarn.rb +0 -23
@@ -112,17 +112,13 @@ Puppet::Functions.create_function(:download_file, Puppet::Functions::InternalFun
|
|
112
112
|
call_function('debug', "Simulating file download of '#{source}' - no targets given - no action taken")
|
113
113
|
Bolt::ResultSet.new([])
|
114
114
|
else
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
executor.download_file(targets, source, destination, options, Puppet::Pops::PuppetStack.top_of_stack)
|
115
|
+
file_line = Puppet::Pops::PuppetStack.top_of_stack
|
116
|
+
r = if executor.in_parallel?
|
117
|
+
executor.run_in_thread do
|
118
|
+
executor.download_file(targets, source, destination, options, file_line)
|
120
119
|
end
|
121
|
-
|
122
|
-
Fiber.yield('unfinished') while future.incomplete?
|
123
|
-
future.value || future.reason
|
124
120
|
else
|
125
|
-
executor.download_file(targets, source, destination, options,
|
121
|
+
executor.download_file(targets, source, destination, options, file_line)
|
126
122
|
end
|
127
123
|
|
128
124
|
if !r.ok && !options[:catch_errors]
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'bolt/yarn'
|
4
|
-
|
5
3
|
# Map a code block onto an array, where each array element executes in parallel.
|
6
4
|
# This function is experimental.
|
7
5
|
#
|
@@ -10,6 +8,7 @@ Puppet::Functions.create_function(:parallelize, Puppet::Functions::InternalFunct
|
|
10
8
|
# Map a block onto an array, where each array element executes in parallel.
|
11
9
|
# This function is experimental.
|
12
10
|
# @param data The array to apply the block to.
|
11
|
+
# @param block The code block to execute for each array element.
|
13
12
|
# @return [Array] An array of PlanResult objects. Each input from the input
|
14
13
|
# array returns a corresponding PlanResult object.
|
15
14
|
# @example Execute two tasks on two targets.
|
@@ -34,21 +33,38 @@ Puppet::Functions.create_function(:parallelize, Puppet::Functions::InternalFunct
|
|
34
33
|
executor = Puppet.lookup(:bolt_executor)
|
35
34
|
executor.report_function_call(self.class.name)
|
36
35
|
|
37
|
-
|
38
|
-
executor.
|
39
|
-
|
36
|
+
futures = data.map do |object|
|
37
|
+
executor.create_future(scope: scope) do |newscope|
|
38
|
+
# Catch 'return' calls inside the block
|
39
|
+
result = catch(:return) do
|
40
|
+
# Add the object to the block parameters
|
41
|
+
args = { block.parameters[0][1].to_s => object }
|
42
|
+
# Execute the block. Individual plan steps in the block will yield
|
43
|
+
# the Fiber if they haven't finished, so all this needs to do is run
|
44
|
+
# the block.
|
45
|
+
block.closure.call_by_name_with_scope(newscope, args, true)
|
46
|
+
end
|
40
47
|
|
41
|
-
|
48
|
+
# If we got a return from the block, get its value
|
49
|
+
# Otherwise the result is the last line from the block
|
50
|
+
result = result.value if result.is_a?(Puppet::Pops::Evaluator::Return)
|
42
51
|
|
43
|
-
|
44
|
-
|
45
|
-
|
52
|
+
# Validate the result is a PlanResult
|
53
|
+
unless Puppet::Pops::Types::TypeParser.singleton.parse('Boltlib::PlanResult').instance?(result)
|
54
|
+
raise Bolt::InvalidParallelResult.new(result.to_s, *Puppet::Pops::PuppetStack.top_of_stack)
|
55
|
+
end
|
46
56
|
|
47
|
-
|
48
|
-
|
49
|
-
|
57
|
+
result
|
58
|
+
rescue Puppet::PreformattedError => e
|
59
|
+
if e.cause.is_a?(Bolt::Error)
|
60
|
+
e.cause
|
61
|
+
else
|
62
|
+
raise e
|
63
|
+
end
|
64
|
+
end
|
50
65
|
end
|
51
66
|
|
52
|
-
|
67
|
+
# We may eventually want parallelize to accept a timeout
|
68
|
+
executor.wait(futures)
|
53
69
|
end
|
54
70
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
|
5
|
+
# Send a command with a payload to PuppetDB.
|
6
|
+
#
|
7
|
+
# The `pdb_command` function only supports version 5 of the `replace_facts`
|
8
|
+
# command. Other commands might also work, but are not tested or supported
|
9
|
+
# by Bolt.
|
10
|
+
#
|
11
|
+
# See the [commands endpoint](https://puppet.com/docs/puppetdb/latest/api/command/v1/commands.html)
|
12
|
+
# documentation for more information about available commands and payload
|
13
|
+
# format.
|
14
|
+
#
|
15
|
+
# _This function is experimental and subject to change._
|
16
|
+
#
|
17
|
+
# > **Note:** Not available in apply block
|
18
|
+
#
|
19
|
+
Puppet::Functions.create_function(:puppetdb_command) do
|
20
|
+
# @param command The command to invoke.
|
21
|
+
# @param version The version of the command to invoke.
|
22
|
+
# @param payload The payload to the command.
|
23
|
+
# @return The UUID identifying the response sent by PuppetDB.
|
24
|
+
# @example Replace facts for a target
|
25
|
+
# $payload = {
|
26
|
+
# 'certname' => 'localhost',
|
27
|
+
# 'environment' => 'dev',
|
28
|
+
# 'producer' => 'bolt',
|
29
|
+
# 'producer_timestamp' => '1970-01-01',
|
30
|
+
# 'values' => { 'orchestrator' => 'bolt' }
|
31
|
+
# }
|
32
|
+
#
|
33
|
+
# puppetdb_command('replace_facts', 5, $payload)
|
34
|
+
dispatch :puppetdb_command do
|
35
|
+
param 'String[1]', :command
|
36
|
+
param 'Integer', :version
|
37
|
+
param 'Hash[Data, Data]', :payload
|
38
|
+
return_type 'String'
|
39
|
+
end
|
40
|
+
|
41
|
+
def puppetdb_command(command, version, payload)
|
42
|
+
# Disallow in apply blocks.
|
43
|
+
unless Puppet[:tasks]
|
44
|
+
raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
|
45
|
+
Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING,
|
46
|
+
action: 'puppetdb_command'
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Send analytics report.
|
51
|
+
Puppet.lookup(:bolt_executor).report_function_call(self.class.name)
|
52
|
+
|
53
|
+
puppetdb_client = Puppet.lookup(:bolt_pdb_client)
|
54
|
+
|
55
|
+
# Error if the PDB client does not implement :send_command
|
56
|
+
unless puppetdb_client.respond_to?(:send_command)
|
57
|
+
raise Bolt::Error.new(
|
58
|
+
"PuppetDB client #{puppetdb_client.class} does not implement :send_command, "\
|
59
|
+
"unable to invoke command.",
|
60
|
+
'bolt/pdb-command'
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
puppetdb_client.send_command(command, version, payload)
|
65
|
+
end
|
66
|
+
end
|
@@ -11,6 +11,7 @@ require 'bolt/error'
|
|
11
11
|
Puppet::Functions.create_function(:remove_from_group) do
|
12
12
|
# @param target A pattern identifying a single target.
|
13
13
|
# @param group The name of the group to remove the target from.
|
14
|
+
# @return [nil]
|
14
15
|
# @example Remove Target from group.
|
15
16
|
# remove_from_group('foo@example.com', 'group1')
|
16
17
|
# @example Remove failing Targets from the rest of a plan
|
@@ -87,23 +87,13 @@ Puppet::Functions.create_function(:run_command) do
|
|
87
87
|
call_function('debug', "Simulating run_command('#{command}') - no targets given - no action taken")
|
88
88
|
Bolt::ResultSet.new([])
|
89
89
|
else
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
executor.run_command(targets,
|
95
|
-
command,
|
96
|
-
options,
|
97
|
-
Puppet::Pops::PuppetStack.top_of_stack)
|
90
|
+
file_line = Puppet::Pops::PuppetStack.top_of_stack
|
91
|
+
r = if executor.in_parallel?
|
92
|
+
executor.run_in_thread do
|
93
|
+
executor.run_command(targets, command, options, file_line)
|
98
94
|
end
|
99
|
-
|
100
|
-
Fiber.yield('unfinished') while future.incomplete?
|
101
|
-
future.value || future.reason
|
102
95
|
else
|
103
|
-
executor.run_command(targets,
|
104
|
-
command,
|
105
|
-
options,
|
106
|
-
Puppet::Pops::PuppetStack.top_of_stack)
|
96
|
+
executor.run_command(targets, command, options, file_line)
|
107
97
|
end
|
108
98
|
|
109
99
|
if !r.ok && !options[:catch_errors]
|
@@ -108,7 +108,11 @@ Puppet::Functions.create_function(:run_script, Puppet::Functions::InternalFuncti
|
|
108
108
|
# Send Analytics Report
|
109
109
|
executor.report_function_call(self.class.name)
|
110
110
|
|
111
|
-
|
111
|
+
future = executor&.future || {}
|
112
|
+
fallback = future.fetch('file_paths', false)
|
113
|
+
|
114
|
+
# Find the file path if it exists, otherwise return nil
|
115
|
+
found = Bolt::Util.find_file_from_scope(script, scope, fallback)
|
112
116
|
unless found && Puppet::FileSystem.exist?(found)
|
113
117
|
raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
|
114
118
|
Puppet::Pops::Issues::NO_SUCH_FILE_OR_DIRECTORY, file: script
|
@@ -126,25 +130,13 @@ Puppet::Functions.create_function(:run_script, Puppet::Functions::InternalFuncti
|
|
126
130
|
if targets.empty?
|
127
131
|
Bolt::ResultSet.new([])
|
128
132
|
else
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
executor.run_script(targets,
|
134
|
-
found,
|
135
|
-
arguments,
|
136
|
-
options,
|
137
|
-
Puppet::Pops::PuppetStack.top_of_stack)
|
133
|
+
file_line = Puppet::Pops::PuppetStack.top_of_stack
|
134
|
+
r = if executor.in_parallel?
|
135
|
+
executor.run_in_thread do
|
136
|
+
executor.run_script(targets, found, arguments, options, file_line)
|
138
137
|
end
|
139
|
-
|
140
|
-
Fiber.yield('unfinished') while future.incomplete?
|
141
|
-
future.value || future.reason
|
142
138
|
else
|
143
|
-
executor.run_script(targets,
|
144
|
-
found,
|
145
|
-
arguments,
|
146
|
-
options,
|
147
|
-
Puppet::Pops::PuppetStack.top_of_stack)
|
139
|
+
executor.run_script(targets, found, arguments, options, file_line)
|
148
140
|
end
|
149
141
|
|
150
142
|
if !r.ok && !options[:catch_errors]
|
@@ -133,25 +133,13 @@ Puppet::Functions.create_function(:run_task) do
|
|
133
133
|
if targets.empty?
|
134
134
|
Bolt::ResultSet.new([])
|
135
135
|
else
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
executor.run_task(targets,
|
141
|
-
task,
|
142
|
-
params,
|
143
|
-
options,
|
144
|
-
Puppet::Pops::PuppetStack.top_of_stack)
|
136
|
+
file_line = Puppet::Pops::PuppetStack.top_of_stack
|
137
|
+
result = if executor.in_parallel?
|
138
|
+
executor.run_in_thread do
|
139
|
+
executor.run_task(targets, task, params, options, file_line)
|
145
140
|
end
|
146
|
-
|
147
|
-
Fiber.yield('unfinished') while future.incomplete?
|
148
|
-
future.value || future.reason
|
149
141
|
else
|
150
|
-
executor.run_task(targets,
|
151
|
-
task,
|
152
|
-
params,
|
153
|
-
options,
|
154
|
-
Puppet::Pops::PuppetStack.top_of_stack)
|
142
|
+
executor.run_task(targets, task, params, options, file_line)
|
155
143
|
end
|
156
144
|
|
157
145
|
if !result.ok && !options[:catch_errors]
|
@@ -180,23 +180,13 @@ Puppet::Functions.create_function(:run_task_with) do
|
|
180
180
|
else
|
181
181
|
# Combine the results from the task run with any failing results that were
|
182
182
|
# generated earlier when creating the target mapping
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
executor.run_task_with(target_mapping,
|
188
|
-
task,
|
189
|
-
options,
|
190
|
-
Puppet::Pops::PuppetStack.top_of_stack)
|
183
|
+
file_line = Puppet::Pops::PuppetStack.top_of_stack
|
184
|
+
task_result = if executor.in_parallel?
|
185
|
+
executor.run_in_thread do
|
186
|
+
executor.run_task_with(target_mapping, task, options, file_line)
|
191
187
|
end
|
192
|
-
|
193
|
-
Fiber.yield('unfinished') while future.incomplete?
|
194
|
-
future.value || future.reason
|
195
188
|
else
|
196
|
-
executor.run_task_with(target_mapping,
|
197
|
-
task,
|
198
|
-
options,
|
199
|
-
Puppet::Pops::PuppetStack.top_of_stack)
|
189
|
+
executor.run_task_with(target_mapping, task, options, file_line)
|
200
190
|
end
|
201
191
|
result = Bolt::ResultSet.new(task_result.results + error_set)
|
202
192
|
|
@@ -70,7 +70,11 @@ Puppet::Functions.create_function(:upload_file, Puppet::Functions::InternalFunct
|
|
70
70
|
# Send Analytics Report
|
71
71
|
executor.report_function_call(self.class.name)
|
72
72
|
|
73
|
-
|
73
|
+
future = executor&.future || {}
|
74
|
+
fallback = future.fetch('file_paths', false)
|
75
|
+
|
76
|
+
# Find the file path if it exists, otherwise return nil
|
77
|
+
found = Bolt::Util.find_file_from_scope(source, scope, fallback)
|
74
78
|
unless found && Puppet::FileSystem.exist?(found)
|
75
79
|
raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
|
76
80
|
Puppet::Pops::Issues::NO_SUCH_FILE_OR_DIRECTORY, file: source
|
@@ -83,25 +87,13 @@ Puppet::Functions.create_function(:upload_file, Puppet::Functions::InternalFunct
|
|
83
87
|
call_function('debug', "Simulating file upload of '#{found}' - no targets given - no action taken")
|
84
88
|
Bolt::ResultSet.new([])
|
85
89
|
else
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
executor.upload_file(targets,
|
91
|
-
found,
|
92
|
-
destination,
|
93
|
-
options,
|
94
|
-
Puppet::Pops::PuppetStack.top_of_stack)
|
90
|
+
file_line = Puppet::Pops::PuppetStack.top_of_stack
|
91
|
+
r = if executor.in_parallel?
|
92
|
+
executor.run_in_thread do
|
93
|
+
executor.upload_file(targets, found, destination, options, file_line)
|
95
94
|
end
|
96
|
-
|
97
|
-
Fiber.yield('unfinished') while future.incomplete?
|
98
|
-
future.value || future.reason
|
99
95
|
else
|
100
|
-
executor.upload_file(targets,
|
101
|
-
found,
|
102
|
-
destination,
|
103
|
-
options,
|
104
|
-
Puppet::Pops::PuppetStack.top_of_stack)
|
96
|
+
executor.upload_file(targets, found, destination, options, file_line)
|
105
97
|
end
|
106
98
|
if !r.ok && !options[:catch_errors]
|
107
99
|
raise Bolt::RunFailure.new(r, 'upload_file', source)
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/logger'
|
4
|
+
require 'bolt/target'
|
5
|
+
|
6
|
+
# Wait for a Future or array of Futures to finish and return results,
|
7
|
+
# optionally with a timeout.
|
8
|
+
#
|
9
|
+
# > **Note:** Not available in apply block
|
10
|
+
Puppet::Functions.create_function(:wait, Puppet::Functions::InternalFunction) do
|
11
|
+
# Wait for Future(s) to finish
|
12
|
+
# @param futures A Bolt Future object or array of Bolt Futures to wait on.
|
13
|
+
# @param options A hash of additional options.
|
14
|
+
# @option options [Boolean] _catch_errors Whether to catch raised errors.
|
15
|
+
# @return A Result or Results from the Futures
|
16
|
+
# @example Upload a large file in the background, then wait until it's loaded
|
17
|
+
# $futures = background() || {
|
18
|
+
# upload_file("./very_large_file", "/opt/jfrog/artifactory/var/etc/artifactory", $targets)
|
19
|
+
# }
|
20
|
+
# # Run an unrelated task
|
21
|
+
# run_task("deploy", $targets)
|
22
|
+
# # Wait for the file upload to finish
|
23
|
+
# $results = wait($futures)
|
24
|
+
dispatch :wait do
|
25
|
+
param 'Variant[Future, Array[Future]]', :futures
|
26
|
+
optional_param 'Hash[String[1], Any]', :options
|
27
|
+
return_type 'Array[Boltlib::PlanResult]'
|
28
|
+
end
|
29
|
+
|
30
|
+
# Wait for Future(s) to finish with timeout
|
31
|
+
# @param futures A Bolt Future object or array of Bolt Futures to wait on.
|
32
|
+
# @param timeout How long to wait for Futures to finish before raising a Timeout error.
|
33
|
+
# @param options A hash of additional options.
|
34
|
+
# @option options [Boolean] _catch_errors Whether to catch raised errors.
|
35
|
+
# @return A Result or Results from the Futures
|
36
|
+
# @example Upload a large file in the background with a 30 second timeout.
|
37
|
+
# $futures = background() || {
|
38
|
+
# upload_file("./very_large_file", "/opt/jfrog/artifactory/var/etc/artifactory", $targets)
|
39
|
+
# }
|
40
|
+
# # Run an unrelated task
|
41
|
+
# run_task("deploy", $targets)
|
42
|
+
# # Wait for the file upload to finish
|
43
|
+
# $results = wait($futures, 30)
|
44
|
+
#
|
45
|
+
# @example Upload a large file in the background with a 30 second timeout, catching any errors.
|
46
|
+
# $futures = background() || {
|
47
|
+
# upload_file("./very_large_file", "/opt/jfrog/artifactory/var/etc/artifactory", $targets)
|
48
|
+
# }
|
49
|
+
# # Run an unrelated task
|
50
|
+
# run_task("deploy", $targets)
|
51
|
+
# # Wait for the file upload to finish
|
52
|
+
# $results = wait($futures, 30, '_catch_errors' => true)
|
53
|
+
dispatch :wait_with_timeout do
|
54
|
+
param 'Variant[Future, Array[Future]]', :futures
|
55
|
+
param 'Variant[Integer[0], Float[0.0]]', :timeout
|
56
|
+
optional_param 'Hash[String[1], Any]', :options
|
57
|
+
return_type 'Array[Boltlib::PlanResult]'
|
58
|
+
end
|
59
|
+
|
60
|
+
def wait(futures, options = {})
|
61
|
+
inner_wait(futures, nil, options)
|
62
|
+
end
|
63
|
+
|
64
|
+
def wait_with_timeout(futures, timeout, options = {})
|
65
|
+
inner_wait(futures, timeout, options)
|
66
|
+
end
|
67
|
+
|
68
|
+
def inner_wait(futures, timeout = nil, options = {})
|
69
|
+
unless Puppet[:tasks]
|
70
|
+
raise Puppet::ParseErrorWithIssue
|
71
|
+
.from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'wait')
|
72
|
+
end
|
73
|
+
|
74
|
+
valid, unknown = options.partition { |k, _v| %w[_catch_errors].include?(k) }.map(&:to_h)
|
75
|
+
if unknown.any?
|
76
|
+
file, line = Puppet::Pops::PuppetStack.top_of_stack
|
77
|
+
msg = "The wait() function call in #{file}#L#{line} received unknown options "\
|
78
|
+
"#{unknown.keys}. Removing unknown options and continuing..."
|
79
|
+
Bolt::Logger.warn("plan_function_options", msg)
|
80
|
+
end
|
81
|
+
|
82
|
+
valid = valid.transform_keys { |k| k.sub(/^_/, '').to_sym }
|
83
|
+
valid[:timeout] = timeout if timeout
|
84
|
+
|
85
|
+
executor = Puppet.lookup(:bolt_executor)
|
86
|
+
executor.report_function_call(self.class.name)
|
87
|
+
|
88
|
+
futures = Array(futures)
|
89
|
+
executor.wait(futures, **valid)
|
90
|
+
end
|
91
|
+
end
|
@@ -9,6 +9,7 @@ Puppet::Functions.create_function(:write_file) do
|
|
9
9
|
# @param content File content to write.
|
10
10
|
# @param destination An absolute path on the target(s).
|
11
11
|
# @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
|
12
|
+
# @param options A hash of additional options.
|
12
13
|
# @option options [Boolean] _catch_errors Whether to catch raised errors.
|
13
14
|
# @option options [String] _run_as User to run as using privilege escalation.
|
14
15
|
# @return A list of results, one entry per target.
|