Module: Poise::Helpers::Inversion::Provider

Includes:
DefinedIn
Defined in:
lib/poise/helpers/inversion.rb

Overview

Provider implementation for Poise::Helpers::Inversion.

See Also:

Since:

  • 2.0.0

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DefinedIn

poise_defined!, poise_defined_in, poise_defined_in_cookbook

Class Method Details

.default_inversion_attributes(node) ⇒ Array<Array<String>>

Default attribute paths to check for inversion options. Based on the cookbook this class and its superclasses are defined in.

Parameters:

  • node (Chef::Node)

    Node to load from.

Returns:

  • (Array<Array<String>>)

Raises:

Since:

  • 2.0.0



244
245
246
247
248
249
250
251
252
253
254
255
256
# 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) ⇒ Hash

Default options data for this provider class.

Parameters:

  • node (Chef::Node)

    Node to load from.

  • resource (Chef::Resource)

    Resource to load from.

Returns:

  • (Hash)

Since:

  • 2.0.0



314
315
316
# File 'lib/poise/helpers/inversion.rb', line 314

def default_inversion_options(node, resource)
  {}
end

.inversion_attributeArray<String>? .inversion_attribute(val) ⇒ Array<String>?

Overloads:

  • .inversion_attributeArray<String>?

    Return the inversion attribute name(s) for this class.

    Returns:

    • (Array<String>, nil)
  • .inversion_attribute(val) ⇒ Array<String>?

    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.

    Parameters:

    • val (String, Array<String>)

      Attribute path.

    Returns:

    • (Array<String>, nil)

Since:

  • 2.0.0



226
227
228
229
230
231
232
233
234
235
236
237
# 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) ⇒ Hash

Compile all the different levels of inversion options together.

Parameters:

  • node (Chef::Node)

    Node to load from.

  • resource (Chef::Resource)

    Resource to load from.

Returns:

  • (Hash)

Since:

  • 2.0.0



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# 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_resourceSymbo, nill .inversion_resource(val) ⇒ Symbol?

Overloads:

  • .inversion_resourceSymbo, nill

    Return the inversion resource name for this class.

    Returns:

    • (Symbo, nill)
  • .inversion_resource(val) ⇒ Symbol?

    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.

    Parameters:

    • val (Symbol, Class)

      Name to set.

    Returns:

    • (Symbol, nil)

Since:

  • 2.0.0



203
204
205
206
207
208
209
210
211
212
213
214
# 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

.providesSymbol .provides(name, opts = {}, &block) ⇒ Symbol

Override the normal #provides to set the inversion provider name instead of adding to the normal provider map.

Overloads:

  • .providesSymbol

    Return the inversion provider name for the class.

    Returns:

    • (Symbol)
  • .provides(name, opts = {}, &block) ⇒ Symbol

    Set the inversion provider name for the class.

    Parameters:

    • name (Symbol)

      Provider name.

    • opts (Hash) (defaults to: {})

      NodeMap filter options.

    • block (Proc)

      NodeMap filter proc.

    Returns:

    • (Symbol)

Since:

  • 2.0.0



339
340
341
342
343
344
345
346
347
348
349
# 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_auto?(node, resource) ⇒ Boolean

Subclass hook to provide auto-detection for providers.

Parameters:

  • node (Chef::Node)

    Node to check against.

  • resource (Chef::Resource)

    Resource to check against.

Returns:

  • (Boolean)

Since:

  • 2.0.0



377
378
379
# File 'lib/poise/helpers/inversion.rb', line 377

def provides_auto?(node, resource)
  false
end

.resolve_inversion_attribute(node) ⇒ Chef::Node::Attribute

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.

Parameters:

  • node (Chef::Node)

    Node to load from.

Returns:

  • (Chef::Node::Attribute)

Since:

  • 2.0.0



265
266
267
268
269
270
271
272
273
274
# 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) ⇒ String

Resolve which provider name should be used for a resource.

Parameters:

  • node (Chef::Node)

    Node to load from.

  • resource (Chef::Resource)

    Resource to query.

Returns:

  • (String)

Since:

  • 2.0.0



323
324
325
# File 'lib/poise/helpers/inversion.rb', line 323

def resolve_inversion_provider(node, resource)
  inversion_options(node, resource)['provider'] || 'auto'
end

Instance Method Details

#optionsHash

Compile all the different levels of inversion options together.

Examples:

def action_run
  if options['depends']
    # ...
  end
end

Returns:

  • (Hash)

Since:

  • 2.0.0



187
188
189
# File 'lib/poise/helpers/inversion.rb', line 187

def options
  @options ||= self.class.inversion_options(node, new_resource)
end