|
5 | 5 | require 'puppet/resource_api/glue' |
6 | 6 | require 'puppet/resource_api/parameter' |
7 | 7 | require 'puppet/resource_api/property' |
| 8 | +require 'puppet/resource_api/provider_get_cache' |
8 | 9 | require 'puppet/resource_api/puppet_context' unless RUBY_PLATFORM == 'java' |
9 | 10 | require 'puppet/resource_api/read_only_parameter' |
10 | 11 | require 'puppet/resource_api/transport' |
@@ -69,6 +70,15 @@ def type_definition |
69 | 70 | apply_to_device |
70 | 71 | end |
71 | 72 |
|
| 73 | + define_singleton_method(:rsapi_provider_get_cache) do |
| 74 | + # This gives a new cache per resource provider on each Puppet run: |
| 75 | + @rsapi_provider_get_cache ||= Puppet::ResourceApi::ProviderGetCache.new |
| 76 | + end |
| 77 | + |
| 78 | + def rsapi_provider_get_cache |
| 79 | + self.class.rsapi_provider_get_cache |
| 80 | + end |
| 81 | + |
72 | 82 | def initialize(attributes) |
73 | 83 | # $stderr.puts "A: #{attributes.inspect}" |
74 | 84 | if attributes.is_a? Puppet::Resource |
@@ -154,8 +164,18 @@ def generate |
154 | 164 | end |
155 | 165 |
|
156 | 166 | def rsapi_current_state |
157 | | - refresh_current_state unless @rsapi_current_state |
158 | | - @rsapi_current_state |
| 167 | + return @rsapi_current_state if @rsapi_current_state |
| 168 | + |
| 169 | + # If the current state is not set, then check the cache and, if a value is |
| 170 | + # found, ensure it passes strict_check before allowing it to be used: |
| 171 | + cached_value = rsapi_provider_get_cache.get(rsapi_title) |
| 172 | + strict_check(cached_value) if cached_value |
| 173 | + @rsapi_current_state = cached_value |
| 174 | + end |
| 175 | + |
| 176 | + def rsapi_current_state=(value) |
| 177 | + rsapi_provider_get_cache.add(rsapi_title, value) |
| 178 | + @rsapi_current_state = value |
159 | 179 | end |
160 | 180 |
|
161 | 181 | def to_resource |
@@ -242,57 +262,89 @@ def to_resource_shim(resource) |
242 | 262 | type_definition.create_attribute_in(self, name, param_or_property, parent, options) |
243 | 263 | end |
244 | 264 |
|
| 265 | + def self.rsapi_provider_get(names = nil) |
| 266 | + # If the cache has been marked as having all instances, then just return the |
| 267 | + # full contents or the filtered contents based on names: |
| 268 | + if rsapi_provider_get_cache.cached_all? |
| 269 | + return rsapi_provider_get_cache.all if names.nil? |
| 270 | + |
| 271 | + # If we have all instances cached but need specific ones, filter from cache |
| 272 | + cached_resources = names.map { |name| rsapi_provider_get_cache.get(name) }.compact |
| 273 | + return cached_resources unless cached_resources.empty? |
| 274 | + end |
| 275 | + |
| 276 | + # For simple_get_filter, if we're asking for specific resources and they're cached, return those |
| 277 | + if type_definition.feature?('simple_get_filter') && !names.nil? |
| 278 | + cached_resources = names.map { |name| rsapi_provider_get_cache.get(name) }.compact |
| 279 | + return cached_resources if names.length == cached_resources.length |
| 280 | + end |
| 281 | + |
| 282 | + fetched = if type_definition.feature?('simple_get_filter') |
| 283 | + my_provider.get(context, names) |
| 284 | + else |
| 285 | + my_provider.get(context) |
| 286 | + end |
| 287 | + |
| 288 | + fetched.each do |resource_hash| |
| 289 | + type_definition.check_schema(resource_hash) |
| 290 | + rsapi_provider_get_cache.add(build_title(type_definition, resource_hash), resource_hash) |
| 291 | + end |
| 292 | + |
| 293 | + if names.nil? && !type_definition.feature?('simple_get_filter') |
| 294 | + # Mark the cache as having all possible instances: |
| 295 | + rsapi_provider_get_cache.cached_all |
| 296 | + end |
| 297 | + |
| 298 | + fetched |
| 299 | + end |
| 300 | + |
245 | 301 | def self.instances |
246 | 302 | # puts 'instances' |
247 | 303 | # force autoloading of the provider |
248 | 304 | provider(type_definition.name) |
249 | 305 |
|
250 | | - initial_fetch = if type_definition.feature?('simple_get_filter') |
251 | | - my_provider.get(context, []) |
252 | | - else |
253 | | - my_provider.get(context) |
254 | | - end |
255 | | - |
256 | | - initial_fetch.map do |resource_hash| |
257 | | - type_definition.check_schema(resource_hash) |
| 306 | + rsapi_provider_get.map do |resource_hash| |
258 | 307 | # allow a :title from the provider to override the default |
259 | 308 | result = if resource_hash.key? :title |
260 | 309 | new(title: resource_hash[:title]) |
261 | 310 | else |
262 | 311 | new(title: build_title(type_definition, resource_hash)) |
263 | 312 | end |
| 313 | + # Cache the state in the generated resource, but unfortunately |
| 314 | + # this only benefits "puppet resource", not apply runs: |
264 | 315 | result.cache_current_state(resource_hash) |
265 | 316 | result |
266 | 317 | end |
267 | 318 | end |
268 | 319 |
|
269 | 320 | def refresh_current_state |
270 | | - @rsapi_current_state = if type_definition.feature?('simple_get_filter') |
271 | | - my_provider.get(context, [rsapi_title]).find { |h| namevar_match?(h) } |
272 | | - else |
273 | | - my_provider.get(context).find { |h| namevar_match?(h) } |
274 | | - end |
275 | | - |
276 | | - if @rsapi_current_state |
277 | | - type_definition.check_schema(@rsapi_current_state) |
278 | | - strict_check(@rsapi_current_state) |
| 321 | + current_state = self.class.rsapi_provider_get([rsapi_title]).find { |h| namevar_match?(h) } |
| 322 | + |
| 323 | + if current_state |
| 324 | + strict_check(current_state) |
279 | 325 | else |
280 | | - @rsapi_current_state = if rsapi_title.is_a? Hash |
281 | | - rsapi_title.dup |
282 | | - else |
283 | | - { title: rsapi_title } |
284 | | - end |
285 | | - @rsapi_current_state[:ensure] = :absent if type_definition.ensurable? |
| 326 | + current_state = if rsapi_title.is_a? Hash |
| 327 | + rsapi_title.dup |
| 328 | + else |
| 329 | + { title: rsapi_title } |
| 330 | + end |
| 331 | + current_state[:ensure] = :absent if type_definition.ensurable? |
286 | 332 | end |
| 333 | + self.rsapi_current_state = current_state |
287 | 334 | end |
288 | 335 |
|
289 | | - # Use this to set the current state from the `instances` method |
| 336 | + # Use this to set the current state from the `instances` method. "puppet resources" |
| 337 | + # needs this to minimize provider get() calls, but during a Puppet apply run |
| 338 | + # the instances() method is only used by resource generation, and resource |
| 339 | + # generators use and then discard the resources created by `instances``, so this |
| 340 | + # does not help with that: |
290 | 341 | def cache_current_state(resource_hash) |
291 | | - @rsapi_current_state = resource_hash |
292 | | - strict_check(@rsapi_current_state) |
| 342 | + self.rsapi_current_state = resource_hash |
| 343 | + strict_check(resource_hash) |
293 | 344 | end |
294 | 345 |
|
295 | 346 | def retrieve |
| 347 | + refresh_current_state unless rsapi_current_state |
296 | 348 | Puppet.debug("Current State: #{rsapi_current_state.inspect}") |
297 | 349 |
|
298 | 350 | result = Puppet::Resource.new(self.class, title, parameters: rsapi_current_state) |
|
0 commit comments