facter 4.0.52 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/facter.rb +20 -20
  3. data/lib/facter/custom_facts/core/execution/base.rb +7 -3
  4. data/lib/facter/custom_facts/core/execution/popen3.rb +13 -1
  5. data/lib/facter/custom_facts/util/collection.rb +5 -0
  6. data/lib/facter/custom_facts/util/normalization.rb +7 -2
  7. data/lib/facter/facts/linux/cloud/provider.rb +9 -2
  8. data/lib/facter/facts/linux/hypervisors/xen.rb +2 -4
  9. data/lib/facter/facts/solaris/hypervisors/ldom.rb +1 -1
  10. data/lib/facter/facts/solaris/hypervisors/zone.rb +1 -1
  11. data/lib/facter/facts/solaris/mountpoints.rb +1 -1
  12. data/lib/facter/facts/windows/az_metadata.rb +1 -5
  13. data/lib/facter/facts/windows/cloud/provider.rb +6 -2
  14. data/lib/facter/framework/core/fact_augmenter.rb +21 -4
  15. data/lib/facter/framework/core/fact_loaders/external_fact_loader.rb +9 -6
  16. data/lib/facter/framework/core/fact_loaders/fact_loader.rb +36 -33
  17. data/lib/facter/framework/core/fact_manager.rb +85 -14
  18. data/lib/facter/framework/core/options/config_file_options.rb +7 -0
  19. data/lib/facter/framework/core/options/option_store.rb +3 -1
  20. data/lib/facter/framework/formatters/formatter_helper.rb +3 -5
  21. data/lib/facter/framework/parsers/query_parser.rb +7 -14
  22. data/lib/facter/models/fact_collection.rb +32 -5
  23. data/lib/facter/resolvers/aix/ffi/ffi_helper.rb +1 -1
  24. data/lib/facter/resolvers/base_resolver.rb +2 -2
  25. data/lib/facter/resolvers/dmi_decode.rb +0 -1
  26. data/lib/facter/resolvers/linux/hostname.rb +16 -5
  27. data/lib/facter/resolvers/macosx/mountpoints.rb +14 -1
  28. data/lib/facter/resolvers/networking.rb +1 -1
  29. data/lib/facter/resolvers/selinux.rb +5 -7
  30. data/lib/facter/resolvers/solaris/ffi/structs.rb +12 -0
  31. data/lib/facter/resolvers/solaris/mountpoints.rb +22 -16
  32. data/lib/facter/resolvers/solaris/networking.rb +20 -5
  33. data/lib/facter/resolvers/solaris/zone.rb +0 -1
  34. data/lib/facter/resolvers/windows/uptime.rb +3 -22
  35. data/lib/facter/templates/man.erb +6 -6
  36. data/lib/facter/util/facts/unit_converter.rb +2 -2
  37. data/lib/facter/util/facts/virtual_detector.rb +6 -13
  38. data/lib/facter/util/resolvers/http.rb +7 -1
  39. data/lib/facter/util/resolvers/networking/primary_interface.rb +11 -5
  40. data/lib/facter/util/utils.rb +18 -1
  41. data/lib/facter/version.rb +1 -1
  42. metadata +3 -3
@@ -111,6 +111,18 @@ module Facter
111
111
  self[:sin_addr][:s_addr]
112
112
  end
113
113
  end
114
+
115
+ class In6Addr < ::FFI::Struct
116
+ layout :s_addr, [:uint32_t, 4]
117
+ end
118
+
119
+ class SockaddrIn6 < ::FFI::Struct
120
+ layout :sin6_family, :sa_family_t,
121
+ :sin6_port, :in_port_t,
122
+ :sin6_flowinfo, :uint32_t,
123
+ :sin6_addr, In6Addr,
124
+ :sin6_scope_id, :uint32_t
125
+ end
114
126
  end
115
127
  end
116
128
  end
@@ -14,23 +14,26 @@ module Facter
14
14
  @fact_list.fetch(fact_name) { read_mounts(fact_name) }
15
15
  end
16
16
 
17
- def root_device
18
- cmdline = Facter::Util::FileHelper.safe_read('/proc/cmdline')
19
- match = cmdline.match(/root=([^\s]+)/)
20
- match&.captures&.first
21
- end
22
-
23
- def compute_device(device)
24
- # If the "root" device, lookup the actual device from the kernel options
25
- # This is done because not all systems symlink /dev/root
26
- device = root_device if device == '/dev/root'
27
- device
17
+ def exclude_auto_home_mounts!
18
+ @mounts.reject! do |mount|
19
+ parent = mount[:path].rpartition('/').first
20
+ @auto_home_paths.include?(parent)
21
+ end
28
22
  end
29
23
 
30
24
  def read_mounts(fact_name) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
31
- mounts = []
25
+ @mounts = []
26
+ @auto_home_paths = []
27
+
32
28
  Facter::Util::Resolvers::FilesystemHelper.read_mountpoints.each do |fs|
33
- device = compute_device(fs.name)
29
+ if fs.name == 'auto_home'
30
+ @auto_home_paths << fs.mount_point
31
+ next
32
+ end
33
+
34
+ next if fs.mount_type == 'autofs'
35
+
36
+ device = fs.name
34
37
  filesystem = fs.mount_type
35
38
  path = fs.mount_point
36
39
  options = fs.options.split(',').map(&:strip)
@@ -47,11 +50,14 @@ module Facter
47
50
  available = Facter::Util::Facts::UnitConverter.bytes_to_human_readable(available_bytes)
48
51
  used = Facter::Util::Facts::UnitConverter.bytes_to_human_readable(used_bytes)
49
52
 
50
- mounts << Hash[Facter::Util::Resolvers::FilesystemHelper::MOUNT_KEYS
51
- .zip(Facter::Util::Resolvers::FilesystemHelper::MOUNT_KEYS
53
+ @mounts << Hash[Facter::Util::Resolvers::FilesystemHelper::MOUNT_KEYS
54
+ .zip(Facter::Util::Resolvers::FilesystemHelper::MOUNT_KEYS
52
55
  .map { |v| binding.local_variable_get(v) })]
53
56
  end
54
- @fact_list[:mountpoints] = mounts
57
+
58
+ exclude_auto_home_mounts!
59
+
60
+ @fact_list[:mountpoints] = @mounts
55
61
  @fact_list[fact_name]
56
62
  end
57
63
  end
@@ -101,16 +101,31 @@ module Facter
101
101
  end
102
102
 
103
103
  def inet_ntop(lifreq, ss_family)
104
- sockaddr = FFI::Sockaddr.new(lifreq.lifru_addr.to_ptr)
105
- sockaddr_in = FFI::SockaddrIn.new(sockaddr.to_ptr)
106
- ip = FFI::InAddr.new(sockaddr_in[:sin_addr].to_ptr)
107
- buffer_size = FFI::INET_ADDRSTRLEN
108
- buffer_size = FFI::INET6_ADDRSTRLEN if ss_family == FFI::AF_INET6
104
+ if ss_family == FFI::AF_INET
105
+ buffer_size = FFI::INET_ADDRSTRLEN
106
+ ip = get_ipv4(lifreq)
107
+ else # FFI::AF_INET6
108
+ buffer_size = FFI::INET6_ADDRSTRLEN
109
+ ip = get_ipv6(lifreq)
110
+ end
111
+
109
112
  buffer = ::FFI::MemoryPointer.new(:char, buffer_size)
110
113
 
111
114
  FFI::Ioctl.inet_ntop(ss_family, ip.to_ptr, buffer.to_ptr, buffer.size)
112
115
  end
113
116
 
117
+ def get_ipv4(lifreq)
118
+ sockaddr = FFI::Sockaddr.new(lifreq.lifru_addr.to_ptr)
119
+ sockaddr_in = FFI::SockaddrIn.new(sockaddr.to_ptr)
120
+ FFI::InAddr.new(sockaddr_in[:sin_addr].to_ptr)
121
+ end
122
+
123
+ def get_ipv6(lifreq)
124
+ sockaddr = FFI::Sockaddr.new(lifreq.lifru_addr.to_ptr)
125
+ sockaddr_in6 = FFI::SockaddrIn6.new(sockaddr.to_ptr)
126
+ FFI::In6Addr.new(sockaddr_in6[:sin6_addr].to_ptr)
127
+ end
128
+
114
129
  def count_interfaces
115
130
  lifnum = FFI::Lifnum.new
116
131
  lifnum[:lifn_family] = FFI::AF_UNSPEC
@@ -38,7 +38,6 @@ module Facter
38
38
  uuid: uuid,
39
39
  status: status,
40
40
  path: path
41
-
42
41
  }
43
42
  end
44
43
  zones_fact
@@ -17,7 +17,7 @@ module Facter
17
17
  @fact_list.fetch(fact_name) { calculate_system_uptime(fact_name) }
18
18
  end
19
19
 
20
- def substract_system_uptime_from_ole
20
+ def subtract_system_uptime_from_ole
21
21
  win = Facter::Util::Windows::Win32Ole.new
22
22
  opsystem = win.return_first('SELECT LocalDateTime,LastBootUpTime FROM Win32_OperatingSystem')
23
23
  unless opsystem
@@ -35,35 +35,16 @@ module Facter
35
35
  end
36
36
 
37
37
  def calculate_system_uptime(fact_name)
38
- seconds = substract_system_uptime_from_ole.to_i if substract_system_uptime_from_ole
38
+ seconds = subtract_system_uptime_from_ole&.to_i
39
39
  if !seconds || seconds.negative?
40
40
  @log.debug 'Unable to determine system uptime!'
41
41
  return
42
42
  end
43
43
 
44
- hours = seconds / 3600
45
- days = hours / 24
46
-
47
- result = { seconds: seconds, hours: hours, days: days }
48
-
49
- result[:uptime] = determine_uptime(result)
50
- build_fact_list(result)
51
-
44
+ @fact_list = Facter::Util::Resolvers::UptimeHelper.create_uptime_hash(seconds)
52
45
  @fact_list[fact_name]
53
46
  end
54
47
 
55
- def determine_uptime(result_hash)
56
- minutes = (result_hash[:seconds] - result_hash[:hours] * 3600) / 60
57
-
58
- if result_hash[:days].zero?
59
- "#{result_hash[:hours]}:#{minutes} hours"
60
- elsif result_hash[:days] == 1
61
- "#{result_hash[:days]} day"
62
- else
63
- "#{result_hash[:days]} days"
64
- end
65
- end
66
-
67
48
  def build_fact_list(system_uptime)
68
49
  @fact_list[:days] = system_uptime[:days]
69
50
  @fact_list[:hours] = system_uptime[:hours]
@@ -13,14 +13,14 @@ Many of the command line options can also be set via the HOCON config file. This
13
13
 
14
14
  OPTIONS
15
15
  -------
16
- <% @Facter::Cli.class_options.each do |name, option| -%><% next if option.hide%>
16
+ <% Facter::Cli.class_options.each do |name, option| -%><% next if option.hide%>
17
17
  * `<%= option.aliases[0] + '`, `' if option.aliases.any? %>--<%= 'no-' if negate_options.include?(name.to_s)%><%= name.to_s.gsub('_','-') %>`:
18
18
 
19
19
  <%= option.description %>
20
20
 
21
21
  <% end -%>
22
22
 
23
- <% @Facter::Cli.commands.select { |_k, command_class| command_class.instance_of?(Thor::Command) }.each do |_, command| -%>
23
+ <% Facter::Cli.commands.select { |_k, command_class| command_class.instance_of?(Thor::Command) }.each do |_, command| -%>
24
24
  * `<%= command.usage %>`:
25
25
 
26
26
  <%= command.description %>
@@ -32,7 +32,7 @@ FILES
32
32
  -----
33
33
  <em>/etc/puppetlabs/facter/facter.conf</em>
34
34
 
35
- A HOCON config file that can be used to specify directories for custom and external facts, set various command line options, and specify facts to block. See example below for details, or visit the GitHub README.
35
+ A HOCON config file that can be used to specify directories for custom and external facts, set various command line options, and specify facts to block. See example below for details, or visit the [GitHub README](https://github.com/puppetlabs/puppetlabs-hocon#overview).
36
36
 
37
37
  EXAMPLES
38
38
  --------
@@ -55,7 +55,7 @@ dmi => {
55
55
  version => "6.00"
56
56
  }
57
57
  }
58
- [\.\.\.]
58
+ [...]
59
59
  ```
60
60
 
61
61
  Display a single structured fact:
@@ -91,7 +91,7 @@ $ facter processorcount
91
91
  Format facts as JSON:
92
92
 
93
93
  ```
94
- $ facter \-\-json os.name os.release.major processors.isa
94
+ $ facter --json os.name os.release.major processors.isa
95
95
  {
96
96
  "os.name": "Ubuntu",
97
97
  "os.release.major": "14.04",
@@ -120,7 +120,7 @@ cli : {
120
120
  verbose : false,
121
121
  log-level : "info"
122
122
  }
123
- # always loaded, fact-sepcific configuration
123
+ # always loaded, fact-specific configuration
124
124
  facts : {
125
125
  # for valid blocklist entries, use --list-block-groups
126
126
  blocklist : [ "file system", "EC2" ],
@@ -10,7 +10,7 @@ module Facter
10
10
 
11
11
  value_in_bytes = value_in_bytes.to_i
12
12
 
13
- (value_in_bytes / (1024.0 * 1024.0)).round(2)
13
+ (value_in_bytes / (1024.0 * 1024.0))
14
14
  end
15
15
 
16
16
  def hertz_to_human_readable(speed)
@@ -19,7 +19,7 @@ module Facter
19
19
 
20
20
  validated_speed, metric_prefix = determine_metric_prefix(speed)
21
21
 
22
- format('%<displayed_speed>.2f', displayed_speed: validated_speed).to_s + ' ' + metric_prefix + 'Hz'
22
+ format('%<displayed_speed>.2f', displayed_speed: validated_speed.round(2)).to_s + ' ' + metric_prefix + 'Hz'
23
23
  end
24
24
 
25
25
  def bytes_to_human_readable(bytes)
@@ -9,27 +9,20 @@ module Facter
9
9
  end
10
10
 
11
11
  def platform
12
- fact_value = check_docker_lxc || check_dmi || check_freebsd || check_gce || retrieve_from_virt_what
13
- fact_value ||= check_vmware || check_open_vz || check_vserver || check_xen || check_other_facts
14
- fact_value ||= check_lspci || 'physical'
12
+ @@fact_value ||= check_docker_lxc || check_freebsd || check_gce || retrieve_from_virt_what
13
+ @@fact_value ||= check_vmware || check_open_vz || check_vserver || check_xen || check_other_facts
14
+ @@fact_value ||= check_lspci || 'physical'
15
15
 
16
- fact_value
16
+ @@fact_value
17
17
  end
18
18
 
19
+ private
20
+
19
21
  def check_docker_lxc
20
22
  @log.debug('Checking Docker and LXC')
21
23
  Facter::Resolvers::Containers.resolve(:vm)
22
24
  end
23
25
 
24
- def check_dmi
25
- @log.debug('Checking DMI')
26
- vendor = Facter::Resolvers::DmiDecode.resolve(:vendor)
27
- @log.debug("dmi detected vendor: #{vendor}")
28
- return 'kvm' if vendor =~ /Amazon/
29
-
30
- 'xen' if vendor =~ /Xen/
31
- end
32
-
33
26
  def check_gce
34
27
  @log.debug('Checking GCE')
35
28
  bios_vendor = Facter::Resolvers::Linux::DmiBios.resolve(:bios_vendor)
@@ -10,7 +10,7 @@ module Facter
10
10
  CONNECTION_TIMEOUT = 0.6
11
11
  SESSION_TIMEOUT = 5
12
12
 
13
- # Makes a GET http request and returns it's response.
13
+ # Makes a GET http request and returns its response.
14
14
  #
15
15
  # Params:
16
16
  # url: String which contains the address to which the request will be made
@@ -40,6 +40,12 @@ module Facter
40
40
  http = http_obj(uri, timeouts)
41
41
  request = request_obj(headers, uri, request_type)
42
42
 
43
+ # The Windows implementation of sockets does not respect net/http
44
+ # timeouts, so check if the target is reachable in a different way
45
+ if Gem.win_platform?
46
+ Socket.tcp(uri.host, uri.port, connect_timeout: timeouts[:connection] || CONNECTION_TIMEOUT)
47
+ end
48
+
43
49
  # Make the request
44
50
  response = http.request(request)
45
51
  response.uri = url
@@ -37,11 +37,8 @@ module Facter
37
37
  next if index.zero?
38
38
 
39
39
  route = line.strip.split("\t")
40
- if route.count > 7 &&
41
- route[ROUTE_TABLE_MAPPING['Destination']] == '00000000' &&
42
- route[ROUTE_TABLE_MAPPING['Mask']] == '00000000'
43
- return route[ROUTE_TABLE_MAPPING['Iface']]
44
- end
40
+
41
+ return route[ROUTE_TABLE_MAPPING['Iface']] if valid_default_route?(route)
45
42
  end
46
43
 
47
44
  nil
@@ -74,6 +71,15 @@ module Facter
74
71
 
75
72
  nil
76
73
  end
74
+
75
+ private
76
+
77
+ def valid_default_route?(route)
78
+ route.count > 7 &&
79
+ route[ROUTE_TABLE_MAPPING['Destination']] == '00000000' &&
80
+ route[ROUTE_TABLE_MAPPING['Mask']] == '00000000' &&
81
+ route[ROUTE_TABLE_MAPPING['Iface']] != '*' # `*` represents blackhole and not a valid interface
82
+ end
77
83
  end
78
84
  end
79
85
  end
@@ -4,7 +4,7 @@ module Facter
4
4
  module Utils
5
5
  # Sort nested hash.
6
6
  def self.sort_hash_by_key(hash, recursive = true, &block)
7
- hash.keys.sort(&block).each_with_object({}) do |key, seed|
7
+ hash.keys.sort(&block).each_with_object(hash.class.new) do |key, seed|
8
8
  seed[key] = hash[key]
9
9
  seed[key] = sort_hash_by_key(seed[key], true, &block) if recursive && seed[key].is_a?(Hash)
10
10
 
@@ -29,5 +29,22 @@ module Facter
29
29
  object
30
30
  end
31
31
  end
32
+
33
+ def self.try_to_bool(value)
34
+ case value.to_s
35
+ when 'true'
36
+ true
37
+ when 'false'
38
+ false
39
+ else
40
+ value
41
+ end
42
+ end
43
+
44
+ def self.try_to_int(value)
45
+ Integer(value)
46
+ rescue ArgumentError, TypeError
47
+ value
48
+ end
32
49
  end
33
50
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Facter
4
- VERSION = '4.0.52' unless defined?(VERSION)
4
+ VERSION = '4.1.0' 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.0.52
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-16 00:00:00.000000000 Z
11
+ date: 2021-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -1043,7 +1043,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1043
1043
  - !ruby/object:Gem::Version
1044
1044
  version: '0'
1045
1045
  requirements: []
1046
- rubygems_version: 3.0.0
1046
+ rubygems_version: 3.0.8
1047
1047
  signing_key:
1048
1048
  specification_version: 4
1049
1049
  summary: New version of Facter