diff options
Diffstat (limited to 'spec/unit/provider/mount')
-rw-r--r-- | spec/unit/provider/mount/mount_spec.rb | 398 | ||||
-rw-r--r-- | spec/unit/provider/mount/windows_spec.rb | 134 |
2 files changed, 532 insertions, 0 deletions
diff --git a/spec/unit/provider/mount/mount_spec.rb b/spec/unit/provider/mount/mount_spec.rb new file mode 100644 index 0000000000..c497a08e40 --- /dev/null +++ b/spec/unit/provider/mount/mount_spec.rb @@ -0,0 +1,398 @@ +# +# Author:: Joshua Timberman (<joshua@opscode.com>) +# Copyright:: Copyright (c) 2008 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 'ostruct' + +describe Chef::Provider::Mount::Mount do + before(:each) do + @node = Chef::Node.new + @events = Chef::EventDispatch::Dispatcher.new + @run_context = Chef::RunContext.new(@node, {}, @events) + + @new_resource = Chef::Resource::Mount.new("/tmp/foo") + @new_resource.device "/dev/sdz1" + @new_resource.device_type :device + @new_resource.fstype "ext3" + + @new_resource.supports :remount => false + + @provider = Chef::Provider::Mount::Mount.new(@new_resource, @run_context) + + ::File.stub!(:exists?).with("/dev/sdz1").and_return true + ::File.stub!(:exists?).with("/tmp/foo").and_return true + end + + describe "when discovering the current fs state" do + before do + @provider.stub!(:shell_out!).and_return(OpenStruct.new(:stdout => '')) + ::File.stub!(:foreach).with("/etc/fstab") + end + + it "should create a current resource with the same mount point and device" do + @provider.load_current_resource + @provider.current_resource.name.should == '/tmp/foo' + @provider.current_resource.mount_point.should == '/tmp/foo' + @provider.current_resource.device.should == '/dev/sdz1' + end + + it "should accecpt device_type :uuid" do + @new_resource.device_type :uuid + @new_resource.device "d21afe51-a0fe-4dc6-9152-ac733763ae0a" + @stdout_findfs = mock("STDOUT", :first => "/dev/sdz1") + @provider.should_receive(:popen4).with("/sbin/findfs UUID=d21afe51-a0fe-4dc6-9152-ac733763ae0a").and_yield(@pid,@stdin,@stdout_findfs,@stderr).and_return(@status) + @provider.load_current_resource() + @provider.mountable? + end + + describe "when dealing with network mounts" do + { "nfs" => "nfsserver:/vol/path", + "cifs" => "//cifsserver/share" }.each do |type, fs_spec| + it "should detect network fs_spec (#{type})" do + @new_resource.device fs_spec + @provider.network_device?.should be_true + end + + it "should ignore trailing slash and set mounted to true for network mount (#{type})" do + @new_resource.device fs_spec + @provider.stub!(:shell_out!).and_return(OpenStruct.new(:stdout => "#{fs_spec}/ on /tmp/foo type #{type} (rw)\n")) + @provider.load_current_resource + @provider.current_resource.mounted.should be_true + end + end + end + + it "should raise an error if the mount device does not exist" do + ::File.stub!(:exists?).with("/dev/sdz1").and_return false + lambda { @provider.load_current_resource();@provider.mountable? }.should raise_error(Chef::Exceptions::Mount) + end + + it "should not call mountable? with load_current_resource - CHEF-1565" do + ::File.stub!(:exists?).with("/dev/sdz1").and_return false + @provider.should_receive(:mounted?).and_return(true) + @provider.should_receive(:enabled?).and_return(true) + @provider.should_not_receive(:mountable?) + @provider.load_current_resource + end + + it "should raise an error if the mount device (uuid) does not exist" do + @new_resource.device_type :uuid + @new_resource.device "d21afe51-a0fe-4dc6-9152-ac733763ae0a" + status_findfs = mock("Status", :exitstatus => 1) + stdout_findfs = mock("STDOUT", :first => nil) + @provider.should_receive(:popen4).with("/sbin/findfs UUID=d21afe51-a0fe-4dc6-9152-ac733763ae0a").and_yield(@pid,@stdin,stdout_findfs,@stderr).and_return(status_findfs) + ::File.should_receive(:exists?).with("").and_return(false) + lambda { @provider.load_current_resource();@provider.mountable? }.should raise_error(Chef::Exceptions::Mount) + end + + it "should raise an error if the mount point does not exist" do + ::File.stub!(:exists?).with("/tmp/foo").and_return false + lambda { @provider.load_current_resource();@provider.mountable? }.should raise_error(Chef::Exceptions::Mount) + end + + it "does not expect the device to exist for tmpfs" do + @new_resource.fstype("tmpfs") + @new_resource.device("whatever") + lambda { @provider.load_current_resource() }.should_not raise_error + end + + it "does not expect the device to exist for Fuse filesystems" do + @new_resource.fstype("fuse") + @new_resource.device("nilfs#xxx") + lambda { @provider.load_current_resource() }.should_not raise_error + end + + it "should set mounted true if the mount point is found in the mounts list" do + @provider.stub!(:shell_out!).and_return(OpenStruct.new(:stdout => '/dev/sdz1 on /tmp/foo')) + @provider.load_current_resource() + @provider.current_resource.mounted.should be_true + end + + it "should set mounted true if the symlink target of the device is found in the mounts list" do + target = "/dev/mapper/target" + + ::File.stub!(:symlink?).with("#{@new_resource.device}").and_return(true) + ::File.stub!(:readlink).with("#{@new_resource.device}").and_return(target) + + @provider.stub!(:shell_out!).and_return(OpenStruct.new(:stdout => "/dev/mapper/target on /tmp/foo type ext3 (rw)\n")) + @provider.load_current_resource() + @provider.current_resource.mounted.should be_true + end + + it "should set mounted true if the mount point is found last in the mounts list" do + mount = "/dev/sdy1 on #{@new_resource.mount_point} type ext3 (rw)\n" + mount << "#{@new_resource.device} on #{@new_resource.mount_point} type ext3 (rw)\n" + + @provider.stub!(:shell_out!).and_return(OpenStruct.new(:stdout => mount)) + @provider.load_current_resource() + @provider.current_resource.mounted.should be_true + end + + it "should set mounted false if the mount point is not last in the mounts list" do + mount = "#{@new_resource.device} on #{@new_resource.mount_point} type ext3 (rw)\n" + mount << "/dev/sdy1 on #{@new_resource.mount_point} type ext3 (rw)\n" + + @provider.stub!(:shell_out!).and_return(OpenStruct.new(:stdout => mount)) + @provider.load_current_resource() + @provider.current_resource.mounted.should be_false + end + + it "mounted should be false if the mount point is not found in the mounts list" do + @provider.stub!(:shell_out!).and_return(OpenStruct.new(:stdout => "/dev/sdy1 on /tmp/foo type ext3 (rw)\n")) + @provider.load_current_resource() + @provider.current_resource.mounted.should be_false + end + + it "should set enabled to true if the mount point is last in fstab" do + fstab1 = "/dev/sdy1 /tmp/foo ext3 defaults 1 2\n" + fstab2 = "#{@new_resource.device} #{@new_resource.mount_point} ext3 defaults 1 2\n" + + ::File.stub!(:foreach).with("/etc/fstab").and_yield(fstab1).and_yield(fstab2) + + @provider.load_current_resource + @provider.current_resource.enabled.should be_true + end + + it "should set enabled to true if the mount point is not last in fstab and mount_point is a substring of another mount" do + fstab1 = "#{@new_resource.device} #{@new_resource.mount_point} ext3 defaults 1 2\n" + fstab2 = "/dev/sdy1 /tmp/foo/bar ext3 defaults 1 2\n" + + ::File.stub!(:foreach).with("/etc/fstab").and_yield(fstab1).and_yield(fstab2) + + @provider.load_current_resource + @provider.current_resource.enabled.should be_true + end + + it "should set enabled to true if the symlink target is in fstab" do + target = "/dev/mapper/target" + + ::File.stub!(:symlink?).with("#{@new_resource.device}").and_return(true) + ::File.stub!(:readlink).with("#{@new_resource.device}").and_return(target) + + fstab = "/dev/sdz1 /tmp/foo ext3 defaults 1 2\n" + + ::File.stub!(:foreach).with("/etc/fstab").and_yield fstab + + @provider.load_current_resource + @provider.current_resource.enabled.should be_true + end + + it "should set enabled to false if the mount point is not in fstab" do + fstab = "/dev/sdy1 #{@new_resource.mount_point} ext3 defaults 1 2\n" + ::File.stub!(:foreach).with("/etc/fstab").and_yield fstab + + @provider.load_current_resource + @provider.current_resource.enabled.should be_false + end + + it "should ignore commented lines in fstab " do + fstab = "\# #{@new_resource.device} #{@new_resource.mount_point} ext3 defaults 1 2\n" + ::File.stub!(:foreach).with("/etc/fstab").and_yield fstab + + @provider.load_current_resource + @provider.current_resource.enabled.should be_false + end + + it "should set enabled to false if the mount point is not last in fstab" do + line_1 = "#{@new_resource.device} #{@new_resource.mount_point} ext3 defaults 1 2\n" + line_2 = "/dev/sdy1 #{@new_resource.mount_point} ext3 defaults 1 2\n" + ::File.stub!(:foreach).with("/etc/fstab").and_yield(line_1).and_yield(line_2) + + @provider.load_current_resource + @provider.current_resource.enabled.should be_false + end + end + + context "after the mount's state has been discovered" do + before do + @current_resource = Chef::Resource::Mount.new("/tmp/foo") + @current_resource.device "/dev/sdz1" + @current_resource.device_type :device + @current_resource.fstype "ext3" + + @provider.current_resource = @current_resource + end + + describe "mount_fs" do + it "should mount the filesystem if it is not mounted" do + @provider.rspec_reset + @provider.should_receive(:shell_out!).with("mount -t ext3 -o defaults /dev/sdz1 /tmp/foo") + @provider.mount_fs() + end + + it "should mount the filesystem with options if options were passed" do + options = "rw,noexec,noauto" + @new_resource.options(%w{rw noexec noauto}) + @provider.should_receive(:shell_out!).with("mount -t ext3 -o rw,noexec,noauto /dev/sdz1 /tmp/foo") + @provider.mount_fs() + end + + it "should mount the filesystem specified by uuid" do + @new_resource.device "d21afe51-a0fe-4dc6-9152-ac733763ae0a" + @new_resource.device_type :uuid + @stdout_findfs = mock("STDOUT", :first => "/dev/sdz1") + @provider.stub!(:popen4).with("/sbin/findfs UUID=d21afe51-a0fe-4dc6-9152-ac733763ae0a").and_yield(@pid,@stdin,@stdout_findfs,@stderr).and_return(@status) + @stdout_mock = mock('stdout mock') + @stdout_mock.stub!(:each).and_yield("#{@new_resource.device} on #{@new_resource.mount_point}") + @provider.should_receive(:shell_out!).with("mount -t #{@new_resource.fstype} -o defaults -U #{@new_resource.device} #{@new_resource.mount_point}").and_return(@stdout_mock) + @provider.mount_fs() + end + + it "should not mount the filesystem if it is mounted" do + @current_resource.stub!(:mounted).and_return(true) + @provider.should_not_receive(:shell_out!) + @provider.mount_fs() + end + + end + + describe "umount_fs" do + it "should umount the filesystem if it is mounted" do + @current_resource.mounted(true) + @provider.should_receive(:shell_out!).with("umount /tmp/foo") + @provider.umount_fs() + end + + it "should not umount the filesystem if it is not mounted" do + @current_resource.mounted(false) + @provider.should_not_receive(:shell_out!) + @provider.umount_fs() + end + end + + describe "remount_fs" do + it "should use mount -o remount if remount is supported" do + @new_resource.supports({:remount => true}) + @current_resource.mounted(true) + @provider.should_receive(:shell_out!).with("mount -o remount #{@new_resource.mount_point}") + @provider.remount_fs + end + + it "should umount and mount if remount is not supported" do + @new_resource.supports({:remount => false}) + @current_resource.mounted(true) + @provider.should_receive(:umount_fs) + @provider.should_receive(:sleep).with(1) + @provider.should_receive(:mount_fs) + @provider.remount_fs() + end + + it "should not try to remount at all if mounted is false" do + @current_resource.mounted(false) + @provider.should_not_receive(:shell_out!) + @provider.should_not_receive(:umount_fs) + @provider.should_not_receive(:mount_fs) + @provider.remount_fs() + end + end + + describe "when enabling the fs" do + it "should enable if enabled isn't true" do + @current_resource.enabled(false) + + @fstab = StringIO.new + ::File.stub!(:open).with("/etc/fstab", "a").and_yield(@fstab) + @provider.enable_fs + @fstab.string.should match(%r{^/dev/sdz1\s+/tmp/foo\s+ext3\s+defaults\s+0\s+2\s*$}) + end + + it "should not enable if enabled is true and resources match" do + @current_resource.enabled(true) + @current_resource.fstype("ext3") + @current_resource.options(["defaults"]) + @current_resource.dump(0) + @current_resource.pass(2) + ::File.should_not_receive(:open).with("/etc/fstab", "a") + + @provider.enable_fs + end + + it "should enable if enabled is true and resources do not match" do + @current_resource.enabled(true) + @current_resource.fstype("auto") + @current_resource.options(["defaults"]) + @current_resource.dump(0) + @current_resource.pass(2) + @fstab = StringIO.new + ::File.stub(:readlines).and_return([]) + ::File.should_receive(:open).once.with("/etc/fstab", "w").and_yield(@fstab) + ::File.should_receive(:open).once.with("/etc/fstab", "a").and_yield(@fstab) + + @provider.enable_fs + end + end + + describe "when disabling the fs" do + it "should disable if enabled is true" do + @current_resource.enabled(true) + + other_mount = "/dev/sdy1 /tmp/foo ext3 defaults 1 2\n" + this_mount = "/dev/sdz1 /tmp/foo ext3 defaults 1 2\n" + + @fstab_read = [this_mount, other_mount] + ::File.stub!(:readlines).with("/etc/fstab").and_return(@fstab_read) + @fstab_write = StringIO.new + ::File.stub!(:open).with("/etc/fstab", "w").and_yield(@fstab_write) + + @provider.disable_fs + @fstab_write.string.should match(Regexp.escape(other_mount)) + @fstab_write.string.should_not match(Regexp.escape(this_mount)) + end + + it "should disable if enabled is true and ignore commented lines" do + @current_resource.enabled(true) + + fstab_read = [%q{/dev/sdy1 /tmp/foo ext3 defaults 1 2}, + %q{/dev/sdz1 /tmp/foo ext3 defaults 1 2}, + %q{#/dev/sdz1 /tmp/foo ext3 defaults 1 2}] + fstab_write = StringIO.new + + ::File.stub!(:readlines).with("/etc/fstab").and_return(fstab_read) + ::File.stub!(:open).with("/etc/fstab", "w").and_yield(fstab_write) + + @provider.disable_fs + fstab_write.string.should match(%r{^/dev/sdy1 /tmp/foo ext3 defaults 1 2$}) + fstab_write.string.should match(%r{^#/dev/sdz1 /tmp/foo ext3 defaults 1 2$}) + fstab_write.string.should_not match(%r{^/dev/sdz1 /tmp/foo ext3 defaults 1 2$}) + end + + it "should disable only the last entry if enabled is true" do + @current_resource.stub!(:enabled).and_return(true) + fstab_read = ["/dev/sdz1 /tmp/foo ext3 defaults 1 2\n", + "/dev/sdy1 /tmp/foo ext3 defaults 1 2\n", + "/dev/sdz1 /tmp/foo ext3 defaults 1 2\n"] + + fstab_write = StringIO.new + ::File.stub!(:readlines).with("/etc/fstab").and_return(fstab_read) + ::File.stub!(:open).with("/etc/fstab", "w").and_yield(fstab_write) + + @provider.disable_fs + fstab_write.string.should == "/dev/sdz1 /tmp/foo ext3 defaults 1 2\n/dev/sdy1 /tmp/foo ext3 defaults 1 2\n" + end + + it "should not disable if enabled is false" do + @current_resource.stub!(:enabled).and_return(false) + + ::File.stub!(:readlines).with("/etc/fstab").and_return([]) + ::File.should_not_receive(:open).and_yield(@fstab) + + @provider.disable_fs + end + end + end +end diff --git a/spec/unit/provider/mount/windows_spec.rb b/spec/unit/provider/mount/windows_spec.rb new file mode 100644 index 0000000000..f173ebba22 --- /dev/null +++ b/spec/unit/provider/mount/windows_spec.rb @@ -0,0 +1,134 @@ +# +# Author:: Doug MacEachern (<dougm@vmware.com>) +# Copyright:: Copyright (c) 2010 VMware, 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 Chef + class Util + class Windows + class NetUse + end + class Volume + end + end + end +end + +GUID = "\\\\?\\Volume{578e72b5-6e70-11df-b5c5-000c29d4a7d9}\\" +REMOTE = "\\\\server-name\\path" + +describe Chef::Provider::Mount::Windows do + before(:each) do + @node = Chef::Node.new + @events = Chef::EventDispatch::Dispatcher.new + @run_context = Chef::RunContext.new(@node, {}, @events) + @new_resource = Chef::Resource::Mount.new("X:") + @new_resource.device GUID + @current_resource = Chef::Resource::Mount.new("X:") + Chef::Resource::Mount.stub!(:new).and_return(@current_resource) + + @net_use = mock("Chef::Util::Windows::NetUse") + Chef::Util::Windows::NetUse.stub!(:new).and_return(@net_use) + @vol = mock("Chef::Util::Windows::Volume") + Chef::Util::Windows::Volume.stub!(:new).and_return(@vol) + + @provider = Chef::Provider::Mount::Windows.new(@new_resource, @run_context) + @provider.current_resource = @current_resource + end + + describe "when loading the current resource" do + it "should set mounted true if the mount point is found" do + @vol.stub!(:device).and_return(@new_resource.device) + @current_resource.should_receive(:mounted).with(true) + @provider.load_current_resource + end + + it "should set mounted false if the mount point is not found" do + @vol.stub!(:device).and_raise(ArgumentError) + @current_resource.should_receive(:mounted).with(false) + @provider.load_current_resource + end + + describe "with a local device" do + before do + @new_resource.device GUID + @vol.stub!(:device).and_return(@new_resource.device) + @net_use.stub!(:device).and_raise(ArgumentError) + end + + it "should determine the device is a volume GUID" do + @provider.should_receive(:is_volume).with(@new_resource.device).and_return(true) + @provider.load_current_resource + end + end + + describe "with a remote device" do + before do + @new_resource.device REMOTE + @net_use.stub!(:device).and_return(@new_resource.device) + @vol.stub!(:device).and_raise(ArgumentError) + end + + it "should determine the device is remote" do + @provider.should_receive(:is_volume).with(@new_resource.device).and_return(false) + @provider.load_current_resource + end + end + + describe "when mounting a file system" do + before do + @new_resource.device GUID + @vol.stub!(:add) + @vol.stub!(:device).and_raise(ArgumentError) + @provider.load_current_resource + end + + it "should mount the filesystem if it is not mounted" do + @vol.should_receive(:add).with(@new_resource.device) + @provider.mount_fs + end + + it "should not mount the filesystem if it is mounted" do + @vol.should_not_receive(:add) + @current_resource.stub!(:mounted).and_return(true) + @provider.mount_fs + end + end + + describe "when unmounting a file system" do + before do + @new_resource.device GUID + @vol.stub!(:delete) + @vol.stub!(:device).and_raise(ArgumentError) + @provider.load_current_resource + end + + it "should umount the filesystem if it is mounted" do + @current_resource.stub!(:mounted).and_return(true) + @vol.should_receive(:delete) + @provider.umount_fs + end + + it "should not umount the filesystem if it is not mounted" do + @current_resource.stub!(:mounted).and_return(false) + @vol.should_not_receive(:delete) + @provider.umount_fs + end + end + end +end |