summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorJohn Keiser <john@johnkeiser.com>2015-06-30 21:14:28 -0600
committerJohn Keiser <john@johnkeiser.com>2015-07-06 12:04:47 -0600
commit591b5599f5412faa382e45d035d76535cd93736a (patch)
tree3494785822024b7c4acc97adc4883c7a73e2eaaf /spec
parentcfd2b1fa1b26e8b0aa92a5ba8bd294b96379b2fa (diff)
downloadchef-591b5599f5412faa382e45d035d76535cd93736a.tar.gz
Re-separate priority map and DSL handler map so that provides has veto power over priority
Diffstat (limited to 'spec')
-rw-r--r--spec/integration/recipes/recipe_dsl_spec.rb959
-rw-r--r--spec/unit/lwrp_spec.rb8
-rw-r--r--spec/unit/provider_resolver_spec.rb7
-rw-r--r--spec/unit/resource_spec.rb6
4 files changed, 606 insertions, 374 deletions
diff --git a/spec/integration/recipes/recipe_dsl_spec.rb b/spec/integration/recipes/recipe_dsl_spec.rb
index fa38808e3e..4e80c5a738 100644
--- a/spec/integration/recipes/recipe_dsl_spec.rb
+++ b/spec/integration/recipes/recipe_dsl_spec.rb
@@ -401,370 +401,6 @@ describe "Recipe DSL methods" do
}.to raise_error(NoMethodError)
end
end
-
- context "with a resource named 'B' with resource name :two_classes_one_dsl" do
- let(:two_classes_one_dsl) { :"two_classes_one_dsl#{Namer.current_index}" }
- let(:resource_class) {
- result = Class.new(BaseThingy) do
- def self.name
- "B"
- end
- def self.to_s; name; end
- def self.inspect; name.inspect; end
- end
- result.resource_name two_classes_one_dsl
- result
- }
- before { resource_class } # pull on it so it gets defined before the recipe runs
-
- context "and another resource named 'A' with resource_name :two_classes_one_dsl" do
- let(:resource_class_a) {
- result = Class.new(BaseThingy) do
- def self.name
- "A"
- end
- def self.to_s; name; end
- def self.inspect; name.inspect; end
- end
- result.resource_name two_classes_one_dsl
- result
- }
- before { resource_class_a } # pull on it so it gets defined before the recipe runs
-
- it "two_classes_one_dsl resolves to A (alphabetically earliest)" do
- two_classes_one_dsl = self.two_classes_one_dsl
- recipe = converge {
- instance_eval("#{two_classes_one_dsl} 'blah'")
- }
- expect(recipe.logged_warnings).to eq ''
- expect(BaseThingy.created_resource).to eq resource_class_a
- end
-
- it "resource_matching_short_name returns B" do
- expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class_a
- end
- end
-
- context "and another resource named 'Z' with resource_name :two_classes_one_dsl" do
- let(:resource_class_z) {
- result = Class.new(BaseThingy) do
- def self.name
- "Z"
- end
- def self.to_s; name; end
- def self.inspect; name.inspect; end
- end
- result.resource_name two_classes_one_dsl
- result
- }
- before { resource_class_z } # pull on it so it gets defined before the recipe runs
-
- it "two_classes_one_dsl resolves to B (alphabetically earliest)" do
- two_classes_one_dsl = self.two_classes_one_dsl
- recipe = converge {
- instance_eval("#{two_classes_one_dsl} 'blah'")
- }
- expect(recipe.logged_warnings).to eq ''
- expect(BaseThingy.created_resource).to eq resource_class
- end
-
- it "resource_matching_short_name returns B" do
- expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
- end
- end
-
- context "and another resource Blarghle with provides :two_classes_one_dsl, os: 'blarghle'" do
- let(:resource_class_blarghle) {
- result = Class.new(BaseThingy) do
- def self.name
- "Blarghle"
- end
- def self.to_s; name; end
- def self.inspect; name.inspect; end
- end
- result.resource_name two_classes_one_dsl
- result.provides two_classes_one_dsl, os: 'blarghle'
- result
- }
- before { resource_class_blarghle } # pull on it so it gets defined before the recipe runs
-
- it "on os = blarghle, two_classes_one_dsl resolves to Blarghle" do
- two_classes_one_dsl = self.two_classes_one_dsl
- recipe = converge {
- # this is an ugly way to test, make Cheffish expose node attrs
- run_context.node.automatic[:os] = 'blarghle'
- instance_eval("#{two_classes_one_dsl} 'blah' do; end")
- }
- expect(recipe.logged_warnings).to eq ''
- expect(BaseThingy.created_resource).to eq resource_class_blarghle
- end
-
- it "on os = linux, two_classes_one_dsl resolves to B" do
- two_classes_one_dsl = self.two_classes_one_dsl
- recipe = converge {
- # this is an ugly way to test, make Cheffish expose node attrs
- run_context.node.automatic[:os] = 'linux'
- instance_eval("#{two_classes_one_dsl} 'blah' do; end")
- }
- expect(recipe.logged_warnings).to eq ''
- expect(BaseThingy.created_resource).to eq resource_class
- end
- end
- end
-
- context "with a resource MyResource" do
- let(:resource_class) { Class.new(BaseThingy) do
- def self.called_provides
- @called_provides
- end
- def to_s
- "MyResource"
- end
- end }
- let(:my_resource) { :"my_resource#{Namer.current_index}" }
- let(:blarghle_blarghle_little_star) { :"blarghle_blarghle_little_star#{Namer.current_index}" }
-
- context "with resource_name :my_resource" do
- before {
- resource_class.resource_name my_resource
- }
-
- context "with provides? returning true to my_resource" do
- before {
- my_resource = self.my_resource
- resource_class.define_singleton_method(:provides?) do |node, resource_name|
- @called_provides = true
- resource_name == my_resource
- end
- }
-
- it "my_resource returns the resource and calls provides?, but does not emit a warning" do
- dsl_name = self.my_resource
- recipe = converge {
- instance_eval("#{dsl_name} 'foo'")
- }
- expect(recipe.logged_warnings).to eq ''
- expect(BaseThingy.created_resource).to eq resource_class
- expect(resource_class.called_provides).to be_truthy
- end
- end
-
- context "with provides? returning true to blarghle_blarghle_little_star and not resource_name" do
- before do
- blarghle_blarghle_little_star = self.blarghle_blarghle_little_star
- resource_class.define_singleton_method(:provides?) do |node, resource_name|
- @called_provides = true
- resource_name == blarghle_blarghle_little_star
- end
- end
-
- it "my_resource does not return the resource" do
- dsl_name = self.my_resource
- expect_converge {
- instance_eval("#{dsl_name} 'foo'")
- }.to raise_error(Chef::Exceptions::NoSuchResourceType)
- expect(resource_class.called_provides).to be_truthy
- end
-
- it "blarghle_blarghle_little_star 'foo' returns the resource and emits a warning" do
- dsl_name = self.blarghle_blarghle_little_star
- recipe = converge {
- instance_eval("#{dsl_name} 'foo'")
- }
- expect(recipe.logged_warnings).to include "WARN: #{resource_class}.provides? returned true when asked if it provides DSL #{dsl_name}, but provides :#{dsl_name} was never called!"
- expect(BaseThingy.created_resource).to eq resource_class
- expect(resource_class.called_provides).to be_truthy
- end
- end
-
- context "and a provider" do
- let(:provider_class) do
- Class.new(BaseThingy::Provider) do
- def self.name
- "MyProvider"
- end
- def self.to_s; name; end
- def self.inspect; name.inspect; end
- def self.called_provides
- @called_provides
- end
- end
- end
-
- before do
- resource_class.send(:define_method, :provider) { nil }
- end
-
- context "that provides :my_resource" do
- before do
- provider_class.provides my_resource
- end
-
- context "with supports? returning true" do
- before do
- provider_class.define_singleton_method(:supports?) { |resource,action| true }
- end
-
- it "my_resource runs the provider and does not emit a warning" do
- my_resource = self.my_resource
- recipe = converge {
- instance_eval("#{my_resource} 'foo'")
- }
- expect(recipe.logged_warnings).to eq ''
- expect(BaseThingy.created_provider).to eq provider_class
- end
-
- context "and another provider supporting :my_resource with supports? false" do
- let(:provider_class2) do
- Class.new(BaseThingy::Provider) do
- def self.name
- "MyProvider2"
- end
- def self.to_s; name; end
- def self.inspect; name.inspect; end
- def self.called_provides
- @called_provides
- end
- provides my_resource
- def self.supports?(resource, action)
- false
- end
- end
- end
-
- it "my_resource runs the first provider" do
- my_resource = self.my_resource
- recipe = converge {
- instance_eval("#{my_resource} 'foo'")
- }
- expect(recipe.logged_warnings).to eq ''
- expect(BaseThingy.created_provider).to eq provider_class
- end
- end
- end
-
- context "with supports? returning false" do
- before do
- provider_class.define_singleton_method(:supports?) { |resource,action| false }
- end
-
- # TODO no warning? ick
- it "my_resource runs the provider anyway" do
- my_resource = self.my_resource
- recipe = converge {
- instance_eval("#{my_resource} 'foo'")
- }
- expect(recipe.logged_warnings).to eq ''
- expect(BaseThingy.created_provider).to eq provider_class
- end
-
- context "and another provider supporting :my_resource with supports? true" do
- let(:provider_class2) do
- my_resource = self.my_resource
- Class.new(BaseThingy::Provider) do
- def self.name
- "MyProvider2"
- end
- def self.to_s; name; end
- def self.inspect; name.inspect; end
- def self.called_provides
- @called_provides
- end
- provides my_resource
- def self.supports?(resource, action)
- true
- end
- end
- end
- before { provider_class2 } # make sure the provider class shows up
-
- it "my_resource runs the other provider" do
- my_resource = self.my_resource
- recipe = converge {
- instance_eval("#{my_resource} 'foo'")
- }
- expect(recipe.logged_warnings).to eq ''
- expect(BaseThingy.created_provider).to eq provider_class2
- end
- end
- end
- end
-
- context "with provides? returning true" do
- before {
- my_resource = self.my_resource
- provider_class.define_singleton_method(:provides?) do |node, resource|
- @called_provides = true
- resource.declared_type == my_resource
- end
- }
-
- context "that provides :my_resource" do
- before {
- provider_class.provides my_resource
- }
-
- it "my_resource calls the provider (and calls provides?), but does not emit a warning" do
- my_resource = self.my_resource
- recipe = converge {
- instance_eval("#{my_resource} 'foo'")
- }
- expect(recipe.logged_warnings).to eq ''
- expect(BaseThingy.created_provider).to eq provider_class
- expect(provider_class.called_provides).to be_truthy
- end
- end
-
- context "that does not call provides :my_resource" do
- it "my_resource calls the provider (and calls provides?), and emits a warning" do
- my_resource = self.my_resource
- recipe = converge {
- instance_eval("#{my_resource} 'foo'")
- }
- expect(recipe.logged_warnings).to include("WARN: #{provider_class}.provides? returned true when asked if it provides DSL #{my_resource}, but provides :#{my_resource} was never called!")
- expect(BaseThingy.created_provider).to eq provider_class
- expect(provider_class.called_provides).to be_truthy
- end
- end
- end
-
- context "with provides? returning false to my_resource" do
- before {
- my_resource = self.my_resource
- provider_class.define_singleton_method(:provides?) do |node, resource|
- @called_provides = true
- false
- end
- }
-
- context "that provides :my_resource" do
- before {
- provider_class.provides my_resource
- }
-
- it "my_resource fails to find a provider (and calls provides)" do
- my_resource = self.my_resource
- expect_converge {
- instance_eval("#{my_resource} 'foo'")
- }.to raise_error(Chef::Exceptions::ProviderNotFound)
- expect(provider_class.called_provides).to be_truthy
- end
- end
-
- context "that does not provide :my_resource" do
- it "my_resource fails to find a provider (and calls provides)" do
- my_resource = self.my_resource
- expect_converge {
- instance_eval("#{my_resource} 'foo'")
- }.to raise_error(Chef::Exceptions::ProviderNotFound)
- expect(provider_class.called_provides).to be_truthy
- end
- end
- end
- end
- end
- end
-
end
end
@@ -1175,6 +811,601 @@ describe "Recipe DSL methods" do
end
end
end
+
+ context "with a resource named 'B' with resource name :two_classes_one_dsl" do
+ let(:two_classes_one_dsl) { :"two_classes_one_dsl#{Namer.current_index}" }
+ let(:resource_class) {
+ result = Class.new(BaseThingy) do
+ def self.name
+ "B"
+ end
+ def self.to_s; name; end
+ def self.inspect; name.inspect; end
+ end
+ result.resource_name two_classes_one_dsl
+ result
+ }
+ before { resource_class } # pull on it so it gets defined before the recipe runs
+
+ context "and another resource named 'A' with resource_name :two_classes_one_dsl" do
+ let(:resource_class_a) {
+ result = Class.new(BaseThingy) do
+ def self.name
+ "A"
+ end
+ def self.to_s; name; end
+ def self.inspect; name.inspect; end
+ end
+ result.resource_name two_classes_one_dsl
+ result
+ }
+ before { resource_class_a } # pull on it so it gets defined before the recipe runs
+
+ it "two_classes_one_dsl resolves to A (alphabetically earliest)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_resource).to eq resource_class_a
+ end
+
+ it "resource_matching_short_name returns B" do
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class_a
+ end
+ end
+
+ context "and another resource named 'Z' with resource_name :two_classes_one_dsl" do
+ let(:resource_class_z) {
+ result = Class.new(BaseThingy) do
+ def self.name
+ "Z"
+ end
+ def self.to_s; name; end
+ def self.inspect; name.inspect; end
+ end
+ result.resource_name two_classes_one_dsl
+ result
+ }
+ before { resource_class_z } # pull on it so it gets defined before the recipe runs
+
+ it "two_classes_one_dsl resolves to B (alphabetically earliest)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_resource).to eq resource_class
+ end
+
+ it "resource_matching_short_name returns B" do
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
+ end
+
+ context "and a priority array [ Z, B ]" do
+ before do
+ Chef.set_resource_priority_array(two_classes_one_dsl, [ resource_class_z, resource_class ])
+ end
+
+ it "two_classes_one_dsl resolves to Z (respects the priority array)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_resource).to eq resource_class_z
+ end
+
+ it "resource_matching_short_name returns B" do
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
+ end
+
+ context "when Z provides(:two_classes_one_dsl) { false }" do
+ before do
+ resource_class_z.provides(two_classes_one_dsl) { false }
+ end
+
+ it "two_classes_one_dsl resolves to B (picks the next thing in the priority array)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_resource).to eq resource_class
+ end
+
+ it "resource_matching_short_name returns B" do
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
+ end
+ end
+ end
+
+ context "and priority arrays [ B ] and [ Z ]" do
+ before do
+ Chef.set_resource_priority_array(two_classes_one_dsl, [ resource_class ])
+ Chef.set_resource_priority_array(two_classes_one_dsl, [ resource_class_z ])
+ end
+
+ it "two_classes_one_dsl resolves to Z (respects the most recent priority array)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_resource).to eq resource_class_z
+ end
+
+ it "resource_matching_short_name returns B" do
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
+ end
+
+ context "when Z provides(:two_classes_one_dsl) { false }" do
+ before do
+ resource_class_z.provides(two_classes_one_dsl) { false }
+ end
+
+ it "two_classes_one_dsl resolves to B (picks the first match from the other priority array)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_resource).to eq resource_class
+ end
+
+ it "resource_matching_short_name returns B" do
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
+ end
+ end
+ end
+
+ context "and a priority array [ Z ]" do
+ before do
+ Chef.set_resource_priority_array(two_classes_one_dsl, [ resource_class_z ])
+ end
+
+ context "when Z provides(:two_classes_one_dsl) { false }" do
+ before do
+ resource_class_z.provides(two_classes_one_dsl) { false }
+ end
+
+ it "two_classes_one_dsl resolves to B (picks the first match outside the priority array)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_resource).to eq resource_class
+ end
+
+ it "resource_matching_short_name returns B" do
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
+ end
+ end
+ end
+
+ end
+
+ context "and a provider named 'B' which provides :two_classes_one_dsl" do
+ before do
+ resource_class.send(:define_method, :provider) { nil }
+ end
+
+ let(:provider_class) {
+ result = Class.new(BaseThingy::Provider) do
+ def self.name
+ "B"
+ end
+ def self.to_s; name; end
+ def self.inspect; name.inspect; end
+ end
+ result.provides two_classes_one_dsl
+ result
+ }
+ before { provider_class } # pull on it so it gets defined before the recipe runs
+
+ context "and another provider named 'A'" do
+ let(:provider_class_a) {
+ result = Class.new(BaseThingy::Provider) do
+ def self.name
+ "A"
+ end
+ def self.to_s; name; end
+ def self.inspect; name.inspect; end
+ end
+ result
+ }
+ context "which provides :two_classes_one_dsl" do
+ before { provider_class_a.provides two_classes_one_dsl }
+
+ it "two_classes_one_dsl resolves to A (alphabetically earliest)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_provider).to eq provider_class_a
+ end
+ end
+ context "which provides(:two_classes_one_dsl) { false }" do
+ before { provider_class_a.provides(two_classes_one_dsl) { false } }
+
+ it "two_classes_one_dsl resolves to B (since A declined)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_provider).to eq provider_class
+ end
+ end
+ end
+
+ context "and another provider named 'Z'" do
+ let(:provider_class_z) {
+ result = Class.new(BaseThingy::Provider) do
+ def self.name
+ "Z"
+ end
+ def self.to_s; name; end
+ def self.inspect; name.inspect; end
+ end
+ result
+ }
+ before { provider_class_z } # pull on it so it gets defined before the recipe runs
+
+ context "which provides :two_classes_one_dsl" do
+ before { provider_class_z.provides two_classes_one_dsl }
+
+ it "two_classes_one_dsl resolves to B (alphabetically earliest)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_provider).to eq provider_class
+ end
+
+ context "with a priority array [ Z, B ]" do
+ before { Chef.set_provider_priority_array two_classes_one_dsl, [ provider_class_z, provider_class ] }
+
+ it "two_classes_one_dsl resolves to Z (respects the priority map)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_provider).to eq provider_class_z
+ end
+ end
+ end
+
+ context "which provides(:two_classes_one_dsl) { false }" do
+ before { provider_class_z.provides(two_classes_one_dsl) { false } }
+
+ context "with a priority array [ Z, B ]" do
+ before { Chef.set_provider_priority_array two_classes_one_dsl, [ provider_class_z, provider_class ] }
+
+ it "two_classes_one_dsl resolves to B (the next one in the priority map)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_provider).to eq provider_class
+ end
+ end
+
+ context "with priority arrays [ B ] and [ Z ]" do
+ before { Chef.set_provider_priority_array two_classes_one_dsl, [ provider_class_z ] }
+ before { Chef.set_provider_priority_array two_classes_one_dsl, [ provider_class ] }
+
+ it "two_classes_one_dsl resolves to B (the one in the next priority map)" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ instance_eval("#{two_classes_one_dsl} 'blah'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_provider).to eq provider_class
+ end
+ end
+ end
+ end
+ end
+
+ context "and another resource Blarghle with provides :two_classes_one_dsl, os: 'blarghle'" do
+ let(:resource_class_blarghle) {
+ result = Class.new(BaseThingy) do
+ def self.name
+ "Blarghle"
+ end
+ def self.to_s; name; end
+ def self.inspect; name.inspect; end
+ end
+ result.resource_name two_classes_one_dsl
+ result.provides two_classes_one_dsl, os: 'blarghle'
+ result
+ }
+ before { resource_class_blarghle } # pull on it so it gets defined before the recipe runs
+
+ it "on os = blarghle, two_classes_one_dsl resolves to Blarghle" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ # this is an ugly way to test, make Cheffish expose node attrs
+ run_context.node.automatic[:os] = 'blarghle'
+ instance_eval("#{two_classes_one_dsl} 'blah' do; end")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_resource).to eq resource_class_blarghle
+ end
+
+ it "on os = linux, two_classes_one_dsl resolves to B" do
+ two_classes_one_dsl = self.two_classes_one_dsl
+ recipe = converge {
+ # this is an ugly way to test, make Cheffish expose node attrs
+ run_context.node.automatic[:os] = 'linux'
+ instance_eval("#{two_classes_one_dsl} 'blah' do; end")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_resource).to eq resource_class
+ end
+ end
+ end
+
+ context "with a resource MyResource" do
+ let(:resource_class) { Class.new(BaseThingy) do
+ def self.called_provides
+ @called_provides
+ end
+ def to_s
+ "MyResource"
+ end
+ end }
+ let(:my_resource) { :"my_resource#{Namer.current_index}" }
+ let(:blarghle_blarghle_little_star) { :"blarghle_blarghle_little_star#{Namer.current_index}" }
+
+ context "with resource_name :my_resource" do
+ before {
+ resource_class.resource_name my_resource
+ }
+
+ context "with provides? returning true to my_resource" do
+ before {
+ my_resource = self.my_resource
+ resource_class.define_singleton_method(:provides?) do |node, resource_name|
+ @called_provides = true
+ resource_name == my_resource
+ end
+ }
+
+ it "my_resource returns the resource and calls provides?, but does not emit a warning" do
+ dsl_name = self.my_resource
+ recipe = converge {
+ instance_eval("#{dsl_name} 'foo'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_resource).to eq resource_class
+ expect(resource_class.called_provides).to be_truthy
+ end
+ end
+
+ context "with provides? returning true to blarghle_blarghle_little_star and not resource_name" do
+ before do
+ blarghle_blarghle_little_star = self.blarghle_blarghle_little_star
+ resource_class.define_singleton_method(:provides?) do |node, resource_name|
+ @called_provides = true
+ resource_name == blarghle_blarghle_little_star
+ end
+ end
+
+ it "my_resource does not return the resource" do
+ dsl_name = self.my_resource
+ expect_converge {
+ instance_eval("#{dsl_name} 'foo'")
+ }.to raise_error(Chef::Exceptions::NoSuchResourceType)
+ expect(resource_class.called_provides).to be_truthy
+ end
+
+ it "blarghle_blarghle_little_star 'foo' returns the resource and emits a warning" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ dsl_name = self.blarghle_blarghle_little_star
+ recipe = converge {
+ instance_eval("#{dsl_name} 'foo'")
+ }
+ expect(recipe.logged_warnings).to include "WARN: #{resource_class}.provides? returned true when asked if it provides DSL #{dsl_name}, but provides :#{dsl_name} was never called!"
+ expect(BaseThingy.created_resource).to eq resource_class
+ expect(resource_class.called_provides).to be_truthy
+ end
+ end
+
+ context "and a provider" do
+ let(:provider_class) do
+ Class.new(BaseThingy::Provider) do
+ def self.name
+ "MyProvider"
+ end
+ def self.to_s; name; end
+ def self.inspect; name.inspect; end
+ def self.called_provides
+ @called_provides
+ end
+ end
+ end
+
+ before do
+ resource_class.send(:define_method, :provider) { nil }
+ end
+
+ context "that provides :my_resource" do
+ before do
+ provider_class.provides my_resource
+ end
+
+ context "with supports? returning true" do
+ before do
+ provider_class.define_singleton_method(:supports?) { |resource,action| true }
+ end
+
+ it "my_resource runs the provider and does not emit a warning" do
+ my_resource = self.my_resource
+ recipe = converge {
+ instance_eval("#{my_resource} 'foo'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_provider).to eq provider_class
+ end
+
+ context "and another provider supporting :my_resource with supports? false" do
+ let(:provider_class2) do
+ Class.new(BaseThingy::Provider) do
+ def self.name
+ "MyProvider2"
+ end
+ def self.to_s; name; end
+ def self.inspect; name.inspect; end
+ def self.called_provides
+ @called_provides
+ end
+ provides my_resource
+ def self.supports?(resource, action)
+ false
+ end
+ end
+ end
+
+ it "my_resource runs the first provider" do
+ my_resource = self.my_resource
+ recipe = converge {
+ instance_eval("#{my_resource} 'foo'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_provider).to eq provider_class
+ end
+ end
+ end
+
+ context "with supports? returning false" do
+ before do
+ provider_class.define_singleton_method(:supports?) { |resource,action| false }
+ end
+
+ # TODO no warning? ick
+ it "my_resource runs the provider anyway" do
+ my_resource = self.my_resource
+ recipe = converge {
+ instance_eval("#{my_resource} 'foo'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_provider).to eq provider_class
+ end
+
+ context "and another provider supporting :my_resource with supports? true" do
+ let(:provider_class2) do
+ my_resource = self.my_resource
+ Class.new(BaseThingy::Provider) do
+ def self.name
+ "MyProvider2"
+ end
+ def self.to_s; name; end
+ def self.inspect; name.inspect; end
+ def self.called_provides
+ @called_provides
+ end
+ provides my_resource
+ def self.supports?(resource, action)
+ true
+ end
+ end
+ end
+ before { provider_class2 } # make sure the provider class shows up
+
+ it "my_resource runs the other provider" do
+ my_resource = self.my_resource
+ recipe = converge {
+ instance_eval("#{my_resource} 'foo'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_provider).to eq provider_class2
+ end
+ end
+ end
+ end
+
+ context "with provides? returning true" do
+ before {
+ my_resource = self.my_resource
+ provider_class.define_singleton_method(:provides?) do |node, resource|
+ @called_provides = true
+ resource.declared_type == my_resource
+ end
+ }
+
+ context "that provides :my_resource" do
+ before {
+ provider_class.provides my_resource
+ }
+
+ it "my_resource calls the provider (and calls provides?), but does not emit a warning" do
+ my_resource = self.my_resource
+ recipe = converge {
+ instance_eval("#{my_resource} 'foo'")
+ }
+ expect(recipe.logged_warnings).to eq ''
+ expect(BaseThingy.created_provider).to eq provider_class
+ expect(provider_class.called_provides).to be_truthy
+ end
+ end
+
+ context "that does not call provides :my_resource" do
+ it "my_resource calls the provider (and calls provides?), and emits a warning" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ my_resource = self.my_resource
+ recipe = converge {
+ instance_eval("#{my_resource} 'foo'")
+ }
+ expect(recipe.logged_warnings).to include("WARN: #{provider_class}.provides? returned true when asked if it provides DSL #{my_resource}, but provides :#{my_resource} was never called!")
+ expect(BaseThingy.created_provider).to eq provider_class
+ expect(provider_class.called_provides).to be_truthy
+ end
+ end
+ end
+
+ context "with provides? returning false to my_resource" do
+ before {
+ my_resource = self.my_resource
+ provider_class.define_singleton_method(:provides?) do |node, resource|
+ @called_provides = true
+ false
+ end
+ }
+
+ context "that provides :my_resource" do
+ before {
+ provider_class.provides my_resource
+ }
+
+ it "my_resource fails to find a provider (and calls provides)" do
+ my_resource = self.my_resource
+ expect_converge {
+ instance_eval("#{my_resource} 'foo'")
+ }.to raise_error(Chef::Exceptions::ProviderNotFound)
+ expect(provider_class.called_provides).to be_truthy
+ end
+ end
+
+ context "that does not provide :my_resource" do
+ it "my_resource fails to find a provider (and calls provides)" do
+ my_resource = self.my_resource
+ expect_converge {
+ instance_eval("#{my_resource} 'foo'")
+ }.to raise_error(Chef::Exceptions::ProviderNotFound)
+ expect(provider_class.called_provides).to be_truthy
+ end
+ end
+ end
+ end
+ end
+ end
end
before(:all) { Namer.current_index = 0 }
diff --git a/spec/unit/lwrp_spec.rb b/spec/unit/lwrp_spec.rb
index 545524eb10..bcb64cb21e 100644
--- a/spec/unit/lwrp_spec.rb
+++ b/spec/unit/lwrp_spec.rb
@@ -439,7 +439,7 @@ describe "LWRP" do
end
it "sets itself as a provider for a resource of the same name" do
- found_providers = Chef::Platform::ProviderPriorityMap.instance.list_handlers(node, :lwrp_buck_passer)
+ found_providers = Chef::Platform::ProviderHandlerMap.instance.list(node, :lwrp_buck_passer)
# we bypass the per-file loading to get the file to load each time,
# which creates the LWRP class repeatedly. New things get prepended to
# the list of providers.
@@ -451,7 +451,7 @@ describe "LWRP" do
let(:lwrp_cookbok_name) { "l_w_r_p" }
it "sets itself as a provider for a resource of the same name" do
- found_providers = Chef::Platform::ProviderPriorityMap.instance.list_handlers(node, :l_w_r_p_buck_passer)
+ found_providers = Chef::Platform::ProviderHandlerMap.instance.list(node, :l_w_r_p_buck_passer)
expect(found_providers.size).to eq(1)
expect(found_providers.last).to eq(get_lwrp_provider(:l_w_r_p_buck_passer))
end
@@ -462,10 +462,10 @@ describe "LWRP" do
let(:lwrp_cookbok_name) { "l-w-r-p" }
it "sets itself as a provider for a resource of the same name" do
- incorrect_providers = Chef::Platform::ProviderPriorityMap.instance.list_handlers(node, :'l-w-r-p_buck_passer')
+ incorrect_providers = Chef::Platform::ProviderHandlerMap.instance.list(node, :'l-w-r-p_buck_passer')
expect(incorrect_providers).to eq([])
- found_providers = Chef::Platform::ProviderPriorityMap.instance.list_handlers(node, :l_w_r_p_buck_passer)
+ found_providers = Chef::Platform::ProviderHandlerMap.instance.list(node, :l_w_r_p_buck_passer)
expect(found_providers.first).to eq(get_lwrp_provider(:l_w_r_p_buck_passer))
end
end
diff --git a/spec/unit/provider_resolver_spec.rb b/spec/unit/provider_resolver_spec.rb
index e09b12a20a..88df4a20cc 100644
--- a/spec/unit/provider_resolver_spec.rb
+++ b/spec/unit/provider_resolver_spec.rb
@@ -90,13 +90,14 @@ describe Chef::ProviderResolver do
end
def self.expect_providers(**providers)
- providers.each do |name, expected_provider|
+ providers.each do |name, expected|
describe name.to_s do
let(:resource_name) { name }
tags = []
+ expected_provider = nil
expected_resource = nil
- Array(expected_provider).each do |p|
+ Array(expected).each do |p|
if p.is_a?(Class) && p <= Chef::Provider
expected_provider = p
elsif p.is_a?(Class) && p <= Chef::Resource
@@ -525,8 +526,8 @@ describe Chef::ProviderResolver do
# We want to check that these are unsupported:
apt_package: nil,
bff_package: nil,
- dsc_script: nil,
dpkg_package: nil,
+ dsc_script: nil,
ips_package: nil,
pacman_package: nil,
paludis_package: nil,
diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb
index 1377950c99..b9ba80068b 100644
--- a/spec/unit/resource_spec.rb
+++ b/spec/unit/resource_spec.rb
@@ -810,21 +810,21 @@ describe Chef::Resource do
end
it 'adds mappings for a single platform' do
- expect(Chef.resource_priority_map).to receive(:set).with(
+ expect(Chef.resource_handler_map).to receive(:set).with(
:dinobot, Chef::Resource::Klz, { platform: ['autobots'] }
)
klz.provides :dinobot, platform: ['autobots']
end
it 'adds mappings for multiple platforms' do
- expect(Chef.resource_priority_map).to receive(:set).with(
+ expect(Chef.resource_handler_map).to receive(:set).with(
:energy, Chef::Resource::Klz, { platform: ['autobots', 'decepticons']}
)
klz.provides :energy, platform: ['autobots', 'decepticons']
end
it 'adds mappings for all platforms' do
- expect(Chef.resource_priority_map).to receive(:set).with(
+ expect(Chef.resource_handler_map).to receive(:set).with(
:tape_deck, Chef::Resource::Klz, {}
)
klz.provides :tape_deck