module Poise::Helpers::Inversion::Provider::ClassMethods
@!classmethods
Public Instance Methods
Default attribute paths to check for inversion options. Based on the cookbook this class and its superclasses are defined in.
@param node [Chef::Node] Node to load from. @return [Array<Array<String>>]
# File lib/poise/helpers/inversion.rb, line 244 def default_inversion_attributes(node) klass = self tried = [] while klass.respond_to?(:poise_defined_in_cookbook) cookbook = klass.poise_defined_in_cookbook(node.run_context) if node[cookbook] return [cookbook] end tried << cookbook klass = klass.superclass end raise Poise::Error.new("Unable to find inversion attributes, tried: #{tried.join(', ')}") end
Default options data for this provider class.
@param node [Chef::Node] Node to load from. @param resource [Chef::Resource] Resource
to load from. @return [Hash]
# File lib/poise/helpers/inversion.rb, line 314 def default_inversion_options(node, resource) {} end
# File lib/poise/helpers/inversion.rb, line 381 def included(klass) super klass.extend(ClassMethods) end
@overload inversion_attribute
()
Return the inversion attribute name(s) for this class. @return [Array<String>, nil]
@overload inversion_attribute
(val)
Set the inversion attribute name(s) for this class. This is used by {.resolve_inversion_attribute} to load configuration data from node attributes. To specify a nested attribute pass an array of strings corresponding to the keys. @param val [String, Array<String>] Attribute path. @return [Array<String>, nil]
# File lib/poise/helpers/inversion.rb, line 226 def inversion_attribute(val=Poise::NOT_PASSED) if val != Poise::NOT_PASSED # Coerce to an array of strings. val = Array(val).map {|name| name.to_s } @poise_inversion_attribute = val end if defined?(@poise_inversion_attribute) @poise_inversion_attribute else Poise::Utils.ancestor_send(self, :inversion_attribute, default: nil) end end
Compile all the different levels of inversion options together.
@param node [Chef::Node] Node to load from. @param resource [Chef::Resource] Resource
to load from. @return [Hash]
# File lib/poise/helpers/inversion.rb, line 281 def inversion_options(node, resource) Mash.new.tap do |opts| attrs = resolve_inversion_attribute(node) # Cast the run state to a Mash because string vs. symbol keys. I can # at least promise poise_inversion will be a str so cut down on the # amount of data to convert. run_state = Mash.new(node.run_state.fetch('poise_inversion', {}).fetch(inversion_resource, {}))[resource.name] || {} # Class-level defaults. opts.update(default_inversion_options(node, resource)) # Resource options for all providers. opts.update(resource.options) if resource.respond_to?(:options) # Global provider from node attributes. opts.update(provider: attrs['provider']) if attrs['provider'] # Attribute options for all providers. opts.update(attrs['options']) if attrs['options'] # Resource options for this provider. opts.update(resource.options(provides)) if resource.respond_to?(:options) # Attribute options for this resource name. opts.update(attrs[resource.name]) if attrs[resource.name] # Options resource options for all providers. opts.update(run_state['*']) if run_state['*'] # Options resource options for this provider. opts.update(run_state[provides]) if run_state[provides] # Vomitdebug output for tracking down weirdness. Poise.debug("[#{resource}] Resolved inversion options: #{opts.inspect}") end end
@overload inversion_resource
()
Return the inversion resource name for this class. @return [Symbo, nill]
@overload inversion_resource
(val)
Set the inversion resource name for this class. You can pass either a symbol in DSL format or a resource class that uses Poise. This name is used to determine which resources the inversion provider is a candidate for. @param val [Symbol, Class] Name to set. @return [Symbol, nil]
# File lib/poise/helpers/inversion.rb, line 203 def inversion_resource(val=Poise::NOT_PASSED) if val != Poise::NOT_PASSED val = val.resource_name if val.is_a?(Class) Chef::Log.debug("[#{self.name}] Setting inversion resource to #{val}") @poise_inversion_resource = val.to_sym end if defined?(@poise_inversion_resource) @poise_inversion_resource else Poise::Utils.ancestor_send(self, :inversion_resource, default: nil) end end
Override the normal provides
to set the inversion provider name instead of adding to the normal provider map.
@overload provides()
Return the inversion provider name for the class. @return [Symbol]
@overload provides(name, opts={}, &block)
Set the inversion provider name for the class. @param name [Symbol] Provider name. @param opts [Hash] NodeMap filter options. @param block [Proc] NodeMap filter proc. @return [Symbol]
# File lib/poise/helpers/inversion.rb, line 339 def provides(name=nil, opts={}, &block) if name raise Poise::Error.new("Inversion resource name not set for #{self.name}") unless inversion_resource @poise_inversion_provider = name Chef::Log.debug("[#{self.name}] Setting inversion provider name to #{name}") Poise::Helpers::Inversion.provider_map(inversion_resource).set(name.to_sym, self, opts, &block) # Set the actual Chef-level provides name for DSL dispatch. super(inversion_resource) end @poise_inversion_provider end
Override the default provides?
to check for our inverted providers.
@api private @param node [Chef::Node] Node to use for attribute checks. @param resource [Chef::Resource] Resource
instance to match. @return [Boolean]
# File lib/poise/helpers/inversion.rb, line 357 def provides?(node, resource) raise Poise::Error.new("Inversion resource name not set for #{self.name}") unless inversion_resource resource_name_equivalents = {resource.resource_name => true} # If subclass_providers! might be in play, check for those names too. if resource.class.respond_to?(:subclass_resource_equivalents) resource.class.subclass_resource_equivalents.each do |name| resource_name_equivalents[name] = true end end return false unless resource_name_equivalents[inversion_resource] provider_name = resolve_inversion_provider(node, resource).to_s Poise.debug("[#{resource}] Checking provides? on #{self.name}. Got provider_name #{provider_name.inspect}") provider_name == provides.to_s || ( provider_name == 'auto' && !resource.provider_no_auto.include?(provides.to_s) && provides_auto?(node, resource) ) end
Subclass hook to provide auto-detection for providers.
@param node [Chef::Node] Node to check against. @param resource [Chef::Resource] Resource
to check against. @return [Boolean]
# File lib/poise/helpers/inversion.rb, line 377 def provides_auto?(node, resource) false end
Resolve the node attribute used as the base for inversion options for this class. This can be set explicitly with {.inversion_attribute} or the default is to use the name of the cookbook the provider is defined in.
@param node [Chef::Node] Node to load from. @return [Chef::Node::Attribute]
# File lib/poise/helpers/inversion.rb, line 265 def resolve_inversion_attribute(node) # Default to using just the name of the cookbook. attribute_names = inversion_attribute || default_inversion_attributes(node) return {} if attribute_names.empty? attribute_names.inject(node) do |memo, key| memo[key] || begin raise Poise::Error.new("Attribute #{key} not set when expanding inversion attribute for #{self.name}: #{memo}") end end end
Resolve which provider name should be used for a resource.
@param node [Chef::Node] Node to load from. @param resource [Chef::Resource] Resource
to query. @return [String]
# File lib/poise/helpers/inversion.rb, line 323 def resolve_inversion_provider(node, resource) inversion_options(node, resource)['provider'] || 'auto' end