module Poise::Helpers::Inversion::Provider::ClassMethods

@!classmethods

Public Instance Methods

default_inversion_attributes(node) click to toggle source

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_inversion_options(node, resource) click to toggle source

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
included(klass) click to toggle source
Calls superclass method
# File lib/poise/helpers/inversion.rb, line 381
def included(klass)
  super
  klass.extend(ClassMethods)
end
inversion_attribute(val=Poise::NOT_PASSED) click to toggle source

@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
inversion_options(node, resource) click to toggle source

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
inversion_resource(val=Poise::NOT_PASSED) click to toggle source

@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
provides(name=nil, opts={}, &block) click to toggle source

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]
Calls superclass method
# 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
provides?(node, resource) click to toggle source

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
provides_auto?(node, resource) click to toggle source

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_inversion_attribute(node) click to toggle source

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_inversion_provider(node, resource) click to toggle source

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