facter 4.5.0 → 4.5.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bc6c44e0072feade1a48b1a15c423c6028dd18d66fd3edaed7aa7ae07ac4922
4
- data.tar.gz: 452afdcc9dd049b23e43ea3623c5758c2447fec809a44680ab5928a65cd12b17
3
+ metadata.gz: d43b50edf3b5f7815e25fb42dc5cae9f15d2fb2dcbb5fd7146957667f48fa9cb
4
+ data.tar.gz: 2792c74d6509bddd13f391e9eaac528a5e8a8852fa6f276a433d2bddeb58d3d8
5
5
  SHA512:
6
- metadata.gz: 77e545e417001ef58de71b4aa470ebbb4e71349d19c64eafce67268c019f41e1367b6bb00acc1c6e24586ee39f751a3f652c6227f7ccd16e300b7a4b3fbe10d2
7
- data.tar.gz: c605efaacef975278de37d8d091ab251228d4f1d8c139e103eb2b50cbf0f3d49feac1f0b8f4c9f724b2a44e25bf1d832853ec28f82d0588afebe61b8a22a02b6
6
+ metadata.gz: bac838d93cb84e7e3934e048368e69106182d25450979749228e2c32a8f2bd21792fd58c245e0cd7b18bbd9e5a11b6bf0edb7067435dd0948b4df25cef1517a8
7
+ data.tar.gz: b800f80520161b8ec33eb241811227565525c6bff880d271e78906b364c2e7d0fd4f54ac3984d7a6c93084c11de47788a0cd5549af770e91fbc3db9a65415deb
@@ -93,7 +93,12 @@ module LegacyFacter
93
93
  if data == false
94
94
  log.warn "Could not interpret fact file #{fact.file}"
95
95
  elsif (data == {}) || data.nil?
96
- log.debug("Fact file #{fact.file} was parsed but no key=>value data was returned")
96
+ log.debug(
97
+ "Structured data fact file #{fact.file} was parsed but was either empty or an invalid filetype "\
98
+ '(valid filetypes are .yaml, .json, and .txt).'
99
+ )
100
+ elsif !data.is_a?(Hash)
101
+ log.error("Structured data fact file #{fact.file} was parsed but no key=>value data was returned.")
97
102
  else
98
103
  add_data(data, collection, fact, weight)
99
104
  end
@@ -20,10 +20,15 @@ module Facts
20
20
  end
21
21
 
22
22
  def determine_release_version
23
+ # For backwards compatibility, use system-release for AL1/AL2
23
24
  version = Facter::Resolvers::ReleaseFromFirstLine.resolve(:release, release_file: '/etc/system-release')
25
+ if !version.nil? && version != '2'
26
+ # Use os-release for AL2023 and up
27
+ version = Facter::Resolvers::Amzn::OsReleaseRpm.resolve(:version)
28
+ end
24
29
  version ||= Facter::Resolvers::OsRelease.resolve(:version_id)
25
30
 
26
- Facter::Util::Facts.release_hash_from_string(version)
31
+ Facter::Util::Facts.release_hash_from_string(version, include_patch: true)
27
32
  end
28
33
  end
29
34
  end
@@ -18,7 +18,12 @@ module Facts
18
18
  end
19
19
 
20
20
  def determine_release_version
21
+ # For backwards compatibility, use system-release for AL1/AL2
21
22
  version = Facter::Resolvers::ReleaseFromFirstLine.resolve(:release, release_file: '/etc/system-release')
23
+ if !version.nil? && version != '2'
24
+ # Use os-release for AL2023 and up
25
+ version = Facter::Resolvers::Amzn::OsReleaseRpm.resolve(:version)
26
+ end
22
27
  version ||= Facter::Resolvers::OsRelease.resolve(:version_id)
23
28
 
24
29
  Facter::Util::Facts.release_hash_from_string(version)
@@ -21,9 +21,10 @@ module Facter
21
21
 
22
22
  def find_nested_classes(mod, discovered_classes)
23
23
  mod.constants.each do |constant_name|
24
- if mod.const_get(constant_name).instance_of? Class
25
- discovered_classes << mod.const_get(constant_name)
26
- elsif mod.const_get(constant_name).instance_of? Module
24
+ obj = mod.const_get(constant_name)
25
+ if obj.instance_of? Class
26
+ discovered_classes << obj
27
+ elsif obj.instance_of? Module
27
28
  find_nested_classes(Module.const_get("#{mod.name}::#{constant_name}"), discovered_classes)
28
29
  end
29
30
  end
@@ -244,6 +244,8 @@ os_hierarchy.each do |os|
244
244
  require_relative '../../facts/amzn/os/distro/release.rb'
245
245
  require_relative '../../facts/amzn/os/release.rb'
246
246
 
247
+ require_relative '../../resolvers/amzn/os_release_rpm'
248
+
247
249
  when 'bsd'
248
250
  require_relative '../../facts/bsd/kernelmajversion.rb'
249
251
  require_relative '../../facts/bsd/kernelversion.rb'
@@ -18,18 +18,18 @@ module Facter
18
18
  # Because a root fact will always be resolved by a collection of child facts,
19
19
  # we can return one or more child facts for each parent.
20
20
  #
21
- # query - is the user input used to search for facts
22
- # loaded_fact - is a list with all facts for the current operating system
21
+ # @param query_list [Array] The list of facts to search for
22
+ # @param loaded_facts [Array] All of the fact definitions for the current operating system
23
23
  #
24
- # Returns a list of SearchedFact objects that resolve the users query.
25
- def parse(query_list, loaded_fact)
24
+ # @return [Array<SearchedFact>] a list of searchable facts that resolve the user's query
25
+ def parse(query_list, loaded_facts)
26
26
  matched_facts = []
27
27
  @query_list = query_list
28
28
 
29
- return no_user_query(loaded_fact) unless query_list.any?
29
+ return no_user_query(loaded_facts) unless query_list.any?
30
30
 
31
31
  query_list.each do |query|
32
- found_facts = search_for_facts(query, loaded_fact)
32
+ found_facts = search_for_facts(query, loaded_facts)
33
33
  matched_facts << found_facts
34
34
  end
35
35
 
@@ -44,15 +44,17 @@ module Facter
44
44
  searched_facts
45
45
  end
46
46
 
47
- def search_for_facts(query, loaded_fact_hash)
47
+ def search_for_facts(query, loaded_facts)
48
48
  resolvable_fact_list = []
49
49
  query = query.to_s
50
50
  query_tokens = query.end_with?('.*') ? [query] : query.split('.')
51
51
  size = query_tokens.size
52
52
 
53
+ # Try to match the most specific query_tokens to the least, returning the first match
53
54
  size.times do |i|
54
55
  query_token_range = 0..size - i - 1
55
- resolvable_fact_list = get_facts_matching_tokens(query_tokens, query_token_range, loaded_fact_hash)
56
+ query_fact = query_tokens[query_token_range].join('.')
57
+ resolvable_fact_list = get_facts_matching_tokens(query_tokens, query_fact, loaded_facts)
56
58
 
57
59
  return resolvable_fact_list if resolvable_fact_list.any?
58
60
  end
@@ -62,12 +64,10 @@ module Facter
62
64
  resolvable_fact_list
63
65
  end
64
66
 
65
- def get_facts_matching_tokens(query_tokens, query_token_range, loaded_fact_hash)
67
+ def get_facts_matching_tokens(query_tokens, query_fact, loaded_facts)
66
68
  resolvable_fact_list = []
67
69
 
68
- loaded_fact_hash.each do |loaded_fact|
69
- query_fact = query_tokens[query_token_range].join('.')
70
-
70
+ loaded_facts.each do |loaded_fact|
71
71
  next unless found_fact?(loaded_fact.name, query_fact)
72
72
 
73
73
  searched_fact = construct_loaded_fact(query_tokens, loaded_fact)
@@ -79,16 +79,20 @@ module Facter
79
79
  end
80
80
 
81
81
  def found_fact?(fact_name, query_fact)
82
+ # This is the case where the fact_name contains a wildcard like
83
+ # blockdevice_.*_model and we're querying for the legacy fact
84
+ # specifically using 'blockdevice_sba_model' and we don't want the query
85
+ # 'blockdevice.sba.model' to match
82
86
  fact_with_wildcard = fact_name.include?('.*') && !query_fact.include?('.')
83
87
 
84
- processed_equery_fact = query_fact.gsub('\\', '\\\\\\\\')
85
-
86
- return false if fact_with_wildcard && !query_fact.match("^#{fact_name}$")
87
-
88
- # Must escape metacharacters (like dots) to ensure the correct fact is found
89
- return false unless fact_with_wildcard || fact_name.match("^#{Regexp.escape(processed_equery_fact)}($|\\.)")
90
-
91
- true
88
+ if fact_with_wildcard
89
+ # fact_name contains wildcard, so we're intentially not escaping.
90
+ query_fact.match("^#{fact_name}$")
91
+ else
92
+ processed_equery_fact = query_fact.gsub('\\', '\\\\\\\\')
93
+ # Must escape metacharacters (like dots) to ensure the correct fact is found
94
+ fact_name.match("^#{Regexp.escape(processed_equery_fact)}($|\\.)")
95
+ end
92
96
  end
93
97
 
94
98
  def construct_loaded_fact(query_tokens, loaded_fact)
@@ -47,7 +47,7 @@ module Facter
47
47
  end
48
48
 
49
49
  def compute_size(size_hash)
50
- physical_partitions = size_hash['TOTAL PPs'].to_i + size_hash['FREE PPs'].to_i
50
+ physical_partitions = size_hash['TOTAL PPs'].to_i
51
51
  size_physical_partition = size_hash['PP SIZE']
52
52
  exp = if size_physical_partition[/mega/]
53
53
  Facter::Util::Aix::InfoExtractor::MEGABYTES_EXPONENT
@@ -56,14 +56,14 @@ module Facter
56
56
  end
57
57
 
58
58
  def compute_size(info_hash)
59
- physical_partitions = info_hash['PPs'].to_i
59
+ logical_partitions = info_hash['LPs'].to_i
60
60
  size_physical_partition = info_hash['PP SIZE']
61
61
  exp = if size_physical_partition[/mega/]
62
62
  Facter::Util::Aix::InfoExtractor::MEGABYTES_EXPONENT
63
63
  else
64
64
  Facter::Util::Aix::InfoExtractor::GIGABYTES_EXPONENT
65
65
  end
66
- size_physical_partition.to_i * physical_partitions * exp
66
+ size_physical_partition.to_i * logical_partitions * exp
67
67
  end
68
68
  end
69
69
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facter
4
+ module Resolvers
5
+ module Amzn
6
+ class OsReleaseRpm < BaseResolver
7
+ init_resolver
8
+
9
+ class << self
10
+ private
11
+
12
+ def post_resolve(fact_name, _options)
13
+ @fact_list.fetch(fact_name) { rpm_system_call(fact_name) }
14
+ end
15
+
16
+ def rpm_system_call(fact_name)
17
+ output = Facter::Core::Execution.execute(
18
+ 'rpm -q --qf \'%{NAME}\n%{VERSION}\n%{RELEASE}\n%{VENDOR}\' -f /etc/os-release',
19
+ logger: log
20
+ )
21
+ build_fact_list(output)
22
+
23
+ @fact_list[fact_name]
24
+ end
25
+
26
+ def build_fact_list(output)
27
+ rpm_results = output.split("\n")
28
+
29
+ return if rpm_results.empty?
30
+
31
+ @fact_list[:package],
32
+ @fact_list[:version],
33
+ @fact_list[:release],
34
+ @fact_list[:vendor] = rpm_results.map(&:strip)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -15,25 +15,33 @@ module Facter
15
15
 
16
16
  def calculate_system_memory(fact_name)
17
17
  read_total_memory_in_bytes
18
- read_available_memory_in_bytes
18
+ read_used_memory_in_bytes
19
19
 
20
- @fact_list[:used_bytes] = @fact_list[:total_bytes] - @fact_list[:available_bytes]
20
+ @fact_list[:available_bytes] = @fact_list[:total_bytes] - @fact_list[:used_bytes]
21
21
  @fact_list[:capacity] = Facter::Util::Resolvers::FilesystemHelper
22
22
  .compute_capacity(@fact_list[:used_bytes], @fact_list[:total_bytes])
23
23
 
24
24
  @fact_list[fact_name]
25
25
  end
26
26
 
27
- def read_available_memory_in_bytes
28
- output = Facter::Core::Execution.execute('vmstat -H --libxo json', logger: log)
29
- data = JSON.parse(output)
30
- @fact_list[:available_bytes] = data['memory']['free-memory'] * 1024
27
+ def pagesize
28
+ @pagesize ||= Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'vm.stats.vm.v_page_size')
29
+ end
30
+
31
+ def read_used_memory_in_bytes
32
+ require_relative 'ffi/ffi_helper'
33
+
34
+ @fact_list[:used_bytes] = pagesize * (
35
+ Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'vm.stats.vm.v_active_count') +
36
+ Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'vm.stats.vm.v_wire_count')
37
+ )
31
38
  end
32
39
 
33
40
  def read_total_memory_in_bytes
34
41
  require_relative 'ffi/ffi_helper'
35
42
 
36
- @fact_list[:total_bytes] = Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'hw.physmem')
43
+ @fact_list[:total_bytes] = pagesize *
44
+ Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'vm.stats.vm.v_page_count')
37
45
  end
38
46
  end
39
47
  end
@@ -19,6 +19,12 @@ module Facter
19
19
 
20
20
  matches = output.match(/System Configuration:\s+(.+?)\s+sun\d+\S+\s+(.+)/)&.captures
21
21
 
22
+ # There are circumstances (e.g. in non-global zones) when prtdiag
23
+ # will return text, but it's an error message or some other string
24
+ # that isn't parsed by the above match/capture. In that case, we
25
+ # simply return.
26
+ return if matches.nil?
27
+
22
28
  @fact_list[:manufacturer] = matches[0]&.strip
23
29
  @fact_list[:product_name] = matches[1]&.strip
24
30
 
@@ -10,7 +10,7 @@ module Facter
10
10
 
11
11
  attach_function :ioctl_base, :ioctl, %i[int int pointer], :int
12
12
  attach_function :open_socket, :socket, %i[int int int], :int
13
- attach_function :close_socket, :shutdown, %i[int int], :int
13
+ attach_function :close_socket, :close, %i[int], :int
14
14
  attach_function :inet_ntop, %i[int pointer pointer uint], :string
15
15
 
16
16
  def self.ioctl(call_const, pointer, address_family = AF_INET)
@@ -18,7 +18,7 @@ module Facter
18
18
  begin
19
19
  ioctl_base(fd, call_const, pointer)
20
20
  ensure
21
- Ioctl.close_socket(fd, 2)
21
+ Ioctl.close_socket(fd)
22
22
  end
23
23
  end
24
24
  end
@@ -79,7 +79,7 @@ module Facter
79
79
  ioctl = FFI::Ioctl.ioctl(FFI::SIOCGLIFMTU, lifreq, lifreq.ss_family)
80
80
 
81
81
  if ioctl == -1
82
- @log.error("Cold not read MTU, error code is #{::FFI::LastError.error}")
82
+ @log.error("Could not read MTU, error code is: #{::FFI::LastError.error}")
83
83
  return
84
84
  end
85
85
 
@@ -28,12 +28,16 @@ module Facter
28
28
  def build_fact_list(output)
29
29
  uname_results = output.split("\n")
30
30
 
31
- @fact_list[:machine] = uname_results[0].strip
32
- @fact_list[:nodename] = uname_results[1].strip
33
- @fact_list[:processor] = uname_results[2].strip
34
- @fact_list[:kernelrelease] = uname_results[3].strip
35
- @fact_list[:kernelname] = uname_results[4].strip
36
- @fact_list[:kernelversion] = uname_results[5].strip
31
+ if !uname_results.empty?
32
+ @fact_list[:machine],
33
+ @fact_list[:nodename],
34
+ @fact_list[:processor],
35
+ @fact_list[:kernelrelease],
36
+ @fact_list[:kernelname],
37
+ @fact_list[:kernelversion] = uname_results.map(&:strip)
38
+ else
39
+ log.warn('Request to uname returned no output. Uname related facts are not populated.')
40
+ end
37
41
  end
38
42
  end
39
43
  end
@@ -26,7 +26,9 @@ module Facter
26
26
 
27
27
  def detect_xen_type
28
28
  xen_type = 'xen0' if File.exist?('/dev/xen/evtchn')
29
- xen_type = 'xenu' if !xen_type && (File.exist?('/proc/xen') || File.exist?('/dev/xvda1'))
29
+ if !xen_type && (File.exist?('/proc/xen') || (File.exist?('/dev/xvda1') && !File.symlink?('/dev/xvda1')))
30
+ xen_type = 'xenu'
31
+ end
30
32
 
31
33
  xen_type
32
34
  end
@@ -61,7 +61,7 @@ module Facter
61
61
  properties = PROPERTIES[cmd]
62
62
  properties.each do |property|
63
63
  str = (properties - [property]).join('|')
64
- matcher = content.match(/#{Regexp.escape(property)}([^\n]*?)(#{str}|\n|$)/s)
64
+ matcher = content.match(/(?:^|^[^:]+:[^:]+)#{Regexp.escape(property)}([^\n]*?)(#{str}|\n|$)/s)
65
65
  if matcher
66
66
  value = matcher[1].strip
67
67
  property_hash[property.split(':').first] = value
@@ -25,7 +25,7 @@ module Facter
25
25
  os
26
26
  end
27
27
 
28
- def release_hash_from_string(output)
28
+ def release_hash_from_string(output, include_patch: false)
29
29
  return unless output
30
30
 
31
31
  versions = output.split('.')
@@ -33,6 +33,7 @@ module Facter
33
33
  release['full'] = output
34
34
  release['major'] = versions[0]
35
35
  release['minor'] = versions[1] if versions[1]
36
+ release['patch'] = versions[2] if versions[2] && include_patch
36
37
  end
37
38
  end
38
39
 
@@ -3,13 +3,7 @@
3
3
  module Facter
4
4
  module Util
5
5
  module Resolvers
6
- class FingerPrint
7
- attr_accessor :sha1, :sha256
8
- def initialize(sha1, sha256)
9
- @sha1 = sha1
10
- @sha256 = sha256
11
- end
12
- end
6
+ FingerPrint = Struct.new(:sha1, :sha256)
13
7
  end
14
8
  end
15
9
  end
@@ -57,6 +57,8 @@ module Facter
57
57
  end
58
58
 
59
59
  def find_in_interfaces(interfaces)
60
+ return if interfaces.nil?
61
+
60
62
  interfaces.each do |iface_name, interface|
61
63
  interface[:bindings]&.each do |binding|
62
64
  return iface_name unless Facter::Util::Resolvers::Networking.ignored_ip_address(binding[:address])
@@ -3,15 +3,7 @@
3
3
  module Facter
4
4
  module Util
5
5
  module Resolvers
6
- class Ssh
7
- attr_accessor :fingerprint, :type, :key, :name
8
- def initialize(fingerprint, type, key, name)
9
- @fingerprint = fingerprint
10
- @type = type
11
- @key = key
12
- @name = name
13
- end
14
- end
6
+ Ssh = Struct.new(:fingerprint, :type, :key, :name)
15
7
  end
16
8
  end
17
9
  end
@@ -9,6 +9,7 @@ module Facter
9
9
  class SshHelper
10
10
  class << self
11
11
  SSH_NAME = { 'ssh-dss' => 'dsa', 'ecdsa-sha2-nistp256' => 'ecdsa',
12
+ 'ecdsa-sha2-nistp384' => 'ecdsa', 'ecdsa-sha2-nistp521' => 'ecdsa',
12
13
  'ssh-ed25519' => 'ed25519', 'ssh-rsa' => 'rsa' }.freeze
13
14
  SSH_FINGERPRINT = { 'rsa' => 1, 'dsa' => 2, 'ecdsa' => 3, 'ed25519' => 4 }.freeze
14
15
 
@@ -16,6 +17,7 @@ module Facter
16
17
  key_name = SSH_NAME[key_type]
17
18
  return unless key_name
18
19
 
20
+ # decode64 ignores non-base64 characters including newlines
19
21
  decoded_key = Base64.decode64(key)
20
22
  ssh_fp = SSH_FINGERPRINT[key_name]
21
23
  sha1 = "SSHFP #{ssh_fp} 1 #{Digest::SHA1.new.update(decoded_key)}"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Facter
4
- VERSION = '4.5.0' unless defined?(VERSION)
4
+ VERSION = '4.5.2' unless defined?(VERSION)
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: facter
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.5.0
4
+ version: 4.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-26 00:00:00.000000000 Z
11
+ date: 2024-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -934,6 +934,7 @@ files:
934
934
  - lib/facter/resolvers/aix/partitions.rb
935
935
  - lib/facter/resolvers/aix/processors.rb
936
936
  - lib/facter/resolvers/aix/serialnumber.rb
937
+ - lib/facter/resolvers/amzn/os_release_rpm.rb
937
938
  - lib/facter/resolvers/augeas.rb
938
939
  - lib/facter/resolvers/az.rb
939
940
  - lib/facter/resolvers/base_resolver.rb
@@ -1101,7 +1102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1101
1102
  - !ruby/object:Gem::Version
1102
1103
  version: '0'
1103
1104
  requirements: []
1104
- rubygems_version: 3.4.12
1105
+ rubygems_version: 3.4.20
1105
1106
  signing_key:
1106
1107
  specification_version: 4
1107
1108
  summary: Facter, a system inventory tool