facter 4.1.1 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/lib/facter.rb +1 -1
  3. data/lib/facter/config.rb +2 -0
  4. data/lib/facter/custom_facts/core/execution/posix.rb +2 -2
  5. data/lib/facter/custom_facts/core/execution/windows.rb +1 -1
  6. data/lib/facter/custom_facts/util/directory_loader.rb +1 -1
  7. data/lib/facter/custom_facts/util/windows_root.rb +2 -1
  8. data/lib/facter/facts/freebsd/is_virtual.rb +1 -5
  9. data/lib/facter/facts/freebsd/virtual.rb +1 -2
  10. data/lib/facter/facts/linux/az_metadata.rb +1 -5
  11. data/lib/facter/facts/linux/cloud/provider.rb +1 -5
  12. data/lib/facter/facts/linux/ec2_metadata.rb +1 -5
  13. data/lib/facter/facts/linux/ec2_userdata.rb +1 -5
  14. data/lib/facter/facts/linux/hypervisors/xen.rb +1 -2
  15. data/lib/facter/facts/linux/is_virtual.rb +1 -5
  16. data/lib/facter/facts/linux/virtual.rb +1 -2
  17. data/lib/facter/facts/macosx/os/macosx/version.rb +6 -3
  18. data/lib/facter/facts/windows/az_metadata.rb +1 -1
  19. data/lib/facter/facts/windows/cloud/provider.rb +1 -1
  20. data/lib/facter/facts/windows/ec2_metadata.rb +1 -1
  21. data/lib/facter/facts/windows/ec2_userdata.rb +1 -1
  22. data/lib/facter/facts/windows/gce.rb +1 -1
  23. data/lib/facter/facts/windows/hypervisors/hyperv.rb +1 -1
  24. data/lib/facter/facts/windows/hypervisors/kvm.rb +2 -1
  25. data/lib/facter/facts/windows/hypervisors/virtualbox.rb +2 -2
  26. data/lib/facter/facts/windows/hypervisors/vmware.rb +1 -1
  27. data/lib/facter/facts/windows/hypervisors/xen.rb +3 -1
  28. data/lib/facter/facts/windows/is_virtual.rb +15 -0
  29. data/lib/facter/facts/windows/virtual.rb +15 -0
  30. data/lib/facter/framework/core/cache_manager.rb +2 -2
  31. data/lib/facter/framework/core/fact/external/external_fact_manager.rb +0 -1
  32. data/lib/facter/framework/core/fact/internal/internal_fact_manager.rb +41 -39
  33. data/lib/facter/framework/core/fact_filter.rb +4 -14
  34. data/lib/facter/framework/core/file_loader.rb +1 -1
  35. data/lib/facter/framework/parsers/query_parser.rb +5 -12
  36. data/lib/facter/models/fact_collection.rb +20 -3
  37. data/lib/facter/models/resolved_fact.rb +2 -3
  38. data/lib/facter/models/searched_fact.rb +2 -3
  39. data/lib/facter/resolvers/linux/networking.rb +18 -0
  40. data/lib/facter/resolvers/mountpoints.rb +16 -8
  41. data/lib/facter/resolvers/partitions.rb +1 -1
  42. data/lib/facter/resolvers/ruby.rb +1 -1
  43. data/lib/facter/resolvers/windows/ffi/identity_ffi.rb +5 -0
  44. data/lib/facter/resolvers/windows/identity.rb +1 -6
  45. data/lib/facter/resolvers/windows/virtualization.rb +46 -44
  46. data/lib/facter/resolvers/xen.rb +6 -1
  47. data/lib/facter/util/facts/posix/virtual_detector.rb +74 -0
  48. data/lib/facter/util/linux/if_inet6.rb +73 -0
  49. data/lib/facter/version.rb +1 -1
  50. metadata +26 -9
  51. data/lib/facter/facts/windows/virtualization/is_virtual.rb +0 -17
  52. data/lib/facter/facts/windows/virtualization/virtual.rb +0 -17
  53. data/lib/facter/framework/core/fact_augmenter.rb +0 -54
  54. data/lib/facter/util/facts/virtual_detector.rb +0 -83
@@ -1,21 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Facter
4
- # Filter inside value of a fact.
5
- # e.g. os.release.major is the user query, os.release is the fact
6
- # and major is the filter criteria inside tha fact
7
4
  class FactFilter
8
- def filter_facts!(searched_facts, user_query)
9
- filter_legacy_facts!(searched_facts) if user_query.empty?
10
- filter_blocked_legacy_facts!(searched_facts)
11
-
12
- searched_facts.each do |fact|
13
- fact.value = if fact.filter_tokens.any? && fact.value.respond_to?(:dig)
14
- fact.value.dig(*fact.filter_tokens)
15
- else
16
- fact.value
17
- end
18
- end
5
+ def filter_facts!(resolved_facts, user_query)
6
+ filter_legacy_facts!(resolved_facts) if user_query.empty?
7
+ filter_blocked_legacy_facts!(resolved_facts)
8
+ resolved_facts
19
9
  end
20
10
 
21
11
  private
@@ -37,6 +37,7 @@ load_dir(['config'])
37
37
  load_dir(['util'])
38
38
  load_dir(%w[util resolvers])
39
39
  load_dir(%w[util facts])
40
+ load_dir(%w[util facts posix])
40
41
  load_dir(%w[util resolvers networking])
41
42
 
42
43
  load_dir(['resolvers'])
@@ -58,5 +59,4 @@ os_hierarchy.each { |operating_system| load_dir(['resolvers', operating_system.d
58
59
  require 'facter/custom_facts/core/legacy_facter'
59
60
  load_dir(%w[framework utils])
60
61
 
61
- require 'facter/framework/core/fact_augmenter'
62
62
  require 'facter/framework/parsers/query_parser'
@@ -41,7 +41,7 @@ module Facter
41
41
  def no_user_query(loaded_facts)
42
42
  searched_facts = []
43
43
  loaded_facts.each do |loaded_fact|
44
- searched_facts << SearchedFact.new(loaded_fact.name, loaded_fact.klass, [], '', loaded_fact.type)
44
+ searched_facts << SearchedFact.new(loaded_fact.name, loaded_fact.klass, '', loaded_fact.type)
45
45
  end
46
46
  searched_facts
47
47
  end
@@ -59,7 +59,7 @@ module Facter
59
59
  return resolvable_fact_list if resolvable_fact_list.any?
60
60
  end
61
61
 
62
- resolvable_fact_list << SearchedFact.new(query, nil, [], query, :nil) if resolvable_fact_list.empty?
62
+ resolvable_fact_list << SearchedFact.new(query, nil, query, :nil) if resolvable_fact_list.empty?
63
63
 
64
64
  resolvable_fact_list
65
65
  end
@@ -73,7 +73,7 @@ module Facter
73
73
 
74
74
  next unless found_fact?(loaded_fact.name, query_fact)
75
75
 
76
- searched_fact = construct_loaded_fact(query_tokens, query_token_range, loaded_fact)
76
+ searched_fact = construct_loaded_fact(query_tokens, loaded_fact)
77
77
  resolvable_fact_list << searched_fact
78
78
  end
79
79
 
@@ -93,23 +93,16 @@ module Facter
93
93
  true
94
94
  end
95
95
 
96
- def construct_loaded_fact(query_tokens, query_token_range, loaded_fact)
97
- filter_tokens = construct_filter_tokens(query_tokens, query_token_range)
96
+ def construct_loaded_fact(query_tokens, loaded_fact)
98
97
  user_query = @query_list.any? ? query_tokens.join('.') : ''
99
98
  fact_name = loaded_fact.name.to_s
100
99
  klass_name = loaded_fact.klass
101
100
  type = loaded_fact.type
102
- sf = SearchedFact.new(fact_name, klass_name, filter_tokens, user_query, type)
101
+ sf = SearchedFact.new(fact_name, klass_name, user_query, type)
103
102
  sf.file = loaded_fact.file
104
103
 
105
104
  sf
106
105
  end
107
-
108
- def construct_filter_tokens(query_tokens, query_token_range)
109
- query_tokens.drop(query_token_range.size).map do |token|
110
- token =~ /^[0-9]+$/ ? token.to_i : token
111
- end
112
- end
113
106
  end
114
107
  end
115
108
  end
@@ -11,6 +11,12 @@ module Facter
11
11
  deep_to_h.to_yaml
12
12
  end
13
13
 
14
+ # Transorms a list of {Facter::ResolvedFact} into a nested collection.
15
+ # @param facts [Array<Facter::ResolvedFact>]
16
+ #
17
+ # @return [FactCollection]
18
+ #
19
+ # @api private
14
20
  def build_fact_collection!(facts)
15
21
  facts.each do |fact|
16
22
  next if %i[core legacy].include?(fact.type) && fact.value.nil?
@@ -23,15 +29,26 @@ module Facter
23
29
 
24
30
  def dig_fact(user_query)
25
31
  value(user_query)
26
- rescue KeyError
32
+ rescue KeyError, TypeError
27
33
  nil
28
34
  end
29
35
 
36
+ # Collection#fetch implementation for nested collections.
37
+ # @param user_query [String] the search terms, separated by "."
38
+ #
39
+ # @return [String]
40
+ #
41
+ # @example for fact_collection = { "os": { "name": "Darwin" } }
42
+ # fact_collection.fetch("os.name") #=> "Darwin"
43
+ #
44
+ # @api private
30
45
  def value(user_query)
31
46
  fetch(user_query) do
32
47
  split_user_query = Facter::Utils.split_user_query(user_query)
33
48
  split_user_query.reduce(self) do |memo, key|
34
- memo.fetch(key) { memo.fetch(key.to_s) } if memo.is_a?(Hash) || memo.is_a?(Array)
49
+ raise KeyError unless memo.respond_to?(:fetch)
50
+
51
+ memo.fetch(key) { memo.fetch(key.to_s) }
35
52
  end
36
53
  end
37
54
  end
@@ -60,7 +77,7 @@ module Facter
60
77
 
61
78
  def bury_fact(fact)
62
79
  split_fact_name = extract_fact_name(fact)
63
- bury(*split_fact_name + fact.filter_tokens << fact.value)
80
+ bury(*split_fact_name << fact.value)
64
81
  rescue NoMethodError
65
82
  @log.error("#{fact.type.to_s.capitalize} fact `#{fact.name}` cannot be added to collection."\
66
83
  ' The format of this fact is incompatible with other'\
@@ -3,14 +3,13 @@
3
3
  module Facter
4
4
  class ResolvedFact
5
5
  attr_reader :name, :type
6
- attr_accessor :user_query, :filter_tokens, :value, :file
6
+ attr_accessor :user_query, :value, :file
7
7
 
8
- def initialize(name, value = '', type = :core, user_query = nil, filter_tokens = [])
8
+ def initialize(name, value = '', type = :core, user_query = nil)
9
9
  @name = name
10
10
  @value = Utils.deep_stringify_keys(value)
11
11
  @type = type
12
12
  @user_query = user_query
13
- @filter_tokens = filter_tokens
14
13
  end
15
14
 
16
15
  def legacy?
@@ -2,13 +2,12 @@
2
2
 
3
3
  module Facter
4
4
  class SearchedFact
5
- attr_reader :name, :fact_class, :filter_tokens, :user_query, :type
5
+ attr_reader :name, :fact_class, :user_query, :type
6
6
  attr_accessor :file
7
7
 
8
- def initialize(fact_name, fact_class, filter_tokens, user_query, type)
8
+ def initialize(fact_name, fact_class, user_query, type)
9
9
  @name = fact_name
10
10
  @fact_class = fact_class
11
- @filter_tokens = filter_tokens
12
11
  @user_query = user_query
13
12
  @type = type
14
13
  end
@@ -20,6 +20,7 @@ module Facter
20
20
  add_info_from_routing_table
21
21
  retrieve_primary_interface
22
22
  Facter::Util::Resolvers::Networking.expand_main_bindings(@fact_list)
23
+ add_flags
23
24
  @fact_list[fact_name]
24
25
  end
25
26
 
@@ -72,6 +73,23 @@ module Facter
72
73
  compare_ips(routes6, :bindings6)
73
74
  end
74
75
 
76
+ def add_flags
77
+ flags = Facter::Util::Linux::IfInet6.read_flags
78
+ flags.each_pair do |iface, ips|
79
+ next unless @fact_list[:interfaces].key?(iface)
80
+
81
+ ips.each_pair do |ip, ip_flags|
82
+ next unless @fact_list[:interfaces][iface].key?(:bindings6)
83
+
84
+ @fact_list[:interfaces][iface][:bindings6].each do |binding|
85
+ next unless binding[:address] == ip
86
+
87
+ binding[:flags] = ip_flags
88
+ end
89
+ end
90
+ end
91
+ end
92
+
75
93
  def compare_ips(routes, binding_key)
76
94
  routes.each do |route|
77
95
  next unless @fact_list[:interfaces].key?(route[:interface])
@@ -67,10 +67,24 @@ module Facter
67
67
  end
68
68
 
69
69
  def get_mount_sizes(mount)
70
- stats = Facter::Util::Resolvers::FilesystemHelper.read_mountpoint_stats(mount[:path])
70
+ begin
71
+ stats = Facter::Util::Resolvers::FilesystemHelper.read_mountpoint_stats(mount[:path])
72
+ get_bytes_data(mount, stats)
73
+ rescue Sys::Filesystem::Error => e
74
+ @log.debug("Could not get stats for mountpoint #{mount[:path]}, got #{e}")
75
+ mount[:size_bytes] = mount[:available_bytes] = mount[:used_bytes] = 0
76
+ end
77
+
78
+ populate_mount(mount)
79
+ end
71
80
 
72
- get_bytes_data(mount, stats)
81
+ def get_bytes_data(mount, stats)
82
+ mount[:size_bytes] = stats.bytes_total.abs
83
+ mount[:available_bytes] = stats.bytes_available.abs
84
+ mount[:used_bytes] = stats.bytes_used.abs
85
+ end
73
86
 
87
+ def populate_mount(mount)
74
88
  total_bytes = mount[:used_bytes] + mount[:available_bytes]
75
89
  mount[:capacity] = Facter::Util::Resolvers::FilesystemHelper.compute_capacity(mount[:used_bytes], total_bytes)
76
90
 
@@ -78,12 +92,6 @@ module Facter
78
92
  mount[:available] = Facter::Util::Facts::UnitConverter.bytes_to_human_readable(mount[:available_bytes])
79
93
  mount[:used] = Facter::Util::Facts::UnitConverter.bytes_to_human_readable(mount[:used_bytes])
80
94
  end
81
-
82
- def get_bytes_data(mount, stats)
83
- mount[:size_bytes] = stats.bytes_total.abs
84
- mount[:available_bytes] = stats.bytes_available.abs
85
- mount[:used_bytes] = stats.bytes_used.abs
86
- end
87
95
  end
88
96
  end
89
97
  end
@@ -109,7 +109,7 @@ module Facter
109
109
 
110
110
  output = Facter::Core::Execution.execute("which #{command}", logger: log)
111
111
 
112
- blkid_and_lsblk[:command_exists_key] = !output.empty?
112
+ blkid_and_lsblk[command_exists_key] = !output.empty?
113
113
  end
114
114
 
115
115
  def execute_and_extract_blkid_info
@@ -13,7 +13,7 @@ module Facter
13
13
  end
14
14
 
15
15
  def retrieve_ruby_information(fact_name)
16
- @fact_list[:sitedir] = RbConfig::CONFIG['sitelibdir']
16
+ @fact_list[:sitedir] = RbConfig::CONFIG['sitelibdir'] if RbConfig::CONFIG['sitedir']
17
17
  @fact_list[:platform] = RUBY_PLATFORM
18
18
  @fact_list[:version] = RUBY_VERSION
19
19
  @fact_list[fact_name]
@@ -12,4 +12,9 @@ module IdentityFFI
12
12
  ffi_convention :stdcall
13
13
  ffi_lib :shell32
14
14
  attach_function :IsUserAnAdmin, [], :win32_bool
15
+
16
+ def self.privileged?
17
+ result = self.IsUserAnAdmin()
18
+ result && result != FFI::WIN32FALSE
19
+ end
15
20
  end
@@ -31,12 +31,7 @@ module Facter
31
31
  return
32
32
  end
33
33
 
34
- { user: name_ptr.read_wide_string_with_length(size_ptr.read_uint32), privileged: privileged? }
35
- end
36
-
37
- def privileged?
38
- result = IdentityFFI::IsUserAnAdmin()
39
- result && result != FFI::WIN32FALSE
34
+ { user: name_ptr.read_wide_string_with_length(size_ptr.read_uint32), privileged: IdentityFFI.privileged? }
40
35
  end
41
36
 
42
37
  def retrieve_facts(fact_name)
@@ -2,63 +2,65 @@
2
2
 
3
3
  module Facter
4
4
  module Resolvers
5
- class Virtualization < BaseResolver
6
- @log = Facter::Log.new(self)
5
+ module Windows
6
+ class Virtualization < BaseResolver
7
+ @log = Facter::Log.new(self)
7
8
 
8
- init_resolver
9
+ init_resolver
9
10
 
10
- class << self
11
- # Virtual
12
- # Is_Virtual
11
+ class << self
12
+ # Virtual
13
+ # Is_Virtual
13
14
 
14
- MODEL_HASH = { 'VirtualBox' => 'virtualbox', 'VMware' => 'vmware', 'KVM' => 'kvm',
15
- 'Bochs' => 'bochs', 'Google' => 'gce', 'OpenStack' => 'openstack' }.freeze
15
+ MODEL_HASH = { 'VirtualBox' => 'virtualbox', 'VMware' => 'vmware', 'KVM' => 'kvm',
16
+ 'Bochs' => 'bochs', 'Google' => 'gce', 'OpenStack' => 'openstack' }.freeze
16
17
 
17
- private
18
+ private
18
19
 
19
- def post_resolve(fact_name, _options)
20
- @fact_list.fetch(fact_name) { read_fact_from_computer_system(fact_name) }
21
- end
22
-
23
- def read_fact_from_computer_system(fact_name)
24
- win = Facter::Util::Windows::Win32Ole.new
25
- comp = win.exec_query('SELECT Manufacturer,Model,OEMStringArray FROM Win32_ComputerSystem')
26
- unless comp
27
- @log.debug 'WMI query returned no results for Win32_ComputerSystem with values'\
28
- ' Manufacturer, Model and OEMStringArray.'
29
- return
20
+ def post_resolve(fact_name, _options)
21
+ @fact_list.fetch(fact_name) { read_fact_from_computer_system(fact_name) }
30
22
  end
31
23
 
32
- build_fact_list(comp)
33
- @fact_list[fact_name]
34
- end
24
+ def read_fact_from_computer_system(fact_name)
25
+ win = Facter::Util::Windows::Win32Ole.new
26
+ comp = win.exec_query('SELECT Manufacturer,Model,OEMStringArray FROM Win32_ComputerSystem')
27
+ unless comp
28
+ @log.debug 'WMI query returned no results for Win32_ComputerSystem with values'\
29
+ ' Manufacturer, Model and OEMStringArray.'
30
+ return
31
+ end
35
32
 
36
- def determine_hypervisor_by_model(comp)
37
- MODEL_HASH[MODEL_HASH.keys.find { |key| comp.Model =~ /^#{key}/ }]
38
- end
33
+ build_fact_list(comp)
34
+ @fact_list[fact_name]
35
+ end
39
36
 
40
- def determine_hypervisor_by_manufacturer(comp)
41
- manufacturer = comp.Manufacturer
42
- if comp.Model =~ /^Virtual Machine/ && manufacturer =~ /^Microsoft/
43
- 'hyperv'
44
- elsif manufacturer =~ /^Xen/
45
- 'xen'
46
- elsif manufacturer =~ /^Amazon EC2/
47
- 'kvm'
48
- else
49
- 'physical'
37
+ def determine_hypervisor_by_model(comp)
38
+ MODEL_HASH[MODEL_HASH.keys.find { |key| comp.Model =~ /^#{key}/ }]
39
+ end
40
+
41
+ def determine_hypervisor_by_manufacturer(comp)
42
+ manufacturer = comp.Manufacturer
43
+ if comp.Model =~ /^Virtual Machine/ && manufacturer =~ /^Microsoft/
44
+ 'hyperv'
45
+ elsif manufacturer =~ /^Xen/
46
+ 'xen'
47
+ elsif manufacturer =~ /^Amazon EC2/
48
+ 'kvm'
49
+ else
50
+ 'physical'
51
+ end
50
52
  end
51
- end
52
53
 
53
- def build_fact_list(comp)
54
- @fact_list[:oem_strings] = []
55
- @fact_list[:oem_strings] += comp.to_enum.map(&:OEMStringArray).flatten
54
+ def build_fact_list(comp)
55
+ @fact_list[:oem_strings] = []
56
+ @fact_list[:oem_strings] += comp.to_enum.map(&:OEMStringArray).flatten
56
57
 
57
- comp = comp.to_enum.first
58
- hypervisor = determine_hypervisor_by_model(comp) || determine_hypervisor_by_manufacturer(comp)
58
+ comp = comp.to_enum.first
59
+ hypervisor = determine_hypervisor_by_model(comp) || determine_hypervisor_by_manufacturer(comp)
59
60
 
60
- @fact_list[:virtual] = hypervisor
61
- @fact_list[:is_virtual] = hypervisor.include?('physical') ? false : true
61
+ @fact_list[:virtual] = hypervisor
62
+ @fact_list[:is_virtual] = hypervisor.include?('physical') ? false : true
63
+ end
62
64
  end
63
65
  end
64
66
  end
@@ -56,7 +56,12 @@ module Facter
56
56
  end
57
57
 
58
58
  def find_command
59
- return XEN_TOOLSTACK if File.exist?(XEN_TOOLSTACK)
59
+ num_stacks = 0
60
+ XEN_COMMANDS.each do |command|
61
+ num_stacks += 1 if File.exist?(command)
62
+ end
63
+
64
+ return XEN_TOOLSTACK if num_stacks > 1 && File.exist?(XEN_TOOLSTACK)
60
65
 
61
66
  XEN_COMMANDS.each { |command| return command if File.exist?(command) }
62
67
  end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facter
4
+ module Util
5
+ module Facts
6
+ module Posix
7
+ module VirtualDetector
8
+ class << self
9
+ def platform
10
+ @@fact_value ||= check_docker_lxc || check_freebsd || check_gce || retrieve_from_virt_what
11
+ @@fact_value ||= check_vmware || check_open_vz || check_vserver || check_xen || check_other_facts
12
+ @@fact_value ||= check_lspci || 'physical'
13
+
14
+ @@fact_value
15
+ end
16
+
17
+ private
18
+
19
+ def check_docker_lxc
20
+ Facter::Resolvers::Containers.resolve(:vm)
21
+ end
22
+
23
+ def check_gce
24
+ bios_vendor = Facter::Resolvers::Linux::DmiBios.resolve(:bios_vendor)
25
+ 'gce' if bios_vendor&.include?('Google')
26
+ end
27
+
28
+ def check_vmware
29
+ Facter::Resolvers::Vmware.resolve(:vm)
30
+ end
31
+
32
+ def retrieve_from_virt_what
33
+ Facter::Resolvers::VirtWhat.resolve(:vm)
34
+ end
35
+
36
+ def check_open_vz
37
+ Facter::Resolvers::OpenVz.resolve(:vm)
38
+ end
39
+
40
+ def check_vserver
41
+ Facter::Resolvers::VirtWhat.resolve(:vserver)
42
+ end
43
+
44
+ def check_xen
45
+ Facter::Resolvers::Xen.resolve(:vm)
46
+ end
47
+
48
+ def check_freebsd
49
+ return unless Object.const_defined?('Facter::Resolvers::Freebsd::Virtual')
50
+
51
+ Facter::Resolvers::Freebsd::Virtual.resolve(:vm)
52
+ end
53
+
54
+ def check_other_facts
55
+ bios_vendor = Facter::Resolvers::Linux::DmiBios.resolve(:bios_vendor)
56
+ return 'kvm' if bios_vendor&.include?('Amazon EC2')
57
+
58
+ product_name = Facter::Resolvers::Linux::DmiBios.resolve(:product_name)
59
+ return unless product_name
60
+
61
+ Facter::Util::Facts::HYPERVISORS_HASH.each { |key, value| return value if product_name.include?(key) }
62
+
63
+ nil
64
+ end
65
+
66
+ def check_lspci
67
+ Facter::Resolvers::Lspci.resolve(:vm)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end