summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Keiser <john@johnkeiser.com>2015-06-03 12:04:34 -0700
committerJohn Keiser <john@johnkeiser.com>2015-06-03 12:04:34 -0700
commitdb703fe2e73ab7f783c860013cde836864de5e73 (patch)
tree098ef9c4e383288fb6c8e523375b1440198391a5
parent27deff0d81499c9df32cfc0235792ea3a23834e4 (diff)
parent88857ae52f4bfb36d2aa3ca852cfbddd4fdff63b (diff)
downloadchef-db703fe2e73ab7f783c860013cde836864de5e73.tar.gz
Merge branch 'jk/3463'
-rw-r--r--lib/chef/resource.rb66
-rw-r--r--lib/chef/resource/lwrp_base.rb2
-rw-r--r--spec/unit/lwrp_spec.rb127
3 files changed, 173 insertions, 22 deletions
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index b8bf53d6ec..ab955f5454 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -1274,31 +1274,61 @@ class Chef
end
end
- # 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
+ # @api private
+ def self.register_deprecated_lwrp_class(resource_class, class_name)
+ if Chef::Resource.const_defined?(class_name, false)
+ Chef::Log.warn "#{class_name} already exists! Deprecation class overwrites #{resource_class}"
+ Chef::Resource.send(:remove_const, class_name)
end
- def const_missing(class_name)
- if deprecated_constants[class_name.to_sym]
+ # In order to generate deprecation warnings when you use Chef::Resource::MyLwrp,
+ # we make a special subclass (identical in nearly all respects) of the
+ # actual LWRP. When you say any of these, a deprecation warning will be
+ # generated:
+ #
+ # - Chef::Resource::MyLwrp.new(...)
+ # - resource.is_a?(Chef::Resource::MyLwrp)
+ # - resource.kind_of?(Chef::Resource::MyLwrp)
+ # - case resource
+ # when Chef::Resource::MyLwrp
+ # end
+ #
+ resource_subclass = class_eval <<-EOM, __FILE__, __LINE__+1
+ class Chef::Resource::#{class_name} < resource_class
+ def initialize(*args, &block)
+ Chef::Log.deprecation("Using an LWRP by its name (#{class_name}) directly is no longer supported in Chef 13 and will be removed. Use Chef::Resource.resource_for_node(node, name) instead.")
+ super
+ end
+ self
+ end
+ EOM
+ # Make case, is_a and kind_of work with the new subclass, for backcompat.
+ # Any subclass of Chef::Resource::ResourceClass is already a subclass of resource_class
+ # Any subclass of resource_class is considered a subclass of Chef::Resource::ResourceClass
+ resource_class.class_eval do
+ define_method(:is_a?) do |other|
+ other.is_a?(Module) && other === self
+ end
+ define_method(:kind_of?) do |other|
+ other.is_a?(Module) && other === self
+ end
+ end
+ resource_subclass.class_eval do
+ define_singleton_method(:===) do |other|
Chef::Log.deprecation("Using an LWRP by its name (#{class_name}) directly is no longer supported in Chef 13 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}"
+ # resource_subclass is a superclass of all resource_class descendants.
+ if self == resource_subclass && other.class <= resource_class
+ return true
+ end
+ super(other)
end
end
+ deprecated_constants[class_name.to_sym] = resource_subclass
+ end
- def deprecated_constants
- @deprecated_constants ||= {}
- end
+ def self.deprecated_constants
+ @deprecated_constants ||= {}
end
- extend DeprecatedLWRPClass
# @api private
def lookup_provider_constant(name, action=:nothing)
diff --git a/lib/chef/resource/lwrp_base.rb b/lib/chef/resource/lwrp_base.rb
index 20d236a161..c486233020 100644
--- a/lib/chef/resource/lwrp_base.rb
+++ b/lib/chef/resource/lwrp_base.rb
@@ -69,8 +69,8 @@ class Chef
LWRPBase.loaded_lwrps[filename] = true
+ # Create the deprecated Chef::Resource::LwrpFoo 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 f83678308a..58cba27adf 100644
--- a/spec/unit/lwrp_spec.rb
+++ b/spec/unit/lwrp_spec.rb
@@ -160,8 +160,8 @@ describe "LWRP" do
end
end
- it "should load the resource into a properly-named class and emit a warning about deprecation when accessing it" do
- expect { Chef::Resource::LwrpFoo }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
+ it "should load the resource into a properly-named class and emit a warning when it is initialized" do
+ expect { Chef::Resource::LwrpFoo.new('hi') }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
end
it "should be resolvable with Chef::ResourceResolver.resolve(:lwrp_foo)" do
@@ -211,6 +211,127 @@ describe "LWRP" do
expect(cls.node[:penguin_name]).to eql("jackass")
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 load the resource into a properly-named class" do
+ expect(Chef::Resource::LwrpFoo).to be_kind_of(Class)
+ expect(Chef::Resource::LwrpFoo <= Chef::Resource::LWRPBase).to be_truthy
+ end
+
+ it "get_lwrp(:lwrp_foo).new is a Chef::Resource::LwrpFoo" do
+ lwrp = get_lwrp(:lwrp_foo).new('hi')
+ expect(lwrp.kind_of?(Chef::Resource::LwrpFoo)).to be_truthy
+ expect(lwrp.is_a?(Chef::Resource::LwrpFoo)).to be_truthy
+ expect(get_lwrp(:lwrp_foo) === lwrp).to be_truthy
+ expect(Chef::Resource::LwrpFoo === lwrp).to be_truthy
+ end
+
+ it "Chef::Resource::LwrpFoo.new is a get_lwrp(:lwrp_foo)" do
+ lwrp = Chef::Resource::LwrpFoo.new('hi')
+ expect(lwrp.kind_of?(get_lwrp(:lwrp_foo))).to be_truthy
+ expect(lwrp.is_a?(get_lwrp(:lwrp_foo))).to be_truthy
+ expect(get_lwrp(:lwrp_foo) === lwrp).to be_truthy
+ expect(Chef::Resource::LwrpFoo === lwrp).to be_truthy
+ end
+
+ it "works even if LwrpFoo exists in the top level" do
+ module ::LwrpFoo
+ end
+ expect(Chef::Resource::LwrpFoo).not_to eq(::LwrpFoo)
+ end
+
+ context "with a subclass of get_lwrp(:lwrp_foo)" do
+ let(:subclass) do
+ Class.new(get_lwrp(:lwrp_foo))
+ end
+
+ it "subclass.new is a subclass" do
+ lwrp = subclass.new('hi')
+ expect(lwrp.kind_of?(subclass)).to be_truthy
+ expect(lwrp.is_a?(subclass)).to be_truthy
+ expect(subclass === lwrp).to be_truthy
+ expect(lwrp.class === subclass)
+ end
+ it "subclass.new is a Chef::Resource::LwrpFoo" do
+ lwrp = subclass.new('hi')
+ expect(lwrp.kind_of?(Chef::Resource::LwrpFoo)).to be_truthy
+ expect(lwrp.is_a?(Chef::Resource::LwrpFoo)).to be_truthy
+ expect(Chef::Resource::LwrpFoo === lwrp).to be_truthy
+ expect(lwrp.class === Chef::Resource::LwrpFoo)
+ end
+ it "subclass.new is a get_lwrp(:lwrp_foo)" do
+ lwrp = subclass.new('hi')
+ expect(lwrp.kind_of?(get_lwrp(:lwrp_foo))).to be_truthy
+ expect(lwrp.is_a?(get_lwrp(:lwrp_foo))).to be_truthy
+ expect(get_lwrp(:lwrp_foo) === lwrp).to be_truthy
+ expect(lwrp.class === get_lwrp(:lwrp_foo))
+ end
+ it "Chef::Resource::LwrpFoo.new is *not* a subclass" do
+ lwrp = Chef::Resource::LwrpFoo.new('hi')
+ expect(lwrp.kind_of?(subclass)).to be_falsey
+ expect(lwrp.is_a?(subclass)).to be_falsey
+ expect(subclass === lwrp.class).to be_falsey
+ expect(subclass === Chef::Resource::LwrpFoo).to be_falsey
+ end
+ it "get_lwrp(:lwrp_foo).new is *not* a subclass" do
+ lwrp = get_lwrp(:lwrp_foo).new('hi')
+ expect(lwrp.kind_of?(subclass)).to be_falsey
+ expect(lwrp.is_a?(subclass)).to be_falsey
+ expect(subclass === lwrp.class).to be_falsey
+ expect(subclass === get_lwrp(:lwrp_foo)).to be_falsey
+ end
+ end
+
+ context "with a subclass of Chef::Resource::LwrpFoo" do
+ let(:subclass) do
+ Class.new(Chef::Resource::LwrpFoo)
+ end
+
+ it "subclass.new is a subclass" do
+ lwrp = subclass.new('hi')
+ expect(lwrp.kind_of?(subclass)).to be_truthy
+ expect(lwrp.is_a?(subclass)).to be_truthy
+ expect(subclass === lwrp).to be_truthy
+ expect(lwrp.class === subclass)
+ end
+ it "subclass.new is a Chef::Resource::LwrpFoo" do
+ lwrp = subclass.new('hi')
+ expect(lwrp.kind_of?(Chef::Resource::LwrpFoo)).to be_truthy
+ expect(lwrp.is_a?(Chef::Resource::LwrpFoo)).to be_truthy
+ expect(Chef::Resource::LwrpFoo === lwrp).to be_truthy
+ expect(lwrp.class === Chef::Resource::LwrpFoo)
+ end
+ it "subclass.new is a get_lwrp(:lwrp_foo)" do
+ lwrp = subclass.new('hi')
+ expect(lwrp.kind_of?(get_lwrp(:lwrp_foo))).to be_truthy
+ expect(lwrp.is_a?(get_lwrp(:lwrp_foo))).to be_truthy
+ expect(get_lwrp(:lwrp_foo) === lwrp).to be_truthy
+ expect(lwrp.class === get_lwrp(:lwrp_foo))
+ end
+ it "Chef::Resource::LwrpFoo.new is *not* a subclass" do
+ lwrp = Chef::Resource::LwrpFoo.new('hi')
+ expect(lwrp.kind_of?(subclass)).to be_falsey
+ expect(lwrp.is_a?(subclass)).to be_falsey
+ expect(subclass === lwrp.class).to be_falsey
+ expect(subclass === Chef::Resource::LwrpFoo).to be_falsey
+ end
+ it "get_lwrp(:lwrp_foo).new is *not* a subclass" do
+ lwrp = get_lwrp(:lwrp_foo).new('hi')
+ expect(lwrp.kind_of?(subclass)).to be_falsey
+ expect(lwrp.is_a?(subclass)).to be_falsey
+ expect(subclass === lwrp.class).to be_falsey
+ expect(subclass === get_lwrp(:lwrp_foo)).to be_falsey
+ end
+ end
+ end
+
context "resource_name" do
let(:klass) { Class.new(Chef::Resource::LWRPBase) }
@@ -355,7 +476,7 @@ describe "LWRP" do
provider.action_twiddle_thumbs
end
- context "resource class created" do
+ context "provider 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