bolt 2.23.0 → 2.27.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 +1 -1
- data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +2 -1
- data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +1 -1
- data/bolt-modules/dir/lib/puppet/functions/dir/children.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 +11 -7
- data/lib/bolt/applicator.rb +11 -10
- data/lib/bolt/bolt_option_parser.rb +75 -13
- data/lib/bolt/catalog.rb +4 -2
- data/lib/bolt/cli.rb +156 -176
- data/lib/bolt/config.rb +55 -25
- data/lib/bolt/config/options.rb +28 -6
- data/lib/bolt/executor.rb +5 -3
- data/lib/bolt/inventory.rb +8 -1
- data/lib/bolt/inventory/group.rb +4 -4
- data/lib/bolt/inventory/inventory.rb +1 -1
- data/lib/bolt/inventory/target.rb +1 -1
- data/lib/bolt/logger.rb +12 -6
- data/lib/bolt/outputter/human.rb +10 -0
- data/lib/bolt/outputter/json.rb +11 -0
- data/lib/bolt/outputter/logger.rb +3 -3
- data/lib/bolt/outputter/rainbow.rb +15 -0
- data/lib/bolt/pal.rb +23 -12
- data/lib/bolt/pal/yaml_plan/evaluator.rb +1 -1
- data/lib/bolt/pal/yaml_plan/transpiler.rb +11 -3
- data/lib/bolt/plugin/puppetdb.rb +1 -1
- data/lib/bolt/project.rb +63 -17
- data/lib/bolt/project_migrate.rb +138 -0
- data/lib/bolt/puppetdb/client.rb +1 -1
- data/lib/bolt/puppetdb/config.rb +1 -1
- data/lib/bolt/puppetfile.rb +160 -0
- data/lib/bolt/puppetfile/installer.rb +43 -0
- data/lib/bolt/puppetfile/module.rb +66 -0
- data/lib/bolt/r10k_log_proxy.rb +1 -1
- data/lib/bolt/rerun.rb +2 -2
- data/lib/bolt/result.rb +23 -0
- data/lib/bolt/shell.rb +1 -1
- data/lib/bolt/shell/bash.rb +7 -7
- data/lib/bolt/task.rb +1 -1
- data/lib/bolt/transport/base.rb +1 -1
- data/lib/bolt/transport/docker/connection.rb +10 -10
- data/lib/bolt/transport/local/connection.rb +3 -3
- data/lib/bolt/transport/orch.rb +3 -3
- data/lib/bolt/transport/ssh.rb +1 -1
- data/lib/bolt/transport/ssh/connection.rb +6 -6
- data/lib/bolt/transport/ssh/exec_connection.rb +5 -5
- data/lib/bolt/transport/winrm.rb +1 -1
- data/lib/bolt/transport/winrm/connection.rb +9 -9
- data/lib/bolt/util.rb +2 -2
- data/lib/bolt/util/puppet_log_level.rb +4 -3
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/base_config.rb +2 -2
- data/lib/bolt_server/config.rb +1 -1
- data/lib/bolt_server/file_cache.rb +1 -1
- data/lib/bolt_server/transport_app.rb +189 -14
- data/lib/bolt_spec/plans.rb +1 -1
- data/lib/bolt_spec/run.rb +3 -0
- metadata +12 -12
data/lib/bolt/config.rb
CHANGED
@@ -19,7 +19,7 @@ module Bolt
|
|
19
19
|
class Config
|
20
20
|
include Bolt::Config::Options
|
21
21
|
|
22
|
-
attr_reader :config_files, :
|
22
|
+
attr_reader :config_files, :logs, :data, :transports, :project, :modified_concurrency, :deprecations
|
23
23
|
|
24
24
|
BOLT_CONFIG_NAME = 'bolt.yaml'
|
25
25
|
BOLT_DEFAULTS_NAME = 'bolt-defaults.yaml'
|
@@ -32,16 +32,19 @@ module Bolt
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def self.from_project(project, overrides = {})
|
35
|
+
logs = []
|
35
36
|
conf = if project.project_file == project.config_file
|
36
37
|
project.data
|
37
38
|
else
|
38
|
-
Bolt::Util.read_optional_yaml_hash(project.config_file, 'config')
|
39
|
+
c = Bolt::Util.read_optional_yaml_hash(project.config_file, 'config')
|
40
|
+
logs << { debug: "Loaded configuration from #{project.config_file}" } if File.exist?(project.config_file)
|
41
|
+
c
|
39
42
|
end
|
40
43
|
|
41
44
|
data = load_defaults(project).push(
|
42
45
|
filepath: project.config_file,
|
43
46
|
data: conf,
|
44
|
-
|
47
|
+
logs: logs,
|
45
48
|
deprecations: []
|
46
49
|
)
|
47
50
|
|
@@ -50,17 +53,20 @@ module Bolt
|
|
50
53
|
|
51
54
|
def self.from_file(configfile, overrides = {})
|
52
55
|
project = Bolt::Project.create_project(Pathname.new(configfile).expand_path.dirname)
|
56
|
+
logs = []
|
53
57
|
|
54
58
|
conf = if project.project_file == project.config_file
|
55
59
|
project.data
|
56
60
|
else
|
57
|
-
Bolt::Util.read_yaml_hash(configfile, 'config')
|
61
|
+
c = Bolt::Util.read_yaml_hash(configfile, 'config')
|
62
|
+
logs << { debug: "Loaded configuration from #{configfile}" }
|
63
|
+
c
|
58
64
|
end
|
59
65
|
|
60
66
|
data = load_defaults(project).push(
|
61
|
-
filepath:
|
67
|
+
filepath: configfile,
|
62
68
|
data: conf,
|
63
|
-
|
69
|
+
logs: logs,
|
64
70
|
deprecations: []
|
65
71
|
)
|
66
72
|
|
@@ -90,13 +96,13 @@ module Bolt
|
|
90
96
|
def self.load_bolt_defaults_yaml(dir)
|
91
97
|
filepath = dir + BOLT_DEFAULTS_NAME
|
92
98
|
data = Bolt::Util.read_yaml_hash(filepath, 'config')
|
93
|
-
|
99
|
+
logs = [{ debug: "Loaded configuration from #{filepath}" }]
|
94
100
|
|
95
101
|
# Warn if 'bolt.yaml' detected in same directory.
|
96
102
|
if File.exist?(bolt_yaml = dir + BOLT_CONFIG_NAME)
|
97
|
-
|
98
|
-
|
99
|
-
|
103
|
+
logs.push(
|
104
|
+
warn: "Detected multiple configuration files: ['#{bolt_yaml}', '#{filepath}']. '#{bolt_yaml}' "\
|
105
|
+
"will be ignored."
|
100
106
|
)
|
101
107
|
end
|
102
108
|
|
@@ -105,9 +111,9 @@ module Bolt
|
|
105
111
|
|
106
112
|
if project_config.any?
|
107
113
|
data.reject! { |key, _| project_config.include?(key) }
|
108
|
-
|
109
|
-
|
110
|
-
|
114
|
+
logs.push(
|
115
|
+
warn: "Unsupported project configuration detected in '#{filepath}': #{project_config.keys}. "\
|
116
|
+
"Project configuration should be set in 'bolt-project.yaml'."
|
111
117
|
)
|
112
118
|
end
|
113
119
|
|
@@ -116,10 +122,10 @@ module Bolt
|
|
116
122
|
|
117
123
|
if transport_config.any?
|
118
124
|
data.reject! { |key, _| transport_config.include?(key) }
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
125
|
+
logs.push(
|
126
|
+
warn: "Unsupported inventory configuration detected in '#{filepath}': #{transport_config.keys}. "\
|
127
|
+
"Transport configuration should be set under the 'inventory-config' option or "\
|
128
|
+
"in 'inventory.yaml'."
|
123
129
|
)
|
124
130
|
end
|
125
131
|
|
@@ -142,7 +148,7 @@ module Bolt
|
|
142
148
|
data = data.merge(data.delete('inventory-config'))
|
143
149
|
end
|
144
150
|
|
145
|
-
{ filepath: filepath, data: data,
|
151
|
+
{ filepath: filepath, data: data, logs: logs, deprecations: [] }
|
146
152
|
end
|
147
153
|
|
148
154
|
# Loads a 'bolt.yaml' file, the legacy configuration file. There's no special munging needed
|
@@ -150,11 +156,12 @@ module Bolt
|
|
150
156
|
def self.load_bolt_yaml(dir)
|
151
157
|
filepath = dir + BOLT_CONFIG_NAME
|
152
158
|
data = Bolt::Util.read_yaml_hash(filepath, 'config')
|
159
|
+
logs = [{ debug: "Loaded configuration from #{filepath}" }]
|
153
160
|
deprecations = [{ type: 'Using bolt.yaml for system configuration',
|
154
161
|
msg: "Configuration file #{filepath} is deprecated and will be removed in a future version "\
|
155
162
|
"of Bolt. Use '#{dir + BOLT_DEFAULTS_NAME}' instead." }]
|
156
163
|
|
157
|
-
{ filepath: filepath, data: data,
|
164
|
+
{ filepath: filepath, data: data, logs: logs, deprecations: deprecations }
|
158
165
|
end
|
159
166
|
|
160
167
|
def self.load_defaults(project)
|
@@ -187,13 +194,13 @@ module Bolt
|
|
187
194
|
unless config_data.is_a?(Array)
|
188
195
|
config_data = [{ filepath: project.config_file,
|
189
196
|
data: config_data,
|
190
|
-
|
197
|
+
logs: [],
|
191
198
|
deprecations: [] }]
|
192
199
|
end
|
193
200
|
|
194
|
-
@logger =
|
201
|
+
@logger = Bolt::Logger.logger(self)
|
195
202
|
@project = project
|
196
|
-
@
|
203
|
+
@logs = @project.logs.dup
|
197
204
|
@deprecations = @project.deprecations.dup
|
198
205
|
@transports = {}
|
199
206
|
@config_files = []
|
@@ -213,8 +220,15 @@ module Bolt
|
|
213
220
|
'transport' => 'ssh'
|
214
221
|
}
|
215
222
|
|
223
|
+
if project.path.directory?
|
224
|
+
default_data['log']['bolt-debug.log'] = {
|
225
|
+
'level' => 'debug',
|
226
|
+
'append' => false
|
227
|
+
}
|
228
|
+
end
|
229
|
+
|
216
230
|
loaded_data = config_data.each_with_object([]) do |data, acc|
|
217
|
-
@
|
231
|
+
@logs.concat(data[:logs]) if data[:logs].any?
|
218
232
|
@deprecations.concat(data[:deprecations]) if data[:deprecations].any?
|
219
233
|
|
220
234
|
if data[:data].any?
|
@@ -330,10 +344,26 @@ module Bolt
|
|
330
344
|
end
|
331
345
|
|
332
346
|
private def update_logs(logs)
|
347
|
+
begin
|
348
|
+
if logs['bolt-debug.log'] && logs['bolt-debug.log'] != 'disable'
|
349
|
+
FileUtils.touch(File.expand_path('bolt-debug.log', @project.path))
|
350
|
+
end
|
351
|
+
rescue StandardError
|
352
|
+
logs.delete('bolt-debug.log')
|
353
|
+
end
|
354
|
+
|
333
355
|
logs.each_with_object({}) do |(key, val), acc|
|
334
|
-
|
356
|
+
# Remove any disabled logs
|
357
|
+
next if val == 'disable'
|
335
358
|
|
336
359
|
name = normalize_log(key)
|
360
|
+
|
361
|
+
# But otherwise it has to be a Hash
|
362
|
+
unless val.is_a?(Hash)
|
363
|
+
raise Bolt::ValidationError,
|
364
|
+
"config of log #{name} must be a Hash, received #{val.class} #{val.inspect}"
|
365
|
+
end
|
366
|
+
|
337
367
|
acc[name] = val.slice('append', 'level')
|
338
368
|
.transform_keys(&:to_sym)
|
339
369
|
|
@@ -358,7 +388,7 @@ module Bolt
|
|
358
388
|
def validate
|
359
389
|
if @data['future']
|
360
390
|
msg = "Configuration option 'future' no longer exposes future behavior."
|
361
|
-
@
|
391
|
+
@logs << { warn: msg }
|
362
392
|
end
|
363
393
|
|
364
394
|
keys = OPTIONS.keys - %w[plugins plugin_hooks puppetdb]
|
data/lib/bolt/config/options.rb
CHANGED
@@ -176,7 +176,9 @@ module Bolt
|
|
176
176
|
description: "A map of configuration for the logfile output. Under `log`, you can configure log options "\
|
177
177
|
"for `console` and add configuration for individual log files, such as "\
|
178
178
|
"`~/.puppetlabs/bolt/debug.log`. Individual log files must be valid filepaths. If the log "\
|
179
|
-
"file does not exist, then Bolt will create it before logging information."
|
179
|
+
"file does not exist, then Bolt will create it before logging information. Set the value to "\
|
180
|
+
"`disable` to remove a log file defined at an earlier level of the config hierarchy. By "\
|
181
|
+
"default, Bolt logs to a bolt-debug.log file in the Bolt project directory.",
|
180
182
|
type: Hash,
|
181
183
|
properties: {
|
182
184
|
"console" => {
|
@@ -186,15 +188,16 @@ module Bolt
|
|
186
188
|
"level" => {
|
187
189
|
description: "The type of information to log.",
|
188
190
|
type: String,
|
189
|
-
enum: %w[debug error info
|
190
|
-
_default: "warn
|
191
|
+
enum: %w[trace debug error info warn fatal any],
|
192
|
+
_default: "warn"
|
191
193
|
}
|
192
194
|
}
|
193
195
|
}
|
194
196
|
},
|
195
197
|
additionalProperties: {
|
196
198
|
description: "Configuration for the logfile output.",
|
197
|
-
type: Hash,
|
199
|
+
type: [String, Hash],
|
200
|
+
enum: ['disable'],
|
198
201
|
properties: {
|
199
202
|
"append" => {
|
200
203
|
description: "Whether to append output to an existing log file.",
|
@@ -204,8 +207,8 @@ module Bolt
|
|
204
207
|
"level" => {
|
205
208
|
description: "The type of information to log.",
|
206
209
|
type: String,
|
207
|
-
enum: %w[debug error info
|
208
|
-
_default: "warn
|
210
|
+
enum: %w[trace debug error info warn fatal any],
|
211
|
+
_default: "warn"
|
209
212
|
}
|
210
213
|
}
|
211
214
|
},
|
@@ -224,6 +227,24 @@ module Bolt
|
|
224
227
|
_example: ["~/.puppetlabs/bolt/modules", "~/.puppetlabs/bolt/site-modules"],
|
225
228
|
_default: ["project/modules", "project/site-modules", "project/site"]
|
226
229
|
},
|
230
|
+
"modules" => {
|
231
|
+
description: "A list of module dependencies for the project. Each dependency is a map of data specifying "\
|
232
|
+
"the module to install. To install the project's module dependencies, run the `bolt module "\
|
233
|
+
"install` command.",
|
234
|
+
type: Array,
|
235
|
+
items: {
|
236
|
+
type: Hash,
|
237
|
+
required: ["name"],
|
238
|
+
properties: {
|
239
|
+
"name" => {
|
240
|
+
description: "The name of the module.",
|
241
|
+
type: String
|
242
|
+
}
|
243
|
+
}
|
244
|
+
},
|
245
|
+
_plugin: false,
|
246
|
+
_example: [{ "name" => "puppetlabs-mysql" }, { "name" => "puppetlabs-apache" }]
|
247
|
+
},
|
227
248
|
"name" => {
|
228
249
|
description: "The name of the Bolt project. When this option is configured, the project is considered a "\
|
229
250
|
"[Bolt project](experimental_features.md#bolt-projects), allowing Bolt to load content from "\
|
@@ -473,6 +494,7 @@ module Bolt
|
|
473
494
|
inventoryfile
|
474
495
|
log
|
475
496
|
modulepath
|
497
|
+
modules
|
476
498
|
name
|
477
499
|
plans
|
478
500
|
plugin_hooks
|
data/lib/bolt/executor.rb
CHANGED
@@ -40,7 +40,7 @@ module Bolt
|
|
40
40
|
require 'concurrent'
|
41
41
|
|
42
42
|
@analytics = analytics
|
43
|
-
@logger =
|
43
|
+
@logger = Bolt::Logger.logger(self)
|
44
44
|
|
45
45
|
@transports = Bolt::TRANSPORTS.each_with_object({}) do |(key, val), coll|
|
46
46
|
coll[key.to_s] = if key == :remote
|
@@ -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)
|
data/lib/bolt/inventory.rb
CHANGED
@@ -46,10 +46,13 @@ module Bolt
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def self.from_config(config, plugins)
|
49
|
+
logger = Logging.logger[self]
|
50
|
+
|
49
51
|
if ENV.include?(ENVIRONMENT_VAR)
|
50
52
|
begin
|
51
53
|
data = YAML.safe_load(ENV[ENVIRONMENT_VAR])
|
52
54
|
raise Bolt::ParseError, "Could not parse inventory from $#{ENVIRONMENT_VAR}" unless data.is_a?(Hash)
|
55
|
+
logger.debug("Loaded inventory from environment variable #{ENVIRONMENT_VAR}")
|
53
56
|
rescue Psych::Exception
|
54
57
|
raise Bolt::ParseError, "Could not parse inventory from $#{ENVIRONMENT_VAR}"
|
55
58
|
end
|
@@ -57,8 +60,12 @@ module Bolt
|
|
57
60
|
data = if config.inventoryfile
|
58
61
|
Bolt::Util.read_yaml_hash(config.inventoryfile, 'inventory')
|
59
62
|
else
|
60
|
-
Bolt::Util.read_optional_yaml_hash(config.default_inventoryfile, 'inventory')
|
63
|
+
i = Bolt::Util.read_optional_yaml_hash(config.default_inventoryfile, 'inventory')
|
64
|
+
logger.debug("Loaded inventory from #{config.default_inventoryfile}") if i
|
65
|
+
i
|
61
66
|
end
|
67
|
+
# This avoids rubocop complaining about identical conditionals
|
68
|
+
logger.debug("Loaded inventory from #{config.inventoryfile}") if config.inventoryfile
|
62
69
|
end
|
63
70
|
|
64
71
|
# Resolve plugin references from transport config
|
data/lib/bolt/inventory/group.rb
CHANGED
@@ -19,7 +19,7 @@ module Bolt
|
|
19
19
|
CONFIG_KEYS = Bolt::Config::INVENTORY_OPTIONS.keys
|
20
20
|
|
21
21
|
def initialize(input, plugins)
|
22
|
-
@logger =
|
22
|
+
@logger = Bolt::Logger.logger(self)
|
23
23
|
@plugins = plugins
|
24
24
|
|
25
25
|
input = @plugins.resolve_top_level_references(input) if @plugins.reference?(input)
|
@@ -119,7 +119,7 @@ module Bolt
|
|
119
119
|
end
|
120
120
|
|
121
121
|
if contains_target?(t_name)
|
122
|
-
@logger.
|
122
|
+
@logger.debug("Ignoring duplicate target in #{@name}: #{target}")
|
123
123
|
return
|
124
124
|
end
|
125
125
|
|
@@ -200,14 +200,14 @@ module Bolt
|
|
200
200
|
# If this is an alias for an existing target, then add it to this group
|
201
201
|
elsif (canonical_name = aliases[string_target])
|
202
202
|
if contains_target?(canonical_name)
|
203
|
-
@logger.
|
203
|
+
@logger.debug("Ignoring duplicate target in #{@name}: #{canonical_name}")
|
204
204
|
else
|
205
205
|
@unresolved_targets[canonical_name] = { 'name' => canonical_name }
|
206
206
|
end
|
207
207
|
# If it's not the name or alias of an existing target, then make a
|
208
208
|
# new target using the string as the URI
|
209
209
|
elsif contains_target?(string_target)
|
210
|
-
@logger.
|
210
|
+
@logger.debug("Ignoring duplicate target in #{@name}: #{string_target}")
|
211
211
|
else
|
212
212
|
@unresolved_targets[string_target] = { 'uri' => string_target }
|
213
213
|
end
|
@@ -16,7 +16,7 @@ module Bolt
|
|
16
16
|
|
17
17
|
# TODO: Pass transport config instead of config object
|
18
18
|
def initialize(data, transport, transports, plugins)
|
19
|
-
@logger =
|
19
|
+
@logger = Bolt::Logger.logger(self)
|
20
20
|
@data = data || {}
|
21
21
|
@transport = transport
|
22
22
|
@config = transports
|
@@ -13,7 +13,7 @@ module Bolt
|
|
13
13
|
raise Bolt::Inventory::ValidationError.new("Target must have either a name or uri", nil)
|
14
14
|
end
|
15
15
|
|
16
|
-
@logger =
|
16
|
+
@logger = Bolt::Logger.logger(inventory)
|
17
17
|
|
18
18
|
# If the target isn't mentioned by any groups, it won't have a uri or
|
19
19
|
# name and we will use the target_name as both
|
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]
|
@@ -29,7 +28,7 @@ module Bolt
|
|
29
28
|
end
|
30
29
|
|
31
30
|
def self.configure(destinations, color)
|
32
|
-
root_logger =
|
31
|
+
root_logger = Bolt::Logger.logger(:root)
|
33
32
|
|
34
33
|
root_logger.add_appenders Logging.appenders.stderr(
|
35
34
|
'console',
|
@@ -67,6 +66,13 @@ module Bolt
|
|
67
66
|
end
|
68
67
|
end
|
69
68
|
|
69
|
+
# A helper to ensure the Logging library is always initialized with our
|
70
|
+
# custom log levels before retrieving a Logger instance.
|
71
|
+
def self.logger(name)
|
72
|
+
initialize_logging
|
73
|
+
Logging.logger[name]
|
74
|
+
end
|
75
|
+
|
70
76
|
def self.analytics=(analytics)
|
71
77
|
@analytics = analytics
|
72
78
|
end
|
@@ -81,7 +87,7 @@ module Bolt
|
|
81
87
|
|
82
88
|
def self.default_layout
|
83
89
|
Logging.layouts.pattern(
|
84
|
-
pattern: '%d %-6l %c
|
90
|
+
pattern: '%d %-6l [%T] [%c] %m\n',
|
85
91
|
date_pattern: '%Y-%m-%dT%H:%M:%S.%6N'
|
86
92
|
)
|
87
93
|
end
|
@@ -91,7 +97,7 @@ module Bolt
|
|
91
97
|
end
|
92
98
|
|
93
99
|
def self.default_file_level
|
94
|
-
:
|
100
|
+
:warn
|
95
101
|
end
|
96
102
|
|
97
103
|
# Explicitly check the log level names instead of the log level number, as levels
|
@@ -111,7 +117,7 @@ module Bolt
|
|
111
117
|
def self.warn_once(type, msg)
|
112
118
|
@mutex.synchronize {
|
113
119
|
@warnings ||= []
|
114
|
-
@logger ||=
|
120
|
+
@logger ||= Bolt::Logger.logger(self)
|
115
121
|
unless @warnings.include?(type)
|
116
122
|
@logger.warn(msg)
|
117
123
|
@warnings << type
|
data/lib/bolt/outputter/human.rb
CHANGED
@@ -286,6 +286,16 @@ module Bolt
|
|
286
286
|
"details and parameters for a specific plan.")
|
287
287
|
end
|
288
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
|
+
|
289
299
|
def print_module_list(module_list)
|
290
300
|
module_list.each do |path, modules|
|
291
301
|
if (mod = modules.find { |m| m[:internal_module_group] })
|