bolt 1.19.0 → 1.20.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/datatypes/applyresult.rb +2 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +2 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +3 -10
- data/bolt-modules/boltlib/lib/puppet/functions/add_to_group.rb +3 -10
- data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +3 -9
- data/bolt-modules/boltlib/lib/puppet/functions/facts.rb +2 -8
- data/bolt-modules/boltlib/lib/puppet/functions/fail_plan.rb +2 -2
- data/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb +3 -8
- data/bolt-modules/boltlib/lib/puppet/functions/get_targets.rb +2 -8
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_fact.rb +2 -7
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +2 -7
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +2 -7
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +1 -6
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +2 -7
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +7 -33
- data/bolt-modules/boltlib/lib/puppet/functions/set_feature.rb +3 -10
- data/bolt-modules/boltlib/lib/puppet/functions/set_var.rb +3 -10
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +2 -7
- data/bolt-modules/boltlib/lib/puppet/functions/vars.rb +2 -8
- data/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb +2 -7
- data/bolt-modules/boltlib/lib/puppet/functions/without_default_logging.rb +1 -1
- data/lib/bolt/applicator.rb +7 -3
- data/lib/bolt/apply_result.rb +8 -21
- data/lib/bolt/bolt_option_parser.rb +2 -2
- data/lib/bolt/catalog.rb +0 -1
- data/lib/bolt/cli.rb +51 -29
- data/lib/bolt/config.rb +0 -2
- data/lib/bolt/executor.rb +38 -50
- data/lib/bolt/inventory/group.rb +5 -0
- data/lib/bolt/inventory/group2.rb +5 -0
- data/lib/bolt/logger.rb +7 -3
- data/lib/bolt/outputter.rb +6 -4
- data/lib/bolt/outputter/human.rb +90 -6
- data/lib/bolt/outputter/json.rb +4 -4
- data/lib/bolt/outputter/logger.rb +53 -0
- data/lib/bolt/pal.rb +3 -3
- data/lib/bolt/pal/yaml_plan/step.rb +1 -1
- data/lib/bolt/plugin.rb +2 -0
- data/lib/bolt/plugin/terraform.rb +84 -0
- data/lib/bolt/result.rb +12 -8
- data/lib/bolt/result_set.rb +4 -0
- data/lib/bolt/transport/orch.rb +4 -4
- data/lib/bolt/version.rb +1 -1
- metadata +4 -3
- data/lib/bolt/notifier.rb +0 -23
data/lib/bolt/apply_result.rb
CHANGED
@@ -65,7 +65,7 @@ module Bolt
|
|
65
65
|
def initialize(target, error: nil, report: nil)
|
66
66
|
@target = target
|
67
67
|
@value = {}
|
68
|
-
@
|
68
|
+
@action = 'apply'
|
69
69
|
value['report'] = report if report
|
70
70
|
value['_error'] = error if error
|
71
71
|
value['_output'] = metrics_message if metrics_message
|
@@ -77,26 +77,13 @@ module Bolt
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
when 'err'
|
88
|
-
logger.error(log['message'])
|
89
|
-
when 'warn'
|
90
|
-
logger.info(log['message'])
|
91
|
-
when 'notice'
|
92
|
-
logger.notice(log['message'])
|
93
|
-
when 'info'
|
94
|
-
logger.info(log['message'])
|
95
|
-
else
|
96
|
-
logger.debug(log["message"])
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
80
|
+
def logs
|
81
|
+
value.dig('report', 'logs') || []
|
82
|
+
end
|
83
|
+
|
84
|
+
# Return only log messages associated with resources
|
85
|
+
def resource_logs
|
86
|
+
logs.reject { |log| log['source'] == 'Puppet' }
|
100
87
|
end
|
101
88
|
|
102
89
|
def metrics_message
|
@@ -281,8 +281,8 @@ Usage: bolt apply <manifest.pp> [options]
|
|
281
281
|
define('-h', '--help', 'Display help') do |_|
|
282
282
|
@options[:help] = true
|
283
283
|
end
|
284
|
-
define('-v', '--verbose', 'Display verbose logging') do |
|
285
|
-
@options[:verbose] =
|
284
|
+
define('-v', '--[no-]verbose', 'Display verbose logging') do |value|
|
285
|
+
@options[:verbose] = value
|
286
286
|
end
|
287
287
|
define('--debug', 'Display debug logging') do |_|
|
288
288
|
@options[:debug] = true
|
data/lib/bolt/catalog.rb
CHANGED
@@ -65,7 +65,6 @@ module Bolt
|
|
65
65
|
target = request['target']
|
66
66
|
pdb_client = Bolt::PuppetDB::Client.new(Bolt::PuppetDB::Config.new(request['pdb_config']))
|
67
67
|
options = request['puppet_config'] || {}
|
68
|
-
|
69
68
|
with_puppet_settings(request['hiera_config']) do
|
70
69
|
Puppet[:rich_data] = true
|
71
70
|
Puppet[:node_name_value] = target['name']
|
data/lib/bolt/cli.rb
CHANGED
@@ -126,6 +126,11 @@ module Bolt
|
|
126
126
|
update_targets(options)
|
127
127
|
end
|
128
128
|
|
129
|
+
unless options.key?(:verbose)
|
130
|
+
# Default to verbose for everything except plans
|
131
|
+
options[:verbose] = options[:subcommand] != 'plan'
|
132
|
+
end
|
133
|
+
|
129
134
|
options
|
130
135
|
rescue Bolt::Error => e
|
131
136
|
warn e.message
|
@@ -261,11 +266,19 @@ module Bolt
|
|
261
266
|
screen += '_object'
|
262
267
|
end
|
263
268
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
+
screen_view_fields = {
|
270
|
+
output_format: config.format
|
271
|
+
}
|
272
|
+
|
273
|
+
# Only include target and inventory info for commands that take a targets
|
274
|
+
# list. This avoids loading inventory for commands that don't need it.
|
275
|
+
if options.key?(:targets)
|
276
|
+
screen_view_fields.merge!(target_nodes: options[:targets].count,
|
277
|
+
inventory_nodes: inventory.node_names.count,
|
278
|
+
inventory_groups: inventory.group_names.count)
|
279
|
+
end
|
280
|
+
|
281
|
+
@analytics.screen_view(screen, screen_view_fields)
|
269
282
|
|
270
283
|
if options[:action] == 'show'
|
271
284
|
if options[:subcommand] == 'task'
|
@@ -314,29 +327,23 @@ module Bolt
|
|
314
327
|
elapsed_time = Benchmark.realtime do
|
315
328
|
executor_opts = {}
|
316
329
|
executor_opts['_description'] = options[:description] if options.key?(:description)
|
330
|
+
executor.subscribe(outputter)
|
331
|
+
executor.subscribe(log_outputter)
|
317
332
|
results =
|
318
333
|
case options[:subcommand]
|
319
334
|
when 'command'
|
320
|
-
executor.run_command(targets, options[:object], executor_opts)
|
321
|
-
outputter.print_event(event)
|
322
|
-
end
|
335
|
+
executor.run_command(targets, options[:object], executor_opts)
|
323
336
|
when 'script'
|
324
337
|
script = options[:object]
|
325
338
|
validate_file('script', script)
|
326
|
-
executor.run_script(
|
327
|
-
targets, script, options[:leftovers], executor_opts
|
328
|
-
) do |event|
|
329
|
-
outputter.print_event(event)
|
330
|
-
end
|
339
|
+
executor.run_script(targets, script, options[:leftovers], executor_opts)
|
331
340
|
when 'task'
|
332
341
|
pal.run_task(options[:object],
|
333
342
|
targets,
|
334
343
|
options[:task_options],
|
335
344
|
executor,
|
336
345
|
inventory,
|
337
|
-
options[:description])
|
338
|
-
outputter.print_event(event)
|
339
|
-
end
|
346
|
+
options[:description])
|
340
347
|
when 'file'
|
341
348
|
src = options[:object]
|
342
349
|
dest = options[:leftovers].first
|
@@ -345,13 +352,13 @@ module Bolt
|
|
345
352
|
raise Bolt::CLIError, "A destination path must be specified"
|
346
353
|
end
|
347
354
|
validate_file('source file', src, true)
|
348
|
-
executor.upload_file(targets, src, dest, executor_opts)
|
349
|
-
outputter.print_event(event)
|
350
|
-
end
|
355
|
+
executor.upload_file(targets, src, dest, executor_opts)
|
351
356
|
end
|
352
357
|
end
|
353
358
|
|
359
|
+
executor.shutdown
|
354
360
|
rerun.update(results)
|
361
|
+
|
355
362
|
outputter.print_summary(results, elapsed_time)
|
356
363
|
code = results.ok ? 0 : 2
|
357
364
|
end
|
@@ -398,12 +405,16 @@ module Bolt
|
|
398
405
|
plan_context[:description] = options[:description] if options[:description]
|
399
406
|
|
400
407
|
executor = Bolt::Executor.new(config.concurrency, @analytics, options[:noop])
|
408
|
+
executor.subscribe(outputter) if options.fetch(:format, 'human') == 'human'
|
409
|
+
executor.subscribe(log_outputter)
|
401
410
|
executor.start_plan(plan_context)
|
402
411
|
result = pal.run_plan(plan_name, plan_arguments, executor, inventory, puppetdb_client)
|
403
412
|
|
404
413
|
# If a non-bolt exception bubbles up the plan won't get finished
|
405
414
|
executor.finish_plan(result)
|
415
|
+
executor.shutdown
|
406
416
|
rerun.update(result)
|
417
|
+
|
407
418
|
outputter.print_plan_result(result)
|
408
419
|
result.ok? ? 0 : 1
|
409
420
|
end
|
@@ -412,18 +423,25 @@ module Bolt
|
|
412
423
|
ast = pal.parse_manifest(code, filename)
|
413
424
|
|
414
425
|
executor = Bolt::Executor.new(config.concurrency, @analytics, noop)
|
415
|
-
|
416
|
-
executor.
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
426
|
+
executor.subscribe(outputter) if options.fetch(:format, 'human') == 'human'
|
427
|
+
executor.subscribe(log_outputter)
|
428
|
+
# apply logging looks like plan logging, so tell the outputter we're in a
|
429
|
+
# plan even though we're not
|
430
|
+
executor.publish_event(type: :plan_start, plan: nil)
|
431
|
+
|
432
|
+
results = nil
|
433
|
+
elapsed_time = Benchmark.realtime do
|
434
|
+
pal.in_plan_compiler(executor, inventory, puppetdb_client) do |compiler|
|
435
|
+
compiler.call_function('apply_prep', targets)
|
436
|
+
end
|
421
437
|
|
422
|
-
|
423
|
-
|
438
|
+
results = pal.with_bolt_executor(executor, inventory, puppetdb_client) do
|
439
|
+
Puppet.lookup(:apply_executor).apply_ast(ast, targets, '_catch_errors' => true, '_noop' => noop)
|
440
|
+
end
|
424
441
|
end
|
425
442
|
|
426
|
-
|
443
|
+
executor.shutdown
|
444
|
+
outputter.print_apply_result(results, elapsed_time)
|
427
445
|
rerun.update(results)
|
428
446
|
|
429
447
|
results.ok ? 0 : 1
|
@@ -499,7 +517,11 @@ module Bolt
|
|
499
517
|
end
|
500
518
|
|
501
519
|
def outputter
|
502
|
-
@outputter ||= Bolt::Outputter.for_format(config.format, config.color, config.trace)
|
520
|
+
@outputter ||= Bolt::Outputter.for_format(config.format, config.color, options[:verbose], config.trace)
|
521
|
+
end
|
522
|
+
|
523
|
+
def log_outputter
|
524
|
+
@log_outputter ||= Bolt::Outputter::Logger.new(options[:verbose], config.trace)
|
503
525
|
end
|
504
526
|
|
505
527
|
def bundled_content
|
data/lib/bolt/config.rb
CHANGED
data/lib/bolt/executor.rb
CHANGED
@@ -8,7 +8,6 @@ require 'set'
|
|
8
8
|
require 'bolt/analytics'
|
9
9
|
require 'bolt/result'
|
10
10
|
require 'bolt/config'
|
11
|
-
require 'bolt/notifier'
|
12
11
|
require 'bolt/result_set'
|
13
12
|
require 'bolt/puppetdb'
|
14
13
|
|
@@ -41,6 +40,8 @@ module Bolt
|
|
41
40
|
end
|
42
41
|
end
|
43
42
|
@reported_transports = Set.new
|
43
|
+
@subscribers = Set.new
|
44
|
+
@publisher = Concurrent::SingleThreadExecutor.new
|
44
45
|
|
45
46
|
@noop = noop
|
46
47
|
@run_as = nil
|
@@ -50,7 +51,6 @@ module Bolt
|
|
50
51
|
Concurrent.global_immediate_executor
|
51
52
|
end
|
52
53
|
@logger.debug { "Started with #{concurrency} max thread(s)" }
|
53
|
-
@notifier = Bolt::Notifier.new
|
54
54
|
end
|
55
55
|
|
56
56
|
def transport(transport)
|
@@ -61,6 +61,24 @@ module Bolt
|
|
61
61
|
impl.value
|
62
62
|
end
|
63
63
|
|
64
|
+
def subscribe(subscriber)
|
65
|
+
@subscribers << subscriber
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
def publish_event(event)
|
70
|
+
@subscribers.each do |subscriber|
|
71
|
+
@publisher.post(subscriber) do |sub|
|
72
|
+
sub.handle_event(event)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def shutdown
|
78
|
+
@publisher.shutdown
|
79
|
+
@publisher.wait_for_termination
|
80
|
+
end
|
81
|
+
|
64
82
|
# Starts executing the given block on a list of nodes in parallel, one thread per "batch".
|
65
83
|
#
|
66
84
|
# This is the main driver of execution on a list of targets. It first
|
@@ -129,31 +147,19 @@ module Bolt
|
|
129
147
|
end
|
130
148
|
|
131
149
|
def log_action(description, targets)
|
132
|
-
|
133
|
-
log_method = @plan_logging ? :notice : :info
|
134
|
-
target_str = if targets.length > 5
|
135
|
-
"#{targets.count} targets"
|
136
|
-
else
|
137
|
-
targets.map(&:uri).join(', ')
|
138
|
-
end
|
139
|
-
|
140
|
-
@logger.send(log_method, "Starting: #{description} on #{target_str}")
|
150
|
+
publish_event(type: :step_start, description: description, targets: targets)
|
141
151
|
|
142
152
|
start_time = Time.now
|
143
153
|
results = yield
|
144
154
|
duration = Time.now - start_time
|
145
155
|
|
146
|
-
|
147
|
-
plural = failures == 1 ? '' : 's'
|
148
|
-
|
149
|
-
@logger.send(log_method, "Finished: #{description} with #{failures} failure#{plural} in #{duration.round(2)} sec")
|
156
|
+
publish_event(type: :step_finish, description: description, result: results, duration: duration)
|
150
157
|
|
151
158
|
results
|
152
159
|
end
|
153
160
|
|
154
161
|
def log_plan(plan_name)
|
155
|
-
|
156
|
-
@logger.send(log_method, "Starting: plan #{plan_name}")
|
162
|
+
publish_event(type: :plan_start, plan: plan_name)
|
157
163
|
start_time = Time.now
|
158
164
|
|
159
165
|
results = nil
|
@@ -161,7 +167,7 @@ module Bolt
|
|
161
167
|
results = yield
|
162
168
|
ensure
|
163
169
|
duration = Time.now - start_time
|
164
|
-
|
170
|
+
publish_event(type: :plan_finish, plan: plan_name, duration: duration)
|
165
171
|
end
|
166
172
|
|
167
173
|
results
|
@@ -220,72 +226,56 @@ module Bolt
|
|
220
226
|
result
|
221
227
|
end
|
222
228
|
|
223
|
-
def run_command(targets, command, options = {}
|
229
|
+
def run_command(targets, command, options = {})
|
224
230
|
description = options.fetch('_description', "command '#{command}'")
|
225
231
|
log_action(description, targets) do
|
226
|
-
notify = proc { |event| @notifier.notify(callback, event) if callback }
|
227
232
|
options = { '_run_as' => run_as }.merge(options) if run_as
|
228
233
|
|
229
|
-
|
234
|
+
batch_execute(targets) do |transport, batch|
|
230
235
|
with_node_logging("Running command '#{command}'", batch) do
|
231
|
-
transport.batch_command(batch, command, options, &
|
236
|
+
transport.batch_command(batch, command, options, &method(:publish_event))
|
232
237
|
end
|
233
238
|
end
|
234
|
-
|
235
|
-
@notifier.shutdown
|
236
|
-
results
|
237
239
|
end
|
238
240
|
end
|
239
241
|
|
240
|
-
def run_script(targets, script, arguments, options = {}
|
242
|
+
def run_script(targets, script, arguments, options = {})
|
241
243
|
description = options.fetch('_description', "script #{script}")
|
242
244
|
log_action(description, targets) do
|
243
|
-
notify = proc { |event| @notifier.notify(callback, event) if callback }
|
244
245
|
options = { '_run_as' => run_as }.merge(options) if run_as
|
245
246
|
|
246
|
-
|
247
|
+
batch_execute(targets) do |transport, batch|
|
247
248
|
with_node_logging("Running script #{script} with '#{arguments}'", batch) do
|
248
|
-
transport.batch_script(batch, script, arguments, options, &
|
249
|
+
transport.batch_script(batch, script, arguments, options, &method(:publish_event))
|
249
250
|
end
|
250
251
|
end
|
251
|
-
|
252
|
-
@notifier.shutdown
|
253
|
-
results
|
254
252
|
end
|
255
253
|
end
|
256
254
|
|
257
|
-
def run_task(targets, task, arguments, options = {}
|
255
|
+
def run_task(targets, task, arguments, options = {})
|
258
256
|
description = options.fetch('_description', "task #{task.name}")
|
259
257
|
log_action(description, targets) do
|
260
|
-
notify = proc { |event| @notifier.notify(callback, event) if callback }
|
261
258
|
options = { '_run_as' => run_as }.merge(options) if run_as
|
262
259
|
arguments['_task'] = task.name
|
263
260
|
|
264
|
-
|
261
|
+
batch_execute(targets) do |transport, batch|
|
265
262
|
with_node_logging("Running task #{task.name} with '#{arguments}'", batch) do
|
266
|
-
transport.batch_task(batch, task, arguments, options, &
|
263
|
+
transport.batch_task(batch, task, arguments, options, &method(:publish_event))
|
267
264
|
end
|
268
265
|
end
|
269
|
-
|
270
|
-
@notifier.shutdown
|
271
|
-
results
|
272
266
|
end
|
273
267
|
end
|
274
268
|
|
275
|
-
def upload_file(targets, source, destination, options = {}
|
269
|
+
def upload_file(targets, source, destination, options = {})
|
276
270
|
description = options.fetch('_description', "file upload from #{source} to #{destination}")
|
277
271
|
log_action(description, targets) do
|
278
|
-
notify = proc { |event| @notifier.notify(callback, event) if callback }
|
279
272
|
options = { '_run_as' => run_as }.merge(options) if run_as
|
280
273
|
|
281
|
-
|
274
|
+
batch_execute(targets) do |transport, batch|
|
282
275
|
with_node_logging("Uploading file #{source} to #{destination}", batch) do
|
283
|
-
transport.batch_upload(batch, source, destination, options, &
|
276
|
+
transport.batch_upload(batch, source, destination, options, &method(:publish_event))
|
284
277
|
end
|
285
278
|
end
|
286
|
-
|
287
|
-
@notifier.shutdown
|
288
|
-
results
|
289
279
|
end
|
290
280
|
end
|
291
281
|
|
@@ -334,7 +324,6 @@ module Bolt
|
|
334
324
|
# we'll need to refactor.
|
335
325
|
def start_plan(plan_context)
|
336
326
|
transport('pcp').plan_context = plan_context
|
337
|
-
@plan_logging = true
|
338
327
|
end
|
339
328
|
|
340
329
|
def finish_plan(plan_result)
|
@@ -342,11 +331,10 @@ module Bolt
|
|
342
331
|
end
|
343
332
|
|
344
333
|
def without_default_logging
|
345
|
-
|
346
|
-
@plan_logging = false
|
334
|
+
publish_event(type: :disable_default_output)
|
347
335
|
yield
|
348
336
|
ensure
|
349
|
-
|
337
|
+
publish_event(type: :enable_default_output)
|
350
338
|
end
|
351
339
|
end
|
352
340
|
end
|
data/lib/bolt/inventory/group.rb
CHANGED
@@ -62,6 +62,11 @@ module Bolt
|
|
62
62
|
msg = "Found unexpected key(s) #{unexpected_keys.join(', ')} in node #{node['name']}"
|
63
63
|
@logger.warn(msg)
|
64
64
|
end
|
65
|
+
|
66
|
+
unless node['config'].nil? || node['config'].is_a?(Hash)
|
67
|
+
raise ValidationError.new("Invalid configuration for node: #{node['name']}", @name)
|
68
|
+
end
|
69
|
+
|
65
70
|
config_keys = node['config']&.keys || []
|
66
71
|
unless (unexpected_keys = config_keys - CONFIG_KEYS).empty?
|
67
72
|
msg = "Found unexpected key(s) #{unexpected_keys.join(', ')} in config for node #{node['name']}"
|
@@ -102,6 +102,11 @@ module Bolt
|
|
102
102
|
msg = "Found unexpected key(s) #{unexpected_keys.join(', ')} in target #{target['name']}"
|
103
103
|
@logger.warn(msg)
|
104
104
|
end
|
105
|
+
|
106
|
+
unless target['config'].nil? || target['config'].is_a?(Hash)
|
107
|
+
raise ValidationError.new("Invalid configuration for target: #{target['name']}", @name)
|
108
|
+
end
|
109
|
+
|
105
110
|
config_keys = target['config']&.keys || []
|
106
111
|
unless (unexpected_keys = config_keys - CONFIG_KEYS).empty?
|
107
112
|
msg = "Found unexpected key(s) #{unexpected_keys.join(', ')} in config for target #{target['name']}"
|
data/lib/bolt/logger.rb
CHANGED
@@ -33,7 +33,7 @@ module Bolt
|
|
33
33
|
root_logger.add_appenders Logging.appenders.stderr(
|
34
34
|
'console',
|
35
35
|
layout: console_layout(color),
|
36
|
-
level:
|
36
|
+
level: default_console_level
|
37
37
|
)
|
38
38
|
|
39
39
|
# We set the root logger's level so that it logs everything but we do
|
@@ -53,7 +53,7 @@ module Bolt
|
|
53
53
|
filename: name[5..-1], # strip the "file:" prefix
|
54
54
|
truncate: (params[:append] == false),
|
55
55
|
layout: default_layout,
|
56
|
-
level:
|
56
|
+
level: default_file_level
|
57
57
|
)
|
58
58
|
rescue ArgumentError => e
|
59
59
|
raise Bolt::Error.new("Failed to open log #{name}: #{e.message}", 'bolt/log-error')
|
@@ -81,7 +81,11 @@ module Bolt
|
|
81
81
|
)
|
82
82
|
end
|
83
83
|
|
84
|
-
def self.
|
84
|
+
def self.default_console_level
|
85
|
+
:warn
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.default_file_level
|
85
89
|
:notice
|
86
90
|
end
|
87
91
|
|