Skip to content

Commit 67e1ff6

Browse files
committed
Merge pull request #1699 from stschulte/ticket/master/mount_fixes
Various mount fixes
2 parents 937faed + 0f9434c commit 67e1ff6

File tree

7 files changed

+557
-335
lines changed

7 files changed

+557
-335
lines changed

lib/puppet/provider/mount.rb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@
55
module Puppet::Provider::Mount
66
# This only works when the mount point is synced to the fstab.
77
def mount
8-
# Manually pass the mount options in, since some OSes *cough*OS X*cough* don't
9-
# read from /etc/fstab but still want to use this type.
108
args = []
11-
args << "-o" << self.options if self.options and self.options != :absent
9+
10+
# In general we do not have to pass mountoptions because we always
11+
# flush /etc/fstab before attempting to mount. But old code suggests
12+
# that MacOS always needs the mount options to be explicitly passed to
13+
# the mount command
14+
if Facter.value(:kernel) == 'Darwin'
15+
args << "-o" << self.options if self.options and self.options != :absent
16+
end
1217
args << resource[:name]
1318

1419
mountcmd(*args)

lib/puppet/type/mount.rb

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ def syncothers
118118
device is supporting by the mount, including network
119119
devices or devices specified by UUID rather than device
120120
path, depending on the operating system."
121+
122+
validate do |value|
123+
raise Puppet::Error, "device must not contain whitespace: #{value}" if value =~ /\s/
124+
end
121125
end
122126

123127
# Solaris specifies two devices, not just one.
@@ -128,47 +132,68 @@ def syncothers
128132

129133
# Default to the device but with "dsk" replaced with "rdsk".
130134
defaultto do
131-
if Facter["osfamily"].value == "Solaris"
132-
device = @resource.value(:device)
133-
if device =~ %r{/dsk/}
135+
if Facter.value(:osfamily) == "Solaris"
136+
if device = resource[:device] and device =~ %r{/dsk/}
134137
device.sub(%r{/dsk/}, "/rdsk/")
138+
elsif fstype = resource[:fstype] and fstype == 'nfs'
139+
'-'
135140
else
136141
nil
137142
end
138143
else
139144
nil
140145
end
141146
end
147+
148+
validate do |value|
149+
raise Puppet::Error, "blockdevice must not contain whitespace: #{value}" if value =~ /\s/
150+
end
142151
end
143152

144153
newproperty(:fstype) do
145154
desc "The mount type. Valid values depend on the
146155
operating system. This is a required option."
156+
157+
validate do |value|
158+
raise Puppet::Error, "fstype must not contain whitespace: #{value}" if value =~ /\s/
159+
end
147160
end
148161

149162
newproperty(:options) do
150163
desc "Mount options for the mounts, as they would
151164
appear in the fstab."
165+
166+
validate do |value|
167+
raise Puppet::Error, "option must not contain whitespace: #{value}" if value =~ /\s/
168+
end
152169
end
153170

154171
newproperty(:pass) do
155172
desc "The pass in which the mount is checked."
156173

157174
defaultto {
158-
0 if @resource.managed?
175+
if @resource.managed?
176+
if Facter.value(:osfamily) == 'Solaris'
177+
'-'
178+
else
179+
0
180+
end
181+
end
159182
}
160183
end
161184

162185
newproperty(:atboot) do
163186
desc "Whether to mount the mount at boot. Not all platforms
164187
support this."
188+
189+
newvalues :yes, :no
165190
end
166191

167192
newproperty(:dump) do
168193
desc "Whether to dump the mount. Not all platform support this.
169194
Valid values are `1` or `0`. or `2` on FreeBSD, Default is `0`."
170195

171-
if Facter["operatingsystem"].value == "FreeBSD"
196+
if Facter.value(:operatingsystem) == "FreeBSD"
172197
newvalue(%r{(0|1|2)})
173198
else
174199
newvalue(%r{(0|1)})
@@ -197,6 +222,14 @@ def syncothers
197222
desc "The mount path for the mount."
198223

199224
isnamevar
225+
226+
validate do |value|
227+
raise Puppet::Error, "name must not contain whitespace: #{value}" if value =~ /\s/
228+
end
229+
230+
munge do |value|
231+
value.gsub(/^(.+?)\/*$/, '\1')
232+
end
200233
end
201234

202235
newparam(:remounts) do

spec/integration/provider/mount_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def create_fake_fstab(initially_contains_entry)
2020
@current_options = "local"
2121
@current_device = "/dev/disk1s1"
2222
Puppet::Type.type(:mount).defaultprovider.stubs(:default_target).returns(@fake_fstab)
23+
Facter.stubs(:value).with(:kernel).returns('Darwin')
2324
Facter.stubs(:value).with(:operatingsystem).returns('Darwin')
2425
Facter.stubs(:value).with(:osfamily).returns('Darwin')
2526
Puppet::Util::ExecutionStub.set do |command, options|

spec/unit/provider/mount/parsed_spec.rb

Lines changed: 44 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,114 +2,102 @@
22
require 'spec_helper'
33
require 'shared_behaviours/all_parsedfile_providers'
44

5-
provider_class = Puppet::Type.type(:mount).provider(:parsed)
5+
describe Puppet::Type.type(:mount).provider(:parsed), :unless => Puppet.features.microsoft_windows? do
66

7-
describe provider_class, :unless => Puppet.features.microsoft_windows? do
7+
let :vfstab_sample do
8+
"/dev/dsk/c0d0s0 /dev/rdsk/c0d0s0 \t\t / \t ufs 1 no\t-"
9+
end
810

9-
before :each do
10-
@mount_class = Puppet::Type.type(:mount)
11-
@provider = @mount_class.provider(:parsed)
11+
let :fstab_sample do
12+
"/dev/vg00/lv01\t/spare \t \t ext3 defaults\t1 2"
1213
end
1314

1415
# LAK:FIXME I can't mock Facter because this test happens at parse-time.
1516
it "should default to /etc/vfstab on Solaris" do
1617
pending "This test only works on Solaris" unless Facter.value(:osfamily) == 'Solaris'
17-
Puppet::Type.type(:mount).provider(:parsed).default_target.should == '/etc/vfstab'
18+
described_class.default_target.should == '/etc/vfstab'
1819
end
1920

2021
it "should default to /etc/fstab on anything else" do
2122
pending "This test does not work on Solaris" if Facter.value(:osfamily) == 'Solaris'
22-
Puppet::Type.type(:mount).provider(:parsed).default_target.should == '/etc/fstab'
23+
described_class.default_target.should == '/etc/fstab'
2324
end
2425

2526
describe "when parsing a line" do
26-
2727
it "should not crash on incomplete lines in fstab" do
28-
parse = @provider.parse <<-FSTAB
28+
parse = described_class.parse <<-FSTAB
2929
/dev/incomplete
3030
/dev/device name
3131
FSTAB
32-
lambda{ @provider.to_line(parse[0]) }.should_not raise_error
32+
expect { described_class.to_line(parse[0]) }.to_not raise_error
3333
end
3434

3535
# it_should_behave_like "all parsedfile providers",
3636
# provider_class, my_fixtures('*.fstab')
3737

3838
describe "on Solaris", :if => Facter.value(:osfamily) == 'Solaris' do
39-
40-
before :each do
41-
@example_line = "/dev/dsk/c0d0s0 /dev/rdsk/c0d0s0 \t\t / \t ufs 1 no\t-"
42-
end
43-
4439
it "should extract device from the first field" do
45-
@provider.parse_line(@example_line)[:device].should == '/dev/dsk/c0d0s0'
40+
described_class.parse_line(vfstab_sample)[:device].should == '/dev/dsk/c0d0s0'
4641
end
4742

4843
it "should extract blockdevice from second field" do
49-
@provider.parse_line(@example_line)[:blockdevice].should == "/dev/rdsk/c0d0s0"
44+
described_class.parse_line(vfstab_sample)[:blockdevice].should == "/dev/rdsk/c0d0s0"
5045
end
5146

5247
it "should extract name from third field" do
53-
@provider.parse_line(@example_line)[:name].should == "/"
48+
described_class.parse_line(vfstab_sample)[:name].should == "/"
5449
end
5550

5651
it "should extract fstype from fourth field" do
57-
@provider.parse_line(@example_line)[:fstype].should == "ufs"
52+
described_class.parse_line(vfstab_sample)[:fstype].should == "ufs"
5853
end
5954

6055
it "should extract pass from fifth field" do
61-
@provider.parse_line(@example_line)[:pass].should == "1"
56+
described_class.parse_line(vfstab_sample)[:pass].should == "1"
6257
end
6358

6459
it "should extract atboot from sixth field" do
65-
@provider.parse_line(@example_line)[:atboot].should == "no"
60+
described_class.parse_line(vfstab_sample)[:atboot].should == "no"
6661
end
6762

6863
it "should extract options from seventh field" do
69-
@provider.parse_line(@example_line)[:options].should == "-"
64+
described_class.parse_line(vfstab_sample)[:options].should == "-"
7065
end
71-
7266
end
7367

7468
describe "on other platforms than Solaris", :if => Facter.value(:osfamily) != 'Solaris' do
75-
76-
before :each do
77-
@example_line = "/dev/vg00/lv01\t/spare \t \t ext3 defaults\t1 2"
78-
end
79-
8069
it "should extract device from the first field" do
81-
@provider.parse_line(@example_line)[:device].should == '/dev/vg00/lv01'
70+
described_class.parse_line(fstab_sample)[:device].should == '/dev/vg00/lv01'
8271
end
8372

8473
it "should extract name from second field" do
85-
@provider.parse_line(@example_line)[:name].should == "/spare"
74+
described_class.parse_line(fstab_sample)[:name].should == "/spare"
8675
end
8776

8877
it "should extract fstype from third field" do
89-
@provider.parse_line(@example_line)[:fstype].should == "ext3"
78+
described_class.parse_line(fstab_sample)[:fstype].should == "ext3"
9079
end
9180

9281
it "should extract options from fourth field" do
93-
@provider.parse_line(@example_line)[:options].should == "defaults"
82+
described_class.parse_line(fstab_sample)[:options].should == "defaults"
9483
end
9584

9685
it "should extract dump from fifth field" do
97-
@provider.parse_line(@example_line)[:dump].should == "1"
86+
described_class.parse_line(fstab_sample)[:dump].should == "1"
9887
end
9988

10089
it "should extract options from sixth field" do
101-
@provider.parse_line(@example_line)[:pass].should == "2"
90+
described_class.parse_line(fstab_sample)[:pass].should == "2"
10291
end
103-
10492
end
10593

10694
end
10795

10896
describe "mountinstances" do
10997
it "should get name from mountoutput found on Solaris" do
11098
Facter.stubs(:value).with(:osfamily).returns 'Solaris'
111-
@provider.stubs(:mountcmd).returns(File.read(my_fixture('solaris.mount')))
112-
mounts = @provider.mountinstances
99+
described_class.stubs(:mountcmd).returns(File.read(my_fixture('solaris.mount')))
100+
mounts = described_class.mountinstances
113101
mounts.size.should == 6
114102
mounts[0].should == { :name => '/', :mounted => :yes }
115103
mounts[1].should == { :name => '/proc', :mounted => :yes }
@@ -121,8 +109,8 @@
121109

122110
it "should get name from mountoutput found on HP-UX" do
123111
Facter.stubs(:value).with(:osfamily).returns 'HP-UX'
124-
@provider.stubs(:mountcmd).returns(File.read(my_fixture('hpux.mount')))
125-
mounts = @provider.mountinstances
112+
described_class.stubs(:mountcmd).returns(File.read(my_fixture('hpux.mount')))
113+
mounts = described_class.mountinstances
126114
mounts.size.should == 17
127115
mounts[0].should == { :name => '/', :mounted => :yes }
128116
mounts[1].should == { :name => '/devices', :mounted => :yes }
@@ -145,8 +133,8 @@
145133

146134
it "should get name from mountoutput found on Darwin" do
147135
Facter.stubs(:value).with(:osfamily).returns 'Darwin'
148-
@provider.stubs(:mountcmd).returns(File.read(my_fixture('darwin.mount')))
149-
mounts = @provider.mountinstances
136+
described_class.stubs(:mountcmd).returns(File.read(my_fixture('darwin.mount')))
137+
mounts = described_class.mountinstances
150138
mounts.size.should == 6
151139
mounts[0].should == { :name => '/', :mounted => :yes }
152140
mounts[1].should == { :name => '/dev', :mounted => :yes }
@@ -158,8 +146,8 @@
158146

159147
it "should get name from mountoutput found on Linux" do
160148
Facter.stubs(:value).with(:osfamily).returns 'Gentoo'
161-
@provider.stubs(:mountcmd).returns(File.read(my_fixture('linux.mount')))
162-
mounts = @provider.mountinstances
149+
described_class.stubs(:mountcmd).returns(File.read(my_fixture('linux.mount')))
150+
mounts = described_class.mountinstances
163151
mounts[0].should == { :name => '/', :mounted => :yes }
164152
mounts[1].should == { :name => '/lib64/rc/init.d', :mounted => :yes }
165153
mounts[2].should == { :name => '/sys', :mounted => :yes }
@@ -169,8 +157,8 @@
169157

170158
it "should get name from mountoutput found on AIX" do
171159
Facter.stubs(:value).with(:osfamily).returns 'AIX'
172-
@provider.stubs(:mountcmd).returns(File.read(my_fixture('aix.mount')))
173-
mounts = @provider.mountinstances
160+
described_class.stubs(:mountcmd).returns(File.read(my_fixture('aix.mount')))
161+
mounts = described_class.mountinstances
174162
mounts[0].should == { :name => '/', :mounted => :yes }
175163
mounts[1].should == { :name => '/tmp', :mounted => :yes }
176164
mounts[2].should == { :name => '/home', :mounted => :yes }
@@ -179,8 +167,8 @@
179167
end
180168

181169
it "should raise an error if a line is not understandable" do
182-
@provider.stubs(:mountcmd).returns("bazinga!")
183-
lambda { @provider.mountinstances }.should raise_error Puppet::Error
170+
described_class.stubs(:mountcmd).returns("bazinga!")
171+
expect { described_class.mountinstances }.to raise_error Puppet::Error, 'Could not understand line bazinga! from mount output'
184172
end
185173

186174
end
@@ -203,16 +191,16 @@
203191
# Stub the mount output to our fixture.
204192
begin
205193
mount = my_fixture(platform + '.mount')
206-
@provider.stubs(:mountcmd).returns File.read(mount)
194+
described_class.stubs(:mountcmd).returns File.read(mount)
207195
rescue
208196
pending "is #{platform}.mount missing at this point?"
209197
end
210198

211199
# Note: we have to stub default_target before creating resources
212200
# because it is used by Puppet::Type::Mount.new to populate the
213201
# :target property.
214-
@provider.stubs(:default_target).returns fstab
215-
@retrieve = @provider.instances.collect { |prov| {:name => prov.get(:name), :ensure => prov.get(:ensure)}}
202+
described_class.stubs(:default_target).returns fstab
203+
@retrieve = described_class.instances.collect { |prov| {:name => prov.get(:name), :ensure => prov.get(:ensure)}}
216204
end
217205

218206
# Following mountpoint are present in all fstabs/mountoutputs
@@ -246,15 +234,15 @@
246234
# Stub the mount output to our fixture.
247235
begin
248236
mount = my_fixture(platform + '.mount')
249-
@provider.stubs(:mountcmd).returns File.read(mount)
237+
described_class.stubs(:mountcmd).returns File.read(mount)
250238
rescue
251239
pending "is #{platform}.mount missing at this point?"
252240
end
253241

254242
# Note: we have to stub default_target before creating resources
255243
# because it is used by Puppet::Type::Mount.new to populate the
256244
# :target property.
257-
@provider.stubs(:default_target).returns fstab
245+
described_class.stubs(:default_target).returns fstab
258246

259247
@res_ghost = Puppet::Type::Mount.new(:name => '/ghost') # in no fake fstab
260248
@res_mounted = Puppet::Type::Mount.new(:name => '/') # in every fake fstab
@@ -270,24 +258,24 @@
270258

271259
it "should set :ensure to :unmounted if found in fstab but not mounted" do
272260
pending("Solaris:Unable to stub Operating System Fact at runtime", :if => Facter.value(:osfamily) == "Solaris")
273-
@provider.prefetch(@resource_hash)
261+
described_class.prefetch(@resource_hash)
274262
@res_unmounted.provider.get(:ensure).should == :unmounted
275263
end
276264

277265
it "should set :ensure to :ghost if not found in fstab but mounted" do
278266
pending("Solaris:Unable to stub Operating System Fact at runtime", :if => Facter.value(:osfamily) == "Solaris")
279-
@provider.prefetch(@resource_hash)
267+
described_class.prefetch(@resource_hash)
280268
@res_ghost.provider.get(:ensure).should == :ghost
281269
end
282270

283271
it "should set :ensure to :mounted if found in fstab and mounted" do
284272
pending("Solaris:Unable to stub Operating System Fact at runtime", :if => Facter.value(:osfamily) == "Solaris")
285-
@provider.prefetch(@resource_hash)
273+
described_class.prefetch(@resource_hash)
286274
@res_mounted.provider.get(:ensure).should == :mounted
287275
end
288276

289277
it "should set :ensure to :absent if not found in fstab and not mounted" do
290-
@provider.prefetch(@resource_hash)
278+
described_class.prefetch(@resource_hash)
291279
@res_absent.provider.get(:ensure).should == :absent
292280
end
293281
end

0 commit comments

Comments
 (0)