facter 4.0.37 → 4.0.42

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/bin/facter +3 -4
  3. data/lib/facter.rb +163 -23
  4. data/lib/facter/custom_facts/core/execution/base.rb +42 -6
  5. data/lib/facter/custom_facts/util/directory_loader.rb +1 -1
  6. data/lib/facter/facts/aix/disks.rb +1 -1
  7. data/lib/facter/facts/aix/kernel.rb +1 -1
  8. data/lib/facter/facts/aix/kernelmajversion.rb +1 -1
  9. data/lib/facter/facts/aix/kernelrelease.rb +1 -1
  10. data/lib/facter/facts/aix/kernelversion.rb +1 -1
  11. data/lib/facter/facts/aix/os/release.rb +1 -1
  12. data/lib/facter/facts/linux/cloud.rb +15 -0
  13. data/lib/facter/facts/linux/disks.rb +1 -1
  14. data/lib/facter/facts/linux/ec2_metadata.rb +5 -27
  15. data/lib/facter/facts/linux/ec2_userdata.rb +5 -27
  16. data/lib/facter/facts/linux/is_virtual.rb +7 -46
  17. data/lib/facter/facts/linux/virtual.rb +3 -58
  18. data/lib/facter/facts/rhel/os/release.rb +2 -2
  19. data/lib/facter/facts/solaris/disks.rb +1 -1
  20. data/lib/facter/facts_utils/virtual_detector.rb +78 -0
  21. data/lib/facter/framework/cli/cli.rb +84 -36
  22. data/lib/facter/framework/cli/cli_launcher.rb +34 -38
  23. data/lib/facter/framework/config/fact_groups.rb +36 -2
  24. data/lib/facter/framework/core/cache_manager.rb +40 -23
  25. data/lib/facter/framework/core/fact_loaders/fact_loader.rb +14 -11
  26. data/lib/facter/framework/core/options/config_file_options.rb +5 -3
  27. data/lib/facter/framework/core/options/option_store.rb +27 -10
  28. data/lib/facter/framework/logging/logger.rb +3 -11
  29. data/lib/facter/patches/sysfilesystem/sys/statvfs.rb +92 -0
  30. data/lib/facter/resolvers/aix/os_level.rb +27 -0
  31. data/lib/facter/resolvers/cloud.rb +39 -0
  32. data/lib/facter/resolvers/dmi_decode.rb +1 -0
  33. data/lib/facter/resolvers/memory_resolver.rb +12 -14
  34. data/lib/facter/resolvers/networking_linux_resolver.rb +0 -1
  35. data/lib/facter/resolvers/utils/filesystem_helper.rb +3 -1
  36. data/lib/facter/version.rb +1 -1
  37. metadata +7 -4
  38. data/lib/facter/resolvers/aix/os_level_resolver.rb +0 -25
  39. data/lib/facter/resolvers/os_level_resolver.rb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f2ed5162fef26cfbf5bd010cf7737ac8b4856cf59f9f55745d6cfc1bec39781e
4
- data.tar.gz: 761beee20f449b3bbe1e5dc35c0bcd675e9602902804e7add3ee6c3d31a8916d
3
+ metadata.gz: ffa55de7f92a74b84788507b7e9667f158edc68abef1412f40ab5d3beb8f6aad
4
+ data.tar.gz: e92ff5798a9abab30f1887c5e4f934d75cef67975b2485e53ba6dc58b59ee899
5
5
  SHA512:
6
- metadata.gz: 92751ef6452023c4e4edd9c2b7d21bd78bef74404d5550d4de353b4243f6639f29abbba1f00d6f8ba0b4bbf7afbea060f00aa34919a2d1d94459e1df5515e706
7
- data.tar.gz: b4ca79c0907439874ae638a920def98b9ed0d3e2893a77b6bc3d44dfb3cba756f88e550d55d14a8e4cdb9d2c5b58a6d0c6a6c335955ae819607021a80562cd65
6
+ metadata.gz: 4841268cf5f76f1ad2b0ed2bf16b2527dd73e4d41728c64dbe13986b1a574759f900e2748e72ce72f6c677cf754d8a4f5115530140285412a07943e13b6312a5
7
+ data.tar.gz: bd48e0942af375429188957956a5555963297d62a9bc6549529ae1713b7670b41bfc5eea6b894d961e3e32507963e394779c372ad3b12a6422b5218f94b0f9e4
data/bin/facter CHANGED
@@ -4,8 +4,7 @@
4
4
  require 'pathname'
5
5
  require 'facter/framework/cli/cli_launcher.rb'
6
6
 
7
- cli_launcher = CliLauncher.new(ARGV)
7
+ Facter::OptionsValidator.validate(ARGV)
8
+ processed_arguments = CliLauncher.prepare_arguments(ARGV)
8
9
 
9
- cli_launcher.validate_options
10
- cli_launcher.prepare_arguments
11
- cli_launcher.start
10
+ CliLauncher.start(processed_arguments)
@@ -13,8 +13,31 @@ module Facter
13
13
  Options.init
14
14
  Log.output(STDOUT)
15
15
  @already_searched = {}
16
+ @debug_once = []
17
+ @warn_once = []
16
18
 
17
19
  class << self
20
+ def resolve(args_as_string)
21
+ require 'facter/framework/cli/cli_launcher'
22
+
23
+ args = args_as_string.split(' ')
24
+
25
+ Facter::OptionsValidator.validate(args)
26
+ processed_arguments = CliLauncher.prepare_arguments(args, nil)
27
+
28
+ cli = Facter::Cli.new([], processed_arguments)
29
+
30
+ if cli.args.include?(:version)
31
+ cli.invoke(:version, [])
32
+ elsif cli.args.include?('--list-cache-groups')
33
+ cli.invoke(:list_cache_groups, [])
34
+ elsif cli.args.include?('--list-block-groups')
35
+ cli.invoke(:list_block_groups, [])
36
+ else
37
+ cli.invoke(:arg_parser)
38
+ end
39
+ end
40
+
18
41
  def clear_messages
19
42
  logger.debug('clear_messages is not implemented')
20
43
  end
@@ -54,6 +77,8 @@ module Facter
54
77
  # @api public
55
78
  def clear
56
79
  @already_searched = {}
80
+ @debug_once = []
81
+ @warn_once = []
57
82
  LegacyFacter.clear
58
83
  Options[:custom_dir] = []
59
84
  LegacyFacter.collection.invalidate_custom_facts
@@ -68,24 +93,54 @@ module Facter
68
93
  fact_collection.dig(*splitted_user_query)
69
94
  end
70
95
 
71
- # Prints out a debug message when debug option is set to true
72
- # @param msg [String] Message to be printed out
96
+ # Logs debug message when debug option is set to true
97
+ # @param message [Object] Message object to be logged
98
+ #
99
+ # @return [nil]
100
+ #
101
+ # @api public
102
+ def debug(message)
103
+ return unless debugging?
104
+
105
+ logger.debug(message.to_s)
106
+ nil
107
+ end
108
+
109
+ # Logs the same debug message only once when debug option is set to true
110
+ # @param message [Object] Message object to be logged
73
111
  #
74
112
  # @return [nil]
75
113
  #
76
114
  # @api public
77
- def debug(msg)
115
+ def debugonce(message)
78
116
  return unless debugging?
79
117
 
80
- logger.debug(msg)
118
+ message_string = message.to_s
119
+ return if @debug_once.include? message_string
120
+
121
+ @debug_once << message_string
122
+ logger.debug(message_string)
81
123
  nil
82
124
  end
83
125
 
126
+ # Define a new fact or extend an existing fact.
127
+ #
128
+ # @param name [Symbol] The name of the fact to define
129
+ # @param options [Hash] A hash of options to set on the fact
130
+ #
131
+ # @return [Facter::Util::Fact] The fact that was defined
132
+ #
133
+ # @api public
134
+ def define_fact(name, options = {}, &block)
135
+ options[:fact_type] = :custom
136
+ LegacyFacter.define_fact(name, options, &block)
137
+ end
138
+
84
139
  def on_message(&block)
85
140
  Facter::Log.on_message(&block)
86
141
  end
87
142
 
88
- # Check whether debuging is enabled
143
+ # Check whether debugging is enabled
89
144
  #
90
145
  # @return [bool]
91
146
  #
@@ -104,11 +159,31 @@ module Facter
104
159
  Facter::Options[:debug] = debug_bool
105
160
  end
106
161
 
162
+ # Iterates over fact names and values
163
+ #
164
+ # @yieldparam [String] name the fact name
165
+ # @yieldparam [String] value the current value of the fact
166
+ #
167
+ # @return [Facter]
168
+ #
169
+ # @api public
170
+ def each
171
+ log_blocked_facts
172
+ resolved_facts = Facter::FactManager.instance.resolve_facts
173
+ SessionCache.invalidate_all_caches
174
+
175
+ resolved_facts.each do |fact|
176
+ yield(fact.name, fact.value)
177
+ end
178
+
179
+ self
180
+ end
181
+
107
182
  # Returns a fact object by name. If you use this, you still have to
108
183
  # call {Facter::Util::Fact#value `value`} on it to retrieve the actual
109
184
  # value.
110
185
  #
111
- # @param name [String] the name of the fact
186
+ # @param user_query [String] the name of the fact
112
187
  #
113
188
  # @return [Facter::Util::Fact, nil] The fact object, or nil if no fact
114
189
  # is found.
@@ -134,6 +209,16 @@ module Facter
134
209
  nil
135
210
  end
136
211
 
212
+ # Loads all facts
213
+ #
214
+ # @return [nil]
215
+ #
216
+ # @api public
217
+ def loadfacts
218
+ LegacyFacter.loadfacts
219
+ nil
220
+ end
221
+
137
222
  # Register directories to be searched for custom facts. The registered directories
138
223
  # must be absolute paths or they will be ignored.
139
224
  #
@@ -199,7 +284,7 @@ module Facter
199
284
  end
200
285
 
201
286
  # Enable or disable trace
202
- # @param debug_bool [bool] Set trace on debug state
287
+ # @param bool [bool] Set trace on debug state
203
288
  #
204
289
  # @return [type] [description]
205
290
  #
@@ -210,7 +295,7 @@ module Facter
210
295
 
211
296
  # Gets the value for a fact. Returns `nil` if no such fact exists.
212
297
  #
213
- # @param name [String] the fact name
298
+ # @param user_query [String] the fact name
214
299
  # @return [String] the value of the fact, or nil if no fact is found
215
300
  #
216
301
  # @api public
@@ -220,6 +305,18 @@ module Facter
220
305
  @already_searched[user_query]&.value
221
306
  end
222
307
 
308
+ def values(options, user_queries)
309
+ init_cli_options(options, user_queries)
310
+ resolved_facts = Facter::FactManager.instance.resolve_facts(user_queries)
311
+ Facter::SessionCache.invalidate_all_caches
312
+
313
+ if user_queries.count.zero?
314
+ Facter::FactCollection.new.build_fact_collection!(resolved_facts)
315
+ else
316
+ FormatterHelper.retrieve_facts_to_display_for_user_query(user_queries, resolved_facts)
317
+ end
318
+ end
319
+
223
320
  # Returns Facter version
224
321
  #
225
322
  # @return [String] Current version
@@ -247,23 +344,67 @@ module Facter
247
344
  [fact_formatter.format(resolved_facts), status || 0]
248
345
  end
249
346
 
250
- def log_exception(exception, message = :default)
251
- arr = []
252
- if message == :default
253
- arr << exception.message
254
- elsif message
255
- arr << message
256
- end
257
- if Options[:trace]
258
- arr << 'backtrace:'
259
- arr.concat(exception.backtrace)
260
- end
347
+ def log_exception(exception, message = nil)
348
+ error_message = []
349
+
350
+ error_message << message.to_s unless message.nil? || (message.is_a?(String) && message.empty?)
261
351
 
262
- logger.error(arr.flatten.join("\n"))
352
+ parse_exception(exception, error_message)
353
+ logger.error(error_message.flatten.join("\n"))
354
+ end
355
+
356
+ # Returns a list with the names of all solved facts
357
+ #
358
+ # @return [Array] the list with all the fact names
359
+ #
360
+ # @api public
361
+ def list
362
+ to_hash.keys.sort
363
+ end
364
+
365
+ # Logs the message parameter as a warning.
366
+ #
367
+ # @param message [Object] the warning object to be displayed
368
+ #
369
+ # @return [nil]
370
+ #
371
+ # @api public
372
+ def warn(message)
373
+ logger.warn(message.to_s)
374
+ nil
375
+ end
376
+
377
+ # Logs only once the same warning message.
378
+ #
379
+ # @param message [Object] the warning message object
380
+ #
381
+ # @return [nil]
382
+ #
383
+ # @api public
384
+ def warnonce(message)
385
+ message_string = message.to_s
386
+ return if @warn_once.include? message_string
387
+
388
+ @warn_once << message_string
389
+ logger.warn(message_string)
390
+ nil
263
391
  end
264
392
 
265
393
  private
266
394
 
395
+ def parse_exception(exception, error_message)
396
+ if exception.is_a?(Exception)
397
+ error_message << exception.message if error_message.empty?
398
+
399
+ if Options[:trace] && !exception.backtrace.nil?
400
+ error_message << 'backtrace:'
401
+ error_message.concat(exception.backtrace)
402
+ end
403
+ elsif error_message.empty?
404
+ error_message << exception.to_s
405
+ end
406
+ end
407
+
267
408
  def logger
268
409
  @logger ||= Log.new(self)
269
410
  end
@@ -303,10 +444,9 @@ module Facter
303
444
  # Returns exit status when user query contains facts that do
304
445
  # not exist
305
446
  #
306
- # @param dirs [Array] Arguments sent to CLI
307
- # @param dirs [Array] List of resolved facts
447
+ # @param resolved_facts [Array] List of resolved facts
308
448
  #
309
- # @return [Integer, nil] Will return status 1 if user query contains
449
+ # @return [1/nil] Will return status 1 if user query contains
310
450
  # facts that are not found or resolved, otherwise it will return nil
311
451
  #
312
452
  # @api private
@@ -6,6 +6,10 @@ module Facter
6
6
  class Base
7
7
  STDERR_MESSAGE = 'Command %s resulted with the following stderr message: %s'
8
8
 
9
+ def initialize
10
+ @log = Log.new(self)
11
+ end
12
+
9
13
  # This is part of the public API. No race condition can happen
10
14
  # here because custom facts are executed sequentially
11
15
  def with_env(values)
@@ -36,9 +40,7 @@ module Facter
36
40
  end
37
41
 
38
42
  def execute(command, options = {})
39
- on_fail = options.fetch(:on_fail, :raise)
40
- expand = options.fetch(:expand, true)
41
- logger = options[:logger]
43
+ on_fail, expand, logger, time_limit = extract_options(options)
42
44
 
43
45
  expanded_command = if !expand && builtin_command?(command) || logger
44
46
  command
@@ -55,11 +57,21 @@ module Facter
55
57
  return on_fail
56
58
  end
57
59
 
58
- execute_command(expanded_command, on_fail, logger)
60
+ execute_command(expanded_command, on_fail, logger, time_limit)
59
61
  end
60
62
 
61
63
  private
62
64
 
65
+ def extract_options(options)
66
+ on_fail = options.fetch(:on_fail, :raise)
67
+ expand = options.fetch(:expand, true)
68
+ logger = options[:logger]
69
+ time_limit = options[:limit].to_i
70
+ time_limit = time_limit.positive? ? time_limit : nil
71
+
72
+ [on_fail, expand, logger, time_limit]
73
+ end
74
+
63
75
  def log_stderr(msg, command, logger)
64
76
  return if !msg || msg.empty?
65
77
 
@@ -77,12 +89,36 @@ module Facter
77
89
  output.chomp =~ /builtin/ ? true : false
78
90
  end
79
91
 
80
- def execute_command(command, on_fail, logger = nil)
92
+ def execute_command(command, on_fail, logger = nil, time_limit = nil)
93
+ time_limit ||= 300
81
94
  begin
82
95
  # Set LC_ALL and LANG to force i18n to C for the duration of this exec;
83
96
  # this ensures that any code that parses the
84
97
  # output of the command can expect it to be in a consistent / predictable format / locale
85
- out, stderr, _status_ = Open3.capture3({ 'LC_ALL' => 'C', 'LANG' => 'C' }, command.to_s)
98
+ opts = { 'LC_ALL' => 'C', 'LANG' => 'C' }
99
+ require 'timeout'
100
+ @log.debug("Executing command: #{command}")
101
+ out, stderr = Open3.popen3(opts, command.to_s) do |_, stdout, stderr, wait_thr|
102
+ pid = wait_thr.pid
103
+ stdout_messages = +''
104
+ stderr_messages = +''
105
+ out_reader = Thread.new { stdout.read }
106
+ err_reader = Thread.new { stderr.read }
107
+ begin
108
+ Timeout.timeout(time_limit) do
109
+ stdout_messages << out_reader.value
110
+ stderr_messages << err_reader.value
111
+ end
112
+ rescue Timeout::Error
113
+ message = "Timeout encounter after #{time_limit}s, killing process with pid: #{pid}"
114
+ Process.kill('KILL', pid)
115
+ on_fail == :raise ? (raise StandardError, message) : @log.debug(message)
116
+ ensure
117
+ out_reader.kill
118
+ err_reader.kill
119
+ end
120
+ [stdout_messages, stderr_messages]
121
+ end
86
122
  log_stderr(stderr, command, logger)
87
123
  rescue StandardError => e
88
124
  return '' if logger
@@ -59,7 +59,7 @@ module LegacyFacter
59
59
  basename = File.basename(file)
60
60
  next if file_blocked?(basename)
61
61
 
62
- if facts.find { |f| f.name == basename } && cm.group_cached?(basename)
62
+ if facts.find { |f| f.name == basename } && cm.fact_cache_enabled?(basename)
63
63
  Facter.log_exception(Exception.new("Caching is enabled for group \"#{basename}\" while "\
64
64
  'there are at least two external facts files with the same filename'))
65
65
  else
@@ -24,7 +24,7 @@ module Facts
24
24
 
25
25
  def add_legacy_facts(disks, facts)
26
26
  disks.each do |disk_name, disk_info|
27
- facts.push(Facter::ResolvedFact.new("blockdevice_#{disk_name}_size", disk_info[:size_bytes].to_s, :legacy))
27
+ facts.push(Facter::ResolvedFact.new("blockdevice_#{disk_name}_size", disk_info[:size_bytes], :legacy))
28
28
  end
29
29
  end
30
30
  end
@@ -6,7 +6,7 @@ module Facts
6
6
  FACT_NAME = 'kernel'
7
7
 
8
8
  def call_the_resolver
9
- fact_value = Facter::Resolvers::OsLevel.resolve(:kernel)
9
+ fact_value = Facter::Resolvers::Aix::OsLevel.resolve(:kernel)
10
10
 
11
11
  Facter::ResolvedFact.new(FACT_NAME, fact_value)
12
12
  end
@@ -6,7 +6,7 @@ module Facts
6
6
  FACT_NAME = 'kernelmajversion'
7
7
 
8
8
  def call_the_resolver
9
- fact_value = Facter::Resolvers::OsLevel.resolve(:build)
9
+ fact_value = Facter::Resolvers::Aix::OsLevel.resolve(:build)
10
10
  kernelmajversion = fact_value.split('-')[0]
11
11
 
12
12
  Facter::ResolvedFact.new(FACT_NAME, kernelmajversion)
@@ -6,7 +6,7 @@ module Facts
6
6
  FACT_NAME = 'kernelrelease'
7
7
 
8
8
  def call_the_resolver
9
- fact_value = Facter::Resolvers::OsLevel.resolve(:build).strip
9
+ fact_value = Facter::Resolvers::Aix::OsLevel.resolve(:build).strip
10
10
 
11
11
  Facter::ResolvedFact.new(FACT_NAME, fact_value)
12
12
  end
@@ -6,7 +6,7 @@ module Facts
6
6
  FACT_NAME = 'kernelversion'
7
7
 
8
8
  def call_the_resolver
9
- fact_value = Facter::Resolvers::OsLevel.resolve(:build)
9
+ fact_value = Facter::Resolvers::Aix::OsLevel.resolve(:build)
10
10
  kernelversion = fact_value.split('-')[0]
11
11
 
12
12
  Facter::ResolvedFact.new(FACT_NAME, kernelversion)
@@ -8,7 +8,7 @@ module Facts
8
8
  ALIASES = %w[operatingsystemmajrelease operatingsystemrelease].freeze
9
9
 
10
10
  def call_the_resolver
11
- fact_value = Facter::Resolvers::OsLevel.resolve(:build)
11
+ fact_value = Facter::Resolvers::Aix::OsLevel.resolve(:build)
12
12
  major = fact_value.split('-')[0]
13
13
 
14
14
  [Facter::ResolvedFact.new(FACT_NAME, full: fact_value.strip, major: major),