facter 4.2.2 → 4.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/facter.rb +10 -16
- data/lib/facter/custom_facts/core/file_loader.rb +0 -1
- data/lib/facter/custom_facts/core/legacy_facter.rb +0 -2
- data/lib/facter/custom_facts/core/resolvable.rb +1 -1
- data/lib/facter/custom_facts/util/collection.rb +6 -4
- data/lib/facter/custom_facts/util/confine.rb +9 -3
- data/lib/facter/custom_facts/util/directory_loader.rb +18 -6
- data/lib/facter/custom_facts/util/fact.rb +12 -10
- data/lib/facter/custom_facts/util/loader.rb +5 -1
- data/lib/facter/custom_facts/util/parser.rb +8 -2
- data/lib/facter/custom_facts/util/resolution.rb +5 -1
- data/lib/facter/framework/core/fact/internal/internal_fact_manager.rb +0 -2
- data/lib/facter/framework/core/fact_loaders/fact_loader.rb +0 -1
- data/lib/facter/framework/core/fact_manager.rb +11 -0
- data/lib/facter/framework/logging/logger.rb +61 -0
- data/lib/facter/framework/parsers/query_parser.rb +1 -4
- data/lib/facter/resolvers/os_release.rb +7 -4
- data/lib/facter/version.rb +1 -1
- metadata +2 -3
- data/lib/facter/custom_facts/core/logging.rb +0 -203
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 353d24b45ac4083ff9a2f7de05702a93e8701487cc6020de93ed974d527e7f53
|
4
|
+
data.tar.gz: c02329462e40922777fac34fab775ea1d68b884b7d4d8f8e99544bdb737f57e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ccd6eb8e93836cf558c7ed12c943d8c30d14bad521f2de821b014ceb30b3d1f4fc92cc3c54690ff853b5d62dd4c3521293127f87d08fe6525d5ff2f317e3637
|
7
|
+
data.tar.gz: d4a75033160dac87a2244855c7a2ff8d34fb733b527cc8ffd45279c3e2821b0860f3b1982ab1e0e4182c9c75cf45129ebe0c68738eeb605b9e435b5d460da309
|
data/lib/facter.rb
CHANGED
@@ -13,8 +13,6 @@ module Facter
|
|
13
13
|
Options.init
|
14
14
|
Log.output(STDOUT)
|
15
15
|
@already_searched = {}
|
16
|
-
@debug_once = []
|
17
|
-
@warn_once = []
|
18
16
|
|
19
17
|
class << self
|
20
18
|
# Method used by puppet-agent to retrieve facts
|
@@ -109,8 +107,7 @@ module Facter
|
|
109
107
|
# @api public
|
110
108
|
def clear
|
111
109
|
@already_searched = {}
|
112
|
-
|
113
|
-
@warn_once = []
|
110
|
+
Facter.clear_messages
|
114
111
|
LegacyFacter.clear
|
115
112
|
Options[:custom_dir] = []
|
116
113
|
LegacyFacter.collection.invalidate_custom_facts
|
@@ -119,6 +116,13 @@ module Facter
|
|
119
116
|
nil
|
120
117
|
end
|
121
118
|
|
119
|
+
# Clears the seen state of debug and warning messages.
|
120
|
+
#
|
121
|
+
# @return [nil]
|
122
|
+
def clear_messages
|
123
|
+
Facter::Log.clear_messages
|
124
|
+
end
|
125
|
+
|
122
126
|
# Retrieves the value of a core fact. External or custom facts are
|
123
127
|
# not returned with this call. Returns `nil` if no such fact exists.
|
124
128
|
#
|
@@ -153,13 +157,7 @@ module Facter
|
|
153
157
|
#
|
154
158
|
# @api public
|
155
159
|
def debugonce(message)
|
156
|
-
|
157
|
-
|
158
|
-
message_string = message.to_s
|
159
|
-
return if @debug_once.include? message_string
|
160
|
-
|
161
|
-
@debug_once << message_string
|
162
|
-
logger.debug(message_string)
|
160
|
+
logger.debugonce(message)
|
163
161
|
nil
|
164
162
|
end
|
165
163
|
|
@@ -482,11 +480,7 @@ module Facter
|
|
482
480
|
#
|
483
481
|
# @api public
|
484
482
|
def warnonce(message)
|
485
|
-
|
486
|
-
return if @warn_once.include? message_string
|
487
|
-
|
488
|
-
@warn_once << message_string
|
489
|
-
logger.warn(message_string)
|
483
|
+
logger.warnonce(message)
|
490
484
|
nil
|
491
485
|
end
|
492
486
|
|
@@ -103,7 +103,7 @@ module LegacyFacter
|
|
103
103
|
|
104
104
|
finishtime = Time.now.to_f
|
105
105
|
ms = (finishtime - starttime) * 1000
|
106
|
-
|
106
|
+
Facter::Log.show_time format('%<qn>s: %<ms>.2fms', qn: qualified_name, ms: ms)
|
107
107
|
end
|
108
108
|
|
109
109
|
def qualified_name
|
@@ -32,7 +32,7 @@ module LegacyFacter
|
|
32
32
|
|
33
33
|
fact
|
34
34
|
rescue StandardError => e
|
35
|
-
|
35
|
+
log.log_exception("Unable to add fact #{name}: #{e}")
|
36
36
|
end
|
37
37
|
|
38
38
|
# Add a resolution mechanism for a named fact. This does not distinguish
|
@@ -71,9 +71,7 @@ module LegacyFacter
|
|
71
71
|
# Try HARDER
|
72
72
|
internal_loader.load_all unless @facts[name]
|
73
73
|
|
74
|
-
if @facts.empty?
|
75
|
-
LegacyFacter.warnonce("No facts loaded from #{internal_loader.search_path.join(File::PATH_SEPARATOR)}")
|
76
|
-
end
|
74
|
+
log.warnonce("No facts loaded from #{internal_loader.search_path.join(File::PATH_SEPARATOR)}") if @facts.empty?
|
77
75
|
|
78
76
|
@facts[name]
|
79
77
|
end
|
@@ -181,6 +179,10 @@ module LegacyFacter
|
|
181
179
|
@external_facts_loaded = true
|
182
180
|
external_loader.load(self)
|
183
181
|
end
|
182
|
+
|
183
|
+
def log
|
184
|
+
@log ||= Facter::Log.new(self)
|
185
|
+
end
|
184
186
|
end
|
185
187
|
end
|
186
188
|
end
|
@@ -41,13 +41,13 @@ module LegacyFacter
|
|
41
41
|
begin
|
42
42
|
return !!@block.call
|
43
43
|
rescue StandardError => e
|
44
|
-
|
44
|
+
log.debug "Confine raised #{e.class} #{e}"
|
45
45
|
return false
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
unless (fact = Facter[@fact])
|
50
|
-
|
50
|
+
log.debug format('No fact for %<fact>s', fact: @fact)
|
51
51
|
return false
|
52
52
|
end
|
53
53
|
value = convert(fact.value)
|
@@ -58,13 +58,19 @@ module LegacyFacter
|
|
58
58
|
begin
|
59
59
|
return !!@block.call(value)
|
60
60
|
rescue StandardError => e
|
61
|
-
|
61
|
+
log.debug "Confine raised #{e.class} #{e}"
|
62
62
|
return false
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
66
|
@values.any? { |v| convert(v) === value }
|
67
67
|
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def log
|
72
|
+
@log ||= Facter::Log.new(self)
|
73
|
+
end
|
68
74
|
end
|
69
75
|
end
|
70
76
|
end
|
@@ -52,6 +52,10 @@ module LegacyFacter
|
|
52
52
|
|
53
53
|
private
|
54
54
|
|
55
|
+
def log
|
56
|
+
@log ||= Facter::Log.new(self)
|
57
|
+
end
|
58
|
+
|
55
59
|
def load_directory_entries(_collection)
|
56
60
|
cm = Facter::CacheManager.new
|
57
61
|
facts = []
|
@@ -87,18 +91,26 @@ module LegacyFacter
|
|
87
91
|
data = resolve_fact(fact, parser)
|
88
92
|
|
89
93
|
if data == false
|
90
|
-
|
94
|
+
log.warn "Could not interpret fact file #{fact.file}"
|
91
95
|
elsif (data == {}) || data.nil?
|
92
|
-
|
96
|
+
log.debug("Fact file #{fact.file} was parsed but no key=>value data was returned")
|
93
97
|
else
|
94
|
-
data
|
95
|
-
collection.add(p, value: v, fact_type: :external,
|
96
|
-
file: fact.file) { has_weight(weight) }
|
97
|
-
end
|
98
|
+
add_data(data, collection, fact, weight)
|
98
99
|
end
|
99
100
|
end
|
100
101
|
end
|
101
102
|
|
103
|
+
def add_data(data, collection, fact, weight)
|
104
|
+
data.each do |key, value|
|
105
|
+
collection.add(
|
106
|
+
key,
|
107
|
+
value: value,
|
108
|
+
fact_type: :external,
|
109
|
+
file: fact.file
|
110
|
+
) { has_weight(weight) }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
102
114
|
def resolve_fact(fact, parser)
|
103
115
|
data = nil
|
104
116
|
fact_name = File.basename(fact.file)
|
@@ -47,8 +47,6 @@ module Facter
|
|
47
47
|
@used_resolution_weight = 0
|
48
48
|
|
49
49
|
@value = nil
|
50
|
-
|
51
|
-
@log = Facter::Log.new(self)
|
52
50
|
end
|
53
51
|
|
54
52
|
# Adds a new {Facter::Util::Resolution resolution}. This requires a
|
@@ -87,8 +85,8 @@ module Facter
|
|
87
85
|
|
88
86
|
resolve
|
89
87
|
rescue StandardError => e
|
90
|
-
|
91
|
-
|
88
|
+
log.log_exception("Unable to add resolve #{resolution_name.inspect} for fact #{@name}: #{e.message}")
|
89
|
+
nil
|
92
90
|
end
|
93
91
|
|
94
92
|
# Retrieve an existing resolution by name
|
@@ -122,7 +120,7 @@ module Facter
|
|
122
120
|
return @value if @value
|
123
121
|
|
124
122
|
if @resolves.empty?
|
125
|
-
|
123
|
+
log.debug format('No resolves for %<name>s', name: @name)
|
126
124
|
return nil
|
127
125
|
end
|
128
126
|
|
@@ -147,12 +145,16 @@ module Facter
|
|
147
145
|
def extract_ldapname_option!(options)
|
148
146
|
return unless options[:ldapname]
|
149
147
|
|
150
|
-
|
148
|
+
log.warnonce('ldapname is deprecated and will be removed in a future version')
|
151
149
|
self.ldapname = options.delete(:ldapname)
|
152
150
|
end
|
153
151
|
|
154
152
|
private
|
155
153
|
|
154
|
+
def log
|
155
|
+
@log ||= Facter::Log.new(self)
|
156
|
+
end
|
157
|
+
|
156
158
|
def resolve_value
|
157
159
|
return Facter.core_value(name) if @value.nil?
|
158
160
|
|
@@ -222,18 +224,18 @@ module Facter
|
|
222
224
|
|
223
225
|
def log_fact_path(resolve)
|
224
226
|
fact = resolve.fact
|
225
|
-
|
227
|
+
log.debug("#{resolve.fact_type} fact #{fact.name} got resolved from: #{fact.location}")
|
226
228
|
end
|
227
229
|
|
228
230
|
def announce_when_no_suitable_resolution(resolutions)
|
229
231
|
return unless resolutions.empty?
|
230
232
|
|
231
|
-
|
232
|
-
|
233
|
+
log.debug format('Found no suitable resolves of %<resolver_length> for %<name>s',
|
234
|
+
resolver_length: @resolves.length, name: @name)
|
233
235
|
end
|
234
236
|
|
235
237
|
def announce_when_no_value_found(value)
|
236
|
-
|
238
|
+
log.debug(format('value for %<name>s is still nil', name: @name)) if value.nil?
|
237
239
|
end
|
238
240
|
|
239
241
|
def create_or_return_resolution(resolution_name, resolution_type)
|
@@ -78,7 +78,7 @@ module LegacyFacter
|
|
78
78
|
if valid_search_path?(path)
|
79
79
|
search_paths << path
|
80
80
|
else
|
81
|
-
|
81
|
+
log.debug "Excluding #{path} from search path. Fact file paths must be an absolute directory"
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
@@ -89,6 +89,10 @@ module LegacyFacter
|
|
89
89
|
|
90
90
|
private
|
91
91
|
|
92
|
+
def log
|
93
|
+
@log ||= Facter::Log.new(self)
|
94
|
+
end
|
95
|
+
|
92
96
|
# Validate that the given path is valid, ie it is an absolute path.
|
93
97
|
#
|
94
98
|
# @api private
|
@@ -137,11 +137,17 @@ module LegacyFacter
|
|
137
137
|
if LegacyFacter.json?
|
138
138
|
JSON.parse(content)
|
139
139
|
else
|
140
|
-
|
141
|
-
|
140
|
+
log.warnonce "Cannot parse JSON data file #{filename} without the json library."
|
141
|
+
log.warnonce 'Suggested next step is `gem install json` to install the json library.'
|
142
142
|
nil
|
143
143
|
end
|
144
144
|
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
def log
|
149
|
+
@log ||= Facter::Log.new(self)
|
150
|
+
end
|
145
151
|
end
|
146
152
|
|
147
153
|
register(JsonParser) do |filename|
|
@@ -91,7 +91,7 @@ module Facter
|
|
91
91
|
msg = "Already evaluated #{@name}"
|
92
92
|
msg << " at #{@last_evaluated}" if msg.is_a? String
|
93
93
|
msg << ', reevaluating anyways'
|
94
|
-
|
94
|
+
log.warn msg
|
95
95
|
end
|
96
96
|
|
97
97
|
instance_eval(&block)
|
@@ -171,6 +171,10 @@ module Facter
|
|
171
171
|
|
172
172
|
private
|
173
173
|
|
174
|
+
def log
|
175
|
+
@log ||= Facter::Log.new(self)
|
176
|
+
end
|
177
|
+
|
174
178
|
# If the weights are equal, we consider external facts greater tan custom facts
|
175
179
|
def compare_equal_weights(other)
|
176
180
|
# Other is considered greater because self is custom fact and other is external
|
@@ -11,10 +11,8 @@ module Facter
|
|
11
11
|
def resolve_facts(searched_facts)
|
12
12
|
internal_searched_facts = filter_internal_facts(searched_facts)
|
13
13
|
resolved_facts = if Options[:sequential]
|
14
|
-
log.debug('Resolving facts sequentially')
|
15
14
|
resolve_sequentially(internal_searched_facts)
|
16
15
|
else
|
17
|
-
log.debug('Resolving fact in parallel')
|
18
16
|
resolve_in_parallel(internal_searched_facts)
|
19
17
|
end
|
20
18
|
|
@@ -13,6 +13,7 @@ module Facter
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def resolve_facts(user_query = [])
|
16
|
+
log_resolving_method
|
16
17
|
@options[:user_query] = user_query
|
17
18
|
cache_manager = Facter::CacheManager.new
|
18
19
|
|
@@ -40,6 +41,7 @@ module Facter
|
|
40
41
|
# - load all the core facts, external facts and env facts
|
41
42
|
# - load all custom facts
|
42
43
|
def resolve_fact(user_query)
|
44
|
+
log_resolving_method
|
43
45
|
@options[:user_query] = user_query
|
44
46
|
@log.debug("resolving fact with user_query: #{user_query}")
|
45
47
|
|
@@ -58,12 +60,21 @@ module Facter
|
|
58
60
|
end
|
59
61
|
|
60
62
|
def resolve_core(user_query = [], options = {})
|
63
|
+
log_resolving_method
|
61
64
|
@cache_manager = CacheManager.new
|
62
65
|
core_fact(user_query, options)
|
63
66
|
end
|
64
67
|
|
65
68
|
private
|
66
69
|
|
70
|
+
def log_resolving_method
|
71
|
+
if Options[:sequential]
|
72
|
+
@log.debugonce('Resolving facts sequentially')
|
73
|
+
else
|
74
|
+
@log.debugonce('Resolving fact in parallel')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
67
78
|
def core_fact(user_query, options)
|
68
79
|
loaded_facts_hash = @fact_loader.load_internal_facts(user_query, options)
|
69
80
|
|
@@ -15,8 +15,16 @@ module Facter
|
|
15
15
|
@@logger = nil
|
16
16
|
@@message_callback = nil
|
17
17
|
@@has_errors = false
|
18
|
+
@@debug_messages = []
|
19
|
+
@@warn_messages = []
|
20
|
+
@@timing = false
|
18
21
|
|
19
22
|
class << self
|
23
|
+
def clear_messages
|
24
|
+
@@debug_messages.clear
|
25
|
+
@@warn_messages.clear
|
26
|
+
end
|
27
|
+
|
20
28
|
def on_message(&block)
|
21
29
|
@@message_callback = block
|
22
30
|
end
|
@@ -47,6 +55,41 @@ module Facter
|
|
47
55
|
"[#{datetime}] #{severity} #{msg} \n"
|
48
56
|
end
|
49
57
|
end
|
58
|
+
|
59
|
+
# Print an exception message, and optionally a backtrace if trace is set
|
60
|
+
|
61
|
+
# Print timing information
|
62
|
+
#
|
63
|
+
# @param string [String] the time to print
|
64
|
+
# @return [void]
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
def show_time(string)
|
68
|
+
return unless string && timing?
|
69
|
+
|
70
|
+
if @@message_callback
|
71
|
+
@@message_callback.call(:info, string)
|
72
|
+
else
|
73
|
+
warn("#{GREEN}#{string}#{RESET}")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Enable or disable logging of timing information
|
78
|
+
#
|
79
|
+
# @param bool [true, false]
|
80
|
+
# @return [void]
|
81
|
+
#
|
82
|
+
# @api private
|
83
|
+
def timing(bool)
|
84
|
+
@@timing = bool
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns whether timing output is turned on
|
88
|
+
#
|
89
|
+
# @api private
|
90
|
+
def timing?
|
91
|
+
@@timing
|
92
|
+
end
|
50
93
|
end
|
51
94
|
|
52
95
|
def initialize(logged_class)
|
@@ -68,6 +111,16 @@ module Facter
|
|
68
111
|
end
|
69
112
|
end
|
70
113
|
|
114
|
+
def debugonce(msg)
|
115
|
+
return unless debugging_active?
|
116
|
+
|
117
|
+
message_string = msg.to_s
|
118
|
+
return if @@debug_messages.include? message_string
|
119
|
+
|
120
|
+
@@debug_messages << message_string
|
121
|
+
debug(message_string)
|
122
|
+
end
|
123
|
+
|
71
124
|
def info(msg)
|
72
125
|
if msg.nil? || msg.empty?
|
73
126
|
empty_message_error(msg)
|
@@ -88,6 +141,14 @@ module Facter
|
|
88
141
|
end
|
89
142
|
end
|
90
143
|
|
144
|
+
def warnonce(message)
|
145
|
+
message_string = message.to_s
|
146
|
+
return if @@warn_messages.include? message_string
|
147
|
+
|
148
|
+
@@warn_messages << message_string
|
149
|
+
warn(message_string)
|
150
|
+
end
|
151
|
+
|
91
152
|
def error(msg, colorize = false)
|
92
153
|
@@has_errors = true
|
93
154
|
|
@@ -24,13 +24,11 @@ module Facter
|
|
24
24
|
# Returns a list of SearchedFact objects that resolve the users query.
|
25
25
|
def parse(query_list, loaded_fact)
|
26
26
|
matched_facts = []
|
27
|
-
@log.debug "User query is: #{query_list}"
|
28
27
|
@query_list = query_list
|
29
28
|
|
30
29
|
return no_user_query(loaded_fact) unless query_list.any?
|
31
30
|
|
32
31
|
query_list.each do |query|
|
33
|
-
@log.debug "Query is #{query}"
|
34
32
|
found_facts = search_for_facts(query, loaded_fact)
|
35
33
|
matched_facts << found_facts
|
36
34
|
end
|
@@ -65,7 +63,6 @@ module Facter
|
|
65
63
|
end
|
66
64
|
|
67
65
|
def get_facts_matching_tokens(query_tokens, query_token_range, loaded_fact_hash)
|
68
|
-
@log.debug "Checking query tokens #{query_tokens[query_token_range].join('.')}"
|
69
66
|
resolvable_fact_list = []
|
70
67
|
|
71
68
|
loaded_fact_hash.each do |loaded_fact|
|
@@ -77,7 +74,7 @@ module Facter
|
|
77
74
|
resolvable_fact_list << searched_fact
|
78
75
|
end
|
79
76
|
|
80
|
-
@log.debug "List of resolvable facts: #{resolvable_fact_list.inspect}"
|
77
|
+
@log.debug "List of resolvable facts: #{resolvable_fact_list.inspect}" if resolvable_fact_list.any?
|
81
78
|
resolvable_fact_list
|
82
79
|
end
|
83
80
|
|
@@ -53,12 +53,15 @@ module Facter
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def process_name
|
56
|
-
|
56
|
+
os_name = @fact_list[:name]
|
57
|
+
return unless os_name
|
57
58
|
|
58
|
-
@fact_list[:name] = if
|
59
|
-
|
59
|
+
@fact_list[:name] = if os_name.downcase.start_with?('red', 'oracle', 'arch', 'manjaro')
|
60
|
+
os_name = os_name.split(' ')[0..1].join
|
61
|
+
os_name = os_name.capitalize if os_name.downcase.start_with?('arch', 'manjaro')
|
62
|
+
os_name
|
60
63
|
else
|
61
|
-
|
64
|
+
os_name.split(' ')[0].strip
|
62
65
|
end
|
63
66
|
end
|
64
67
|
|
data/lib/facter/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: facter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.2.
|
4
|
+
version: 4.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppet
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -214,7 +214,6 @@ files:
|
|
214
214
|
- lib/facter/custom_facts/core/execution/windows.rb
|
215
215
|
- lib/facter/custom_facts/core/file_loader.rb
|
216
216
|
- lib/facter/custom_facts/core/legacy_facter.rb
|
217
|
-
- lib/facter/custom_facts/core/logging.rb
|
218
217
|
- lib/facter/custom_facts/core/resolvable.rb
|
219
218
|
- lib/facter/custom_facts/core/suitable.rb
|
220
219
|
- lib/facter/custom_facts/util/collection.rb
|
@@ -1,203 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module LegacyFacter
|
4
|
-
module Core
|
5
|
-
module Logging
|
6
|
-
extend self
|
7
|
-
|
8
|
-
# @api private
|
9
|
-
GREEN = "\e[0;32m"
|
10
|
-
# @api private
|
11
|
-
RESET = "\e[0m"
|
12
|
-
|
13
|
-
RED = "\e[31m"
|
14
|
-
|
15
|
-
# @api private
|
16
|
-
@@debug = false
|
17
|
-
# @api private
|
18
|
-
@@timing = false
|
19
|
-
# @api private
|
20
|
-
@@trace = false
|
21
|
-
|
22
|
-
# @api private
|
23
|
-
@@warn_messages = {}
|
24
|
-
# @api private
|
25
|
-
@@debug_messages = {}
|
26
|
-
|
27
|
-
# @api private
|
28
|
-
@@message_callback = nil
|
29
|
-
|
30
|
-
# Used to register a callback that is called when a message is logged.
|
31
|
-
# If a block is given, Facter will not log messages.
|
32
|
-
# If a block is not given, Facter will resume logging messages.
|
33
|
-
# @param block [Proc] the callback to call when a message is logged.
|
34
|
-
# The first argument to the callback will be a symbol representing a level. The supported
|
35
|
-
# levels are: :trace, :debug, :info, :warn, :error, and :fatal.
|
36
|
-
# The second argument to the callback will be a string containing the message
|
37
|
-
# that was logged.
|
38
|
-
# @api public
|
39
|
-
def on_message(&block)
|
40
|
-
@@message_callback = block
|
41
|
-
end
|
42
|
-
|
43
|
-
# Prints a debug message if debugging is turned on
|
44
|
-
#
|
45
|
-
# @param msg [String] the debug message
|
46
|
-
# @return [void]
|
47
|
-
def debug(msg)
|
48
|
-
return unless debugging?
|
49
|
-
|
50
|
-
if msg.nil? || msg.empty?
|
51
|
-
invoker = caller(1..1).first.slice(/.*:\d+/)
|
52
|
-
self.warn "#{self.class}#debug invoked with invalid message #{msg.inspect}:#{msg.class} at #{invoker}"
|
53
|
-
elsif @@message_callback
|
54
|
-
@@message_callback.call(:debug, msg)
|
55
|
-
else
|
56
|
-
puts GREEN + msg + RESET
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# Prints a debug message only once.
|
61
|
-
#
|
62
|
-
# @note Uniqueness is based on the string, not the specific location
|
63
|
-
# of the method call.
|
64
|
-
#
|
65
|
-
# @param msg [String] the debug message
|
66
|
-
# @return [void]
|
67
|
-
def debugonce(msg)
|
68
|
-
return unless msg && !msg.empty? && @@debug_messages[msg].nil?
|
69
|
-
|
70
|
-
@@debug_messages[msg] = true
|
71
|
-
debug(msg)
|
72
|
-
end
|
73
|
-
|
74
|
-
# Prints a warning message. The message is only printed if debugging
|
75
|
-
# is enabled.
|
76
|
-
#
|
77
|
-
# @param msg [String] the warning message to be printed
|
78
|
-
#
|
79
|
-
# @return [void]
|
80
|
-
def warn(msg)
|
81
|
-
if msg.nil? || msg.empty?
|
82
|
-
invoker = caller(1..1).first.slice(/.*:\d+/)
|
83
|
-
msg = "#{self.class}#debug invoked with invalid message #{msg.inspect}:#{msg.class} at #{invoker}"
|
84
|
-
end
|
85
|
-
if @@message_callback
|
86
|
-
@@message_callback.call(:warn, msg)
|
87
|
-
else
|
88
|
-
Kernel.warn msg
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# Prints a warning message only once per process. Each unique string
|
93
|
-
# is printed once.
|
94
|
-
#
|
95
|
-
# @note Unlike {warn} the message will be printed even if debugging is
|
96
|
-
# not turned on. This behavior is likely to change and should not be
|
97
|
-
# relied on.
|
98
|
-
#
|
99
|
-
# @param msg [String] the warning message to be printed
|
100
|
-
#
|
101
|
-
# @return [void]
|
102
|
-
def warnonce(msg)
|
103
|
-
return unless @@warn_messages[msg].nil?
|
104
|
-
|
105
|
-
self.warn(msg)
|
106
|
-
@@warn_messages[msg] = true
|
107
|
-
end
|
108
|
-
|
109
|
-
def log_exception(exception, message = :default)
|
110
|
-
self.warn(format_exception(exception, message, @@trace))
|
111
|
-
end
|
112
|
-
|
113
|
-
def format_exception(exception, message, trace)
|
114
|
-
arr = []
|
115
|
-
|
116
|
-
if message == :default
|
117
|
-
arr << exception.message
|
118
|
-
elsif message
|
119
|
-
arr << message
|
120
|
-
end
|
121
|
-
|
122
|
-
if trace
|
123
|
-
arr << 'backtrace:'
|
124
|
-
arr.concat(exception.backtrace)
|
125
|
-
end
|
126
|
-
|
127
|
-
"#{RED}#{arr.flatten.join("\n")}#{RESET}"
|
128
|
-
end
|
129
|
-
|
130
|
-
# Print an exception message, and optionally a backtrace if trace is set
|
131
|
-
|
132
|
-
# Print timing information
|
133
|
-
#
|
134
|
-
# @param string [String] the time to print
|
135
|
-
# @return [void]
|
136
|
-
#
|
137
|
-
# @api private
|
138
|
-
def show_time(string)
|
139
|
-
return unless string && timing?
|
140
|
-
|
141
|
-
if @@message_callback
|
142
|
-
@@message_callback.call(:info, string)
|
143
|
-
else
|
144
|
-
$stderr.puts "#{GREEN}#{string}#{RESET}"
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
# Enable or disable logging of debug messages
|
149
|
-
#
|
150
|
-
# @param bool [true, false]
|
151
|
-
# @return [void]
|
152
|
-
#
|
153
|
-
# @api private
|
154
|
-
def debugging(bool)
|
155
|
-
@@debug = bool
|
156
|
-
end
|
157
|
-
|
158
|
-
# Is debugging enabled?
|
159
|
-
#
|
160
|
-
# @return [true, false]
|
161
|
-
#
|
162
|
-
# @api private
|
163
|
-
def debugging?
|
164
|
-
@@debug
|
165
|
-
end
|
166
|
-
|
167
|
-
# Enable or disable logging of timing information
|
168
|
-
#
|
169
|
-
# @param bool [true, false]
|
170
|
-
# @return [void]
|
171
|
-
#
|
172
|
-
# @api private
|
173
|
-
def timing(bool)
|
174
|
-
@@timing = bool
|
175
|
-
end
|
176
|
-
|
177
|
-
# Returns whether timing output is turned on
|
178
|
-
#
|
179
|
-
# @api private
|
180
|
-
def timing?
|
181
|
-
@@timing
|
182
|
-
end
|
183
|
-
|
184
|
-
def trace(bool)
|
185
|
-
@@trace = bool
|
186
|
-
end
|
187
|
-
|
188
|
-
def trace?
|
189
|
-
@@trace
|
190
|
-
end
|
191
|
-
|
192
|
-
# Clears the seen state of debug and warning messages. See {debugonce} and {warnonce}.
|
193
|
-
#
|
194
|
-
# @return [void]
|
195
|
-
#
|
196
|
-
# @api private
|
197
|
-
def clear_messages
|
198
|
-
@@debug_messages.clear
|
199
|
-
@@warn_messages.clear
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|