facter 4.0.39 → 4.0.44

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/bin/facter +3 -4
  3. data/lib/facter.rb +107 -28
  4. data/lib/facter/config.rb +354 -0
  5. data/lib/facter/custom_facts/core/aggregate.rb +51 -17
  6. data/lib/facter/custom_facts/core/execution.rb +27 -35
  7. data/lib/facter/custom_facts/core/execution/base.rb +13 -7
  8. data/lib/facter/custom_facts/util/directory_loader.rb +1 -1
  9. data/lib/facter/custom_facts/util/fact.rb +1 -1
  10. data/lib/facter/custom_facts/util/resolution.rb +40 -11
  11. data/lib/facter/facts/aix/disks.rb +1 -1
  12. data/lib/facter/facts/linux/ec2_metadata.rb +5 -29
  13. data/lib/facter/facts/linux/ec2_userdata.rb +5 -27
  14. data/lib/facter/facts/linux/is_virtual.rb +7 -46
  15. data/lib/facter/facts/linux/virtual.rb +3 -58
  16. data/lib/facter/facts/rhel/os/release.rb +1 -1
  17. data/lib/facter/facts/solaris/disks.rb +1 -1
  18. data/lib/facter/facts/solaris/zones.rb +1 -1
  19. data/lib/facter/facts_utils/virtual_detector.rb +78 -0
  20. data/lib/facter/framework/benchmarking/timer.rb +4 -2
  21. data/lib/facter/framework/cli/cli.rb +83 -36
  22. data/lib/facter/framework/cli/cli_launcher.rb +34 -38
  23. data/lib/facter/framework/config/fact_groups.rb +41 -7
  24. data/lib/facter/framework/core/cache_manager.rb +43 -23
  25. data/lib/facter/framework/core/fact_loaders/fact_loader.rb +14 -11
  26. data/lib/facter/framework/core/options/config_file_options.rb +5 -3
  27. data/lib/facter/framework/core/options/option_store.rb +60 -27
  28. data/lib/facter/framework/detector/os_hierarchy.rb +5 -9
  29. data/lib/facter/framework/logging/logger.rb +1 -5
  30. data/lib/facter/resolvers/aix/architecture_resolver.rb +15 -1
  31. data/lib/facter/resolvers/aix/os_level.rb +1 -1
  32. data/lib/facter/resolvers/augeas_resolver.rb +7 -1
  33. data/lib/facter/resolvers/bsd/processors.rb +11 -7
  34. data/lib/facter/resolvers/disk_resolver.rb +11 -3
  35. data/lib/facter/resolvers/dmi_decode.rb +1 -0
  36. data/lib/facter/resolvers/dmi_resolver.rb +2 -2
  37. data/lib/facter/resolvers/freebsd/geom_resolver.rb +12 -20
  38. data/lib/facter/resolvers/freebsd/processors.rb +11 -7
  39. data/lib/facter/resolvers/memory_resolver.rb +12 -14
  40. data/lib/facter/resolvers/mountpoints_resolver.rb +50 -22
  41. data/lib/facter/resolvers/networking_linux_resolver.rb +10 -5
  42. data/lib/facter/resolvers/partitions.rb +60 -57
  43. data/lib/facter/resolvers/processors_resolver.rb +5 -1
  44. data/lib/facter/resolvers/solaris/dmi.rb +2 -0
  45. data/lib/facter/resolvers/solaris/mountpoints.rb +60 -0
  46. data/lib/facter/resolvers/solaris/networking.rb +1 -2
  47. data/lib/facter/resolvers/solaris/os_release.rb +4 -3
  48. data/lib/facter/resolvers/ssh_resolver.rb +4 -4
  49. data/lib/facter/version.rb +1 -1
  50. metadata +5 -4
  51. data/lib/facter/fact_groups.conf +0 -308
  52. data/lib/facter/os_hierarchy.json +0 -36
@@ -1,29 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'facter/config'
4
+
3
5
  module Facter
4
6
  class OsHierarchy
5
7
  def initialize
6
8
  @log = Log.new(self)
7
- json_file_path = File.join(File.dirname(__FILE__), '../../os_hierarchy.json')
8
- json_file = Util::FileHelper.safe_read(json_file_path)
9
- begin
10
- @json_os_hierarchy = JSON.parse(json_file)
11
- rescue JSON::ParserError => _e
12
- @log.error('Could not parse os_hierarchy json')
13
- end
9
+ @os_hierarchy = Facter::Config::OS_HIERARCHY
14
10
  end
15
11
 
16
12
  def construct_hierarchy(searched_os)
17
13
  return [] if searched_os.nil?
18
14
 
19
15
  searched_os = searched_os.to_s.capitalize
20
- if @json_os_hierarchy.nil?
16
+ if @os_hierarchy.nil?
21
17
  @log.debug("There is no os_hierarchy, will fall back to: #{searched_os}")
22
18
  return [searched_os]
23
19
  end
24
20
 
25
21
  @searched_path = []
26
- search(@json_os_hierarchy, searched_os, [])
22
+ search(@os_hierarchy, searched_os, [])
27
23
 
28
24
  @searched_path.map { |os_name| os_name.to_s.capitalize }
29
25
  end
@@ -91,9 +91,7 @@ module Facter
91
91
  def error(msg, colorize = false)
92
92
  @@has_errors = true
93
93
 
94
- if msg.nil? || msg.empty?
95
- empty_message_error(msg)
96
- elsif @@message_callback
94
+ if @@message_callback
97
95
  @@message_callback.call(:error, msg)
98
96
  else
99
97
  msg = colorize(msg, RED) if colorize || Options[:color]
@@ -111,8 +109,6 @@ module Facter
111
109
  private
112
110
 
113
111
  def colorize(msg, color)
114
- return msg if OsDetector.instance.identifier.eql?(:windows)
115
-
116
112
  "#{color}#{msg}#{RESET}"
117
113
  end
118
114
 
@@ -14,9 +14,11 @@ module Facter
14
14
 
15
15
  def read_architecture(fact_name)
16
16
  require_relative 'utils/odm_query'
17
+
18
+ proc_number = read_proc
17
19
  odmquery = ODMQuery.new
18
20
  odmquery
19
- .equals('name', 'proc0')
21
+ .equals('name', proc_number)
20
22
  .equals('attribute', 'type')
21
23
 
22
24
  result = odmquery.execute
@@ -32,6 +34,18 @@ module Facter
32
34
 
33
35
  @fact_list[fact_name]
34
36
  end
37
+
38
+ def read_proc
39
+ odmquery = ODMQuery.new
40
+ odmquery
41
+ .equals('PdDvLn', 'processor/sys/proc_rspc')
42
+ .equals('status', '1')
43
+
44
+ result = odmquery.execute
45
+ result.each_line do |line|
46
+ return line.split('=')[1].strip.delete('\"') if line.include?('name')
47
+ end
48
+ end
35
49
  end
36
50
  end
37
51
  end
@@ -14,7 +14,7 @@ module Facter
14
14
  end
15
15
 
16
16
  def read_oslevel(fact_name)
17
- output = Facter::Core::Execution.execute('/usr/bin/oslevel -s', { limit: 2, logger: log })
17
+ output = Facter::Core::Execution.execute('/usr/bin/oslevel -s', logger: log)
18
18
  @fact_list[:build] = output unless output.empty?
19
19
  @fact_list[:kernel] = 'AIX'
20
20
 
@@ -20,7 +20,13 @@ module Facter
20
20
  end
21
21
 
22
22
  def read_augeas_from_cli
23
- output = Facter::Core::Execution.execute('augparse --version 2>&1', logger: log)
23
+ command = if File.readable?('/opt/puppetlabs/puppet/bin/augparse')
24
+ '/opt/puppetlabs/puppet/bin/augparse'
25
+ else
26
+ 'augparse'
27
+ end
28
+
29
+ output = Facter::Core::Execution.execute("#{command} --version 2>&1", logger: log)
24
30
  Regexp.last_match(1) if output =~ /^augparse (\d+\.\d+\.\d+)/
25
31
  end
26
32
 
@@ -16,8 +16,12 @@ module Facter
16
16
  def collect_processors_info(fact_name)
17
17
  require 'facter/resolvers/bsd/ffi/ffi_helper'
18
18
 
19
- @fact_list[:logical_count] = logical_count
20
- @fact_list[:models] = Array.new(logical_count, model) if logical_count && model
19
+ count = logical_count
20
+ model = processor_model
21
+ speed = processor_speed
22
+
23
+ @fact_list[:logical_count] = count
24
+ @fact_list[:models] = Array.new(count, model) if count && model
21
25
  @fact_list[:speed] = speed * 1000 * 1000 if speed
22
26
 
23
27
  @fact_list[fact_name]
@@ -28,16 +32,16 @@ module Facter
28
32
  HW_NCPU = 3
29
33
  HW_CPUSPEED = 12
30
34
 
31
- def model
32
- @model ||= Facter::Bsd::FfiHelper.sysctl(:string, [CTL_HW, HW_MODEL])
35
+ def processor_model
36
+ Facter::Bsd::FfiHelper.sysctl(:string, [CTL_HW, HW_MODEL])
33
37
  end
34
38
 
35
39
  def logical_count
36
- @logical_count ||= Facter::Bsd::FfiHelper.sysctl(:uint32_t, [CTL_HW, HW_NCPU])
40
+ Facter::Bsd::FfiHelper.sysctl(:uint32_t, [CTL_HW, HW_NCPU])
37
41
  end
38
42
 
39
- def speed
40
- @speed ||= Facter::Bsd::FfiHelper.sysctl(:uint32_t, [CTL_HW, HW_CPUSPEED])
43
+ def processor_speed
44
+ Facter::Bsd::FfiHelper.sysctl(:uint32_t, [CTL_HW, HW_CPUSPEED])
41
45
  end
42
46
  end
43
47
  end
@@ -7,7 +7,7 @@ module Facter
7
7
  @log = Facter::Log.new(self)
8
8
  @fact_list ||= {}
9
9
  DIR = '/sys/block'
10
- FILE_PATHS = { model: 'device/model', size: 'size', vendor: 'device/vendor' }.freeze
10
+ FILE_PATHS = { model: 'device/model', size: 'size', vendor: 'device/vendor', type: 'queue/rotational' }.freeze
11
11
  class << self
12
12
  private
13
13
 
@@ -25,8 +25,16 @@ module Facter
25
25
  result = Util::FileHelper.safe_read(file_path).strip
26
26
  next if result.empty?
27
27
 
28
- # Linux always considers sectors to be 512 bytes long independently of the devices real block size.
29
- value[key] = file =~ /size/ ? construct_size(value, result) : result
28
+ value[key] = case key
29
+ when :size
30
+ # Linux always considers sectors to be 512 bytes long
31
+ # independently of the devices real block size.
32
+ construct_size(value, result)
33
+ when :type
34
+ result == '0' ? 'ssd' : 'hdd'
35
+ else
36
+ result
37
+ end
30
38
  end
31
39
  end
32
40
 
@@ -37,6 +37,7 @@ module Facter
37
37
  @fact_list[:virtualbox_version] = output.match(/vboxVer_(\S+)/)&.captures&.first
38
38
  @fact_list[:virtualbox_revision] = output.match(/vboxRev_(\S+)/)&.captures&.first
39
39
  @fact_list[:vmware_version] = extract_vmware_version(output)
40
+ @fact_list[:vendor] = output.match(/Vendor: (\S+)/)&.captures&.first
40
41
 
41
42
  @fact_list[fact_name]
42
43
  end
@@ -36,9 +36,9 @@ module Facter
36
36
 
37
37
  file_content = Util::FileHelper.safe_read("/sys/class/dmi/id/#{fact_name}", nil)
38
38
  if files.include?(fact_name.to_s) && file_content
39
- @fact_list[fact_name] = file_content.strip
39
+ file_content = file_content.strip
40
+ @fact_list[fact_name] = file_content unless file_content.empty?
40
41
  chassis_to_name(@fact_list[fact_name]) if fact_name == :chassis_type
41
-
42
42
  end
43
43
  @fact_list[fact_name]
44
44
  end
@@ -5,6 +5,8 @@ module Facter
5
5
  module Freebsd
6
6
  class Geom < BaseResolver
7
7
  @fact_list ||= {}
8
+ DISKS_ATTRIBUTES = %i[read_model read_serial_number read_size].freeze
9
+ PARTITIONS_ATTRIBUTES = %i[read_partlabel read_partuuid read_size].freeze
8
10
 
9
11
  class << self
10
12
  private
@@ -17,37 +19,27 @@ module Facter
17
19
  require_relative 'ffi/ffi_helper'
18
20
  require 'rexml/document'
19
21
 
20
- read_disks
21
- read_partitions
22
+ topology = geom_topology
23
+ read_data('DISK', topology, DISKS_ATTRIBUTES)
24
+ read_data('PART', topology, PARTITIONS_ATTRIBUTES)
22
25
 
23
26
  @fact_list[fact_name]
24
27
  end
25
28
 
26
- def read_disks
27
- @fact_list[:disks] = {}
29
+ def read_data(fact_name, geom_topology, data_to_read)
30
+ fact_list_key = fact_name == 'DISK' ? :disks : :partitions
31
+ @fact_list[fact_list_key] = {}
28
32
 
29
- each_geom_class_provider('DISK') do |provider|
33
+ each_geom_class_provider(fact_name, geom_topology) do |provider|
30
34
  name = provider.get_text('./name').value
31
35
 
32
- @fact_list[:disks][name] = %i[read_model read_serial_number read_size].map do |x|
36
+ @fact_list[fact_list_key][name] = data_to_read.map do |x|
33
37
  send(x, provider)
34
38
  end.inject(:merge)
35
39
  end
36
40
  end
37
41
 
38
- def read_partitions
39
- @fact_list[:partitions] = {}
40
-
41
- each_geom_class_provider('PART') do |provider|
42
- name = provider.get_text('./name').value
43
-
44
- @fact_list[:partitions][name] = %i[read_partlabel read_partuuid read_size].map do |x|
45
- send(x, provider)
46
- end.inject(:merge)
47
- end
48
- end
49
-
50
- def each_geom_class_provider(geom_class_name, &block)
42
+ def each_geom_class_provider(geom_class_name, geom_topology, &block)
51
43
  REXML::XPath.each(geom_topology, "/mesh/class[name/text() = '#{geom_class_name}']/geom/provider", &block)
52
44
  end
53
45
 
@@ -95,7 +87,7 @@ module Facter
95
87
  end
96
88
 
97
89
  def geom_topology
98
- @geom_topology ||= REXML::Document.new(geom_confxml)
90
+ REXML::Document.new(geom_confxml)
99
91
  end
100
92
 
101
93
  def geom_confxml
@@ -18,23 +18,27 @@ module Facter
18
18
  def collect_processors_info(fact_name)
19
19
  require 'facter/resolvers/freebsd/ffi/ffi_helper'
20
20
 
21
- @fact_list[:logical_count] = logical_count
22
- @fact_list[:models] = Array.new(logical_count, model) if logical_count && model
21
+ count = logical_count
22
+ model = processors_model
23
+ speed = processors_speed
24
+
25
+ @fact_list[:logical_count] = count
26
+ @fact_list[:models] = Array.new(count, model) if logical_count && model
23
27
  @fact_list[:speed] = speed * 1000 * 1000 if speed
24
28
 
25
29
  @fact_list[fact_name]
26
30
  end
27
31
 
28
- def model
29
- @model ||= Facter::Freebsd::FfiHelper.sysctl_by_name(:string, 'hw.model')
32
+ def processors_model
33
+ Facter::Freebsd::FfiHelper.sysctl_by_name(:string, 'hw.model')
30
34
  end
31
35
 
32
36
  def logical_count
33
- @logical_count ||= Facter::Freebsd::FfiHelper.sysctl_by_name(:uint32_t, 'hw.ncpu')
37
+ Facter::Freebsd::FfiHelper.sysctl_by_name(:uint32_t, 'hw.ncpu')
34
38
  end
35
39
 
36
- def speed
37
- @speed ||= Facter::Freebsd::FfiHelper.sysctl_by_name(:uint32_t, 'hw.clockrate')
40
+ def processors_speed
41
+ Facter::Freebsd::FfiHelper.sysctl_by_name(:uint32_t, 'hw.clockrate')
38
42
  end
39
43
  end
40
44
  end
@@ -25,11 +25,21 @@ module Facter
25
25
 
26
26
  def read_system(output)
27
27
  @fact_list[:total] = kilobytes_to_bytes(output.match(/MemTotal:\s+(\d+)\s/)[1])
28
- @fact_list[:memfree] = kilobytes_to_bytes(output.match(/MemFree:\s+(\d+)\s/)[1])
29
- @fact_list[:used_bytes] = compute_used(@fact_list[:total], reclaimable_memory(output))
28
+ @fact_list[:memfree] = memfree(output)
29
+ @fact_list[:used_bytes] = compute_used(@fact_list[:total], @fact_list[:memfree])
30
30
  @fact_list[:capacity] = compute_capacity(@fact_list[:used_bytes], @fact_list[:total])
31
31
  end
32
32
 
33
+ def memfree(output)
34
+ available = output.match(/MemAvailable:\s+(\d+)\s/)
35
+ return kilobytes_to_bytes(available[1]) if available
36
+
37
+ buffers = kilobytes_to_bytes(output.match(/Buffers:\s+(\d+)\s/)[1])
38
+ cached = kilobytes_to_bytes(output.match(/Cached:\s+(\d+)\s/)[1])
39
+ memfree = kilobytes_to_bytes(output.match(/MemFree:\s+(\d+)\s/)[1])
40
+ memfree + buffers + cached
41
+ end
42
+
33
43
  def read_swap(output)
34
44
  total = output.match(/SwapTotal:\s+(\d+)\s/)[1]
35
45
  return if total.to_i.zero?
@@ -44,18 +54,6 @@ module Facter
44
54
  quantity.to_i * 1024
45
55
  end
46
56
 
47
- def reclaimable_memory(output)
48
- buffers = kilobytes_to_bytes(output.match(/Buffers:\s+(\d+)\s/)[1])
49
- cached = kilobytes_to_bytes(output.match(/Cached:\s+(\d+)\s/)[1])
50
- s_reclaimable = output.match(/SReclaimable:\s+(\d+)\s/)
51
- s_reclaimable = if s_reclaimable
52
- kilobytes_to_bytes(s_reclaimable[1])
53
- else
54
- 0
55
- end
56
- @fact_list[:memfree] + buffers + cached + s_reclaimable
57
- end
58
-
59
57
  def compute_capacity(used, total)
60
58
  format('%<computed_capacity>.2f', computed_capacity: (used / total.to_f * 100)) + '%'
61
59
  end
@@ -10,13 +10,27 @@ module Facter
10
10
  private
11
11
 
12
12
  def post_resolve(fact_name)
13
- @fact_list.fetch(fact_name) { read_mounts }
13
+ @fact_list.fetch(fact_name) { read_mounts(fact_name) }
14
14
  end
15
15
 
16
16
  def root_device
17
17
  cmdline = Util::FileHelper.safe_read('/proc/cmdline')
18
18
  match = cmdline.match(/root=([^\s]+)/)
19
- match&.captures&.first
19
+ root = match&.captures&.first
20
+
21
+ if !root.nil? && root.include?('=')
22
+ # We are dealing with the PARTUUID of the partition. Need to extract partition path.
23
+ root_partition_path = convert_partuuid_to_path(root)
24
+ root = root_partition_path unless root_partition_path.nil?
25
+ end
26
+ root
27
+ end
28
+
29
+ def convert_partuuid_to_path(root)
30
+ blkid_content = Facter::Core::Execution.execute('blkid', logger: log)
31
+ partuuid = root.split('=').last
32
+ match = blkid_content.match(/(.+)#{partuuid}/)
33
+ match&.captures&.first&.split(':')&.first
20
34
  end
21
35
 
22
36
  def compute_device(device)
@@ -26,32 +40,46 @@ module Facter
26
40
  device
27
41
  end
28
42
 
29
- def read_mounts # rubocop:disable Metrics/AbcSize
43
+ def read_mounts(fact_name)
30
44
  mounts = []
31
- FilesystemHelper.read_mountpoints.each do |fs|
32
- device = compute_device(fs.name)
33
- filesystem = fs.mount_type
34
- path = fs.mount_point
35
- options = fs.options.split(',').map(&:strip)
45
+ FilesystemHelper.read_mountpoints.each do |file_system|
46
+ mount = {}
47
+ get_mount_data(file_system, mount)
36
48
 
37
- next if path =~ %r{^/(proc|sys)} && filesystem != 'tmpfs' || filesystem == 'autofs'
49
+ next if mount[:path] =~ %r{^/(proc|sys)} && mount[:filesystem] != 'tmpfs' || mount[:filesystem] == 'autofs'
38
50
 
39
- stats = FilesystemHelper.read_mountpoint_stats(path)
40
- size_bytes = stats.bytes_total.abs
41
- available_bytes = stats.bytes_available.abs
51
+ get_mount_sizes(mount)
52
+ mounts << mount
53
+ end
42
54
 
43
- used_bytes = stats.bytes_used.abs
44
- total_bytes = used_bytes + available_bytes
45
- capacity = FilesystemHelper.compute_capacity(used_bytes, total_bytes)
55
+ @fact_list[:mountpoints] = mounts
56
+ @fact_list[fact_name]
57
+ end
46
58
 
47
- size = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(size_bytes)
48
- available = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(available_bytes)
49
- used = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(used_bytes)
59
+ def get_mount_data(file_system, mount)
60
+ mount[:device] = compute_device(file_system.name)
61
+ mount[:filesystem] = file_system.mount_type
62
+ mount[:path] = file_system.mount_point
63
+ mount[:options] = file_system.options.split(',').map(&:strip)
64
+ end
50
65
 
51
- mounts << Hash[FilesystemHelper::MOUNT_KEYS.zip(FilesystemHelper::MOUNT_KEYS
52
- .map { |v| binding.local_variable_get(v) })]
53
- end
54
- @fact_list[:mountpoints] = mounts
66
+ def get_mount_sizes(mount)
67
+ stats = FilesystemHelper.read_mountpoint_stats(mount[:path])
68
+
69
+ get_bytes_data(mount, stats)
70
+
71
+ total_bytes = mount[:used_bytes] + mount[:available_bytes]
72
+ mount[:capacity] = FilesystemHelper.compute_capacity(mount[:used_bytes], total_bytes)
73
+
74
+ mount[:size] = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(mount[:size_bytes])
75
+ mount[:available] = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(mount[:available_bytes])
76
+ mount[:used] = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(mount[:used_bytes])
77
+ end
78
+
79
+ def get_bytes_data(mount, stats)
80
+ mount[:size_bytes] = stats.bytes_total.abs
81
+ mount[:available_bytes] = stats.bytes_available.abs
82
+ mount[:used_bytes] = stats.bytes_used.abs
55
83
  end
56
84
  end
57
85
  end
@@ -10,7 +10,6 @@ module Facter
10
10
  private
11
11
 
12
12
  def post_resolve(fact_name)
13
- log.debug('in networking_linux_resolver')
14
13
  @fact_list.fetch(fact_name) { retrieve_network_info(fact_name) }
15
14
 
16
15
  @fact_list[fact_name]
@@ -60,9 +59,14 @@ module Facter
60
59
  return if !network_info[interface_name] || network_info[interface_name][:dhcp]
61
60
 
62
61
  index = tokens[0].delete(':')
63
- dhcp = Util::FileHelper.safe_read("/run/systemd/netif/leases/#{index}", nil)
64
- network_info[interface_name][:dhcp] = dhcp.match(/SERVER_ADDRESS=(.*)/)[1] if dhcp
65
- network_info[interface_name][:dhcp] ||= retrieve_from_other_directories(interface_name)
62
+ file_content = Util::FileHelper.safe_read("/run/systemd/netif/leases/#{index}", nil)
63
+ dhcp = file_content.match(/SERVER_ADDRESS=(.*)/) if file_content
64
+ if dhcp
65
+ network_info[interface_name][:dhcp] = dhcp[1]
66
+ else
67
+ alternate_dhcp = retrieve_from_other_directories(interface_name)
68
+ network_info[interface_name][:dhcp] = alternate_dhcp if alternate_dhcp
69
+ end
66
70
  end
67
71
 
68
72
  def retrieve_from_other_directories(interface_name)
@@ -76,7 +80,8 @@ module Facter
76
80
  content = Util::FileHelper.safe_read("#{dir}#{file}", nil)
77
81
  next unless content =~ /interface.*#{interface_name}/
78
82
 
79
- return content.match(/dhcp-server-identifier ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/)[1]
83
+ dhcp = content.match(/dhcp-server-identifier ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/)
84
+ return dhcp[1] if dhcp
80
85
  end
81
86
  end
82
87
  return unless File.readable?('/var/lib/NetworkManager/')