bolt 1.21.0 → 1.22.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/add_facts.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/add_to_group.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/facts.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/fail_plan.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/get_targets.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_fact.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/set_feature.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/set_var.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/vars.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/without_default_logging.rb +1 -1
- data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +1 -0
- data/bolt-modules/ctrl/lib/puppet/functions/ctrl/sleep.rb +1 -0
- data/bolt-modules/file/lib/puppet/functions/file/exists.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 +1 -0
- data/bolt-modules/file/lib/puppet/functions/file/write.rb +1 -0
- data/bolt-modules/out/lib/puppet/functions/out/message.rb +1 -0
- data/bolt-modules/system/lib/puppet/functions/system/env.rb +1 -0
- data/lib/bolt/cli.rb +8 -5
- data/lib/bolt/config.rb +9 -1
- data/lib/bolt/inventory/group2.rb +48 -5
- data/lib/bolt/inventory/inventory2.rb +20 -8
- data/lib/bolt/plugin.rb +2 -0
- data/lib/bolt/plugin/prompt.rb +32 -0
- data/lib/bolt/plugin/terraform.rb +56 -21
- data/lib/bolt/task.rb +0 -1
- 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: b5cea3288b0599937b773308e2f7286661c8e325ee2f04cb69b7e5521423d487
|
4
|
+
data.tar.gz: c1bffcef93f5167db8ecc2a21ce934a74b59ea40280a91b1bbcfde9b74d1b6dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07a86d3b9ab1a6d5d736a00e1384a0955164db3a978f5a3532d9422396116df5c024254c10afeed4af7a9253acd0bc64a78b640531716e5fe917f54b2deca3da
|
7
|
+
data.tar.gz: e30621636ccc9a6da616b7b9802a7aee40c99146e6983c89358332f091c004c3430a963beb2ebe3b1bee5685b2fa5e7be578a907be80971fa07fea0362b3ba7b
|
@@ -25,7 +25,7 @@ Puppet::Functions.create_function(:add_facts) do
|
|
25
25
|
|
26
26
|
inventory = Puppet.lookup(:bolt_inventory)
|
27
27
|
executor = Puppet.lookup(:bolt_executor)
|
28
|
-
executor.report_function_call(
|
28
|
+
executor.report_function_call(self.class.name)
|
29
29
|
|
30
30
|
inventory.add_facts(target, facts)
|
31
31
|
end
|
@@ -29,7 +29,7 @@ Puppet::Functions.create_function(:add_to_group) do
|
|
29
29
|
|
30
30
|
inventory = Puppet.lookup(:bolt_inventory)
|
31
31
|
executor = Puppet.lookup(:bolt_executor)
|
32
|
-
executor.report_function_call(
|
32
|
+
executor.report_function_call(self.class.name)
|
33
33
|
|
34
34
|
inventory.add_to_group(inventory.get_targets(targets), group)
|
35
35
|
end
|
@@ -50,7 +50,7 @@ Puppet::Functions.create_function(:apply_prep) do
|
|
50
50
|
executor = Puppet.lookup(:bolt_executor)
|
51
51
|
inventory = Puppet.lookup(:bolt_inventory)
|
52
52
|
|
53
|
-
executor.report_function_call(
|
53
|
+
executor.report_function_call(self.class.name)
|
54
54
|
|
55
55
|
targets = inventory.get_targets(target_spec)
|
56
56
|
|
@@ -17,7 +17,7 @@ Puppet::Functions.create_function(:facts) do
|
|
17
17
|
inventory = Puppet.lookup(:bolt_inventory)
|
18
18
|
# Bolt executor not expected when invoked from apply block
|
19
19
|
executor = Puppet.lookup(:bolt_executor) { nil }
|
20
|
-
executor&.report_function_call(
|
20
|
+
executor&.report_function_call(self.class.name)
|
21
21
|
|
22
22
|
inventory.facts(target)
|
23
23
|
end
|
@@ -40,7 +40,7 @@ Puppet::Functions.create_function(:fail_plan) do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
executor = Puppet.lookup(:bolt_executor)
|
43
|
-
executor.report_function_call(
|
43
|
+
executor.report_function_call(self.class.name)
|
44
44
|
|
45
45
|
raise Bolt::PlanFailure.new(msg, kind || 'bolt/plan-failure', details, issue_code)
|
46
46
|
end
|
@@ -25,7 +25,7 @@ Puppet::Functions.create_function(:get_targets) do
|
|
25
25
|
inventory = Puppet.lookup(:bolt_inventory)
|
26
26
|
# Bolt executor not expected when invoked from apply block
|
27
27
|
executor = Puppet.lookup(:bolt_executor) { nil }
|
28
|
-
executor&.report_function_call(
|
28
|
+
executor&.report_function_call(self.class.name)
|
29
29
|
|
30
30
|
inventory.get_targets(names)
|
31
31
|
end
|
@@ -20,7 +20,7 @@ Puppet::Functions.create_function(:puppetdb_fact) do
|
|
20
20
|
puppetdb_client = Puppet.lookup(:bolt_pdb_client)
|
21
21
|
# Bolt executor not expected when invoked from apply block
|
22
22
|
executor = Puppet.lookup(:bolt_executor) { nil }
|
23
|
-
executor&.report_function_call(
|
23
|
+
executor&.report_function_call(self.class.name)
|
24
24
|
|
25
25
|
puppetdb_client.facts_for_node(certnames)
|
26
26
|
end
|
@@ -22,7 +22,7 @@ Puppet::Functions.create_function(:puppetdb_query) do
|
|
22
22
|
puppetdb_client = Puppet.lookup(:bolt_pdb_client)
|
23
23
|
# Bolt executor not expected when invoked from apply block
|
24
24
|
executor = Puppet.lookup(:bolt_executor) { nil }
|
25
|
-
executor&.report_function_call(
|
25
|
+
executor&.report_function_call(self.class.name)
|
26
26
|
|
27
27
|
puppetdb_client.make_query(query)
|
28
28
|
end
|
@@ -52,7 +52,7 @@ Puppet::Functions.create_function(:run_command) do
|
|
52
52
|
executor = Puppet.lookup(:bolt_executor)
|
53
53
|
inventory = Puppet.lookup(:bolt_inventory)
|
54
54
|
|
55
|
-
executor.report_function_call(
|
55
|
+
executor.report_function_call(self.class.name)
|
56
56
|
|
57
57
|
# Ensure that given targets are all Target instances
|
58
58
|
targets = inventory.get_targets(targets)
|
@@ -29,7 +29,7 @@ Puppet::Functions.create_function(:run_plan, Puppet::Functions::InternalFunction
|
|
29
29
|
# Bolt calls this function internally to trigger plans from the CLI. We
|
30
30
|
# don't want to count those invocations.
|
31
31
|
unless named_args['_bolt_api_call']
|
32
|
-
executor.report_function_call(
|
32
|
+
executor.report_function_call(self.class.name)
|
33
33
|
end
|
34
34
|
|
35
35
|
# Report bundled content, this should capture plans run from both CLI and Plans
|
@@ -58,7 +58,7 @@ Puppet::Functions.create_function(:run_script, Puppet::Functions::InternalFuncti
|
|
58
58
|
executor = Puppet.lookup(:bolt_executor)
|
59
59
|
inventory = Puppet.lookup(:bolt_inventory)
|
60
60
|
|
61
|
-
executor.report_function_call(
|
61
|
+
executor.report_function_call(self.class.name)
|
62
62
|
|
63
63
|
found = Puppet::Parser::Files.find_file(script, scope.compiler.environment)
|
64
64
|
unless found && Puppet::FileSystem.exist?(found)
|
@@ -56,7 +56,7 @@ Puppet::Functions.create_function(:run_task) do
|
|
56
56
|
# Bolt calls this function internally to trigger tasks from the CLI. We
|
57
57
|
# don't want to count those invocations.
|
58
58
|
unless task_args['_bolt_api_call']
|
59
|
-
executor.report_function_call(
|
59
|
+
executor.report_function_call(self.class.name)
|
60
60
|
end
|
61
61
|
|
62
62
|
# Report bundled content, this should capture tasks run from both CLI and Plans
|
@@ -32,7 +32,7 @@ Puppet::Functions.create_function(:set_feature) do
|
|
32
32
|
|
33
33
|
inventory = Puppet.lookup(:bolt_inventory)
|
34
34
|
executor = Puppet.lookup(:bolt_executor)
|
35
|
-
executor.report_function_call(
|
35
|
+
executor.report_function_call(self.class.name)
|
36
36
|
|
37
37
|
inventory.set_feature(target, feature, value)
|
38
38
|
|
@@ -26,7 +26,7 @@ Puppet::Functions.create_function(:set_var) do
|
|
26
26
|
|
27
27
|
inventory = Puppet.lookup(:bolt_inventory)
|
28
28
|
executor = Puppet.lookup(:bolt_executor)
|
29
|
-
executor.report_function_call(
|
29
|
+
executor.report_function_call(self.class.name)
|
30
30
|
|
31
31
|
inventory.set_var(target, key, value)
|
32
32
|
end
|
@@ -62,7 +62,7 @@ Puppet::Functions.create_function(:upload_file, Puppet::Functions::InternalFunct
|
|
62
62
|
executor = Puppet.lookup(:bolt_executor)
|
63
63
|
inventory = Puppet.lookup(:bolt_inventory)
|
64
64
|
|
65
|
-
executor.report_function_call(
|
65
|
+
executor.report_function_call(self.class.name)
|
66
66
|
|
67
67
|
found = Puppet::Parser::Files.find_file(source, scope.compiler.environment)
|
68
68
|
unless found && Puppet::FileSystem.exist?(found)
|
@@ -21,7 +21,7 @@ Puppet::Functions.create_function(:vars) do
|
|
21
21
|
inventory = Puppet.lookup(:bolt_inventory)
|
22
22
|
# Bolt executor not expected when invoked from apply block
|
23
23
|
executor = Puppet.lookup(:bolt_executor) { nil }
|
24
|
-
executor&.report_function_call(
|
24
|
+
executor&.report_function_call(self.class.name)
|
25
25
|
|
26
26
|
inventory.vars(target)
|
27
27
|
end
|
@@ -29,7 +29,7 @@ Puppet::Functions.create_function(:wait_until_available) do
|
|
29
29
|
executor = Puppet.lookup(:bolt_executor)
|
30
30
|
inventory = Puppet.lookup(:bolt_inventory)
|
31
31
|
|
32
|
-
executor.report_function_call(
|
32
|
+
executor.report_function_call(self.class.name)
|
33
33
|
|
34
34
|
# Ensure that given targets are all Target instances
|
35
35
|
targets = inventory.get_targets(targets)
|
@@ -29,7 +29,7 @@ Puppet::Functions.create_function(:without_default_logging) do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
executor = Puppet.lookup(:bolt_executor)
|
32
|
-
executor.report_function_call(
|
32
|
+
executor.report_function_call(self.class.name)
|
33
33
|
|
34
34
|
executor.without_default_logging do
|
35
35
|
yield
|
@@ -14,6 +14,7 @@ Puppet::Functions.create_function(:'file::exists', Puppet::Functions::InternalFu
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def exists(scope, filename)
|
17
|
+
Puppet.lookup(:bolt_executor) {}&.report_function_call(self.class.name)
|
17
18
|
found = Puppet::Parser::Files.find_file(filename, scope.compiler.environment)
|
18
19
|
found && Puppet::FileSystem.exist?(found)
|
19
20
|
end
|
@@ -14,6 +14,7 @@ Puppet::Functions.create_function(:'file::read', Puppet::Functions::InternalFunc
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def read(scope, filename)
|
17
|
+
Puppet.lookup(:bolt_executor) {}&.report_function_call(self.class.name)
|
17
18
|
found = Puppet::Parser::Files.find_file(filename, scope.compiler.environment)
|
18
19
|
unless found && Puppet::FileSystem.exist?(found)
|
19
20
|
raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
|
@@ -14,6 +14,7 @@ Puppet::Functions.create_function(:'file::readable', Puppet::Functions::Internal
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def readable(scope, filename)
|
17
|
+
Puppet.lookup(:bolt_executor) {}&.report_function_call(self.class.name)
|
17
18
|
found = Puppet::Parser::Files.find_file(filename, scope.compiler.environment)
|
18
19
|
found && File.readable?(found)
|
19
20
|
end
|
data/lib/bolt/cli.rb
CHANGED
@@ -310,7 +310,7 @@ module Bolt
|
|
310
310
|
when 'plan'
|
311
311
|
code = run_plan(options[:object], options[:task_options], options[:target_args], options)
|
312
312
|
when 'puppetfile'
|
313
|
-
code = install_puppetfile(@config.puppetfile, @config.modulepath)
|
313
|
+
code = install_puppetfile(@config.puppetfile_config, @config.puppetfile, @config.modulepath)
|
314
314
|
when 'apply'
|
315
315
|
if options[:object]
|
316
316
|
validate_file('manifest', options[:object])
|
@@ -451,18 +451,21 @@ module Bolt
|
|
451
451
|
outputter.print_module_list(pal.list_modules)
|
452
452
|
end
|
453
453
|
|
454
|
-
def install_puppetfile(puppetfile, modulepath)
|
455
|
-
require 'r10k/
|
454
|
+
def install_puppetfile(config, puppetfile, modulepath)
|
455
|
+
require 'r10k/cli'
|
456
456
|
require 'bolt/r10k_log_proxy'
|
457
457
|
|
458
458
|
if puppetfile.exist?
|
459
459
|
moduledir = modulepath.first.to_s
|
460
|
-
|
460
|
+
r10k_opts = {
|
461
461
|
root: puppetfile.dirname.to_s,
|
462
462
|
puppetfile: puppetfile.to_s,
|
463
463
|
moduledir: moduledir
|
464
464
|
}
|
465
|
-
|
465
|
+
|
466
|
+
settings = R10K::Settings.global_settings.evaluate(config)
|
467
|
+
R10K::Initializers::GlobalInitializer.new(settings).call
|
468
|
+
install_action = R10K::Action::Puppetfile::Install.new(r10k_opts, nil)
|
466
469
|
|
467
470
|
# Override the r10k logger with a proxy to our own logger
|
468
471
|
R10K::Logging.instance_variable_set(:@outputter, Bolt::R10KLogProxy.new)
|
data/lib/bolt/config.rb
CHANGED
@@ -32,13 +32,16 @@ module Bolt
|
|
32
32
|
|
33
33
|
class Config
|
34
34
|
attr_accessor :concurrency, :format, :trace, :log, :puppetdb, :color, :save_rerun,
|
35
|
-
:transport, :transports, :inventoryfile, :compile_concurrency, :boltdir
|
35
|
+
:transport, :transports, :inventoryfile, :compile_concurrency, :boltdir,
|
36
|
+
:puppetfile_config
|
36
37
|
attr_writer :modulepath
|
37
38
|
|
38
39
|
TRANSPORT_OPTIONS = %i[password run-as sudo-password extensions
|
39
40
|
private-key tty tmpdir user connect-timeout
|
40
41
|
cacert token-file service-url interpreters file-protocol smb-port].freeze
|
41
42
|
|
43
|
+
PUPPETFILE_OPTIONS = %w[proxy].freeze
|
44
|
+
|
42
45
|
def self.default
|
43
46
|
new(Bolt::Boltdir.new('.'), {})
|
44
47
|
end
|
@@ -66,6 +69,7 @@ module Bolt
|
|
66
69
|
@puppetdb = {}
|
67
70
|
@color = true
|
68
71
|
@save_rerun = true
|
72
|
+
@puppetfile_config = {}
|
69
73
|
|
70
74
|
# add an entry for the default console logger
|
71
75
|
@log = { 'console' => {} }
|
@@ -145,6 +149,10 @@ module Bolt
|
|
145
149
|
|
146
150
|
@inventoryfile = File.expand_path(data['inventoryfile'], @boltdir.path) if data.key?('inventoryfile')
|
147
151
|
|
152
|
+
if data.key?('puppetfile')
|
153
|
+
@puppetfile_config = data['puppetfile'].select { |k, _| PUPPETFILE_OPTIONS.include?(k) }
|
154
|
+
end
|
155
|
+
|
148
156
|
@hiera_config = File.expand_path(data['hiera-config'], @boltdir.path) if data.key?('hiera-config')
|
149
157
|
@compile_concurrency = data['compile-concurrency'] if data.key?('compile-concurrency')
|
150
158
|
|
@@ -16,11 +16,16 @@ module Bolt
|
|
16
16
|
GROUP_KEYS = DATA_KEYS + %w[groups targets target-lookups]
|
17
17
|
CONFIG_KEYS = Bolt::TRANSPORTS.keys.map(&:to_s) + ['transport']
|
18
18
|
|
19
|
-
def initialize(data)
|
19
|
+
def initialize(data, plugins)
|
20
20
|
@logger = Logging.logger[self]
|
21
|
-
|
22
21
|
raise ValidationError.new("Expected group to be a Hash, not #{data.class}", nil) unless data.is_a?(Hash)
|
22
|
+
raise ValidationError.new("Cannot set group with plugin", nil) if data.key?('_plugin')
|
23
23
|
raise ValidationError.new("Group does not have a name", nil) unless data.key?('name')
|
24
|
+
@plugins = plugins
|
25
|
+
|
26
|
+
%w[name vars features facts].each do |key|
|
27
|
+
validate_config_plugin(data[key], key, nil)
|
28
|
+
end
|
24
29
|
|
25
30
|
@name = data['name']
|
26
31
|
raise ValidationError.new("Group name must be a String, not #{@name.inspect}", nil) unless @name.is_a?(String)
|
@@ -34,7 +39,8 @@ module Bolt
|
|
34
39
|
@vars = fetch_value(data, 'vars', Hash)
|
35
40
|
@facts = fetch_value(data, 'facts', Hash)
|
36
41
|
@features = fetch_value(data, 'features', Array)
|
37
|
-
|
42
|
+
|
43
|
+
@config = config_only_plugin(fetch_value(data, 'config', Hash))
|
38
44
|
|
39
45
|
@target_lookups = fetch_value(data, 'target-lookups', Array)
|
40
46
|
|
@@ -60,9 +66,41 @@ module Bolt
|
|
60
66
|
end
|
61
67
|
end
|
62
68
|
|
63
|
-
@groups = groups.map { |g| Group2.new(g) }
|
69
|
+
@groups = groups.map { |g| Group2.new(g, plugins) }
|
64
70
|
end
|
65
71
|
|
72
|
+
def validate_config_plugin(data, key, group_name = nil)
|
73
|
+
if data.is_a?(Hash) && data.include?('_plugin')
|
74
|
+
if group_name
|
75
|
+
raise ValidationError.new("Cannot set target #{key.inspect} with plugin", group_name)
|
76
|
+
else
|
77
|
+
raise ValidationError.new("Cannot set group #{key.inspect} with plugin", nil)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
if data.is_a? Hash
|
81
|
+
data.each do |_k, v|
|
82
|
+
validate_config_plugin(v, key, group_name)
|
83
|
+
end
|
84
|
+
elsif data.is_a? Array
|
85
|
+
data.map { |v| validate_config_plugin(v, key, group_name) }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
private :validate_config_plugin
|
89
|
+
|
90
|
+
def config_only_plugin(data)
|
91
|
+
Bolt::Util.walk_vals(data) do |value|
|
92
|
+
if value.is_a?(Hash) && value.include?('_plugin')
|
93
|
+
unless (plugin = @plugins.by_name(value['_plugin']))
|
94
|
+
raise ValidationError.new("unkown plugin: #{value['_plugin'].inspect}", nil)
|
95
|
+
end
|
96
|
+
plugin.new.inventory_config_lookup(value)
|
97
|
+
else
|
98
|
+
value
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
private :config_only_plugin
|
103
|
+
|
66
104
|
def target_data(target_name)
|
67
105
|
if (data = @targets[target_name])
|
68
106
|
{ 'config' => data['config'] || {},
|
@@ -83,6 +121,11 @@ module Bolt
|
|
83
121
|
unless target.is_a?(Hash)
|
84
122
|
raise ValidationError.new("Node entry must be a String or Hash, not #{target.class}", @name)
|
85
123
|
end
|
124
|
+
raise ValidationError.new("Cannot set target with plugin", @name) if target.key?('_plugin')
|
125
|
+
target.each do |k, v|
|
126
|
+
next if k == 'config'
|
127
|
+
validate_config_plugin(v, k, @name)
|
128
|
+
end
|
86
129
|
|
87
130
|
target['name'] ||= target['uri']
|
88
131
|
|
@@ -113,6 +156,7 @@ module Bolt
|
|
113
156
|
@logger.warn(msg)
|
114
157
|
end
|
115
158
|
|
159
|
+
target['config'] = config_only_plugin(target['config'])
|
116
160
|
unless target.include?('alias')
|
117
161
|
return
|
118
162
|
end
|
@@ -145,7 +189,6 @@ module Bolt
|
|
145
189
|
|
146
190
|
unless (plugin = plugins.by_name(lookup['plugin']))
|
147
191
|
raise ValidationError.new("target-lookup specifies an unkown plugin: '#{lookup['plugin']}'", @name)
|
148
|
-
|
149
192
|
end
|
150
193
|
|
151
194
|
targets = plugin.lookup_targets(lookup)
|
@@ -16,13 +16,12 @@ module Bolt
|
|
16
16
|
@logger = Logging.logger[self]
|
17
17
|
# Config is saved to add config options to targets
|
18
18
|
@config = config || Bolt::Config.default
|
19
|
-
@data = data
|
20
|
-
@groups = Group2.new(data.merge('name' => 'all'))
|
19
|
+
@data = data || {}
|
20
|
+
@groups = Group2.new(@data.merge('name' => 'all'), plugins)
|
21
21
|
@group_lookup = {}
|
22
22
|
@target_vars = target_vars
|
23
23
|
@target_facts = target_facts
|
24
24
|
@target_features = target_features
|
25
|
-
|
26
25
|
@groups.lookup_targets(plugins)
|
27
26
|
@groups.resolve_aliases(@groups.target_aliases, @groups.target_names)
|
28
27
|
collect_groups
|
@@ -103,13 +102,13 @@ module Bolt
|
|
103
102
|
|
104
103
|
def data_hash
|
105
104
|
{
|
106
|
-
data:
|
105
|
+
data: {},
|
107
106
|
target_hash: {
|
108
|
-
target_vars:
|
109
|
-
target_facts:
|
110
|
-
target_features:
|
107
|
+
target_vars: {},
|
108
|
+
target_facts: {},
|
109
|
+
target_features: {}
|
111
110
|
},
|
112
|
-
config:
|
111
|
+
config: { transports: {} }
|
113
112
|
}
|
114
113
|
end
|
115
114
|
|
@@ -121,6 +120,18 @@ module Bolt
|
|
121
120
|
end
|
122
121
|
private :groups_in
|
123
122
|
|
123
|
+
# Look for _plugins
|
124
|
+
def config_plugin(data)
|
125
|
+
Bolt::Util.walk_vals(data) do |val|
|
126
|
+
if val.is_a?(Concurrent::Delay)
|
127
|
+
val.value
|
128
|
+
else
|
129
|
+
val
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
private :config_plugin
|
134
|
+
|
124
135
|
# Pass a target to get_targets for a public version of this
|
125
136
|
# Should this reconfigure configured targets?
|
126
137
|
def update_target(target)
|
@@ -138,6 +149,7 @@ module Bolt
|
|
138
149
|
set_vars_from_hash(target.name, data['vars']) unless @target_vars[target.name]
|
139
150
|
set_facts(target.name, data['facts']) unless @target_facts[target.name]
|
140
151
|
data['features']&.each { |feature| set_feature(target, feature) } unless @target_features[target.name]
|
152
|
+
data['config'] = config_plugin(data['config'])
|
141
153
|
|
142
154
|
# Use Config object to ensure config section is treated consistently with config file
|
143
155
|
conf = @config.deep_clone
|
data/lib/bolt/plugin.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'bolt/plugin/puppetdb'
|
4
4
|
require 'bolt/plugin/terraform'
|
5
|
+
require 'bolt/plugin/prompt'
|
5
6
|
|
6
7
|
module Bolt
|
7
8
|
class Plugin
|
@@ -9,6 +10,7 @@ module Bolt
|
|
9
10
|
plugins = new(config)
|
10
11
|
plugins.add_plugin(Bolt::Plugin::Puppetdb.new(pdb_client))
|
11
12
|
plugins.add_plugin(Bolt::Plugin::Terraform.new)
|
13
|
+
plugins.add_plugin(Bolt::Plugin::Prompt)
|
12
14
|
plugins
|
13
15
|
end
|
14
16
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'concurrent/delay'
|
4
|
+
module Bolt
|
5
|
+
class Plugin
|
6
|
+
class Prompt
|
7
|
+
def initialize
|
8
|
+
# Might not need this
|
9
|
+
@logger = Logging.logger[self]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.name
|
13
|
+
'prompt'
|
14
|
+
end
|
15
|
+
|
16
|
+
def hooks
|
17
|
+
['inventory_config_lookup']
|
18
|
+
end
|
19
|
+
|
20
|
+
def inventory_config_lookup(opts)
|
21
|
+
raise Bolt::ValidationError, "Prompt requires a 'message'" unless opts['message']
|
22
|
+
# Return a delay to only be evaluated when needed
|
23
|
+
Concurrent::Delay.new do
|
24
|
+
STDOUT.print "#{opts['message']}:"
|
25
|
+
value = STDIN.noecho(&:gets).chomp
|
26
|
+
STDOUT.puts
|
27
|
+
value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -24,29 +24,22 @@ module Bolt
|
|
24
24
|
def lookup_targets(opts)
|
25
25
|
state = load_statefile(opts)
|
26
26
|
|
27
|
-
resources = state
|
28
|
-
mod.fetch('resources', {}).map do |name, resource|
|
29
|
-
[name, resource.dig('primary', 'attributes')]
|
30
|
-
end
|
31
|
-
end
|
27
|
+
resources = extract_resources(state)
|
32
28
|
|
33
29
|
regex = Regexp.new(opts['resource_type'])
|
34
30
|
|
35
31
|
resources.select do |name, _resource|
|
36
32
|
name.match?(regex)
|
37
33
|
end.map do |name, resource|
|
38
|
-
|
39
|
-
warn_missing_property(name, opts['uri'])
|
40
|
-
next
|
41
|
-
end
|
34
|
+
target = {}
|
42
35
|
|
43
|
-
|
36
|
+
if opts.key?('uri')
|
37
|
+
uri = lookup(name, resource, opts['uri'])
|
38
|
+
target['uri'] = uri if uri
|
39
|
+
end
|
44
40
|
if opts.key?('name')
|
45
|
-
|
46
|
-
|
47
|
-
else
|
48
|
-
warn_missing_property(name, opts['name'])
|
49
|
-
end
|
41
|
+
real_name = lookup(name, resource, opts['name'])
|
42
|
+
target['name'] = real_name if real_name
|
50
43
|
end
|
51
44
|
if opts.key?('config')
|
52
45
|
target['config'] = resolve_config(name, resource, opts['config'])
|
@@ -65,15 +58,57 @@ module Bolt
|
|
65
58
|
raise Bolt::FileError.new("Could not load Terraform state file #{filename}: #{e}", filename)
|
66
59
|
end
|
67
60
|
|
61
|
+
# Format the list of resources into a list of [name, attribute map]
|
62
|
+
# pairs. This method handles both version 4 and earlier statefiles, doing
|
63
|
+
# the appropriate munging based on the shape of the data.
|
64
|
+
def extract_resources(state)
|
65
|
+
if state['version'] >= 4
|
66
|
+
state.fetch('resources', []).flat_map do |resource_set|
|
67
|
+
prefix = "#{resource_set['type']}.#{resource_set['name']}"
|
68
|
+
resource_set['instances'].map do |resource|
|
69
|
+
instance_name = prefix
|
70
|
+
instance_name += ".#{resource['index_key']}" if resource['index_key']
|
71
|
+
|
72
|
+
[instance_name, resource['attributes']]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
else
|
76
|
+
state.fetch('modules', {}).flat_map do |mod|
|
77
|
+
mod.fetch('resources', {}).map do |name, resource|
|
78
|
+
[name, resource.dig('primary', 'attributes')]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Look up a nested value from the resource attributes. The key is of the
|
85
|
+
# form `foo.bar.0.baz`. For terraform statefile version 3, this will
|
86
|
+
# exactly correspond to a key in the resource. In version 4, it will
|
87
|
+
# correspond to a nested hash entry at {foo: {bar: [{baz: <value>}]}}
|
88
|
+
# For simplicity's sake, we just check both.
|
89
|
+
def lookup(name, resource, path)
|
90
|
+
segments = path.split('.').map do |segment|
|
91
|
+
begin
|
92
|
+
Integer(segment)
|
93
|
+
rescue ArgumentError
|
94
|
+
segment
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
value = resource[path] || resource.dig(*segments)
|
99
|
+
unless value
|
100
|
+
warn_missing_property(name, path)
|
101
|
+
end
|
102
|
+
value
|
103
|
+
end
|
104
|
+
|
105
|
+
# Walk the "template" config mapping provided in the plugin config and
|
106
|
+
# replace all values with the corresponding value from the resource
|
107
|
+
# parameters.
|
68
108
|
def resolve_config(name, resource, config_template)
|
69
109
|
Bolt::Util.walk_vals(config_template) do |value|
|
70
110
|
if value.is_a?(String)
|
71
|
-
|
72
|
-
resource[value]
|
73
|
-
else
|
74
|
-
warn_missing_property(name, value)
|
75
|
-
nil
|
76
|
-
end
|
111
|
+
lookup(name, resource, value)
|
77
112
|
else
|
78
113
|
value
|
79
114
|
end
|
data/lib/bolt/task.rb
CHANGED
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.22.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
|
+
date: 2019-06-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -388,6 +388,7 @@ files:
|
|
388
388
|
- lib/bolt/pal/yaml_plan/transpiler.rb
|
389
389
|
- lib/bolt/plan_result.rb
|
390
390
|
- lib/bolt/plugin.rb
|
391
|
+
- lib/bolt/plugin/prompt.rb
|
391
392
|
- lib/bolt/plugin/puppetdb.rb
|
392
393
|
- lib/bolt/plugin/terraform.rb
|
393
394
|
- lib/bolt/puppetdb.rb
|