facter 4.0.47 → 4.0.48

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