diff options
Diffstat (limited to 'spec/unit/resource_spec.rb')
-rw-r--r-- | spec/unit/resource_spec.rb | 975 |
1 files changed, 0 insertions, 975 deletions
diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb deleted file mode 100644 index e85633eaab..0000000000 --- a/spec/unit/resource_spec.rb +++ /dev/null @@ -1,975 +0,0 @@ -# -# Author:: Adam Jacob (<adam@opscode.com>) -# Author:: Christopher Walters (<cw@opscode.com>) -# Author:: Tim Hinderliter (<tim@opscode.com>) -# Author:: Seth Chisamore (<schisamo@opscode.com>) -# Copyright:: Copyright (c) 2008-2011 Opscode, Inc. -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require 'spec_helper' - -class ResourceTestHarness < Chef::Resource - provider_base Chef::Provider::Package -end - -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 - - describe "when inherited" do - - it "adds an entry to a list of subclasses" do - subclass = Class.new(Chef::Resource) - Chef::Resource.resource_classes.should include(subclass) - end - - it "keeps track of subclasses of subclasses" do - subclass = Class.new(Chef::Resource) - subclass_of_subclass = Class.new(subclass) - Chef::Resource.resource_classes.should include(subclass_of_subclass) - end - - end - - describe "when declaring the identity attribute" do - it "has no identity attribute by default" do - Chef::Resource.identity_attr.should be_nil - end - - it "sets an identity attribute" do - resource_class = Class.new(Chef::Resource) - resource_class.identity_attr(:path) - resource_class.identity_attr.should == :path - end - - it "inherits an identity attribute from a superclass" do - resource_class = Class.new(Chef::Resource) - resource_subclass = Class.new(resource_class) - resource_class.identity_attr(:package_name) - resource_subclass.identity_attr.should == :package_name - end - - it "overrides the identity attribute from a superclass when the identity attr is set" do - resource_class = Class.new(Chef::Resource) - resource_subclass = Class.new(resource_class) - resource_class.identity_attr(:package_name) - resource_subclass.identity_attr(:something_else) - resource_subclass.identity_attr.should == :something_else - end - end - - describe "when no identity attribute has been declared" do - before do - @resource_sans_id = Chef::Resource.new("my-name") - end - - # 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 - @resource_sans_id.identity.should == "my-name" - end - end - - describe "when an identity attribute has been declared" do - before do - @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 - - it "gives the value of its identity attribute" do - @file_resource.identity.should == "/tmp/foo.txt" - end - end - - describe "when declaring state attributes" do - it "has no state_attrs by default" do - Chef::Resource.state_attrs.should be_empty - end - - it "sets a list of state attributes" do - resource_class = Class.new(Chef::Resource) - resource_class.state_attrs(:checksum, :owner, :group, :mode) - resource_class.state_attrs.should =~ [:checksum, :owner, :group, :mode] - end - - it "inherits state attributes from the superclass" do - resource_class = Class.new(Chef::Resource) - resource_subclass = Class.new(resource_class) - resource_class.state_attrs(:checksum, :owner, :group, :mode) - resource_subclass.state_attrs.should =~ [:checksum, :owner, :group, :mode] - end - - it "combines inherited state attributes with non-inherited state attributes" do - resource_class = Class.new(Chef::Resource) - resource_subclass = Class.new(resource_class) - resource_class.state_attrs(:checksum, :owner) - resource_subclass.state_attrs(:group, :mode) - resource_subclass.state_attrs.should =~ [:checksum, :owner, :group, :mode] - end - - end - - describe "when a set of state attributes has been declared" do - before do - @file_resource_class = Class.new(Chef::Resource) do - - state_attrs :checksum, :owner, :group, :mode - - attr_accessor :checksum - attr_accessor :owner - attr_accessor :group - 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 - - it "describes its state" do - resource_state = @file_resource.state - resource_state.keys.should =~ [:checksum, :owner, :group, :mode] - resource_state[:checksum].should == "abc123" - resource_state[:owner].should == "root" - resource_state[:group].should == "wheel" - resource_state[:mode].should == "0644" - end - end - - describe "load_prior_resource" do - 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 - end - - it "should load the attributes of a prior resource" do - @resource.load_prior_resource - @resource.supports.should == { :funky => true } - end - - it "should not inherit the action from the prior resource" do - @resource.load_prior_resource - @resource.action.should_not == @prior_resource.action - end - end - - describe "name" do - it "should have a name" do - @resource.name.should eql("funk") - end - - it "should let you set a new name" do - @resource.name "monkey" - @resource.name.should eql("monkey") - end - - it "should not be valid without a name" do - lambda { @resource.name false }.should raise_error(ArgumentError) - end - - it "should always have a string for name" do - lambda { @resource.name Hash.new }.should raise_error(ArgumentError) - end - end - - describe "noop" do - it "should accept true or false for noop" do - lambda { @resource.noop true }.should_not raise_error - lambda { @resource.noop false }.should_not raise_error - lambda { @resource.noop "eat it" }.should 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") - @resource.delayed_notifications.detect{|e| e.resource.name == "coffee" && e.action == :reload}.should_not 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 - @resource.immediate_notifications.detect{|e| e.resource.name == "coffee" && e.action == :reload}.should_not 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") - lambda { - @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "coffee"), :someday - }.should 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") - @resource.delayed_notifications.detect{|e| e.resource.name == "coffee" && e.action == :reload}.should_not be_nil - - @run_context.resource_collection << Chef::Resource::ZenMaster.new("beans") - @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "beans") - @resource.delayed_notifications.detect{|e| e.resource.name == "beans" && e.action == :reload}.should_not 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) - @resource.delayed_notifications.should 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) - @resource.immediate_notifications.should 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) - @resource.delayed_notifications.should include(expected_notification) - 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 - zr.delayed_notifications.detect{|e| e.resource.name == "funk" && e.action == :reload}.should_not 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 - zr.delayed_notifications.detect{|e| e.resource.name == @resource.name && e.action == :reload}.should_not be_nil - - @run_context.resource_collection << Chef::Resource::ZenMaster.new("bean") - zrb = @run_context.resource_collection.find(:zen_master => "bean") - zrb.subscribes :reload, zr - zr.delayed_notifications.detect{|e| e.resource.name == @resource.name && e.action == :reload}.should_not 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 - zr.immediate_notifications.detect{|e| e.resource.name == @resource.name && e.action == :reload}.should_not 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'" - @resource.defined_at.should == "/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'" - @resource.defined_at.should == "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" - @resource.defined_at.should == "animals::wombats line 80" - end - - it "should recognize dynamically defined resources" do - @resource.defined_at.should == "dynamically defined" - end - end - - describe "to_s" do - it "should become a string like resource_name[name]" do - zm = Chef::Resource::ZenMaster.new("coffee") - zm.to_s.should eql("zen_master[coffee]") - end - end - - describe "is" do - it "should return the arguments passed with 'is'" do - zm = Chef::Resource::ZenMaster.new("coffee") - zm.is("one", "two", "three").should == %w|one two three| - end - - it "should allow arguments preceeded by is to methods" do - @resource.noop(@resource.is(true)) - @resource.noop.should eql(true) - end - end - - describe "to_json" do - it "should serialize to json" do - json = @resource.to_json - json.should =~ /json_class/ - json.should =~ /instance_vars/ - end - end - - describe "to_hash" do - it "should convert to a hash" do - hash = @resource.to_hash - expected_keys = [ :allowed_actions, :params, :provider, :updated, - :updated_by_last_action, :before, :supports, - :noop, :ignore_failure, :name, :source_line, - :action, :retries, :retry_delay, :elapsed_time, - :guard_interpreter, :sensitive ] - (hash.keys - expected_keys).should == [] - (expected_keys - hash.keys).should == [] - hash[:name].should eql("funk") - end - end - - describe "self.json_create" do - it "should deserialize itself from json" do - json = @resource.to_json - serialized_node = Chef::JSONCompat.from_json(json) - serialized_node.should be_a_kind_of(Chef::Resource) - serialized_node.name.should 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) - @resource.supports.should eql(support_hash) - end - - it "should return the current value of supports" do - @resource.supports.should == {} - end - end - - describe "ignore_failure" do - it "should default to throwing an error if a provider fails for a resource" do - @resource.ignore_failure.should == false - end - - it "should allow you to set whether a provider should throw exceptions with ignore_failure" do - @resource.ignore_failure(true) - @resource.ignore_failure.should == true - end - - it "should allow you to epic_fail" do - @resource.epic_fail(true) - @resource.epic_fail.should == true - end - end - - describe "retries" do - it "should default to not retrying if a provider fails for a resource" do - @resource.retries.should == 0 - end - - it "should allow you to set how many retries a provider should attempt after a failure" do - @resource.retries(2) - @resource.retries.should == 2 - end - - it "should default to a retry delay of 2 seconds" do - @resource.retry_delay.should == 2 - end - - it "should allow you to set the retry delay" do - @resource.retry_delay(10) - @resource.retry_delay.should == 10 - end - end - - describe "setting the base provider class for the resource" do - - it "defaults to Chef::Provider for the base class" do - Chef::Resource.provider_base.should == Chef::Provider - end - - it "allows the base provider to be overriden by a " do - ResourceTestHarness.provider_base.should == Chef::Provider::Package - end - - end - - it "runs an action by finding its provider, loading the current resource and then running the action" do - pending - end - - describe "when updated by a provider" do - before do - @resource.updated_by_last_action(true) - end - - it "records that it was updated" do - @resource.should be_updated - end - - it "records that the last action updated the resource" do - @resource.should be_updated_by_last_action - end - - describe "and then run again without being updated" do - before do - @resource.updated_by_last_action(false) - end - - it "reports that it is updated" do - @resource.should be_updated - end - - it "reports that it was not updated by the last action" do - @resource.should_not be_updated_by_last_action - end - - end - - end - - describe "when invoking its action" do - 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' - 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) - end - - it "runs runs an only_if when one is given" do - snitch_variable = nil - @resource.only_if { snitch_variable = true } - @resource.only_if.first.positivity.should == :only_if - #Chef::Mixin::Command.should_receive(:only_if).with(true, {}).and_return(false) - @resource.run_action(:purr) - snitch_variable.should be_true - 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) - snitch_var1.should == 1 - snitch_var2.should == 2 - end - - it "accepts command options for only_if conditionals" do - Chef::Resource::Conditional.any_instance.should_receive(:evaluate_command).at_least(1).times - @resource.only_if("true", :cwd => '/tmp') - @resource.only_if.first.command_opts.should == {:cwd => '/tmp'} - @resource.run_action(:purr) - end - - it "runs not_if as a command when it is a string" do - Chef::Resource::Conditional.any_instance.should_receive(:evaluate_command).at_least(1).times - @resource.not_if "pwd" - @resource.run_action(:purr) - end - - it "runs not_if as a block when it is a ruby block" do - Chef::Resource::Conditional.any_instance.should_receive(:evaluate_block).at_least(1).times - @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) - end - - it "accepts command options for not_if conditionals" do - @resource.not_if("pwd" , :cwd => '/tmp') - @resource.not_if.first.command_opts.should == {: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) - snitch_var1.should be_nil - snitch_var2.should be_false - end - - it "reports 0 elapsed time if actual elapsed time is < 0" do - expected = Time.now - Time.stub(:now).and_return(expected, expected - 1) - @resource.run_action(:purr) - @resource.elapsed_time.should == 0 - end - - describe "guard_interpreter attribute" do - let(:resource) { @resource } - - it "should be set to :default by default" do - resource.guard_interpreter.should == :default - end - - it "if set to :default should return :default when read" do - resource.guard_interpreter(:default) - resource.guard_interpreter.should == :default - end - - it "should raise Chef::Exceptions::ValidationFailed on an attempt to set the guard_interpreter attribute to something other than a Symbol" do - expect { resource.guard_interpreter('command_dot_com') }.to raise_error(Chef::Exceptions::ValidationFailed) - end - - it "should not raise an exception when setting the guard interpreter attribute to a Symbol" do - Chef::GuardInterpreter::ResourceGuardInterpreter.stub(:new).and_return(nil) - expect { resource.guard_interpreter(:command_dot_com) }.not_to raise_error - end - end - end - - describe "should_skip?" do - before do - @resource = Chef::Resource::Cat.new("sugar", @run_context) - end - - it "should return false by default" do - @resource.should_skip?(:purr).should be_false - end - - it "should return false when only_if is met" do - @resource.only_if { true } - @resource.should_skip?(:purr).should be_false - end - - it "should return true when only_if is not met" do - @resource.only_if { false } - @resource.should_skip?(:purr).should be_true - end - - it "should return true when not_if is met" do - @resource.not_if { true } - @resource.should_skip?(:purr).should be_true - end - - it "should return false when not_if is not met" do - @resource.not_if { false } - @resource.should_skip?(:purr).should be_false - 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 } - @resource.should_skip?(:purr).should be_true - 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 } - @resource.should_skip?(:purr).should be_true - 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 } - @resource.should_skip?(:purr).should be_true - end - - it "should return true when action is :nothing" do - @resource.should_skip?(:nothing).should be_true - end - - it "should return true when action is :nothing ignoring only_if/not_if conditionals" do - @resource.only_if { true } - @resource.not_if { false } - @resource.should_skip?(:nothing).should be_true - 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) - @run_context.stub(:events).and_return(fdoc) - fdoc.should_receive(:puts).with(" (skipped due to action :nothing)", anything()) - @resource.should_skip?(:nothing) - end - - end - - describe "when resource action is :nothing" do - 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' - 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) - snitch_var1.should == 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) - 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 - - @run_context.resource_collection << @resource1 - @run_context.resource_collection << @resource2 - @runner.converge - - snitch_var1.should == 1 - snitch_var2.should == 2 - end - end - - describe "building the platform map" do - - it 'adds mappings for a single platform' do - klz = Class.new(Chef::Resource) - Chef::Resource.platform_map.should_receive(:set).with( - :platform => :autobots, :short_name => :dinobot, :resource => klz - ) - klz.provides :dinobot, :on_platforms => ['autobots'] - end - - it 'adds mappings for multiple platforms' do - klz = Class.new(Chef::Resource) - Chef::Resource.platform_map.should_receive(:set).twice - klz.provides :energy, :on_platforms => ['autobots','decepticons'] - end - - it 'adds mappings for all platforms' do - klz = Class.new(Chef::Resource) - Chef::Resource.platform_map.should_receive(:set).with( - :short_name => :tape_deck, :resource => klz - ) - klz.provides :tape_deck - end - - end - - describe "lookups from the platform map" do - - before(:each) do - @node = Chef::Node.new - @node.name("bumblebee") - @node.automatic[:platform] = "autobots" - @node.automatic[:platform_version] = "6.1" - Object.const_set('Soundwave', Class.new(Chef::Resource)) - Object.const_set('Grimlock', Class.new(Chef::Resource){ provides :dinobot, :on_platforms => ['autobots'] }) - end - - after(:each) do - Object.send(:remove_const, :Soundwave) - Object.send(:remove_const, :Grimlock) - end - - describe "resource_for_platform" do - it 'return a resource by short_name and platform' do - Chef::Resource.resource_for_platform(:dinobot,'autobots','6.1').should eql(Grimlock) - end - it "returns a resource by short_name if nothing else matches" do - Chef::Resource.resource_for_node(:soundwave, @node).should eql(Soundwave) - end - end - - describe "resource_for_node" do - it "returns a resource by short_name and node" do - Chef::Resource.resource_for_node(:dinobot, @node).should eql(Grimlock) - end - it "returns a resource by short_name if nothing else matches" do - Chef::Resource.resource_for_node(:soundwave, @node).should eql(Soundwave) - end - end - - end - - describe "when creating notifications" do - - describe "with a string resource spec" do - - it "creates a delayed notification when timing is not specified" do - @resource.notifies(:run, "execute[foo]") - @run_context.delayed_notification_collection.should have(1).notifications - end - - it "creates a delayed notification when :delayed is not specified" do - @resource.notifies(:run, "execute[foo]", :delayed) - @run_context.delayed_notification_collection.should have(1).notifications - end - - it "creates an immediate notification when :immediate is specified" do - @resource.notifies(:run, "execute[foo]", :immediate) - @run_context.immediate_notification_collection.should have(1).notifications - end - - it "creates an immediate notification when :immediately is specified" do - @resource.notifies(:run, "execute[foo]", :immediately) - @run_context.immediate_notification_collection.should have(1).notifications - end - - describe "with a syntax error in the resource spec" do - - it "raises an exception immmediately" do - lambda do - @resource.notifies(:run, "typo[missing-closing-bracket") - end.should 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 - - it "creates a delayed notification when timing is not specified" do - @resource.notifies(:run, @notified_resource) - @run_context.delayed_notification_collection.should have(1).notifications - end - - it "creates a delayed notification when :delayed is not specified" do - @resource.notifies(:run, @notified_resource, :delayed) - @run_context.delayed_notification_collection.should have(1).notifications - end - - it "creates an immediate notification when :immediate is specified" do - @resource.notifies(:run, @notified_resource, :immediate) - @run_context.immediate_notification_collection.should have(1).notifications - end - - it "creates an immediate notification when :immediately is specified" do - @resource.notifies(:run, @notified_resource, :immediately) - @run_context.immediate_notification_collection.should have(1).notifications - 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 - - def compiled_resource_data(resource, action, err) - error_inspector = Chef::Formatters::ErrorInspectors::ResourceFailureInspector.new(resource, action, err) - description = Chef::Formatters::ErrorDescription.new("test") - error_inspector.add_explanation(description) - Chef::Log.info("descrtiption: #{description.inspect},error_inspector: #{error_inspector}") - description.sections[1]["Compiled Resource:"] - end - - it "set to false by default" do - @resource.sensitive.should be_false - end - - it "when set to false should show compiled resource for failed resource" do - expect { @resource_file.run_action(@action) }.to raise_error { |err| - compiled_resource_data(@resource_file, @action, err).should 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| - compiled_resource_data(@resource_file, @action, err).should eql("suppressed sensitive resource output") - } - end - - end -end - -describe Chef::Resource::Notification do - before do - @notification = Chef::Resource::Notification.new(:service_apache, :restart, :template_httpd_conf) - end - - it "has a resource to be notified" do - @notification.resource.should == :service_apache - end - - it "has an action to take on the service" do - @notification.action.should == :restart - end - - it "has a notifying resource" do - @notification.notifying_resource.should == :template_httpd_conf - end - - it "is a duplicate of another notification with the same target resource and action" do - other = Chef::Resource::Notification.new(:service_apache, :restart, :sync_web_app_code) - @notification.duplicates?(other).should be_true - end - - it "is not a duplicate of another notification if the actions differ" do - other = Chef::Resource::Notification.new(:service_apache, :enable, :install_apache) - @notification.duplicates?(other).should be_false - end - - it "is not a duplicate of another notification if the target resources differ" do - other = Chef::Resource::Notification.new(:service_sshd, :restart, :template_httpd_conf) - @notification.duplicates?(other).should be_false - end - - it "raises an ArgumentError if you try to check a non-ducktype object for duplication" do - lambda {@notification.duplicates?(:not_a_notification)}.should raise_error(ArgumentError) - end - - it "takes no action to resolve a resource reference that doesn't need to be resolved" do - @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @notification.resource = @keyboard_cat - @long_cat = Chef::Resource::Cat.new("long_cat") - @notification.notifying_resource = @long_cat - @resource_collection = Chef::ResourceCollection.new - # would raise an error since the resource is not in the collection - @notification.resolve_resource_reference(@resource_collection) - @notification.resource.should == @keyboard_cat - end - - it "resolves a lazy reference to a resource" do - @notification.resource = {:cat => "keyboard_cat"} - @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @resource_collection = Chef::ResourceCollection.new - @resource_collection << @keyboard_cat - @long_cat = Chef::Resource::Cat.new("long_cat") - @notification.notifying_resource = @long_cat - @notification.resolve_resource_reference(@resource_collection) - @notification.resource.should == @keyboard_cat - end - - it "resolves a lazy reference to its notifying resource" do - @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @notification.resource = @keyboard_cat - @notification.notifying_resource = {:cat => "long_cat"} - @long_cat = Chef::Resource::Cat.new("long_cat") - @resource_collection = Chef::ResourceCollection.new - @resource_collection << @long_cat - @notification.resolve_resource_reference(@resource_collection) - @notification.notifying_resource.should == @long_cat - end - - it "resolves lazy references to both its resource and its notifying resource" do - @notification.resource = {:cat => "keyboard_cat"} - @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @resource_collection = Chef::ResourceCollection.new - @resource_collection << @keyboard_cat - @notification.notifying_resource = {:cat => "long_cat"} - @long_cat = Chef::Resource::Cat.new("long_cat") - @resource_collection << @long_cat - @notification.resolve_resource_reference(@resource_collection) - @notification.resource.should == @keyboard_cat - @notification.notifying_resource.should == @long_cat - end - - it "raises a RuntimeError if you try to reference multiple resources" do - @notification.resource = {:cat => ["keyboard_cat", "cheez_cat"]} - @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @cheez_cat = Chef::Resource::Cat.new("cheez_cat") - @resource_collection = Chef::ResourceCollection.new - @resource_collection << @keyboard_cat - @resource_collection << @cheez_cat - @long_cat = Chef::Resource::Cat.new("long_cat") - @notification.notifying_resource = @long_cat - lambda {@notification.resolve_resource_reference(@resource_collection)}.should raise_error(RuntimeError) - end - - it "raises a RuntimeError if you try to reference multiple notifying resources" do - @notification.notifying_resource = {:cat => ["long_cat", "cheez_cat"]} - @long_cat = Chef::Resource::Cat.new("long_cat") - @cheez_cat = Chef::Resource::Cat.new("cheez_cat") - @resource_collection = Chef::ResourceCollection.new - @resource_collection << @long_cat - @resource_collection << @cheez_cat - @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @notification.resource = @keyboard_cat - lambda {@notification.resolve_resource_reference(@resource_collection)}.should raise_error(RuntimeError) - end - - it "raises a RuntimeError if it can't find a resource in the resource collection when resolving a lazy reference" do - @notification.resource = {:cat => "keyboard_cat"} - @cheez_cat = Chef::Resource::Cat.new("cheez_cat") - @resource_collection = Chef::ResourceCollection.new - @resource_collection << @cheez_cat - @long_cat = Chef::Resource::Cat.new("long_cat") - @notification.notifying_resource = @long_cat - lambda {@notification.resolve_resource_reference(@resource_collection)}.should raise_error(RuntimeError) - end - - it "raises a RuntimeError if it can't find a notifying resource in the resource collection when resolving a lazy reference" do - @notification.notifying_resource = {:cat => "long_cat"} - @cheez_cat = Chef::Resource::Cat.new("cheez_cat") - @resource_collection = Chef::ResourceCollection.new - @resource_collection << @cheez_cat - @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @notification.resource = @keyboard_cat - lambda {@notification.resolve_resource_reference(@resource_collection)}.should raise_error(RuntimeError) - end - - it "raises an ArgumentError if improper syntax is used in the lazy reference to its resource" do - @notification.resource = "cat => keyboard_cat" - @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @resource_collection = Chef::ResourceCollection.new - @resource_collection << @keyboard_cat - @long_cat = Chef::Resource::Cat.new("long_cat") - @notification.notifying_resource = @long_cat - lambda {@notification.resolve_resource_reference(@resource_collection)}.should raise_error(ArgumentError) - end - - it "raises an ArgumentError if improper syntax is used in the lazy reference to its notifying resource" do - @notification.notifying_resource = "cat => long_cat" - @long_cat = Chef::Resource::Cat.new("long_cat") - @resource_collection = Chef::ResourceCollection.new - @resource_collection << @long_cat - @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @notification.resource = @keyboard_cat - lambda {@notification.resolve_resource_reference(@resource_collection)}.should raise_error(ArgumentError) - end - - # Create test to resolve lazy references to both notifying resource and dest. resource - # Create tests to check proper error raising - -end |