facter 4.0.51 → 4.0.52

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/lib/docs/generate_cli.rb +7 -0
  3. data/lib/facter.rb +57 -44
  4. data/lib/facter/custom_facts/core/aggregate.rb +9 -0
  5. data/lib/facter/custom_facts/core/resolvable.rb +11 -0
  6. data/lib/facter/custom_facts/util/resolution.rb +2 -0
  7. data/lib/facter/facts/amzn/lsbdistcodename.rb +16 -0
  8. data/lib/facter/facts/amzn/lsbdistdescription.rb +16 -0
  9. data/lib/facter/facts/amzn/lsbdistid.rb +16 -0
  10. data/lib/facter/facts/amzn/os/distro/codename.rb +24 -0
  11. data/lib/facter/facts/amzn/os/distro/description.rb +21 -0
  12. data/lib/facter/facts/amzn/os/distro/id.rb +21 -0
  13. data/lib/facter/facts/amzn/os/distro/release.rb +32 -0
  14. data/lib/facter/facts/linux/az_metadata.rb +27 -0
  15. data/lib/facter/facts/linux/cloud/provider.rb +17 -0
  16. data/lib/facter/facts/linux/dhcp_servers.rb +2 -2
  17. data/lib/facter/facts/linux/interfaces.rb +1 -1
  18. data/lib/facter/facts/linux/ipaddress6_interfaces.rb +1 -1
  19. data/lib/facter/facts/linux/ipaddress_interfaces.rb +1 -1
  20. data/lib/facter/facts/linux/macaddress_interfaces.rb +1 -1
  21. data/lib/facter/facts/linux/mtu_interfaces.rb +1 -1
  22. data/lib/facter/facts/linux/netmask6_interfaces.rb +1 -1
  23. data/lib/facter/facts/linux/netmask_interfaces.rb +1 -1
  24. data/lib/facter/facts/linux/network6_interfaces.rb +1 -1
  25. data/lib/facter/facts/linux/network_interfaces.rb +1 -1
  26. data/lib/facter/facts/linux/networking/dhcp.rb +1 -1
  27. data/lib/facter/facts/linux/networking/domain.rb +1 -1
  28. data/lib/facter/facts/linux/networking/fqdn.rb +1 -1
  29. data/lib/facter/facts/linux/networking/hostname.rb +1 -1
  30. data/lib/facter/facts/linux/networking/interfaces.rb +1 -1
  31. data/lib/facter/facts/linux/networking/ip.rb +1 -1
  32. data/lib/facter/facts/linux/networking/ip6.rb +1 -1
  33. data/lib/facter/facts/linux/networking/mac.rb +1 -1
  34. data/lib/facter/facts/linux/networking/mtu.rb +1 -1
  35. data/lib/facter/facts/linux/networking/netmask.rb +1 -1
  36. data/lib/facter/facts/linux/networking/netmask6.rb +1 -1
  37. data/lib/facter/facts/linux/networking/network.rb +1 -1
  38. data/lib/facter/facts/linux/networking/network6.rb +1 -1
  39. data/lib/facter/facts/linux/networking/primary.rb +1 -1
  40. data/lib/facter/facts/linux/networking/scope6.rb +1 -1
  41. data/lib/facter/facts/linux/scope6_interfaces.rb +1 -1
  42. data/lib/facter/facts/rhel/lsbdistcodename.rb +16 -0
  43. data/lib/facter/facts/rhel/lsbdistdescription.rb +16 -0
  44. data/lib/facter/facts/rhel/lsbdistid.rb +16 -0
  45. data/lib/facter/facts/rhel/os/distro/codename.rb +2 -4
  46. data/lib/facter/facts/rhel/os/distro/description.rb +2 -4
  47. data/lib/facter/facts/rhel/os/distro/id.rb +2 -4
  48. data/lib/facter/facts/rhel/os/distro/release.rb +13 -12
  49. data/lib/facter/facts/sles/lsbdistcodename.rb +16 -0
  50. data/lib/facter/facts/sles/lsbdistdescription.rb +16 -0
  51. data/lib/facter/facts/sles/lsbdistid.rb +16 -0
  52. data/lib/facter/facts/sles/os/distro/codename.rb +3 -4
  53. data/lib/facter/facts/sles/os/distro/description.rb +2 -5
  54. data/lib/facter/facts/sles/os/distro/id.rb +6 -5
  55. data/lib/facter/facts/sles/os/distro/release.rb +17 -12
  56. data/lib/facter/facts/ubuntu/lsbdistrelease.rb +2 -2
  57. data/lib/facter/facts/windows/az_metadata.rb +27 -0
  58. data/lib/facter/facts/windows/cloud/provider.rb +17 -0
  59. data/lib/facter/framework/cli/cli.rb +5 -5
  60. data/lib/facter/framework/config/config_reader.rb +2 -0
  61. data/lib/facter/framework/config/fact_groups.rb +25 -2
  62. data/lib/facter/framework/core/cache_manager.rb +5 -1
  63. data/lib/facter/framework/core/fact_filter.rb +3 -3
  64. data/lib/facter/framework/core/fact_loaders/fact_loader.rb +0 -1
  65. data/lib/facter/framework/core/fact_manager.rb +5 -3
  66. data/lib/facter/framework/core/options.rb +1 -2
  67. data/lib/facter/framework/core/options/option_store.rb +1 -3
  68. data/lib/facter/framework/parsers/query_parser.rb +13 -6
  69. data/lib/facter/resolvers/az.rb +39 -0
  70. data/lib/facter/resolvers/linux/hostname.rb +115 -0
  71. data/lib/facter/resolvers/linux/networking.rb +106 -0
  72. data/lib/facter/resolvers/redhat_release.rb +28 -12
  73. data/lib/facter/resolvers/solaris/ffi/functions.rb +1 -1
  74. data/lib/facter/templates/man.erb +8 -0
  75. data/lib/facter/util/linux/dhcp.rb +86 -0
  76. data/lib/facter/util/linux/routing_table.rb +60 -0
  77. data/lib/facter/util/linux/socket_parser.rb +114 -0
  78. data/lib/facter/util/resolvers/ffi/hostname.rb +70 -0
  79. data/lib/facter/version.rb +1 -1
  80. metadata +29 -7
  81. data/lib/facter/facts/linux/cloud.rb +0 -15
  82. data/lib/facter/resolvers/cloud.rb +0 -39
  83. data/lib/facter/resolvers/networking_linux.rb +0 -296
@@ -6,13 +6,12 @@ module Facts
6
6
  module Distro
7
7
  class Codename
8
8
  FACT_NAME = 'os.distro.codename'
9
- ALIASES = 'lsbdistcodename'
10
9
 
11
10
  def call_the_resolver
12
- fact_value = Facter::Resolvers::LsbRelease.resolve(:codename)
11
+ fact_value = Facter::Resolvers::OsRelease.resolve(:version_codename)
12
+ fact_value = 'n/a' if !fact_value || fact_value.empty?
13
13
 
14
- [Facter::ResolvedFact.new(FACT_NAME, fact_value),
15
- Facter::ResolvedFact.new(ALIASES, fact_value, :legacy)]
14
+ Facter::ResolvedFact.new(FACT_NAME, fact_value)
16
15
  end
17
16
  end
18
17
  end
@@ -6,13 +6,10 @@ module Facts
6
6
  module Distro
7
7
  class Description
8
8
  FACT_NAME = 'os.distro.description'
9
- ALIASES = 'lsbdistdescription'
10
9
 
11
10
  def call_the_resolver
12
- fact_value = Facter::Resolvers::LsbRelease.resolve(:description)
13
-
14
- [Facter::ResolvedFact.new(FACT_NAME, fact_value),
15
- Facter::ResolvedFact.new(ALIASES, fact_value, :legacy)]
11
+ fact_value = Facter::Resolvers::OsRelease.resolve(:pretty_name)
12
+ Facter::ResolvedFact.new(FACT_NAME, fact_value)
16
13
  end
17
14
  end
18
15
  end
@@ -6,13 +6,14 @@ module Facts
6
6
  module Distro
7
7
  class Id
8
8
  FACT_NAME = 'os.distro.id'
9
- ALIASES = 'lsbdistid'
10
9
 
11
10
  def call_the_resolver
12
- fact_value = Facter::Resolvers::LsbRelease.resolve(:distributor_id)
13
-
14
- [Facter::ResolvedFact.new(FACT_NAME, fact_value),
15
- Facter::ResolvedFact.new(ALIASES, fact_value, :legacy)]
11
+ fact_value = if Facter::Resolvers::OsRelease.resolve(:version_id).start_with?('12')
12
+ 'SUSE LINUX'
13
+ else
14
+ 'SUSE'
15
+ end
16
+ Facter::ResolvedFact.new(FACT_NAME, fact_value)
16
17
  end
17
18
  end
18
19
  end
@@ -9,20 +9,25 @@ module Facts
9
9
  ALIASES = %w[lsbdistrelease lsbmajdistrelease lsbminordistrelease].freeze
10
10
 
11
11
  def call_the_resolver
12
- fact_value = Facter::Resolvers::LsbRelease.resolve(:release)
13
- return Facter::ResolvedFact.new(FACT_NAME, nil) unless fact_value
12
+ version = Facter::Resolvers::OsRelease.resolve(:version_id)
13
+ fact_value = build_fact_list(version)
14
14
 
15
- versions = fact_value.split('.')
16
- release = {
17
- 'full' => fact_value,
18
- 'major' => versions[0],
19
- 'minor' => versions[1]
20
- }
15
+ [Facter::ResolvedFact.new(FACT_NAME, fact_value),
16
+ Facter::ResolvedFact.new(ALIASES[0], fact_value[:full], :legacy),
17
+ Facter::ResolvedFact.new(ALIASES[1], fact_value[:major], :legacy),
18
+ Facter::ResolvedFact.new(ALIASES[2], fact_value[:minor], :legacy)]
19
+ end
21
20
 
22
- [Facter::ResolvedFact.new(FACT_NAME, release),
23
- Facter::ResolvedFact.new(ALIASES[0], fact_value, :legacy),
24
- Facter::ResolvedFact.new(ALIASES[1], versions[0], :legacy),
25
- Facter::ResolvedFact.new(ALIASES[2], versions[1], :legacy)]
21
+ def build_fact_list(version)
22
+ if version.include?('.')
23
+ {
24
+ full: version,
25
+ major: version.split('.').first,
26
+ minor: version.split('.').last
27
+ }
28
+ else
29
+ { full: version, major: version, minor: nil }
30
+ end
26
31
  end
27
32
  end
28
33
  end
@@ -15,8 +15,8 @@ module Facts
15
15
  version = fact_value.split('.')
16
16
 
17
17
  [Facter::ResolvedFact.new(FACT_NAME, fact_value, :legacy),
18
- Facter::ResolvedFact.new(ALIASES[0], version[0], :legacy),
19
- Facter::ResolvedFact.new(ALIASES[1], version[1], :legacy)]
18
+ Facter::ResolvedFact.new(ALIASES[0], "#{version[0]}.#{version[1]}", :legacy),
19
+ Facter::ResolvedFact.new(ALIASES[1], version[2], :legacy)]
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facts
4
+ module Windows
5
+ class AzMetadata
6
+ FACT_NAME = 'az_metadata'
7
+
8
+ def initialize
9
+ @virtual = Facter::Util::Facts::VirtualDetector.new
10
+ end
11
+
12
+ def call_the_resolver
13
+ return Facter::ResolvedFact.new(FACT_NAME, nil) unless azure_hypervisor?
14
+
15
+ fact_value = Facter::Resolvers::Az.resolve(:metadata)
16
+
17
+ Facter::ResolvedFact.new(FACT_NAME, fact_value&.empty? ? nil : fact_value)
18
+ end
19
+
20
+ private
21
+
22
+ def azure_hypervisor?
23
+ @virtual.platform == 'hyperv'
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facts
4
+ module Windows
5
+ module Cloud
6
+ class Provider
7
+ FACT_NAME = 'cloud.provider'
8
+
9
+ def call_the_resolver
10
+ az_metadata = Facter::Resolvers::Az.resolve(:metadata)
11
+
12
+ Facter::ResolvedFact.new(FACT_NAME, az_metadata&.empty? ? nil : 'azure')
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -134,9 +134,9 @@ module Facter
134
134
 
135
135
  desc '--list-block-groups', 'List block groups'
136
136
  map ['--list-block-groups'] => :list_block_groups
137
- def list_block_groups(*args)
137
+ def list_block_groups
138
138
  options = @options.map { |(k, v)| [k.to_sym, v] }.to_h
139
- Facter::Options.init_from_cli(options, args)
139
+ Facter::Options.init_from_cli(options)
140
140
 
141
141
  block_groups = Facter::FactGroups.new.groups.to_yaml.lines[1..-1].join
142
142
  block_groups.gsub!(/:\s*\n/, "\n")
@@ -146,9 +146,9 @@ module Facter
146
146
 
147
147
  desc '--list-cache-groups', 'List cache groups'
148
148
  map ['--list-cache-groups'] => :list_cache_groups
149
- def list_cache_groups(*args)
149
+ def list_cache_groups
150
150
  options = @options.map { |(k, v)| [k.to_sym, v] }.to_h
151
- Facter::Options.init_from_cli(options, args)
151
+ Facter::Options.init_from_cli(options)
152
152
 
153
153
  cache_groups = Facter::FactGroups.new.groups.to_yaml.lines[1..-1].join
154
154
  cache_groups.gsub!(/:\s*\n/, "\n")
@@ -156,7 +156,7 @@ module Facter
156
156
  puts cache_groups
157
157
  end
158
158
 
159
- desc '--puppet, -p', '(NOT SUPPORTED)Load the Puppet libraries, thus allowing Facter to load Puppet-specific facts.'
159
+ desc '--puppet, -p', 'Load the Puppet libraries, thus allowing Facter to load Puppet-specific facts.'
160
160
  map ['--puppet', '-p'] => :puppet
161
161
  def puppet(*args)
162
162
  Facter.puppet_facts
@@ -45,6 +45,8 @@ module Facter
45
45
  end
46
46
 
47
47
  def default_path
48
+ return '' if RUBY_PLATFORM == 'java'
49
+
48
50
  os = OsDetector.instance.identifier
49
51
 
50
52
  windows_path = File.join('C:', 'ProgramData', 'PuppetLabs', 'facter', 'etc', 'facter.conf')
@@ -7,7 +7,15 @@ module Facter
7
7
  attr_accessor :groups_ttls
8
8
  attr_reader :groups, :block_list, :facts_ttls
9
9
 
10
- STRING_TO_SECONDS = { 'seconds' => 1, 'minutes' => 60, 'hours' => 3600, 'days' => 3600 * 24 }.freeze
10
+ STRING_TO_SECONDS = { 'ns' => 1.fdiv(1_000_000_000), 'nanos' => 1.fdiv(1_000_000_000),
11
+ 'nanoseconds' => 1.fdiv(1_000_000_000),
12
+ 'us' => 1.fdiv(1_000_000), 'micros' => 1.fdiv(1_000_000), 'microseconds' => 1.fdiv(1_000_000),
13
+ '' => 1.fdiv(1000), 'ms' => 1.fdiv(1000), 'milis' => 1.fdiv(1000),
14
+ 'milliseconds' => 1.fdiv(1000),
15
+ 's' => 1, 'seconds' => 1,
16
+ 'm' => 60, 'minutes' => 60,
17
+ 'h' => 3600, 'hours' => 3600,
18
+ 'd' => 3600 * 24, 'days' => 3600 * 24 }.freeze
11
19
 
12
20
  def initialize
13
21
  @groups = Facter::Config::FACT_GROUPS.dup
@@ -103,7 +111,22 @@ module Facter
103
111
 
104
112
  def ttls_to_seconds(ttls)
105
113
  duration, unit = ttls.split(' ', 2)
106
- duration.to_i * STRING_TO_SECONDS[unit]
114
+ unit = '' if duration && !unit
115
+ unit = append_s(unit)
116
+ seconds = STRING_TO_SECONDS[unit]
117
+ if seconds
118
+ (duration.to_i * seconds).to_i
119
+ else
120
+ log = Log.new(self)
121
+ log.error("Could not parse time unit #{unit} (try #{STRING_TO_SECONDS.keys.reject(&:empty?).join(', ')})")
122
+ nil
123
+ end
124
+ end
125
+
126
+ def append_s(unit)
127
+ return unit + 's' if unit.length > 2 && unit[-1] != 's'
128
+
129
+ unit
107
130
  end
108
131
  end
109
132
  end
@@ -209,7 +209,11 @@ cache_format_version is incorrect!")
209
209
  def delete_cache(group_name)
210
210
  cache_file_name = File.join(@cache_dir, group_name)
211
211
 
212
- File.delete(cache_file_name) if File.readable?(cache_file_name)
212
+ begin
213
+ File.delete(cache_file_name) if File.readable?(cache_file_name)
214
+ rescue Errno::EACCES => e
215
+ @log.warn("Could not delete cache: #{e.message}")
216
+ end
213
217
  end
214
218
  end
215
219
  end
@@ -5,8 +5,8 @@ module Facter
5
5
  # e.g. os.release.major is the user query, os.release is the fact
6
6
  # and major is the filter criteria inside tha fact
7
7
  class FactFilter
8
- def filter_facts!(searched_facts)
9
- filter_legacy_facts!(searched_facts)
8
+ def filter_facts!(searched_facts, user_query)
9
+ filter_legacy_facts!(searched_facts) if user_query.empty?
10
10
  filter_blocked_legacy_facts!(searched_facts)
11
11
 
12
12
  searched_facts.each do |fact|
@@ -32,7 +32,7 @@ module Facter
32
32
  end
33
33
 
34
34
  def filter_legacy_facts!(resolved_facts)
35
- return unless !Options[:show_legacy] && Options[:user_query].empty?
35
+ return if Options[:show_legacy]
36
36
 
37
37
  resolved_facts.reject!(&:legacy?)
38
38
  end
@@ -48,7 +48,6 @@ module Facter
48
48
  def load_internal_facts(options)
49
49
  @log.debug('Loading internal facts')
50
50
  internal_facts = []
51
-
52
51
  if options[:user_query] || options[:show_legacy]
53
52
  # if we have a user query, then we must search in core facts and legacy facts
54
53
  @log.debug('Loading all internal facts')
@@ -29,7 +29,7 @@ module Facter
29
29
  resolved_facts = resolved_facts.concat(cached_facts)
30
30
  cache_manager.cache_facts(resolved_facts)
31
31
 
32
- FactFilter.new.filter_facts!(resolved_facts)
32
+ FactFilter.new.filter_facts!(resolved_facts, user_query)
33
33
 
34
34
  log_resolved_facts(resolved_facts)
35
35
  resolved_facts
@@ -40,7 +40,7 @@ module Facter
40
40
 
41
41
  searched_facts = QueryParser.parse(user_query, loaded_facts_hash)
42
42
  resolved_facts = @internal_fact_mgr.resolve_facts(searched_facts)
43
- FactFilter.new.filter_facts!(resolved_facts)
43
+ FactFilter.new.filter_facts!(resolved_facts, user_query)
44
44
 
45
45
  resolved_facts
46
46
  end
@@ -48,7 +48,9 @@ module Facter
48
48
  private
49
49
 
50
50
  def parse_user_query(user_query)
51
- loaded_facts = @fact_loader.load(Options.get)
51
+ options = Options.get
52
+ options[:user_query] = user_query
53
+ loaded_facts = @fact_loader.load(options)
52
54
 
53
55
  QueryParser.parse(user_query, loaded_facts)
54
56
  end
@@ -41,10 +41,9 @@ module Facter
41
41
  store(ConfigFileOptions.get)
42
42
  end
43
43
 
44
- def init_from_cli(cli_options = {}, user_query = nil)
44
+ def init_from_cli(cli_options = {})
45
45
  Facter::OptionStore.cli = true
46
46
  Facter::OptionStore.show_legacy = false
47
- Facter::OptionStore.user_query = user_query
48
47
  Facter::OptionStore.trace = cli_options[:trace]
49
48
  OptionStore.set(:config, cli_options[:config])
50
49
  ConfigFileOptions.init(cli_options[:config])
@@ -13,7 +13,6 @@ module Facter
13
13
  @ruby = true
14
14
  @external_facts = true
15
15
  @config = nil
16
- @user_query = []
17
16
  @strict = false
18
17
  @json = false
19
18
  @cache = true
@@ -41,7 +40,7 @@ module Facter
41
40
  attr_reader :debug, :verbose, :log_level, :show_legacy,
42
41
  :custom_facts, :blocked_facts, :ruby, :external_facts
43
42
 
44
- attr_accessor :config, :user_query, :strict, :json,
43
+ attr_accessor :config, :strict, :json,
45
44
  :cache, :yaml, :puppet, :ttls, :block, :cli, :config_file_custom_dir,
46
45
  :config_file_external_dir, :default_external_dir, :fact_groups,
47
46
  :block_list, :color, :trace, :sequential, :timing, :hocon, :allow_external_loggers
@@ -171,7 +170,6 @@ module Facter
171
170
  @log_level = :warn
172
171
  @show_legacy = true
173
172
  @ruby = true
174
- @user_query = []
175
173
  @json = false
176
174
  @hocon = false
177
175
  @cache = true
@@ -69,12 +69,19 @@ module Facter
69
69
  resolvable_fact_list = []
70
70
 
71
71
  loaded_fact_hash.each do |loaded_fact|
72
- query_fact = query_tokens[query_token_range].join('.')
73
-
74
- next unless found_fact?(loaded_fact.name, query_fact)
75
-
76
- searched_fact = construct_loaded_fact(query_tokens, query_token_range, loaded_fact)
77
- resolvable_fact_list << searched_fact
72
+ # return the fact if toplevel namespace is found in the first query token
73
+ # eg. query: 'os.name' and loaded_fact_hash contains a fact with 'os' name
74
+ # it will construt and return the 'os' fact
75
+ if loaded_fact.name == query_tokens[0]
76
+ resolvable_fact_list = [construct_loaded_fact(query_tokens, query_token_range, loaded_fact)]
77
+ else
78
+ query_fact = query_tokens[query_token_range].join('.')
79
+
80
+ next unless found_fact?(loaded_fact.name, query_fact)
81
+
82
+ searched_fact = construct_loaded_fact(query_tokens, query_token_range, loaded_fact)
83
+ resolvable_fact_list << searched_fact
84
+ end
78
85
  end
79
86
 
80
87
  @log.debug "List of resolvable facts: #{resolvable_fact_list.inspect}"
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facter
4
+ module Resolvers
5
+ class Az < BaseResolver
6
+ init_resolver
7
+
8
+ AZ_METADATA_URL = 'http://169.254.169.254/metadata/instance?api-version=2020-09-01'
9
+ AZ_SESSION_TIMEOUT = 5
10
+
11
+ class << self
12
+ private
13
+
14
+ def post_resolve(fact_name, _options)
15
+ log.debug('Querying Az metadata')
16
+ @fact_list.fetch(fact_name) { read_facts(fact_name) }
17
+ end
18
+
19
+ def read_facts(fact_name)
20
+ @fact_list[:metadata] = {}
21
+ data = get_data_from(AZ_METADATA_URL)
22
+ @fact_list[:metadata] = JSON.parse(data) unless data.empty?
23
+
24
+ @fact_list[fact_name]
25
+ end
26
+
27
+ def get_data_from(url)
28
+ headers = { Metadata: 'true' }
29
+ Facter::Util::Resolvers::Http.get_request(url, headers, { session: determine_session_timeout })
30
+ end
31
+
32
+ def determine_session_timeout
33
+ session_env = ENV['AZ_SESSION_TIMEOUT']
34
+ session_env ? session_env.to_i : AZ_SESSION_TIMEOUT
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facter
4
+ module Resolvers
5
+ module Linux
6
+ class Hostname < BaseResolver
7
+ # :fqdn
8
+ # :domain
9
+ # :hostname
10
+
11
+ init_resolver
12
+
13
+ class << self
14
+ private
15
+
16
+ def post_resolve(fact_name, _options)
17
+ @fact_list.fetch(fact_name) { retrieve_info(fact_name) }
18
+ end
19
+
20
+ def retrieve_info(fact_name)
21
+ require 'socket'
22
+ require 'facter/util/resolvers/ffi/hostname'
23
+
24
+ output = retrieving_hostname
25
+ return nil unless output
26
+
27
+ # Check if the gethostname method retrieved fqdn
28
+ hostname, domain = parse_fqdn(output)
29
+
30
+ fqdn = retrieve_fqdn_for_host(hostname) if hostname_and_no_domain?(hostname, domain)
31
+
32
+ _, domain = parse_fqdn(fqdn) if exists_and_valid_fqdn?(fqdn, hostname)
33
+
34
+ domain = read_domain unless exists_and_not_empty?(domain)
35
+
36
+ construct_fact_list(hostname, domain, fqdn)
37
+ @fact_list[fact_name]
38
+ end
39
+
40
+ def retrieving_hostname
41
+ output = Socket.gethostname
42
+ if !output || output.empty? || output['0.0.0.0']
43
+ output = Facter::Util::Resolvers::Ffi::Hostname.getffihostname
44
+ end
45
+
46
+ log.debug("Tried to retrieve hostname and got: #{output}")
47
+ output && !output.empty? ? output : nil
48
+ end
49
+
50
+ def parse_fqdn(output)
51
+ if output =~ /(.*?)\.(.+$)/
52
+ log.debug("Managed to read hostname: #{Regexp.last_match(1)} and domain: #{Regexp.last_match(2)}")
53
+ [Regexp.last_match(1), Regexp.last_match(2)]
54
+ else
55
+ log.debug("Only managed to read hostname: #{output}, no domain was found.")
56
+ [output, '']
57
+ end
58
+ end
59
+
60
+ def retrieve_fqdn_for_host(host)
61
+ begin
62
+ name = Socket.getaddrinfo(host, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)[0]
63
+ rescue StandardError => e
64
+ log.debug("Socket.getaddrinfo failed to retrieve fqdn for hostname #{host} with: #{e}")
65
+ end
66
+
67
+ return name[2] if !name.nil? && !name.empty? && host != name[2] && name[2] != name[3]
68
+
69
+ retrieve_fqdn_for_host_with_ffi(host)
70
+ end
71
+
72
+ def retrieve_fqdn_for_host_with_ffi(host)
73
+ fqdn = Facter::Util::Resolvers::Ffi::Hostname.getffiaddrinfo(host)
74
+ log.debug("FFI getaddrinfo was called and it retrieved: #{fqdn}")
75
+ fqdn
76
+ end
77
+
78
+ def exists_and_valid_fqdn?(fqdn, hostname)
79
+ exists_and_not_empty?(fqdn) && fqdn.start_with?("#{hostname}.")
80
+ end
81
+
82
+ def hostname_and_no_domain?(hostname, domain)
83
+ domain.empty? && !hostname.empty?
84
+ end
85
+
86
+ def read_domain
87
+ file_content = Facter::Util::FileHelper.safe_read('/etc/resolv.conf')
88
+ if file_content =~ /^domain\s+(\S+)/
89
+ Regexp.last_match(1)
90
+ elsif file_content =~ /^search\s+(\S+)/
91
+ Regexp.last_match(1)
92
+ end
93
+ end
94
+
95
+ def construct_fqdn(host, domain, fqdn)
96
+ return fqdn if exists_and_not_empty?(fqdn)
97
+ return if host.nil? || host.empty?
98
+
99
+ exists_and_not_empty?(domain) ? "#{host}.#{domain}" : host
100
+ end
101
+
102
+ def construct_fact_list(hostname, domain, fqdn)
103
+ @fact_list[:hostname] = hostname
104
+ @fact_list[:domain] = domain
105
+ @fact_list[:fqdn] = construct_fqdn(@fact_list[:hostname], @fact_list[:domain], fqdn)
106
+ end
107
+
108
+ def exists_and_not_empty?(variable)
109
+ variable && !variable.empty?
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end