facter 4.0.52 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/facter.rb +20 -20
  3. data/lib/facter/custom_facts/core/execution/base.rb +7 -3
  4. data/lib/facter/custom_facts/core/execution/popen3.rb +13 -1
  5. data/lib/facter/custom_facts/util/collection.rb +5 -0
  6. data/lib/facter/custom_facts/util/normalization.rb +7 -2
  7. data/lib/facter/facts/linux/cloud/provider.rb +9 -2
  8. data/lib/facter/facts/linux/hypervisors/xen.rb +2 -4
  9. data/lib/facter/facts/solaris/hypervisors/ldom.rb +1 -1
  10. data/lib/facter/facts/solaris/hypervisors/zone.rb +1 -1
  11. data/lib/facter/facts/solaris/mountpoints.rb +1 -1
  12. data/lib/facter/facts/windows/az_metadata.rb +1 -5
  13. data/lib/facter/facts/windows/cloud/provider.rb +6 -2
  14. data/lib/facter/framework/core/fact_augmenter.rb +21 -4
  15. data/lib/facter/framework/core/fact_loaders/external_fact_loader.rb +9 -6
  16. data/lib/facter/framework/core/fact_loaders/fact_loader.rb +36 -33
  17. data/lib/facter/framework/core/fact_manager.rb +85 -14
  18. data/lib/facter/framework/core/options/config_file_options.rb +7 -0
  19. data/lib/facter/framework/core/options/option_store.rb +3 -1
  20. data/lib/facter/framework/formatters/formatter_helper.rb +3 -5
  21. data/lib/facter/framework/parsers/query_parser.rb +7 -14
  22. data/lib/facter/models/fact_collection.rb +32 -5
  23. data/lib/facter/resolvers/aix/ffi/ffi_helper.rb +1 -1
  24. data/lib/facter/resolvers/base_resolver.rb +2 -2
  25. data/lib/facter/resolvers/dmi_decode.rb +0 -1
  26. data/lib/facter/resolvers/linux/hostname.rb +16 -5
  27. data/lib/facter/resolvers/macosx/mountpoints.rb +14 -1
  28. data/lib/facter/resolvers/networking.rb +1 -1
  29. data/lib/facter/resolvers/selinux.rb +5 -7
  30. data/lib/facter/resolvers/solaris/ffi/structs.rb +12 -0
  31. data/lib/facter/resolvers/solaris/mountpoints.rb +22 -16
  32. data/lib/facter/resolvers/solaris/networking.rb +20 -5
  33. data/lib/facter/resolvers/solaris/zone.rb +0 -1
  34. data/lib/facter/resolvers/windows/uptime.rb +3 -22
  35. data/lib/facter/templates/man.erb +6 -6
  36. data/lib/facter/util/facts/unit_converter.rb +2 -2
  37. data/lib/facter/util/facts/virtual_detector.rb +6 -13
  38. data/lib/facter/util/resolvers/http.rb +7 -1
  39. data/lib/facter/util/resolvers/networking/primary_interface.rb +11 -5
  40. data/lib/facter/util/utils.rb +18 -1
  41. data/lib/facter/version.rb +1 -1
  42. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 778d4d972d3e950f98d4fd8dbd4100e7b2a0c168369949b234d7088ddeba539f
4
- data.tar.gz: 50303cfdfcf434c38d3d9539c35362f190dd84b82a8f85227d804a876b5a4ce3
3
+ metadata.gz: c5eeb6c68641c9730832a6e41af6bd0bf5367f1953cd737122356a1ddb9a1265
4
+ data.tar.gz: 3ead9f3065982b9eb476844a21901d5fd1fa8bc1f165b3118490054b004352df
5
5
  SHA512:
6
- metadata.gz: 38f84ef3e3699e3bed3b348ae07562f9423121011659ef9ebac4395a157eb06bd110a64e7481f82331e8f65e908936df826c630f57f879ba79686bee0878ac5a
7
- data.tar.gz: bf2a8b2d1d1e23a0d0ba22f21d2b8e228bc238f2eededc1ab4474dff9e0d5f13094ec2c5990f24916a563b28fd75bfa2d745bd728d2f6cda9b31283116d9df34
6
+ metadata.gz: 6c10f947a77e46942b5b062b2f3e1ded108b15f9f3a48202e75681be8590400644f42f6d3f3496061741ed81e8fca9ae314098257f1036d6ac09fee694e9a366
7
+ data.tar.gz: 39b85182513dd1a2b8737785cf5b56f946df171c62462bd39cb32008d52ba7cf2c23d27e91e55998e4b037734838f3eba061d3b96d41c11b2cffe1714d1de838
data/lib/facter.rb CHANGED
@@ -253,23 +253,6 @@ module Facter
253
253
  self
254
254
  end
255
255
 
256
- # Returns a fact object by name. If you use this, you still have to
257
- # call {Facter::Util::Fact#value `value`} on it to retrieve the actual
258
- # value.
259
- #
260
- # @param user_query [String] the name of the fact
261
- #
262
- # @return [Facter::Util::Fact, nil] The fact object, or nil if no fact
263
- # is found.
264
- #
265
- # @api public
266
- def fact(user_query)
267
- user_query = user_query.to_s
268
- resolve_fact(user_query)
269
-
270
- @already_searched[user_query]
271
- end
272
-
273
256
  # Reset search paths for custom and external facts
274
257
  # If config file is set custom and external facts will be reloaded
275
258
  #
@@ -411,9 +394,27 @@ module Facter
411
394
  def value(user_query)
412
395
  user_query = user_query.to_s
413
396
  resolve_fact(user_query)
397
+
414
398
  @already_searched[user_query]&.value
415
399
  end
416
400
 
401
+ # Returns a fact object by name. If you use this, you still have to
402
+ # call {Facter::Util::Fact#value `value`} on it to retrieve the actual
403
+ # value.
404
+ #
405
+ # @param user_query [String] the name of the fact
406
+ #
407
+ # @return [Facter::Util::Fact, nil] The fact object, or nil if no fact
408
+ # is found.
409
+ #
410
+ # @api public
411
+ def fact(user_query)
412
+ user_query = user_query.to_s
413
+ resolve_fact(user_query)
414
+
415
+ @already_searched[user_query]
416
+ end
417
+
417
418
  # Returns Facter version
418
419
  #
419
420
  # @return [String] Current version
@@ -545,15 +546,14 @@ module Facter
545
546
  # @return [ResolvedFact]
546
547
  def resolve_fact(user_query)
547
548
  user_query = user_query.to_s
548
- resolved_facts = Facter::FactManager.instance.resolve_facts([user_query])
549
+ resolved_facts = Facter::FactManager.instance.resolve_fact(user_query)
549
550
  # we must make a distinction between custom facts that return nil and nil facts
550
551
  # Nil facts should not be packaged as ResolvedFacts! (add_fact_to_searched_facts packages facts)
551
552
  resolved_facts = resolved_facts.reject { |fact| fact.type == :nil }
552
553
  fact_collection = FactCollection.new.build_fact_collection!(resolved_facts)
553
- splitted_user_query = Facter::Utils.split_user_query(user_query)
554
554
 
555
555
  begin
556
- value = fact_collection.value(*splitted_user_query)
556
+ value = fact_collection.value(user_query)
557
557
  add_fact_to_searched_facts(user_query, value)
558
558
  rescue KeyError
559
559
  nil
@@ -94,11 +94,15 @@ module Facter
94
94
  end
95
95
  log_stderr(stderr, command, logger)
96
96
  rescue StandardError => e
97
- return '' if logger
97
+ message = "Failed while executing '#{command}': #{e.message}"
98
+ if logger
99
+ @log.debug(message)
100
+ return ''
101
+ end
102
+
98
103
  return on_fail unless on_fail == :raise
99
104
 
100
- raise Facter::Core::Execution::ExecutionFailure.new,
101
- "Failed while executing '#{command}': #{e.message}"
105
+ raise Facter::Core::Execution::ExecutionFailure.new, message
102
106
  end
103
107
 
104
108
  [out.strip, stderr]
@@ -11,6 +11,8 @@ module Facter
11
11
  module Core
12
12
  module Execution
13
13
  class Popen3
14
+ @log ||= Log.new(self)
15
+
14
16
  def self.popen_rune(cmd, opts, child_io, parent_io) # :nodoc:
15
17
  pid = spawn(*cmd, opts)
16
18
  child_io.each(&:close)
@@ -20,7 +22,17 @@ module Facter
20
22
  return yield(*result)
21
23
  ensure
22
24
  parent_io.each(&:close)
23
- Process.wait(pid)
25
+ begin
26
+ Process.wait(pid)
27
+ rescue Errno::ENOENT
28
+ # For some reason, the first Process.wait executed in JRuby
29
+ # always fails with ENOENT. However, the command output is
30
+ # filled in so we just need to silently continue.
31
+ # https://github.com/jruby/jruby/issues/5971
32
+ raise unless RUBY_PLATFORM == 'java'
33
+
34
+ @log.debug('Caught ENOENT during Process.wait on JRuby, continuing...')
35
+ end
24
36
  end
25
37
  end
26
38
  result
@@ -106,6 +106,11 @@ module LegacyFacter
106
106
  @loaded = false
107
107
  end
108
108
 
109
+ def custom_fact(fact_name)
110
+ internal_loader.load(fact_name)
111
+ @custom_facts = @facts.select { |_k, v| v.options[:fact_type] == :custom }
112
+ end
113
+
109
114
  # Builds a hash of custom facts
110
115
  def custom_facts
111
116
  return @custom_facts if @valid_custom_facts
@@ -5,7 +5,10 @@ module LegacyFacter
5
5
  module Normalization
6
6
  class NormalizationError < StandardError; end
7
7
 
8
- VALID_TYPES = [Integer, Float, TrueClass, FalseClass, NilClass, Symbol, String, Array, Hash].freeze
8
+ # load Date and Time classes
9
+ require 'time'
10
+
11
+ VALID_TYPES = [Integer, Float, TrueClass, FalseClass, NilClass, Symbol, String, Array, Hash, Date, Time].freeze
9
12
 
10
13
  module_function
11
14
 
@@ -16,8 +19,10 @@ module LegacyFacter
16
19
  # @return [void]
17
20
  def normalize(value)
18
21
  case value
19
- when Integer, Float, TrueClass, FalseClass, NilClass, Symbol, Date
22
+ when Integer, Float, TrueClass, FalseClass, NilClass, Symbol
20
23
  value
24
+ when Date, Time
25
+ value.iso8601
21
26
  when String
22
27
  normalize_string(value)
23
28
  when Array
@@ -6,10 +6,17 @@ module Facts
6
6
  class Provider
7
7
  FACT_NAME = 'cloud.provider'
8
8
 
9
+ def initialize
10
+ @virtual = Facter::Util::Facts::VirtualDetector.new
11
+ end
12
+
9
13
  def call_the_resolver
10
- az_metadata = Facter::Resolvers::Az.resolve(:metadata)
14
+ provider = case @virtual.platform
15
+ when 'hyperv'
16
+ 'azure' unless Facter::Resolvers::Az.resolve(:metadata).empty?
17
+ end
11
18
 
12
- Facter::ResolvedFact.new(FACT_NAME, az_metadata&.empty? ? nil : 'azure')
19
+ Facter::ResolvedFact.new(FACT_NAME, provider)
13
20
  end
14
21
  end
15
22
  end
@@ -8,6 +8,7 @@ module Facts
8
8
 
9
9
  def initialize
10
10
  @log = Facter::Log.new(self)
11
+ @virtual = Facter::Util::Facts::VirtualDetector.new
11
12
  end
12
13
 
13
14
  def call_the_resolver
@@ -28,10 +29,7 @@ module Facts
28
29
  private
29
30
 
30
31
  def xen?
31
- Facter::Resolvers::VirtWhat.resolve(:vm) =~ /xen/ ||
32
- Facter::Resolvers::Xen.resolve(:vm) =~ /xen/ ||
33
- discover_hypervisor == 'xenhvm' ||
34
- Facter::Resolvers::Lspci.resolve(:vm) =~ /xen/
32
+ @virtual.platform =~ /xen/
35
33
  end
36
34
 
37
35
  def hvm?
@@ -17,7 +17,7 @@ module Facts
17
17
  fact_value = %i[
18
18
  chassis_serial control_domain domain_name
19
19
  domain_uuid role_control role_io role_root role_service
20
- ].map! { |key| [key, Facter::Resolvers::Solaris::Ldom.resolve(key)] }.to_h
20
+ ].map! { |key| [key, Facter::Utils.try_to_bool(Facter::Resolvers::Solaris::Ldom.resolve(key))] }.to_h
21
21
 
22
22
  Facter::ResolvedFact.new(FACT_NAME, fact_value)
23
23
  end
@@ -27,7 +27,7 @@ module Facts
27
27
 
28
28
  {
29
29
  brand: current_zone[:brand],
30
- id: current_zone[:id],
30
+ id: Facter::Utils.try_to_int(current_zone[:id]),
31
31
  ip_type: current_zone[:iptype],
32
32
  name: current_zone[:name],
33
33
  uuid: current_zone[:uuid]
@@ -6,7 +6,7 @@ module Facts
6
6
  FACT_NAME = 'mountpoints'
7
7
 
8
8
  def call_the_resolver
9
- mountpoints = Facter::Resolvers::Mountpoints.resolve(FACT_NAME.to_sym)
9
+ mountpoints = Facter::Resolvers::Solaris::Mountpoints.resolve(FACT_NAME.to_sym)
10
10
  return Facter::ResolvedFact.new(FACT_NAME, nil) unless mountpoints
11
11
 
12
12
  fact = {}
@@ -5,10 +5,6 @@ module Facts
5
5
  class AzMetadata
6
6
  FACT_NAME = 'az_metadata'
7
7
 
8
- def initialize
9
- @virtual = Facter::Util::Facts::VirtualDetector.new
10
- end
11
-
12
8
  def call_the_resolver
13
9
  return Facter::ResolvedFact.new(FACT_NAME, nil) unless azure_hypervisor?
14
10
 
@@ -20,7 +16,7 @@ module Facts
20
16
  private
21
17
 
22
18
  def azure_hypervisor?
23
- @virtual.platform == 'hyperv'
19
+ Facter::Resolvers::Virtualization.resolve(:virtual) == 'hyperv'
24
20
  end
25
21
  end
26
22
  end
@@ -7,9 +7,13 @@ module Facts
7
7
  FACT_NAME = 'cloud.provider'
8
8
 
9
9
  def call_the_resolver
10
- az_metadata = Facter::Resolvers::Az.resolve(:metadata)
10
+ virtual = Facter::Resolvers::Virtualization.resolve(:virtual)
11
+ provider = case virtual
12
+ when 'hyperv'
13
+ 'azure' unless Facter::Resolvers::Az.resolve(:metadata).empty?
14
+ end
11
15
 
12
- Facter::ResolvedFact.new(FACT_NAME, az_metadata&.empty? ? nil : 'azure')
16
+ Facter::ResolvedFact.new(FACT_NAME, provider)
13
17
  end
14
18
  end
15
19
  end
@@ -20,10 +20,9 @@ module Facter
20
20
  .reject(&:user_query)
21
21
  .uniq(&:name)
22
22
  else
23
- resolved_facts
24
- .select { |resolved_fact| searched_fact.name.eql?(resolved_fact.name) }
25
- .reject(&:user_query)
26
- .uniq(&:name)
23
+ resolved_facts.select do |resolved_fact|
24
+ valid_fact(searched_fact, resolved_fact)
25
+ end.reject(&:user_query).uniq(&:name)
27
26
  end
28
27
  end
29
28
 
@@ -33,5 +32,23 @@ module Facter
33
32
  matched_fact.filter_tokens = searched_fact.filter_tokens
34
33
  end
35
34
  end
35
+
36
+ private_class_method def self.valid_fact(searched_fact, resolved_fact)
37
+ return false unless searched_fact.name.eql?(resolved_fact.name)
38
+
39
+ if searched_fact.filter_tokens.any?
40
+ case resolved_fact.value
41
+ when Array, Hash
42
+ begin
43
+ resolved_fact.value.dig(*searched_fact.filter_tokens)
44
+ rescue TypeError
45
+ return false
46
+ end
47
+ else
48
+ return false
49
+ end
50
+ end
51
+ true
52
+ end
36
53
  end
37
54
  end
@@ -10,20 +10,23 @@ module Facter
10
10
  @external_facts = load_external_facts
11
11
  end
12
12
 
13
+ def load_fact(fact_name)
14
+ build_custom_facts(LegacyFacter.collection.custom_fact(fact_name)) || []
15
+ end
16
+
13
17
  private
14
18
 
15
19
  def load_custom_facts
16
- custom_facts = []
17
-
18
20
  custom_facts_to_load = LegacyFacter.collection.custom_facts
21
+ build_custom_facts(custom_facts_to_load) || []
22
+ end
19
23
 
20
- custom_facts_to_load&.each do |k, v|
24
+ def build_custom_facts(custom_facts_to_load)
25
+ custom_facts_to_load&.map do |k, v|
21
26
  loaded_fact = LoadedFact.new(k.to_s, nil, :custom)
22
27
  loaded_fact.is_env = v.options[:is_env] if v.options[:is_env]
23
- custom_facts << loaded_fact
28
+ loaded_fact
24
29
  end
25
-
26
- custom_facts
27
30
  end
28
31
 
29
32
  def load_external_facts
@@ -11,38 +11,21 @@ module Facter
11
11
 
12
12
  @internal_facts = []
13
13
  @external_facts = []
14
+ @custom_facts = []
14
15
  @facts = []
15
- end
16
16
 
17
- def load(options)
18
17
  @internal_loader ||= InternalFactLoader.new
19
18
  @external_fact_loader ||= ExternalFactLoader.new
19
+ end
20
20
 
21
- @facts = []
22
- @external_facts = []
23
-
21
+ def load(options)
24
22
  @internal_facts = load_internal_facts(options)
23
+ @custom_facts = load_custom_facts(options)
25
24
  @external_facts = load_external_facts(options)
26
25
 
27
26
  filter_env_facts
28
27
 
29
- @facts = @internal_facts + @external_facts
30
- end
31
-
32
- private
33
-
34
- def filter_env_facts
35
- env_fact_names = @external_facts.select { |fact| fact.is_env == true }.map(&:name)
36
- return unless env_fact_names.any?
37
-
38
- @internal_facts.delete_if do |fact|
39
- if env_fact_names.include?(fact.name)
40
- @log.debug("Reading #{fact.name} fact from environment variable")
41
- true
42
- else
43
- false
44
- end
45
- end
28
+ @facts = @internal_facts + @external_facts + @custom_facts
46
29
  end
47
30
 
48
31
  def load_internal_facts(options)
@@ -60,23 +43,43 @@ module Facter
60
43
  block_facts(internal_facts, options)
61
44
  end
62
45
 
46
+ def load_custom_fact(options, fact_name)
47
+ return [] unless options[:custom_facts]
48
+
49
+ custom_facts = @external_fact_loader.load_fact(fact_name)
50
+ block_facts(custom_facts, options)
51
+ end
52
+
53
+ def load_custom_facts(options)
54
+ return [] unless options[:custom_facts]
55
+
56
+ @log.debug('Loading custom facts')
57
+ custom_facts = @external_fact_loader.custom_facts
58
+ block_facts(custom_facts, options)
59
+ end
60
+
63
61
  def load_external_facts(options)
62
+ return [] unless options[:external_facts]
63
+
64
64
  @log.debug('Loading external facts')
65
- external_facts = []
65
+ external_facts = @external_fact_loader.external_facts
66
+ block_facts(external_facts, options)
67
+ end
66
68
 
67
- if options[:custom_facts]
68
- @log.debug('Loading custom facts')
69
- external_facts += @external_fact_loader.custom_facts
70
- end
69
+ private
71
70
 
72
- external_facts = block_facts(external_facts, options)
71
+ def filter_env_facts
72
+ env_fact_names = @external_facts.select { |fact| fact.is_env == true }.map(&:name)
73
+ return unless env_fact_names.any?
73
74
 
74
- if options[:external_facts]
75
- @log.debug('Loading external facts')
76
- external_facts += @external_fact_loader.external_facts
75
+ @internal_facts.delete_if do |fact|
76
+ if env_fact_names.include?(fact.name)
77
+ @log.debug("Reading #{fact.name} fact from environment variable")
78
+ true
79
+ else
80
+ false
81
+ end
77
82
  end
78
-
79
- external_facts
80
83
  end
81
84
 
82
85
  def block_facts(facts, options)