facter 4.0.44 → 4.0.46

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/lib/facter.rb +15 -1
  3. data/lib/facter/config.rb +1 -0
  4. data/lib/facter/custom_facts/core/execution.rb +28 -4
  5. data/lib/facter/custom_facts/core/execution/base.rb +33 -33
  6. data/lib/facter/custom_facts/util/parser.rb +17 -3
  7. data/lib/facter/facts/solaris/hypervisors/ldom.rb +3 -0
  8. data/lib/facter/facts/solaris/ldom.rb +4 -1
  9. data/lib/facter/framework/cli/cli.rb +19 -5
  10. data/lib/facter/framework/config/fact_groups.rb +5 -3
  11. data/lib/facter/framework/core/cache_manager.rb +57 -15
  12. data/lib/facter/framework/core/fact/internal/core_fact.rb +6 -1
  13. data/lib/facter/framework/core/fact/internal/internal_fact_manager.rb +38 -4
  14. data/lib/facter/framework/core/fact_augmenter.rb +1 -1
  15. data/lib/facter/framework/core/fact_loaders/fact_loader.rb +1 -1
  16. data/lib/facter/framework/core/fact_manager.rb +1 -1
  17. data/lib/facter/framework/core/options/config_file_options.rb +16 -5
  18. data/lib/facter/framework/core/options/option_store.rb +7 -3
  19. data/lib/facter/resolvers/aio_agent_version.rb +1 -1
  20. data/lib/facter/resolvers/aix/architecture_resolver.rb +2 -1
  21. data/lib/facter/resolvers/aix/disks.rb +2 -1
  22. data/lib/facter/resolvers/aix/filesystem_resolver.rb +1 -1
  23. data/lib/facter/resolvers/aix/hardware_resolver.rb +2 -1
  24. data/lib/facter/resolvers/aix/load_averages_resolver.rb +2 -1
  25. data/lib/facter/resolvers/aix/memory.rb +2 -1
  26. data/lib/facter/resolvers/aix/mountpoints.rb +2 -1
  27. data/lib/facter/resolvers/aix/networking_resolver.rb +1 -1
  28. data/lib/facter/resolvers/aix/nim.rb +1 -1
  29. data/lib/facter/resolvers/aix/os_level.rb +1 -1
  30. data/lib/facter/resolvers/aix/partitions.rb +2 -1
  31. data/lib/facter/resolvers/aix/processors.rb +2 -1
  32. data/lib/facter/resolvers/aix/serialnumber.rb +1 -1
  33. data/lib/facter/resolvers/augeas_resolver.rb +1 -1
  34. data/lib/facter/resolvers/base_resolver.rb +11 -4
  35. data/lib/facter/resolvers/bsd/processors.rb +2 -1
  36. data/lib/facter/resolvers/cloud.rb +1 -1
  37. data/lib/facter/resolvers/containers.rb +2 -1
  38. data/lib/facter/resolvers/debian_version.rb +1 -1
  39. data/lib/facter/resolvers/disk_resolver.rb +4 -1
  40. data/lib/facter/resolvers/dmi_decode.rb +1 -1
  41. data/lib/facter/resolvers/dmi_resolver.rb +2 -1
  42. data/lib/facter/resolvers/ec2.rb +2 -1
  43. data/lib/facter/resolvers/eos_release_resolver.rb +1 -1
  44. data/lib/facter/resolvers/facterversion_resolver.rb +1 -1
  45. data/lib/facter/resolvers/filesystems_resolver.rb +4 -1
  46. data/lib/facter/resolvers/fips_enabled_resolver.rb +4 -1
  47. data/lib/facter/resolvers/freebsd/dmi_resolver.rb +1 -1
  48. data/lib/facter/resolvers/freebsd/freebsd_version_resolver.rb +9 -7
  49. data/lib/facter/resolvers/freebsd/geom_resolver.rb +2 -1
  50. data/lib/facter/resolvers/freebsd/processors.rb +2 -1
  51. data/lib/facter/resolvers/freebsd/swap_memory_resolver.rb +2 -1
  52. data/lib/facter/resolvers/freebsd/system_memory_resolver.rb +2 -1
  53. data/lib/facter/resolvers/gce.rb +2 -1
  54. data/lib/facter/resolvers/hostname_resolver.rb +2 -1
  55. data/lib/facter/resolvers/identity_resolver.rb +2 -1
  56. data/lib/facter/resolvers/linux/docker_uptime.rb +2 -1
  57. data/lib/facter/resolvers/linux/load_averages.rb +2 -1
  58. data/lib/facter/resolvers/load_averages.rb +2 -1
  59. data/lib/facter/resolvers/lpar_resolver.rb +1 -1
  60. data/lib/facter/resolvers/lsb_release_resolver.rb +1 -1
  61. data/lib/facter/resolvers/lspci.rb +1 -1
  62. data/lib/facter/resolvers/macosx/dmi_resolver.rb +1 -1
  63. data/lib/facter/resolvers/macosx/filesystems_resolver.rb +1 -1
  64. data/lib/facter/resolvers/macosx/load_averages_resolver.rb +2 -1
  65. data/lib/facter/resolvers/macosx/mountpoints_resolver.rb +2 -1
  66. data/lib/facter/resolvers/macosx/processor_resolver.rb +2 -1
  67. data/lib/facter/resolvers/macosx/swap_memory_resolver.rb +2 -1
  68. data/lib/facter/resolvers/macosx/system_memory_resolver.rb +2 -1
  69. data/lib/facter/resolvers/macosx/system_profiler_resolver.rb +1 -3
  70. data/lib/facter/resolvers/memory_resolver.rb +3 -1
  71. data/lib/facter/resolvers/mountpoints_resolver.rb +4 -1
  72. data/lib/facter/resolvers/networking_linux_resolver.rb +5 -4
  73. data/lib/facter/resolvers/networking_resolver.rb +1 -1
  74. data/lib/facter/resolvers/open_vz.rb +1 -1
  75. data/lib/facter/resolvers/os_release_resolver.rb +1 -1
  76. data/lib/facter/resolvers/partitions.rb +2 -1
  77. data/lib/facter/resolvers/path_resolver.rb +1 -1
  78. data/lib/facter/resolvers/processors_resolver.rb +4 -1
  79. data/lib/facter/resolvers/puppet_version_resolver.rb +1 -1
  80. data/lib/facter/resolvers/redhat_release_resolver.rb +1 -1
  81. data/lib/facter/resolvers/ruby_resolver.rb +1 -1
  82. data/lib/facter/resolvers/selinux_resolver.rb +1 -1
  83. data/lib/facter/resolvers/solaris/disks.rb +1 -1
  84. data/lib/facter/resolvers/solaris/dmi.rb +1 -1
  85. data/lib/facter/resolvers/solaris/dmi_sparc.rb +1 -1
  86. data/lib/facter/resolvers/solaris/filesystems.rb +1 -1
  87. data/lib/facter/resolvers/solaris/ipaddress.rb +2 -1
  88. data/lib/facter/resolvers/solaris/ldom.rb +1 -3
  89. data/lib/facter/resolvers/solaris/memory.rb +2 -1
  90. data/lib/facter/resolvers/solaris/mountpoints.rb +2 -2
  91. data/lib/facter/resolvers/solaris/networking.rb +1 -1
  92. data/lib/facter/resolvers/solaris/os_release.rb +2 -1
  93. data/lib/facter/resolvers/solaris/processors.rb +2 -1
  94. data/lib/facter/resolvers/solaris/zone.rb +1 -1
  95. data/lib/facter/resolvers/solaris/zone_name.rb +1 -1
  96. data/lib/facter/resolvers/ssh_resolver.rb +4 -1
  97. data/lib/facter/resolvers/suse_release_resolver.rb +1 -1
  98. data/lib/facter/resolvers/sw_vers_resolver.rb +2 -2
  99. data/lib/facter/resolvers/timezone_resolver.rb +1 -1
  100. data/lib/facter/resolvers/uname_resolver.rb +1 -1
  101. data/lib/facter/resolvers/uptime_resolver.rb +1 -1
  102. data/lib/facter/resolvers/utils/networking.rb +2 -0
  103. data/lib/facter/resolvers/virt_what.rb +1 -1
  104. data/lib/facter/resolvers/vmware.rb +1 -1
  105. data/lib/facter/resolvers/windows/aio_agent_version.rb +1 -1
  106. data/lib/facter/resolvers/windows/dmi_bios_resolver.rb +1 -1
  107. data/lib/facter/resolvers/windows/dmi_computersystem_resolver.rb +1 -1
  108. data/lib/facter/resolvers/windows/fips_resolver.rb +2 -1
  109. data/lib/facter/resolvers/windows/hardware_architecture_resolver.rb +2 -1
  110. data/lib/facter/resolvers/windows/identity_resolver.rb +2 -1
  111. data/lib/facter/resolvers/windows/kernel_resolver.rb +3 -1
  112. data/lib/facter/resolvers/windows/memory_resolver.rb +3 -1
  113. data/lib/facter/resolvers/windows/netkvm_resolver.rb +2 -1
  114. data/lib/facter/resolvers/windows/networking_resolver.rb +2 -1
  115. data/lib/facter/resolvers/windows/processors_resolver.rb +2 -1
  116. data/lib/facter/resolvers/windows/product_release_resolver.rb +2 -1
  117. data/lib/facter/resolvers/windows/ssh.rb +3 -1
  118. data/lib/facter/resolvers/windows/system32_resolver.rb +3 -1
  119. data/lib/facter/resolvers/windows/uptime_resolver.rb +2 -1
  120. data/lib/facter/resolvers/windows/virtualization_resolver.rb +2 -1
  121. data/lib/facter/resolvers/windows/win_os_description_resolver.rb +3 -1
  122. data/lib/facter/resolvers/wpar_resolver.rb +1 -1
  123. data/lib/facter/resolvers/xen.rb +1 -1
  124. data/lib/facter/resolvers/zfs.rb +2 -1
  125. data/lib/facter/resolvers/zpool.rb +2 -1
  126. data/lib/facter/version.rb +1 -1
  127. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 26e4084c96b8e155bea96be6eb69c241acf2974bf31d98ebc20a571f191e3083
4
- data.tar.gz: 8cfb10254f2474b003c7d5f4739b455302546258b3dd0b65b1768df6e1a38b1e
3
+ metadata.gz: 71eb4894f5e565033d547ffb64d562aee98c6b6a082bca7387259f9a779830d8
4
+ data.tar.gz: 95331a72cf0dc86fabbcad33447724a3a55b536c366bb8ba356428fddefd1587
5
5
  SHA512:
6
- metadata.gz: 74e4755e3dedc6aedcba900d72577faa265f889b31b7ae60f6c85f0221f1e96f748c8b1342d9fc6ea7eafdf57dcacb675f3001465892b968f076c18432cfe9b7
7
- data.tar.gz: cc030bcb93b65dddf47b5fdbbe39487a95f08794caf0f60985134c733f74a98ede9d0822c3647e9e0ab634eb9c336dd4a33a6f22d26ab8438f105787fbe74614
6
+ metadata.gz: 24caa700190be726fa0a7dc0f7dbbac290e073fab078c32b2b67d8a79c336daeab4c3254389a58e7bb4538706c8b8114d609173b78c31e7d676ca50d21a3bcb7
7
+ data.tar.gz: 9edcd692bfe2b0de59a6a6bf6f1700387e25da56127148ffd656edb901fc7fa47db7fe61eae3e4bf17ac8ddaa17e655c65ed366ef3fcc79db2a28e20ab1e6a37
@@ -177,6 +177,18 @@ module Facter
177
177
  Facter::Options[:debug] = debug_bool
178
178
  end
179
179
 
180
+ def enable_sequential
181
+ Facter::Options[:sequential] = true
182
+ end
183
+
184
+ def disable_sequential
185
+ Facter::Options[:sequential] = false
186
+ end
187
+
188
+ def sequential?
189
+ Facter::Options[:sequential]
190
+ end
191
+
180
192
  # Iterates over fact names and values
181
193
  #
182
194
  # @yieldparam [String] name the fact name
@@ -339,13 +351,15 @@ module Facter
339
351
  # @param options [Hash] parameters for the fact - attributes
340
352
  # of {Facter::Util::Fact} and {Facter::Util::Resolution} can be
341
353
  # supplied here
342
- # @param user_queries [String] the fact names
354
+ # @param user_queries [Array] the fact names
343
355
  #
344
356
  # @return [FactCollection] hash with fact names and values
345
357
  #
346
358
  # @api public
347
359
  def values(options, user_queries)
348
360
  init_cli_options(options, user_queries)
361
+ Options[:show_legacy] = true
362
+ log_blocked_facts
349
363
  resolved_facts = Facter::FactManager.instance.resolve_facts(user_queries)
350
364
 
351
365
  if user_queries.count.zero?
@@ -117,6 +117,7 @@ module Facter
117
117
  domain
118
118
  fqdn
119
119
  dhcp_servers
120
+ scope6
120
121
  ],
121
122
  'operating system' => %w[
122
123
  os
@@ -98,16 +98,19 @@ module Facter
98
98
  # Execute a command and return the output of that program.
99
99
  # @param command [String] Command to run
100
100
  #
101
- # @param options [Hash] Hash with options for the aggregate fact
101
+ # @param options [Hash] Hash with options for the command
102
102
  #
103
- # @option options [Object] :on_fail How to behave when the command could
103
+ # Options accepted values :on_fail How to behave when the command could
104
104
  # not be run. Specifying :raise will raise an error, anything else will
105
105
  # return that object on failure. Default is :raise.
106
+ # :logger Optional logger used to log the command's stderr.
107
+ # :time_limit Optional time out for the specified command. If no time_limit is passed,
108
+ # a default of 300 seconds is used.
106
109
  #
107
110
  # @raise [Facter::Core::Execution::ExecutionFailure] If the command does
108
- # not exist or could not be executed.
111
+ # not exist or could not be executed and :on_fail is set to :raise
109
112
  #
110
- # @return [String] the output of the program, or the value of :on_fail if
113
+ # @return [String] the output of the program, or the value of :on_fail (if it's different than :raise) if
111
114
  # command execution failed and :on_fail was specified.
112
115
  #
113
116
  # @api public
@@ -115,6 +118,27 @@ module Facter
115
118
  @@impl.execute(command, options)
116
119
  end
117
120
 
121
+ # Execute a command and return the stdout and stderr of that program.
122
+ # @param command [String] Command to run
123
+ #
124
+ # @param on_fail[Object] How to behave when the command could
125
+ # not be run. Specifying :raise will raise an error, anything else will
126
+ # return that object on failure. Default is :raise.
127
+ # @param logger Optional logger used to log the command's stderr.
128
+ # @param time_limit Optional time out for the specified command. If no time_limit is passed,
129
+ # a default of 300 seconds is used.
130
+ #
131
+ # @raise [Facter::Core::Execution::ExecutionFailure] If the command does
132
+ # not exist or could not be executed and :on_fail is set to :raise
133
+ #
134
+ # @return [String, String] the stdout and stderr of the program, or the value of
135
+ # :on_fail if command execution failed and :on_fail was specified.
136
+ #
137
+ # @api private
138
+ def execute_command(command, on_fail = nil, logger = nil, time_limit = nil)
139
+ @@impl.execute_command(command, on_fail, logger, time_limit)
140
+ end
141
+
118
142
  class ExecutionFailure < StandardError; end
119
143
  end
120
144
  end
@@ -4,7 +4,7 @@ module Facter
4
4
  module Core
5
5
  module Execution
6
6
  class Base
7
- STDERR_MESSAGE = 'Command %s resulted with the following stderr message: %s'
7
+ STDERR_MESSAGE = 'Command %s completed with the following stderr message: %s'
8
8
 
9
9
  def initialize
10
10
  @log = Log.new(self)
@@ -57,39 +57,11 @@ module Facter
57
57
  return on_fail
58
58
  end
59
59
 
60
- execute_command(expanded_command, on_fail, logger, time_limit)
60
+ out, = execute_command(expanded_command, on_fail, logger, time_limit)
61
+ out
61
62
  end
62
63
 
63
- private
64
-
65
- def extract_options(options)
66
- on_fail = options.fetch(:on_fail, :raise)
67
- expand = options.fetch(:expand, true)
68
- logger = options[:logger]
69
- time_limit = options[:limit].to_i
70
- time_limit = time_limit.positive? ? time_limit : nil
71
-
72
- [on_fail, expand, logger, time_limit]
73
- end
74
-
75
- def log_stderr(msg, command, logger)
76
- return if !msg || msg.empty?
77
-
78
- if logger
79
- logger.debug(format(STDERR_MESSAGE, command, msg.strip))
80
- else
81
- file_name = command.split('/').last
82
- logger = Facter::Log.new(file_name)
83
- logger.warn(format(STDERR_MESSAGE, command, msg.strip))
84
- end
85
- end
86
-
87
- def builtin_command?(command)
88
- output, _status = Open3.capture2("type #{command}")
89
- output.chomp =~ /builtin/ ? true : false
90
- end
91
-
92
- def execute_command(command, on_fail, logger = nil, time_limit = nil)
64
+ def execute_command(command, on_fail = nil, logger = nil, time_limit = nil)
93
65
  time_limit ||= 300
94
66
  begin
95
67
  # Set LC_ALL and LANG to force i18n to C for the duration of this exec;
@@ -128,7 +100,35 @@ module Facter
128
100
  "Failed while executing '#{command}': #{e.message}"
129
101
  end
130
102
 
131
- out.strip
103
+ [out.strip, stderr]
104
+ end
105
+
106
+ private
107
+
108
+ def extract_options(options)
109
+ on_fail = options.fetch(:on_fail, :raise)
110
+ expand = options.fetch(:expand, true)
111
+ logger = options[:logger]
112
+ time_limit = options[:limit].to_i
113
+ time_limit = time_limit.positive? ? time_limit : nil
114
+
115
+ [on_fail, expand, logger, time_limit]
116
+ end
117
+
118
+ def log_stderr(msg, command, logger)
119
+ return if !msg || msg.empty?
120
+
121
+ unless logger
122
+ file_name = command.split('/').last
123
+ logger = Facter::Log.new(file_name)
124
+ end
125
+
126
+ logger.debug(format(STDERR_MESSAGE, command, msg.strip))
127
+ end
128
+
129
+ def builtin_command?(command)
130
+ output, _status = Open3.capture2("type #{command}")
131
+ output.chomp =~ /builtin/ ? true : false
132
132
  end
133
133
  end
134
134
  end
@@ -8,6 +8,8 @@
8
8
  module LegacyFacter
9
9
  module Util
10
10
  module Parser
11
+ STDERR_MESSAGE = 'Command %s completed with the following stderr message: %s'
12
+
11
13
  @parsers = []
12
14
 
13
15
  # For support mutliple extensions you can pass an array of extensions as
@@ -75,6 +77,15 @@ module LegacyFacter
75
77
  res = KeyValuePairOutputFormat.parse output unless res.is_a?(Hash)
76
78
  res
77
79
  end
80
+
81
+ def log_stderr(msg, command, file)
82
+ return if !msg || msg.empty?
83
+
84
+ file_name = file.split('/').last
85
+ logger = Facter::Log.new(file_name)
86
+
87
+ logger.warn(format(STDERR_MESSAGE, command, msg.strip))
88
+ end
78
89
  end
79
90
 
80
91
  module KeyValuePairOutputFormat
@@ -139,7 +150,9 @@ module LegacyFacter
139
150
 
140
151
  class ScriptParser < Base
141
152
  def parse_results
142
- parse_executable_output(Facter::Core::Execution.exec(quote(filename)))
153
+ stdout, stderr = Facter::Core::Execution.execute_command(quote(filename))
154
+ log_stderr(stderr, filename, filename)
155
+ parse_executable_output(stdout)
143
156
  end
144
157
 
145
158
  private
@@ -172,8 +185,9 @@ module LegacyFacter
172
185
 
173
186
  shell_command =
174
187
  "\"#{powershell}\" -NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass -File \"#{filename}\""
175
- output = Facter::Core::Execution.exec(shell_command)
176
- parse_executable_output(output)
188
+ stdout, stderr = Facter::Core::Execution.execute_command(shell_command)
189
+ log_stderr(stderr, shell_command, filename)
190
+ parse_executable_output(stdout)
177
191
  end
178
192
  end
179
193
 
@@ -11,6 +11,9 @@ module Facts
11
11
  end
12
12
 
13
13
  def call_the_resolver
14
+ chassis_serial = Facter::Resolvers::Solaris::Ldom.resolve(:chassis_serial)
15
+ return Facter::ResolvedFact.new(FACT_NAME, nil) if !chassis_serial || chassis_serial.empty?
16
+
14
17
  fact_value = %i[
15
18
  chassis_serial control_domain domain_name
16
19
  domain_uuid role_control role_io role_root role_service
@@ -10,8 +10,11 @@ module Facts
10
10
  end
11
11
 
12
12
  def call_the_resolver
13
+ chassis_serial = resolve(:chassis_serial)
14
+ return Facter::ResolvedFact.new(FACT_NAME, nil) if !chassis_serial || chassis_serial.empty?
15
+
13
16
  fact_value = {
14
- domainchassis: resolve(:chassis_serial),
17
+ domainchassis: chassis_serial,
15
18
  domaincontrol: resolve(:control_domain),
16
19
  domainname: resolve(:domain_name),
17
20
  domainrole: {
@@ -79,11 +79,6 @@ module Facter
79
79
  type: :boolean,
80
80
  desc: 'Show legacy facts when querying all facts.'
81
81
 
82
- class_option :puppet,
83
- type: :boolean,
84
- aliases: '-p',
85
- desc: 'Load the Puppet libraries, thus allowing Facter to load Puppet-specific facts.'
86
-
87
82
  class_option :yaml,
88
83
  aliases: '-y',
89
84
  type: :boolean,
@@ -98,6 +93,10 @@ module Facter
98
93
  aliases: '-t',
99
94
  desc: 'Show how much time it took to resolve each fact'
100
95
 
96
+ class_option :sequential,
97
+ type: :boolean,
98
+ desc: 'Resolve facts sequentially'
99
+
101
100
  desc '--man', 'Display manual.', hide: true
102
101
  map ['--man'] => :man
103
102
  def man(*args)
@@ -157,6 +156,20 @@ module Facter
157
156
  puts cache_groups
158
157
  end
159
158
 
159
+ desc '--puppet, -p', '(NOT SUPPORTED)Load the Puppet libraries, thus allowing Facter to load Puppet-specific facts.'
160
+ map ['--puppet', '-p'] => :puppet
161
+ def puppet(*args)
162
+ log = Log.new(self)
163
+ log.warn('`facter --puppet` and `facter -p` are no longer supported, use `puppet facts show` instead')
164
+ log.warn('the output does not contain puppet facts!')
165
+
166
+ output, status = Facter.to_user_output(@options, *args)
167
+ puts output
168
+
169
+ status = 1 if Facter::Log.errors?
170
+ exit status
171
+ end
172
+
160
173
  desc 'help', 'Help for all arguments'
161
174
  def help(*args)
162
175
  help_string = +''
@@ -201,6 +214,7 @@ module Facter
201
214
  end
202
215
 
203
216
  def build_option(name, aliases, description)
217
+ name = name.tr('_', '-')
204
218
  help_option = +''
205
219
  help_option << aliases.join(',').rjust(10)
206
220
  help_option << ' '
@@ -4,10 +4,9 @@ require 'facter/config'
4
4
 
5
5
  module Facter
6
6
  class FactGroups
7
+ attr_accessor :groups_ttls
7
8
  attr_reader :groups, :block_list, :facts_ttls
8
9
 
9
- @groups_ttls = []
10
-
11
10
  STRING_TO_SECONDS = { 'seconds' => 1, 'minutes' => 60, 'hours' => 3600, 'days' => 3600 * 24 }.freeze
12
11
 
13
12
  def initialize
@@ -38,7 +37,10 @@ module Facter
38
37
  fact = get_fact(fact_name)
39
38
  return fact[:group] if fact
40
39
 
41
- @groups.detect { |k, v| break k if Array(v).find { |f| fact_name =~ /^#{f}.*/ } }
40
+ # @groups.detect { |k, v| break k if Array(v).find { |f| fact_name =~ /^#{f}.*/ } }
41
+ @groups.detect do |k, v|
42
+ break k if Array(v).find { |f| fact_name.include?('.*') ? fact_name == f : fact_name =~ /^#{f}.*/ }
43
+ end
42
44
  end
43
45
 
44
46
  # Get config ttls for a given group
@@ -10,7 +10,7 @@ module Facter
10
10
  end
11
11
 
12
12
  def resolve_facts(searched_facts)
13
- return searched_facts, [] if !File.directory?(@cache_dir) || !Options[:cache]
13
+ return searched_facts, [] if (!File.directory?(@cache_dir) || !Options[:cache]) && Options[:ttls].any?
14
14
 
15
15
  facts = []
16
16
  searched_facts.delete_if do |fact|
@@ -27,8 +27,9 @@ module Facter
27
27
  end
28
28
 
29
29
  def cache_facts(resolved_facts)
30
- return unless Options[:cache]
30
+ return unless Options[:cache] && Options[:ttls].any?
31
31
 
32
+ @groups = {}
32
33
  resolved_facts.each do |fact|
33
34
  cache_fact(fact)
34
35
  end
@@ -48,8 +49,8 @@ module Facter
48
49
  false
49
50
  end
50
51
 
51
- fact_group = @fact_groups.get_fact_group(fact_name)
52
- delete_cache(fact_group) if fact_group && !cached
52
+ # fact_group = @fact_groups.get_fact_group(fact_name)
53
+ # delete_cache(fact_group) if fact_group && !cached
53
54
  cached
54
55
  end
55
56
 
@@ -66,6 +67,8 @@ module Facter
66
67
 
67
68
  fact = @fact_groups.get_fact(fact_name)
68
69
 
70
+ return if external_fact_in_custom_group?(searched_fact, fact_name, fact)
71
+
69
72
  return unless fact
70
73
 
71
74
  return unless check_ttls?(fact[:group], fact[:ttls])
@@ -73,6 +76,16 @@ module Facter
73
76
  read_fact(searched_fact, fact[:group])
74
77
  end
75
78
 
79
+ def external_fact_in_custom_group?(searched_fact, fact_name, fact)
80
+ if searched_fact.type == :file && fact[:group] != fact_name
81
+ @log.error("Cannot cache '#{fact_name}' fact from '#{fact[:group]}' group. "\
82
+ 'Caching custom group is not supported for external facts.')
83
+ return true
84
+ end
85
+
86
+ false
87
+ end
88
+
76
89
  def read_fact(searched_fact, fact_group)
77
90
  data = nil
78
91
  Facter::Framework::Benchmarking::Timer.measure(searched_fact.name, 'cached') do
@@ -80,27 +93,53 @@ module Facter
80
93
  end
81
94
  return unless data
82
95
 
96
+ unless searched_fact.file
97
+ return unless valid_format_version?(searched_fact, data, fact_group)
98
+
99
+ delete_cache(fact_group) unless data.keys.grep(/#{searched_fact.name}/).any?
100
+ # data.fetch(searched_fact.name) { delete_cache(fact_group) }
101
+ end
102
+
83
103
  @log.debug("loading cached values for #{searched_fact.name} facts")
84
104
 
85
105
  create_facts(searched_fact, data)
86
106
  end
87
107
 
108
+ def valid_format_version?(searched_fact, data, fact_group)
109
+ unless data['cache_format_version'] == 1
110
+ @log.debug("The fact #{searched_fact.name} could not be read from the cache, \
111
+ cache_format_version is incorrect!")
112
+ delete_cache(fact_group)
113
+ return false
114
+ end
115
+
116
+ true
117
+ end
118
+
88
119
  def create_facts(searched_fact, data)
89
120
  if searched_fact.type == :file
90
- facts = []
91
- data.each do |fact_name, fact_value|
92
- fact = Facter::ResolvedFact.new(fact_name, fact_value, searched_fact.type,
93
- searched_fact.user_query, searched_fact.filter_tokens)
94
- fact.file = searched_fact.file
95
- facts << fact
96
- end
97
- facts
121
+ resolve_external_fact(searched_fact, data)
98
122
  else
123
+ return unless data[searched_fact.name]
124
+
99
125
  [Facter::ResolvedFact.new(searched_fact.name, data[searched_fact.name], searched_fact.type,
100
126
  searched_fact.user_query, searched_fact.filter_tokens)]
101
127
  end
102
128
  end
103
129
 
130
+ def resolve_external_fact(searched_fact, data)
131
+ facts = []
132
+ data.each do |fact_name, fact_value|
133
+ next if fact_name == 'cache_format_version'
134
+
135
+ fact = Facter::ResolvedFact.new(fact_name, fact_value, searched_fact.type,
136
+ searched_fact.user_query, searched_fact.filter_tokens)
137
+ fact.file = searched_fact.file
138
+ facts << fact
139
+ end
140
+ facts
141
+ end
142
+
104
143
  def cache_fact(fact)
105
144
  fact_name = if fact.file
106
145
  File.basename(fact.file)
@@ -110,7 +149,7 @@ module Facter
110
149
 
111
150
  group_name = @fact_groups.get_fact_group(fact_name)
112
151
 
113
- return if !group_name || fact.value.nil?
152
+ return unless group_name
114
153
 
115
154
  return unless fact_cache_enabled?(fact_name)
116
155
 
@@ -131,6 +170,8 @@ module Facter
131
170
  next if File.readable?(cache_file_name)
132
171
 
133
172
  @log.debug("caching values for #{group_name} facts")
173
+
174
+ data['cache_format_version'] = 1
134
175
  File.write(cache_file_name, JSON.pretty_generate(data))
135
176
  end
136
177
  end
@@ -142,7 +183,7 @@ module Facter
142
183
  data = nil
143
184
  file = Util::FileHelper.safe_read(cache_file_name)
144
185
  begin
145
- data = JSON.parse(file)
186
+ data = JSON.parse(file) unless file.nil?
146
187
  rescue JSON::ParserError
147
188
  delete_cache(group_name)
148
189
  end
@@ -161,12 +202,13 @@ module Facter
161
202
  File.delete(cache_file_name)
162
203
  end
163
204
 
164
- @log.debug("#{group_name} facts cache file expired/missing")
205
+ @log.debug("#{group_name} facts cache file expired, missing or is corrupt")
165
206
  true
166
207
  end
167
208
 
168
209
  def delete_cache(group_name)
169
210
  cache_file_name = File.join(@cache_dir, group_name)
211
+
170
212
  File.delete(cache_file_name) if File.readable?(cache_file_name)
171
213
  end
172
214
  end