summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@opscode.com>2013-03-20 14:57:18 -0700
committerLamont Granquist <lamont@opscode.com>2013-03-20 14:57:18 -0700
commitde0452180a1464d4a74992e0f9a83733ff4d8da2 (patch)
tree97db54bc4ebcf3629028ac4507f9e4040c6c176e
parent0e94bb48a688e7bb6b5488cb583af470d18acdda (diff)
downloadchef-de0452180a1464d4a74992e0f9a83733ff4d8da2.tar.gz
file provider spec work
-rw-r--r--spec/support/shared/unit/provider/file.rb585
-rw-r--r--spec/unit/provider/cookbook_file_spec.rb63
-rw-r--r--spec/unit/provider/file_spec.rb563
-rw-r--r--spec/unit/provider/remote_file_spec.rb52
-rw-r--r--spec/unit/provider/template_spec.rb83
5 files changed, 717 insertions, 629 deletions
diff --git a/spec/support/shared/unit/provider/file.rb b/spec/support/shared/unit/provider/file.rb
new file mode 100644
index 0000000000..ebb90d11ae
--- /dev/null
+++ b/spec/support/shared/unit/provider/file.rb
@@ -0,0 +1,585 @@
+#
+# Author:: Lamont Granquist (<lamont@opscode.com>)
+# Copyright:: Copyright (c) 2013 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'
+require 'tmpdir'
+
+shared_examples_for Chef::Provider::File do
+ # Mocksplosion
+
+ let(:node) { double('Chef::Node') }
+ let(:events) { double('Chef::Events').as_null_object } # mock all the methods
+ let(:run_context) { double('Chef::RunContext', :node => node, :events => events) }
+ let(:enclosing_directory) { File.expand_path(File.join(CHEF_SPEC_DATA, "templates")) }
+ let(:resource_path) { File.expand_path(File.join(enclosing_directory, "seattle.txt")) }
+
+ # Subject
+
+ let(:provider) do
+ provider = described_class.new(resource, run_context)
+ provider.stub!(:content).and_return(content)
+ provider
+ end
+
+ # Filesystem stubs
+
+ def setup_normal_file
+ File.stub!(:exists?).with(resource_path).and_return(true)
+ File.stub!(:directory?).with(resource_path).and_return(false)
+ File.stub!(:directory?).with(enclosing_directory).and_return(true)
+ File.stub!(:writable?).with(resource_path).and_return(true)
+ File.stub!(:symlink?).with(resource_path).and_return(false)
+ end
+
+ def setup_missing_file
+ File.stub!(:exists?).with(resource_path).and_return(false)
+ File.stub!(:directory?).with(resource_path).and_return(false)
+ File.stub!(:directory?).with(enclosing_directory).and_return(true)
+ File.stub!(:writable?).with(resource_path).and_return(false)
+ File.stub!(:symlink?).with(resource_path).and_return(false)
+ end
+
+ def setup_symlink
+ File.stub!(:exists?).with(resource_path).and_return(true)
+ File.stub!(:directory?).with(resource_path).and_return(false)
+ File.stub!(:directory?).with(enclosing_directory).and_return(true)
+ File.stub!(:writable?).with(resource_path).and_return(true)
+ File.stub!(:symlink?).with(resource_path).and_return(true)
+ end
+
+ def setup_unwritable_file
+ File.stub!(:exists?).with(resource_path).and_return(true)
+ File.stub!(:directory?).with(resource_path).and_return(false)
+ File.stub!(:directory?).with(enclosing_directory).and_return(true)
+ File.stub!(:writable?).with(resource_path).and_return(false)
+ File.stub!(:symlink?).with(resource_path).and_return(false)
+ end
+
+ def setup_missing_enclosing_directory
+ File.stub!(:exists?).with(resource_path).and_return(false)
+ File.stub!(:directory?).with(resource_path).and_return(false)
+ File.stub!(:directory?).with(enclosing_directory).and_return(false)
+ File.stub!(:writable?).with(resource_path).and_return(false)
+ File.stub!(:symlink?).with(resource_path).and_return(false)
+ end
+
+ # Tests
+
+ it "should return a #{described_class}" do
+ provider.should be_a_kind_of(described_class)
+ end
+
+ it "should store the resource passed to new as new_resource" do
+ provider.new_resource.should eql(resource)
+ end
+
+ it "should store the node passed to new as node" do
+ provider.node.should eql(node)
+ end
+
+ context "when loading the current resource" do
+
+ context "when running load_current_resource and the file exists" do
+ before do
+ setup_normal_file
+ provider.load_current_resource
+ end
+
+ it "should load a current resource based on the one specified at construction" do
+ provider.current_resource.should be_a_kind_of(Chef::Resource::File)
+ end
+
+ it "the loaded current_resource name should be the same as the resource name" do
+ provider.current_resource.name.should eql(resource.name)
+ end
+
+ it "the loaded current_resource path should be the same as the resoure path" do
+ provider.current_resource.path.should eql(resource.path)
+ end
+
+ it "the loaded current_resource content should be nil" do
+ provider.current_resource.content.should eql(nil)
+ end
+ end
+
+ context "when running load_current_resource and the file does not exist" do
+ before do
+ setup_missing_file
+ provider.load_current_resource
+ end
+
+ it "the current_resource should be a Chef::Resource::File" do
+ provider.current_resource.should be_a_kind_of(Chef::Resource::File)
+ end
+
+ it "the current_resource name should be the same as the resource name" do
+ provider.current_resource.name.should eql(resource.name)
+ end
+
+ it "the current_resource path should be the same as the resource path" do
+ provider.current_resource.path.should eql(resource.path)
+ end
+
+ it "the loaded current_resource content should be nil" do
+ provider.current_resource.content.should eql(nil)
+ end
+ end
+
+ context "examining file security metadata on Unix with a file that exists" do
+ before do
+ # fake that we're on unix even if we're on windows
+ Chef::Platform.stub!(:windows?).and_return(false)
+ # mock up the filesystem to behave like unix
+ setup_normal_file
+ stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
+ File.should_receive(:stat).with(resource.path).at_least(:once).and_return(stat_struct)
+ Etc.stub!(:getgrgid).with(0).and_return(mock("Group Ent", :name => "wheel"))
+ Etc.stub!(:getpwuid).with(0).and_return(mock("User Ent", :name => "root"))
+ end
+
+ context "when the new_resource does not specify any state" do
+ before do
+ provider.load_current_resource
+ end
+
+ it "should load the permissions into the current_resource" do
+ provider.current_resource.mode.should == "0600"
+ provider.current_resource.owner.should == "root"
+ provider.current_resource.group.should == "wheel"
+ end
+
+ it "should not set the new_resource permissions" do
+ provider.new_resource.group.should be_nil
+ provider.new_resource.owner.should be_nil
+ provider.new_resource.mode.should be_nil
+ end
+ end
+
+ context "when the new_resource explicitly specifies resource state as numbers" do
+ before do
+ resource.owner(1)
+ resource.group(1)
+ resource.mode(0644)
+ provider.load_current_resource
+ end
+
+ it "should load the permissions into the current_resource as numbers (BUT DOESN'T, BUG?)" do
+ # FIXME: inconsistency, hmmmm....
+ provider.current_resource.mode.should == "0600"
+ provider.current_resource.owner.should == 0
+ provider.current_resource.group.should == 0
+ end
+
+ it "should not set the new_resource permissions" do
+ provider.new_resource.group.should == 1
+ provider.new_resource.owner.should == 1
+ provider.new_resource.mode.should == 0644
+ end
+ end
+
+ context "when the new_resource explicitly specifies resource state as symbols" do
+ before do
+ resource.owner("macklemore")
+ resource.group("seattlehiphop")
+ resource.mode("0321")
+ provider.load_current_resource
+ end
+
+ it "should load the permissions into the current_resource as symbols" do
+ provider.current_resource.mode.should == "0600"
+ provider.current_resource.owner.should == "root"
+ provider.current_resource.group.should == "wheel"
+ end
+
+ it "should not set the new_resource permissions" do
+ provider.new_resource.group.should == "seattlehiphop"
+ provider.new_resource.owner.should == "macklemore"
+ provider.new_resource.mode.should == "0321"
+ end
+ end
+
+ end
+
+ context "examining file security metadata on Unix with a file that does not exist" do
+ before do
+ # fake that we're on unix even if we're on windows
+ Chef::Platform.stub!(:windows?).and_return(false)
+ setup_missing_file
+ end
+
+ context "when the new_resource does not specify any state" do
+ before do
+ provider.load_current_resource
+ end
+
+ it "the current_resource permissions should be nil" do
+ provider.current_resource.mode.should be_nil
+ provider.current_resource.owner.should be_nil
+ provider.current_resource.group.should be_nil
+ end
+
+ it "should not set the new_resource permissions" do
+ provider.new_resource.group.should be_nil
+ provider.new_resource.owner.should be_nil
+ provider.new_resource.mode.should be_nil
+ end
+ end
+
+ context "when the new_resource explicitly specifies resource state" do
+ before do
+ resource.owner(63945)
+ resource.group(51948)
+ resource.mode(0123)
+ provider.load_current_resource
+ end
+
+ it "the current_resource permissions should be nil" do
+ provider.current_resource.mode.should be_nil
+ provider.current_resource.owner.should be_nil
+ provider.current_resource.group.should be_nil
+ end
+
+ it "should not set the new_resource permissions" do
+ provider.new_resource.group.should == 51948
+ provider.new_resource.owner.should == 63945
+ provider.new_resource.mode.should == 0123
+ end
+ end
+ end
+ end
+
+ context "when loading the new_resource after the run" do
+
+ before do
+ # fake that we're on unix even if we're on windows
+ Chef::Platform.stub!(:windows?).and_return(false)
+ # mock up the filesystem to behave like unix
+ setup_normal_file
+ stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
+ File.stub!(:stat).with(resource.path).and_return(stat_struct)
+ Etc.stub!(:getgrgid).with(0).and_return(mock("Group Ent", :name => "wheel"))
+ Etc.stub!(:getpwuid).with(0).and_return(mock("User Ent", :name => "root"))
+ provider.send(:load_resource_attributes_from_file, resource)
+ end
+
+ it "new_resource should record the new permission information" do
+ provider.new_resource.group.should == "wheel"
+ provider.new_resource.owner.should == "root"
+ provider.new_resource.mode.should == "0600"
+ end
+ end
+
+ context "when reporting security metadata on windows (FIXME: moar tests)" do
+
+ it "records the file owner" do
+ pending
+ end
+
+ it "records rights for each user in the ACL" do
+ pending
+ end
+
+ it "records deny_rights for each user in the ACL" do
+ pending
+ end
+ end
+
+ context "define_resource_requirements" do
+ context "when the enclosing directory does not exist" do
+ before { setup_missing_enclosing_directory }
+
+ [:create, :create_if_missing, :touch].each do |action|
+ context "action #{action}" do
+ it "raises EnclosingDirectoryDoesNotExist" do
+ lambda {provider.run_action(action)}.should raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
+ end
+
+ it "does not raise an exception in why-run mode" do
+ Chef::Config[:why_run] = true
+ lambda {provider.run_action(action)}.should_not raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
+ Chef::Config[:why_run] = false
+ end
+ end
+ end
+ end
+
+ context "when the file exists but is not deletable" do
+ before { setup_unwritable_file }
+
+ it "action delete raises InsufficientPermissions" do
+ lambda {provider.run_action(:delete)}.should raise_error(Chef::Exceptions::InsufficientPermissions)
+ end
+
+ it "action delete also raises InsufficientPermissions in why-run mode" do
+ Chef::Config[:why_run] = true
+ lambda {provider.run_action(:delete)}.should raise_error(Chef::Exceptions::InsufficientPermissions)
+ Chef::Config[:why_run] = false
+ end
+ end
+ end
+
+ context "action create" do
+ it "should create the file, update its contents and then set the acls on the file" do
+ setup_missing_file
+ provider.should_receive(:do_create_file)
+ provider.should_receive(:do_contents_changes)
+ provider.should_receive(:do_acl_changes)
+ provider.should_receive(:load_resource_attributes_from_file)
+ provider.run_action(:create)
+ end
+
+ context "do_create_file" do
+ context "when the file exists" do
+ before { setup_normal_file }
+ it "should not create the file" do
+ provider.deployment_strategy.should_not_receive(:create).with(resource_path)
+ provider.send(:do_create_file)
+ provider.send(:file_created?).should == false
+ end
+ end
+ context "when the file does not exist" do
+ before { setup_missing_file }
+ it "should create the file" do
+ provider.deployment_strategy.should_receive(:create).with(resource_path)
+ provider.send(:do_create_file)
+ provider.send(:file_created?).should == true
+ end
+ end
+ end
+
+ context "do_contents_changes" do
+ context "when there is content to deploy" do
+ before do
+ tempfile = double('Tempfile', :path => "/tmp/foo-bar-baz")
+ content.stub!(:tempfile).and_return(tempfile)
+ File.should_receive(:exists?).with("/tmp/foo-bar-baz").and_return(true)
+ tempfile.should_receive(:unlink).once
+ end
+
+ context "when the contents have changed" do
+ let (:tempfile_path) { "/tmp/foo-bar-baz" }
+ let (:tempfile_md5) { "71f3811d0472fbef15d90a779615b254" }
+ let (:diff_for_reporting) { "+++\n---\n+foo\n-bar\n" }
+ before do
+ provider.stub!(:contents_changed?).and_return(true)
+ diff = double('Diff', :for_output => ['+++','---','+foo','-bar'],
+ :for_reporting => diff_for_reporting )
+ diff.stub!(:diff).with(resource_path, tempfile_path).and_return(true)
+ provider.should_receive(:diff).at_least(:once).and_return(diff)
+ provider.should_receive(:checksum).with(tempfile_path).and_return(tempfile_md5)
+ provider.deployment_strategy.should_receive(:deploy).with(tempfile_path, resource_path)
+ end
+ context "when the file was created" do
+ before { provider.should_receive(:file_created?).at_least(:once).and_return(true) }
+ it "does not backup the file and does not produce a diff for reporting" do
+ provider.should_not_receive(:backup)
+ provider.send(:do_contents_changes)
+ resource.diff.should be_nil
+ end
+ end
+ context "when the file was not created" do
+ before { provider.should_receive(:file_created?).at_least(:once).and_return(false) }
+ it "backs up the file and produces a diff for reporting" do
+ provider.should_receive(:backup)
+ provider.send(:do_contents_changes)
+ resource.diff.should == diff_for_reporting
+ end
+ end
+ end
+
+ it "does nothing when the contents have not changed" do
+ provider.stub!(:contents_changed?).and_return(false)
+ provider.should_not_receive(:diff)
+ provider.send(:do_contents_changes)
+ end
+ end
+
+ it "does nothing when there is no content to deploy (tempfile returned from contents is nil)" do
+ provider.send(:content).should_receive(:tempfile).at_least(:once).and_return(nil)
+ provider.should_not_receive(:diff)
+ lambda{ provider.send(:do_contents_changes) }.should_not raise_error
+ end
+
+ it "raises an exception when the content object returns a tempfile with a nil path" do
+ tempfile = double('Tempfile', :path => nil)
+ provider.send(:content).should_receive(:tempfile).at_least(:once).and_return(tempfile)
+ lambda{ provider.send(:do_contents_changes) }.should raise_error
+ end
+
+ it "raises an exception when the content object returns a tempfile that does not exist" do
+ tempfile = double('Tempfile', :path => "/tmp/foo-bar-baz")
+ provider.send(:content).should_receive(:tempfile).at_least(:once).and_return(tempfile)
+ File.should_receive(:exists?).with("/tmp/foo-bar-baz").and_return(false)
+ lambda{ provider.send(:do_contents_changes) }.should raise_error
+ end
+ end
+
+ context "do_acl_changes" do
+ it "needs tests" do
+ pending
+ end
+ end
+
+ # it "should compare the current content with the requested content" do
+ # @provider.load_current_resource
+ #
+ # @provider.new_resource.content "foobar"
+ # @provider.compare_content.should eql(false)
+ #
+ # @provider.new_resource.content IO.read(@resource.path)
+ # @provider.compare_content.should eql(true)
+ # end
+ #
+ # it "should set the content of the file to the requested content" do
+ # io = StringIO.new
+ # @provider.load_current_resource
+ # @provider.new_resource.content "foobar"
+ # @provider.should_receive(:diff_current_from_content).and_return("")
+ # @provider.should_receive(:backup)
+ # # checksum check
+ # File.should_receive(:open).with(@provider.new_resource.path, "rb").and_yield(io)
+ # File.should_receive(:open).with(@provider.new_resource.path, "w").and_yield(io)
+ # @provider.set_content
+ # io.string.should == "foobar"
+ # end
+ #
+ # it "should not set the content of the file if it already matches the requested content" do
+ # @provider.load_current_resource
+ # @provider.new_resource.content IO.read(@resource.path)
+ # # Checksum check:
+ # File.should_receive(:open).with(@resource.path, "rb").and_yield(StringIO.new(@resource.content))
+ # File.should_not_receive(:open).with(@provider.new_resource.path, "w")
+ # lambda { @provider.set_content }.should_not raise_error
+ # @resource.should_not be_updated_by_last_action
+ # end
+ #
+ # it "should create the file if it is missing, then set the attributes on action_create" do
+ # @provider.load_current_resource
+ # @provider.stub!(:update_new_file_state)
+ # @provider.new_resource.stub!(:path).and_return(File.join(Dir.tmpdir, "monkeyfoo"))
+ # @provider.access_controls.should_receive(:set_all)
+ # @provider.should_receive(:diff_current_from_content).and_return("")
+ # File.stub!(:open).and_return(1)
+ # #File.should_receive(:directory?).with("/tmp").and_return(true)
+ # File.should_receive(:open).with(@provider.new_resource.path, "w+")
+ # @provider.run_action(:create)
+ # @resource.should be_updated_by_last_action
+ # end
+ #
+ # it "should create the file with the proper content if it is missing, then set attributes on action_create" do
+ # io = StringIO.new
+ # @provider.load_current_resource
+ # @provider.new_resource.content "foobar"
+ # @provider.new_resource.stub!(:path).and_return(File.join(Dir.tmpdir, "monkeyfoo"))
+ # @provider.should_receive(:diff_current_from_content).and_return("")
+ # @provider.stub!(:update_new_file_state)
+ # File.should_receive(:open).with(@provider.new_resource.path, "w+").and_yield(io)
+ # @provider.access_controls.should_receive(:set_all)
+ # @provider.run_action(:create)
+ # io.string.should == "foobar"
+ # @resource.should be_updated_by_last_action
+ # end
+ end
+
+ context "action delete" do
+ context "when the file exists" do
+ context "when the file is writable" do
+ context "when the file is not a symlink" do
+ before { setup_normal_file }
+ it "should backup and delete the file and be updated by the last action" do
+ provider.should_receive(:backup).at_least(:once).and_return(true)
+ File.should_receive(:delete).with(resource_path).and_return(true)
+ provider.run_action(:delete)
+ resource.should be_updated_by_last_action
+ end
+ end
+ context "when the file is a symlink" do
+ before { setup_symlink }
+ it "should not backup the symlink" do
+ provider.should_not_receive(:backup)
+ File.should_receive(:delete).with(resource_path).and_return(true)
+ provider.run_action(:delete)
+ resource.should be_updated_by_last_action
+ end
+ end
+ end
+ context "when the file is not writable" do
+ before { setup_unwritable_file }
+ it "should not try to backup or delete the file, and should not be updated by last action" do
+ provider.should_not_receive(:backup)
+ File.should_not_receive(:delete)
+ lambda { provider.run_action(:delete) }.should raise_error()
+ resource.should_not be_updated_by_last_action
+ end
+ end
+ end
+
+ context "when the file does not exist" do
+ before { setup_missing_file }
+
+ it "should not try to backup or delete the file, and should not be updated by last action" do
+ provider.should_not_receive(:backup)
+ File.should_not_receive(:delete)
+ lambda { provider.run_action(:delete) }.should_not raise_error()
+ resource.should_not be_updated_by_last_action
+ end
+ end
+ end
+
+ context "action touch" do
+ context "when the file does not exist" do
+ before { setup_missing_file }
+ it "should update the atime/mtime on action_touch" do
+ File.should_receive(:utime).once
+ provider.should_receive(:action_create)
+ provider.run_action(:touch)
+ resource.should be_updated_by_last_action
+ end
+ end
+ context "when the file exists" do
+ before { setup_normal_file }
+ it "should update the atime/mtime on action_touch" do
+ File.should_receive(:utime).once
+ provider.should_receive(:action_create)
+ provider.run_action(:touch)
+ resource.should be_updated_by_last_action
+ end
+ end
+ end
+
+ context "action create_if_missing" do
+ context "when the file does not exist" do
+ before { setup_missing_file }
+ it "should call action_create" do
+ provider.should_receive(:action_create)
+ provider.run_action(:create_if_missing)
+ end
+ end
+
+ context "when the file exists" do
+ before { setup_normal_file }
+ it "should not call action_create" do
+ provider.should_not_receive(:action_create)
+ provider.run_action(:create_if_missing)
+ end
+ end
+
+ end
+
+end
+
diff --git a/spec/unit/provider/cookbook_file_spec.rb b/spec/unit/provider/cookbook_file_spec.rb
index 6761eba692..66fdd9871d 100644
--- a/spec/unit/provider/cookbook_file_spec.rb
+++ b/spec/unit/provider/cookbook_file_spec.rb
@@ -1,6 +1,7 @@
#
# Author:: Daniel DeLeo (<dan@opscode.com>)
-# Copyright:: Copyright (c) 2010 Opscode, Inc.
+# Author:: Lamont Granquist (<lamont@opscode.com>)
+# Copyright:: Copyright (c) 2009-2013 Opscode, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,31 +20,47 @@
require 'spec_helper'
require 'ostruct'
+require 'support/shared/unit/provider/file'
+
describe Chef::Provider::CookbookFile do
- before do
- Chef::FileAccessControl.any_instance.stub(:set_all)
- Chef::FileAccessControl.any_instance.stub(:modified?).and_return(true)
- @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) }
-
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- cl = Chef::CookbookLoader.new(@cookbook_repo)
- cl.load_cookbooks
- @cookbook_collection = Chef::CookbookCollection.new(cl)
- @run_context = Chef::RunContext.new(@node, @cookbook_collection, @events)
-
- @new_resource = Chef::Resource::CookbookFile.new('apache2_module_conf_generate.pl', @run_context)
- @new_resource.cookbook_name = 'apache2'
- @provider = Chef::Provider::CookbookFile.new(@new_resource, @run_context)
-
- @file_content=<<-EXPECTED
-# apache2_module_conf_generate.pl
-# this is just here for show.
-EXPECTED
+ let(:resource) do
+ resource = Chef::Resource::CookbookFile.new("seattle", @run_context)
+ resource.path(resource_path)
+ resource.cookbook_name = 'apache2'
+ resource
+ end
+
+ let(:content) do
+ content = mock('Chef::Provider::File::Content::CookbookFile')
end
+ it_behaves_like Chef::Provider::File
+
+# before do
+# Chef::FileAccessControl.any_instance.stub(:set_all)
+# Chef::FileAccessControl.any_instance.stub(:modified?).and_return(true)
+# @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
+# Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) }
+#
+# @node = Chef::Node.new
+# @events = Chef::EventDispatch::Dispatcher.new
+# cl = Chef::CookbookLoader.new(@cookbook_repo)
+# cl.load_cookbooks
+# @cookbook_collection = Chef::CookbookCollection.new(cl)
+# @run_context = Chef::RunContext.new(@node, @cookbook_collection, @events)
+#
+# @new_resource = Chef::Resource::CookbookFile.new('apache2_module_conf_generate.pl', @run_context)
+# @new_resource.cookbook_name = 'apache2'
+# @provider = Chef::Provider::CookbookFile.new(@new_resource, @run_context)
+#
+# @file_content=<<-EXPECTED
+## apache2_module_conf_generate.pl
+## this is just here for show.
+#EXPECTED
+#
+# end
+
it "prefers the explicit cookbook name on the resource to the implicit one" do
@new_resource.cookbook('nginx')
@provider.resource_cookbook.should == 'nginx'
@@ -139,7 +156,7 @@ EXPECTED
it "stages the cookbook to a temporary file" do
# prevents file backups where we might not have write access
- @provider.should_receive(:backup_new_resource)
+ @provider.should_receive(:backup_new_resource)
@new_resource.path(@install_to)
@provider.should_receive(:deploy_tempfile)
@provider.run_action(:create)
diff --git a/spec/unit/provider/file_spec.rb b/spec/unit/provider/file_spec.rb
index a9253336c6..020d2b9b8d 100644
--- a/spec/unit/provider/file_spec.rb
+++ b/spec/unit/provider/file_spec.rb
@@ -17,19 +17,10 @@
# limitations under the License.
#
-require 'spec_helper'
-require 'tmpdir'
+require 'support/shared/unit/provider/file'
describe Chef::Provider::File do
- # Mocksplosion
-
- let(:node) { double('Chef::Node') }
- let(:events) { double('Chef::Events').as_null_object } # mock all the methods
- let(:run_context) { double('Chef::RunContext', :node => node, :events => events) }
- let(:enclosing_directory) { File.expand_path(File.join(CHEF_SPEC_DATA, "templates")) }
- let(:resource_path) { File.expand_path(File.join(enclosing_directory, "seattle.txt")) }
-
let(:resource) do
# need to check for/against mutating state within the new_resource, so don't mock
resource = Chef::Resource::File.new("seattle")
@@ -37,556 +28,10 @@ describe Chef::Provider::File do
resource
end
- # Subject
-
- let(:provider) do
- Chef::Provider::File.new(resource, run_context)
- end
-
- # Filesystem stubs
-
- def setup_normal_file
- File.stub!(:exists?).with(resource_path).and_return(true)
- File.stub!(:directory?).with(resource_path).and_return(false)
- File.stub!(:directory?).with(enclosing_directory).and_return(true)
- File.stub!(:writable?).with(resource_path).and_return(true)
- File.stub!(:symlink?).with(resource_path).and_return(false)
- end
-
- def setup_missing_file
- File.stub!(:exists?).with(resource_path).and_return(false)
- File.stub!(:directory?).with(resource_path).and_return(false)
- File.stub!(:directory?).with(enclosing_directory).and_return(true)
- File.stub!(:writable?).with(resource_path).and_return(false)
- File.stub!(:symlink?).with(resource_path).and_return(false)
- end
-
- def setup_symlink
- File.stub!(:exists?).with(resource_path).and_return(true)
- File.stub!(:directory?).with(resource_path).and_return(false)
- File.stub!(:directory?).with(enclosing_directory).and_return(true)
- File.stub!(:writable?).with(resource_path).and_return(true)
- File.stub!(:symlink?).with(resource_path).and_return(true)
- end
-
- def setup_unwritable_file
- File.stub!(:exists?).with(resource_path).and_return(true)
- File.stub!(:directory?).with(resource_path).and_return(false)
- File.stub!(:directory?).with(enclosing_directory).and_return(true)
- File.stub!(:writable?).with(resource_path).and_return(false)
- File.stub!(:symlink?).with(resource_path).and_return(false)
- end
-
- def setup_missing_enclosing_directory
- File.stub!(:exists?).with(resource_path).and_return(false)
- File.stub!(:directory?).with(resource_path).and_return(false)
- File.stub!(:directory?).with(enclosing_directory).and_return(false)
- File.stub!(:writable?).with(resource_path).and_return(false)
- File.stub!(:symlink?).with(resource_path).and_return(false)
- end
-
- # Tests
-
- it "should return a Chef::Provider::File" do
- provider.should be_a_kind_of(Chef::Provider::File)
- end
-
- it "should store the resource passed to new as new_resource" do
- provider.new_resource.should eql(resource)
- end
-
- it "should store the node passed to new as node" do
- provider.node.should eql(node)
- end
-
- context "when loading the current resource" do
-
- context "when running load_current_resource and the file exists" do
- before do
- setup_normal_file
- provider.load_current_resource
- end
-
- it "should load a current resource based on the one specified at construction" do
- provider.current_resource.should be_a_kind_of(Chef::Resource::File)
- end
-
- it "the loaded current_resource name should be the same as the resource name" do
- provider.current_resource.name.should eql(resource.name)
- end
-
- it "the loaded current_resource path should be the same as the resoure path" do
- provider.current_resource.path.should eql(resource.path)
- end
-
- it "the loaded current_resource content should be nil" do
- provider.current_resource.content.should eql(nil)
- end
- end
-
- context "when running load_current_resource and the file does not exist" do
- before do
- setup_missing_file
- provider.load_current_resource
- end
-
- it "the current_resource should be a Chef::Resource::File" do
- provider.current_resource.should be_a_kind_of(Chef::Resource::File)
- end
-
- it "the current_resource name should be the same as the resource name" do
- provider.current_resource.name.should eql(resource.name)
- end
-
- it "the current_resource path should be the same as the resource path" do
- provider.current_resource.path.should eql(resource.path)
- end
-
- it "the loaded current_resource content should be nil" do
- provider.current_resource.content.should eql(nil)
- end
- end
-
- context "examining file security metadata on Unix with a file that exists" do
- before do
- # fake that we're on unix even if we're on windows
- Chef::Platform.stub!(:windows?).and_return(false)
- # mock up the filesystem to behave like unix
- setup_normal_file
- stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
- File.should_receive(:stat).with(resource.path).at_least(:once).and_return(stat_struct)
- Etc.stub!(:getgrgid).with(0).and_return(mock("Group Ent", :name => "wheel"))
- Etc.stub!(:getpwuid).with(0).and_return(mock("User Ent", :name => "root"))
- end
-
- context "when the new_resource does not specify any state" do
- before do
- provider.load_current_resource
- end
-
- it "should load the permissions into the current_resource" do
- provider.current_resource.mode.should == "0600"
- provider.current_resource.owner.should == "root"
- provider.current_resource.group.should == "wheel"
- end
-
- it "should not set the new_resource permissions" do
- provider.new_resource.group.should be_nil
- provider.new_resource.owner.should be_nil
- provider.new_resource.mode.should be_nil
- end
- end
-
- context "when the new_resource explicitly specifies resource state as numbers" do
- before do
- resource.owner(1)
- resource.group(1)
- resource.mode(0644)
- provider.load_current_resource
- end
-
- it "should load the permissions into the current_resource as numbers (BUT DOESN'T, BUG?)" do
- # FIXME: inconsistency, hmmmm....
- provider.current_resource.mode.should == "0600"
- provider.current_resource.owner.should == 0
- provider.current_resource.group.should == 0
- end
-
- it "should not set the new_resource permissions" do
- provider.new_resource.group.should == 1
- provider.new_resource.owner.should == 1
- provider.new_resource.mode.should == 0644
- end
- end
-
- context "when the new_resource explicitly specifies resource state as symbols" do
- before do
- resource.owner("macklemore")
- resource.group("seattlehiphop")
- resource.mode("0321")
- provider.load_current_resource
- end
-
- it "should load the permissions into the current_resource as symbols" do
- provider.current_resource.mode.should == "0600"
- provider.current_resource.owner.should == "root"
- provider.current_resource.group.should == "wheel"
- end
-
- it "should not set the new_resource permissions" do
- provider.new_resource.group.should == "seattlehiphop"
- provider.new_resource.owner.should == "macklemore"
- provider.new_resource.mode.should == "0321"
- end
- end
-
- end
-
- context "examining file security metadata on Unix with a file that does not exist" do
- before do
- # fake that we're on unix even if we're on windows
- Chef::Platform.stub!(:windows?).and_return(false)
- setup_missing_file
- end
-
- context "when the new_resource does not specify any state" do
- before do
- provider.load_current_resource
- end
-
- it "the current_resource permissions should be nil" do
- provider.current_resource.mode.should be_nil
- provider.current_resource.owner.should be_nil
- provider.current_resource.group.should be_nil
- end
-
- it "should not set the new_resource permissions" do
- provider.new_resource.group.should be_nil
- provider.new_resource.owner.should be_nil
- provider.new_resource.mode.should be_nil
- end
- end
-
- context "when the new_resource explicitly specifies resource state" do
- before do
- resource.owner(63945)
- resource.group(51948)
- resource.mode(0123)
- provider.load_current_resource
- end
-
- it "the current_resource permissions should be nil" do
- provider.current_resource.mode.should be_nil
- provider.current_resource.owner.should be_nil
- provider.current_resource.group.should be_nil
- end
-
- it "should not set the new_resource permissions" do
- provider.new_resource.group.should == 51948
- provider.new_resource.owner.should == 63945
- provider.new_resource.mode.should == 0123
- end
- end
- end
- end
-
- context "when loading the new_resource after the run" do
-
- before do
- # fake that we're on unix even if we're on windows
- Chef::Platform.stub!(:windows?).and_return(false)
- # mock up the filesystem to behave like unix
- setup_normal_file
- stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
- File.stub!(:stat).with(resource.path).and_return(stat_struct)
- Etc.stub!(:getgrgid).with(0).and_return(mock("Group Ent", :name => "wheel"))
- Etc.stub!(:getpwuid).with(0).and_return(mock("User Ent", :name => "root"))
- provider.send(:load_resource_attributes_from_file, resource)
- end
-
- it "new_resource should record the new permission information" do
- provider.new_resource.group.should == "wheel"
- provider.new_resource.owner.should == "root"
- provider.new_resource.mode.should == "0600"
- end
- end
-
- context "when reporting security metadata on windows (FIXME: moar tests)" do
-
- it "records the file owner" do
- pending
- end
-
- it "records rights for each user in the ACL" do
- pending
- end
-
- it "records deny_rights for each user in the ACL" do
- pending
- end
- end
-
- context "define_resource_requirements" do
- context "when the enclosing directory does not exist" do
- before { setup_missing_enclosing_directory }
-
- [:create, :create_if_missing, :touch].each do |action|
- describe "action #{action}" do
- it "raises EnclosingDirectoryDoesNotExist" do
- lambda {provider.run_action(action)}.should raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
- end
-
- it "does not raise an exception in why-run mode" do
- Chef::Config[:why_run] = true
- lambda {provider.run_action(action)}.should_not raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
- Chef::Config[:why_run] = false
- end
- end
- end
- end
-
- context "when the file exists but is not deletable" do
- before { setup_unwritable_file }
-
- it "action delete raises InsufficientPermissions" do
- lambda {provider.run_action(:delete)}.should raise_error(Chef::Exceptions::InsufficientPermissions)
- end
-
- it "action delete also raises InsufficientPermissions in why-run mode" do
- Chef::Config[:why_run] = true
- lambda {provider.run_action(:delete)}.should raise_error(Chef::Exceptions::InsufficientPermissions)
- Chef::Config[:why_run] = false
- end
- end
- end
-
- context "action create" do
- it "should create the file, update its contents and then set the acls on the file" do
- setup_missing_file
- provider.should_receive(:do_create_file)
- provider.should_receive(:do_contents_changes)
- provider.should_receive(:do_acl_changes)
- provider.should_receive(:load_resource_attributes_from_file)
- provider.run_action(:create)
- end
-
- context "do_create_file" do
- context "when the file exists" do
- before { setup_normal_file }
- it "should not create the file" do
- provider.deployment_strategy.should_not_receive(:create).with(resource_path)
- provider.send(:do_create_file)
- provider.send(:file_created?).should == false
- end
- end
- context "when the file does not exist" do
- before { setup_missing_file }
- it "should create the file" do
- provider.deployment_strategy.should_receive(:create).with(resource_path)
- provider.send(:do_create_file)
- provider.send(:file_created?).should == true
- end
- end
- end
-
- context "do_contents_changes" do
- context "when there is content to deploy" do
- before do
- tempfile = double('Tempfile', :path => "/tmp/foo-bar-baz")
- provider.send(:content).should_receive(:tempfile).at_least(:once).and_return(tempfile)
- File.should_receive(:exists?).with("/tmp/foo-bar-baz").and_return(true)
- tempfile.should_receive(:unlink).once
- end
-
- context "when the contents have changed" do
- let (:tempfile_path) { "/tmp/foo-bar-baz" }
- let (:tempfile_md5) { "71f3811d0472fbef15d90a779615b254" }
- let (:diff_for_reporting) { "+++\n---\n+foo\n-bar\n" }
- before do
- provider.stub!(:contents_changed?).and_return(true)
- diff = double('Diff', :for_output => ['+++','---','+foo','-bar'],
- :for_reporting => diff_for_reporting )
- diff.stub!(:diff).with(resource_path, tempfile_path).and_return(true)
- provider.should_receive(:diff).at_least(:once).and_return(diff)
- provider.should_receive(:checksum).with(tempfile_path).and_return(tempfile_md5)
- provider.deployment_strategy.should_receive(:deploy).with(tempfile_path, resource_path)
- end
- context "when the file was created" do
- before { provider.should_receive(:file_created?).at_least(:once).and_return(true) }
- it "does not backup the file and does not produce a diff for reporting" do
- provider.should_not_receive(:backup)
- provider.send(:do_contents_changes)
- resource.diff.should be_nil
- end
- end
- context "when the file was not created" do
- before { provider.should_receive(:file_created?).at_least(:once).and_return(false) }
- it "backs up the file and produces a diff for reporting" do
- provider.should_receive(:backup)
- provider.send(:do_contents_changes)
- resource.diff.should == diff_for_reporting
- end
- end
- end
-
- it "does nothing when the contents have not changed" do
- provider.stub!(:contents_changed?).and_return(false)
- provider.should_not_receive(:diff)
- provider.send(:do_contents_changes)
- end
- end
-
- it "does nothing when there is no content to deploy (tempfile returned from contents is nil)" do
- provider.send(:content).should_receive(:tempfile).at_least(:once).and_return(nil)
- provider.should_not_receive(:diff)
- lambda{ provider.send(:do_contents_changes) }.should_not raise_error
- end
-
- it "raises an exception when the content object returns a tempfile with a nil path" do
- tempfile = double('Tempfile', :path => nil)
- provider.send(:content).should_receive(:tempfile).at_least(:once).and_return(tempfile)
- lambda{ provider.send(:do_contents_changes) }.should raise_error
- end
-
- it "raises an exception when the content object returns a tempfile that does not exist" do
- tempfile = double('Tempfile', :path => "/tmp/foo-bar-baz")
- provider.send(:content).should_receive(:tempfile).at_least(:once).and_return(tempfile)
- File.should_receive(:exists?).with("/tmp/foo-bar-baz").and_return(false)
- lambda{ provider.send(:do_contents_changes) }.should raise_error
- end
- end
-
- context "do_acl_changes" do
- it "needs tests" do
- pending
- end
- end
-
- # it "should compare the current content with the requested content" do
- # @provider.load_current_resource
- #
- # @provider.new_resource.content "foobar"
- # @provider.compare_content.should eql(false)
- #
- # @provider.new_resource.content IO.read(@resource.path)
- # @provider.compare_content.should eql(true)
- # end
- #
- # it "should set the content of the file to the requested content" do
- # io = StringIO.new
- # @provider.load_current_resource
- # @provider.new_resource.content "foobar"
- # @provider.should_receive(:diff_current_from_content).and_return("")
- # @provider.should_receive(:backup)
- # # checksum check
- # File.should_receive(:open).with(@provider.new_resource.path, "rb").and_yield(io)
- # File.should_receive(:open).with(@provider.new_resource.path, "w").and_yield(io)
- # @provider.set_content
- # io.string.should == "foobar"
- # end
- #
- # it "should not set the content of the file if it already matches the requested content" do
- # @provider.load_current_resource
- # @provider.new_resource.content IO.read(@resource.path)
- # # Checksum check:
- # File.should_receive(:open).with(@resource.path, "rb").and_yield(StringIO.new(@resource.content))
- # File.should_not_receive(:open).with(@provider.new_resource.path, "w")
- # lambda { @provider.set_content }.should_not raise_error
- # @resource.should_not be_updated_by_last_action
- # end
- #
- # it "should create the file if it is missing, then set the attributes on action_create" do
- # @provider.load_current_resource
- # @provider.stub!(:update_new_file_state)
- # @provider.new_resource.stub!(:path).and_return(File.join(Dir.tmpdir, "monkeyfoo"))
- # @provider.access_controls.should_receive(:set_all)
- # @provider.should_receive(:diff_current_from_content).and_return("")
- # File.stub!(:open).and_return(1)
- # #File.should_receive(:directory?).with("/tmp").and_return(true)
- # File.should_receive(:open).with(@provider.new_resource.path, "w+")
- # @provider.run_action(:create)
- # @resource.should be_updated_by_last_action
- # end
- #
- # it "should create the file with the proper content if it is missing, then set attributes on action_create" do
- # io = StringIO.new
- # @provider.load_current_resource
- # @provider.new_resource.content "foobar"
- # @provider.new_resource.stub!(:path).and_return(File.join(Dir.tmpdir, "monkeyfoo"))
- # @provider.should_receive(:diff_current_from_content).and_return("")
- # @provider.stub!(:update_new_file_state)
- # File.should_receive(:open).with(@provider.new_resource.path, "w+").and_yield(io)
- # @provider.access_controls.should_receive(:set_all)
- # @provider.run_action(:create)
- # io.string.should == "foobar"
- # @resource.should be_updated_by_last_action
- # end
- end
-
- context "action delete" do
- context "when the file exists" do
- context "when the file is writable" do
- context "when the file is not a symlink" do
- before { setup_normal_file }
- it "should backup and delete the file and be updated by the last action" do
- provider.should_receive(:backup).at_least(:once).and_return(true)
- File.should_receive(:delete).with(resource_path).and_return(true)
- provider.run_action(:delete)
- resource.should be_updated_by_last_action
- end
- end
- context "when the file is a symlink" do
- before { setup_symlink }
- it "should not backup the symlink" do
- provider.should_not_receive(:backup)
- File.should_receive(:delete).with(resource_path).and_return(true)
- provider.run_action(:delete)
- resource.should be_updated_by_last_action
- end
- end
- end
- context "when the file is not writable" do
- before { setup_unwritable_file }
- it "should not try to backup or delete the file, and should not be updated by last action" do
- provider.should_not_receive(:backup)
- File.should_not_receive(:delete)
- lambda { provider.run_action(:delete) }.should raise_error()
- resource.should_not be_updated_by_last_action
- end
- end
- end
-
- context "when the file does not exist" do
- before { setup_missing_file }
-
- it "should not try to backup or delete the file, and should not be updated by last action" do
- provider.should_not_receive(:backup)
- File.should_not_receive(:delete)
- lambda { provider.run_action(:delete) }.should_not raise_error()
- resource.should_not be_updated_by_last_action
- end
- end
- end
-
- context "action touch" do
- context "when the file does not exist" do
- before { setup_missing_file }
- it "should update the atime/mtime on action_touch" do
- File.should_receive(:utime).once
- provider.should_receive(:action_create)
- provider.run_action(:touch)
- resource.should be_updated_by_last_action
- end
- end
- context "when the file exists" do
- before { setup_normal_file }
- it "should update the atime/mtime on action_touch" do
- File.should_receive(:utime).once
- provider.should_receive(:action_create)
- provider.run_action(:touch)
- resource.should be_updated_by_last_action
- end
- end
- end
-
- context "action create_if_missing" do
- context "when the file does not exist" do
- before { setup_missing_file }
- it "should call action_create" do
- provider.should_receive(:action_create)
- provider.run_action(:create_if_missing)
- end
- end
-
- context "when the file exists" do
- before { setup_normal_file }
- it "should not call action_create" do
- provider.should_not_receive(:action_create)
- provider.run_action(:create_if_missing)
- end
- end
-
+ let(:content) do
+ content = mock('Chef::Provider::File::Content::File')
end
+ it_behaves_like Chef::Provider::File
end
diff --git a/spec/unit/provider/remote_file_spec.rb b/spec/unit/provider/remote_file_spec.rb
index d055180a4a..7b7cd23b46 100644
--- a/spec/unit/provider/remote_file_spec.rb
+++ b/spec/unit/provider/remote_file_spec.rb
@@ -1,6 +1,7 @@
#
# Author:: Adam Jacob (<adam@opscode.com>)
-# Copyright:: Copyright (c) 2008 Opscode, Inc.
+# Author:: Lamont Granquist (<lamont@opscode.com>)
+# Copyright:: Copyright (c) 2008-2013 Opscode, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,22 +19,43 @@
require 'spec_helper'
-describe Chef::Provider::RemoteFile, "action_create" do
+require 'support/shared/unit/provider/file'
+
+
+describe Chef::Provider::RemoteFile do
+ let(:resource) do
+ resource = Chef::Resource::RemoteFile.new("seattle", @run_context)
+ resource.path(resource_path)
+ resource.source("http://foo")
+ resource
+ end
+
before(:each) do
- @resource = Chef::Resource::RemoteFile.new("seattle")
- @resource.path(File.expand_path(File.join(CHEF_SPEC_DATA, "seattle.txt")))
- @resource.source("http://foo")
- @node = Chef::Node.new
- @node.name "latte"
-
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
-
- @provider = Chef::Provider::RemoteFile.new(@resource, @run_context)
- #To prevent the current_resource.checksum from being overridden.
- @provider.stub!(:load_current_resource)
+ ::File.stub!(:exists?).with("#{Chef::Config[:file_cache_path]}/remote_file/#{resource.name}").and_return(false)
+ end
+
+ let(:content) do
+ content = mock('Chef::Provider::File::Content::RemoteFile')
end
+ it_behaves_like Chef::Provider::File
+
+#describe Chef::Provider::RemoteFile, "action_create" do
+# before(:each) do
+# @resource = Chef::Resource::RemoteFile.new("seattle")
+# @resource.path(File.expand_path(File.join(CHEF_SPEC_DATA, "seattle.txt")))
+# @resource.source("http://foo")
+# @node = Chef::Node.new
+# @node.name "latte"
+#
+# @events = Chef::EventDispatch::Dispatcher.new
+# @run_context = Chef::RunContext.new(@node, {}, @events)
+#
+# @provider = Chef::Provider::RemoteFile.new(@resource, @run_context)
+# #To prevent the current_resource.checksum from being overridden.
+# @provider.stub!(:load_current_resource)
+# end
+
describe "when checking if the file is at the target version" do
it "considers the current file to be at the target version if it exists and matches the user-provided checksum" do
@provider.current_resource = @resource.dup
@@ -286,7 +308,7 @@ describe Chef::Provider::RemoteFile, "action_create" do
describe "and create_if_missing is invoked" do
it "should take no action" do
- @provider.should_not_receive(:action_create)
+ @provider.should_not_receive(:action_create)
@provider.run_action(:create_if_missing)
end
end
diff --git a/spec/unit/provider/template_spec.rb b/spec/unit/provider/template_spec.rb
index b709d8e612..321864b4d8 100644
--- a/spec/unit/provider/template_spec.rb
+++ b/spec/unit/provider/template_spec.rb
@@ -1,6 +1,7 @@
#
# Author:: Adam Jacob (<adam@opscode.com>)
-# Copyright:: Copyright (c) 2008 Opscode, Inc.
+# Author:: Lamont Granquist (<lamont@opscode.com>)
+# Copyright:: Copyright (c) 2008-2013 Opscode, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,43 +16,61 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+
require 'stringio'
require 'spec_helper'
require 'etc'
require 'ostruct'
+require 'support/shared/unit/provider/file'
+
describe Chef::Provider::Template do
- before(:each) do
- @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) }
-
- @node = Chef::Node.new
- cl = Chef::CookbookLoader.new(@cookbook_repo)
- cl.load_cookbooks
- @cookbook_collection = Chef::CookbookCollection.new(cl)
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, @cookbook_collection, @events)
-
- @rendered_file_location = Dir.tmpdir + '/openldap_stuff.conf'
-
- @resource = Chef::Resource::Template.new(@rendered_file_location)
- @resource.cookbook_name = 'openldap'
-
- @provider = Chef::Provider::Template.new(@resource, @run_context)
- @current_resource = @resource.dup
- @provider.current_resource = @current_resource
- @access_controls = mock("access controls")
- @provider.stub!(:access_controls).and_return(@access_controls)
- passwd_struct = if windows?
- Struct::Passwd.new("root", "x", 0, 0, "/root", "/bin/bash")
- else
- Struct::Passwd.new("root", "x", 0, 0, "root", "/root", "/bin/bash")
- end
- group_struct = mock("Group Ent", :name => "root", :passwd => "x", :gid => 0)
- Etc.stub!(:getpwuid).and_return(passwd_struct)
- Etc.stub!(:getgrgid).and_return(group_struct)
+
+ let(:resource) do
+ resource = Chef::Resource::Template.new("seattle", @run_context)
+ resource.path(resource_path)
+ resource
end
+ let(:content) do
+ content = mock('Chef::Provider::File::Content::Template', :template_location => "/foo/bar/baz")
+ File.stub(:exists?).with("/foo/bar/baz").and_return(true)
+ content
+ end
+
+ it_behaves_like Chef::Provider::File
+
+# before(:each) do
+# @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
+# Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) }
+#
+# @node = Chef::Node.new
+# cl = Chef::CookbookLoader.new(@cookbook_repo)
+# cl.load_cookbooks
+# @cookbook_collection = Chef::CookbookCollection.new(cl)
+# @events = Chef::EventDispatch::Dispatcher.new
+# @run_context = Chef::RunContext.new(@node, @cookbook_collection, @events)
+#
+# @rendered_file_location = Dir.tmpdir + '/openldap_stuff.conf'
+#
+# @resource = Chef::Resource::Template.new(@rendered_file_location)
+# @resource.cookbook_name = 'openldap'
+#
+# @provider = Chef::Provider::Template.new(@resource, @run_context)
+# @current_resource = @resource.dup
+# @provider.current_resource = @current_resource
+# @access_controls = mock("access controls")
+# @provider.stub!(:access_controls).and_return(@access_controls)
+# passwd_struct = if windows?
+# Struct::Passwd.new("root", "x", 0, 0, "/root", "/bin/bash")
+# else
+# Struct::Passwd.new("root", "x", 0, 0, "root", "/root", "/bin/bash")
+# end
+# group_struct = mock("Group Ent", :name => "root", :passwd => "x", :gid => 0)
+# Etc.stub!(:getpwuid).and_return(passwd_struct)
+# Etc.stub!(:getgrgid).and_return(group_struct)
+# end
+
describe "when creating the template" do
before do
@@ -71,9 +90,9 @@ describe Chef::Provider::Template do
@provider.template_location.should == '/tmp/its_on_disk.erb'
end
- it "stops executing when the local template source can't be found" do
+ it "stops executing when the local template source can't be found" do
@access_controls.stub!(:requires_changes?).and_return(false)
- @resource.source "invalid.erb"
+ @resource.source "invalid.erb"
@resource.local true
lambda { @provider.run_action(:create) } .should raise_error Chef::Mixin::WhyRun::ResourceRequirements::Assertion::AssertionFailure
end