facter 4.0.52 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
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)