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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc29b4aca58aa7208e448120f59687cb5fbdd0cbab78af55861b629420a9fb9e
4
- data.tar.gz: 46ec4cca8088b69d9196f3c251084bdeadaee9b676aa4c33617fd0e40a711d20
3
+ metadata.gz: 4e9167735253231222010ffb141c42048039e6b02c13061dbc6394db8876a6d7
4
+ data.tar.gz: b10298a67bb280b58c265ce2238f91ac611b672eb3c303e9f507e15db6e05e7e
5
5
  SHA512:
6
- metadata.gz: 0a0fbaff3412cc6cc7b92922fae45daf150b950d9f60a2eed1d8a97d32ffd404d7c7577167efe90fecf9425444e4acca5794ad8a49ca6248f0a91b6cb6598dec
7
- data.tar.gz: da32512009bcbe140b70374ea331a0edbe95696df347311b0b0de07f8740818088c9c2fbfc136572c20c9008c953f205c5e855e048141c9e0a933ce1c77f6d09
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
- # TODO: Remove deprecation message
400
- unless password
401
- msg = "Optional parameter for --password is deprecated and no longer prompts for password. " \
402
- "Use the prompt plugin instead to prompt for passwords."
403
- raise Bolt::CLIError, msg
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
- # TODO: Remove deprecation message
427
- unless password
428
- msg = "Optional parameter for --sudo-password is deprecated and no longer prompts for password. " \
429
- "Use the prompt plugin instead to prompt for passwords."
430
- raise Bolt::CLIError, msg
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"
@@ -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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
- VERSION = '1.36.0'
4
+ VERSION = '1.37.0'
5
5
  end
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.36.0
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-07 00:00:00.000000000 Z
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