summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Keiser <john@johnkeiser.com>2015-05-07 16:24:45 -0700
committerJohn Keiser <john@johnkeiser.com>2015-05-13 13:43:15 -0700
commit146f0809c1912988751688fff2ef6945c90a4513 (patch)
tree96e6ac327717318984930b84f69d8690a78b631c
parent0700ce4cd87825c6a925036ad5143ceb79438d38 (diff)
downloadchef-146f0809c1912988751688fff2ef6945c90a4513.tar.gz
Deprecate Chef::Provider::LwrpClass the same way we did Resource
-rw-r--r--lib/chef/provider.rb28
-rw-r--r--lib/chef/provider/lwrp_base.rb135
-rw-r--r--lib/chef/resource.rb63
-rw-r--r--lib/chef/resource/lwrp_base.rb8
-rw-r--r--spec/unit/lwrp_spec.rb35
5 files changed, 160 insertions, 109 deletions
diff --git a/lib/chef/provider.rb b/lib/chef/provider.rb
index 65a56cf726..3ab4d4d2b1 100644
--- a/lib/chef/provider.rb
+++ b/lib/chef/provider.rb
@@ -191,5 +191,33 @@ class Chef
end
end
+ module DeprecatedLWRPClass
+ def const_missing(class_name)
+ if deprecated_constants[class_name.to_sym]
+ Chef::Log.deprecation("Using an LWRP provider by its name (#{class_name}) directly is no longer supported in Chef 12 and will be removed. Use Chef::ProviderResolver.new(node, resource, action) instead.")
+ deprecated_constants[class_name.to_sym]
+ else
+ raise NameError, "uninitialized constant Chef::Provider::#{class_name}"
+ end
+ end
+
+ # @api private
+ def register_deprecated_lwrp_class(provider_class, class_name)
+ # Register Chef::Provider::MyProvider with deprecation warnings if you
+ # try to access it
+ if Chef::Provider.const_defined?(class_name, false)
+ Chef::Log.warn "Chef::Provider::#{class_name} already exists! Cannot create deprecation class for #{provider_class}"
+ else
+ deprecated_constants[class_name.to_sym] = provider_class
+ end
+ end
+
+ private
+
+ def deprecated_constants
+ @deprecated_constants ||= {}
+ end
+ end
+ extend DeprecatedLWRPClass
end
end
diff --git a/lib/chef/provider/lwrp_base.rb b/lib/chef/provider/lwrp_base.rb
index 0eadfe9467..38430ced6d 100644
--- a/lib/chef/provider/lwrp_base.rb
+++ b/lib/chef/provider/lwrp_base.rb
@@ -69,9 +69,6 @@ class Chef
end
- extend Chef::Mixin::ConvertToClassName
- extend Chef::Mixin::FromFile
-
include Chef::DSL::Recipe
# These were previously provided by Chef::Mixin::RecipeDefinitionDSLCore.
@@ -80,72 +77,92 @@ class Chef
include Chef::DSL::PlatformIntrospection
include Chef::DSL::DataQuery
- def self.build_from_file(cookbook_name, filename, run_context)
- provider_class = nil
- provider_name = filename_to_qualified_string(cookbook_name, filename)
+ # no-op `load_current_resource`. Allows simple LWRP providers to work
+ # without defining this method explicitly (silences
+ # Chef::Exceptions::Override exception)
+ def load_current_resource
+ end
+
+ # class methods
+ class <<self
+ include Chef::Mixin::ConvertToClassName
+ include Chef::Mixin::FromFile
+
+ def build_from_file(cookbook_name, filename, run_context)
+ if LWRPBase.loaded_lwrps[filename]
+ Chef::Log.info("LWRP provider #{filename} from cookbook #{cookbook_name} has already been loaded! Skipping the reload.")
+ return loaded_lwrps[filename]
+ end
- class_name = convert_to_class_name(provider_name)
+ resource_name = filename_to_qualified_string(cookbook_name, filename)
- if Chef::Provider.const_defined?(class_name, false)
- Chef::Log.info("#{class_name} light-weight provider is already initialized -- Skipping loading #{filename}!")
- Chef::Log.debug("Overriding already defined LWRPs is not supported anymore starting with Chef 12.")
- provider_class = Chef::Provider.const_get(class_name)
- else
+ # We load the class first to give it a chance to set its own name
provider_class = Class.new(self)
- Chef::Provider.const_set(class_name, provider_class)
- provider_class.provides provider_name.to_sym
+ provider_class.provides resource_name.to_sym
provider_class.class_from_file(filename)
- Chef::Log.debug("Loaded contents of #{filename} into a provider named #{provider_name} defined in Chef::Provider::#{class_name}")
- end
- provider_class
- end
+ # Respect resource_name set inside the LWRP
+ provider_class.instance_eval do
+ define_method(:to_s) do
+ "LWRP provider #{resource_name} from cookbook #{cookbook_name}"
+ end
+ define_method(:inspect) { to_s }
+ end
- # Enables inline evaluation of resources in provider actions.
- #
- # Without this option, any resources declared inside the LWRP are added
- # to the resource collection after the current position at the time the
- # action is executed. Because they are added to the primary resource
- # collection for the chef run, they can notify other resources outside
- # the LWRP, and potentially be notified by resources outside the LWRP
- # (but this is complicated by the fact that they don't exist until the
- # provider executes). In this mode, it is impossible to correctly set the
- # updated_by_last_action flag on the parent LWRP resource, since it
- # executes and returns before its component resources are run.
- #
- # With this option enabled, each action creates a temporary run_context
- # with its own resource collection, evaluates the action's code in that
- # context, and then converges the resources created. If any resources
- # were updated, then this provider's new_resource will be marked updated.
- #
- # In this mode, resources created within the LWRP cannot interact with
- # external resources via notifies, though notifications to other
- # resources within the LWRP will work. Delayed notifications are executed
- # at the conclusion of the provider's action, *not* at the end of the
- # main chef run.
- #
- # This mode of evaluation is experimental, but is believed to be a better
- # set of tradeoffs than the append-after mode, so it will likely become
- # the default in a future major release of Chef.
- #
- def self.use_inline_resources
- extend InlineResources::ClassMethods
- include InlineResources
- end
+ Chef::Log.debug("Loaded contents of #{filename} into provider #{resource_name} (#{provider_class})")
+
+ LWRPBase.loaded_lwrps[filename] = true
- # DSL for defining a provider's actions.
- def self.action(name, &block)
- define_method("action_#{name}") do
- instance_eval(&block)
+ Chef::Provider.register_deprecated_lwrp_class(provider_class, convert_to_class_name(resource_name))
+
+ provider_class
end
- end
- # no-op `load_current_resource`. Allows simple LWRP providers to work
- # without defining this method explicitly (silences
- # Chef::Exceptions::Override exception)
- def load_current_resource
- end
+ # Enables inline evaluation of resources in provider actions.
+ #
+ # Without this option, any resources declared inside the LWRP are added
+ # to the resource collection after the current position at the time the
+ # action is executed. Because they are added to the primary resource
+ # collection for the chef run, they can notify other resources outside
+ # the LWRP, and potentially be notified by resources outside the LWRP
+ # (but this is complicated by the fact that they don't exist until the
+ # provider executes). In this mode, it is impossible to correctly set the
+ # updated_by_last_action flag on the parent LWRP resource, since it
+ # executes and returns before its component resources are run.
+ #
+ # With this option enabled, each action creates a temporary run_context
+ # with its own resource collection, evaluates the action's code in that
+ # context, and then converges the resources created. If any resources
+ # were updated, then this provider's new_resource will be marked updated.
+ #
+ # In this mode, resources created within the LWRP cannot interact with
+ # external resources via notifies, though notifications to other
+ # resources within the LWRP will work. Delayed notifications are executed
+ # at the conclusion of the provider's action, *not* at the end of the
+ # main chef run.
+ #
+ # This mode of evaluation is experimental, but is believed to be a better
+ # set of tradeoffs than the append-after mode, so it will likely become
+ # the default in a future major release of Chef.
+ #
+ def use_inline_resources
+ extend InlineResources::ClassMethods
+ include InlineResources
+ end
+
+ # DSL for defining a provider's actions.
+ def action(name, &block)
+ define_method("action_#{name}") do
+ instance_eval(&block)
+ end
+ end
+
+ protected
+ def loaded_lwrps
+ @loaded_lwrps ||= {}
+ end
+ end
end
end
end
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index 6030572be6..e62e63a44a 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -32,6 +32,8 @@ require 'chef/node_map'
require 'chef/node'
require 'chef/platform'
require 'chef/resource/resource_notification'
+require 'chef/provider_resolver'
+require 'chef/resource_resolver'
require 'chef/mixin/deprecation'
require 'chef/mixin/provides'
@@ -684,6 +686,8 @@ class Chef
#
def provider(arg=nil)
klass = if arg.kind_of?(String) || arg.kind_of?(Symbol)
+ # TODO deprecate. This does class munging. If you know
+ # the class name, just pass the class.
lookup_provider_constant(arg)
else
arg
@@ -1036,7 +1040,6 @@ class Chef
end
def provider_for_action(action)
- require 'chef/provider_resolver'
provider = Chef::ProviderResolver.new(node, self, action).resolve.new(self, run_context)
provider.action = action
provider
@@ -1110,7 +1113,6 @@ class Chef
# === Returns
# <Chef::Resource>:: returns the proper Chef::Resource class
def self.resource_for_node(short_name, node)
- require 'chef/resource_resolver'
klass = Chef::ResourceResolver.new(node, short_name).resolve
raise Chef::Exceptions::NoSuchResourceType.new(short_name, node) if klass.nil?
klass
@@ -1143,43 +1145,42 @@ class Chef
end
end
- def self.const_missing(class_name)
- if deprecated_constants[class_name.to_sym]
- Chef::Log.deprecation("Using an LWRP by its name (#{class_name}) directly is no longer supported in Chef 12 and will be removed. Use Chef::Resource.resource_for_node(node, name) instead.")
- deprecated_constants[class_name.to_sym]
- else
- raise NameError, "uninitialized constant Chef::Resource::#{class_name}"
+ # Implement deprecated LWRP class
+ module DeprecatedLWRPClass
+ # @api private
+ def register_deprecated_lwrp_class(resource_class, class_name)
+ if Chef::Resource.const_defined?(class_name, false)
+ Chef::Log.warn "#{class_name} already exists! Cannot create deprecation class for #{resource_class}"
+ else
+ deprecated_constants[class_name.to_sym] = resource_class
+ end
end
- end
- # @api private
- def self.create_deprecated_lwrp_class(resource_class)
- # Create a class in Chef::Resource::MyResource with deprecation
- # warnings if you try to access it
- class_name = convert_to_class_name(resource_class.resource_name)
- if Chef::Resource.const_defined?(class_name, false)
- Chef::Log.warn "#{class_name} already exists! Cannot create deprecation class for #{resource_class}"
- else
- deprecated_constants[class_name.to_sym] = resource_class
+ def const_missing(class_name)
+ if deprecated_constants[class_name.to_sym]
+ Chef::Log.deprecation("Using an LWRP by its name (#{class_name}) directly is no longer supported in Chef 12 and will be removed. Use Chef::Resource.resource_for_node(node, name) instead.")
+ deprecated_constants[class_name.to_sym]
+ else
+ raise NameError, "uninitialized constant Chef::Resource::#{class_name}"
+ end
end
- end
- private
+ private
- def self.deprecated_constants
- @deprecated_constants ||= {}
+ def deprecated_constants
+ @deprecated_constants ||= {}
+ end
end
+ extend DeprecatedLWRPClass
- def lookup_provider_constant(name)
- begin
- self.class.provider_base.const_get(convert_to_class_name(name.to_s))
- rescue NameError => e
- if e.to_s =~ /#{Regexp.escape(self.class.provider_base.to_s)}/
- raise ArgumentError, "No provider found to match '#{name}'"
- else
- raise e
- end
+ def lookup_provider_constant(name, action=:nothing)
+ resource = Chef::Resource.new(self.name, self.run_context)
+ resource.instance_eval { @resource_name = name }
+ provider = Chef::ProviderResolver.new(self.node, resource, action).resolve
+ if !provider
+ raise ArgumentError, "No provider found to match '#{name}'"
end
+ provider
end
end
end
diff --git a/lib/chef/resource/lwrp_base.rb b/lib/chef/resource/lwrp_base.rb
index 40c44f83f9..c79c205285 100644
--- a/lib/chef/resource/lwrp_base.rb
+++ b/lib/chef/resource/lwrp_base.rb
@@ -47,7 +47,7 @@ class Chef
def build_from_file(cookbook_name, filename, run_context)
if LWRPBase.loaded_lwrps[filename]
- Chef::Log.info("LWRP provider #{filename} from cookbook #{cookbook_name} has already been loaded! Skipping the reload.")
+ Chef::Log.info("LWRP resource #{filename} from cookbook #{cookbook_name} has already been loaded! Skipping the reload.")
return loaded_lwrps[filename]
end
@@ -63,16 +63,16 @@ class Chef
# Respect resource_name set inside the LWRP
resource_class.instance_eval do
define_method(:to_s) do
- "LWRP #{resource_name} from cookbook #{cookbook_name}"
+ "LWRP resource #{resource_name} from cookbook #{cookbook_name}"
end
define_method(:inspect) { to_s }
end
- Chef::Log.debug("Loaded contents of #{filename} into #{resource_class}")
+ Chef::Log.debug("Loaded contents of #{filename} into resource #{resource_name} (#{resource_class})")
LWRPBase.loaded_lwrps[filename] = true
- Chef::Resource.create_deprecated_lwrp_class(resource_class)
+ Chef::Resource.register_deprecated_lwrp_class(resource_class, convert_to_class_name(resource_name))
resource_class
end
diff --git a/spec/unit/lwrp_spec.rb b/spec/unit/lwrp_spec.rb
index 07b2c9d88c..36b470295f 100644
--- a/spec/unit/lwrp_spec.rb
+++ b/spec/unit/lwrp_spec.rb
@@ -320,38 +320,43 @@ describe "LWRP" do
end
before(:each) do
- Dir[File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "lwrp", "resources", "*"))].each do |file|
+ Dir[File.expand_path(File.expand_path("../../data/lwrp/resources/*", __FILE__))].each do |file|
Chef::Resource::LWRPBase.build_from_file("lwrp", file, @run_context)
end
- Dir[File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "lwrp", "providers", "*"))].each do |file|
- Chef::Provider::LWRPBase.build_from_file("lwrp", file, @run_context)
- end
-
- Dir[File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "lwrp_override", "providers", "*"))].each do |file|
+ Dir[File.expand_path(File.expand_path("../../data/lwrp/providers/*", __FILE__))].each do |file|
Chef::Provider::LWRPBase.build_from_file("lwrp", file, @run_context)
end
end
it "should properly handle a new_resource reference" do
- resource = get_lwrp(:lwrp_foo).new("morpheus")
+ resource = get_lwrp(:lwrp_foo).new("morpheus", @run_context)
resource.monkey("bob")
resource.provider(:lwrp_monkey_name_printer)
- resource.run_context = @run_context
provider = Chef::Platform.provider_for_resource(resource, :twiddle_thumbs)
provider.action_twiddle_thumbs
end
- it "should load the provider into a properly-named class" do
- expect(Chef::Provider.const_get("LwrpBuckPasser")).to be_kind_of(Class)
- end
+ context "resource class created" do
+ before do
+ @old_treat_deprecation_warnings_as_errors = Chef::Config[:treat_deprecation_warnings_as_errors]
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ end
+ after do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = @old_treat_deprecation_warnings_as_errors
+ end
- it "should create a method for each attribute" do
- new_resource = double("new resource").as_null_object
- expect(Chef::Provider::LwrpBuckPasser.new(nil, new_resource).methods.map{|m|m.to_sym}).to include(:action_pass_buck)
- expect(Chef::Provider::LwrpThumbTwiddler.new(nil, new_resource).methods.map{|m|m.to_sym}).to include(:action_twiddle_thumbs)
+ it "should load the provider into a properly-named class" do
+ expect(Chef::Provider.const_get("LwrpBuckPasser")).to be_kind_of(Class)
+ expect(Chef::Provider::LwrpBuckPasser <= Chef::Provider::LWRPBase).to be_truthy
+ end
+
+ it "should create a method for each action" do
+ expect(Chef::Provider::LwrpBuckPasser.instance_methods).to include(:action_pass_buck)
+ expect(Chef::Provider::LwrpThumbTwiddler.instance_methods).to include(:action_twiddle_thumbs)
+ end
end
it "should insert resources embedded in the provider into the middle of the resource collection" do