bolt 1.49.0 → 2.0.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 +6 -6
- data/bolt-modules/boltlib/lib/puppet/datatypes/target.rb +24 -45
- data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +3 -3
- data/bolt-modules/boltlib/lib/puppet/functions/add_to_group.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +10 -12
- data/bolt-modules/boltlib/lib/puppet/functions/catch_errors.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/fail_plan.rb +3 -3
- data/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb +5 -4
- data/bolt-modules/boltlib/lib/puppet/functions/get_target.rb +1 -3
- data/bolt-modules/boltlib/lib/puppet/functions/get_targets.rb +1 -2
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_fact.rb +2 -2
- data/bolt-modules/boltlib/lib/puppet/functions/remove_from_group.rb +2 -2
- data/bolt-modules/boltlib/lib/puppet/functions/resolve_references.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +7 -3
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +15 -31
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +9 -5
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +9 -3
- data/bolt-modules/boltlib/lib/puppet/functions/set_config.rb +4 -3
- data/bolt-modules/boltlib/lib/puppet/functions/set_feature.rb +6 -6
- data/bolt-modules/boltlib/lib/puppet/functions/set_var.rb +2 -2
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +7 -3
- data/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb +6 -2
- data/bolt-modules/boltlib/lib/puppet/functions/without_default_logging.rb +2 -2
- data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +2 -1
- data/bolt-modules/file/lib/puppet/functions/file/exists.rb +2 -1
- data/bolt-modules/file/lib/puppet/functions/file/join.rb +1 -0
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +1 -0
- data/bolt-modules/file/lib/puppet/functions/file/readable.rb +2 -1
- data/bolt-modules/out/lib/puppet/functions/out/message.rb +1 -1
- data/bolt-modules/system/lib/puppet/functions/system/env.rb +1 -0
- data/lib/bolt/applicator.rb +70 -118
- data/lib/bolt/apply_target.rb +1 -1
- data/lib/bolt/bolt_option_parser.rb +21 -37
- data/lib/bolt/catalog.rb +5 -22
- data/lib/bolt/catalog/logging.rb +1 -1
- data/lib/bolt/cli.rb +33 -44
- data/lib/bolt/config.rb +15 -18
- data/lib/bolt/error.rb +2 -2
- data/lib/bolt/executor.rb +32 -40
- data/lib/bolt/inventory.rb +9 -367
- data/lib/bolt/inventory/group.rb +293 -182
- data/lib/bolt/inventory/{inventory2.rb → inventory.rb} +25 -14
- data/lib/bolt/inventory/target.rb +1 -1
- data/lib/bolt/module.rb +4 -4
- data/lib/bolt/outputter/human.rb +11 -6
- data/lib/bolt/outputter/json.rb +3 -11
- data/lib/bolt/pal.rb +1 -2
- data/lib/bolt/pal/yaml_plan/step/resources.rb +1 -1
- data/lib/bolt/plugin.rb +1 -1
- data/lib/bolt/plugin/module.rb +19 -36
- data/lib/bolt/plugin/prompt.rb +2 -4
- data/lib/bolt/puppetdb/config.rb +1 -3
- data/lib/bolt/result.rb +3 -6
- data/lib/bolt/secret/base.rb +0 -6
- data/lib/bolt/target.rb +8 -219
- data/lib/bolt/transport/local/shell.rb +9 -13
- data/lib/bolt/transport/orch.rb +3 -5
- data/lib/bolt/transport/ssh.rb +1 -0
- data/lib/bolt/transport/ssh/connection.rb +1 -4
- data/lib/bolt/transport/winrm/connection.rb +1 -1
- data/lib/bolt/util.rb +2 -8
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/transport_app.rb +35 -17
- data/lib/bolt_spec/plans.rb +8 -2
- data/libexec/bolt_catalog +19 -5
- metadata +4 -8
- data/exe/bolt-inventory-pdb +0 -13
- data/lib/bolt/inventory/group2.rb +0 -403
- data/lib/bolt_ext/puppetdb_inventory.rb +0 -129
data/lib/bolt/apply_target.rb
CHANGED
@@ -46,7 +46,7 @@ module Bolt
|
|
46
46
|
end
|
47
47
|
|
48
48
|
# Merge the config hash with inventory config
|
49
|
-
config = Bolt::Util.deep_merge(config, @config)
|
49
|
+
config = Bolt::Util.deep_merge(config, @config || {})
|
50
50
|
transport = config['transport'] || 'ssh'
|
51
51
|
t_conf = config['transports'][transport] || {}
|
52
52
|
uri_obj = parse_uri(uri)
|
@@ -6,7 +6,7 @@ require 'optparse'
|
|
6
6
|
|
7
7
|
module Bolt
|
8
8
|
class BoltOptionParser < OptionParser
|
9
|
-
OPTIONS = { inventory: %w[
|
9
|
+
OPTIONS = { inventory: %w[targets query rerun description],
|
10
10
|
authentication: %w[user password password-prompt private-key host-key-check ssl ssl-verify],
|
11
11
|
escalation: %w[run-as sudo-password sudo-password-prompt sudo-executable],
|
12
12
|
run_context: %w[concurrency inventoryfile save-rerun],
|
@@ -67,7 +67,7 @@ module Bolt
|
|
67
67
|
{ flags: ACTION_OPTS + %w[params compile-concurrency tmpdir],
|
68
68
|
banner: PLAN_RUN_HELP }
|
69
69
|
when 'show'
|
70
|
-
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters],
|
70
|
+
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters] + %w[filter format],
|
71
71
|
banner: PLAN_SHOW_HELP }
|
72
72
|
else
|
73
73
|
{ flags: OPTIONS[:global],
|
@@ -130,7 +130,7 @@ module Bolt
|
|
130
130
|
{ flags: ACTION_OPTS + %w[params tmpdir noop],
|
131
131
|
banner: TASK_RUN_HELP }
|
132
132
|
when 'show'
|
133
|
-
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters],
|
133
|
+
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters] + %w[filter format],
|
134
134
|
banner: TASK_SHOW_HELP }
|
135
135
|
else
|
136
136
|
{ flags: OPTIONS[:global],
|
@@ -599,17 +599,11 @@ module Bolt
|
|
599
599
|
@warnings = []
|
600
600
|
|
601
601
|
separator "\nINVENTORY OPTIONS"
|
602
|
-
define('-n', '--nodes NODES',
|
603
|
-
'Alias for --targets',
|
604
|
-
'Deprecated in favor of --targets') do |nodes|
|
605
|
-
@options [:nodes] ||= []
|
606
|
-
@options[:nodes] << get_arg_input(nodes)
|
607
|
-
end
|
608
602
|
define('-t', '--targets TARGETS',
|
609
603
|
'Identifies the targets of command.',
|
610
604
|
'Enter a comma-separated list of target URIs or group names.',
|
611
605
|
"Or read a target list from an input file '@<file>' or stdin '-'.",
|
612
|
-
'Example: --targets localhost,
|
606
|
+
'Example: --targets localhost,target_group,ssh://nix.com:23,winrm://windows.puppet.com',
|
613
607
|
'URI format is [protocol://]host[:port]',
|
614
608
|
"SSH is the default protocol; may be #{TRANSPORTS.keys.join(', ')}",
|
615
609
|
'For Windows targets, specify the winrm:// protocol if it has not be configured',
|
@@ -621,10 +615,10 @@ module Bolt
|
|
621
615
|
define('-q', '--query QUERY', 'Query PuppetDB to determine the targets') do |query|
|
622
616
|
@options[:query] = query
|
623
617
|
end
|
624
|
-
define('--rerun FILTER', 'Retry on
|
625
|
-
"'all' all
|
626
|
-
"'failure'
|
627
|
-
"'success'
|
618
|
+
define('--rerun FILTER', 'Retry on targets from the last run',
|
619
|
+
"'all' all targets that were part of the last run.",
|
620
|
+
"'failure' targets that failed in the last run.",
|
621
|
+
"'success' targets that succeeded in the last run.") do |rerun|
|
628
622
|
@options[:rerun] = rerun
|
629
623
|
end
|
630
624
|
define('--noop', 'See what changes Bolt will make without actually executing the changes') do |_|
|
@@ -650,18 +644,9 @@ module Bolt
|
|
650
644
|
define('-u', '--user USER', 'User to authenticate as') do |user|
|
651
645
|
@options[:user] = user
|
652
646
|
end
|
653
|
-
define('-p', '--password
|
647
|
+
define('-p', '--password PASSWORD',
|
654
648
|
'Password to authenticate with') do |password|
|
655
|
-
|
656
|
-
msg = "Optional parameter for --password is deprecated and will no longer prompt for password. " \
|
657
|
-
"Use the prompt plugin or --password-prompt instead to prompt for passwords."
|
658
|
-
@warnings << { option: 'password', msg: msg }
|
659
|
-
STDOUT.print "Please enter your password: "
|
660
|
-
@options[:password] = STDIN.noecho(&:gets).chomp
|
661
|
-
STDOUT.puts
|
662
|
-
else
|
663
|
-
@options[:password] = password
|
664
|
-
end
|
649
|
+
@options[:password] = password
|
665
650
|
end
|
666
651
|
define('--password-prompt', 'Prompt for user to input password') do |_password|
|
667
652
|
STDERR.print "Please enter your password: "
|
@@ -685,18 +670,9 @@ module Bolt
|
|
685
670
|
define('--run-as USER', 'User to run as using privilege escalation') do |user|
|
686
671
|
@options[:'run-as'] = user
|
687
672
|
end
|
688
|
-
define('--sudo-password
|
673
|
+
define('--sudo-password PASSWORD',
|
689
674
|
'Password for privilege escalation') do |password|
|
690
|
-
|
691
|
-
msg = "Optional parameter for --sudo-password is deprecated and will no longer prompt for password. " \
|
692
|
-
"Use the prompt plugin or --sudo-password-prompt instead to prompt for passwords."
|
693
|
-
@warnings << { option: 'sudo-password', msg: msg }
|
694
|
-
STDOUT.print "Please enter your privilege escalation password: "
|
695
|
-
@options[:'sudo-password'] = STDIN.noecho(&:gets).chomp
|
696
|
-
STDOUT.puts
|
697
|
-
else
|
698
|
-
@options[:'sudo-password'] = password
|
699
|
-
end
|
675
|
+
@options[:'sudo-password'] = password
|
700
676
|
end
|
701
677
|
define('--sudo-password-prompt', 'Prompt for user to input escalation password') do |_password|
|
702
678
|
STDERR.print "Please enter your privilege escalation password: "
|
@@ -753,7 +729,7 @@ module Bolt
|
|
753
729
|
define('--connect-timeout TIMEOUT', Integer, 'Connection timeout (defaults vary)') do |timeout|
|
754
730
|
@options[:'connect-timeout'] = timeout
|
755
731
|
end
|
756
|
-
define('--[no-]tty', 'Request a pseudo TTY on
|
732
|
+
define('--[no-]tty', 'Request a pseudo TTY on targets that support it') do |tty|
|
757
733
|
@options[:tty] = tty
|
758
734
|
end
|
759
735
|
define('--tmpdir DIR', 'The directory to upload and execute temporary files on the target') do |tmpdir|
|
@@ -761,6 +737,14 @@ module Bolt
|
|
761
737
|
end
|
762
738
|
|
763
739
|
separator "\nDISPLAY OPTIONS"
|
740
|
+
define('--filter FILTER', 'Filter tasks and plans by a matching substring') do |filter|
|
741
|
+
unless /^[a-z0-9_:]+$/.match(filter)
|
742
|
+
msg = "Illegal characters in filter string '#{filter}'. Filters must match a legal "\
|
743
|
+
"task or plan name."
|
744
|
+
raise Bolt::CLIError, msg
|
745
|
+
end
|
746
|
+
@options[:filter] = filter
|
747
|
+
end
|
764
748
|
define('--format FORMAT', 'Output format to use: human or json') do |format|
|
765
749
|
@options[:format] = format
|
766
750
|
end
|
data/lib/bolt/catalog.rb
CHANGED
@@ -53,43 +53,26 @@ module Bolt
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
def setup_inventory(inventory)
|
57
|
-
config = Bolt::Config.default
|
58
|
-
config.overwrite_transport_data(inventory['config']['transport'],
|
59
|
-
Bolt::Util.symbolize_top_level_keys(inventory['config']['transports']))
|
60
|
-
|
61
|
-
Bolt::Inventory.new(inventory['data'],
|
62
|
-
config,
|
63
|
-
Bolt::Util.symbolize_top_level_keys(inventory['target_hash']))
|
64
|
-
end
|
65
|
-
|
66
56
|
def compile_catalog(request)
|
67
57
|
pal_main = request['code_ast'] || request['code_string']
|
68
58
|
target = request['target']
|
69
59
|
pdb_client = Bolt::PuppetDB::Client.new(Bolt::PuppetDB::Config.new(request['pdb_config']))
|
70
60
|
options = request['puppet_config'] || {}
|
71
|
-
|
72
61
|
with_puppet_settings(request['hiera_config']) do
|
73
62
|
Puppet[:rich_data] = true
|
74
63
|
Puppet[:node_name_value] = target['name']
|
75
64
|
env_conf = { modulepath: request['modulepath'] || [],
|
76
65
|
facts: target['facts'] || {} }
|
77
|
-
env_conf[:variables] =
|
66
|
+
env_conf[:variables] = {}
|
78
67
|
Puppet::Pal.in_tmp_environment('bolt_catalog', env_conf) do |pal|
|
79
|
-
inv =
|
80
|
-
Bolt::ApplyInventory.new(request['config'])
|
81
|
-
else
|
82
|
-
setup_inventory(request['inventory'])
|
83
|
-
end
|
68
|
+
inv = Bolt::ApplyInventory.new(request['config'])
|
84
69
|
Puppet.override(bolt_pdb_client: pdb_client,
|
85
70
|
bolt_inventory: inv) do
|
86
71
|
Puppet.lookup(:pal_current_node).trusted_data = target['trusted']
|
87
72
|
pal.with_catalog_compiler do |compiler|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
pal.send(:add_variables, compiler.send(:topscope), vars.merge(target['variables']))
|
92
|
-
end
|
73
|
+
# This needs to happen inside the catalog compiler so loaders are initialized for loading
|
74
|
+
vars = Puppet::Pops::Serialization::FromDataConverter.convert(request['plan_vars'])
|
75
|
+
pal.send(:add_variables, compiler.send(:topscope), target['variables'].merge(vars))
|
93
76
|
|
94
77
|
# Configure language strictness in the CatalogCompiler. We want Bolt to be able
|
95
78
|
# to compile most Puppet 4+ manifests, so we default to allowing deprecated functions.
|
data/lib/bolt/catalog/logging.rb
CHANGED
@@ -10,6 +10,6 @@ Puppet::Util::Log.newdesttype :stderr do
|
|
10
10
|
def handle(msg)
|
11
11
|
str = msg.respond_to?(:multiline) ? msg.multiline : msg.to_s
|
12
12
|
str = msg.source == "Puppet" ? str : "#{msg.source}: #{str}"
|
13
|
-
warn({ msg.level
|
13
|
+
warn({ level: msg.level, message: str }.to_json)
|
14
14
|
end
|
15
15
|
end
|
data/lib/bolt/cli.rb
CHANGED
@@ -122,11 +122,6 @@ module Bolt
|
|
122
122
|
Bolt::Config.from_boltdir(boltdir, options)
|
123
123
|
end
|
124
124
|
|
125
|
-
# Set $future global if configured
|
126
|
-
# rubocop:disable Style/GlobalVars
|
127
|
-
$future = @config.future
|
128
|
-
# rubocop:enable Style/GlobalVars
|
129
|
-
|
130
125
|
Bolt::Logger.configure(config.log, config.color)
|
131
126
|
|
132
127
|
# Logger must be configured before checking path case, otherwise warnings will not display
|
@@ -135,7 +130,10 @@ module Bolt
|
|
135
130
|
# Log the file paths for loaded config files
|
136
131
|
config_loaded
|
137
132
|
|
133
|
+
# Display warnings created during parser and config initialization
|
138
134
|
parser.warnings.each { |warning| @logger.warn(warning[:msg]) }
|
135
|
+
config.warnings.each { |warning| @logger.warn(warning[:msg]) }
|
136
|
+
|
139
137
|
# After validation, initialize inventory and targets. Errors here are better to catch early.
|
140
138
|
# After this step
|
141
139
|
# options[:target_args] will contain a string/array version of the targetting options this is passed to plans
|
@@ -154,12 +152,6 @@ module Bolt
|
|
154
152
|
options[:verbose] = options[:subcommand] != 'plan'
|
155
153
|
end
|
156
154
|
|
157
|
-
# TODO: Remove deprecation warning
|
158
|
-
if options[:nodes]
|
159
|
-
@logger.warn("Deprecation Warning: The --nodes command line option has been " \
|
160
|
-
"deprecated in favor of --targets.")
|
161
|
-
end
|
162
|
-
|
163
155
|
warn_inventory_overrides_cli(options)
|
164
156
|
options
|
165
157
|
rescue Bolt::Error => e
|
@@ -168,23 +160,23 @@ module Bolt
|
|
168
160
|
end
|
169
161
|
|
170
162
|
def update_targets(options)
|
171
|
-
target_opts = options.keys.select { |opt| %i[query rerun
|
172
|
-
target_string = "'--
|
163
|
+
target_opts = options.keys.select { |opt| %i[query rerun targets].include?(opt) }
|
164
|
+
target_string = "'--targets', '--rerun', or '--query'"
|
173
165
|
if target_opts.length > 1
|
174
166
|
raise Bolt::CLIError, "Only one targeting option #{target_string} may be specified"
|
175
167
|
elsif target_opts.empty? && options[:subcommand] != 'plan'
|
176
168
|
raise Bolt::CLIError, "Command requires a targeting option: #{target_string}"
|
177
169
|
end
|
178
170
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
options[:target_args] =
|
187
|
-
options[:targets] = inventory.get_targets(
|
171
|
+
targets = if options[:query]
|
172
|
+
query_puppetdb_nodes(options[:query])
|
173
|
+
elsif options[:rerun]
|
174
|
+
rerun.get_targets(options[:rerun])
|
175
|
+
else
|
176
|
+
options[:targets] || []
|
177
|
+
end
|
178
|
+
options[:target_args] = targets
|
179
|
+
options[:targets] = inventory.get_targets(targets)
|
188
180
|
end
|
189
181
|
|
190
182
|
def validate(options)
|
@@ -453,7 +445,9 @@ module Bolt
|
|
453
445
|
end
|
454
446
|
|
455
447
|
def list_tasks
|
456
|
-
|
448
|
+
tasks = pal.list_tasks
|
449
|
+
tasks.select! { |task| task.first.include?(options[:filter]) } if options[:filter]
|
450
|
+
outputter.print_tasks(tasks, pal.list_modulepath)
|
457
451
|
end
|
458
452
|
|
459
453
|
def show_plan(plan_name)
|
@@ -461,7 +455,9 @@ module Bolt
|
|
461
455
|
end
|
462
456
|
|
463
457
|
def list_plans
|
464
|
-
|
458
|
+
plans = pal.list_plans
|
459
|
+
plans.select! { |plan| plan.first.include?(options[:filter]) } if options[:filter]
|
460
|
+
outputter.print_plans(plans, pal.list_modulepath)
|
465
461
|
end
|
466
462
|
|
467
463
|
def list_targets
|
@@ -584,27 +580,18 @@ module Bolt
|
|
584
580
|
end
|
585
581
|
|
586
582
|
def migrate_project
|
587
|
-
|
588
|
-
|
589
|
-
else
|
590
|
-
inventory_file = config.inventoryfile || config.boltdir.inventory_file
|
591
|
-
|
592
|
-
begin
|
593
|
-
Bolt::Util.file_stat(inventory_file)
|
594
|
-
rescue Errno::ENOENT
|
595
|
-
raise Bolt::FileError.new("The inventory file '#{inventory_file}' does not exist", inventory_file)
|
596
|
-
end
|
583
|
+
inventory_file = config.inventoryfile || config.default_inventoryfile
|
584
|
+
data = Bolt::Util.read_yaml_hash(inventory_file, 'inventory')
|
597
585
|
|
598
|
-
|
599
|
-
|
586
|
+
migrated = migrate_group(data)
|
587
|
+
ok = File.write(inventory_file, data.to_yaml) if migrated
|
600
588
|
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
"Successfully migrated Bolt project to latest version"
|
589
|
+
result = if migrated && ok
|
590
|
+
"Successfully migrated Bolt project to latest version."
|
591
|
+
elsif !migrated
|
592
|
+
"Bolt project already on latest version. Nothing to do."
|
606
593
|
else
|
607
|
-
"Could not migrate Bolt project to latest version"
|
594
|
+
"Could not migrate Bolt project to latest version."
|
608
595
|
end
|
609
596
|
outputter.print_message result
|
610
597
|
|
@@ -615,7 +602,9 @@ module Bolt
|
|
615
602
|
# and all 'name' keys nested in a 'targets' hash with 'uri' keys. Data is
|
616
603
|
# modified in place.
|
617
604
|
def migrate_group(group)
|
605
|
+
migrated = false
|
618
606
|
if group.key?('nodes')
|
607
|
+
migrated = true
|
619
608
|
targets = group['nodes'].map do |target|
|
620
609
|
target['uri'] = target.delete('name') if target.is_a?(Hash)
|
621
610
|
target
|
@@ -624,9 +613,9 @@ module Bolt
|
|
624
613
|
group['targets'] = targets
|
625
614
|
end
|
626
615
|
(group['groups'] || []).each do |subgroup|
|
627
|
-
migrate_group(subgroup)
|
616
|
+
migrated ||= migrate_group(subgroup)
|
628
617
|
end
|
629
|
-
|
618
|
+
migrated
|
630
619
|
end
|
631
620
|
|
632
621
|
def install_puppetfile(config, puppetfile, modulepath)
|
data/lib/bolt/config.rb
CHANGED
@@ -34,10 +34,10 @@ module Bolt
|
|
34
34
|
class Config
|
35
35
|
attr_accessor :concurrency, :format, :trace, :log, :puppetdb, :color, :save_rerun,
|
36
36
|
:transport, :transports, :inventoryfile, :compile_concurrency, :boltdir,
|
37
|
-
:puppetfile_config, :plugins, :plugin_hooks, :
|
37
|
+
:puppetfile_config, :plugins, :plugin_hooks, :trusted_external,
|
38
38
|
:apply_settings
|
39
39
|
attr_writer :modulepath
|
40
|
-
attr_reader :config_files
|
40
|
+
attr_reader :config_files, :warnings
|
41
41
|
|
42
42
|
OPTIONS = {
|
43
43
|
"apply_settings" => "A map of Puppet settings to use when applying Puppet code",
|
@@ -64,9 +64,7 @@ module Bolt
|
|
64
64
|
"specified in the URL or inventory.",
|
65
65
|
"trusted-external-command" => "The path to an executable on the Bolt controller that can produce "\
|
66
66
|
"external trusted facts. **External trusted facts are experimental in both "\
|
67
|
-
"Puppet and Bolt and this API may change or be removed.**"
|
68
|
-
"future" => "Whether to use new, breaking changes. This allows testing if Bolt content "\
|
69
|
-
"is compatible with expected future behavior."
|
67
|
+
"Puppet and Bolt and this API may change or be removed.**"
|
70
68
|
}.freeze
|
71
69
|
|
72
70
|
DEFAULT_OPTIONS = {
|
@@ -77,8 +75,7 @@ module Bolt
|
|
77
75
|
"hiera-config" => "Boltdir/hiera.yaml",
|
78
76
|
"inventoryfile" => "Boltdir/inventory.yaml",
|
79
77
|
"modulepath" => ["Boltdir/modules", "Boltdir/site-modules", "Boltdir/site"],
|
80
|
-
"save-rerun" => true
|
81
|
-
"future" => false
|
78
|
+
"save-rerun" => true
|
82
79
|
}.freeze
|
83
80
|
|
84
81
|
PUPPETFILE_OPTIONS = {
|
@@ -170,6 +167,7 @@ module Bolt
|
|
170
167
|
@plugins = {}
|
171
168
|
@plugin_hooks = {}
|
172
169
|
@apply_settings = {}
|
170
|
+
@warnings = []
|
173
171
|
|
174
172
|
# add an entry for the default console logger
|
175
173
|
@log = { 'console' => {} }
|
@@ -234,11 +232,7 @@ module Bolt
|
|
234
232
|
def normalize_log(target)
|
235
233
|
return target if target == 'console'
|
236
234
|
target = target[5..-1] if target.start_with?('file:')
|
237
|
-
|
238
|
-
'file:' + File.expand_path(target, @boltdir.path)
|
239
|
-
else
|
240
|
-
'file:' + File.expand_path(target)
|
241
|
-
end
|
235
|
+
'file:' + File.expand_path(target, @boltdir.path)
|
242
236
|
end
|
243
237
|
|
244
238
|
def update_logs(logs)
|
@@ -260,7 +254,10 @@ module Bolt
|
|
260
254
|
end
|
261
255
|
|
262
256
|
def update_from_file(data)
|
263
|
-
|
257
|
+
if data['future']
|
258
|
+
msg = "Configuration option 'future' no longer exposes future behavior."
|
259
|
+
@warnings << { option: 'future', msg: msg }
|
260
|
+
end
|
264
261
|
|
265
262
|
if data['log'].is_a?(Hash)
|
266
263
|
update_logs(data['log'])
|
@@ -351,11 +348,11 @@ module Bolt
|
|
351
348
|
TRANSPORTS.each do |key, impl|
|
352
349
|
if data[key.to_s]
|
353
350
|
selected = impl.filter_options(data[key.to_s])
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
351
|
+
|
352
|
+
# Expand file paths relative to the Boltdir
|
353
|
+
to_expand = %w[private-key cacert token-file] & selected.keys
|
354
|
+
to_expand.each do |opt|
|
355
|
+
selected[opt] = File.expand_path(selected[opt], @boltdir.path) if selected[opt].is_a?(String)
|
359
356
|
end
|
360
357
|
|
361
358
|
@transports[key] = Bolt::Util.deep_merge(@transports[key], selected)
|
data/lib/bolt/error.rb
CHANGED
@@ -101,8 +101,8 @@ module Bolt
|
|
101
101
|
end
|
102
102
|
|
103
103
|
class ApplyError < Error
|
104
|
-
def initialize(target)
|
105
|
-
super("Apply failed to compile for #{target}", 'bolt/apply-error')
|
104
|
+
def initialize(target, msg)
|
105
|
+
super("Apply failed to compile for #{target}: #{msg}", 'bolt/apply-error')
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
data/lib/bolt/executor.rb
CHANGED
@@ -96,32 +96,30 @@ module Bolt
|
|
96
96
|
# Pass this argument through to avoid retaining a reference to a
|
97
97
|
# local variable that will change on the next iteration of the loop.
|
98
98
|
@pool.post(batch_promises) do |result_promises|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
promise.set(Bolt::Result.from_exception(target, error))
|
124
|
-
end
|
99
|
+
results = yield transport, batch
|
100
|
+
Array(results).each do |result|
|
101
|
+
result_promises[result.target].set(result)
|
102
|
+
end
|
103
|
+
# NotImplementedError can be thrown if the transport is not implemented improperly
|
104
|
+
rescue StandardError, NotImplementedError => e
|
105
|
+
result_promises.each do |target, promise|
|
106
|
+
# If an exception happens while running, the result won't be logged
|
107
|
+
# by the CLI. Log a warning, as this is probably a problem with the transport.
|
108
|
+
# If batch_* commands are used from the Base transport, then exceptions
|
109
|
+
# normally shouldn't reach here.
|
110
|
+
@logger.warn(e)
|
111
|
+
promise.set(Bolt::Result.from_exception(target, e))
|
112
|
+
end
|
113
|
+
ensure
|
114
|
+
# Make absolutely sure every promise gets a result to avoid a
|
115
|
+
# deadlock. Use whatever exception is causing this block to
|
116
|
+
# execute, or generate one if we somehow got here without an
|
117
|
+
# exception and some promise is still missing a result.
|
118
|
+
result_promises.each do |target, promise|
|
119
|
+
next if promise.fulfilled?
|
120
|
+
error = $ERROR_INFO || Bolt::Error.new("No result was returned for #{target.uri}",
|
121
|
+
"puppetlabs.bolt/missing-result-error")
|
122
|
+
promise.set(Bolt::Result.from_exception(target, error))
|
125
123
|
end
|
126
124
|
end
|
127
125
|
batch_promises.values
|
@@ -286,16 +284,14 @@ module Bolt
|
|
286
284
|
log_action(description, targets) do
|
287
285
|
batch_execute(targets) do |transport, batch|
|
288
286
|
with_node_logging('Waiting until available', batch) do
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
(
|
295
|
-
|
296
|
-
|
297
|
-
)
|
298
|
-
end
|
287
|
+
wait_until(wait_time, retry_interval) { transport.batch_connected?(batch) }
|
288
|
+
batch.map { |target| Result.new(target) }
|
289
|
+
rescue TimeoutError => e
|
290
|
+
available, unavailable = batch.partition { |target| transport.batch_connected?([target]) }
|
291
|
+
(
|
292
|
+
available.map { |target| Result.new(target) } +
|
293
|
+
unavailable.map { |target| Result.from_exception(target, e) }
|
294
|
+
)
|
299
295
|
end
|
300
296
|
end
|
301
297
|
end
|
@@ -338,9 +334,5 @@ module Bolt
|
|
338
334
|
ensure
|
339
335
|
publish_event(type: :enable_default_output)
|
340
336
|
end
|
341
|
-
|
342
|
-
def deprecation(msg)
|
343
|
-
@logger.warn msg
|
344
|
-
end
|
345
337
|
end
|
346
338
|
end
|