diff options
author | John Keiser <john@johnkeiser.com> | 2015-12-02 18:07:51 -0800 |
---|---|---|
committer | John Keiser <john@johnkeiser.com> | 2015-12-02 18:07:51 -0800 |
commit | 2a610564a8a42208adf2158a7c5c0657b243d58a (patch) | |
tree | 3d8c709dc70407f1aadd98b10060b79626b72976 | |
parent | 3d7440aae2f78f99d63ed4a24b5b1f3c5b1da8a8 (diff) | |
parent | 0c5ef9442d6fe8be5a9d0eb5d50ace124adeffd5 (diff) | |
download | chef-2a610564a8a42208adf2158a7c5c0657b243d58a.tar.gz |
Merge branch 'jk/4127'
-rw-r--r-- | lib/chef/resource.rb | 11 | ||||
-rw-r--r-- | spec/unit/resource_spec.rb | 521 |
2 files changed, 276 insertions, 256 deletions
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index 90453bd00e..3edcc24e17 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -664,13 +664,18 @@ class Chef end def to_hash + # Grab all current state, then any other ivars (backcompat) + result = {} + self.class.state_properties.each do |p| + result[p.name] = p.get(self) + end safe_ivars = instance_variables.map { |ivar| ivar.to_sym } - FORBIDDEN_IVARS - instance_vars = Hash.new safe_ivars.each do |iv| key = iv.to_s.sub(/^@/,'').to_sym - instance_vars[key] = instance_variable_get(iv) + next if result.has_key?(key) + result[key] = instance_variable_get(iv) end - instance_vars + result end def self.json_create(o) diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index b9ba80068b..59951941d7 100644 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -22,25 +22,24 @@ require 'spec_helper' describe Chef::Resource do - before(:each) do - @cookbook_repo_path = File.join(CHEF_SPEC_DATA, 'cookbooks') - @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(@cookbook_repo_path)) - @node = Chef::Node.new - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, @cookbook_collection, @events) - @resource = Chef::Resource.new("funk", @run_context) - end + let(:cookbook_repo_path) { File.join(CHEF_SPEC_DATA, 'cookbooks') } + let(:cookbook_collection) { Chef::CookbookCollection.new(Chef::CookbookLoader.new(cookbook_repo_path)) } + let(:node) { Chef::Node.new } + let(:events) { Chef::EventDispatch::Dispatcher.new } + let(:run_context) { Chef::RunContext.new(node, cookbook_collection, events) } + let(:resource) { resource_class.new("funk", run_context) } + let(:resource_class) { Chef::Resource } it "should mixin shell_out" do - expect(@resource.respond_to?(:shell_out)).to be true + expect(resource.respond_to?(:shell_out)).to be true end it "should mixin shell_out!" do - expect(@resource.respond_to?(:shell_out!)).to be true + expect(resource.respond_to?(:shell_out!)).to be true end it "should mixin shell_out_with_systems_locale" do - expect(@resource.respond_to?(:shell_out_with_systems_locale)).to be true + expect(resource.respond_to?(:shell_out_with_systems_locale)).to be true end describe "when inherited" do @@ -86,30 +85,29 @@ describe Chef::Resource do end describe "when no identity attribute has been declared" do - before do - @resource_sans_id = Chef::Resource.new("my-name") - end + let(:resource_sans_id) { Chef::Resource.new("my-name") } # Would rather force identity attributes to be set for everything, # but that's not plausible for back compat reasons. it "uses the name as the identity" do - expect(@resource_sans_id.identity).to eq("my-name") + expect(resource_sans_id.identity).to eq("my-name") end end describe "when an identity attribute has been declared" do - before do - @file_resource_class = Class.new(Chef::Resource) do + let(:file_resource) { + file_resource_class = Class.new(Chef::Resource) do identity_attr :path attr_accessor :path end - @file_resource = @file_resource_class.new("identity-attr-test") - @file_resource.path = "/tmp/foo.txt" - end + file_resource = file_resource_class.new("identity-attr-test") + file_resource.path = "/tmp/foo.txt" + file_resource + } it "gives the value of its identity attribute" do - expect(@file_resource.identity).to eq("/tmp/foo.txt") + expect(file_resource.identity).to eq("/tmp/foo.txt") end end @@ -142,8 +140,8 @@ describe Chef::Resource do end describe "when a set of state attributes has been declared" do - before do - @file_resource_class = Class.new(Chef::Resource) do + let(:file_resource) { + file_resource_class = Class.new(Chef::Resource) do state_attrs :checksum, :owner, :group, :mode @@ -153,15 +151,16 @@ describe Chef::Resource do attr_accessor :mode end - @file_resource = @file_resource_class.new("describe-state-test") - @file_resource.checksum = "abc123" - @file_resource.owner = "root" - @file_resource.group = "wheel" - @file_resource.mode = "0644" - end + file_resource = file_resource_class.new("describe-state-test") + file_resource.checksum = "abc123" + file_resource.owner = "root" + file_resource.group = "wheel" + file_resource.mode = "0644" + file_resource + } it "describes its state" do - resource_state = @file_resource.state + resource_state = file_resource.state expect(resource_state.keys).to match_array([:checksum, :owner, :group, :mode]) expect(resource_state[:checksum]).to eq("abc123") expect(resource_state[:owner]).to eq("root") @@ -171,157 +170,160 @@ describe Chef::Resource do end describe "load_from" do + let(:prior_resource) { + prior_resource = Chef::Resource.new("funk") + prior_resource.supports(:funky => true) + prior_resource.source_line + prior_resource.allowed_actions << :funkytown + prior_resource.action(:funkytown) + prior_resource + } before(:each) do - @prior_resource = Chef::Resource.new("funk") - @prior_resource.supports(:funky => true) - @prior_resource.source_line - @prior_resource.allowed_actions << :funkytown - @prior_resource.action(:funkytown) - @resource.allowed_actions << :funkytown - @run_context.resource_collection << @prior_resource + resource.allowed_actions << :funkytown + run_context.resource_collection << prior_resource end it "should load the attributes of a prior resource" do - @resource.load_from(@prior_resource) - expect(@resource.supports).to eq({ :funky => true }) + resource.load_from(prior_resource) + expect(resource.supports).to eq({ :funky => true }) end it "should not inherit the action from the prior resource" do - @resource.load_from(@prior_resource) - expect(@resource.action).not_to eq(@prior_resource.action) + resource.load_from(prior_resource) + expect(resource.action).not_to eq(prior_resource.action) end end describe "name" do it "should have a name" do - expect(@resource.name).to eql("funk") + expect(resource.name).to eql("funk") end it "should let you set a new name" do - @resource.name "monkey" - expect(@resource.name).to eql("monkey") + resource.name "monkey" + expect(resource.name).to eql("monkey") end it "coerces arrays to names" do - expect(@resource.name ['a', 'b']).to eql('a, b') + expect(resource.name ['a', 'b']).to eql('a, b') end it "should coerce objects to a string" do - expect(@resource.name Object.new).to be_a(String) + expect(resource.name Object.new).to be_a(String) end end describe "noop" do it "should accept true or false for noop" do - expect { @resource.noop true }.not_to raise_error - expect { @resource.noop false }.not_to raise_error - expect { @resource.noop "eat it" }.to raise_error(ArgumentError) + expect { resource.noop true }.not_to raise_error + expect { resource.noop false }.not_to raise_error + expect { resource.noop "eat it" }.to raise_error(ArgumentError) end end describe "notifies" do it "should make notified resources appear in the actions hash" do - @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") - @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "coffee") - expect(@resource.delayed_notifications.detect{|e| e.resource.name == "coffee" && e.action == :reload}).not_to be_nil + run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") + resource.notifies :reload, run_context.resource_collection.find(:zen_master => "coffee") + expect(resource.delayed_notifications.detect{|e| e.resource.name == "coffee" && e.action == :reload}).not_to be_nil end it "should make notified resources be capable of acting immediately" do - @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") - @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "coffee"), :immediate - expect(@resource.immediate_notifications.detect{|e| e.resource.name == "coffee" && e.action == :reload}).not_to be_nil + run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") + resource.notifies :reload, run_context.resource_collection.find(:zen_master => "coffee"), :immediate + expect(resource.immediate_notifications.detect{|e| e.resource.name == "coffee" && e.action == :reload}).not_to be_nil end it "should raise an exception if told to act in other than :delay or :immediate(ly)" do - @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") + run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") expect { - @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "coffee"), :someday + resource.notifies :reload, run_context.resource_collection.find(:zen_master => "coffee"), :someday }.to raise_error(ArgumentError) end it "should allow multiple notified resources appear in the actions hash" do - @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") - @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "coffee") - expect(@resource.delayed_notifications.detect{|e| e.resource.name == "coffee" && e.action == :reload}).not_to be_nil + run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") + resource.notifies :reload, run_context.resource_collection.find(:zen_master => "coffee") + expect(resource.delayed_notifications.detect{|e| e.resource.name == "coffee" && e.action == :reload}).not_to be_nil - @run_context.resource_collection << Chef::Resource::ZenMaster.new("beans") - @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "beans") - expect(@resource.delayed_notifications.detect{|e| e.resource.name == "beans" && e.action == :reload}).not_to be_nil + run_context.resource_collection << Chef::Resource::ZenMaster.new("beans") + resource.notifies :reload, run_context.resource_collection.find(:zen_master => "beans") + expect(resource.delayed_notifications.detect{|e| e.resource.name == "beans" && e.action == :reload}).not_to be_nil end it "creates a notification for a resource that is not yet in the resource collection" do - @resource.notifies(:restart, :service => 'apache') - expected_notification = Chef::Resource::Notification.new({:service => "apache"}, :restart, @resource) - expect(@resource.delayed_notifications).to include(expected_notification) + resource.notifies(:restart, :service => 'apache') + expected_notification = Chef::Resource::Notification.new({:service => "apache"}, :restart, resource) + expect(resource.delayed_notifications).to include(expected_notification) end it "notifies another resource immediately" do - @resource.notifies_immediately(:restart, :service => 'apache') - expected_notification = Chef::Resource::Notification.new({:service => "apache"}, :restart, @resource) - expect(@resource.immediate_notifications).to include(expected_notification) + resource.notifies_immediately(:restart, :service => 'apache') + expected_notification = Chef::Resource::Notification.new({:service => "apache"}, :restart, resource) + expect(resource.immediate_notifications).to include(expected_notification) end it "notifies a resource to take action at the end of the chef run" do - @resource.notifies_delayed(:restart, :service => "apache") - expected_notification = Chef::Resource::Notification.new({:service => "apache"}, :restart, @resource) - expect(@resource.delayed_notifications).to include(expected_notification) + resource.notifies_delayed(:restart, :service => "apache") + expected_notification = Chef::Resource::Notification.new({:service => "apache"}, :restart, resource) + expect(resource.delayed_notifications).to include(expected_notification) end it "notifies a resource with an array for its name via its prettified string name" do - @run_context.resource_collection << Chef::Resource::ZenMaster.new(["coffee", "tea"]) - @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "coffee, tea") - expect(@resource.delayed_notifications.detect{|e| e.resource.name == "coffee, tea" && e.action == :reload}).not_to be_nil + run_context.resource_collection << Chef::Resource::ZenMaster.new(["coffee", "tea"]) + resource.notifies :reload, run_context.resource_collection.find(:zen_master => "coffee, tea") + expect(resource.delayed_notifications.detect{|e| e.resource.name == "coffee, tea" && e.action == :reload}).not_to be_nil end end describe "subscribes" do it "should make resources appear in the actions hash of subscribed nodes" do - @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") - zr = @run_context.resource_collection.find(:zen_master => "coffee") - @resource.subscribes :reload, zr + run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") + zr = run_context.resource_collection.find(:zen_master => "coffee") + resource.subscribes :reload, zr expect(zr.delayed_notifications.detect{|e| e.resource.name == "funk" && e.action == :reload}).not_to be_nil end it "should make resources appear in the actions hash of subscribed nodes" do - @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") - zr = @run_context.resource_collection.find(:zen_master => "coffee") - @resource.subscribes :reload, zr - expect(zr.delayed_notifications.detect{|e| e.resource.name == @resource.name && e.action == :reload}).not_to be_nil + run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") + zr = run_context.resource_collection.find(:zen_master => "coffee") + resource.subscribes :reload, zr + expect(zr.delayed_notifications.detect{|e| e.resource.name == resource.name && e.action == :reload}).not_to be_nil - @run_context.resource_collection << Chef::Resource::ZenMaster.new("bean") - zrb = @run_context.resource_collection.find(:zen_master => "bean") + run_context.resource_collection << Chef::Resource::ZenMaster.new("bean") + zrb = run_context.resource_collection.find(:zen_master => "bean") zrb.subscribes :reload, zr - expect(zr.delayed_notifications.detect{|e| e.resource.name == @resource.name && e.action == :reload}).not_to be_nil + expect(zr.delayed_notifications.detect{|e| e.resource.name == resource.name && e.action == :reload}).not_to be_nil end it "should make subscribed resources be capable of acting immediately" do - @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") - zr = @run_context.resource_collection.find(:zen_master => "coffee") - @resource.subscribes :reload, zr, :immediately - expect(zr.immediate_notifications.detect{|e| e.resource.name == @resource.name && e.action == :reload}).not_to be_nil + run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") + zr = run_context.resource_collection.find(:zen_master => "coffee") + resource.subscribes :reload, zr, :immediately + expect(zr.immediate_notifications.detect{|e| e.resource.name == resource.name && e.action == :reload}).not_to be_nil end end describe "defined_at" do it "should correctly parse source_line on unix-like operating systems" do - @resource.source_line = "/some/path/to/file.rb:80:in `wombat_tears'" - expect(@resource.defined_at).to eq("/some/path/to/file.rb line 80") + resource.source_line = "/some/path/to/file.rb:80:in `wombat_tears'" + expect(resource.defined_at).to eq("/some/path/to/file.rb line 80") end it "should correctly parse source_line on Windows" do - @resource.source_line = "C:/some/path/to/file.rb:80 in 1`wombat_tears'" - expect(@resource.defined_at).to eq("C:/some/path/to/file.rb line 80") + resource.source_line = "C:/some/path/to/file.rb:80 in 1`wombat_tears'" + expect(resource.defined_at).to eq("C:/some/path/to/file.rb line 80") end it "should include the cookbook and recipe when it knows it" do - @resource.source_line = "/some/path/to/file.rb:80:in `wombat_tears'" - @resource.recipe_name = "wombats" - @resource.cookbook_name = "animals" - expect(@resource.defined_at).to eq("animals::wombats line 80") + resource.source_line = "/some/path/to/file.rb:80:in `wombat_tears'" + resource.recipe_name = "wombats" + resource.cookbook_name = "animals" + expect(resource.defined_at).to eq("animals::wombats line 80") end it "should recognize dynamically defined resources" do - expect(@resource.defined_at).to eq("dynamically defined") + expect(resource.defined_at).to eq("dynamically defined") end end @@ -345,7 +347,7 @@ describe Chef::Resource do expect(r.declared_type).to eq :d end - it "and there are no provides lines, @resource_name is used" do + it "and there are no provides lines, resource_name is used" do c = Class.new(Chef::Resource) do def initialize(*args, &block) @resource_name = :blah @@ -419,26 +421,39 @@ describe Chef::Resource do end it "should allow arguments preceded by is to methods" do - @resource.noop(@resource.is(true)) - expect(@resource.noop).to eql(true) + resource.noop(resource.is(true)) + expect(resource.noop).to eql(true) end end describe "to_json" do it "should serialize to json" do - json = @resource.to_json + json = resource.to_json expect(json).to match(/json_class/) expect(json).to match(/instance_vars/) end include_examples "to_json equivalent to Chef::JSONCompat.to_json" do - let(:jsonable) { @resource } + let(:jsonable) { resource } end end describe "to_hash" do + context "when the resource has a property with a default" do + let(:resource_class) { Class.new(Chef::Resource) { property :a, default: 1 } } + it "should include the default in the hash" do + expect(resource.to_hash.keys.sort).to eq([:a, :allowed_actions, :params, :provider, :updated, + :updated_by_last_action, :before, :supports, + :noop, :ignore_failure, :name, :source_line, + :action, :retries, :retry_delay, :elapsed_time, + :default_guard_interpreter, :guard_interpreter, :sensitive].sort) + expect(resource.to_hash[:name]).to eq "funk" + expect(resource.to_hash[:a]).to eq 1 + end + end + it "should convert to a hash" do - hash = @resource.to_hash + hash = resource.to_hash expected_keys = [ :allowed_actions, :params, :provider, :updated, :updated_by_last_action, :before, :supports, :noop, :ignore_failure, :name, :source_line, @@ -452,80 +467,83 @@ describe Chef::Resource do describe "self.json_create" do it "should deserialize itself from json" do - json = Chef::JSONCompat.to_json(@resource) + json = Chef::JSONCompat.to_json(resource) serialized_node = Chef::JSONCompat.from_json(json) expect(serialized_node).to be_a_kind_of(Chef::Resource) - expect(serialized_node.name).to eql(@resource.name) + expect(serialized_node.name).to eql(resource.name) end end describe "supports" do it "should allow you to set what features this resource supports" do support_hash = { :one => :two } - @resource.supports(support_hash) - expect(@resource.supports).to eql(support_hash) + resource.supports(support_hash) + expect(resource.supports).to eql(support_hash) end it "should return the current value of supports" do - expect(@resource.supports).to eq({}) + expect(resource.supports).to eq({}) end end describe "ignore_failure" do it "should default to throwing an error if a provider fails for a resource" do - expect(@resource.ignore_failure).to eq(false) + expect(resource.ignore_failure).to eq(false) end it "should allow you to set whether a provider should throw exceptions with ignore_failure" do - @resource.ignore_failure(true) - expect(@resource.ignore_failure).to eq(true) + resource.ignore_failure(true) + expect(resource.ignore_failure).to eq(true) end it "should allow you to epic_fail" do - @resource.epic_fail(true) - expect(@resource.epic_fail).to eq(true) + resource.epic_fail(true) + expect(resource.epic_fail).to eq(true) end end describe "retries" do - before do - @retriable_resource = Chef::Resource::Cat.new("precious", @run_context) - @retriable_resource.provider = Chef::Provider::SnakeOil - @retriable_resource.action = :purr + let(:retriable_resource) { + retriable_resource = Chef::Resource::Cat.new("precious", run_context) + retriable_resource.provider = Chef::Provider::SnakeOil + retriable_resource.action = :purr + retriable_resource + } - @node.automatic_attrs[:platform] = "fubuntu" - @node.automatic_attrs[:platform_version] = '10.04' + before do + node.automatic_attrs[:platform] = "fubuntu" + node.automatic_attrs[:platform_version] = '10.04' end it "should default to not retrying if a provider fails for a resource" do - expect(@retriable_resource.retries).to eq(0) + expect(retriable_resource.retries).to eq(0) end it "should allow you to set how many retries a provider should attempt after a failure" do - @retriable_resource.retries(2) - expect(@retriable_resource.retries).to eq(2) + retriable_resource.retries(2) + expect(retriable_resource.retries).to eq(2) end it "should default to a retry delay of 2 seconds" do - expect(@retriable_resource.retry_delay).to eq(2) + expect(retriable_resource.retry_delay).to eq(2) end it "should allow you to set the retry delay" do - @retriable_resource.retry_delay(10) - expect(@retriable_resource.retry_delay).to eq(10) + retriable_resource.retry_delay(10) + expect(retriable_resource.retry_delay).to eq(10) end it "should keep given value of retries intact after the provider fails for a resource" do - @retriable_resource.retries(3) - @retriable_resource.retry_delay(0) # No need to wait. + retriable_resource.retries(3) + retriable_resource.retry_delay(0) # No need to wait. - provider = Chef::Provider::SnakeOil.new(@retriable_resource, @run_context) + provider = Chef::Provider::SnakeOil.new(retriable_resource, run_context) allow(Chef::Provider::SnakeOil).to receive(:new).and_return(provider) allow(provider).to receive(:action_purr).and_raise - expect(@retriable_resource).to receive(:sleep).exactly(3).times - expect { @retriable_resource.run_action(:purr) }.to raise_error - expect(@retriable_resource.retries).to eq(3) + expect(retriable_resource).to receive(:sleep).exactly(3).times + expect { retriable_resource.run_action(:purr) }.to raise_error + expect(retriable_resource.retries).to eq(3) end end @@ -560,28 +578,28 @@ describe Chef::Resource do describe "when updated by a provider" do before do - @resource.updated_by_last_action(true) + resource.updated_by_last_action(true) end it "records that it was updated" do - expect(@resource).to be_updated + expect(resource).to be_updated end it "records that the last action updated the resource" do - expect(@resource).to be_updated_by_last_action + expect(resource).to be_updated_by_last_action end describe "and then run again without being updated" do before do - @resource.updated_by_last_action(false) + resource.updated_by_last_action(false) end it "reports that it is updated" do - expect(@resource).to be_updated + expect(resource).to be_updated end it "reports that it was not updated by the last action" do - expect(@resource).not_to be_updated_by_last_action + expect(resource).not_to be_updated_by_last_action end end @@ -589,72 +607,75 @@ describe Chef::Resource do end describe "when invoking its action" do + let(:resource) { + resource = Chef::Resource.new("provided", run_context) + resource.provider = Chef::Provider::SnakeOil + resource + } before do - @resource = Chef::Resource.new("provided", @run_context) - @resource.provider = Chef::Provider::SnakeOil - @node.automatic_attrs[:platform] = "fubuntu" - @node.automatic_attrs[:platform_version] = '10.04' + node.automatic_attrs[:platform] = "fubuntu" + node.automatic_attrs[:platform_version] = '10.04' end it "does not run only_if if no only_if command is given" do expect_any_instance_of(Chef::Resource::Conditional).not_to receive(:evaluate) - @resource.only_if.clear - @resource.run_action(:purr) + resource.only_if.clear + resource.run_action(:purr) end it "runs runs an only_if when one is given" do snitch_variable = nil - @resource.only_if { snitch_variable = true } - expect(@resource.only_if.first.positivity).to eq(:only_if) + resource.only_if { snitch_variable = true } + expect(resource.only_if.first.positivity).to eq(:only_if) #Chef::Mixin::Command.should_receive(:only_if).with(true, {}).and_return(false) - @resource.run_action(:purr) + resource.run_action(:purr) expect(snitch_variable).to be_truthy end it "runs multiple only_if conditionals" do snitch_var1, snitch_var2 = nil, nil - @resource.only_if { snitch_var1 = 1 } - @resource.only_if { snitch_var2 = 2 } - @resource.run_action(:purr) + resource.only_if { snitch_var1 = 1 } + resource.only_if { snitch_var2 = 2 } + resource.run_action(:purr) expect(snitch_var1).to eq(1) expect(snitch_var2).to eq(2) end it "accepts command options for only_if conditionals" do expect_any_instance_of(Chef::Resource::Conditional).to receive(:evaluate_command).at_least(1).times - @resource.only_if("true", :cwd => '/tmp') - expect(@resource.only_if.first.command_opts).to eq({:cwd => '/tmp'}) - @resource.run_action(:purr) + resource.only_if("true", :cwd => '/tmp') + expect(resource.only_if.first.command_opts).to eq({:cwd => '/tmp'}) + resource.run_action(:purr) end it "runs not_if as a command when it is a string" do expect_any_instance_of(Chef::Resource::Conditional).to receive(:evaluate_command).at_least(1).times - @resource.not_if "pwd" - @resource.run_action(:purr) + resource.not_if "pwd" + resource.run_action(:purr) end it "runs not_if as a block when it is a ruby block" do expect_any_instance_of(Chef::Resource::Conditional).to receive(:evaluate_block).at_least(1).times - @resource.not_if { puts 'foo' } - @resource.run_action(:purr) + resource.not_if { puts 'foo' } + resource.run_action(:purr) end it "does not run not_if if no not_if command is given" do expect_any_instance_of(Chef::Resource::Conditional).not_to receive(:evaluate) - @resource.not_if.clear - @resource.run_action(:purr) + resource.not_if.clear + resource.run_action(:purr) end it "accepts command options for not_if conditionals" do - @resource.not_if("pwd" , :cwd => '/tmp') - expect(@resource.not_if.first.command_opts).to eq({:cwd => '/tmp'}) + resource.not_if("pwd" , :cwd => '/tmp') + expect(resource.not_if.first.command_opts).to eq({:cwd => '/tmp'}) end it "accepts multiple not_if conditionals" do snitch_var1, snitch_var2 = true, true - @resource.not_if {snitch_var1 = nil} - @resource.not_if {snitch_var2 = false} - @resource.run_action(:purr) + resource.not_if {snitch_var1 = nil} + resource.not_if {snitch_var2 = false} + resource.run_action(:purr) expect(snitch_var1).to be_nil expect(snitch_var2).to be_falsey end @@ -662,13 +683,11 @@ describe Chef::Resource do it "reports 0 elapsed time if actual elapsed time is < 0" do expected = Time.now allow(Time).to receive(:now).and_return(expected, expected - 1) - @resource.run_action(:purr) - expect(@resource.elapsed_time).to eq(0) + resource.run_action(:purr) + expect(resource.elapsed_time).to eq(0) end describe "guard_interpreter attribute" do - let(:resource) { @resource } - it "should be set to :default by default" do expect(resource.guard_interpreter).to eq(:default) end @@ -691,106 +710,108 @@ describe Chef::Resource do describe "should_skip?" do before do - @resource = Chef::Resource::Cat.new("sugar", @run_context) + resource = Chef::Resource::Cat.new("sugar", run_context) end it "should return false by default" do - expect(@resource.should_skip?(:purr)).to be_falsey + expect(resource.should_skip?(:purr)).to be_falsey end it "should return false when only_if is met" do - @resource.only_if { true } - expect(@resource.should_skip?(:purr)).to be_falsey + resource.only_if { true } + expect(resource.should_skip?(:purr)).to be_falsey end it "should return true when only_if is not met" do - @resource.only_if { false } - expect(@resource.should_skip?(:purr)).to be_truthy + resource.only_if { false } + expect(resource.should_skip?(:purr)).to be_truthy end it "should return true when not_if is met" do - @resource.not_if { true } - expect(@resource.should_skip?(:purr)).to be_truthy + resource.not_if { true } + expect(resource.should_skip?(:purr)).to be_truthy end it "should return false when not_if is not met" do - @resource.not_if { false } - expect(@resource.should_skip?(:purr)).to be_falsey + resource.not_if { false } + expect(resource.should_skip?(:purr)).to be_falsey end it "should return true when only_if is met but also not_if is met" do - @resource.only_if { true } - @resource.not_if { true } - expect(@resource.should_skip?(:purr)).to be_truthy + resource.only_if { true } + resource.not_if { true } + expect(resource.should_skip?(:purr)).to be_truthy end it "should return true when one of multiple only_if's is not met" do - @resource.only_if { true } - @resource.only_if { false } - @resource.only_if { true } - expect(@resource.should_skip?(:purr)).to be_truthy + resource.only_if { true } + resource.only_if { false } + resource.only_if { true } + expect(resource.should_skip?(:purr)).to be_truthy end it "should return true when one of multiple not_if's is met" do - @resource.not_if { false } - @resource.not_if { true } - @resource.not_if { false } - expect(@resource.should_skip?(:purr)).to be_truthy + resource.not_if { false } + resource.not_if { true } + resource.not_if { false } + expect(resource.should_skip?(:purr)).to be_truthy end it "should return true when action is :nothing" do - expect(@resource.should_skip?(:nothing)).to be_truthy + expect(resource.should_skip?(:nothing)).to be_truthy end it "should return true when action is :nothing ignoring only_if/not_if conditionals" do - @resource.only_if { true } - @resource.not_if { false } - expect(@resource.should_skip?(:nothing)).to be_truthy + resource.only_if { true } + resource.not_if { false } + expect(resource.should_skip?(:nothing)).to be_truthy end it "should print \"skipped due to action :nothing\" message for doc formatter when action is :nothing" do fdoc = Chef::Formatters.new(:doc, STDOUT, STDERR) - allow(@run_context).to receive(:events).and_return(fdoc) + allow(run_context).to receive(:events).and_return(fdoc) expect(fdoc).to receive(:puts).with(" (skipped due to action :nothing)", anything()) - @resource.should_skip?(:nothing) + resource.should_skip?(:nothing) end end describe "when resource action is :nothing" do + let(:resource1) { + resource1 = Chef::Resource::Cat.new("sugar", run_context) + resource1.action = :nothing + resource1 + } before do - @resource1 = Chef::Resource::Cat.new("sugar", @run_context) - @resource1.action = :nothing - - @node.automatic_attrs[:platform] = "fubuntu" - @node.automatic_attrs[:platform_version] = '10.04' + node.automatic_attrs[:platform] = "fubuntu" + node.automatic_attrs[:platform_version] = '10.04' end it "should not run only_if/not_if conditionals (CHEF-972)" do snitch_var1 = 0 - @resource1.only_if { snitch_var1 = 1 } - @resource1.not_if { snitch_var1 = 2 } - @resource1.run_action(:nothing) + resource1.only_if { snitch_var1 = 1 } + resource1.not_if { snitch_var1 = 2 } + resource1.run_action(:nothing) expect(snitch_var1).to eq(0) end it "should run only_if/not_if conditionals when notified to run another action (CHEF-972)" do snitch_var1 = snitch_var2 = 0 - @runner = Chef::Runner.new(@run_context) + runner = Chef::Runner.new(run_context) Chef::Platform.set( :resource => :cat, :provider => Chef::Provider::SnakeOil ) - @resource1.only_if { snitch_var1 = 1 } - @resource1.not_if { snitch_var2 = 2 } - @resource2 = Chef::Resource::Cat.new("coffee", @run_context) - @resource2.notifies :purr, @resource1 - @resource2.action = :purr + resource1.only_if { snitch_var1 = 1 } + resource1.not_if { snitch_var2 = 2 } + resource2 = Chef::Resource::Cat.new("coffee", run_context) + resource2.notifies :purr, resource1 + resource2.action = :purr - @run_context.resource_collection << @resource1 - @run_context.resource_collection << @resource2 - @runner.converge + run_context.resource_collection << resource1 + run_context.resource_collection << resource2 + runner.converge expect(snitch_var1).to eq(1) expect(snitch_var2).to eq(2) @@ -838,10 +859,10 @@ describe Chef::Resource do before(:each) do Chef::Resource::Klz1 = klz1 - @node = Chef::Node.new - @node.name("bumblebee") - @node.automatic[:platform] = "autobots" - @node.automatic[:platform_version] = "6.1" + 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 @@ -852,7 +873,7 @@ describe Chef::Resource do end it "returns a resource by short_name if nothing else matches" do - expect(Chef::Resource.resource_for_node(:soundwave, @node)).to eql(klz1) + expect(Chef::Resource.resource_for_node(:soundwave, node)).to eql(klz1) end end @@ -861,10 +882,9 @@ describe Chef::Resource do before(:each) do Chef::Resource::Klz2 = klz2 - @node = Chef::Node.new - @node.name("bumblebee") - @node.automatic[:platform] = "autobots" - @node.automatic[:platform_version] = "6.1" + node.name("bumblebee") + node.automatic[:platform] = "autobots" + node.automatic[:platform_version] = "6.1" klz2.provides :dinobot, :platform => ['autobots'] Object.const_set('Grimlock', klz2) klz2.provides :grimlock @@ -876,7 +896,7 @@ describe Chef::Resource do end it "returns a resource by short_name and node" do - expect(Chef::Resource.resource_for_node(:dinobot, @node)).to eql(klz2) + expect(Chef::Resource.resource_for_node(:dinobot, node)).to eql(klz2) end end @@ -887,69 +907,64 @@ describe Chef::Resource do describe "with a string resource spec" do it "creates a delayed notification when timing is not specified" do - @resource.notifies(:run, "execute[foo]") - expect(@run_context.delayed_notification_collection.size).to eq(1) + resource.notifies(:run, "execute[foo]") + expect(run_context.delayed_notification_collection.size).to eq(1) end it "creates a delayed notification when :delayed is not specified" do - @resource.notifies(:run, "execute[foo]", :delayed) - expect(@run_context.delayed_notification_collection.size).to eq(1) + resource.notifies(:run, "execute[foo]", :delayed) + expect(run_context.delayed_notification_collection.size).to eq(1) end it "creates an immediate notification when :immediate is specified" do - @resource.notifies(:run, "execute[foo]", :immediate) - expect(@run_context.immediate_notification_collection.size).to eq(1) + resource.notifies(:run, "execute[foo]", :immediate) + expect(run_context.immediate_notification_collection.size).to eq(1) end it "creates an immediate notification when :immediately is specified" do - @resource.notifies(:run, "execute[foo]", :immediately) - expect(@run_context.immediate_notification_collection.size).to eq(1) + resource.notifies(:run, "execute[foo]", :immediately) + expect(run_context.immediate_notification_collection.size).to eq(1) end describe "with a syntax error in the resource spec" do it "raises an exception immmediately" do expect do - @resource.notifies(:run, "typo[missing-closing-bracket") + resource.notifies(:run, "typo[missing-closing-bracket") end.to raise_error(Chef::Exceptions::InvalidResourceSpecification) end end end describe "with a resource reference" do - before do - @notified_resource = Chef::Resource.new("punk", @run_context) - end + let(:notified_resource) { Chef::Resource.new("punk", run_context) } it "creates a delayed notification when timing is not specified" do - @resource.notifies(:run, @notified_resource) - expect(@run_context.delayed_notification_collection.size).to eq(1) + resource.notifies(:run, notified_resource) + expect(run_context.delayed_notification_collection.size).to eq(1) end it "creates a delayed notification when :delayed is not specified" do - @resource.notifies(:run, @notified_resource, :delayed) - expect(@run_context.delayed_notification_collection.size).to eq(1) + resource.notifies(:run, notified_resource, :delayed) + expect(run_context.delayed_notification_collection.size).to eq(1) end it "creates an immediate notification when :immediate is specified" do - @resource.notifies(:run, @notified_resource, :immediate) - expect(@run_context.immediate_notification_collection.size).to eq(1) + resource.notifies(:run, notified_resource, :immediate) + expect(run_context.immediate_notification_collection.size).to eq(1) end it "creates an immediate notification when :immediately is specified" do - @resource.notifies(:run, @notified_resource, :immediately) - expect(@run_context.immediate_notification_collection.size).to eq(1) + resource.notifies(:run, notified_resource, :immediately) + expect(run_context.immediate_notification_collection.size).to eq(1) end end end describe "resource sensitive attribute" do - - before(:each) do - @resource_file = Chef::Resource::File.new("/nonexistent/CHEF-5098/file", @run_context) - @action = :create - end + let(:resource_file) { Chef::Resource::File.new("/nonexistent/CHEF-5098/file", run_context) } + let(:action) { :create } def compiled_resource_data(resource, action, err) error_inspector = Chef::Formatters::ErrorInspectors::ResourceFailureInspector.new(resource, action, err) @@ -960,19 +975,19 @@ describe Chef::Resource do end it "set to false by default" do - expect(@resource.sensitive).to be_falsey + expect(resource.sensitive).to be_falsey end it "when set to false should show compiled resource for failed resource" do - expect { @resource_file.run_action(@action) }.to raise_error { |err| - expect(compiled_resource_data(@resource_file, @action, err)).to match 'path "/nonexistent/CHEF-5098/file"' + expect { resource_file.run_action(action) }.to raise_error { |err| + expect(compiled_resource_data(resource_file, action, err)).to match 'path "/nonexistent/CHEF-5098/file"' } end it "when set to true should show compiled resource for failed resource" do - @resource_file.sensitive true - expect { @resource_file.run_action(@action) }.to raise_error { |err| - expect(compiled_resource_data(@resource_file, @action, err)).to eql("suppressed sensitive resource output") + resource_file.sensitive true + expect { resource_file.run_action(action) }.to raise_error { |err| + expect(compiled_resource_data(resource_file, action, err)).to eql("suppressed sensitive resource output") } end |