~ubuntu-branches/ubuntu/quantal/puppet/quantal

« back to all changes in this revision

Viewing changes to spec/unit/type/user_spec.rb

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-07-14 01:56:30 UTC
  • mfrom: (1.1.29) (3.1.43 sid)
  • Revision ID: package-import@ubuntu.com-20120714015630-ntj41rkvkq4zph4y
Tags: 2.7.18-1ubuntu1
* Resynchronise with Debian. (LP: #1023931) Remaining changes:
  - debian/puppetmaster-passenger.postinst: Make sure we error if puppet
    config print doesn't work
  - debian/puppetmaster-passenger.postinst: Ensure upgrades from
    <= 2.7.11-1 fixup passenger apache configuration.
* Dropped upstreamed patches:
  - debian/patches/CVE-2012-1906_CVE-2012-1986_to_CVE-2012-1989.patch
  - debian/patches/puppet-12844
  - debian/patches/2.7.17-Puppet-July-2012-CVE-fixes.patch
* Drop Build-Depends on ruby-rspec (in universe):
  - debian/control: remove ruby-rspec from Build-Depends
  - debian/patches/no-rspec.patch: make Rakefile work anyway if rspec
    isn't installed so we can use it in debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/env rspec
2
2
require 'spec_helper'
3
3
 
4
 
user = Puppet::Type.type(:user)
5
 
 
6
 
describe user do
7
 
  before do
8
 
    ENV["PATH"] += File::PATH_SEPARATOR + "/usr/sbin" unless ENV["PATH"].split(File::PATH_SEPARATOR).include?("/usr/sbin")
9
 
    @provider = stub 'provider'
10
 
    @resource = stub 'resource', :resource => nil, :provider => @provider, :line => nil, :file => nil
11
 
  end
12
 
 
13
 
  it "should have a default provider inheriting from Puppet::Provider" do
14
 
    user.defaultprovider.ancestors.should be_include(Puppet::Provider)
 
4
describe Puppet::Type.type(:user) do
 
5
  before :each do
 
6
    @provider_class = described_class.provide(:simple) do
 
7
      has_features :manages_expiry, :manages_password_age, :manages_passwords, :manages_solaris_rbac
 
8
      mk_resource_methods
 
9
      def create; end
 
10
      def delete; end
 
11
      def exists?; get(:ensure) != :absent; end
 
12
      def flush; end
 
13
      def self.instances; []; end
 
14
    end
 
15
    described_class.stubs(:defaultprovider).returns @provider_class
15
16
  end
16
17
 
17
18
  it "should be able to create a instance" do
18
 
    user.new(:name => "foo").should_not be_nil
 
19
    described_class.new(:name => "foo").should_not be_nil
19
20
  end
20
21
 
21
22
  it "should have an allows_duplicates feature" do
22
 
    user.provider_feature(:allows_duplicates).should_not be_nil
 
23
    described_class.provider_feature(:allows_duplicates).should_not be_nil
23
24
  end
24
25
 
25
26
  it "should have an manages_homedir feature" do
26
 
    user.provider_feature(:manages_homedir).should_not be_nil
 
27
    described_class.provider_feature(:manages_homedir).should_not be_nil
27
28
  end
28
29
 
29
30
  it "should have an manages_passwords feature" do
30
 
    user.provider_feature(:manages_passwords).should_not be_nil
 
31
    described_class.provider_feature(:manages_passwords).should_not be_nil
31
32
  end
32
33
 
33
34
  it "should have a manages_solaris_rbac feature" do
34
 
    user.provider_feature(:manages_solaris_rbac).should_not be_nil
 
35
    described_class.provider_feature(:manages_solaris_rbac).should_not be_nil
35
36
  end
36
37
 
37
38
  it "should have a manages_expiry feature" do
38
 
    user.provider_feature(:manages_expiry).should_not be_nil
 
39
    described_class.provider_feature(:manages_expiry).should_not be_nil
39
40
  end
40
41
 
41
42
  it "should have a manages_password_age feature" do
42
 
    user.provider_feature(:manages_password_age).should_not be_nil
 
43
    described_class.provider_feature(:manages_password_age).should_not be_nil
43
44
  end
44
45
 
45
46
  it "should have a system_users feature" do
46
 
    user.provider_feature(:system_users).should_not be_nil
 
47
    described_class.provider_feature(:system_users).should_not be_nil
47
48
  end
48
49
 
49
50
  describe "instances" do
50
 
    it "should have a valid provider" do
51
 
      user.new(:name => "foo").provider.class.ancestors.should be_include(Puppet::Provider)
52
 
    end
53
 
 
54
51
    it "should delegate existence questions to its provider" do
55
 
      instance = user.new(:name => "foo")
56
 
      instance.provider.expects(:exists?).returns "eh"
57
 
      instance.exists?.should == "eh"
 
52
      @provider = @provider_class.new(:name => 'foo', :ensure => :absent)
 
53
      instance = described_class.new(:name => "foo", :provider => @provider)
 
54
      instance.exists?.should == false
 
55
 
 
56
      @provider.set(:ensure => :present)
 
57
      instance.exists?.should == true
58
58
    end
59
59
  end
60
60
 
62
62
 
63
63
  properties.each do |property|
64
64
    it "should have a #{property} property" do
65
 
      user.attrclass(property).ancestors.should be_include(Puppet::Property)
 
65
      described_class.attrclass(property).ancestors.should be_include(Puppet::Property)
66
66
    end
67
67
 
68
68
    it "should have documentation for its #{property} property" do
69
 
      user.attrclass(property).doc.should be_instance_of(String)
 
69
      described_class.attrclass(property).doc.should be_instance_of(String)
70
70
    end
71
71
  end
72
72
 
74
74
 
75
75
  list_properties.each do |property|
76
76
    it "should have a list '#{property}'" do
77
 
      user.attrclass(property).ancestors.should be_include(Puppet::Property::List)
 
77
      described_class.attrclass(property).ancestors.should be_include(Puppet::Property::List)
78
78
    end
79
79
  end
80
80
 
81
81
  it "should have an ordered list 'profiles'" do
82
 
    user.attrclass(:profiles).ancestors.should be_include(Puppet::Property::OrderedList)
 
82
    described_class.attrclass(:profiles).ancestors.should be_include(Puppet::Property::OrderedList)
83
83
  end
84
84
 
85
85
  it "should have key values 'keys'" do
86
 
    user.attrclass(:keys).ancestors.should be_include(Puppet::Property::KeyValue)
 
86
    described_class.attrclass(:keys).ancestors.should be_include(Puppet::Property::KeyValue)
87
87
  end
88
88
 
89
89
  describe "when retrieving all current values" do
90
90
    before do
91
 
      @user = user.new(:name => "foo", :uid => 10)
 
91
      @provider = @provider_class.new(:name => 'foo', :ensure => :present, :uid => 15, :gid => 15)
 
92
      @user = described_class.new(:name => "foo", :uid => 10, :provider => @provider)
92
93
    end
93
94
 
94
95
    it "should return a hash containing values for all set properties" do
95
96
      @user[:gid] = 10
96
 
      @user.property(:ensure).expects(:retrieve).returns :present
97
 
      @user.property(:uid).expects(:retrieve).returns 15
98
 
      @user.property(:gid).expects(:retrieve).returns 15
99
97
      values = @user.retrieve
100
98
      [@user.property(:uid), @user.property(:gid)].each { |property| values.should be_include(property) }
101
99
    end
107
105
    end
108
106
 
109
107
    it "should include the result of retrieving each property's current value if the user is present" do
110
 
      @user.property(:ensure).expects(:retrieve).returns :present
111
 
      @user.property(:uid).expects(:retrieve).returns 15
112
108
      @user.retrieve[@user.property(:uid)].should == 15
113
109
    end
114
110
  end
115
111
 
116
112
  describe "when managing the ensure property" do
117
 
    before do
118
 
      @ensure = user.attrclass(:ensure).new(:resource => @resource)
119
 
    end
120
 
 
121
113
    it "should support a :present value" do
122
 
      lambda { @ensure.should = :present }.should_not raise_error
 
114
      lambda { described_class.new(:name => 'foo', :ensure => :present) }.should_not raise_error
123
115
    end
124
116
 
125
117
    it "should support an :absent value" do
126
 
      lambda { @ensure.should = :absent }.should_not raise_error
 
118
      lambda { described_class.new(:name => 'foo', :ensure => :absent) }.should_not raise_error
127
119
    end
128
120
 
129
121
    it "should call :create on the provider when asked to sync to the :present state" do
 
122
      @provider = @provider_class.new(:name => 'foo', :ensure => :absent)
130
123
      @provider.expects(:create)
131
 
      @ensure.should = :present
132
 
      @ensure.sync
 
124
      described_class.new(:name => 'foo', :ensure => :present, :provider => @provider).parameter(:ensure).sync
133
125
    end
134
126
 
135
127
    it "should call :delete on the provider when asked to sync to the :absent state" do
 
128
      @provider = @provider_class.new(:name => 'foo', :ensure => :present)
136
129
      @provider.expects(:delete)
137
 
      @ensure.should = :absent
138
 
      @ensure.sync
 
130
      described_class.new(:name => 'foo', :ensure => :absent, :provider => @provider).parameter(:ensure).sync
139
131
    end
140
132
 
141
133
    describe "and determining the current state" do
142
134
      it "should return :present when the provider indicates the user exists" do
143
 
        @provider.expects(:exists?).returns true
144
 
        @ensure.retrieve.should == :present
 
135
        @provider = @provider_class.new(:name => 'foo', :ensure => :present)
 
136
        described_class.new(:name => 'foo', :ensure => :absent, :provider => @provider).parameter(:ensure).retrieve.should == :present
145
137
      end
146
138
 
147
139
      it "should return :absent when the provider indicates the user does not exist" do
148
 
        @provider.expects(:exists?).returns false
149
 
        @ensure.retrieve.should == :absent
 
140
        @provider = @provider_class.new(:name => 'foo', :ensure => :absent)
 
141
        described_class.new(:name => 'foo', :ensure => :present, :provider => @provider).parameter(:ensure).retrieve.should == :absent
150
142
      end
151
143
    end
152
144
  end
153
145
 
154
146
  describe "when managing the uid property" do
155
147
    it "should convert number-looking strings into actual numbers" do
156
 
      uid = user.attrclass(:uid).new(:resource => @resource)
157
 
      uid.should = "50"
158
 
      uid.should.must == 50
 
148
      described_class.new(:name => 'foo', :uid => '50')[:uid].should == 50
159
149
    end
160
150
 
161
151
    it "should support UIDs as numbers" do
162
 
      uid = user.attrclass(:uid).new(:resource => @resource)
163
 
      uid.should = 50
164
 
      uid.should.must == 50
 
152
      described_class.new(:name => 'foo', :uid => 50)[:uid].should == 50
165
153
    end
166
154
 
167
 
    it "should :absent as a value" do
168
 
      uid = user.attrclass(:uid).new(:resource => @resource)
169
 
      uid.should = :absent
170
 
      uid.should.must == :absent
 
155
    it "should support :absent as a value" do
 
156
      described_class.new(:name => 'foo', :uid => :absent)[:uid].should == :absent
171
157
    end
172
158
  end
173
159
 
174
160
  describe "when managing the gid" do
175
 
    it "should :absent as a value" do
176
 
      gid = user.attrclass(:gid).new(:resource => @resource)
177
 
      gid.should = :absent
178
 
      gid.should.must == :absent
 
161
    it "should support :absent as a value" do
 
162
      described_class.new(:name => 'foo', :gid => :absent)[:gid].should == :absent
179
163
    end
180
164
 
181
165
    it "should convert number-looking strings into actual numbers" do
182
 
      gid = user.attrclass(:gid).new(:resource => @resource)
183
 
      gid.should = "50"
184
 
      gid.should.must == 50
 
166
      described_class.new(:name => 'foo', :gid => '50')[:gid].should == 50
185
167
    end
186
168
 
187
169
    it "should support GIDs specified as integers" do
188
 
      gid = user.attrclass(:gid).new(:resource => @resource)
189
 
      gid.should = 50
190
 
      gid.should.must == 50
 
170
      described_class.new(:name => 'foo', :gid => 50)[:gid].should == 50
191
171
    end
192
172
 
193
173
    it "should support groups specified by name" do
194
 
      gid = user.attrclass(:gid).new(:resource => @resource)
195
 
      gid.should = "foo"
196
 
      gid.should.must == "foo"
 
174
      described_class.new(:name => 'foo', :gid => 'foo')[:gid].should == 'foo'
197
175
    end
198
176
 
199
177
    describe "when testing whether in sync" do
200
 
      before do
201
 
        @gid = user.attrclass(:gid).new(:resource => @resource, :should => %w{foo bar})
202
 
      end
203
 
 
204
178
      it "should return true if no 'should' values are set" do
205
 
        @gid = user.attrclass(:gid).new(:resource => @resource)
206
 
 
207
 
        @gid.must be_safe_insync(500)
 
179
        # this is currently not the case because gid has no default value, so we would never even
 
180
        # call insync? on that property
 
181
        if param = described_class.new(:name => 'foo').parameter(:gid)
 
182
          param.must be_safe_insync(500)
 
183
        end
208
184
      end
209
185
 
210
186
      it "should return true if any of the specified groups are equal to the current integer" do
211
187
        Puppet::Util.expects(:gid).with("foo").returns 300
212
188
        Puppet::Util.expects(:gid).with("bar").returns 500
213
 
 
214
 
        @gid.must be_safe_insync(500)
 
189
        described_class.new(:name => 'baz', :gid => [ 'foo', 'bar' ]).parameter(:gid).must be_safe_insync(500)
215
190
      end
216
191
 
217
192
      it "should return false if none of the specified groups are equal to the current integer" do
218
193
        Puppet::Util.expects(:gid).with("foo").returns 300
219
194
        Puppet::Util.expects(:gid).with("bar").returns 500
220
 
 
221
 
        @gid.should_not be_safe_insync(700)
 
195
        described_class.new(:name => 'baz', :gid => [ 'foo', 'bar' ]).parameter(:gid).must_not be_safe_insync(700)
222
196
      end
223
197
    end
224
198
 
225
199
    describe "when syncing" do
226
 
      before do
227
 
        @gid = user.attrclass(:gid).new(:resource => @resource, :should => %w{foo bar})
228
 
      end
229
 
 
230
200
      it "should use the first found, specified group as the desired value and send it to the provider" do
231
201
        Puppet::Util.expects(:gid).with("foo").returns nil
232
202
        Puppet::Util.expects(:gid).with("bar").returns 500
233
203
 
 
204
        @provider = @provider_class.new(:name => 'foo')
 
205
        resource = described_class.new(:name => 'foo', :provider => @provider, :gid => [ 'foo', 'bar' ])
 
206
 
234
207
        @provider.expects(:gid=).with 500
235
 
 
236
 
        @gid.sync
237
 
      end
238
 
    end
239
 
  end
 
208
        resource.parameter(:gid).sync
 
209
      end
 
210
    end
 
211
  end
 
212
 
 
213
  describe "when managing groups" do
 
214
    it "should support a singe group" do
 
215
      lambda { described_class.new(:name => 'foo', :groups => 'bar') }.should_not raise_error
 
216
    end
 
217
 
 
218
    it "should support multiple groups as an array" do
 
219
      lambda { described_class.new(:name => 'foo', :groups => [ 'bar' ]) }.should_not raise_error
 
220
      lambda { described_class.new(:name => 'foo', :groups => [ 'bar', 'baz' ]) }.should_not raise_error
 
221
    end
 
222
 
 
223
    it "should not support a comma separated list" do
 
224
      lambda { described_class.new(:name => 'foo', :groups => 'bar,baz') }.should raise_error(Puppet::Error, /Group names must be provided as an array/)
 
225
    end
 
226
 
 
227
    it "should not support an empty string" do
 
228
      lambda { described_class.new(:name => 'foo', :groups => '') }.should raise_error(Puppet::Error, /Group names must not be empty/)
 
229
    end
 
230
 
 
231
    describe "when testing is in sync" do
 
232
 
 
233
      before :each do
 
234
        # the useradd provider uses a single string to represent groups and so does Puppet::Property::List when converting to should values
 
235
        @provider = @provider_class.new(:name => 'foo', :groups => 'a,b,e,f')
 
236
      end
 
237
 
 
238
      it "should not care about order" do
 
239
        @property = described_class.new(:name => 'foo', :groups => [ 'a', 'c', 'b' ]).property(:groups)
 
240
        @property.must be_safe_insync([ 'a', 'b', 'c' ])
 
241
        @property.must be_safe_insync([ 'a', 'c', 'b' ])
 
242
        @property.must be_safe_insync([ 'b', 'a', 'c' ])
 
243
        @property.must be_safe_insync([ 'b', 'c', 'a' ])
 
244
        @property.must be_safe_insync([ 'c', 'a', 'b' ])
 
245
        @property.must be_safe_insync([ 'c', 'b', 'a' ])
 
246
      end
 
247
 
 
248
      it "should merge current value and desired value if membership minimal" do
 
249
        @instance = described_class.new(:name => 'foo', :groups => [ 'a', 'c', 'b' ], :provider => @provider)
 
250
        @instance[:membership] = :minimum
 
251
        @instance[:groups].should == 'a,b,c,e,f'
 
252
      end
 
253
 
 
254
      it "should not treat a subset of groups insync if membership inclusive" do
 
255
        @instance = described_class.new(:name => 'foo', :groups => [ 'a', 'c', 'b' ], :provider => @provider)
 
256
        @instance[:membership] = :inclusive
 
257
        @instance[:groups].should == 'a,b,c'
 
258
      end
 
259
    end
 
260
  end
 
261
 
240
262
 
241
263
  describe "when managing expiry" do
242
 
    before do
243
 
      @expiry = user.attrclass(:expiry).new(:resource => @resource)
244
 
    end
245
 
 
246
264
    it "should fail if given an invalid date" do
247
 
      lambda { @expiry.should = "200-20-20" }.should raise_error(Puppet::Error)
 
265
      lambda { described_class.new(:name => 'foo', :expiry => "200-20-20") }.should raise_error(Puppet::Error, /Expiry dates must be YYYY-MM-DD/)
248
266
    end
249
267
  end
250
268
 
251
269
  describe "when managing minimum password age" do
252
 
    before do
253
 
      @age = user.attrclass(:password_min_age).new(:resource => @resource)
254
 
    end
255
 
 
256
270
    it "should accept a negative minimum age" do
257
 
      expect { @age.should = -1 }.should_not raise_error
 
271
      expect { described_class.new(:name => 'foo', :password_min_age => '-1') }.should_not raise_error
258
272
    end
259
273
 
260
274
    it "should fail with an empty minimum age" do
261
 
      expect { @age.should = '' }.should raise_error(Puppet::Error)
 
275
      expect { described_class.new(:name => 'foo', :password_min_age => '') }.should raise_error(Puppet::Error, /minimum age must be provided as a number/)
262
276
    end
263
277
  end
264
278
 
265
279
  describe "when managing maximum password age" do
266
 
    before do
267
 
      @age = user.attrclass(:password_max_age).new(:resource => @resource)
268
 
    end
269
 
 
270
280
    it "should accept a negative maximum age" do
271
 
      expect { @age.should = -1 }.should_not raise_error
 
281
      expect { described_class.new(:name => 'foo', :password_max_age => '-1') }.should_not raise_error
272
282
    end
273
283
 
274
284
    it "should fail with an empty maximum age" do
275
 
      expect { @age.should = '' }.should raise_error(Puppet::Error)
 
285
      expect { described_class.new(:name => 'foo', :password_max_age => '') }.should raise_error(Puppet::Error, /maximum age must be provided as a number/)
276
286
    end
277
287
  end
278
288
 
279
289
  describe "when managing passwords" do
280
290
    before do
281
 
      @password = user.attrclass(:password).new(:resource => @resource, :should => "mypass")
 
291
      @password = described_class.new(:name => 'foo', :password => 'mypass').parameter(:password)
282
292
    end
283
293
 
284
294
    it "should not include the password in the change log when adding the password" do
298
308
    end
299
309
 
300
310
    it "should fail if a ':' is included in the password" do
301
 
      lambda { @password.should = "some:thing" }.should raise_error(Puppet::Error)
 
311
      lambda { described_class.new(:name => 'foo', :password => "some:thing") }.should raise_error(Puppet::Error, /Passwords cannot include ':'/)
302
312
    end
303
313
 
304
314
    it "should allow the value to be set to :absent" do
305
 
      lambda { @password.should = :absent }.should_not raise_error
 
315
      lambda { described_class.new(:name => 'foo', :password => :absent) }.should_not raise_error
306
316
    end
307
317
  end
308
318
 
309
319
  describe "when manages_solaris_rbac is enabled" do
310
 
    before do
311
 
      @provider.stubs(:satisfies?).returns(false)
312
 
      @provider.expects(:satisfies?).with([:manages_solaris_rbac]).returns(true)
313
 
    end
314
 
 
315
320
    it "should support a :role value for ensure" do
316
 
      @ensure = user.attrclass(:ensure).new(:resource => @resource)
317
 
      lambda { @ensure.should = :role }.should_not raise_error
 
321
      lambda { described_class.new(:name => 'foo', :ensure => :role) }.should_not raise_error
318
322
    end
319
323
  end
320
324
 
321
325
  describe "when user has roles" do
322
 
    before do
323
 
      # To test this feature, we have to support it.
324
 
      user.new(:name => "foo").provider.class.stubs(:feature?).returns(true)
325
 
    end
326
 
 
327
326
    it "should autorequire roles" do
328
 
      testuser = Puppet::Type.type(:user).new(:name => "testuser")
329
 
      testuser.provider.stubs(:send).with(:roles).returns("")
330
 
      testuser[:roles] = "testrole"
331
 
 
332
 
      testrole = Puppet::Type.type(:user).new(:name => "testrole")
 
327
      testuser = described_class.new(:name => "testuser", :roles => ['testrole'] )
 
328
      testrole = described_class.new(:name => "testrole")
333
329
 
334
330
      config = Puppet::Resource::Catalog.new :testing do |conf|
335
331
        [testuser, testrole].each { |resource| conf.add_resource resource }