facter 4.0.47 → 4.0.48

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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/lib/facter.rb +0 -1
  3. data/lib/facter/config.rb +1 -2
  4. data/lib/facter/custom_facts/util/fact.rb +19 -1
  5. data/lib/facter/custom_facts/util/resolution.rb +1 -1
  6. data/lib/facter/facts/aix/disks.rb +1 -1
  7. data/lib/facter/facts/aix/ssh.rb +1 -1
  8. data/lib/facter/facts/aix/sshalgorithmkey.rb +1 -1
  9. data/lib/facter/facts/aix/sshfp_algorithm.rb +1 -1
  10. data/lib/facter/facts/freebsd/ssh.rb +1 -1
  11. data/lib/facter/facts/freebsd/sshalgorithmkey.rb +1 -1
  12. data/lib/facter/facts/freebsd/sshfp_algorithm.rb +1 -1
  13. data/lib/facter/facts/linux/disks.rb +1 -1
  14. data/lib/facter/facts/linux/os/family.rb +4 -2
  15. data/lib/facter/facts/linux/ssh.rb +1 -1
  16. data/lib/facter/facts/linux/sshalgorithmkey.rb +1 -1
  17. data/lib/facter/facts/linux/sshfp_algorithm.rb +1 -1
  18. data/lib/facter/facts/macosx/ssh.rb +1 -1
  19. data/lib/facter/facts/macosx/sshalgorithmkey.rb +1 -1
  20. data/lib/facter/facts/macosx/sshfp_algorithm.rb +1 -1
  21. data/lib/facter/facts/solaris/disks.rb +1 -1
  22. data/lib/facter/facts/solaris/ssh.rb +1 -1
  23. data/lib/facter/facts/solaris/sshalgorithmkey.rb +1 -1
  24. data/lib/facter/facts/solaris/sshfp_algorithm.rb +1 -1
  25. data/lib/facter/facts/windows/networking/fqdn.rb +1 -1
  26. data/lib/facter/framework/core/options/option_store.rb +3 -1
  27. data/lib/facter/framework/detector/os_detector.rb +1 -0
  28. data/lib/facter/resolvers/aix/{architecture_resolver.rb → architecture.rb} +0 -0
  29. data/lib/facter/resolvers/aix/{filesystem_resolver.rb → filesystem.rb} +0 -0
  30. data/lib/facter/resolvers/aix/{hardware_resolver.rb → hardware.rb} +0 -0
  31. data/lib/facter/resolvers/aix/{load_averages_resolver.rb → load_averages.rb} +0 -0
  32. data/lib/facter/resolvers/aix/{networking_resolver.rb → networking.rb} +0 -0
  33. data/lib/facter/resolvers/{augeas_resolver.rb → augeas.rb} +0 -0
  34. data/lib/facter/resolvers/{disk_resolver.rb → disk.rb} +0 -0
  35. data/lib/facter/resolvers/{dmi_resolver.rb → dmi.rb} +0 -0
  36. data/lib/facter/resolvers/{eos_release_resolver.rb → eos_release.rb} +0 -0
  37. data/lib/facter/resolvers/{facterversion_resolver.rb → facterversion.rb} +0 -0
  38. data/lib/facter/resolvers/{filesystems_resolver.rb → filesystems.rb} +0 -0
  39. data/lib/facter/resolvers/{fips_enabled_resolver.rb → fips_enabled.rb} +0 -0
  40. data/lib/facter/resolvers/freebsd/{dmi_resolver.rb → dmi.rb} +0 -0
  41. data/lib/facter/resolvers/freebsd/{freebsd_version_resolver.rb → freebsd_version.rb} +0 -0
  42. data/lib/facter/resolvers/freebsd/{geom_resolver.rb → geom.rb} +0 -0
  43. data/lib/facter/resolvers/freebsd/{swap_memory_resolver.rb → swap_memory.rb} +0 -0
  44. data/lib/facter/resolvers/freebsd/{system_memory_resolver.rb → system_memory.rb} +0 -0
  45. data/lib/facter/resolvers/freebsd/{virtual_resolver.rb → virtual.rb} +0 -0
  46. data/lib/facter/resolvers/{hostname_resolver.rb → hostname.rb} +0 -0
  47. data/lib/facter/resolvers/{identity_resolver.rb → identity.rb} +0 -0
  48. data/lib/facter/resolvers/{lpar_resolver.rb → lpar.rb} +0 -0
  49. data/lib/facter/resolvers/{lsb_release_resolver.rb → lsb_release.rb} +0 -0
  50. data/lib/facter/resolvers/macosx/{dmi_resolver.rb → dmi.rb} +0 -0
  51. data/lib/facter/resolvers/macosx/{filesystems_resolver.rb → filesystems.rb} +0 -0
  52. data/lib/facter/resolvers/macosx/{load_averages_resolver.rb → load_averages.rb} +0 -0
  53. data/lib/facter/resolvers/macosx/{mountpoints_resolver.rb → mountpoints.rb} +0 -0
  54. data/lib/facter/resolvers/macosx/{processor_resolver.rb → processor.rb} +0 -0
  55. data/lib/facter/resolvers/macosx/{swap_memory_resolver.rb → swap_memory.rb} +0 -0
  56. data/lib/facter/resolvers/macosx/{system_memory_resolver.rb → system_memory.rb} +0 -0
  57. data/lib/facter/resolvers/macosx/{system_profiler_resolver.rb → system_profiler.rb} +0 -0
  58. data/lib/facter/resolvers/{memory_resolver.rb → memory.rb} +0 -0
  59. data/lib/facter/resolvers/{mountpoints_resolver.rb → mountpoints.rb} +0 -0
  60. data/lib/facter/resolvers/{networking_resolver.rb → networking.rb} +0 -0
  61. data/lib/facter/resolvers/networking_linux.rb +296 -0
  62. data/lib/facter/resolvers/{os_release_resolver.rb → os_release.rb} +0 -0
  63. data/lib/facter/resolvers/{path_resolver.rb → path.rb} +0 -0
  64. data/lib/facter/resolvers/{processors_resolver.rb → processors.rb} +0 -0
  65. data/lib/facter/resolvers/{redhat_release_resolver.rb → redhat_release.rb} +0 -0
  66. data/lib/facter/resolvers/{ruby_resolver.rb → ruby.rb} +0 -0
  67. data/lib/facter/resolvers/{selinux_resolver.rb → selinux.rb} +0 -0
  68. data/lib/facter/resolvers/{ssh_resolver.rb → ssh.rb} +1 -1
  69. data/lib/facter/resolvers/{suse_release_resolver.rb → suse_release.rb} +0 -0
  70. data/lib/facter/resolvers/{sw_vers_resolver.rb → sw_vers.rb} +0 -0
  71. data/lib/facter/resolvers/{timezone_resolver.rb → timezone.rb} +0 -0
  72. data/lib/facter/resolvers/{uname_resolver.rb → uname.rb} +0 -0
  73. data/lib/facter/resolvers/{uptime_resolver.rb → uptime.rb} +0 -0
  74. data/lib/facter/resolvers/windows/{dmi_bios_resolver.rb → dmi_bios.rb} +0 -0
  75. data/lib/facter/resolvers/windows/{dmi_computersystem_resolver.rb → dmi_computersystem.rb} +0 -0
  76. data/lib/facter/resolvers/windows/{fips_resolver.rb → fips.rb} +0 -0
  77. data/lib/facter/resolvers/windows/{hardware_architecture_resolver.rb → hardware_architecture.rb} +0 -0
  78. data/lib/facter/resolvers/windows/{identity_resolver.rb → identity.rb} +0 -0
  79. data/lib/facter/resolvers/windows/{kernel_resolver.rb → kernel.rb} +0 -0
  80. data/lib/facter/resolvers/windows/{memory_resolver.rb → memory.rb} +0 -0
  81. data/lib/facter/resolvers/windows/{netkvm_resolver.rb → netkvm.rb} +0 -0
  82. data/lib/facter/resolvers/windows/{networking_resolver.rb → networking.rb} +13 -0
  83. data/lib/facter/resolvers/windows/{processors_resolver.rb → processors.rb} +0 -0
  84. data/lib/facter/resolvers/windows/{product_release_resolver.rb → product_release.rb} +0 -0
  85. data/lib/facter/resolvers/windows/{system32_resolver.rb → system32.rb} +0 -0
  86. data/lib/facter/resolvers/windows/{uptime_resolver.rb → uptime.rb} +0 -0
  87. data/lib/facter/resolvers/windows/{virtualization_resolver.rb → virtualization.rb} +0 -0
  88. data/lib/facter/resolvers/windows/{win_os_description_resolver.rb → win_os_description.rb} +0 -0
  89. data/lib/facter/resolvers/{wpar_resolver.rb → wpar.rb} +0 -0
  90. data/lib/facter/util/facts/facts_utils.rb +16 -0
  91. data/lib/facter/version.rb +1 -1
  92. metadata +78 -79
  93. data/lib/facter/resolvers/networking_linux_resolver.rb +0 -258
  94. data/lib/facter/util/resolvers/networking.rb +0 -90
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87e1b483df51f967d4e88c90f67ddfef304184d235d08746500c61619c56dee2
4
- data.tar.gz: d573d4d221bc71e512c36a2f8218b0d70512ace56cb0eaa37dba3a9eee27bcde
3
+ metadata.gz: a97076330c5a6ac8a2d8ba6a5a36ecc3b8b3d5661d46057a444f0bafc1fe1e35
4
+ data.tar.gz: b84fcccd87ee9e7554e99342bf3722f383f23481480b9090e1cdba1ed26021ed
5
5
  SHA512:
6
- metadata.gz: 49f5a8c11e45cdc6e9550e6fa50335700b8c43c048b46b1f091ea4b4a1f66588865a36c2ca1b447bea72c80a1548ca37d6f998eca4187047c6f2e95b2daf87d5
7
- data.tar.gz: b6b21071a59dbfedc1499b6464e2556aa272f9fc99feb1674c6961a1a3a564570e9a7df127ad80140703ee320f73b1e41c82deec41dfb4160814544f1a0ae2d4
6
+ metadata.gz: beba9d7a66f00a6914558d54df18438a64e0e78f9d5109f5a5657f605480a26519a8c5a3b5b12e31c6c312a48c43066fadf302e433f6e57f129ba9214277e266
7
+ data.tar.gz: 73348a9dd6e2b68f50c7b73f543b0e90153b4753d2f7641ff078ee58860229af32c2f4a3871c25fc7da011308cb5ce20d2c6e455645b6c1e8ae2c59f9092b3b9
@@ -381,7 +381,6 @@ module Facter
381
381
  # @api public
382
382
  def values(options, user_queries)
383
383
  init_cli_options(options, user_queries)
384
- Options[:show_legacy] = true
385
384
  log_blocked_facts
386
385
  resolved_facts = Facter::FactManager.instance.resolve_facts(user_queries)
387
386
  resolved_facts.reject! { |fact| fact.type == :custom && fact.value.nil? }
@@ -312,8 +312,7 @@ module Facter
312
312
  'operatingsystemrelease',
313
313
  'osfamily',
314
314
  'physicalprocessorcount',
315
- 'processor.*',
316
- 'processor*',
315
+ 'processor[0-9]+.*',
317
316
  'processorcount',
318
317
  'productname',
319
318
  'rubyplatform',
@@ -43,6 +43,8 @@ module Facter
43
43
  @used_resolution_weight = 0
44
44
 
45
45
  @value = nil
46
+
47
+ @log = Facter::Log.new(self)
46
48
  end
47
49
 
48
50
  # Adds a new {Facter::Util::Resolution resolution}. This requires a
@@ -201,11 +203,27 @@ module Facter
201
203
  break
202
204
  end
203
205
  @used_resolution_weight = resolve.weight
204
- return value unless value.nil?
206
+ next if value.nil?
207
+
208
+ log_fact_path(resolve)
209
+
210
+ return value
205
211
  end
206
212
  nil
207
213
  end
208
214
 
215
+ def log_fact_path(resolve)
216
+ fact_type, resolved_from = if resolve.instance_of?(Facter::Core::Aggregate)
217
+ ['aggregate', resolve.instance_variable_get(:@aggregate).source_location[0]]
218
+ elsif resolve.fact_type == :external
219
+ ['external', resolve.file]
220
+ else
221
+ ['custom', resolve.last_evaluated]
222
+ end
223
+
224
+ @log.debug("#{fact_type} fact #{resolve.fact.name} got resolved from: #{resolved_from}")
225
+ end
226
+
209
227
  def announce_when_no_suitable_resolution(resolutions)
210
228
  return unless resolutions.empty?
211
229
 
@@ -51,7 +51,7 @@ module Facter
51
51
  # @return [Facter::Util::Fact] Associated fact with this resolution.
52
52
  #
53
53
  # @api private
54
- attr_reader :fact
54
+ attr_reader :fact, :last_evaluated, :file
55
55
 
56
56
  # Create a new resolution mechanism.
57
57
  #
@@ -4,7 +4,7 @@ module Facts
4
4
  module Aix
5
5
  class Disks
6
6
  FACT_NAME = 'disks'
7
- ALIASES = %w[blockdevices blockdevice_.*_size'].freeze
7
+ ALIASES = %w[blockdevices blockdevice_.*_size].freeze
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
@@ -16,7 +16,7 @@ module Facts
16
16
  end
17
17
 
18
18
  def resolver_data
19
- Facter::Resolvers::SshResolver.resolve(:ssh)
19
+ Facter::Resolvers::Ssh.resolve(:ssh)
20
20
  end
21
21
 
22
22
  def create_ssh_fact(ssh)
@@ -8,7 +8,7 @@ module Facts
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
11
- result = Facter::Resolvers::SshResolver.resolve(:ssh)
11
+ result = Facter::Resolvers::Ssh.resolve(:ssh)
12
12
  result.each { |ssh| facts << Facter::ResolvedFact.new("ssh#{ssh.name.to_sym}key", ssh.key, :legacy) }
13
13
  facts
14
14
  end
@@ -8,7 +8,7 @@ module Facts
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
11
- result = Facter::Resolvers::SshResolver.resolve(:ssh)
11
+ result = Facter::Resolvers::Ssh.resolve(:ssh)
12
12
  result.each do |ssh|
13
13
  facts << Facter::ResolvedFact.new("sshfp_#{ssh.name.to_sym}",
14
14
  "#{ssh.fingerprint.sha1}\n#{ssh.fingerprint.sha256}", :legacy)
@@ -6,7 +6,7 @@ module Facts
6
6
  FACT_NAME = 'ssh'
7
7
 
8
8
  def call_the_resolver
9
- result = Facter::Resolvers::SshResolver.resolve(:ssh)
9
+ result = Facter::Resolvers::Ssh.resolve(:ssh)
10
10
  ssh_facts = {}
11
11
  result.each { |ssh| ssh_facts.merge!(create_ssh_fact(ssh)) }
12
12
  Facter::ResolvedFact.new(FACT_NAME, ssh_facts)
@@ -8,7 +8,7 @@ module Facts
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
11
- result = Facter::Resolvers::SshResolver.resolve(:ssh)
11
+ result = Facter::Resolvers::Ssh.resolve(:ssh)
12
12
  result.each { |ssh| facts << Facter::ResolvedFact.new("ssh#{ssh.name.to_sym}key", ssh.key, :legacy) }
13
13
  facts
14
14
  end
@@ -8,7 +8,7 @@ module Facts
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
11
- result = Facter::Resolvers::SshResolver.resolve(:ssh)
11
+ result = Facter::Resolvers::Ssh.resolve(:ssh)
12
12
  result.each do |ssh|
13
13
  facts << Facter::ResolvedFact.new("sshfp_#{ssh.name.to_sym}",
14
14
  "#{ssh.fingerprint.sha1}\n#{ssh.fingerprint.sha256}", :legacy)
@@ -4,7 +4,7 @@ module Facts
4
4
  module Linux
5
5
  class Disks
6
6
  FACT_NAME = 'disks'
7
- ALIASES = %w[blockdevices blockdevice_.*_model blockdevice_.*_size blockdevice_.*_vendor'].freeze
7
+ ALIASES = %w[blockdevices blockdevice_.*_model blockdevice_.*_size blockdevice_.*_vendor].freeze
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
@@ -8,8 +8,10 @@ module Facts
8
8
  ALIASES = 'osfamily'
9
9
 
10
10
  def call_the_resolver
11
- fact_value = Facter::Resolvers::OsRelease.resolve(:id_like)
12
- fact_value ||= Facter::Resolvers::OsRelease.resolve(:id)
11
+ id = Facter::Resolvers::OsRelease.resolve(:id_like)
12
+ id ||= Facter::Resolvers::OsRelease.resolve(:id)
13
+
14
+ fact_value = Facter::Util::Facts.discover_family(id)
13
15
 
14
16
  [Facter::ResolvedFact.new(FACT_NAME, fact_value.capitalize),
15
17
  Facter::ResolvedFact.new(ALIASES, fact_value.capitalize, :legacy)]
@@ -16,7 +16,7 @@ module Facts
16
16
  end
17
17
 
18
18
  def resolver_data
19
- Facter::Resolvers::SshResolver.resolve(:ssh)
19
+ Facter::Resolvers::Ssh.resolve(:ssh)
20
20
  end
21
21
 
22
22
  def create_ssh_fact(ssh)
@@ -8,7 +8,7 @@ module Facts
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
11
- result = Facter::Resolvers::SshResolver.resolve(:ssh)
11
+ result = Facter::Resolvers::Ssh.resolve(:ssh)
12
12
  result.each { |ssh| facts << Facter::ResolvedFact.new("ssh#{ssh.name.to_sym}key", ssh.key, :legacy) }
13
13
  facts
14
14
  end
@@ -8,7 +8,7 @@ module Facts
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
11
- result = Facter::Resolvers::SshResolver.resolve(:ssh)
11
+ result = Facter::Resolvers::Ssh.resolve(:ssh)
12
12
  result.each do |ssh|
13
13
  facts << Facter::ResolvedFact.new("sshfp_#{ssh.name.to_sym}",
14
14
  "#{ssh.fingerprint.sha1}\n#{ssh.fingerprint.sha256}", :legacy)
@@ -16,7 +16,7 @@ module Facts
16
16
  end
17
17
 
18
18
  def resolver_data
19
- Facter::Resolvers::SshResolver.resolve(:ssh)
19
+ Facter::Resolvers::Ssh.resolve(:ssh)
20
20
  end
21
21
 
22
22
  def create_ssh_fact(ssh)
@@ -8,7 +8,7 @@ module Facts
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
11
- result = Facter::Resolvers::SshResolver.resolve(:ssh)
11
+ result = Facter::Resolvers::Ssh.resolve(:ssh)
12
12
  result.each { |ssh| facts << Facter::ResolvedFact.new("ssh#{ssh.name.to_sym}key", ssh.key, :legacy) }
13
13
  facts
14
14
  end
@@ -8,7 +8,7 @@ module Facts
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
11
- result = Facter::Resolvers::SshResolver.resolve(:ssh)
11
+ result = Facter::Resolvers::Ssh.resolve(:ssh)
12
12
  result.each do |ssh|
13
13
  facts << Facter::ResolvedFact.new("sshfp_#{ssh.name.to_sym}",
14
14
  "#{ssh.fingerprint.sha1}\n#{ssh.fingerprint.sha256}", :legacy)
@@ -4,7 +4,7 @@ module Facts
4
4
  module Solaris
5
5
  class Disks
6
6
  FACT_NAME = 'disks'
7
- ALIASES = %w[blockdevices blockdevice_.*_size blockdevice_.*_vendor'].freeze
7
+ ALIASES = %w[blockdevices blockdevice_.*_size blockdevice_.*_vendor].freeze
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
@@ -16,7 +16,7 @@ module Facts
16
16
  end
17
17
 
18
18
  def resolver_data
19
- Facter::Resolvers::SshResolver.resolve(:ssh)
19
+ Facter::Resolvers::Ssh.resolve(:ssh)
20
20
  end
21
21
 
22
22
  def create_ssh_fact(ssh)
@@ -8,7 +8,7 @@ module Facts
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
11
- result = Facter::Resolvers::SshResolver.resolve(:ssh)
11
+ result = Facter::Resolvers::Ssh.resolve(:ssh)
12
12
  result.each { |ssh| facts << Facter::ResolvedFact.new("ssh#{ssh.name.to_sym}key", ssh.key, :legacy) }
13
13
  facts
14
14
  end
@@ -8,7 +8,7 @@ module Facts
8
8
 
9
9
  def call_the_resolver
10
10
  facts = []
11
- result = Facter::Resolvers::SshResolver.resolve(:ssh)
11
+ result = Facter::Resolvers::Ssh.resolve(:ssh)
12
12
  result.each do |ssh|
13
13
  facts << Facter::ResolvedFact.new("sshfp_#{ssh.name.to_sym}",
14
14
  "#{ssh.fingerprint.sha1}\n#{ssh.fingerprint.sha256}", :legacy)
@@ -12,7 +12,7 @@ module Facts
12
12
  hostname = Facter::Resolvers::Hostname.resolve(:hostname)
13
13
  return Facter::ResolvedFact.new(FACT_NAME, nil) if !hostname || hostname.empty?
14
14
 
15
- fact_value = [hostname, domain].compact.join('.')
15
+ fact_value = domain && !domain.empty? ? [hostname, domain].compact.join('.') : hostname
16
16
 
17
17
  [Facter::ResolvedFact.new(FACT_NAME, fact_value), Facter::ResolvedFact.new(ALIASES, fact_value, :legacy)]
18
18
  end
@@ -34,6 +34,7 @@ module Facter
34
34
  @timing = false
35
35
  @external_dir = []
36
36
  @custom_dir = []
37
+ @hocon = false
37
38
 
38
39
  class << self
39
40
  attr_reader :debug, :verbose, :log_level, :show_legacy,
@@ -42,7 +43,7 @@ module Facter
42
43
  attr_accessor :config, :user_query, :strict, :json,
43
44
  :cache, :yaml, :puppet, :ttls, :block, :cli, :config_file_custom_dir,
44
45
  :config_file_external_dir, :default_external_dir, :fact_groups,
45
- :block_list, :color, :trace, :sequential, :timing
46
+ :block_list, :color, :trace, :sequential, :timing, :hocon
46
47
 
47
48
  attr_writer :external_dir
48
49
 
@@ -171,6 +172,7 @@ module Facter
171
172
  @ruby = true
172
173
  @user_query = []
173
174
  @json = false
175
+ @hocon = false
174
176
  @cache = true
175
177
  @yaml = false
176
178
  @puppet = false
@@ -45,6 +45,7 @@ class OsDetector
45
45
  if hierarchy.empty?
46
46
  @log.debug("Could not detect hierarchy using os identifier: #{identifier} , trying with family")
47
47
 
48
+ # https://www.commandlinux.com/man-page/man5/os-release.5.html
48
49
  detect_family.to_s.split.each do |family|
49
50
  hierarchy = @os_hierarchy.construct_hierarchy(family)
50
51
  return hierarchy unless hierarchy.empty?
@@ -0,0 +1,296 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facter
4
+ module Resolvers
5
+ class NetworkingLinux < BaseResolver
6
+ init_resolver
7
+
8
+ DIRS = ['/var/lib/dhclient/', '/var/lib/dhcp/', '/var/lib/dhcp3/', '/var/lib/NetworkManager/', '/var/db/'].freeze
9
+ ROUTE_TYPES = %w[anycast
10
+ unicast
11
+ broadcast
12
+ local
13
+ nat
14
+ unreachable
15
+ prohibit
16
+ blackhole
17
+ throw].freeze
18
+
19
+ class << self
20
+ private
21
+
22
+ def post_resolve(fact_name)
23
+ @fact_list.fetch(fact_name) { retrieve_network_info(fact_name) }
24
+
25
+ @fact_list[fact_name]
26
+ end
27
+
28
+ def retrieve_network_info(fact_name)
29
+ mtu_and_indexes = interfaces_mtu_and_index
30
+ retrieve_interfaces_with_socket(mtu_and_indexes)
31
+ add_info_from_routing_table
32
+ retrieve_primary_interface
33
+ Facter::Util::Resolvers::Networking.expand_main_bindings(@fact_list)
34
+ @fact_list[fact_name]
35
+ end
36
+
37
+ def interfaces_mtu_and_index
38
+ mtu_and_indexes = {}
39
+ output = Facter::Core::Execution.execute('ip link show', logger: log)
40
+ output.each_line do |line|
41
+ next unless line.include?('mtu')
42
+
43
+ parse_ip_command_line(line, mtu_and_indexes)
44
+ end
45
+ log.debug("Associated MTU and index in ip command: #{mtu_and_indexes}")
46
+ mtu_and_indexes
47
+ end
48
+
49
+ def parse_ip_command_line(line, mtu_and_indexes)
50
+ mtu = line.match(/mtu (\d+)/)&.captures&.first&.to_i
51
+ index_tokens = line.split(':')
52
+ index = index_tokens[0].strip
53
+ # vlans are displayed as <vlan_name>@<physical_interface>
54
+ name = index_tokens[1].split('@').first.strip
55
+ mtu_and_indexes[name] = { index: index, mtu: mtu }
56
+ end
57
+
58
+ def retrieve_interfaces_with_socket(mtu_and_indexes)
59
+ require 'socket'
60
+ interfaces = {}
61
+ Socket.getifaddrs.each do |ifaddr|
62
+ populate_interface_info(ifaddr, interfaces, mtu_and_indexes)
63
+ end
64
+
65
+ @fact_list[:interfaces] = interfaces
66
+ end
67
+
68
+ def populate_interface_info(ifaddr, interfaces, mtu_and_indexes)
69
+ interface_name = ifaddr.name
70
+ interfaces[interface_name] = {} if interfaces[interface_name].nil?
71
+ interface_data = interfaces[interface_name]
72
+
73
+ mac(ifaddr, interfaces)
74
+ mtu(ifaddr, interfaces, mtu_and_indexes)
75
+ ip, netmask, ipv4_type = ip_info_of(ifaddr)
76
+ add_binding(interface_data, interface_name, ip, netmask, ipv4_type)
77
+ dhcp(interface_name, mtu_and_indexes[interface_name], interface_data) if interface_data[:dhcp].nil?
78
+ log.debug("Found interface #{interface_name} with #{interface_data}")
79
+ end
80
+
81
+ def mac(ifaddr, interfaces)
82
+ return unless interfaces[ifaddr.name][:mac].nil?
83
+
84
+ mac = search_for_mac(ifaddr)
85
+ interfaces[ifaddr.name][:mac] = mac if mac
86
+ end
87
+
88
+ def search_for_mac(ifaddr)
89
+ mac = mac_from_bonded_interface(ifaddr.name)
90
+ mac ||= mac_from(ifaddr)
91
+ mac if !mac.nil? && mac != '00:00:00:00:00:00' && mac =~ /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/
92
+ end
93
+
94
+ def mac_from_bonded_interface(interface_name)
95
+ master = bond_master_of(interface_name)
96
+ return unless master
97
+
98
+ output = Facter::Util::FileHelper.safe_read("/proc/net/bonding/#{master}", nil)
99
+ return unless output
100
+
101
+ found_match = false
102
+ output.each_line do |line|
103
+ if line.strip == "Slave Interface: #{interface_name}"
104
+ found_match = true
105
+ elsif line.include? 'Slave Interface'
106
+ # if we reached the data block of another interface belonging to the bonded interface
107
+ found_match = false
108
+ end
109
+ return Regexp.last_match(1) if found_match && line =~ /Permanent HW addr: (\S*)/
110
+ end
111
+ end
112
+
113
+ def bond_master_of(interface_name)
114
+ content = Facter::Core::Execution.execute("ip link show #{interface_name}", logger: log)
115
+ content.match(/master (\S*) /)&.captures&.first
116
+ end
117
+
118
+ def mac_from(ifaddr)
119
+ if Socket.const_defined? :PF_LINK
120
+ ifaddr.addr&.getnameinfo&.first # sometimes it returns localhost or ip
121
+ elsif Socket.const_defined? :PF_PACKET
122
+ return if ifaddr.addr.nil?
123
+
124
+ search_mac_in_sockaddr(ifaddr)
125
+ end
126
+ rescue StandardError => e
127
+ log.debug("Could not read mac, got #{e}")
128
+ end
129
+
130
+ def search_mac_in_sockaddr(ifaddr)
131
+ result = ifaddr.addr.inspect_sockaddr
132
+ result&.match(/hwaddr=([\h:]+)/)&.captures&.first
133
+ end
134
+
135
+ def mtu(ifaddr, interfaces, mtu_and_indexes)
136
+ return unless interfaces[ifaddr.name][:mtu].nil?
137
+
138
+ mtu = mtu_and_indexes.dig(ifaddr.name, :mtu)
139
+ interfaces[ifaddr.name][:mtu] = mtu unless mtu.nil?
140
+ end
141
+
142
+ def ip_info_of(ifaddr)
143
+ return if ifaddr.addr.nil? || ifaddr.netmask.nil?
144
+
145
+ # ipv6 ips are retrieved as <ip>%<interface_name>
146
+ ip = ifaddr.addr.ip_address.split('%').first
147
+ netmask = ifaddr.netmask.ip_address
148
+ [ip, netmask, ifaddr.addr.ipv4?]
149
+ rescue StandardError => e
150
+ log.debug("Could not read binding data, got #{e}")
151
+ end
152
+
153
+ def add_binding(interface_data, interface_name, ip, netmask, ip_v4_type)
154
+ binding = Facter::Util::Resolvers::Networking.build_binding(ip, netmask)
155
+ return if binding.nil?
156
+
157
+ log.debug("Adding to interface #{interface_name}, binding:\n#{binding}")
158
+ binding_key = ip_v4_type == true ? :bindings : :bindings6
159
+ interface_data[binding_key] = [] if interface_data[binding_key].nil?
160
+ interface_data[binding_key] << binding
161
+ end
162
+
163
+ def add_info_from_routing_table
164
+ routes4, routes6 = read_routing_table
165
+ compare_ips(routes4, :bindings)
166
+ compare_ips(routes6, :bindings6)
167
+ end
168
+
169
+ def read_routing_table
170
+ ipv4_output = Facter::Core::Execution.execute('ip route show', logger: log)
171
+ ipv6_output = Facter::Core::Execution.execute('ip -6 route show', logger: log)
172
+ routes4 = parse_routes(ipv4_output, true)
173
+ routes6 = parse_routes(ipv6_output, false)
174
+ [routes4, routes6]
175
+ end
176
+
177
+ def parse_routes(output, ipv4_type)
178
+ routes = []
179
+ output.each_line do |line|
180
+ parts = line.split(' ').compact
181
+ next if parts.include?('linkdown')
182
+
183
+ delete_invalid_route_type(parts)
184
+ next if !ipv4_type && !parts[0].include?(':')
185
+
186
+ route = construct_route(parts)
187
+ routes << route unless route[:ip].nil?
188
+ end
189
+ routes.uniq
190
+ end
191
+
192
+ def delete_invalid_route_type(parts)
193
+ route_type = parts[0]
194
+ parts.delete_at(0) if ROUTE_TYPES.include?(route_type)
195
+ end
196
+
197
+ def construct_route(parts)
198
+ route = {}
199
+ dev_index = parts.find_index { |elem| elem == 'dev' }
200
+ src_index = parts.find_index { |elem| elem == 'src' }
201
+ route[:interface] = parts[dev_index + 1] if dev_index
202
+ route[:ip] = parts[src_index + 1] if src_index
203
+ route
204
+ end
205
+
206
+ def compare_ips(routes, binding_key)
207
+ routes.each do |route|
208
+ next unless @fact_list[:interfaces].key?(route[:interface])
209
+
210
+ interface_data = @fact_list[:interfaces][route[:interface]]
211
+ add_binding_if_missing(interface_data, binding_key, route)
212
+ end
213
+ end
214
+
215
+ def add_binding_if_missing(interface_data, binding_key, route)
216
+ interface_binding = interface_data[binding_key]
217
+
218
+ if interface_binding.nil?
219
+ interface_data[binding_key] = [{ address: route[:ip] }]
220
+ elsif interface_binding.none? { |binding| binding[:address] == route[:ip] }
221
+ interface_binding << { address: route[:ip] }
222
+ end
223
+ end
224
+
225
+ def dhcp(interface_name, index_and_mtu, interface_data)
226
+ log.debug("Get DHCP for interface #{interface_name}")
227
+
228
+ search_systemd_netif_leases(interface_data, index_and_mtu)
229
+ search_dhclient_leases(interface_data, interface_name)
230
+ search_internal_leases(interface_data, interface_name)
231
+ search_with_dhcpcd_command(interface_data, interface_name)
232
+ end
233
+
234
+ def search_systemd_netif_leases(interface_data, index_and_mtu)
235
+ return if index_and_mtu.nil?
236
+
237
+ index = index_and_mtu[:index]
238
+ file_content = Facter::Util::FileHelper.safe_read("/run/systemd/netif/leases/#{index}", nil)
239
+ dhcp = file_content.match(/SERVER_ADDRESS=(.*)/) if file_content
240
+ interface_data[:dhcp] = dhcp[1] if dhcp
241
+ end
242
+
243
+ def search_dhclient_leases(interface_data, interface_name)
244
+ return unless interface_data[:dhcp].nil?
245
+
246
+ DIRS.each do |dir|
247
+ next unless File.readable?(dir)
248
+
249
+ lease_files = Dir.entries(dir).select { |file| file =~ /dhclient.*\.lease/ }
250
+ next if lease_files.empty?
251
+
252
+ lease_files.select do |file|
253
+ content = Facter::Util::FileHelper.safe_read("#{dir}#{file}", nil)
254
+ next unless content =~ /interface.*#{interface_name}/
255
+
256
+ dhcp = content.match(/dhcp-server-identifier ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/)
257
+ return interface_data[:dhcp] = dhcp[1] if dhcp
258
+ end
259
+ end
260
+ end
261
+
262
+ def search_internal_leases(interface_data, interface_name)
263
+ return if !interface_data[:dhcp].nil? || !File.readable?('/var/lib/NetworkManager/')
264
+
265
+ files = Dir.entries('/var/lib/NetworkManager/').reject { |dir| dir =~ /^\.+$/ }
266
+ lease_file = files.find { |file| file =~ /internal.*#{interface_name}\.lease/ }
267
+ return unless lease_file
268
+
269
+ dhcp = Facter::Util::FileHelper.safe_read("/var/lib/NetworkManager/#{lease_file}", nil)
270
+
271
+ return unless dhcp
272
+
273
+ dhcp = dhcp.match(/SERVER_ADDRESS=(.*)/)
274
+ interface_data[:dhcp] = dhcp[1] if dhcp
275
+ end
276
+
277
+ def search_with_dhcpcd_command(interface_data, interface_name)
278
+ return unless interface_data[:dhcp].nil?
279
+
280
+ output = Facter::Core::Execution.execute("dhcpcd -U #{interface_name}", logger: log)
281
+ dhcp = output.match(/dhcp_server_identifier='(.*)'/)
282
+ interface_data[:dhcp] = dhcp[1] if dhcp
283
+ end
284
+
285
+ def retrieve_primary_interface
286
+ primary_helper = Facter::Util::Resolvers::Networking::PrimaryInterface
287
+ primary_interface = primary_helper.read_from_proc_route
288
+ primary_interface ||= primary_helper.read_from_ip_route
289
+ primary_interface ||= primary_helper.find_in_interfaces(@fact_list[:interfaces])
290
+
291
+ @fact_list[:primary_interface] = primary_interface
292
+ end
293
+ end
294
+ end
295
+ end
296
+ end