facter 4.0.35 → 4.0.36

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/facter/custom_facts/util/directory_loader.rb +3 -1
  3. data/lib/facter/fact_groups.conf +140 -1
  4. data/lib/facter/facts/aix/disks.rb +17 -2
  5. data/lib/facter/facts/aix/networking/scope6.rb +3 -1
  6. data/lib/facter/facts/aix/scope6_interfaces.rb +0 -2
  7. data/lib/facter/facts/aix/serialnumber.rb +20 -0
  8. data/lib/facter/facts/aix/sshalgorithmkey.rb +17 -0
  9. data/lib/facter/facts/aix/sshfp_algorithm.rb +20 -0
  10. data/lib/facter/facts/debian/os/distro/release.rb +6 -1
  11. data/lib/facter/facts/freebsd/sshalgorithmkey.rb +17 -0
  12. data/lib/facter/facts/freebsd/sshfp_algorithm.rb +20 -0
  13. data/lib/facter/facts/linux/disks.rb +20 -1
  14. data/lib/facter/facts/linux/dmi/board/asset_tag.rb +19 -0
  15. data/lib/facter/facts/linux/ec2_metadata.rb +5 -3
  16. data/lib/facter/facts/linux/ec2_userdata.rb +5 -3
  17. data/lib/facter/facts/linux/gce.rb +16 -0
  18. data/lib/facter/facts/linux/is_virtual.rb +1 -3
  19. data/lib/facter/facts/linux/networking/scope6.rb +3 -1
  20. data/lib/facter/facts/linux/processors/speed.rb +17 -0
  21. data/lib/facter/facts/linux/scope6_interfaces.rb +1 -2
  22. data/lib/facter/facts/linux/sshfp_algorithm.rb +1 -1
  23. data/lib/facter/facts/linux/xen.rb +28 -0
  24. data/lib/facter/facts/macosx/networking/scope6.rb +3 -1
  25. data/lib/facter/facts/macosx/scope6_interfaces.rb +0 -2
  26. data/lib/facter/facts/macosx/sshfp_algorithm.rb +1 -1
  27. data/lib/facter/facts/solaris/disks.rb +21 -2
  28. data/lib/facter/facts/solaris/hypervisors/ldom.rb +24 -0
  29. data/lib/facter/facts/solaris/hypervisors/zone.rb +39 -0
  30. data/lib/facter/facts/solaris/is_virtual.rb +64 -0
  31. data/lib/facter/facts/solaris/kernelmajversion.rb +1 -1
  32. data/lib/facter/facts/solaris/ldom.rb +35 -0
  33. data/lib/facter/facts/solaris/sshalgorithmkey.rb +17 -0
  34. data/lib/facter/facts/solaris/sshfp_algorithm.rb +20 -0
  35. data/lib/facter/facts/solaris/virtual.rb +60 -0
  36. data/lib/facter/facts/solaris/zones.rb +1 -1
  37. data/lib/facter/facts/windows/ec2_metadata.rb +5 -3
  38. data/lib/facter/facts/windows/ec2_userdata.rb +5 -3
  39. data/lib/facter/facts/windows/gce.rb +16 -0
  40. data/lib/facter/facts/windows/networking/scope6.rb +3 -1
  41. data/lib/facter/facts/windows/sshalgorithmkey.rb +22 -0
  42. data/lib/facter/facts/windows/sshfp_algorithm.rb +25 -0
  43. data/lib/facter/facts_utils/facts_utils.rb +2 -0
  44. data/lib/facter/framework/core/fact/internal/core_fact.rb +2 -0
  45. data/lib/facter/framework/core/fact/internal/internal_fact_manager.rb +10 -25
  46. data/lib/facter/framework/core/fact_filter.rb +13 -0
  47. data/lib/facter/framework/core/fact_loaders/fact_loader.rb +24 -1
  48. data/lib/facter/framework/formatters/legacy_fact_formatter.rb +8 -1
  49. data/lib/facter/framework/formatters/yaml_fact_formatter.rb +1 -1
  50. data/lib/facter/resolvers/aix/serialnumber.rb +37 -0
  51. data/lib/facter/resolvers/dmi_resolver.rb +4 -3
  52. data/lib/facter/resolvers/ec2.rb +4 -18
  53. data/lib/facter/resolvers/gce.rb +54 -0
  54. data/lib/facter/resolvers/memory_resolver.rb +8 -1
  55. data/lib/facter/resolvers/processors_resolver.rb +24 -2
  56. data/lib/facter/resolvers/solaris/ldom.rb +70 -0
  57. data/lib/facter/resolvers/utils/http.rb +68 -0
  58. data/lib/facter/resolvers/xen.rb +28 -0
  59. data/lib/facter/version.rb +1 -1
  60. metadata +25 -2
@@ -28,7 +28,7 @@ module Facts
28
28
  end
29
29
 
30
30
  resolved_facts << Facter::ResolvedFact.new('solaris_zones.zones', zones)
31
- resolved_facts << Facter::ResolvedFact.new('zones', results.count, :legacy)
31
+ resolved_facts << Facter::ResolvedFact.new('zones', results.count.to_s, :legacy)
32
32
 
33
33
  resolved_facts.flatten
34
34
  end
@@ -6,14 +6,16 @@ module Facts
6
6
  FACT_NAME = 'ec2_metadata'
7
7
 
8
8
  def call_the_resolver
9
- return Facter::ResolvedFact.new(FACT_NAME, nil) unless aws?
9
+ return Facter::ResolvedFact.new(FACT_NAME, nil) unless aws_hypervisors?
10
10
 
11
11
  fact_value = Facter::Resolvers::Ec2.resolve(:metadata)
12
12
 
13
- Facter::ResolvedFact.new(FACT_NAME, fact_value.empty? ? nil : fact_value)
13
+ Facter::ResolvedFact.new(FACT_NAME, fact_value&.empty? ? nil : fact_value)
14
14
  end
15
15
 
16
- def aws?
16
+ private
17
+
18
+ def aws_hypervisors?
17
19
  virtual = Facter::Resolvers::Virtualization.resolve(:virtual)
18
20
 
19
21
  virtual == 'kvm' || virtual =~ /xen/
@@ -6,14 +6,16 @@ module Facts
6
6
  FACT_NAME = 'ec2_userdata'
7
7
 
8
8
  def call_the_resolver
9
- return Facter::ResolvedFact.new(FACT_NAME, nil) unless aws?
9
+ return Facter::ResolvedFact.new(FACT_NAME, nil) unless aws_hypervisors?
10
10
 
11
11
  fact_value = Facter::Resolvers::Ec2.resolve(:userdata)
12
12
 
13
- Facter::ResolvedFact.new(FACT_NAME, fact_value.empty? ? nil : fact_value)
13
+ Facter::ResolvedFact.new(FACT_NAME, fact_value&.empty? ? nil : fact_value)
14
14
  end
15
15
 
16
- def aws?
16
+ private
17
+
18
+ def aws_hypervisors?
17
19
  virtual = Facter::Resolvers::Virtualization.resolve(:virtual)
18
20
 
19
21
  virtual == 'kvm' || virtual =~ /xen/
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facts
4
+ module Windows
5
+ class Gce
6
+ FACT_NAME = 'gce'
7
+
8
+ def call_the_resolver
9
+ virtualization = Facter::Resolvers::Virtualization.resolve(:virtual)
10
+
11
+ fact_value = virtualization&.include?('gce') ? Facter::Resolvers::Gce.resolve(:metadata) : nil
12
+ Facter::ResolvedFact.new(FACT_NAME, fact_value)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -5,11 +5,13 @@ module Facts
5
5
  module Networking
6
6
  class Scope6
7
7
  FACT_NAME = 'networking.scope6'
8
+ ALIASES = 'scope6'
8
9
 
9
10
  def call_the_resolver
10
11
  fact_value = Facter::Resolvers::Windows::Networking.resolve(:scope6)
11
12
 
12
- Facter::ResolvedFact.new(FACT_NAME, fact_value)
13
+ [Facter::ResolvedFact.new(FACT_NAME, fact_value),
14
+ Facter::ResolvedFact.new('scope6', fact_value, :legacy)]
13
15
  end
14
16
  end
15
17
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facts
4
+ module Windows
5
+ class Sshalgorithmkey
6
+ FACT_NAME = 'ssh.*key'
7
+ TYPE = :legacy
8
+
9
+ def call_the_resolver
10
+ facts = []
11
+ privileged = Facter::Resolvers::Identity.resolve(:privileged)
12
+
13
+ return facts unless privileged
14
+
15
+ result = Facter::Resolvers::Windows::Ssh.resolve(:ssh)
16
+
17
+ result&.each { |ssh| facts << Facter::ResolvedFact.new("ssh#{ssh.name.to_sym}key", ssh.key, :legacy) }
18
+ facts
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facts
4
+ module Windows
5
+ class SshfpAlgorithm
6
+ FACT_NAME = 'sshfp_.*'
7
+ TYPE = :legacy
8
+
9
+ def call_the_resolver
10
+ facts = []
11
+ privileged = Facter::Resolvers::Identity.resolve(:privileged)
12
+
13
+ return facts unless privileged
14
+
15
+ result = Facter::Resolvers::Windows::Ssh.resolve(:ssh)
16
+
17
+ result&.each do |ssh|
18
+ facts << Facter::ResolvedFact.new("sshfp_#{ssh.name.to_sym}",
19
+ "#{ssh.fingerprint.sha1}\n#{ssh.fingerprint.sha256}", :legacy)
20
+ end
21
+ facts
22
+ end
23
+ end
24
+ end
25
+ end
@@ -6,5 +6,7 @@ module Facter
6
6
  'KVM' => 'kvm', 'Virtual Machine' => 'hyperv', 'RHEV Hypervisor' => 'rhev',
7
7
  'oVirt Node' => 'ovirt', 'HVM domU' => 'xenhvm', 'Bochs' => 'bochs', 'OpenBSD' => 'vmm',
8
8
  'BHYVE' => 'bhyve' }.freeze
9
+
10
+ PHYSICAL_HYPERVISORS = %w[physical xen0 vmware_server vmware_workstation openvzhn vserver_host].freeze
9
11
  end
10
12
  end
@@ -9,6 +9,8 @@ module Facter
9
9
  def create
10
10
  fact_class = @searched_fact.fact_class
11
11
 
12
+ return unless fact_class
13
+
12
14
  fact_class.new.call_the_resolver
13
15
  end
14
16
  end
@@ -6,9 +6,8 @@ module Facter
6
6
 
7
7
  def resolve_facts(searched_facts)
8
8
  internal_searched_facts = filter_internal_facts(searched_facts)
9
- threads = start_threads(internal_searched_facts)
10
- resolved_facts = join_threads(threads, internal_searched_facts)
11
9
 
10
+ resolved_facts = resolve(internal_searched_facts)
12
11
  nil_resolved_facts = resolve_nil_facts(searched_facts)
13
12
 
14
13
  resolved_facts.concat(nil_resolved_facts)
@@ -29,36 +28,22 @@ module Facter
29
28
  resolved_facts
30
29
  end
31
30
 
32
- def start_threads(searched_facts)
33
- threads = []
34
- # only resolve a fact once, even if multiple search facts depend on that fact
31
+ def resolve(searched_facts)
32
+ resolved_facts = []
33
+
35
34
  searched_facts
36
35
  .uniq { |searched_fact| searched_fact.fact_class.name }
37
36
  .each do |searched_fact|
38
- threads << Thread.new do
39
- begin
40
- fact = CoreFact.new(searched_fact)
41
- fact.create
42
- rescue StandardError => e
43
- @@log.log_exception(e)
44
- nil
45
- end
37
+ begin
38
+ fact = CoreFact.new(searched_fact)
39
+ fact_value = fact.create
40
+ resolved_facts << fact_value unless fact_value.nil?
41
+ rescue StandardError => e
42
+ @@log.log_exception(e)
46
43
  end
47
44
  end
48
45
 
49
- threads
50
- end
51
-
52
- def join_threads(threads, searched_facts)
53
- resolved_facts = []
54
-
55
- threads.each do |thread|
56
- thread.join
57
- resolved_facts << thread.value unless thread.value.nil?
58
- end
59
-
60
46
  resolved_facts.flatten!
61
-
62
47
  FactAugmenter.augment_resolved_facts(searched_facts, resolved_facts)
63
48
  end
64
49
  end
@@ -7,6 +7,8 @@ module Facter
7
7
  class FactFilter
8
8
  def filter_facts!(searched_facts)
9
9
  filter_legacy_facts!(searched_facts)
10
+ filter_blocked_legacy_facts!(searched_facts)
11
+
10
12
  searched_facts.each do |fact|
11
13
  fact.value = if fact.filter_tokens.any? && fact.value.respond_to?(:dig)
12
14
  fact.value.dig(*fact.filter_tokens)
@@ -18,6 +20,17 @@ module Facter
18
20
 
19
21
  private
20
22
 
23
+ # This will filter out the legacy facts that should be blocked. Because some legacy facts are just aliases
24
+ # to the core ones, even if they are blocked, facter will resolved them but they won't be displayed.
25
+
26
+ def filter_blocked_legacy_facts!(facts)
27
+ blocked_facts = Options[:blocked_facts] || []
28
+
29
+ facts.reject! do |fact|
30
+ blocked_facts.select { |blocked_fact| fact.name.match(/^#{blocked_fact}/) && fact.type == :legacy }.any?
31
+ end
32
+ end
33
+
21
34
  def filter_legacy_facts!(resolved_facts)
22
35
  return unless !Options[:show_legacy] && Options[:user_query].empty?
23
36
 
@@ -64,11 +64,34 @@ module Facter
64
64
  def block_facts(facts, options)
65
65
  blocked_facts = options[:blocked_facts] || []
66
66
 
67
+ reject_list_core, reject_list_legacy = construct_reject_lists(blocked_facts, facts)
68
+
67
69
  facts = facts.reject do |fact|
68
- blocked_facts.select { |blocked_fact| fact.name.match(/^#{blocked_fact}/) }.any?
70
+ reject_list_core.include?(fact) || reject_list_core.find do |fact_to_block|
71
+ fact_to_block.klass == fact.klass
72
+ end || reject_list_legacy.include?(fact)
69
73
  end
70
74
 
71
75
  facts
72
76
  end
77
+
78
+ def construct_reject_lists(blocked_facts, facts)
79
+ reject_list_core = []
80
+ reject_list_legacy = []
81
+
82
+ blocked_facts.each do |blocked|
83
+ facts.each do |fact|
84
+ next unless fact.name =~ /^#{blocked}/
85
+
86
+ if fact.type == :core
87
+ reject_list_core << fact
88
+ else
89
+ reject_list_legacy << fact
90
+ end
91
+ end
92
+ end
93
+
94
+ [reject_list_core, reject_list_legacy]
95
+ end
73
96
  end
74
97
  end
@@ -26,7 +26,8 @@ module Facter
26
26
  pretty_json = hash_to_facter_format(fact_collection)
27
27
 
28
28
  pretty_json = remove_enclosing_accolades(pretty_json)
29
- remove_comma_and_quotation(pretty_json)
29
+ pretty_json = remove_comma_and_quotation(pretty_json)
30
+ handle_newlines(pretty_json)
30
31
  end
31
32
 
32
33
  def format_for_multiple_user_queries(user_queries, resolved_facts)
@@ -38,6 +39,7 @@ module Facter
38
39
  pretty_json = hash_to_facter_format(facts_to_display)
39
40
  pretty_json = remove_enclosing_accolades(pretty_json)
40
41
  pretty_json = remove_comma_and_quotation(pretty_json)
42
+ pretty_json = handle_newlines(pretty_json)
41
43
 
42
44
  @log.debug('Remove quotes from value if value is a string')
43
45
  pretty_json.gsub(/^(\S*) => \"(.*)\"/, '\1 => \2')
@@ -84,6 +86,11 @@ module Facter
84
86
  pretty_fact_json.gsub(/^},/, '}')
85
87
  end
86
88
 
89
+ def handle_newlines(pretty_fact_json)
90
+ @log.debug('Convert newline characters to actual newlines')
91
+ pretty_fact_json.gsub('\n', "\n")
92
+ end
93
+
87
94
  def remove_comma_and_quotation(output)
88
95
  # quotation marks that come after \ are not removed
89
96
  @log.debug('Remove unnecessary comma and quotation marks on root facts')
@@ -56,7 +56,7 @@ module Facter
56
56
  return false if value[/^[0-9]+$/]
57
57
  return true if value =~ /y|Y|yes|Yes|YES|n|N|no|No|NO|True|TRUE|False|FALSE|on|On|ON|off|Off|OFF|:/
58
58
  return false if value[/[a-zA-Z]/]
59
- return false if value[/[0-9]+\.[0-9]+\./]
59
+ return false if value[/[0-9]+\.[0-9]+/]
60
60
 
61
61
  true
62
62
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facter
4
+ module Resolvers
5
+ module Aix
6
+ class Serialnumber < BaseResolver
7
+ @semaphore = Mutex.new
8
+ @fact_list ||= {}
9
+
10
+ class << self
11
+ private
12
+
13
+ def post_resolve(fact_name)
14
+ @fact_list.fetch(fact_name) { read_serialnumber(fact_name) }
15
+ end
16
+
17
+ def read_serialnumber(fact_name)
18
+ odmquery = Facter::ODMQuery.new
19
+ odmquery
20
+ .equals('name', 'sys0')
21
+ .equals('attribute', 'systemid')
22
+ result = odmquery.execute
23
+
24
+ result.each_line do |line|
25
+ if line.include?('value')
26
+ @fact_list[:serialnumber] = line.split('=')[1].strip.delete('\"')[6..-1]
27
+ break
28
+ end
29
+ end
30
+
31
+ @fact_list[fact_name]
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -12,6 +12,7 @@ module Facter
12
12
  # :bios_vendor
13
13
  # :bios_date
14
14
  # :bios_version
15
+ # :board_asset_tag
15
16
  # :board_vendor
16
17
  # :board_serial
17
18
  # :board_name
@@ -29,9 +30,9 @@ module Facter
29
30
  end
30
31
 
31
32
  def read_facts(fact_name)
32
- files = %w[bios_date bios_vendor bios_version board_vendor board_name board_serial
33
- chassis_asset_tag chassis_type sys_vendor product_name product_serial
34
- product_uuid]
33
+ files = %w[bios_date bios_vendor bios_version board_asset_tag board_vendor board_name
34
+ board_serial chassis_asset_tag chassis_type sys_vendor product_name
35
+ product_serial product_uuid]
35
36
  return unless File.directory?('/sys/class/dmi')
36
37
 
37
38
  file_content = Util::FileHelper.safe_read("/sys/class/dmi/id/#{fact_name}", nil)
@@ -7,13 +7,13 @@ module Facter
7
7
  @fact_list ||= {}
8
8
  EC2_METADATA_ROOT_URL = 'http://169.254.169.254/latest/meta-data/'
9
9
  EC2_USERDATA_ROOT_URL = 'http://169.254.169.254/latest/user-data/'
10
- EC2_CONNECTION_TIMEOUT = 0.6
11
10
  EC2_SESSION_TIMEOUT = 5
12
11
 
13
12
  class << self
14
13
  private
15
14
 
16
15
  def post_resolve(fact_name)
16
+ log.debug('Querying Ec2 metadata')
17
17
  @fact_list.fetch(fact_name) { read_facts(fact_name) }
18
18
  end
19
19
 
@@ -29,7 +29,7 @@ module Facter
29
29
  metadata.each_line do |line|
30
30
  next if line.empty?
31
31
 
32
- http_path_component = build_path_compoent(line)
32
+ http_path_component = build_path_component(line)
33
33
  next if http_path_component == 'security-credentials/'
34
34
 
35
35
  if http_path_component.end_with?('/')
@@ -44,27 +44,13 @@ module Facter
44
44
  end
45
45
  end
46
46
 
47
- def build_path_compoent(line)
47
+ def build_path_component(line)
48
48
  array_match = /^(\d+)=.*$/.match(line)
49
49
  array_match ? "#{array_match[1]}/" : line.strip
50
50
  end
51
51
 
52
52
  def get_data_from(url)
53
- require 'net/http'
54
-
55
- parsed_url = URI.parse(url)
56
- http = Net::HTTP.new(parsed_url.host)
57
- http.read_timeout = determine_session_timeout
58
- http.open_timeout = EC2_CONNECTION_TIMEOUT
59
- resp = http.get(parsed_url.path)
60
- response_code_valid?(resp.code) ? resp.body : ''
61
- rescue StandardError => e
62
- log.debug("Trying to connect to #{url} but got: #{e.message}")
63
- ''
64
- end
65
-
66
- def response_code_valid?(http_code)
67
- http_code.to_i.equal?(200)
53
+ Utils::Http.get_request(url, {}, { session: determine_session_timeout })
68
54
  end
69
55
 
70
56
  def determine_session_timeout
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facter
4
+ module Resolvers
5
+ class Gce < BaseResolver
6
+ @semaphore = Mutex.new
7
+ @fact_list ||= {}
8
+ METADATA_URL = 'http://metadata.google.internal/computeMetadata/v1/?recursive=true&alt=json'
9
+ HEADERS = { "Metadata-Flavor": 'Google', "Accept": 'application/json' }.freeze
10
+
11
+ class << self
12
+ private
13
+
14
+ def post_resolve(fact_name)
15
+ log.debug('reading Gce metadata')
16
+ @fact_list.fetch(fact_name) { read_facts(fact_name) }
17
+ end
18
+
19
+ def read_facts(fact_name)
20
+ @fact_list[:metadata] = query_for_metadata
21
+ @fact_list[fact_name]
22
+ end
23
+
24
+ def query_for_metadata
25
+ gce_data = extract_to_hash(Utils::Http.get_request(METADATA_URL, HEADERS))
26
+ parse_instance(gce_data)
27
+
28
+ gce_data.empty? ? nil : gce_data
29
+ end
30
+
31
+ def extract_to_hash(metadata)
32
+ JSON.parse(metadata)
33
+ rescue JSON::ParserError => e
34
+ log.debug("Trying to parse result but got: #{e.message}")
35
+ {}
36
+ end
37
+
38
+ def parse_instance(gce_data)
39
+ instance_data = gce_data['instance']
40
+ return if instance_data.nil? || instance_data.empty?
41
+
42
+ %w[image machineType zone].each do |key|
43
+ instance_data[key] = instance_data[key].split('/').last if instance_data[key]
44
+ end
45
+
46
+ network = instance_data.dig('networkInterfaces', 0, 'network')
47
+ instance_data['networkInterfaces'][0]['network'] = network.split('/').last unless network.nil?
48
+
49
+ gce_data['instance'] = instance_data
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end