class ChefCompat::CopiedFromChef::Chef::ResourceBuilder

Attributes

cookbook_name[R]
created_at[R]
enclosing_provider[R]
name[R]
params[R]
recipe_name[R]
resource[R]
run_context[R]
type[R]

Public Class Methods

new(type:nil, name:nil, created_at: nil, params: nil, run_context: nil, cookbook_name: nil, recipe_name: nil, enclosing_provider: nil) click to toggle source

FIXME (ruby-2.1 syntax): most of these are mandatory

Calls superclass method
# File files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb, line 42
    def initialize(type:nil, name:nil, created_at: nil, params: nil, run_context: nil, cookbook_name: nil, recipe_name: nil, enclosing_provider: nil)
super if defined?(::Chef::ResourceBuilder)
      @type               = type
      @name               = name
      @created_at         = created_at
      @params             = params
      @run_context        = run_context
      @cookbook_name      = cookbook_name
      @recipe_name        = recipe_name
      @enclosing_provider = enclosing_provider
    end

Public Instance Methods

build(&block) click to toggle source
# File files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb, line 54
def build(&block)
  raise ArgumentError, "You must supply a name when declaring a #{type} resource" if name.nil?

  @resource = resource_class.new(name, run_context)
  if resource.resource_name.nil?
    raise Chef::Exceptions::InvalidResourceSpecification, "#{resource}.resource_name is `nil`!  Did you forget to put `provides :blah` or `resource_name :blah` in your resource class?"
  end
  resource.source_line = created_at
  resource.declared_type = type

  # If we have a resource like this one, we want to steal its state
  # This behavior is very counter-intuitive and should be removed.
  # See CHEF-3694, https://tickets.opscode.com/browse/CHEF-3694
  # Moved to this location to resolve CHEF-5052, https://tickets.opscode.com/browse/CHEF-5052
  if prior_resource
    resource.load_from(prior_resource)
  end

  resource.cookbook_name = cookbook_name
  resource.recipe_name = recipe_name
  # Determine whether this resource is being created in the context of an enclosing Provider
  resource.enclosing_provider = enclosing_provider

  # XXX: this is required for definition params inside of the scope of a
  # subresource to work correctly.
  resource.params = params

  # Evaluate resource attribute DSL
  if block_given?
    resource.resource_initializing = true
    begin
      resource.instance_eval(&block)
    ensure
      resource.resource_initializing = false
    end
  end

  # emit a cloned resource warning if it is warranted
  if prior_resource
    if is_trivial_resource?(prior_resource) && identicalish_resources?(prior_resource, resource)
      emit_harmless_cloning_debug
    else
      emit_cloned_resource_warning
    end
  end

  # Run optional resource hook
  resource.after_created

  resource
end

Private Instance Methods

emit_cloned_resource_warning() click to toggle source
# File files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb, line 139
def emit_cloned_resource_warning
  message = "Cloning resource attributes for #{resource} from prior resource (CHEF-3694)"
  message << "\nPrevious #{prior_resource}: #{prior_resource.source_line}" if prior_resource.source_line
  message << "\nCurrent  #{resource}: #{resource.source_line}" if resource.source_line
  Chef.log_deprecation(message)
end
emit_harmless_cloning_debug() click to toggle source
# File files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb, line 146
def emit_harmless_cloning_debug
  Chef::Log.debug("Harmless resource cloning from #{prior_resource}:#{prior_resource.source_line} to #{resource}:#{resource.source_line}")
end
identicalish_resources?(first, second) click to toggle source

this is an equality test specific to checking for 3694 cloning warnings

# File files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb, line 124
def identicalish_resources?(first, second)
  skipped_ivars = [ :@source_line, :@cookbook_name, :@recipe_name, :@params, :@elapsed_time, :@declared_type ]
  checked_ivars = ( first.instance_variables | second.instance_variables ) - skipped_ivars
  non_matching_ivars = checked_ivars.reject do |iv|
    if iv == :@action && ( [first.instance_variable_get(iv)].flatten == [:nothing] || [second.instance_variable_get(iv)].flatten == [:nothing] )
      # :nothing action on either side of the comparison always matches
      true
    else
      first.instance_variable_get(iv) == second.instance_variable_get(iv)
    end
  end
  Chef::Log.debug("ivars which did not match with the prior resource: #{non_matching_ivars}")
  non_matching_ivars.empty?
end
is_trivial_resource?(resource) click to toggle source
# File files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb, line 115
def is_trivial_resource?(resource)
  trivial_resource = resource_class.new(name, run_context)
  # force un-lazy the name property on the created trivial resource
  name_property = resource_class.properties.find { |sym, p| p.name_property? }
  trivial_resource.send(name_property[0]) unless name_property.nil?
  identicalish_resources?(trivial_resource, resource)
end
prior_resource() click to toggle source
# File files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb, line 150
def prior_resource
  @prior_resource ||=
    begin
      key = "#{type}[#{name}]"
      run_context.resource_collection.lookup_local(key)
    rescue Chef::Exceptions::ResourceNotFound
      nil
    end
end
resource_class() click to toggle source
# File files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb, line 108
def resource_class
  # Checks the new platform => short_name => resource mapping initially
  # then fall back to the older approach (Chef::Resource.const_get) for
  # backward compatibility
  @resource_class ||= Chef::Resource.resource_for_node(type, run_context.node)
end