puppet 3.0.1 → 3.0.2.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (97) hide show
  1. data/Gemfile +17 -3
  2. data/Rakefile +7 -5
  3. data/ext/build_defaults.yaml +1 -1
  4. data/ext/debian/puppet.init +33 -34
  5. data/ext/debian/puppet.logrotate +2 -1
  6. data/ext/debian/puppetmaster.init +1 -2
  7. data/ext/suse/client.init +1 -1
  8. data/ext/suse/puppet.spec +3 -0
  9. data/ext/suse/server.init +1 -1
  10. data/ext/windows/service/daemon.rb +1 -1
  11. data/install.rb +32 -53
  12. data/lib/hiera/backend/puppet_backend.rb +6 -5
  13. data/lib/puppet/agent.rb +3 -3
  14. data/lib/puppet/application/agent.rb +1 -2
  15. data/lib/puppet/application/cert.rb +4 -5
  16. data/lib/puppet/application/kick.rb +3 -0
  17. data/lib/puppet/defaults.rb +15 -2
  18. data/lib/puppet/indirector/exec.rb +1 -1
  19. data/lib/puppet/module_tool/skeleton/templates/generator/manifests/init.pp.erb +1 -1
  20. data/lib/puppet/parser/functions/hiera_include.rb +6 -4
  21. data/lib/puppet/parser/lexer.rb +38 -1
  22. data/lib/puppet/parser/relationship.rb +3 -1
  23. data/lib/puppet/provider.rb +1 -1
  24. data/lib/puppet/provider/augeas/augeas.rb +1 -1
  25. data/lib/puppet/provider/file/windows.rb +10 -29
  26. data/lib/puppet/provider/group/ldap.rb +1 -1
  27. data/lib/puppet/provider/group/windows_adsi.rb +1 -1
  28. data/lib/puppet/provider/ldap.rb +5 -1
  29. data/lib/puppet/provider/macauthorization/macauthorization.rb +2 -6
  30. data/lib/puppet/provider/package/dpkg.rb +8 -12
  31. data/lib/puppet/provider/package/macports.rb +2 -2
  32. data/lib/puppet/provider/package/msi.rb +2 -2
  33. data/lib/puppet/provider/package/sun.rb +1 -1
  34. data/lib/puppet/provider/package/windows.rb +2 -2
  35. data/lib/puppet/provider/package/yum.rb +5 -1
  36. data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +2 -2
  37. data/lib/puppet/provider/service/freebsd.rb +1 -1
  38. data/lib/puppet/provider/user/directoryservice.rb +603 -65
  39. data/lib/puppet/provider/user/windows_adsi.rb +1 -1
  40. data/lib/puppet/provider/zpool/zpool.rb +1 -1
  41. data/lib/puppet/run.rb +2 -1
  42. data/lib/puppet/settings.rb +9 -5
  43. data/lib/puppet/ssl/certificate_authority.rb +2 -0
  44. data/lib/puppet/transaction.rb +1 -1
  45. data/lib/puppet/type/cron.rb +4 -4
  46. data/lib/puppet/type/exec.rb +10 -5
  47. data/lib/puppet/type/file.rb +1 -1
  48. data/lib/puppet/type/service.rb +3 -2
  49. data/lib/puppet/type/user.rb +24 -2
  50. data/lib/puppet/util.rb +3 -6
  51. data/lib/puppet/util/adsi.rb +3 -9
  52. data/lib/puppet/util/diff.rb +1 -1
  53. data/lib/puppet/util/execution.rb +13 -6
  54. data/lib/puppet/util/feature.rb +3 -1
  55. data/lib/puppet/util/log/destinations.rb +12 -16
  56. data/lib/puppet/util/selinux.rb +18 -2
  57. data/lib/puppet/util/windows.rb +1 -0
  58. data/lib/puppet/util/windows/security.rb +2 -39
  59. data/lib/puppet/util/windows/sid.rb +96 -0
  60. data/lib/puppet/version.rb +1 -1
  61. data/spec/integration/util/windows/security_spec.rb +3 -23
  62. data/spec/unit/agent_spec.rb +7 -3
  63. data/spec/unit/application/agent_spec.rb +13 -5
  64. data/spec/unit/daemon_spec.rb +2 -1
  65. data/spec/unit/hiera/backend/puppet_backend_spec.rb +49 -42
  66. data/spec/unit/indirector/exec_spec.rb +8 -6
  67. data/spec/unit/parser/functions/hiera_include_spec.rb +11 -4
  68. data/spec/unit/parser/lexer_spec.rb +120 -8
  69. data/spec/unit/parser/relationship_spec.rb +24 -0
  70. data/spec/unit/provider/file/windows_spec.rb +29 -29
  71. data/spec/unit/provider/group/windows_adsi_spec.rb +2 -2
  72. data/spec/unit/provider/nameservice/directoryservice_spec.rb +1 -1
  73. data/spec/unit/provider/package/dpkg_spec.rb +2 -2
  74. data/spec/unit/provider/package/macports_spec.rb +6 -5
  75. data/spec/unit/provider/package/msi_spec.rb +1 -1
  76. data/spec/unit/provider/package/pacman_spec.rb +1 -1
  77. data/spec/unit/provider/package/rpm_spec.rb +1 -1
  78. data/spec/unit/provider/package/sun_spec.rb +4 -4
  79. data/spec/unit/provider/package/windows_spec.rb +1 -1
  80. data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +14 -11
  81. data/spec/unit/provider/user/directoryservice_spec.rb +943 -0
  82. data/spec/unit/provider/user/ldap_spec.rb +22 -8
  83. data/spec/unit/provider/user/windows_adsi_spec.rb +4 -4
  84. data/spec/unit/provider_spec.rb +1 -1
  85. data/spec/unit/run_spec.rb +1 -1
  86. data/spec/unit/settings_spec.rb +16 -0
  87. data/spec/unit/ssl/certificate_authority_spec.rb +24 -0
  88. data/spec/unit/util/adsi_spec.rb +4 -8
  89. data/spec/unit/util/diff_spec.rb +2 -2
  90. data/spec/unit/util/execution_spec.rb +78 -20
  91. data/spec/unit/util/feature_spec.rb +12 -1
  92. data/spec/unit/util/selinux_spec.rb +20 -0
  93. data/spec/unit/util/windows/sid_spec.rb +100 -0
  94. data/spec/unit/util_spec.rb +17 -0
  95. metadata +71 -48
  96. data/Gemfile.lock +0 -44
  97. data/lib/puppet/provider/interface/base.rb +0 -0
@@ -24,14 +24,6 @@ describe provider_class do
24
24
  provider_class.should be_manages_passwords
25
25
  end
26
26
 
27
- it "should use the ldap group provider to convert group names to numbers" do
28
- provider = provider_class.new(:name => "foo")
29
- Puppet::Type.type(:group).provider(:ldap).expects(:name2id).with("bar").returns 10
30
-
31
- provider.gid = 'bar'
32
- provider.gid.should == 10
33
- end
34
-
35
27
  {:name => "uid",
36
28
  :password => "userPassword",
37
29
  :comment => "cn",
@@ -53,10 +45,13 @@ describe provider_class do
53
45
  end
54
46
 
55
47
  it "should generate the sn as the last field of the cn" do
48
+ Puppet::Type.type(:group).provider(:ldap).expects(:name2id).with(["whatever"]).returns [123]
49
+
56
50
  resource = stub 'resource', :should => %w{whatever}
57
51
  resource.stubs(:should).with(:comment).returns ["Luke Kanies"]
58
52
  resource.stubs(:should).with(:ensure).returns :present
59
53
  instance = provider_class.new(:name => "luke", :ensure => :absent)
54
+
60
55
  instance.stubs(:resource).returns resource
61
56
 
62
57
  @connection.expects(:add).with { |dn, attrs| attrs["sn"] == ["Kanies"] }
@@ -65,8 +60,25 @@ describe provider_class do
65
60
  instance.flush
66
61
  end
67
62
 
63
+ it "should translate a group name to the numeric id" do
64
+ Puppet::Type.type(:group).provider(:ldap).expects(:name2id).with("bar").returns 101
65
+
66
+ resource = stub 'resource', :should => %w{whatever}
67
+ resource.stubs(:should).with(:gid).returns 'bar'
68
+ resource.stubs(:should).with(:ensure).returns :present
69
+ instance = provider_class.new(:name => "luke", :ensure => :absent)
70
+ instance.stubs(:resource).returns resource
71
+
72
+ @connection.expects(:add).with { |dn, attrs| attrs["gidNumber"] == ["101"] }
73
+
74
+ instance.create
75
+ instance.flush
76
+ end
77
+
68
78
  describe "with no uid specified" do
69
79
  it "should pick the first available UID after the largest existing UID" do
80
+ Puppet::Type.type(:group).provider(:ldap).expects(:name2id).with(["whatever"]).returns [123]
81
+
70
82
  low = {:name=>["luke"], :shell=>:absent, :uid=>["600"], :home=>["/h"], :gid=>["1000"], :password=>["blah"], :comment=>["l k"]}
71
83
  high = {:name=>["testing"], :shell=>:absent, :uid=>["640"], :home=>["/h"], :gid=>["1000"], :password=>["blah"], :comment=>["t u"]}
72
84
  provider_class.manager.expects(:search).returns([low, high])
@@ -84,6 +96,8 @@ describe provider_class do
84
96
  end
85
97
 
86
98
  it "should pick 501 of no users exist" do
99
+ Puppet::Type.type(:group).provider(:ldap).expects(:name2id).with(["whatever"]).returns [123]
100
+
87
101
  provider_class.manager.expects(:search).returns nil
88
102
 
89
103
  resource = stub 'resource', :should => %w{whatever}
@@ -136,11 +136,11 @@ describe Puppet::Type.type(:user).provider(:windows_adsi) do
136
136
  provider.delete
137
137
  end
138
138
 
139
- it 'should delete the profile if managehome is set' do
139
+ it 'should delete the profile if managehome is set', :if => Puppet.features.microsoft_windows? do
140
140
  resource[:managehome] = true
141
141
 
142
142
  sid = 'S-A-B-C'
143
- Puppet::Util::ADSI.expects(:sid_for_account).with('testuser').returns(sid)
143
+ Puppet::Util::Windows::Security.expects(:name_to_sid).with('testuser').returns(sid)
144
144
  Puppet::Util::ADSI::UserProfile.expects(:delete).with(sid)
145
145
  connection.expects(:Delete).with('user', 'testuser')
146
146
 
@@ -153,8 +153,8 @@ describe Puppet::Type.type(:user).provider(:windows_adsi) do
153
153
  provider.flush
154
154
  end
155
155
 
156
- it "should return the user's SID as uid" do
157
- Puppet::Util::ADSI.expects(:sid_for_account).with('testuser').returns('S-1-5-21-1362942247-2130103807-3279964888-1111')
156
+ it "should return the user's SID as uid", :if => Puppet.features.microsoft_windows? do
157
+ Puppet::Util::Windows::Security.expects(:name_to_sid).with('testuser').returns('S-1-5-21-1362942247-2130103807-3279964888-1111')
158
158
 
159
159
  provider.uid.should == 'S-1-5-21-1362942247-2130103807-3279964888-1111'
160
160
  end
@@ -657,7 +657,7 @@ describe Puppet::Provider do
657
657
  end
658
658
 
659
659
  def allow_creation_of(command, environment = {})
660
- Puppet::Provider::Command.stubs(:new).with(command.name, command.executable, Puppet::Util, Puppet::Util::Execution, { :custom_environment => environment }).returns(command)
660
+ Puppet::Provider::Command.stubs(:new).with(command.name, command.executable, Puppet::Util, Puppet::Util::Execution, { :failonfail => true, :combine => true, :custom_environment => environment }).returns(command)
661
661
  end
662
662
 
663
663
  def file_exists_and_is_executable(path)
@@ -14,7 +14,7 @@ describe Puppet::Run do
14
14
 
15
15
  it "should use a configurer agent as its agent" do
16
16
  agent = mock 'agent'
17
- Puppet::Agent.expects(:new).with(Puppet::Configurer).returns agent
17
+ Puppet::Agent.expects(:new).with(Puppet::Configurer, anything).returns agent
18
18
 
19
19
  @runner.agent.should equal(agent)
20
20
  end
@@ -1539,6 +1539,22 @@ describe Puppet::Settings do
1539
1539
  it "should transform boolean option to no- form" do
1540
1540
  Puppet::Settings.clean_opt("--[no-]option", false).should == ["--no-option", false]
1541
1541
  end
1542
+
1543
+ it "should set preferred run mode from --run_mode <foo> string without error" do
1544
+ args = ["--run_mode", "master"]
1545
+ settings.expects(:handlearg).with("--run_mode", "master").never
1546
+ expect { settings.send(:parse_global_options, args) } .to_not raise_error
1547
+ Puppet.settings.preferred_run_mode.should == :master
1548
+ args.empty?.should == true
1549
+ end
1550
+
1551
+ it "should set preferred run mode from --run_mode=<foo> string without error" do
1552
+ args = ["--run_mode=master"]
1553
+ settings.expects(:handlearg).with("--run_mode", "master").never
1554
+ expect { settings.send(:parse_global_options, args) } .to_not raise_error
1555
+ Puppet.settings.preferred_run_mode.should == :master
1556
+ args.empty?.should == true
1557
+ end
1542
1558
  end
1543
1559
 
1544
1560
  describe "default_certname" do
@@ -905,6 +905,30 @@ describe Puppet::SSL::CertificateAuthority do
905
905
  @ca.crl.expects(:revoke).with { |serial, key| serial == 16 }
906
906
  @ca.revoke('host')
907
907
  end
908
+
909
+ context "revocation by serial number (#16798)" do
910
+ it "revokes when given a lower case hexadecimal formatted string" do
911
+ @ca.crl.expects(:revoke).with { |serial, key| serial == 15 }
912
+ Puppet::SSL::Certificate.indirection.expects(:find).with("0xf").returns nil
913
+
914
+ @ca.revoke('0xf')
915
+ end
916
+
917
+ it "revokes when given an upper case hexadecimal formatted string" do
918
+ @ca.crl.expects(:revoke).with { |serial, key| serial == 15 }
919
+ Puppet::SSL::Certificate.indirection.expects(:find).with("0xF").returns nil
920
+
921
+ @ca.revoke('0xF')
922
+ end
923
+
924
+ it "handles very large serial numbers" do
925
+ bighex = '0x4000000000000000000000000000000000000000'
926
+ @ca.crl.expects(:revoke).with { |serial, key| serial == 2**(159-1) }
927
+ Puppet::SSL::Certificate.indirection.expects(:find).with(bighex).returns nil
928
+
929
+ @ca.revoke(bighex)
930
+ end
931
+ end
908
932
  end
909
933
 
910
934
  it "should be able to generate a complete new SSL host" do
@@ -28,25 +28,21 @@ describe Puppet::Util::ADSI do
28
28
  Puppet::Util::ADSI.computer_uri.should == "WinNT://testcomputername"
29
29
  end
30
30
 
31
- describe ".sid_for_account" do
31
+ describe ".sid_for_account", :if => Puppet.features.microsoft_windows? do
32
32
  it "should return nil if the account does not exist" do
33
- connection.expects(:execquery).returns([])
33
+ Puppet::Util::Windows::Security.expects(:name_to_sid).with('foobar').returns nil
34
34
 
35
35
  Puppet::Util::ADSI.sid_for_account('foobar').should be_nil
36
36
  end
37
37
 
38
38
  it "should return a SID for a passed user or group name" do
39
- Puppet::Util::ADSI.expects(:execquery).with(
40
- "SELECT Sid from Win32_Account WHERE Name = 'testers' AND LocalAccount = true"
41
- ).returns([stub('acct_id', :Sid => 'S-1-5-32-547')])
39
+ Puppet::Util::Windows::Security.expects(:name_to_sid).with('testers').returns 'S-1-5-32-547'
42
40
 
43
41
  Puppet::Util::ADSI.sid_for_account('testers').should == 'S-1-5-32-547'
44
42
  end
45
43
 
46
44
  it "should return a SID for a passed fully-qualified user or group name" do
47
- Puppet::Util::ADSI.expects(:execquery).with(
48
- "SELECT Sid from Win32_Account WHERE Name = 'testers' AND Domain = 'MACHINE' AND LocalAccount = true"
49
- ).returns([stub('acct_id', :Sid => 'S-1-5-32-547')])
45
+ Puppet::Util::Windows::Security.expects(:name_to_sid).with('MACHINE\testers').returns 'S-1-5-32-547'
50
46
 
51
47
  Puppet::Util::ADSI.sid_for_account('MACHINE\testers').should == 'S-1-5-32-547'
52
48
  end
@@ -9,7 +9,7 @@ describe Puppet::Util::Diff do
9
9
  Puppet[:diff] = 'foo'
10
10
  Puppet[:diff_args] = 'bar'
11
11
 
12
- Puppet::Util::Execution.expects(:execute).with(['foo', 'bar', 'a', 'b'], {:failonfail => false}).returns('baz')
12
+ Puppet::Util::Execution.expects(:execute).with(['foo', 'bar', 'a', 'b'], {:failonfail => false, :combine => false}).returns('baz')
13
13
  subject.diff('a', 'b').should == 'baz'
14
14
  end
15
15
 
@@ -17,7 +17,7 @@ describe Puppet::Util::Diff do
17
17
  Puppet[:diff] = 'foo'
18
18
  Puppet[:diff_args] = ''
19
19
 
20
- Puppet::Util::Execution.expects(:execute).with(['foo', 'a', 'b'], {:failonfail => false}).returns('baz')
20
+ Puppet::Util::Execution.expects(:execute).with(['foo', 'a', 'b'], {:failonfail => false, :combine => false}).returns('baz')
21
21
  subject.diff('a', 'b').should == 'baz'
22
22
  end
23
23
 
@@ -3,8 +3,6 @@ require 'spec_helper'
3
3
 
4
4
  describe Puppet::Util::Execution do
5
5
  include Puppet::Util::Execution
6
-
7
-
8
6
  # utility method to help deal with some windows vs. unix differences
9
7
  def process_status(exitstatus)
10
8
  return exitstatus if Puppet.features.microsoft_windows?
@@ -20,7 +18,6 @@ describe Puppet::Util::Execution do
20
18
  Puppet::Util::Execution.send(:execute_windows, command, arguments, stdin, stdout, stderr)
21
19
  end
22
20
 
23
-
24
21
  describe "execution methods" do
25
22
  let(:pid) { 5501 }
26
23
  let(:process_handle) { 0xDEADBEEF }
@@ -254,6 +251,50 @@ describe Puppet::Util::Execution do
254
251
 
255
252
  Puppet::Util::Execution.execute('test command', :squelch => false, :combine => false)
256
253
  end
254
+
255
+ it "should combine stdout and stderr if combine is true" do
256
+ outfile = Tempfile.new('stdout')
257
+ Tempfile.stubs(:new).returns(outfile)
258
+
259
+ Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
260
+ stdout.path == outfile.path and stderr.path == outfile.path
261
+ end.returns(rval)
262
+
263
+ Puppet::Util::Execution.execute('test command', :combine => true)
264
+ end
265
+
266
+ it "should default combine to true when no options are specified" do
267
+ outfile = Tempfile.new('stdout')
268
+ Tempfile.stubs(:new).returns(outfile)
269
+
270
+ Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
271
+ stdout.path == outfile.path and stderr.path == outfile.path
272
+ end.returns(rval)
273
+
274
+ Puppet::Util::Execution.execute('test command')
275
+ end
276
+
277
+ it "should default combine to false when options are specified, but combine is not" do
278
+ outfile = Tempfile.new('stdout')
279
+ Tempfile.stubs(:new).returns(outfile)
280
+
281
+ Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
282
+ stdout.path == outfile.path and stderr.path == null_file
283
+ end.returns(rval)
284
+
285
+ Puppet::Util::Execution.execute('test command', :failonfail => false)
286
+ end
287
+
288
+ it "should default combine to false when an empty hash of options is specified" do
289
+ outfile = Tempfile.new('stdout')
290
+ Tempfile.stubs(:new).returns(outfile)
291
+
292
+ Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
293
+ stdout.path == outfile.path and stderr.path == null_file
294
+ end.returns(rval)
295
+
296
+ Puppet::Util::Execution.execute('test command', {})
297
+ end
257
298
  end
258
299
  end
259
300
 
@@ -483,41 +524,60 @@ describe Puppet::Util::Execution do
483
524
  Tempfile.stubs(:new).returns(stdout)
484
525
  file = File.new(stdout.path, 'r')
485
526
 
486
- expect {
487
- Puppet::Util.execute('test command')
488
- }.to_not raise_error
527
+ Puppet::Util.execute('test command')
489
528
  end
490
529
 
491
530
  it "should raise an error if failonfail is true and the child failed" do
492
531
  stub_process_wait(1)
493
532
 
494
533
  expect {
495
- Puppet::Util::Execution.execute('fail command', :failonfail => true)
534
+ subject.execute('fail command', :failonfail => true)
496
535
  }.to raise_error(Puppet::ExecutionFailure, /Execution of 'fail command' returned 1/)
497
536
  end
498
537
 
499
538
  it "should not raise an error if failonfail is false and the child failed" do
500
539
  stub_process_wait(1)
501
540
 
502
- expect {
503
- Puppet::Util::Execution.execute('fail command', :failonfail => false)
504
- }.not_to raise_error
541
+ subject.execute('fail command', :failonfail => false)
505
542
  end
506
543
 
507
544
  it "should not raise an error if failonfail is true and the child succeeded" do
508
- expect {
509
- Puppet::Util::Execution.execute('fail command', :failonfail => true)
510
- }.not_to raise_error
545
+ stub_process_wait(0)
546
+
547
+ subject.execute('fail command', :failonfail => true)
548
+ end
549
+
550
+ it "should not raise an error if failonfail is false and the child succeeded" do
551
+ stub_process_wait(0)
552
+
553
+ subject.execute('fail command', :failonfail => false)
511
554
  end
512
555
 
513
- it "should respect default values for args that aren't overridden if a partial arg list is passed in" do
556
+ it "should default failonfail to true when no options are specified" do
514
557
  stub_process_wait(1)
558
+
515
559
  expect {
516
- # here we are passing in a non-nil value for "arguments", but we aren't specifying a value for
517
- # :failonfail. We expect it to be set to its normal default value (true).
518
- Puppet::Util::Execution.execute('fail command', { :squelch => true })
560
+ subject.execute('fail command')
519
561
  }.to raise_error(Puppet::ExecutionFailure, /Execution of 'fail command' returned 1/)
520
562
  end
563
+
564
+ it "should default failonfail to false when options are specified, but failonfail is not" do
565
+ stub_process_wait(1)
566
+
567
+ subject.execute('fail command', { :combine => true })
568
+ end
569
+
570
+ it "should default failonfail to false when an empty hash of options is specified" do
571
+ stub_process_wait(1)
572
+
573
+ subject.execute('fail command', {})
574
+ end
575
+
576
+ it "should raise an error if a nil option is specified" do
577
+ expect {
578
+ Puppet::Util::Execution.execute('fail command', nil)
579
+ }.to raise_error(TypeError, /can\'t convert nil into Hash/)
580
+ end
521
581
  end
522
582
  end
523
583
 
@@ -544,9 +604,7 @@ describe Puppet::Util::Execution do
544
604
  it "should not fail if asked not to fail, and the child does" do
545
605
  Puppet::Util::Execution.stubs(:open).returns('error message')
546
606
  $CHILD_STATUS.stubs(:==).with(0).returns(false)
547
- expect do
548
- Puppet::Util::Execution.execpipe('echo hello', false).should == 'error message'
549
- end.not_to raise_error
607
+ Puppet::Util::Execution.execpipe('echo hello', false).should == 'error message'
550
608
  end
551
609
  end
552
610
  end
@@ -39,7 +39,7 @@ describe Puppet::Util::Feature do
39
39
  @features.should be_available
40
40
  end
41
41
 
42
- it "should cache the results of a feature load" do
42
+ it "should cache the results of a feature load via code block" do
43
43
  $loaded_feature = 0
44
44
  @features.add(:myfeature) { $loaded_feature += 1 }
45
45
  @features.myfeature?
@@ -78,4 +78,15 @@ describe Puppet::Util::Feature do
78
78
 
79
79
  @features.should_not be_myfeature
80
80
  end
81
+
82
+ it "should change the feature to be present when its libraries become available" do
83
+ @features.add(:myfeature, :libs => %w{foo bar})
84
+ @features.expects(:require).twice().with("foo").raises(LoadError).then.returns(nil)
85
+ @features.stubs(:require).with("bar")
86
+
87
+ Puppet.expects(:debug)
88
+
89
+ @features.should_not be_myfeature
90
+ @features.should be_myfeature
91
+ end
81
92
  end
@@ -129,6 +129,26 @@ describe Puppet::Util::SELinux do
129
129
  get_selinux_default_context("/foo").should == "user_u:role_r:type_t:s0"
130
130
  end
131
131
 
132
+ it "handles permission denied errors by issuing a warning" do
133
+ self.stubs(:selinux_support?).returns true
134
+ self.stubs(:selinux_label_support?).returns true
135
+ Selinux.stubs(:matchpathcon).with("/root/chuj", 0).returns(-1)
136
+ self.stubs(:file_lstat).with("/root/chuj").raises(Errno::EACCES, "/root/chuj")
137
+
138
+ self.expects(:warning).with("Could not stat; Permission denied - /root/chuj")
139
+ get_selinux_default_context("/root/chuj").should be_nil
140
+ end
141
+
142
+ it "handles no such file or directory errors by issuing a warning" do
143
+ self.stubs(:selinux_support?).returns true
144
+ self.stubs(:selinux_label_support?).returns true
145
+ Selinux.stubs(:matchpathcon).with("/root/chuj", 0).returns(-1)
146
+ self.stubs(:file_lstat).with("/root/chuj").raises(Errno::ENOENT, "/root/chuj")
147
+
148
+ self.expects(:warning).with("Could not stat; No such file or directory - /root/chuj")
149
+ get_selinux_default_context("/root/chuj").should be_nil
150
+ end
151
+
132
152
  it "should return nil if matchpathcon returns failure" do
133
153
  self.expects(:selinux_support?).returns true
134
154
  fstat = stub 'File::Stat', :mode => 0
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env ruby
2
+ require 'spec_helper'
3
+
4
+ describe "Puppet::Util::Windows::SID", :if => Puppet.features.microsoft_windows? do
5
+ if Puppet.features.microsoft_windows?
6
+ require 'puppet/util/windows'
7
+ class SIDTester
8
+ include Puppet::Util::Windows::SID
9
+ end
10
+ end
11
+
12
+ let(:subject) { SIDTester.new }
13
+ let(:sid) { Win32::Security::SID::LocalSystem }
14
+ let(:invalid_sid) { 'bogus' }
15
+ let(:unknown_sid) { 'S-0-0-0' }
16
+ let(:unknown_name) { 'chewbacca' }
17
+
18
+ context "#name_to_sid" do
19
+ it "should return nil if the account does not exist" do
20
+ subject.name_to_sid(unknown_name).should be_nil
21
+ end
22
+
23
+ it "should accept unqualified account name" do
24
+ subject.name_to_sid('SYSTEM').should == sid
25
+ end
26
+
27
+ it "should be case-insensitive" do
28
+ subject.name_to_sid('SYSTEM').should == subject.name_to_sid('system')
29
+ end
30
+
31
+ it "should accept domain qualified account names" do
32
+ subject.name_to_sid('NT AUTHORITY\SYSTEM').should == sid
33
+ end
34
+
35
+ it "should be the identity function for any sid" do
36
+ subject.name_to_sid(sid).should == sid
37
+ end
38
+ end
39
+
40
+ context "#sid_to_name" do
41
+ it "should return nil if given a sid for an account that doesn't exist" do
42
+ subject.sid_to_name(unknown_sid).should be_nil
43
+ end
44
+
45
+ it "should accept a sid" do
46
+ subject.sid_to_name(sid).should == "NT AUTHORITY\\SYSTEM"
47
+ end
48
+ end
49
+
50
+ context "#sid_ptr_to_string" do
51
+ it "should raise if given an invalid sid" do
52
+ expect {
53
+ subject.sid_ptr_to_string(nil)
54
+ }.to raise_error(Puppet::Error, /Invalid SID/)
55
+ end
56
+
57
+ it "should yield a valid sid pointer" do
58
+ string = nil
59
+ subject.string_to_sid_ptr(sid) do |ptr|
60
+ string = subject.sid_ptr_to_string(ptr)
61
+ end
62
+ string.should == sid
63
+ end
64
+ end
65
+
66
+ context "#string_to_sid_ptr" do
67
+ it "should yield sid_ptr" do
68
+ ptr = nil
69
+ subject.string_to_sid_ptr(sid) do |p|
70
+ ptr = p
71
+ end
72
+ ptr.should_not be_nil
73
+ end
74
+
75
+ it "should raise on an invalid sid" do
76
+ expect {
77
+ subject.string_to_sid_ptr(invalid_sid)
78
+ }.to raise_error(Puppet::Error, /Failed to convert string SID/)
79
+ end
80
+ end
81
+
82
+ context "#valid_sid?" do
83
+ it "should return true for a valid SID" do
84
+ subject.valid_sid?(sid).should be_true
85
+ end
86
+
87
+ it "should return false for an invalid SID" do
88
+ subject.valid_sid?(invalid_sid).should be_false
89
+ end
90
+
91
+ it "should raise if the conversion fails" do
92
+ subject.expects(:string_to_sid_ptr).with(sid).
93
+ raises(Puppet::Util::Windows::Error.new("Failed to convert string SID: #{sid}", Windows::Error::ERROR_ACCESS_DENIED))
94
+
95
+ expect {
96
+ subject.string_to_sid_ptr(sid) {|ptr| }
97
+ }.to raise_error(Puppet::Util::Windows::Error, /Failed to convert string SID: #{sid}/)
98
+ end
99
+ end
100
+ end