bolt 1.37.0 → 1.38.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 +2 -1
- data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +2 -2
- data/bolt-modules/file/lib/puppet/functions/file/exists.rb +1 -1
- data/bolt-modules/file/lib/puppet/functions/file/readable.rb +1 -1
- data/bolt-modules/system/lib/puppet/functions/system/env.rb +1 -1
- data/lib/bolt/bolt_option_parser.rb +35 -2
- data/lib/bolt/cli.rb +72 -6
- data/lib/bolt/config.rb +24 -23
- data/lib/bolt/inventory.rb +1 -1
- data/lib/bolt/inventory/target.rb +1 -1
- data/lib/bolt/plugin.rb +50 -22
- data/lib/bolt/plugin/module.rb +11 -9
- data/lib/bolt/plugin/prompt.rb +1 -1
- data/lib/bolt/plugin/task.rb +3 -1
- data/lib/bolt/util.rb +4 -0
- data/lib/bolt/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56eab83c9278b21bfe1241b6fcbbfac9a06adc976d77a7d5900a4940393ea5cd
|
4
|
+
data.tar.gz: c1389de9cad81f4f8ba9b2af9b3aa74bffdbc92e0f9c88ae6f018e7fa43ded1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 104b2eda64ad81d4fc6bbf054309498866b6e8f3e256f455c06b19bb5a2c6e50192dc2c480ffa7c885e2afb2bebc0648e5feb295f22f7a9cc6b5f250b548ea22
|
7
|
+
data.tar.gz: 6115db7ac02b54224e346d12c2bd2fa98d6eee3031b4ae5093f89d0c2883e000cccb63428ace63b6e9a6ed173afafe327274b0b829109c9d3bd1c6fd75b9f699
|
data/Puppetfile
CHANGED
@@ -7,7 +7,7 @@ moduledir File.join(File.dirname(__FILE__), 'modules')
|
|
7
7
|
# Core modules used by 'apply'
|
8
8
|
mod 'puppetlabs-service', '1.1.0'
|
9
9
|
mod 'puppetlabs-facts', '0.6.0'
|
10
|
-
mod 'puppetlabs-puppet_agent', '2.2.
|
10
|
+
mod 'puppetlabs-puppet_agent', '2.2.2'
|
11
11
|
|
12
12
|
# Core types and providers for Puppet 6
|
13
13
|
mod 'puppetlabs-augeas_core', '1.0.5'
|
@@ -33,6 +33,7 @@ mod 'puppetlabs-azure_inventory', '0.2.0'
|
|
33
33
|
mod 'puppetlabs-terraform', '0.2.0'
|
34
34
|
mod 'puppetlabs-vault', '0.2.2'
|
35
35
|
mod 'puppetlabs-aws_inventory', '0.2.0'
|
36
|
+
mod 'puppetlabs-yaml', '0.1.0'
|
36
37
|
|
37
38
|
# If we don't list these modules explicitly, r10k will purge them
|
38
39
|
mod 'canary', local: true
|
@@ -50,8 +50,8 @@ Puppet::Functions.create_function(:apply_prep) do
|
|
50
50
|
end
|
51
51
|
# rubocop:enable Naming/AccessorMethodName
|
52
52
|
|
53
|
-
def run_task(targets, task, args = {})
|
54
|
-
executor.run_task(targets, task, args)
|
53
|
+
def run_task(targets, task, args = {}, options = {})
|
54
|
+
executor.run_task(targets, task, args, options)
|
55
55
|
end
|
56
56
|
|
57
57
|
# Returns true if the target has the puppet-agent feature defined, either from inventory or transport.
|
@@ -16,6 +16,6 @@ Puppet::Functions.create_function(:'file::exists', Puppet::Functions::InternalFu
|
|
16
16
|
def exists(scope, filename)
|
17
17
|
Puppet.lookup(:bolt_executor) {}&.report_function_call(self.class.name)
|
18
18
|
found = Puppet::Parser::Files.find_file(filename, scope.compiler.environment)
|
19
|
-
found
|
19
|
+
found ? Puppet::FileSystem.exist?(found) : false
|
20
20
|
end
|
21
21
|
end
|
@@ -16,6 +16,6 @@ Puppet::Functions.create_function(:'file::readable', Puppet::Functions::Internal
|
|
16
16
|
def readable(scope, filename)
|
17
17
|
Puppet.lookup(:bolt_executor) {}&.report_function_call(self.class.name)
|
18
18
|
found = Puppet::Parser::Files.find_file(filename, scope.compiler.environment)
|
19
|
-
found
|
19
|
+
found ? File.readable?(found) : false
|
20
20
|
end
|
21
21
|
end
|
@@ -7,8 +7,8 @@ require 'optparse'
|
|
7
7
|
module Bolt
|
8
8
|
class BoltOptionParser < OptionParser
|
9
9
|
OPTIONS = { inventory: %w[nodes targets query rerun description],
|
10
|
-
authentication: %w[user password private-key host-key-check ssl ssl-verify],
|
11
|
-
escalation: %w[run-as sudo-password],
|
10
|
+
authentication: %w[user password password-prompt private-key host-key-check ssl ssl-verify],
|
11
|
+
escalation: %w[run-as sudo-password sudo-password-prompt],
|
12
12
|
run_context: %w[concurrency inventoryfile save-rerun],
|
13
13
|
global_config_setters: %w[modulepath boltdir configfile],
|
14
14
|
transports: %w[transport connect-timeout tty],
|
@@ -54,6 +54,9 @@ module Bolt
|
|
54
54
|
when 'init'
|
55
55
|
{ flags: OPTIONS[:global],
|
56
56
|
banner: PROJECT_INIT_HELP }
|
57
|
+
when 'migrate'
|
58
|
+
{ flags: OPTIONS[:global] + %w[inventoryfile boltdir configfile],
|
59
|
+
banner: PROJECT_MIGRATE_HELP }
|
57
60
|
else
|
58
61
|
{ flags: OPTIONS[:global],
|
59
62
|
banner: PROJECT_HELP }
|
@@ -131,6 +134,7 @@ module Bolt
|
|
131
134
|
bolt inventory show Show the list of targets an action would run on
|
132
135
|
bolt group show Show the list of groups in the inventory
|
133
136
|
bolt project init Create a new Bolt project
|
137
|
+
bolt project migrate Migrate a Bolt project to the latest version
|
134
138
|
|
135
139
|
Run `bolt <subcommand> --help` to view specific examples.
|
136
140
|
|
@@ -325,6 +329,7 @@ module Bolt
|
|
325
329
|
|
326
330
|
Available actions are:
|
327
331
|
init Create a new Bolt project
|
332
|
+
migrate Migrate a Bolt project to the latest version
|
328
333
|
|
329
334
|
Available options are:
|
330
335
|
PROJECT_HELP
|
@@ -338,10 +343,22 @@ module Bolt
|
|
338
343
|
Available options are:
|
339
344
|
PROJECT_INIT_HELP
|
340
345
|
|
346
|
+
PROJECT_MIGRATE_HELP = <<~PROJECT_MIGRATE_HELP
|
347
|
+
Usage: bolt project migrate
|
348
|
+
|
349
|
+
Migrate a Bolt project to the latest version.
|
350
|
+
Loads a Bolt project's inventory file and migrates it to the latest version. The
|
351
|
+
inventory file is modified in place and will not preserve comments or formatting.
|
352
|
+
|
353
|
+
Available options are:
|
354
|
+
PROJECT_MIGRATE_HELP
|
355
|
+
|
356
|
+
attr_reader :warnings
|
341
357
|
def initialize(options)
|
342
358
|
super()
|
343
359
|
|
344
360
|
@options = options
|
361
|
+
@warnings = []
|
345
362
|
|
346
363
|
define('-n', '--nodes NODES',
|
347
364
|
'Alias for --targets',
|
@@ -397,6 +414,9 @@ module Bolt
|
|
397
414
|
define('-p', '--password [PASSWORD]',
|
398
415
|
'Password to authenticate with') do |password|
|
399
416
|
if password.nil?
|
417
|
+
msg = "Optional parameter for --password is deprecated and will no longer prompt for password. " \
|
418
|
+
"Use the prompt plugin or --password-prompt instead to prompt for passwords."
|
419
|
+
@warnings << { option: 'password', msg: msg }
|
400
420
|
STDOUT.print "Please enter your password: "
|
401
421
|
@options[:password] = STDIN.noecho(&:gets).chomp
|
402
422
|
STDOUT.puts
|
@@ -404,6 +424,11 @@ module Bolt
|
|
404
424
|
@options[:password] = password
|
405
425
|
end
|
406
426
|
end
|
427
|
+
define('--password-prompt', 'Prompt for user to input password') do |_password|
|
428
|
+
STDERR.print "Please enter your password: "
|
429
|
+
@options[:password] = STDIN.noecho(&:gets).chomp
|
430
|
+
STDERR.puts
|
431
|
+
end
|
407
432
|
define('--private-key KEY', 'Private ssh key to authenticate with') do |key|
|
408
433
|
@options[:'private-key'] = key
|
409
434
|
end
|
@@ -424,6 +449,9 @@ module Bolt
|
|
424
449
|
define('--sudo-password [PASSWORD]',
|
425
450
|
'Password for privilege escalation') do |password|
|
426
451
|
if password.nil?
|
452
|
+
msg = "Optional parameter for --sudo-password is deprecated and will no longer prompt for password. " \
|
453
|
+
"Use the prompt plugin or --sudo-password-prompt instead to prompt for passwords."
|
454
|
+
@warnings << { option: 'sudo-password', msg: msg }
|
427
455
|
STDOUT.print "Please enter your privilege escalation password: "
|
428
456
|
@options[:'sudo-password'] = STDIN.noecho(&:gets).chomp
|
429
457
|
STDOUT.puts
|
@@ -431,6 +459,11 @@ module Bolt
|
|
431
459
|
@options[:'sudo-password'] = password
|
432
460
|
end
|
433
461
|
end
|
462
|
+
define('--sudo-password-prompt', 'Prompt for user to input escalation password') do |_password|
|
463
|
+
STDERR.print "Please enter your privilege escalation password: "
|
464
|
+
@options[:'sudo-password'] = STDIN.noecho(&:gets).chomp
|
465
|
+
STDERR.puts
|
466
|
+
end
|
434
467
|
|
435
468
|
separator "\nRun context:"
|
436
469
|
define('-c', '--concurrency CONCURRENCY', Integer,
|
data/lib/bolt/cli.rb
CHANGED
@@ -37,7 +37,7 @@ module Bolt
|
|
37
37
|
'secret' => %w[encrypt decrypt createkeys],
|
38
38
|
'inventory' => %w[show],
|
39
39
|
'group' => %w[show],
|
40
|
-
'project' => %w[init],
|
40
|
+
'project' => %w[init migrate],
|
41
41
|
'apply' => %w[] }.freeze
|
42
42
|
|
43
43
|
attr_reader :config, :options
|
@@ -129,6 +129,7 @@ module Bolt
|
|
129
129
|
# Logger must be configured before checking path case, otherwise warnings will not display
|
130
130
|
@config.check_path_case('modulepath', @config.modulepath)
|
131
131
|
|
132
|
+
parser.warnings.each { |warning| @logger.warn(warning[:msg]) }
|
132
133
|
# After validation, initialize inventory and targets. Errors here are better to catch early.
|
133
134
|
# After this step
|
134
135
|
# options[:target_args] will contain a string/array version of the targetting options this is passed to plans
|
@@ -367,7 +368,11 @@ module Bolt
|
|
367
368
|
|
368
369
|
case options[:subcommand]
|
369
370
|
when 'project'
|
370
|
-
|
371
|
+
if options[:action] == 'init'
|
372
|
+
code = initialize_project
|
373
|
+
elsif options[:action] == 'migrate'
|
374
|
+
code = migrate_project
|
375
|
+
end
|
371
376
|
when 'plan'
|
372
377
|
code = run_plan(options[:object], options[:task_options], options[:target_args], options)
|
373
378
|
when 'puppetfile'
|
@@ -472,13 +477,27 @@ module Bolt
|
|
472
477
|
|
473
478
|
def run_plan(plan_name, plan_arguments, nodes, options)
|
474
479
|
unless nodes.empty?
|
475
|
-
if plan_arguments['nodes']
|
480
|
+
if plan_arguments['nodes'] || plan_arguments['targets']
|
481
|
+
key = plan_arguments.include?('nodes') ? 'nodes' : 'targets'
|
476
482
|
raise Bolt::CLIError,
|
477
|
-
"A plan's '
|
478
|
-
"case it must not be specified as a separate
|
483
|
+
"A plan's '#{key}' parameter may be specified using the --#{key} option, but in that " \
|
484
|
+
"case it must not be specified as a separate #{key}=<value> parameter nor included " \
|
479
485
|
"in the JSON data passed in the --params option"
|
480
486
|
end
|
481
|
-
|
487
|
+
|
488
|
+
plan_params = pal.get_plan_info(plan_name)['parameters']
|
489
|
+
target_param = plan_params.dig('targets', 'type') =~ /TargetSpec/
|
490
|
+
node_param = plan_params.include?('nodes')
|
491
|
+
|
492
|
+
if node_param && target_param
|
493
|
+
msg = "Plan parameters include both 'nodes' and 'targets' with type 'TargetSpec', " \
|
494
|
+
"neither will populated with the value for --nodes or --targets."
|
495
|
+
@logger.warn(msg)
|
496
|
+
elsif node_param
|
497
|
+
plan_arguments['nodes'] = nodes.join(',')
|
498
|
+
elsif target_param
|
499
|
+
plan_arguments['targets'] = nodes.join(',')
|
500
|
+
end
|
482
501
|
end
|
483
502
|
|
484
503
|
plan_context = { plan_name: plan_name,
|
@@ -507,6 +526,7 @@ module Bolt
|
|
507
526
|
end
|
508
527
|
|
509
528
|
def apply_manifest(code, targets, filename = nil, noop = false)
|
529
|
+
Puppet[:tasks] = false
|
510
530
|
ast = pal.parse_manifest(code, filename)
|
511
531
|
|
512
532
|
executor = Bolt::Executor.new(config.concurrency, analytics, noop)
|
@@ -559,6 +579,52 @@ module Bolt
|
|
559
579
|
ok ? 0 : 1
|
560
580
|
end
|
561
581
|
|
582
|
+
def migrate_project
|
583
|
+
if inventory.version == 2
|
584
|
+
ok = true
|
585
|
+
else
|
586
|
+
inventory_file = config.inventoryfile || config.boltdir.inventory_file
|
587
|
+
|
588
|
+
begin
|
589
|
+
Bolt::Util.file_stat(inventory_file)
|
590
|
+
rescue Errno::ENOENT
|
591
|
+
raise Bolt::FileError.new("The inventory file '#{inventory_file}' does not exist", inventory_file)
|
592
|
+
end
|
593
|
+
|
594
|
+
inv = YAML.safe_load(File.open(inventory_file))
|
595
|
+
migrate_group(inv)
|
596
|
+
|
597
|
+
ok = File.write(inventory_file, { 'version' => 2 }.merge(inv).to_yaml)
|
598
|
+
end
|
599
|
+
|
600
|
+
result = if ok
|
601
|
+
"Successfully migrated Bolt project to latest version"
|
602
|
+
else
|
603
|
+
"Could not migrate Bolt project to latest version"
|
604
|
+
end
|
605
|
+
outputter.print_message result
|
606
|
+
|
607
|
+
ok ? 0 : 1
|
608
|
+
end
|
609
|
+
|
610
|
+
# Walks an inventory hash and replaces all 'nodes' keys with 'targets' keys
|
611
|
+
# and all 'name' keys nested in a 'targets' hash with 'uri' keys. Data is
|
612
|
+
# modified in place.
|
613
|
+
def migrate_group(group)
|
614
|
+
if group.key?('nodes')
|
615
|
+
targets = group['nodes'].map do |target|
|
616
|
+
target['uri'] = target.delete('name') if target.is_a?(Hash)
|
617
|
+
target
|
618
|
+
end
|
619
|
+
group.delete('nodes')
|
620
|
+
group['targets'] = targets
|
621
|
+
end
|
622
|
+
(group['groups'] || []).each do |subgroup|
|
623
|
+
migrate_group(subgroup)
|
624
|
+
end
|
625
|
+
nil
|
626
|
+
end
|
627
|
+
|
562
628
|
def install_puppetfile(config, puppetfile, modulepath)
|
563
629
|
require 'r10k/cli'
|
564
630
|
require 'bolt/r10k_log_proxy'
|
data/lib/bolt/config.rb
CHANGED
@@ -71,7 +71,7 @@ module Bolt
|
|
71
71
|
@save_rerun = true
|
72
72
|
@puppetfile_config = {}
|
73
73
|
@plugins = {}
|
74
|
-
@plugin_hooks = {
|
74
|
+
@plugin_hooks = {}
|
75
75
|
|
76
76
|
# add an entry for the default console logger
|
77
77
|
@log = { 'console' => {} }
|
@@ -166,30 +166,14 @@ module Bolt
|
|
166
166
|
|
167
167
|
@save_rerun = data['save-rerun'] if data.key?('save-rerun')
|
168
168
|
|
169
|
-
# Plugins are only settable from config not inventory so we can overwrite
|
170
169
|
@plugins = data['plugins'] if data.key?('plugins')
|
171
|
-
@plugin_hooks
|
170
|
+
@plugin_hooks = data['plugin_hooks'] if data.key?('plugin_hooks')
|
172
171
|
|
173
|
-
%w[concurrency format puppetdb color
|
172
|
+
%w[concurrency format puppetdb color].each do |key|
|
174
173
|
send("#{key}=", data[key]) if data.key?(key)
|
175
174
|
end
|
176
175
|
|
177
|
-
|
178
|
-
if data[key.to_s]
|
179
|
-
selected = impl.filter_options(data[key.to_s])
|
180
|
-
if @future
|
181
|
-
to_expand = %w[private-key cacert token-file] & selected.keys
|
182
|
-
to_expand.each do |opt|
|
183
|
-
selected[opt] = File.expand_path(selected[opt], @boltdir.path) if opt.is_a?(String)
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
@transports[key] = Bolt::Util.deep_merge(@transports[key], selected)
|
188
|
-
end
|
189
|
-
if @transports[key]['interpreters']
|
190
|
-
@transports[key]['interpreters'] = normalize_interpreters(@transports[key]['interpreters'])
|
191
|
-
end
|
192
|
-
end
|
176
|
+
update_transports(data)
|
193
177
|
end
|
194
178
|
private :update_from_file
|
195
179
|
|
@@ -229,11 +213,28 @@ module Bolt
|
|
229
213
|
end
|
230
214
|
|
231
215
|
def update_from_inventory(data)
|
232
|
-
|
216
|
+
update_transports(data)
|
217
|
+
end
|
233
218
|
|
234
|
-
|
235
|
-
|
219
|
+
def update_transports(data)
|
220
|
+
TRANSPORTS.each do |key, impl|
|
221
|
+
if data[key.to_s]
|
222
|
+
selected = impl.filter_options(data[key.to_s])
|
223
|
+
if @future
|
224
|
+
to_expand = %w[private-key cacert token-file] & selected.keys
|
225
|
+
to_expand.each do |opt|
|
226
|
+
selected[opt] = File.expand_path(selected[opt], @boltdir.path) if opt.is_a?(String)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
@transports[key] = Bolt::Util.deep_merge(@transports[key], selected)
|
231
|
+
end
|
232
|
+
if @transports[key]['interpreters']
|
233
|
+
@transports[key]['interpreters'] = normalize_interpreters(@transports[key]['interpreters'])
|
234
|
+
end
|
236
235
|
end
|
236
|
+
|
237
|
+
@transport = data['transport'] if data.key?('transport')
|
237
238
|
end
|
238
239
|
|
239
240
|
def transport_conf
|
data/lib/bolt/inventory.rb
CHANGED
@@ -234,7 +234,7 @@ module Bolt
|
|
234
234
|
set_facts(target.name, data['facts']) unless @target_facts[target.name]
|
235
235
|
data['features']&.each { |feature| set_feature(target, feature) } unless @target_features[target.name]
|
236
236
|
unless @target_plugin_hooks[target.name]
|
237
|
-
set_plugin_hooks(target.name, @
|
237
|
+
set_plugin_hooks(target.name, (@plugins&.plugin_hooks || {}).merge(data['plugin_hooks'] || {}))
|
238
238
|
end
|
239
239
|
|
240
240
|
# Use Config object to ensure config section is treated consistently with config file
|
@@ -78,7 +78,7 @@ module Bolt
|
|
78
78
|
def plugin_hooks
|
79
79
|
# Merge plugin_hooks from the config file with any defined by the group
|
80
80
|
# or assigned dynamically to the target
|
81
|
-
@inventory.
|
81
|
+
@inventory.plugins.plugin_hooks.merge(group_cache['plugin_hooks']).merge(@plugin_hooks)
|
82
82
|
end
|
83
83
|
|
84
84
|
def set_config(key_or_key_path, value)
|
data/lib/bolt/plugin.rb
CHANGED
@@ -39,9 +39,10 @@ module Bolt
|
|
39
39
|
end
|
40
40
|
|
41
41
|
class PluginContext
|
42
|
-
def initialize(config, pal)
|
42
|
+
def initialize(config, pal, plugins)
|
43
43
|
@pal = pal
|
44
44
|
@config = config
|
45
|
+
@plugins = plugins
|
45
46
|
end
|
46
47
|
|
47
48
|
def serial_executor
|
@@ -50,7 +51,7 @@ module Bolt
|
|
50
51
|
private :serial_executor
|
51
52
|
|
52
53
|
def empty_inventory
|
53
|
-
@empty_inventory ||= Bolt::Inventory.new({}, @config)
|
54
|
+
@empty_inventory ||= Bolt::Inventory::Inventory2.new({}, @config, plugins: @plugins)
|
54
55
|
end
|
55
56
|
private :empty_inventory
|
56
57
|
|
@@ -120,28 +121,46 @@ module Bolt
|
|
120
121
|
|
121
122
|
def self.setup(config, pal, pdb_client, analytics)
|
122
123
|
plugins = new(config, pal, analytics)
|
123
|
-
|
124
|
+
|
125
|
+
# PDB is special because it needs the PDB client. Since it has no config,
|
126
|
+
# we can just add it first.
|
124
127
|
plugins.add_plugin(Bolt::Plugin::Puppetdb.new(pdb_client))
|
125
128
|
|
126
|
-
plugins.
|
127
|
-
plugins.
|
128
|
-
plugins.
|
129
|
-
|
129
|
+
# Initialize any plugins referenced in config. This will also indirectly
|
130
|
+
# initialize any plugins they depend on.
|
131
|
+
if plugins.reference?(config.plugins)
|
132
|
+
msg = "The 'plugins' setting cannot be set by a plugin reference"
|
133
|
+
raise PluginError.new(msg, 'bolt/plugin-error')
|
134
|
+
end
|
135
|
+
|
136
|
+
config.plugins.keys.each do |plugin|
|
137
|
+
plugins.by_name(plugin)
|
138
|
+
end
|
139
|
+
|
140
|
+
plugins.plugin_hooks.merge!(plugins.resolve_references(config.plugin_hooks))
|
130
141
|
|
131
142
|
plugins
|
132
143
|
end
|
133
144
|
|
134
|
-
|
145
|
+
RUBY_PLUGINS = %w[install_agent task pkcs7 prompt].freeze
|
146
|
+
BUILTIN_PLUGINS = %w[task terraform pkcs7 prompt vault aws_inventory puppetdb azure_inventory yaml].freeze
|
147
|
+
DEFAULT_PLUGIN_HOOKS = { 'puppet_library' => { 'plugin' => 'puppet_agent', 'stop_service' => true } }.freeze
|
135
148
|
|
136
149
|
attr_reader :pal, :plugin_context
|
150
|
+
attr_accessor :plugin_hooks
|
151
|
+
|
152
|
+
private_class_method :new
|
137
153
|
|
138
154
|
def initialize(config, pal, analytics)
|
139
155
|
@config = config
|
140
156
|
@analytics = analytics
|
141
|
-
@plugin_context = PluginContext.new(config, pal)
|
157
|
+
@plugin_context = PluginContext.new(config, pal, self)
|
142
158
|
@plugins = {}
|
143
159
|
@pal = pal
|
144
160
|
@unknown = Set.new
|
161
|
+
@resolution_stack = []
|
162
|
+
@unresolved_plugin_configs = config.plugins.dup
|
163
|
+
@plugin_hooks = DEFAULT_PLUGIN_HOOKS.dup
|
145
164
|
end
|
146
165
|
|
147
166
|
def modules
|
@@ -153,11 +172,11 @@ module Bolt
|
|
153
172
|
@plugins[plugin.name] = plugin
|
154
173
|
end
|
155
174
|
|
156
|
-
def add_ruby_plugin(
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
175
|
+
def add_ruby_plugin(plugin_name)
|
176
|
+
cls_name = Bolt::Util.snake_name_to_class_name(plugin_name)
|
177
|
+
filename = "bolt/plugin/#{plugin_name}"
|
178
|
+
require filename
|
179
|
+
cls = Kernel.const_get("Bolt::Plugin::#{cls_name}")
|
161
180
|
opts = {
|
162
181
|
context: @plugin_context,
|
163
182
|
config: config_for_plugin(plugin_name)
|
@@ -177,14 +196,18 @@ module Bolt
|
|
177
196
|
add_plugin(plugin)
|
178
197
|
end
|
179
198
|
|
180
|
-
def add_from_config
|
181
|
-
@config.plugins.keys.each do |plugin_name|
|
182
|
-
by_name(plugin_name)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
199
|
def config_for_plugin(plugin_name)
|
187
|
-
@
|
200
|
+
return {} unless @unresolved_plugin_configs.include?(plugin_name)
|
201
|
+
if @resolution_stack.include?(plugin_name)
|
202
|
+
msg = "Configuration for plugin '#{plugin_name}' depends on the plugin itself"
|
203
|
+
raise PluginError.new(msg, 'bolt/plugin-error')
|
204
|
+
else
|
205
|
+
@resolution_stack.push(plugin_name)
|
206
|
+
config = resolve_references(@unresolved_plugin_configs[plugin_name])
|
207
|
+
@unresolved_plugin_configs.delete(plugin_name)
|
208
|
+
@resolution_stack.pop
|
209
|
+
config
|
210
|
+
end
|
188
211
|
end
|
189
212
|
|
190
213
|
def get_hook(plugin_name, hook)
|
@@ -200,7 +223,9 @@ module Bolt
|
|
200
223
|
def by_name(plugin_name)
|
201
224
|
return @plugins[plugin_name] if @plugins.include?(plugin_name)
|
202
225
|
begin
|
203
|
-
|
226
|
+
if RUBY_PLUGINS.include?(plugin_name)
|
227
|
+
add_ruby_plugin(plugin_name)
|
228
|
+
elsif !@unknown.include?(plugin_name)
|
204
229
|
add_module_plugin(plugin_name)
|
205
230
|
end
|
206
231
|
rescue PluginError::Unknown
|
@@ -218,6 +243,9 @@ module Bolt
|
|
218
243
|
Bolt::Util.postwalk_vals(data) do |value|
|
219
244
|
reference?(value) ? resolve_references(resolve_single_reference(value)) : value
|
220
245
|
end
|
246
|
+
rescue SystemStackError
|
247
|
+
raise Bolt::Error.new("Stack depth exceeded while recursively resolving references.",
|
248
|
+
"bolt/recursive-reference-loop")
|
221
249
|
end
|
222
250
|
|
223
251
|
# Iteratively resolves "top-level" references until the result no longer
|
data/lib/bolt/plugin/module.rb
CHANGED
@@ -158,20 +158,21 @@ module Bolt
|
|
158
158
|
# opts are passed directly from inventory but all of the _ options are
|
159
159
|
# handled previously. That may not always be the case so filter them
|
160
160
|
# out now.
|
161
|
-
|
162
|
-
|
161
|
+
meta, params = opts.partition { |key, _val| key.start_with?('_') }.map(&:to_h)
|
162
|
+
|
163
163
|
# Send config with `_config` when config is defined in bolt_plugin.json
|
164
164
|
# Otherwise, merge config with params
|
165
165
|
# TODO: remove @send_config when deprecated
|
166
166
|
if @send_config
|
167
|
-
|
167
|
+
validate_params(task, params)
|
168
|
+
params['_config'] = config if config?
|
168
169
|
else
|
169
170
|
params = @config ? config.merge(params) : params
|
171
|
+
validate_params(task, params)
|
170
172
|
end
|
171
|
-
|
173
|
+
params['_boltdir'] = @context.boltdir.to_s
|
172
174
|
|
173
|
-
|
174
|
-
[params, metaparams]
|
175
|
+
[params, meta]
|
175
176
|
end
|
176
177
|
|
177
178
|
def extract_task_parameter_schema
|
@@ -199,6 +200,7 @@ module Bolt
|
|
199
200
|
end
|
200
201
|
|
201
202
|
def run_task(task, opts)
|
203
|
+
opts = opts.reject { |key, _val| key.start_with?('_') }
|
202
204
|
params, metaparams = process_params(task, opts)
|
203
205
|
params = params.merge(metaparams)
|
204
206
|
|
@@ -271,11 +273,11 @@ module Bolt
|
|
271
273
|
|
272
274
|
params, meta_params = process_params(task, opts)
|
273
275
|
|
274
|
-
|
275
|
-
|
276
|
+
options = {}
|
277
|
+
options[:run_as] = meta_params['_run_as'] if meta_params['_run_as']
|
276
278
|
|
277
279
|
proc do
|
278
|
-
apply_prep.run_task([target], task, params).first
|
280
|
+
apply_prep.run_task([target], task, params, options).first
|
279
281
|
end
|
280
282
|
end
|
281
283
|
end
|
data/lib/bolt/plugin/prompt.rb
CHANGED
@@ -20,7 +20,7 @@ module Bolt
|
|
20
20
|
|
21
21
|
def resolve_reference(opts)
|
22
22
|
# rubocop:disable Style/GlobalVars
|
23
|
-
$future ? STDERR.print("#{opts['message']}:") : STDOUT.print("#{opts['message']}:")
|
23
|
+
$future ? STDERR.print("#{opts['message']}: ") : STDOUT.print("#{opts['message']}: ")
|
24
24
|
value = STDIN.noecho(&:gets).chomp
|
25
25
|
$future ? STDERR.puts : STDOUT.puts
|
26
26
|
# rubocop:enable Style/GlobalVars
|
data/lib/bolt/plugin/task.rb
CHANGED
@@ -48,13 +48,15 @@ module Bolt
|
|
48
48
|
|
49
49
|
def puppet_library(opts, target, apply_prep)
|
50
50
|
params = opts['parameters'] || {}
|
51
|
+
run_opts = {}
|
52
|
+
run_opts[:run_as] = opts['_run_as'] if opts['_run_as']
|
51
53
|
begin
|
52
54
|
task = apply_prep.get_task(opts['task'], params)
|
53
55
|
rescue Bolt::Error => e
|
54
56
|
raise Bolt::Plugin::PluginError::ExecutionError.new(e.message, name, 'puppet_library')
|
55
57
|
end
|
56
58
|
proc do
|
57
|
-
apply_prep.run_task([target], task, params).first
|
59
|
+
apply_prep.run_task([target], task, params, run_opts).first
|
58
60
|
end
|
59
61
|
end
|
60
62
|
end
|
data/lib/bolt/util.rb
CHANGED
@@ -204,6 +204,10 @@ module Bolt
|
|
204
204
|
File.stat(File.expand_path(path))
|
205
205
|
end
|
206
206
|
|
207
|
+
def snake_name_to_class_name(snake_name)
|
208
|
+
snake_name.split('_').map(&:capitalize).join
|
209
|
+
end
|
210
|
+
|
207
211
|
def class_name_to_file_name(cls_name)
|
208
212
|
# Note this turns Bolt::CLI -> 'bolt/cli' not 'bolt/c_l_i'
|
209
213
|
# this won't handle Bolt::Inventory2Foo
|
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.38.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-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|