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
@@ -1,25 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'bolt/inventory/
|
3
|
+
require 'bolt/inventory/group'
|
4
4
|
require 'bolt/inventory/target'
|
5
5
|
|
6
6
|
module Bolt
|
7
7
|
class Inventory
|
8
|
-
class
|
8
|
+
class Inventory
|
9
9
|
attr_reader :targets, :plugins, :config
|
10
|
-
# This uses "targets" in the message instead of "nodes"
|
11
10
|
class WildcardError < Bolt::Error
|
12
11
|
def initialize(target)
|
13
12
|
super("Found 0 targets matching wildcard pattern #{target}", 'bolt.inventory/wildcard-error')
|
14
13
|
end
|
15
14
|
end
|
16
15
|
|
17
|
-
def initialize(data, config = nil, plugins:
|
16
|
+
def initialize(data, config = nil, plugins:)
|
18
17
|
@logger = Logging.logger[self]
|
19
18
|
# Config is saved to add config options to targets
|
20
19
|
@config = config || Bolt::Config.default
|
21
20
|
@data = data || {}
|
22
|
-
@groups =
|
21
|
+
@groups = Group.new(@data.merge('name' => 'all'), plugins)
|
23
22
|
@plugins = plugins
|
24
23
|
@group_lookup = {}
|
25
24
|
# The targets hash is the canonical source for all targets in inventory
|
@@ -37,7 +36,7 @@ module Bolt
|
|
37
36
|
end
|
38
37
|
|
39
38
|
def target_implementation_class
|
40
|
-
Bolt::
|
39
|
+
Bolt::Target
|
41
40
|
end
|
42
41
|
|
43
42
|
def collect_groups
|
@@ -84,6 +83,20 @@ module Bolt
|
|
84
83
|
}
|
85
84
|
end
|
86
85
|
|
86
|
+
def self.localhost_defaults(data)
|
87
|
+
defaults = {
|
88
|
+
'config' => {
|
89
|
+
'transport' => 'local',
|
90
|
+
'local' => { 'interpreters' => { '.rb' => RbConfig.ruby } }
|
91
|
+
},
|
92
|
+
'features' => ['puppet-agent']
|
93
|
+
}
|
94
|
+
data = Bolt::Util.deep_merge(defaults, data)
|
95
|
+
# If features is an empty array deep_merge won't add the puppet-agent
|
96
|
+
data['features'] += ['puppet-agent'] if data['features'].empty?
|
97
|
+
data
|
98
|
+
end
|
99
|
+
|
87
100
|
#### PRIVATE ####
|
88
101
|
def group_data_for(target_name)
|
89
102
|
@groups.group_collect(target_name)
|
@@ -115,7 +128,7 @@ module Bolt
|
|
115
128
|
private :resolve_name
|
116
129
|
|
117
130
|
def expand_targets(targets)
|
118
|
-
if targets.is_a? Bolt::
|
131
|
+
if targets.is_a? Bolt::Target
|
119
132
|
targets
|
120
133
|
elsif targets.is_a? Array
|
121
134
|
targets.map { |tish| expand_targets(tish) }
|
@@ -125,11 +138,11 @@ module Bolt
|
|
125
138
|
ts = resolve_name(name)
|
126
139
|
ts.map do |t|
|
127
140
|
# If the target doesn't exist, evaluate it from the inventory.
|
128
|
-
# Then return a Bolt::
|
141
|
+
# Then return a Bolt::Target.
|
129
142
|
unless @targets.key?(t)
|
130
143
|
@targets[t] = create_target_from_inventory(t)
|
131
144
|
end
|
132
|
-
Bolt::
|
145
|
+
Bolt::Target.new(t, self)
|
133
146
|
end
|
134
147
|
end
|
135
148
|
end
|
@@ -182,8 +195,8 @@ module Bolt
|
|
182
195
|
|
183
196
|
# Add a brand new target, overriding any existing target with the same
|
184
197
|
# name. This method does not honor target config from the inventory. This
|
185
|
-
# is used when Target.new is called from a plan.
|
186
|
-
def
|
198
|
+
# is used when Target.new is called from a plan or with a data hash.
|
199
|
+
def create_target_from_hash(data)
|
187
200
|
# If target already exists, delete old and replace with new, otherwise add to new to all group
|
188
201
|
new_target = Bolt::Inventory::Target.new(data, self)
|
189
202
|
existing_target = @targets.key?(new_target.name)
|
@@ -257,9 +270,7 @@ module Bolt
|
|
257
270
|
|
258
271
|
def add_facts(target, new_facts = {})
|
259
272
|
@targets[target.name].add_facts(new_facts)
|
260
|
-
|
261
|
-
$future ? target : facts(target)
|
262
|
-
# rubocop:enable Style/GlobalVars
|
273
|
+
target
|
263
274
|
end
|
264
275
|
|
265
276
|
def facts(target)
|
@@ -207,7 +207,7 @@ module Bolt
|
|
207
207
|
|
208
208
|
# This should be handled by `get_targets`
|
209
209
|
if @name == 'localhost'
|
210
|
-
group_data = Bolt::Inventory.localhost_defaults(group_data)
|
210
|
+
group_data = Bolt::Inventory::Inventory.localhost_defaults(group_data)
|
211
211
|
end
|
212
212
|
|
213
213
|
@group_cache = group_data
|
data/lib/bolt/module.rb
CHANGED
@@ -8,10 +8,10 @@ module Bolt
|
|
8
8
|
def self.discover(modulepath)
|
9
9
|
modulepath.each_with_object({}) do |path, mods|
|
10
10
|
next unless File.exist?(path) && File.directory?(path)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
Dir.children(path)
|
12
|
+
.map { |dir| File.join(path, dir) }
|
13
|
+
.select { |dir| File.directory?(dir) }
|
14
|
+
.each do |dir|
|
15
15
|
module_name = File.basename(dir)
|
16
16
|
if module_name =~ MODULE_NAME_REGEX
|
17
17
|
# Puppet will load some objects from shadowed modules but this won't
|
data/lib/bolt/outputter/human.rb
CHANGED
@@ -346,18 +346,23 @@ module Bolt
|
|
346
346
|
# @param [Bolt::PlanResult] plan_result A PlanResult object
|
347
347
|
def print_plan_result(plan_result)
|
348
348
|
value = plan_result.value
|
349
|
-
|
349
|
+
case value
|
350
|
+
when nil
|
350
351
|
@stream.puts("Plan completed successfully with no result")
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
value
|
355
|
-
print_summary(value)
|
352
|
+
when Bolt::ApplyFailure, Bolt::RunFailure
|
353
|
+
print_result_set(value.result_set)
|
354
|
+
when Bolt::ResultSet
|
355
|
+
print_result_set(value)
|
356
356
|
else
|
357
357
|
@stream.puts(::JSON.pretty_generate(plan_result, quirks_mode: true))
|
358
358
|
end
|
359
359
|
end
|
360
360
|
|
361
|
+
def print_result_set(result_set)
|
362
|
+
result_set.each { |result| print_result(result) }
|
363
|
+
print_summary(result_set)
|
364
|
+
end
|
365
|
+
|
361
366
|
def print_puppetfile_result(success, puppetfile, moduledir)
|
362
367
|
if success
|
363
368
|
@stream.puts("Successfully synced modules from #{puppetfile} to #{moduledir}")
|
data/lib/bolt/outputter/json.rb
CHANGED
@@ -36,17 +36,9 @@ module Bolt
|
|
36
36
|
@stream.puts "],\n"
|
37
37
|
@preceding_item = false
|
38
38
|
@items_open = false
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
size: results.size,
|
43
|
-
elapsed: elapsed_time)
|
44
|
-
else
|
45
|
-
@stream.puts format('"node_count": %<size>d, "elapsed_time": %<elapsed>d }',
|
46
|
-
size: results.size,
|
47
|
-
elapsed: elapsed_time)
|
48
|
-
end
|
49
|
-
# rubocop:enable Style/GlobalVars
|
39
|
+
@stream.puts format('"target_count": %<size>d, "elapsed_time": %<elapsed>d }',
|
40
|
+
size: results.size,
|
41
|
+
elapsed: elapsed_time)
|
50
42
|
end
|
51
43
|
|
52
44
|
def print_table(results)
|
data/lib/bolt/pal.rb
CHANGED
@@ -120,8 +120,7 @@ module Bolt
|
|
120
120
|
static_loader = loaders.static_loader
|
121
121
|
static_loader.runtime_3_init
|
122
122
|
if File.directory?(@resource_types)
|
123
|
-
|
124
|
-
(Dir.entries(@resource_types) - %w[. ..]).each do |resource_pp|
|
123
|
+
Dir.children(@resource_types).each do |resource_pp|
|
125
124
|
type_name_from_file = File.basename(resource_pp, '.pp').capitalize
|
126
125
|
typed_name = Puppet::Pops::Loader::TypedName.new(:type, type_name_from_file)
|
127
126
|
resource_type = Puppet::Pops::Types::TypeFactory.resource(type_name_from_file)
|
@@ -80,7 +80,7 @@ module Bolt
|
|
80
80
|
declarations = @normalized_resources.map do |resource|
|
81
81
|
type = resource['type'].is_a?(EvaluableString) ? resource['type'].value : resource['type']
|
82
82
|
title = Bolt::Util.to_code(resource['title'])
|
83
|
-
parameters =
|
83
|
+
parameters = resource['parameters'].transform_values do |val|
|
84
84
|
Bolt::Util.to_code(val)
|
85
85
|
end
|
86
86
|
|
data/lib/bolt/plugin.rb
CHANGED
data/lib/bolt/plugin/module.rb
CHANGED
@@ -6,7 +6,7 @@ module Bolt
|
|
6
6
|
class Plugin
|
7
7
|
class Module
|
8
8
|
class InvalidPluginData < Bolt::Plugin::PluginError
|
9
|
-
def initialize(
|
9
|
+
def initialize(msg, plugin)
|
10
10
|
msg = "Invalid Plugin Data for #{plugin}: #{msg}"
|
11
11
|
super(msg, 'bolt/invalid-plugin-data')
|
12
12
|
end
|
@@ -36,17 +36,17 @@ module Bolt
|
|
36
36
|
def setup
|
37
37
|
@data = load_data
|
38
38
|
@hook_map = find_hooks(@data['hooks'] || {})
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
@config_schema = process_schema(
|
39
|
+
|
40
|
+
if @data['config']
|
41
|
+
msg = <<~MSG.chomp
|
42
|
+
Found unsupported key 'config' in bolt_plugin.json. Config for a plugin is inferred
|
43
|
+
from task parameters, with config values passed as parameters.
|
44
|
+
MSG
|
45
|
+
raise InvalidPluginData.new(msg, name)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Validate againsts the intersection of all task schemas.
|
49
|
+
@config_schema = process_schema(extract_task_parameter_schema)
|
50
50
|
|
51
51
|
validate_config(@config, @config_schema)
|
52
52
|
end
|
@@ -59,10 +59,6 @@ module Bolt
|
|
59
59
|
(@hook_map.keys + [:validate_resolve_reference]).uniq
|
60
60
|
end
|
61
61
|
|
62
|
-
def config?
|
63
|
-
@data.include?('config') && !@data['config'].empty?
|
64
|
-
end
|
65
|
-
|
66
62
|
def load_data
|
67
63
|
JSON.parse(File.read(@module.plugin_data_file))
|
68
64
|
rescue JSON::ParserError => e
|
@@ -159,18 +155,10 @@ module Bolt
|
|
159
155
|
# handled previously. That may not always be the case so filter them
|
160
156
|
# out now.
|
161
157
|
meta, params = opts.partition { |key, _val| key.start_with?('_') }.map(&:to_h)
|
158
|
+
params = config.merge(params)
|
159
|
+
validate_params(task, params)
|
162
160
|
|
163
|
-
|
164
|
-
# Otherwise, merge config with params
|
165
|
-
# TODO: remove @send_config when deprecated
|
166
|
-
if @send_config
|
167
|
-
validate_params(task, params)
|
168
|
-
params['_config'] = config if config?
|
169
|
-
else
|
170
|
-
params = @config ? config.merge(params) : params
|
171
|
-
validate_params(task, params)
|
172
|
-
end
|
173
|
-
params['_boltdir'] = @context.boltdir.to_s
|
161
|
+
meta['_boltdir'] = @context.boltdir.to_s
|
174
162
|
|
175
163
|
[params, meta]
|
176
164
|
end
|
@@ -232,15 +220,10 @@ module Bolt
|
|
232
220
|
end
|
233
221
|
|
234
222
|
def validate_resolve_reference(opts)
|
235
|
-
#
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
params = opts.reject { |k, _v| k.start_with?('_') }
|
240
|
-
else
|
241
|
-
merged = @config.merge(opts)
|
242
|
-
params = merged.reject { |k, _v| k.start_with?('_') }
|
243
|
-
end
|
223
|
+
# Merge config with params
|
224
|
+
merged = @config.merge(opts)
|
225
|
+
params = merged.reject { |k, _v| k.start_with?('_') }
|
226
|
+
|
244
227
|
sig = @hook_map[:resolve_reference]['task']
|
245
228
|
if sig
|
246
229
|
validate_params(sig, params)
|
data/lib/bolt/plugin/prompt.rb
CHANGED
@@ -18,11 +18,9 @@ module Bolt
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def resolve_reference(opts)
|
21
|
-
#
|
22
|
-
$future ? STDERR.print("#{opts['message']}: ") : STDOUT.print("#{opts['message']}: ")
|
21
|
+
STDERR.print("#{opts['message']}: ")
|
23
22
|
value = STDIN.noecho(&:gets).chomp
|
24
|
-
|
25
|
-
# rubocop:enable Style/GlobalVars
|
23
|
+
STDERR.puts
|
26
24
|
|
27
25
|
value
|
28
26
|
end
|
data/lib/bolt/puppetdb/config.rb
CHANGED
@@ -71,13 +71,11 @@ module Bolt
|
|
71
71
|
def expand_paths
|
72
72
|
%w[cacert cert key token].each do |file|
|
73
73
|
next unless @settings[file]
|
74
|
-
|
75
|
-
@settings[file] = if $future && @boltdir_path
|
74
|
+
@settings[file] = if @boltdir_path
|
76
75
|
File.expand_path(@settings[file], @boltdir_path)
|
77
76
|
else
|
78
77
|
File.expand_path(@settings[file])
|
79
78
|
end
|
80
|
-
# rubocop:enable Style/GlobalVars
|
81
79
|
end
|
82
80
|
end
|
83
81
|
|
data/lib/bolt/result.rb
CHANGED
@@ -111,16 +111,13 @@ module Bolt
|
|
111
111
|
end
|
112
112
|
|
113
113
|
def status_hash
|
114
|
-
|
115
|
-
base = {
|
114
|
+
{
|
116
115
|
target: @target.name,
|
117
116
|
action: action,
|
118
117
|
object: object,
|
119
|
-
status: status
|
118
|
+
status: status,
|
119
|
+
value: @value
|
120
120
|
}
|
121
|
-
# rubocop:disable Style/GlobalVars
|
122
|
-
$future ? base.merge(value: @value) : base.merge(result: @value, node: @target.name)
|
123
|
-
# rubocop:enable Style/GlobalVars
|
124
121
|
end
|
125
122
|
|
126
123
|
def generic_value
|
data/lib/bolt/secret/base.rb
CHANGED
@@ -34,12 +34,6 @@ module Bolt
|
|
34
34
|
alias resolve_reference secret_decrypt
|
35
35
|
|
36
36
|
def validate_resolve_reference(opts)
|
37
|
-
# TODO: Remove deprecation warning
|
38
|
-
if opts.include?('encrypted-value')
|
39
|
-
msg = "Parsing error: The 'encrypted-value' key is deprecated and can no longer be used. " \
|
40
|
-
"In your Bolt config files, please use 'encrypted_value' instead."
|
41
|
-
raise Bolt::ValidationError, msg
|
42
|
-
end
|
43
37
|
decode(opts['encrypted_value'])
|
44
38
|
end
|
45
39
|
end
|
data/lib/bolt/target.rb
CHANGED
@@ -4,14 +4,19 @@ require 'bolt/error'
|
|
4
4
|
require 'bolt/util'
|
5
5
|
|
6
6
|
module Bolt
|
7
|
-
class
|
7
|
+
class Target
|
8
8
|
attr_accessor :inventory
|
9
9
|
|
10
|
+
# Target.new from a data hash
|
11
|
+
def self.from_hash(hash, inventory)
|
12
|
+
target = inventory.create_target_from_hash(hash)
|
13
|
+
new(target.name, inventory)
|
14
|
+
end
|
15
|
+
|
10
16
|
# Target.new from a plan initialized with a hash
|
11
17
|
def self.from_asserted_hash(hash)
|
12
18
|
inventory = Puppet.lookup(:bolt_inventory)
|
13
|
-
|
14
|
-
new(target.name, inventory)
|
19
|
+
from_hash(hash, inventory)
|
15
20
|
end
|
16
21
|
|
17
22
|
# TODO: Disallow any positional argument other than URI.
|
@@ -146,220 +151,4 @@ module Bolt
|
|
146
151
|
end
|
147
152
|
alias == eql?
|
148
153
|
end
|
149
|
-
|
150
|
-
class Target
|
151
|
-
attr_reader :options
|
152
|
-
# CODEREVIEW: this feels wrong. The altertative is threading inventory through the
|
153
|
-
# executor to the RemoteTransport
|
154
|
-
attr_accessor :uri, :inventory
|
155
|
-
|
156
|
-
PRINT_OPTS ||= %w[host user port protocol].freeze
|
157
|
-
|
158
|
-
# Satisfies the Puppet datatypes API
|
159
|
-
def self.from_asserted_hash(hash)
|
160
|
-
if hash['uri'] && hash['options']
|
161
|
-
logger = Logging.logger[self]
|
162
|
-
msg = <<~MSG
|
163
|
-
#{Puppet::Pops::PuppetStack.top_of_stack.join(':')}
|
164
|
-
Deprecation Warning: Starting with Bolt 2.0, using 'Target.new' with an 'options' hash key will no
|
165
|
-
will no longer be supported. Use 'Target.new(<config>)', where 'config' is a hash with the same
|
166
|
-
structure used to define targets in the inventory V2 file. For more information see
|
167
|
-
https://puppet.com/docs/bolt/latest/writing_plans.html#creating-target-objects
|
168
|
-
MSG
|
169
|
-
logger.warn(msg)
|
170
|
-
end
|
171
|
-
|
172
|
-
new(hash['uri'], hash['options'])
|
173
|
-
end
|
174
|
-
|
175
|
-
def self.from_asserted_args(uri, options = nil)
|
176
|
-
if options
|
177
|
-
logger = Logging.logger[self]
|
178
|
-
msg = <<~MSG
|
179
|
-
#{Puppet::Pops::PuppetStack.top_of_stack.join(':')}
|
180
|
-
Deprecation Warning: Starting with Bolt 2.0, 'Target.new(<uri>, <options>)' will no
|
181
|
-
longer be supported. Use 'Target.new(<config>)', where 'config' is a hash with the same
|
182
|
-
structure used to define targets in the inventory V2 file. For more information see
|
183
|
-
https://puppet.com/docs/bolt/latest/writing_plans.html#creating-target-objects
|
184
|
-
MSG
|
185
|
-
logger.warn(msg)
|
186
|
-
end
|
187
|
-
|
188
|
-
new(uri, options)
|
189
|
-
end
|
190
|
-
|
191
|
-
# URI can be passes as nil
|
192
|
-
def initialize(uri, options = nil)
|
193
|
-
# lazy-load expensive gem code
|
194
|
-
require 'addressable/uri'
|
195
|
-
|
196
|
-
@uri = uri
|
197
|
-
@uri_obj = parse(uri)
|
198
|
-
@options = options || {}
|
199
|
-
@options.freeze
|
200
|
-
|
201
|
-
if @options['user']
|
202
|
-
@user = @options['user']
|
203
|
-
end
|
204
|
-
|
205
|
-
if @options['password']
|
206
|
-
@password = @options['password']
|
207
|
-
end
|
208
|
-
|
209
|
-
if @options['port']
|
210
|
-
@port = @options['port']
|
211
|
-
end
|
212
|
-
|
213
|
-
if @options['protocol']
|
214
|
-
@protocol = @options['protocol']
|
215
|
-
end
|
216
|
-
|
217
|
-
if @options['host']
|
218
|
-
@host = @options['host']
|
219
|
-
end
|
220
|
-
|
221
|
-
# WARNING: name should never be updated
|
222
|
-
@name = @options['name'] || @uri
|
223
|
-
end
|
224
|
-
|
225
|
-
def update_conf(conf)
|
226
|
-
@protocol = conf[:transport]
|
227
|
-
|
228
|
-
t_conf = conf[:transports][transport.to_sym] || {}
|
229
|
-
# Override url methods
|
230
|
-
@user = t_conf['user']
|
231
|
-
@password = t_conf['password']
|
232
|
-
@port = t_conf['port']
|
233
|
-
@host = t_conf['host']
|
234
|
-
|
235
|
-
# Preserve everything in options so we can easily create copies of a Target.
|
236
|
-
@options = t_conf.merge(@options)
|
237
|
-
|
238
|
-
self
|
239
|
-
end
|
240
|
-
|
241
|
-
def parse(string)
|
242
|
-
if string.nil?
|
243
|
-
nil
|
244
|
-
elsif string =~ %r{^[^:]+://}
|
245
|
-
Addressable::URI.parse(string)
|
246
|
-
else
|
247
|
-
# Initialize with an empty scheme to ensure we parse the hostname correctly
|
248
|
-
Addressable::URI.parse("//#{string}")
|
249
|
-
end
|
250
|
-
rescue Addressable::URI::InvalidURIError => e
|
251
|
-
raise Bolt::ParseError, "Could not parse target URI: #{e.message}"
|
252
|
-
end
|
253
|
-
private :parse
|
254
|
-
|
255
|
-
def features
|
256
|
-
if @inventory
|
257
|
-
@inventory.features(self)
|
258
|
-
else
|
259
|
-
Set.new
|
260
|
-
end
|
261
|
-
end
|
262
|
-
alias feature_set features
|
263
|
-
|
264
|
-
def plugin_hooks
|
265
|
-
if @inventory
|
266
|
-
@inventory.plugin_hooks(self)
|
267
|
-
else
|
268
|
-
{}
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
def vars
|
273
|
-
@inventory.vars(self)
|
274
|
-
end
|
275
|
-
|
276
|
-
def facts
|
277
|
-
@inventory.facts(self)
|
278
|
-
end
|
279
|
-
|
280
|
-
def target_alias
|
281
|
-
@inventory.target_alias(self)
|
282
|
-
end
|
283
|
-
|
284
|
-
# TODO: WHAT does equality mean here?
|
285
|
-
# should we just compare names? is there something else that is meaninful?
|
286
|
-
def eql?(other)
|
287
|
-
if self.class.equal?(other.class)
|
288
|
-
@uri ? @uri == other.uri : @name == other.name
|
289
|
-
else
|
290
|
-
false
|
291
|
-
end
|
292
|
-
end
|
293
|
-
alias == eql?
|
294
|
-
|
295
|
-
def hash
|
296
|
-
@uri.hash ^ @options.hash
|
297
|
-
end
|
298
|
-
|
299
|
-
def to_s
|
300
|
-
opts = @options.select { |k, _| PRINT_OPTS.include? k }
|
301
|
-
"Target('#{@uri}', #{opts})"
|
302
|
-
end
|
303
|
-
|
304
|
-
def to_h
|
305
|
-
options.merge(
|
306
|
-
'name' => name,
|
307
|
-
'uri' => uri,
|
308
|
-
'protocol' => protocol,
|
309
|
-
'user' => user,
|
310
|
-
'password' => password,
|
311
|
-
'host' => host,
|
312
|
-
'port' => port
|
313
|
-
)
|
314
|
-
end
|
315
|
-
|
316
|
-
def detail
|
317
|
-
{
|
318
|
-
'name' => name,
|
319
|
-
'alias' => target_alias,
|
320
|
-
'config' => {
|
321
|
-
'transport' => transport,
|
322
|
-
transport => options
|
323
|
-
},
|
324
|
-
'vars' => vars,
|
325
|
-
'facts' => facts,
|
326
|
-
'features' => features.to_a,
|
327
|
-
'plugin_hooks' => plugin_hooks
|
328
|
-
}
|
329
|
-
end
|
330
|
-
|
331
|
-
def host
|
332
|
-
@uri_obj&.hostname || @host
|
333
|
-
end
|
334
|
-
alias safe_name host
|
335
|
-
|
336
|
-
def name
|
337
|
-
@name || @uri
|
338
|
-
end
|
339
|
-
|
340
|
-
def remote?
|
341
|
-
@uri_obj&.scheme == 'remote' || @protocol == 'remote'
|
342
|
-
end
|
343
|
-
|
344
|
-
def port
|
345
|
-
@uri_obj&.port || @port
|
346
|
-
end
|
347
|
-
|
348
|
-
# transport is separate from protocol for remote targets.
|
349
|
-
def transport
|
350
|
-
remote? ? 'remote' : protocol
|
351
|
-
end
|
352
|
-
|
353
|
-
def protocol
|
354
|
-
@uri_obj&.scheme || @protocol
|
355
|
-
end
|
356
|
-
|
357
|
-
def user
|
358
|
-
Addressable::URI.unencode_component(@uri_obj&.user) || @user
|
359
|
-
end
|
360
|
-
|
361
|
-
def password
|
362
|
-
Addressable::URI.unencode_component(@uri_obj&.password) || @password
|
363
|
-
end
|
364
|
-
end
|
365
154
|
end
|