diff options
author | John Keiser <john@johnkeiser.com> | 2015-05-02 00:11:40 -0700 |
---|---|---|
committer | John Keiser <john@johnkeiser.com> | 2015-05-13 13:43:14 -0700 |
commit | 8e09b80cbeeef8a1a396434bec9dc76737061b13 (patch) | |
tree | d1f6553fb27141088bcbd2b50c5faead8251ce26 | |
parent | 200934f63c02c2b70532eb8a010337ac3b8e9803 (diff) | |
download | chef-8e09b80cbeeef8a1a396434bec9dc76737061b13.tar.gz |
Move LWRP class deprecation warning to const_missing
-rw-r--r-- | lib/chef/dsl/resources.rb | 16 | ||||
-rw-r--r-- | lib/chef/provider/lwrp_base.rb | 1 | ||||
-rw-r--r-- | lib/chef/resource.rb | 33 | ||||
-rw-r--r-- | lib/chef/resource/lwrp_base.rb | 26 | ||||
-rw-r--r-- | lib/chef/resource_resolver.rb | 2 | ||||
-rw-r--r-- | spec/spec_helper.rb | 3 | ||||
-rw-r--r-- | spec/unit/guard_interpreter/resource_guard_interpreter_spec.rb | 2 | ||||
-rw-r--r-- | spec/unit/lwrp_spec.rb | 38 | ||||
-rw-r--r-- | spec/unit/resource/batch_spec.rb | 1 | ||||
-rw-r--r-- | spec/unit/resource/powershell_spec.rb | 1 | ||||
-rw-r--r-- | spec/unit/resource_spec.rb | 64 |
11 files changed, 111 insertions, 76 deletions
diff --git a/lib/chef/dsl/resources.rb b/lib/chef/dsl/resources.rb index 482b14e3aa..4072ff2c89 100644 --- a/lib/chef/dsl/resources.rb +++ b/lib/chef/dsl/resources.rb @@ -8,14 +8,20 @@ class Chef # @api private module Resources def self.add_resource_dsl(dsl_name) - module_eval <<-EOM, __FILE__, __LINE__+1 - def #{dsl_name}(name, created_at=nil, &block) - declare_resource(#{dsl_name.inspect}, name, created_at || caller[0], &block) + begin + module_eval(<<-EOM, __FILE__, __LINE__+1) + def #{dsl_name}(name, created_at=nil, &block) + declare_resource(#{dsl_name.inspect}, name, created_at || caller[0], &block) + end + EOM + rescue SyntaxError + define_method(dsl_name.to_sym) do |name, created_at=nil, &block| + declare_resource(dsl_name, name, created_at || caller[0], &block) end - EOM + end end def self.remove_resource_dsl(dsl_name) - remove_method dsl_name if method_defined?(dsl_name) + remove_method(dsl_name) if method_defined?(dsl_name) end end end diff --git a/lib/chef/provider/lwrp_base.rb b/lib/chef/provider/lwrp_base.rb index 492ddda6da..0eadfe9467 100644 --- a/lib/chef/provider/lwrp_base.rb +++ b/lib/chef/provider/lwrp_base.rb @@ -93,6 +93,7 @@ class Chef else provider_class = Class.new(self) Chef::Provider.const_set(class_name, provider_class) + provider_class.provides provider_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 diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index 7e0dd6395a..565313e3e1 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -1133,16 +1133,43 @@ class Chef begin rname = convert_to_class_name(short_name.to_s) result = Chef::Resource.const_get(rname) - Chef::Log.deprecation("Class Chef::Resource::#{rname} does not declare `provides #{short_name.inspect}`.") - Chef::Log.deprecation("This will no longer work in Chef 13: you must use `provides` to provide DSL.") - result + if result.is_a?(Chef::Resource) + Chef::Log.deprecation("Class Chef::Resource::#{rname} does not declare `provides #{short_name.inspect}`.") + Chef::Log.deprecation("This will no longer work in Chef 13: you must use `provides` to provide DSL.") + result + end rescue NameError nil 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}" + 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 + end + end + private + def self.deprecated_constants + @deprecated_constants ||= {} + end + def lookup_provider_constant(name) begin self.class.provider_base.const_get(convert_to_class_name(name.to_s)) diff --git a/lib/chef/resource/lwrp_base.rb b/lib/chef/resource/lwrp_base.rb index f702db5c96..3e3670b4ac 100644 --- a/lib/chef/resource/lwrp_base.rb +++ b/lib/chef/resource/lwrp_base.rb @@ -50,6 +50,7 @@ class Chef resource_class = Class.new(self) resource_class.resource_name = resource_name resource_class.run_context = run_context + resource_class.provides resource_name.to_sym resource_class.class_from_file(filename) # Respect resource_name set inside the LWRP @@ -62,34 +63,11 @@ class Chef Chef::Log.debug("Loaded contents of #{filename} into #{resource_class}") - create_deprecated_class_in_chef_resource(resource_class) + Chef::Resource.create_deprecated_lwrp_class(resource_class) resource_class end - def self.create_deprecated_class_in_chef_resource(resource_class) - # Create a class in Chef::Resource::MyResource with deprecation - # warnings if you try to instantiate or inherit it (for Chef 12 compatibility) - class_name = convert_to_class_name(resource_class.resource_name) - if Chef::Resource.const_defined?(class_name, false) - Chef::Log.debug "#{class_name} already exists! Cannot create deprecation class #{resource_class}" - else - Chef::Resource.const_set(class_name, Class.new(resource_class) do - self.resource_name = resource_class.resource_name - self.run_context = resource_class.run_context - define_method(:initialize) do |*args, &block| - Chef::Log.warn("Using an LWRP by its name (#{class_name}) directly is no longer supported in Chef 12 and will be removed.") - super(*args, &block) - end - define_singleton_method(:inherited) do |*args, &block| - Chef::Log.warn("Using an LWRP by its name (#{class_name}) directly is no longer supported in Chef 12 and will be removed.") - super(*args, &block) - end - end) - end - Chef::Resource.const_get(class_name) - end - def self.resource_name(arg = NULL_ARG) if arg.equal?(NULL_ARG) @resource_name || dsl_name diff --git a/lib/chef/resource_resolver.rb b/lib/chef/resource_resolver.rb index 4560bac347..d4151e7125 100644 --- a/lib/chef/resource_resolver.rb +++ b/lib/chef/resource_resolver.rb @@ -30,7 +30,7 @@ class Chef def initialize(node, resource) @node = node - @resource = resource + @resource = resource.to_sym end # return a deterministically sorted list of Chef::Resource subclasses diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index fb284c721b..7cc9b8f7d6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -54,6 +54,9 @@ Dir['lib/chef/knife/**/*.rb']. map {|f| f.gsub(%r[\.rb$], '') }. each {|f| require f } +require 'chef/resource_resolver' +require 'chef/provider_resolver' + require 'chef/mixins' require 'chef/dsl' require 'chef/application' diff --git a/spec/unit/guard_interpreter/resource_guard_interpreter_spec.rb b/spec/unit/guard_interpreter/resource_guard_interpreter_spec.rb index 4cf3ba827a..02e4eb2fae 100644 --- a/spec/unit/guard_interpreter/resource_guard_interpreter_spec.rb +++ b/spec/unit/guard_interpreter/resource_guard_interpreter_spec.rb @@ -24,6 +24,7 @@ describe Chef::GuardInterpreter::ResourceGuardInterpreter do node.default["kernel"] = Hash.new node.default["kernel"][:machine] = :x86_64.to_s + node.automatic[:os] = 'windows' node end @@ -144,4 +145,3 @@ describe Chef::GuardInterpreter::ResourceGuardInterpreter do end end end - diff --git a/spec/unit/lwrp_spec.rb b/spec/unit/lwrp_spec.rb index 08273f3872..245074f0ab 100644 --- a/spec/unit/lwrp_spec.rb +++ b/spec/unit/lwrp_spec.rb @@ -31,6 +31,10 @@ describe "LWRP" do $VERBOSE = @original_VERBOSE end + def get_lwrp(name) + Chef::Resource.resource_for_node(name, Chef::Node.new) + end + describe "when overriding an existing class" do before :each do allow($stderr).to receive(:write) @@ -43,7 +47,6 @@ describe "LWRP" do expect(Chef::Log).not_to receive(:debug).with(/anymore/) Chef::Resource::LWRPBase.build_from_file("lwrp", file, nil) Object.send(:remove_const, 'LwrpFoo') - Chef::Resource.send(:remove_const, 'LwrpFoo') end it "should not skip loading a provider when there's a top level symbol of the same name" do @@ -53,7 +56,6 @@ describe "LWRP" do expect(Chef::Log).not_to receive(:debug).with(/anymore/) Chef::Provider::LWRPBase.build_from_file("lwrp", file, nil) Object.send(:remove_const, 'LwrpBuckPasser') - Chef::Provider.send(:remove_const, 'LwrpBuckPasser') end # @todo: we need a before block to manually remove_const all of the LWRPs that we @@ -92,7 +94,7 @@ describe "LWRP" do Dir[File.expand_path( "lwrp/resources/*", CHEF_SPEC_DATA)].each do |file| Chef::Resource::LWRPBase.build_from_file("lwrp", file, nil) end - first_lwr_foo_class = Chef::Resource::LwrpFoo + first_lwr_foo_class = get_lwrp(:lwrp_foo) expect(Chef::Resource.resource_classes).to include(first_lwr_foo_class) Dir[File.expand_path( "lwrp/resources/*", CHEF_SPEC_DATA)].each do |file| Chef::Resource::LWRPBase.build_from_file("lwrp", file, nil) @@ -120,28 +122,28 @@ describe "LWRP" do end end - it "should load the resource into a properly-named class" do - expect(Chef::Resource.const_get("LwrpFoo")).to be_kind_of(Class) + 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) end it "should set resource_name" do - expect(Chef::Resource::LwrpFoo.new("blah").resource_name).to eql(:lwrp_foo) + expect(get_lwrp(:lwrp_foo).new("blah").resource_name).to eql(:lwrp_foo) end it "should add the specified actions to the allowed_actions array" do - expect(Chef::Resource::LwrpFoo.new("blah").allowed_actions).to include(:pass_buck, :twiddle_thumbs) + expect(get_lwrp(:lwrp_foo).new("blah").allowed_actions).to include(:pass_buck, :twiddle_thumbs) end it "should set the specified action as the default action" do - expect(Chef::Resource::LwrpFoo.new("blah").action).to eq(:pass_buck) + expect(get_lwrp(:lwrp_foo).new("blah").action).to eq(:pass_buck) end it "should create a method for each attribute" do - expect(Chef::Resource::LwrpFoo.new("blah").methods.map{ |m| m.to_sym}).to include(:monkey) + expect(get_lwrp(:lwrp_foo).new("blah").methods.map{ |m| m.to_sym}).to include(:monkey) end it "should build attribute methods that respect validation rules" do - expect { Chef::Resource::LwrpFoo.new("blah").monkey(42) }.to raise_error(ArgumentError) + expect { get_lwrp(:lwrp_foo).new("blah").monkey(42) }.to raise_error(ArgumentError) end it "should have access to the run context and node during class definition" do @@ -153,7 +155,7 @@ describe "LWRP" do Chef::Resource::LWRPBase.build_from_file("lwrp", file, run_context) end - cls = Chef::Resource.const_get("LwrpNodeattr") + cls = get_lwrp(:lwrp_nodeattr) expect(cls.node).to be_kind_of(Chef::Node) expect(cls.run_context).to be_kind_of(Chef::RunContext) expect(cls.node[:penguin_name]).to eql("jackass") @@ -312,7 +314,7 @@ describe "LWRP" do end it "should properly handle a new_resource reference" do - resource = Chef::Resource::LwrpFoo.new("morpheus") + resource = get_lwrp(:lwrp_foo).new("morpheus") resource.monkey("bob") resource.provider(:lwrp_monkey_name_printer) resource.run_context = @run_context @@ -332,7 +334,7 @@ describe "LWRP" do end it "should insert resources embedded in the provider into the middle of the resource collection" do - injector = Chef::Resource::LwrpFoo.new("morpheus", @run_context) + injector = get_lwrp(:lwrp_foo).new("morpheus", @run_context) injector.action(:pass_buck) injector.provider(:lwrp_buck_passer) dummy = Chef::Resource::ZenMaster.new("keanu reeves", @run_context) @@ -349,11 +351,11 @@ describe "LWRP" do end it "should insert embedded resources from multiple providers, including from the last position, properly into the resource collection" do - injector = Chef::Resource::LwrpFoo.new("morpheus", @run_context) + injector = get_lwrp(:lwrp_foo).new("morpheus", @run_context) injector.action(:pass_buck) injector.provider(:lwrp_buck_passer) - injector2 = Chef::Resource::LwrpBar.new("tank", @run_context) + injector2 = get_lwrp(:lwrp_bar).new("tank", @run_context) injector2.action(:pass_buck) injector2.provider(:lwrp_buck_passer_2) @@ -376,7 +378,7 @@ describe "LWRP" do end it "should properly handle a new_resource reference" do - resource = Chef::Resource::LwrpFoo.new("morpheus", @run_context) + resource = get_lwrp(:lwrp_foo).new("morpheus", @run_context) resource.monkey("bob") resource.provider(:lwrp_monkey_name_printer) @@ -387,7 +389,7 @@ describe "LWRP" do end it "should properly handle an embedded Resource accessing the enclosing Provider's scope" do - resource = Chef::Resource::LwrpFoo.new("morpheus", @run_context) + resource = get_lwrp(:lwrp_foo).new("morpheus", @run_context) resource.monkey("bob") resource.provider(:lwrp_embedded_resource_accesses_providers_scope) @@ -406,7 +408,7 @@ describe "LWRP" do # Side effect of lwrp_inline_compiler provider for testing notifications. $interior_ruby_block_2 = nil # resource type doesn't matter, so make an existing resource type work with provider. - @resource = Chef::Resource::LwrpFoo.new("morpheus", @run_context) + @resource = get_lwrp(:lwrp_foo).new("morpheus", @run_context) @resource.allowed_actions << :test @resource.action(:test) @resource.provider(:lwrp_inline_compiler) diff --git a/spec/unit/resource/batch_spec.rb b/spec/unit/resource/batch_spec.rb index 4a056b8735..b8c2897f42 100644 --- a/spec/unit/resource/batch_spec.rb +++ b/spec/unit/resource/batch_spec.rb @@ -25,6 +25,7 @@ describe Chef::Resource::Batch do node.default["kernel"] = Hash.new node.default["kernel"][:machine] = :x86_64.to_s + node.automatic[:os] = 'windows' run_context = Chef::RunContext.new(node, nil, nil) diff --git a/spec/unit/resource/powershell_spec.rb b/spec/unit/resource/powershell_spec.rb index c263172ae6..2505c4a3d7 100644 --- a/spec/unit/resource/powershell_spec.rb +++ b/spec/unit/resource/powershell_spec.rb @@ -25,6 +25,7 @@ describe Chef::Resource::PowershellScript do node.default["kernel"] = Hash.new node.default["kernel"][:machine] = :x86_64.to_s + node.automatic[:os] = 'windows' run_context = Chef::RunContext.new(node, nil, nil) diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index 6b2d6c89d3..0479778f55 100644 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -731,35 +731,51 @@ describe Chef::Resource do end - describe "lookups from the platform map" do - let(:klz1) { Class.new(Chef::Resource) } - let(:klz2) { Class.new(Chef::Resource) } + describe "resource_for_node" do + describe "lookups from the platform map" do + let(:klz1) { Class.new(Chef::Resource) } + + before(:each) do + Chef::Resource::Klz1 = klz1 + @node = Chef::Node.new + @node.name("bumblebee") + @node.automatic[:platform] = "autobots" + @node.automatic[:platform_version] = "6.1" + Object.const_set('Soundwave', klz1) + klz1.provides :soundwave + end - before(:each) do - Chef::Resource::Klz1 = klz1 - Chef::Resource::Klz2 = klz2 - @node = Chef::Node.new - @node.name("bumblebee") - @node.automatic[:platform] = "autobots" - @node.automatic[:platform_version] = "6.1" - Object.const_set('Soundwave', klz1) - klz2.provides :dinobot, :on_platforms => ['autobots'] - Object.const_set('Grimlock', klz2) - end + after(:each) do + Object.send(:remove_const, :Soundwave) + Chef::Resource.send(:remove_const, :Klz1) + end - after(:each) do - Object.send(:remove_const, :Soundwave) - Object.send(:remove_const, :Grimlock) - Chef::Resource.send(:remove_const, :Klz1) - Chef::Resource.send(:remove_const, :Klz2) + it "returns a resource by short_name if nothing else matches" do + expect(Chef::Resource.resource_for_node(:soundwave, @node)).to eql(klz1) + end end - describe "resource_for_node" do - it "returns a resource by short_name and node" do - expect(Chef::Resource.resource_for_node(:dinobot, @node)).to eql(Grimlock) + describe "lookups from the platform map" do + let(:klz2) { Class.new(Chef::Resource) } + + before(:each) do + Chef::Resource::Klz2 = klz2 + @node = Chef::Node.new + @node.name("bumblebee") + @node.automatic[:platform] = "autobots" + @node.automatic[:platform_version] = "6.1" + klz2.provides :dinobot, :on_platforms => ['autobots'] + Object.const_set('Grimlock', klz2) + klz2.provides :grimlock end - it "returns a resource by short_name if nothing else matches" do - expect(Chef::Resource.resource_for_node(:soundwave, @node)).to eql(Soundwave) + + after(:each) do + Object.send(:remove_const, :Grimlock) + Chef::Resource.send(:remove_const, :Klz2) + end + + it "returns a resource by short_name and node" do + expect(Chef::Resource.resource_for_node(:dinobot, @node)).to eql(klz2) end end |