bolt 1.36.0 → 1.37.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/bolt-modules/boltlib/lib/puppet/functions/resolve_references.rb +38 -0
- data/lib/bolt/bolt_option_parser.rb +12 -12
- data/lib/bolt/inventory/group2.rb +15 -87
- data/lib/bolt/plugin.rb +66 -0
- data/lib/bolt/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e9167735253231222010ffb141c42048039e6b02c13061dbc6394db8876a6d7
|
4
|
+
data.tar.gz: b10298a67bb280b58c265ce2238f91ac611b672eb3c303e9f507e15db6e05e7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 857e83019439072c518e50ad9c9d1c0dc93cc0e8b536f53348824091d6367fdc6df4b08c2d6c9dbf0cb45fb7fda29051c2743d470e4bba82ec7b708d7ed997cc
|
7
|
+
data.tar.gz: f91623e0811677b7c9c9f643f3a512120e7af52edbaff7d74381b0d7a40556d77dc0f7c98cf7117fdd69db504b310681157e3c44367a27fe57089e6a3dc3dc41
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
|
5
|
+
# Evaulates all _plugin references in a hash and returns the resolved reference data.
|
6
|
+
Puppet::Functions.create_function(:resolve_references) do
|
7
|
+
# Resolve references.
|
8
|
+
# @param references A hash of reference data to resolve.
|
9
|
+
# @return A hash of resolved reference data.
|
10
|
+
# @example Resolve a hash of reference data
|
11
|
+
# $references = {
|
12
|
+
# "targets" => [
|
13
|
+
# "_plugin" => "terraform",
|
14
|
+
# "dir" => "path/to/terraform/project",
|
15
|
+
# "resource_type" => "aws_instance.web",
|
16
|
+
# "uri" => "public_ip"
|
17
|
+
# ]
|
18
|
+
# }
|
19
|
+
#
|
20
|
+
# resolve_references($references)
|
21
|
+
dispatch :resolve_references do
|
22
|
+
param 'Data', :references
|
23
|
+
return_type 'Data'
|
24
|
+
end
|
25
|
+
|
26
|
+
def resolve_references(references)
|
27
|
+
unless Puppet[:tasks]
|
28
|
+
raise Puppet::ParseErrorWithIssue
|
29
|
+
.from_issue_and_stack(
|
30
|
+
Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING,
|
31
|
+
action: 'resolve_references'
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
plugins = Puppet.lookup(:bolt_inventory).plugins
|
36
|
+
plugins.resolve_references(references)
|
37
|
+
end
|
38
|
+
end
|
@@ -396,13 +396,13 @@ module Bolt
|
|
396
396
|
end
|
397
397
|
define('-p', '--password [PASSWORD]',
|
398
398
|
'Password to authenticate with') do |password|
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
399
|
+
if password.nil?
|
400
|
+
STDOUT.print "Please enter your password: "
|
401
|
+
@options[:password] = STDIN.noecho(&:gets).chomp
|
402
|
+
STDOUT.puts
|
403
|
+
else
|
404
|
+
@options[:password] = password
|
404
405
|
end
|
405
|
-
@options[:password] = password
|
406
406
|
end
|
407
407
|
define('--private-key KEY', 'Private ssh key to authenticate with') do |key|
|
408
408
|
@options[:'private-key'] = key
|
@@ -423,13 +423,13 @@ module Bolt
|
|
423
423
|
end
|
424
424
|
define('--sudo-password [PASSWORD]',
|
425
425
|
'Password for privilege escalation') do |password|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
426
|
+
if password.nil?
|
427
|
+
STDOUT.print "Please enter your privilege escalation password: "
|
428
|
+
@options[:'sudo-password'] = STDIN.noecho(&:gets).chomp
|
429
|
+
STDOUT.puts
|
430
|
+
else
|
431
|
+
@options[:'sudo-password'] = password
|
431
432
|
end
|
432
|
-
@options[:'sudo-password'] = password
|
433
433
|
end
|
434
434
|
|
435
435
|
separator "\nRun context:"
|
@@ -21,11 +21,11 @@ module Bolt
|
|
21
21
|
@logger = Logging.logger[self]
|
22
22
|
@plugins = plugins
|
23
23
|
|
24
|
-
input = resolve_top_level_references(input) if reference?(input)
|
24
|
+
input = @plugins.resolve_top_level_references(input) if @plugins.reference?(input)
|
25
25
|
|
26
26
|
raise ValidationError.new("Group does not have a name", nil) unless input.key?('name')
|
27
27
|
|
28
|
-
@name = resolve_references(input['name'])
|
28
|
+
@name = @plugins.resolve_references(input['name'])
|
29
29
|
|
30
30
|
raise ValidationError.new("Group name must be a String, not #{@name.inspect}", nil) unless @name.is_a?(String)
|
31
31
|
raise ValidationError.new("Invalid group name #{@name}", @name) unless @name =~ NAME_REGEX
|
@@ -36,7 +36,7 @@ module Bolt
|
|
36
36
|
|
37
37
|
validate_data_keys(@input)
|
38
38
|
|
39
|
-
targets = resolve_top_level_references(input.fetch('targets', []))
|
39
|
+
targets = @plugins.resolve_top_level_references(input.fetch('targets', []))
|
40
40
|
|
41
41
|
@unresolved_targets = {}
|
42
42
|
@resolved_targets = {}
|
@@ -65,83 +65,11 @@ module Bolt
|
|
65
65
|
# them until we have a value. We don't just use resolve_references
|
66
66
|
# though, since that will resolve any nested references and we want to
|
67
67
|
# leave it to the group to do that lazily.
|
68
|
-
groups = resolve_top_level_references(groups)
|
68
|
+
groups = @plugins.resolve_top_level_references(groups)
|
69
69
|
|
70
70
|
@groups = Array(groups).map { |g| Group2.new(g, plugins) }
|
71
71
|
end
|
72
72
|
|
73
|
-
# Evaluate all _plugin references in a data structure. Leaves are
|
74
|
-
# evaluated and then their parents are evaluated with references replaced
|
75
|
-
# by their values. If the result of a reference contains more references,
|
76
|
-
# they are resolved again before continuing to ascend the tree. The final
|
77
|
-
# result will not contain any references.
|
78
|
-
def resolve_references(data)
|
79
|
-
Bolt::Util.postwalk_vals(data) do |value|
|
80
|
-
reference?(value) ? resolve_references(resolve_single_reference(value)) : value
|
81
|
-
end
|
82
|
-
end
|
83
|
-
private :resolve_references
|
84
|
-
|
85
|
-
# Iteratively resolves "top-level" references until the result no longer
|
86
|
-
# has top-level references. A top-level reference is one which is not
|
87
|
-
# contained within another hash. It may be either the actual top-level
|
88
|
-
# result or arbitrarily nested within arrays. If parameters of the
|
89
|
-
# reference are themselves references, they will be looked. Any remaining
|
90
|
-
# references nested inside the result will *not* be evaluated once the
|
91
|
-
# top-level result is not a reference. This is used to resolve the
|
92
|
-
# `targets` and `groups` keys which are allowed to be references or
|
93
|
-
# arrays of references, but which may return data with nested references
|
94
|
-
# that should be resolved lazily. The end result will either be a single
|
95
|
-
# hash or a flat array of hashes.
|
96
|
-
def resolve_top_level_references(data)
|
97
|
-
if data.is_a?(Array)
|
98
|
-
data.flat_map { |elem| resolve_top_level_references(elem) }
|
99
|
-
elsif reference?(data)
|
100
|
-
partially_resolved = data.map do |k, v|
|
101
|
-
[k, resolve_references(v)]
|
102
|
-
end.to_h
|
103
|
-
fully_resolved = resolve_single_reference(partially_resolved)
|
104
|
-
# The top-level reference may have returned more references, so repeat the process
|
105
|
-
resolve_top_level_references(fully_resolved)
|
106
|
-
else
|
107
|
-
data
|
108
|
-
end
|
109
|
-
end
|
110
|
-
private :resolve_top_level_references
|
111
|
-
|
112
|
-
# Evaluates a single reference. The value returned may be another
|
113
|
-
# reference.
|
114
|
-
def resolve_single_reference(reference)
|
115
|
-
plugin_name = reference['_plugin']
|
116
|
-
begin
|
117
|
-
hook = @plugins.get_hook(plugin_name, :resolve_reference)
|
118
|
-
rescue Bolt::Plugin::PluginError => e
|
119
|
-
raise ValidationError.new(e.message, @name)
|
120
|
-
end
|
121
|
-
|
122
|
-
begin
|
123
|
-
validate_proc = @plugins.get_hook(plugin_name, :validate_resolve_reference)
|
124
|
-
rescue Bolt::Plugin::PluginError
|
125
|
-
validate_proc = proc { |*args| }
|
126
|
-
end
|
127
|
-
|
128
|
-
validate_proc.call(reference)
|
129
|
-
|
130
|
-
begin
|
131
|
-
# Evaluate the plugin and then recursively evaluate any plugin returned by it.
|
132
|
-
hook.call(reference)
|
133
|
-
rescue StandardError => e
|
134
|
-
loc = "resolve_reference in #{@name}"
|
135
|
-
raise Bolt::Plugin::PluginError::ExecutionError.new(e.message, plugin_name, loc)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
private :resolve_single_reference
|
139
|
-
|
140
|
-
# Checks whether a given value is a _plugin reference
|
141
|
-
def reference?(input)
|
142
|
-
input.is_a?(Hash) && input.key?('_plugin')
|
143
|
-
end
|
144
|
-
|
145
73
|
def target_data(target_name)
|
146
74
|
if @unresolved_targets.key?(target_name)
|
147
75
|
target = @unresolved_targets.delete(target_name)
|
@@ -170,9 +98,9 @@ module Bolt
|
|
170
98
|
raise ValidationError.new("Target entry must be a Hash, not #{target.class}", @name)
|
171
99
|
end
|
172
100
|
|
173
|
-
target['name'] = resolve_references(target['name']) if target.key?('name')
|
174
|
-
target['uri'] = resolve_references(target['uri']) if target.key?('uri')
|
175
|
-
target['alias'] = resolve_references(target['alias']) if target.key?('alias')
|
101
|
+
target['name'] = @plugins.resolve_references(target['name']) if target.key?('name')
|
102
|
+
target['uri'] = @plugins.resolve_references(target['uri']) if target.key?('uri')
|
103
|
+
target['alias'] = @plugins.resolve_references(target['alias']) if target.key?('alias')
|
176
104
|
|
177
105
|
t_name = target['name'] || target['uri']
|
178
106
|
|
@@ -303,7 +231,7 @@ module Bolt
|
|
303
231
|
end
|
304
232
|
|
305
233
|
Bolt::Util.walk_keys(input) do |key|
|
306
|
-
if reference?(key)
|
234
|
+
if @plugins.reference?(key)
|
307
235
|
raise ValidationError.new("Group keys cannot be specified as _plugin references", @name)
|
308
236
|
else
|
309
237
|
key
|
@@ -366,11 +294,11 @@ module Bolt
|
|
366
294
|
|
367
295
|
def resolve_data_keys(data, target = nil)
|
368
296
|
result = {
|
369
|
-
'config' => resolve_references(data.fetch('config', {})),
|
370
|
-
'vars' => resolve_references(data.fetch('vars', {})),
|
371
|
-
'facts' => resolve_references(data.fetch('facts', {})),
|
372
|
-
'features' => resolve_references(data.fetch('features', [])),
|
373
|
-
'plugin_hooks' => resolve_references(data.fetch('plugin_hooks', {}))
|
297
|
+
'config' => @plugins.resolve_references(data.fetch('config', {})),
|
298
|
+
'vars' => @plugins.resolve_references(data.fetch('vars', {})),
|
299
|
+
'facts' => @plugins.resolve_references(data.fetch('facts', {})),
|
300
|
+
'features' => @plugins.resolve_references(data.fetch('features', [])),
|
301
|
+
'plugin_hooks' => @plugins.resolve_references(data.fetch('plugin_hooks', {}))
|
374
302
|
}
|
375
303
|
validate_data_keys(result, target)
|
376
304
|
result['features'] = Set.new(result['features'].flatten)
|
@@ -385,13 +313,13 @@ module Bolt
|
|
385
313
|
'features' => Array,
|
386
314
|
'plugin_hooks' => Hash
|
387
315
|
}.each do |key, expected_type|
|
388
|
-
next if !data.key?(key) || data[key].is_a?(expected_type) || reference?(data[key])
|
316
|
+
next if !data.key?(key) || data[key].is_a?(expected_type) || @plugins.reference?(data[key])
|
389
317
|
|
390
318
|
msg = +"Expected #{key} to be of type #{expected_type}, not #{data[key].class}"
|
391
319
|
msg << " for target #{target}" if target
|
392
320
|
raise ValidationError.new(msg, @name)
|
393
321
|
end
|
394
|
-
unless reference?(data['config'])
|
322
|
+
unless @plugins.reference?(data['config'])
|
395
323
|
unexpected_keys = data.fetch('config', {}).keys - CONFIG_KEYS
|
396
324
|
if unexpected_keys.any?
|
397
325
|
msg = +"Found unexpected key(s) #{unexpected_keys.join(', ')} in config for"
|
data/lib/bolt/plugin.rb
CHANGED
@@ -208,6 +208,72 @@ module Bolt
|
|
208
208
|
nil
|
209
209
|
end
|
210
210
|
end
|
211
|
+
|
212
|
+
# Evaluate all _plugin references in a data structure. Leaves are
|
213
|
+
# evaluated and then their parents are evaluated with references replaced
|
214
|
+
# by their values. If the result of a reference contains more references,
|
215
|
+
# they are resolved again before continuing to ascend the tree. The final
|
216
|
+
# result will not contain any references.
|
217
|
+
def resolve_references(data)
|
218
|
+
Bolt::Util.postwalk_vals(data) do |value|
|
219
|
+
reference?(value) ? resolve_references(resolve_single_reference(value)) : value
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Iteratively resolves "top-level" references until the result no longer
|
224
|
+
# has top-level references. A top-level reference is one which is not
|
225
|
+
# contained within another hash. It may be either the actual top-level
|
226
|
+
# result or arbitrarily nested within arrays. If parameters of the
|
227
|
+
# reference are themselves references, they will be looked. Any remaining
|
228
|
+
# references nested inside the result will *not* be evaluated once the
|
229
|
+
# top-level result is not a reference. This is used to resolve the
|
230
|
+
# `targets` and `groups` keys which are allowed to be references or
|
231
|
+
# arrays of references, but which may return data with nested references
|
232
|
+
# that should be resolved lazily. The end result will either be a single
|
233
|
+
# hash or a flat array of hashes.
|
234
|
+
def resolve_top_level_references(data)
|
235
|
+
if data.is_a?(Array)
|
236
|
+
data.flat_map { |elem| resolve_top_level_references(elem) }
|
237
|
+
elsif reference?(data)
|
238
|
+
partially_resolved = data.map do |k, v|
|
239
|
+
[k, resolve_references(v)]
|
240
|
+
end.to_h
|
241
|
+
fully_resolved = resolve_single_reference(partially_resolved)
|
242
|
+
# The top-level reference may have returned more references, so repeat the process
|
243
|
+
resolve_top_level_references(fully_resolved)
|
244
|
+
else
|
245
|
+
data
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# Evaluates a single reference. The value returned may be another
|
250
|
+
# reference.
|
251
|
+
def resolve_single_reference(reference)
|
252
|
+
plugin_name = reference['_plugin']
|
253
|
+
hook = get_hook(plugin_name, :resolve_reference)
|
254
|
+
|
255
|
+
begin
|
256
|
+
validate_proc = get_hook(plugin_name, :validate_resolve_reference)
|
257
|
+
rescue PluginError
|
258
|
+
validate_proc = proc { |*args| }
|
259
|
+
end
|
260
|
+
|
261
|
+
validate_proc.call(reference)
|
262
|
+
|
263
|
+
begin
|
264
|
+
# Evaluate the plugin and then recursively evaluate any plugin returned by it.
|
265
|
+
hook.call(reference)
|
266
|
+
rescue StandardError => e
|
267
|
+
loc = "resolve_reference in #{plugin_name}"
|
268
|
+
raise PluginError::ExecutionError.new(e.message, plugin_name, loc)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
private :resolve_single_reference
|
272
|
+
|
273
|
+
# Checks whether a given value is a _plugin reference
|
274
|
+
def reference?(input)
|
275
|
+
input.is_a?(Hash) && input.key?('_plugin')
|
276
|
+
end
|
211
277
|
end
|
212
278
|
end
|
213
279
|
|
data/lib/bolt/version.rb
CHANGED
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: 1.
|
4
|
+
version: 1.37.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppet
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-11-
|
11
|
+
date: 2019-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -335,6 +335,7 @@ files:
|
|
335
335
|
- bolt-modules/boltlib/lib/puppet/functions/get_targets.rb
|
336
336
|
- bolt-modules/boltlib/lib/puppet/functions/puppetdb_fact.rb
|
337
337
|
- bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb
|
338
|
+
- bolt-modules/boltlib/lib/puppet/functions/resolve_references.rb
|
338
339
|
- bolt-modules/boltlib/lib/puppet/functions/run_command.rb
|
339
340
|
- bolt-modules/boltlib/lib/puppet/functions/run_plan.rb
|
340
341
|
- bolt-modules/boltlib/lib/puppet/functions/run_script.rb
|