bolt 2.19.0 → 2.24.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 +3 -1
- data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +123 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +6 -0
- data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +12 -6
- data/bolt-modules/dir/lib/puppet/functions/dir/children.rb +35 -0
- data/bolt-modules/out/lib/puppet/functions/out/message.rb +1 -1
- data/exe/bolt +1 -0
- data/guides/inventory.txt +19 -0
- data/guides/project.txt +22 -0
- data/lib/bolt/analytics.rb +5 -5
- data/lib/bolt/applicator.rb +4 -3
- data/lib/bolt/bolt_option_parser.rb +100 -27
- data/lib/bolt/catalog.rb +12 -3
- data/lib/bolt/cli.rb +356 -156
- data/lib/bolt/config.rb +2 -2
- data/lib/bolt/config/options.rb +18 -4
- data/lib/bolt/executor.rb +30 -7
- data/lib/bolt/inventory/group.rb +6 -5
- data/lib/bolt/inventory/inventory.rb +4 -3
- data/lib/bolt/logger.rb +3 -4
- data/lib/bolt/module.rb +2 -1
- data/lib/bolt/outputter.rb +56 -0
- data/lib/bolt/outputter/human.rb +10 -9
- data/lib/bolt/outputter/json.rb +11 -4
- data/lib/bolt/outputter/logger.rb +2 -2
- data/lib/bolt/outputter/rainbow.rb +18 -2
- data/lib/bolt/pal.rb +13 -11
- data/lib/bolt/pal/yaml_plan/evaluator.rb +22 -1
- data/lib/bolt/pal/yaml_plan/step.rb +24 -2
- data/lib/bolt/pal/yaml_plan/step/download.rb +38 -0
- data/lib/bolt/pal/yaml_plan/step/message.rb +30 -0
- data/lib/bolt/pal/yaml_plan/step/upload.rb +3 -3
- data/lib/bolt/pal/yaml_plan/transpiler.rb +11 -3
- data/lib/bolt/plugin/prompt.rb +3 -3
- data/lib/bolt/plugin/puppetdb.rb +3 -2
- data/lib/bolt/project.rb +7 -4
- data/lib/bolt/project_migrate.rb +138 -0
- data/lib/bolt/puppetdb/client.rb +2 -0
- data/lib/bolt/puppetdb/config.rb +16 -0
- data/lib/bolt/result.rb +7 -0
- data/lib/bolt/shell/bash.rb +31 -11
- data/lib/bolt/shell/powershell.rb +10 -4
- data/lib/bolt/transport/base.rb +24 -0
- data/lib/bolt/transport/docker.rb +8 -0
- data/lib/bolt/transport/docker/connection.rb +28 -10
- data/lib/bolt/transport/local/connection.rb +15 -2
- data/lib/bolt/transport/orch.rb +15 -3
- data/lib/bolt/transport/simple.rb +6 -0
- data/lib/bolt/transport/ssh/connection.rb +13 -5
- data/lib/bolt/transport/ssh/exec_connection.rb +24 -3
- data/lib/bolt/transport/winrm/connection.rb +125 -15
- data/lib/bolt/util.rb +27 -12
- data/lib/bolt/util/puppet_log_level.rb +4 -3
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/base_config.rb +1 -1
- data/lib/bolt_server/pe/pal.rb +1 -1
- data/lib/bolt_server/transport_app.rb +79 -2
- data/lib/bolt_spec/bolt_context.rb +7 -2
- data/lib/bolt_spec/plans.rb +16 -3
- data/lib/bolt_spec/plans/action_stubs.rb +3 -2
- data/lib/bolt_spec/plans/action_stubs/download_stub.rb +66 -0
- data/lib/bolt_spec/plans/mock_executor.rb +14 -1
- data/lib/bolt_spec/run.rb +22 -0
- data/libexec/apply_catalog.rb +2 -2
- data/libexec/bolt_catalog +4 -3
- data/libexec/custom_facts.rb +1 -1
- data/libexec/query_resources.rb +1 -1
- data/modules/secure_env_vars/plans/init.pp +20 -0
- metadata +11 -2
data/lib/bolt/config.rb
CHANGED
@@ -204,7 +204,7 @@ module Bolt
|
|
204
204
|
'compile-concurrency' => Etc.nprocessors,
|
205
205
|
'concurrency' => default_concurrency,
|
206
206
|
'format' => 'human',
|
207
|
-
'log' => { 'console' => {} },
|
207
|
+
'log' => { 'console' => {}, 'bolt-debug.log' => { 'level' => 'debug', 'append' => false } },
|
208
208
|
'plugin_hooks' => {},
|
209
209
|
'plugins' => {},
|
210
210
|
'puppetdb' => {},
|
@@ -499,7 +499,7 @@ module Bolt
|
|
499
499
|
end
|
500
500
|
|
501
501
|
def matching_paths(paths)
|
502
|
-
|
502
|
+
Array(paths).map { |p| Dir.glob([p, casefold(p)]) }.flatten.uniq.reject { |p| Array(paths).include?(p) }
|
503
503
|
end
|
504
504
|
|
505
505
|
private def casefold(path)
|
data/lib/bolt/config/options.rb
CHANGED
@@ -186,8 +186,8 @@ module Bolt
|
|
186
186
|
"level" => {
|
187
187
|
description: "The type of information to log.",
|
188
188
|
type: String,
|
189
|
-
enum: %w[debug error info
|
190
|
-
_default: "warn
|
189
|
+
enum: %w[trace debug error info warn fatal any],
|
190
|
+
_default: "warn"
|
191
191
|
}
|
192
192
|
}
|
193
193
|
}
|
@@ -204,8 +204,8 @@ module Bolt
|
|
204
204
|
"level" => {
|
205
205
|
description: "The type of information to log.",
|
206
206
|
type: String,
|
207
|
-
enum: %w[debug error info
|
208
|
-
_default: "warn
|
207
|
+
enum: %w[trace debug error info warn fatal any],
|
208
|
+
_default: "warn"
|
209
209
|
}
|
210
210
|
}
|
211
211
|
},
|
@@ -275,11 +275,25 @@ module Bolt
|
|
275
275
|
type: String,
|
276
276
|
_example: "/etc/puppetlabs/puppet/ssl/certs/my-host.example.com.pem"
|
277
277
|
},
|
278
|
+
"connect_timeout" => {
|
279
|
+
description: "How long to wait in seconds when establishing connections with PuppetDB.",
|
280
|
+
type: Integer,
|
281
|
+
minimum: 1,
|
282
|
+
_default: 60,
|
283
|
+
_example: 120
|
284
|
+
},
|
278
285
|
"key" => {
|
279
286
|
description: "The private key for the certificate.",
|
280
287
|
type: String,
|
281
288
|
_example: "/etc/puppetlabs/puppet/ssl/private_keys/my-host.example.com.pem"
|
282
289
|
},
|
290
|
+
"read_timeout" => {
|
291
|
+
description: "How long to wait in seconds for a response from PuppetDB.",
|
292
|
+
type: Integer,
|
293
|
+
minimum: 1,
|
294
|
+
_default: 60,
|
295
|
+
_example: 120
|
296
|
+
},
|
283
297
|
"server_urls" => {
|
284
298
|
description: "An array containing the PuppetDB host to connect to. Include the protocol `https` "\
|
285
299
|
"and the port, which is usually `8081`. For example, "\
|
data/lib/bolt/executor.rb
CHANGED
@@ -56,11 +56,12 @@ module Bolt
|
|
56
56
|
@reported_transports = Set.new
|
57
57
|
@subscribers = {}
|
58
58
|
@publisher = Concurrent::SingleThreadExecutor.new
|
59
|
+
@publisher.post { Thread.current[:name] = 'event-publisher' }
|
59
60
|
|
60
61
|
@noop = noop
|
61
62
|
@run_as = nil
|
62
63
|
@pool = if concurrency > 0
|
63
|
-
Concurrent::ThreadPoolExecutor.new(max_threads: concurrency)
|
64
|
+
Concurrent::ThreadPoolExecutor.new(name: 'exec', max_threads: concurrency)
|
64
65
|
else
|
65
66
|
Concurrent.global_immediate_executor
|
66
67
|
end
|
@@ -125,6 +126,7 @@ module Bolt
|
|
125
126
|
# Pass this argument through to avoid retaining a reference to a
|
126
127
|
# local variable that will change on the next iteration of the loop.
|
127
128
|
@pool.post(batch_promises) do |result_promises|
|
129
|
+
Thread.current[:name] ||= Thread.current.name
|
128
130
|
results = yield transport, batch
|
129
131
|
Array(results).each do |result|
|
130
132
|
result_promises[result.target].set(result)
|
@@ -241,7 +243,7 @@ module Bolt
|
|
241
243
|
|
242
244
|
@analytics&.event('Plan', 'yaml', plan_steps: steps, return_type: return_type)
|
243
245
|
rescue StandardError => e
|
244
|
-
@logger.
|
246
|
+
@logger.trace { "Failed to submit analytics event: #{e.message}" }
|
245
247
|
end
|
246
248
|
|
247
249
|
def with_node_logging(description, batch)
|
@@ -320,6 +322,27 @@ module Bolt
|
|
320
322
|
end
|
321
323
|
end
|
322
324
|
|
325
|
+
def download_file(targets, source, destination, options = {})
|
326
|
+
description = options.fetch(:description, "file download from #{source} to #{destination}")
|
327
|
+
|
328
|
+
begin
|
329
|
+
FileUtils.mkdir_p(destination)
|
330
|
+
rescue Errno::EEXIST => e
|
331
|
+
message = "#{e.message}; unable to create destination directory #{destination}"
|
332
|
+
raise Bolt::Error.new(message, 'bolt/file-exist-error')
|
333
|
+
end
|
334
|
+
|
335
|
+
log_action(description, targets) do
|
336
|
+
options[:run_as] = run_as if run_as && !options.key?(:run_as)
|
337
|
+
|
338
|
+
batch_execute(targets) do |transport, batch|
|
339
|
+
with_node_logging("Downloading file #{source} to #{destination}", batch) do
|
340
|
+
transport.batch_download(batch, source, destination, options, &method(:publish_event))
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
323
346
|
def run_plan(scope, plan, params)
|
324
347
|
plan.call_by_name_with_scope(scope, params, true)
|
325
348
|
end
|
@@ -360,19 +383,19 @@ module Bolt
|
|
360
383
|
end
|
361
384
|
|
362
385
|
def prompt(prompt, options)
|
363
|
-
unless
|
386
|
+
unless $stdin.tty?
|
364
387
|
raise Bolt::Error.new('STDIN is not a tty, unable to prompt', 'bolt/no-tty-error')
|
365
388
|
end
|
366
389
|
|
367
|
-
|
390
|
+
$stderr.print("#{prompt}: ")
|
368
391
|
|
369
392
|
value = if options[:sensitive]
|
370
|
-
|
393
|
+
$stdin.noecho(&:gets).to_s.chomp
|
371
394
|
else
|
372
|
-
|
395
|
+
$stdin.gets.to_s.chomp
|
373
396
|
end
|
374
397
|
|
375
|
-
|
398
|
+
$stderr.puts if options[:sensitive]
|
376
399
|
|
377
400
|
value
|
378
401
|
end
|
data/lib/bolt/inventory/group.rb
CHANGED
@@ -50,10 +50,11 @@ module Bolt
|
|
50
50
|
# or it could be a name/alias of a target defined in another group.
|
51
51
|
# We can't tell the difference until all groups have been resolved,
|
52
52
|
# so we store the string on its own here and process it later.
|
53
|
-
|
53
|
+
case target
|
54
|
+
when String
|
54
55
|
@string_targets << target
|
55
56
|
# Handle plugins at this level so that lookups cannot trigger recursive lookups
|
56
|
-
|
57
|
+
when Hash
|
57
58
|
add_target_definition(target)
|
58
59
|
else
|
59
60
|
raise ValidationError.new("Target entry must be a String or Hash, not #{target.class}", @name)
|
@@ -118,7 +119,7 @@ module Bolt
|
|
118
119
|
end
|
119
120
|
|
120
121
|
if contains_target?(t_name)
|
121
|
-
@logger.
|
122
|
+
@logger.debug("Ignoring duplicate target in #{@name}: #{target}")
|
122
123
|
return
|
123
124
|
end
|
124
125
|
|
@@ -199,14 +200,14 @@ module Bolt
|
|
199
200
|
# If this is an alias for an existing target, then add it to this group
|
200
201
|
elsif (canonical_name = aliases[string_target])
|
201
202
|
if contains_target?(canonical_name)
|
202
|
-
@logger.
|
203
|
+
@logger.debug("Ignoring duplicate target in #{@name}: #{canonical_name}")
|
203
204
|
else
|
204
205
|
@unresolved_targets[canonical_name] = { 'name' => canonical_name }
|
205
206
|
end
|
206
207
|
# If it's not the name or alias of an existing target, then make a
|
207
208
|
# new target using the string as the URI
|
208
209
|
elsif contains_target?(string_target)
|
209
|
-
@logger.
|
210
|
+
@logger.debug("Ignoring duplicate target in #{@name}: #{string_target}")
|
210
211
|
else
|
211
212
|
@unresolved_targets[string_target] = { 'uri' => string_target }
|
212
213
|
end
|
@@ -109,11 +109,12 @@ module Bolt
|
|
109
109
|
private :resolve_name
|
110
110
|
|
111
111
|
def expand_targets(targets)
|
112
|
-
|
112
|
+
case targets
|
113
|
+
when Bolt::Target
|
113
114
|
targets
|
114
|
-
|
115
|
+
when Array
|
115
116
|
targets.map { |tish| expand_targets(tish) }
|
116
|
-
|
117
|
+
when String
|
117
118
|
# Expand a comma-separated list
|
118
119
|
targets.split(/[[:space:],]+/).reject(&:empty?).map do |name|
|
119
120
|
ts = resolve_name(name)
|
data/lib/bolt/logger.rb
CHANGED
@@ -14,13 +14,12 @@ module Bolt
|
|
14
14
|
# redefs, so skip it if it's already been initialized
|
15
15
|
return if Logging.initialized?
|
16
16
|
|
17
|
-
Logging.init :debug, :info, :notice, :warn, :error, :fatal, :any
|
17
|
+
Logging.init :trace, :debug, :info, :notice, :warn, :error, :fatal, :any
|
18
18
|
@mutex = Mutex.new
|
19
19
|
|
20
20
|
Logging.color_scheme(
|
21
21
|
'bolt',
|
22
22
|
lines: {
|
23
|
-
notice: :green,
|
24
23
|
warn: :yellow,
|
25
24
|
error: :red,
|
26
25
|
fatal: %i[white on_red]
|
@@ -81,7 +80,7 @@ module Bolt
|
|
81
80
|
|
82
81
|
def self.default_layout
|
83
82
|
Logging.layouts.pattern(
|
84
|
-
pattern: '%d %-6l %c
|
83
|
+
pattern: '%d %-6l [%T] [%c] %m\n',
|
85
84
|
date_pattern: '%Y-%m-%dT%H:%M:%S.%6N'
|
86
85
|
)
|
87
86
|
end
|
@@ -91,7 +90,7 @@ module Bolt
|
|
91
90
|
end
|
92
91
|
|
93
92
|
def self.default_file_level
|
94
|
-
:
|
93
|
+
:warn
|
95
94
|
end
|
96
95
|
|
97
96
|
# Explicitly check the log level names instead of the log level number, as levels
|
data/lib/bolt/module.rb
CHANGED
@@ -3,7 +3,8 @@
|
|
3
3
|
# Is this Bolt::Pobs::Module?
|
4
4
|
module Bolt
|
5
5
|
class Module
|
6
|
-
|
6
|
+
CONTENT_NAME_REGEX = /\A[a-z][a-z0-9_]*(::[a-z][a-z0-9_]*)*\z/.freeze
|
7
|
+
MODULE_NAME_REGEX = /\A[a-z][a-z0-9_]*\z/.freeze
|
7
8
|
|
8
9
|
def self.discover(modulepath)
|
9
10
|
modulepath.each_with_object({}) do |path, mods|
|
data/lib/bolt/outputter.rb
CHANGED
@@ -21,6 +21,62 @@ module Bolt
|
|
21
21
|
@trace = trace
|
22
22
|
@stream = stream
|
23
23
|
end
|
24
|
+
|
25
|
+
def indent(indent, string)
|
26
|
+
indent = ' ' * indent
|
27
|
+
string.gsub(/^/, indent.to_s)
|
28
|
+
end
|
29
|
+
|
30
|
+
def print_message_event(event)
|
31
|
+
print_message(stringify(event[:message]))
|
32
|
+
end
|
33
|
+
|
34
|
+
def print_message
|
35
|
+
raise NotImplementedError, "print_message() must be implemented by the outputter class"
|
36
|
+
end
|
37
|
+
|
38
|
+
def stringify(message)
|
39
|
+
formatted = format_message(message)
|
40
|
+
if formatted.is_a?(Hash) || formatted.is_a?(Array)
|
41
|
+
::JSON.pretty_generate(formatted)
|
42
|
+
else
|
43
|
+
formatted
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def format_message(message)
|
48
|
+
case message
|
49
|
+
when Array
|
50
|
+
message.map { |item| format_message(item) }
|
51
|
+
when Bolt::ApplyResult
|
52
|
+
format_apply_result(message)
|
53
|
+
when Bolt::Result, Bolt::ResultSet
|
54
|
+
# This is equivalent to to_s, but formattable
|
55
|
+
message.to_data
|
56
|
+
when Bolt::RunFailure
|
57
|
+
formatted_resultset = message.result_set.to_data
|
58
|
+
message.to_h.merge('result_set' => formatted_resultset)
|
59
|
+
when Hash
|
60
|
+
message.each_with_object({}) do |(k, v), h|
|
61
|
+
h[format_message(k)] = format_message(v)
|
62
|
+
end
|
63
|
+
when Integer, Float, NilClass
|
64
|
+
message
|
65
|
+
else
|
66
|
+
message.to_s
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def format_apply_result(result)
|
71
|
+
logs = result.resource_logs&.map do |log|
|
72
|
+
# Omit low-level info/debug messages
|
73
|
+
next if %w[info debug].include?(log['level'])
|
74
|
+
indent(2, format_log(log))
|
75
|
+
end
|
76
|
+
hash = result.to_data
|
77
|
+
hash['logs'] = logs unless logs.empty?
|
78
|
+
hash
|
79
|
+
end
|
24
80
|
end
|
25
81
|
end
|
26
82
|
|
data/lib/bolt/outputter/human.rb
CHANGED
@@ -27,11 +27,6 @@ module Bolt
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def indent(indent, string)
|
31
|
-
indent = ' ' * indent
|
32
|
-
string.gsub(/^/, indent.to_s)
|
33
|
-
end
|
34
|
-
|
35
30
|
def remove_trail(string)
|
36
31
|
string.sub(/\s\z/, '')
|
37
32
|
end
|
@@ -291,6 +286,16 @@ module Bolt
|
|
291
286
|
"details and parameters for a specific plan.")
|
292
287
|
end
|
293
288
|
|
289
|
+
def print_topics(topics)
|
290
|
+
print_message("Available topics are:")
|
291
|
+
print_message(topics.join("\n"))
|
292
|
+
print_message("\nUse `bolt guide <topic>` to view a specific guide.")
|
293
|
+
end
|
294
|
+
|
295
|
+
def print_guide(guide, _topic)
|
296
|
+
@stream.puts(guide)
|
297
|
+
end
|
298
|
+
|
294
299
|
def print_module_list(module_list)
|
295
300
|
module_list.each do |path, modules|
|
296
301
|
if (mod = modules.find { |m| m[:internal_module_group] })
|
@@ -372,10 +377,6 @@ module Bolt
|
|
372
377
|
end
|
373
378
|
end
|
374
379
|
|
375
|
-
def print_message_event(event)
|
376
|
-
print_message(event[:message])
|
377
|
-
end
|
378
|
-
|
379
380
|
def fatal_error(err)
|
380
381
|
@stream.puts(colorize(:red, err.message))
|
381
382
|
if err.is_a? Bolt::RunFailure
|
data/lib/bolt/outputter/json.rb
CHANGED
@@ -83,6 +83,17 @@ module Bolt
|
|
83
83
|
@stream.puts result.to_json
|
84
84
|
end
|
85
85
|
|
86
|
+
def print_topics(topics)
|
87
|
+
print_table('topics' => topics)
|
88
|
+
end
|
89
|
+
|
90
|
+
def print_guide(guide, topic)
|
91
|
+
@stream.puts({
|
92
|
+
'topic' => topic,
|
93
|
+
'guide' => guide
|
94
|
+
}.to_json)
|
95
|
+
end
|
96
|
+
|
86
97
|
def print_puppetfile_result(success, puppetfile, moduledir)
|
87
98
|
@stream.puts({ "success": success,
|
88
99
|
"puppetfile": puppetfile,
|
@@ -121,10 +132,6 @@ module Bolt
|
|
121
132
|
@stream.puts '}' if @object_open
|
122
133
|
end
|
123
134
|
|
124
|
-
def print_message_event(event)
|
125
|
-
print_message(event[:message])
|
126
|
-
end
|
127
|
-
|
128
135
|
def print_message(message)
|
129
136
|
$stderr.puts(message)
|
130
137
|
end
|
@@ -40,13 +40,13 @@ module Bolt
|
|
40
40
|
|
41
41
|
def log_plan_start(event)
|
42
42
|
plan = event[:plan]
|
43
|
-
@logger.
|
43
|
+
@logger.info("Starting: plan #{plan}")
|
44
44
|
end
|
45
45
|
|
46
46
|
def log_plan_finish(event)
|
47
47
|
plan = event[:plan]
|
48
48
|
duration = event[:duration]
|
49
|
-
@logger.
|
49
|
+
@logger.info("Finished: plan #{plan} in #{duration.round(2)} sec")
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
@@ -39,9 +39,10 @@ module Bolt
|
|
39
39
|
a = string.chars.map do |c|
|
40
40
|
case @state
|
41
41
|
when :normal
|
42
|
-
|
42
|
+
case c
|
43
|
+
when "\e"
|
43
44
|
@state = :ansi
|
44
|
-
|
45
|
+
when "\n"
|
45
46
|
@line_color += 1
|
46
47
|
@color = @line_color
|
47
48
|
c
|
@@ -85,6 +86,21 @@ module Bolt
|
|
85
86
|
total_msg << " in #{duration_to_string(elapsed_time)}" unless elapsed_time.nil?
|
86
87
|
@stream.puts colorize(:rainbow, total_msg)
|
87
88
|
end
|
89
|
+
|
90
|
+
def print_guide(guide, _topic)
|
91
|
+
@stream.puts colorize(:rainbow, guide)
|
92
|
+
end
|
93
|
+
|
94
|
+
def print_topics(topics)
|
95
|
+
content = String.new("Available topics are:\n")
|
96
|
+
content += topics.join("\n")
|
97
|
+
content += "\n\nUse `bolt guide <topic>` to view a specific guide."
|
98
|
+
@stream.puts colorize(:rainbow, content)
|
99
|
+
end
|
100
|
+
|
101
|
+
def print_message(message)
|
102
|
+
@stream.puts colorize(:rainbow, message)
|
103
|
+
end
|
88
104
|
end
|
89
105
|
end
|
90
106
|
end
|
data/lib/bolt/pal.rb
CHANGED
@@ -48,7 +48,7 @@ module Bolt
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
attr_reader :modulepath
|
51
|
+
attr_reader :modulepath, :user_modulepath
|
52
52
|
|
53
53
|
def initialize(modulepath, hiera_config, resource_types, max_compiles = Etc.nprocessors,
|
54
54
|
trusted_external = nil, apply_settings = {}, project = nil)
|
@@ -56,7 +56,7 @@ module Bolt
|
|
56
56
|
# is safe and in practice only happens in tests
|
57
57
|
self.class.load_puppet
|
58
58
|
|
59
|
-
@
|
59
|
+
@user_modulepath = modulepath
|
60
60
|
@modulepath = [BOLTLIB_PATH, *modulepath, MODULES_PATH]
|
61
61
|
@hiera_config = hiera_config
|
62
62
|
@trusted_external = trusted_external
|
@@ -67,7 +67,7 @@ module Bolt
|
|
67
67
|
|
68
68
|
@logger = Logging.logger[self]
|
69
69
|
if modulepath && !modulepath.empty?
|
70
|
-
@logger.
|
70
|
+
@logger.debug("Loading modules from #{@modulepath.join(File::PATH_SEPARATOR)}")
|
71
71
|
end
|
72
72
|
|
73
73
|
@loaded = false
|
@@ -150,7 +150,12 @@ module Bolt
|
|
150
150
|
r = Puppet::Pal.in_tmp_environment('bolt', modulepath: @modulepath, facts: {}) do |pal|
|
151
151
|
# Only load the project if it a) exists, b) has a name it can be loaded with
|
152
152
|
bolt_project = @project if @project&.name
|
153
|
+
# Puppet currently won't receive the project unless it is a named project. Since
|
154
|
+
# the download_file plan function needs access to the project path, add it to the
|
155
|
+
# context.
|
156
|
+
bolt_project_data = @project
|
153
157
|
Puppet.override(bolt_project: bolt_project,
|
158
|
+
bolt_project_data: bolt_project_data,
|
154
159
|
yaml_plan_instantiator: Bolt::PAL::YamlPlan::Loader) do
|
155
160
|
pal.with_script_compiler do |compiler|
|
156
161
|
alias_types(compiler)
|
@@ -203,7 +208,7 @@ module Bolt
|
|
203
208
|
# Skip syncing built-in plugins, since we vendor some Puppet 6
|
204
209
|
# versions of "core" types, which are already present on the agent,
|
205
210
|
# but may cause issues on Puppet 5 agents.
|
206
|
-
@
|
211
|
+
@user_modulepath,
|
207
212
|
@project,
|
208
213
|
pdb_client,
|
209
214
|
@hiera_config,
|
@@ -273,15 +278,12 @@ module Bolt
|
|
273
278
|
end
|
274
279
|
end
|
275
280
|
|
276
|
-
def list_modulepath
|
277
|
-
@modulepath - [BOLTLIB_PATH, MODULES_PATH]
|
278
|
-
end
|
279
|
-
|
280
281
|
def parse_params(type, object_name, params)
|
281
282
|
in_bolt_compiler do |compiler|
|
282
|
-
|
283
|
+
case type
|
284
|
+
when 'task'
|
283
285
|
param_spec = compiler.task_signature(object_name)&.task_hash&.dig('parameters')
|
284
|
-
|
286
|
+
when 'plan'
|
285
287
|
plan = compiler.plan_signature(object_name)
|
286
288
|
param_spec = plan.params_type.elements&.each_with_object({}) { |t, h| h[t.name] = t.value_type } if plan
|
287
289
|
end
|
@@ -407,7 +409,7 @@ module Bolt
|
|
407
409
|
end
|
408
410
|
params[name] = { 'type' => type_str }
|
409
411
|
params[name]['sensitive'] = param.type_expr.instance_of?(Puppet::Pops::Types::PSensitiveType)
|
410
|
-
params[name]['default_value'] = param.value
|
412
|
+
params[name]['default_value'] = param.value unless param.value.nil?
|
411
413
|
params[name]['description'] = param.description if param.description
|
412
414
|
end
|
413
415
|
{
|