puppet 3.7.5 → 3.8.1

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 (108) hide show
  1. checksums.yaml +4 -4
  2. data/ext/build_defaults.yaml +5 -5
  3. data/lib/hiera/puppet_function.rb +15 -4
  4. data/lib/puppet.rb +5 -2
  5. data/lib/puppet/application/agent.rb +5 -0
  6. data/lib/puppet/application/apply.rb +5 -0
  7. data/lib/puppet/application/device.rb +8 -3
  8. data/lib/puppet/application/master.rb +5 -0
  9. data/lib/puppet/defaults.rb +8 -0
  10. data/lib/puppet/error.rb +27 -1
  11. data/lib/puppet/file_system.rb +13 -0
  12. data/lib/puppet/file_system/file19windows.rb +8 -0
  13. data/lib/puppet/file_system/file_impl.rb +4 -0
  14. data/lib/puppet/file_system/memory_impl.rb +4 -0
  15. data/lib/puppet/functions.rb +25 -3
  16. data/lib/puppet/functions/defined.rb +130 -0
  17. data/lib/puppet/functions/hiera_include.rb +1 -1
  18. data/lib/puppet/node/environment.rb +4 -0
  19. data/lib/puppet/parser/compiler.rb +5 -2
  20. data/lib/puppet/parser/functions/defined.rb +26 -1
  21. data/lib/puppet/parser/functions/file.rb +3 -1
  22. data/lib/puppet/parser/templatewrapper.rb +2 -1
  23. data/lib/puppet/pops.rb +5 -0
  24. data/lib/puppet/pops/evaluator/access_operator.rb +25 -5
  25. data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -11
  26. data/lib/puppet/pops/evaluator/compare_operator.rb +43 -0
  27. data/lib/puppet/pops/evaluator/evaluator_impl.rb +43 -28
  28. data/lib/puppet/pops/evaluator/runtime3_support.rb +9 -5
  29. data/lib/puppet/pops/functions/dispatch.rb +6 -1
  30. data/lib/puppet/pops/issue_reporter.rb +42 -16
  31. data/lib/puppet/pops/issues.rb +96 -0
  32. data/lib/puppet/pops/loader/module_loaders.rb +3 -1
  33. data/lib/puppet/pops/loaders.rb +6 -4
  34. data/lib/puppet/pops/migration/migration_checker.rb +45 -0
  35. data/lib/puppet/pops/model/factory.rb +1 -1
  36. data/lib/puppet/pops/model/model_meta.rb +1 -1
  37. data/lib/puppet/pops/parser/egrammar.ra +1 -1
  38. data/lib/puppet/pops/parser/eparser.rb +1 -1
  39. data/lib/puppet/pops/parser/epp_support.rb +18 -9
  40. data/lib/puppet/pops/parser/evaluating_parser.rb +7 -1
  41. data/lib/puppet/pops/parser/heredoc_support.rb +12 -11
  42. data/lib/puppet/pops/parser/interpolation_support.rb +7 -1
  43. data/lib/puppet/pops/parser/lexer2.rb +8 -8
  44. data/lib/puppet/pops/parser/lexer_support.rb +46 -20
  45. data/lib/puppet/pops/parser/parser_support.rb +11 -14
  46. data/lib/puppet/pops/parser/slurp_support.rb +22 -6
  47. data/lib/puppet/pops/types/type_calculator.rb +156 -55
  48. data/lib/puppet/pops/types/type_factory.rb +67 -14
  49. data/lib/puppet/pops/types/type_parser.rb +22 -13
  50. data/lib/puppet/pops/types/types.rb +21 -3
  51. data/lib/puppet/pops/types/types_meta.rb +13 -2
  52. data/lib/puppet/pops/validation.rb +25 -2
  53. data/lib/puppet/pops/validation/checker4_0.rb +25 -5
  54. data/lib/puppet/provider/group/windows_adsi.rb +18 -6
  55. data/lib/puppet/provider/mount/parsed.rb +145 -2
  56. data/lib/puppet/provider/package/pip.rb +4 -5
  57. data/lib/puppet/provider/package/zypper.rb +17 -7
  58. data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +35 -10
  59. data/lib/puppet/provider/service/init.rb +7 -0
  60. data/lib/puppet/provider/user/windows_adsi.rb +8 -1
  61. data/lib/puppet/provider/zpool/zpool.rb +7 -2
  62. data/lib/puppet/resource.rb +1 -1
  63. data/lib/puppet/type/group.rb +1 -1
  64. data/lib/puppet/type/mount.rb +14 -3
  65. data/lib/puppet/type/scheduled_task.rb +21 -6
  66. data/lib/puppet/util/log.rb +50 -8
  67. data/lib/puppet/util/log/destinations.rb +23 -2
  68. data/lib/puppet/util/logging.rb +37 -1
  69. data/lib/puppet/util/windows/adsi.rb +36 -11
  70. data/lib/puppet/version.rb +1 -1
  71. data/spec/fixtures/unit/provider/mount/parsed/aix.filesystems +93 -85
  72. data/spec/fixtures/unit/provider/mount/parsed/aix.mount +11 -7
  73. data/spec/integration/parser/collector_spec.rb +7 -0
  74. data/spec/integration/parser/future_compiler_spec.rb +9 -0
  75. data/spec/integration/parser/resource_expressions_spec.rb +3 -0
  76. data/spec/unit/file_system_spec.rb +38 -0
  77. data/spec/unit/functions/defined_spec.rb +291 -0
  78. data/spec/unit/functions/hiera_spec.rb +8 -6
  79. data/spec/unit/functions4_spec.rb +97 -2
  80. data/spec/unit/parser/functions/file_spec.rb +8 -2
  81. data/spec/unit/parser/functions/template_spec.rb +1 -1
  82. data/spec/unit/parser/templatewrapper_spec.rb +1 -1
  83. data/spec/unit/pops/evaluator/access_ops_spec.rb +19 -0
  84. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +61 -8
  85. data/spec/unit/pops/issues_spec.rb +16 -16
  86. data/spec/unit/pops/loaders/module_loaders_spec.rb +5 -0
  87. data/spec/unit/pops/migration_spec.rb +180 -0
  88. data/spec/unit/pops/parser/lexer2_spec.rb +152 -1
  89. data/spec/unit/pops/parser/parse_heredoc_spec.rb +26 -0
  90. data/spec/unit/pops/transformer/transform_calls_spec.rb +1 -1
  91. data/spec/unit/pops/types/type_calculator_spec.rb +204 -11
  92. data/spec/unit/pops/validation_spec.rb +66 -0
  93. data/spec/unit/provider/group/windows_adsi_spec.rb +65 -1
  94. data/spec/unit/provider/mount/parsed_spec.rb +31 -5
  95. data/spec/unit/provider/package/pip_spec.rb +19 -7
  96. data/spec/unit/provider/package/zypper_spec.rb +25 -14
  97. data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +312 -70
  98. data/spec/unit/provider/service/base_spec.rb +42 -31
  99. data/spec/unit/provider/service/freebsd_spec.rb +1 -0
  100. data/spec/unit/provider/service/gentoo_spec.rb +1 -0
  101. data/spec/unit/provider/service/init_spec.rb +18 -0
  102. data/spec/unit/provider/service/openbsd_spec.rb +1 -0
  103. data/spec/unit/provider/service/redhat_spec.rb +1 -0
  104. data/spec/unit/provider/user/windows_adsi_spec.rb +21 -0
  105. data/spec/unit/provider/zpool/zpool_spec.rb +47 -10
  106. data/spec/unit/util/log_spec.rb +113 -0
  107. data/spec/unit/util/windows/adsi_spec.rb +106 -26
  108. metadata +10 -2
@@ -10,68 +10,79 @@ describe "base service provider" do
10
10
 
11
11
  let :type do Puppet::Type.type(:service) end
12
12
  let :provider do type.provider(:base) end
13
+ let(:executor) { Puppet::Util::Execution }
14
+ let(:start_command) { 'start' }
15
+ let(:status_command) { 'status' }
16
+ let(:stop_command) { 'stop' }
13
17
 
14
18
  subject { provider }
15
19
 
16
20
  context "basic operations" do
17
- # Cross-platform file interactions. Fun times.
18
- Ruby = File.join(RbConfig::CONFIG["bindir"],
19
- RbConfig::CONFIG["RUBY_INSTALL_NAME"] +
20
- RbConfig::CONFIG["EXEEXT"])
21
-
22
- Start = [Ruby, '-rfileutils', '-e', 'FileUtils.touch(ARGV[0])']
23
- Status = [Ruby, '-e' 'exit File.file?(ARGV[0])']
24
- Stop = [Ruby, '-e', 'File.exist?(ARGV[0]) and File.unlink(ARGV[0])']
25
-
26
- let :flag do tmpfile('base-service-test') end
27
-
28
21
  subject do
29
- type.new(:name => "test", :provider => :base,
30
- :start => Start + [flag],
31
- :status => Status + [flag],
32
- :stop => Stop + [flag]
22
+ type.new(
23
+ :name => "test",
24
+ :provider => :base,
25
+ :start => start_command,
26
+ :status => status_command,
27
+ :stop => stop_command
33
28
  ).provider
34
29
  end
35
30
 
36
- before :each do
37
- Puppet::FileSystem.unlink(flag) if Puppet::FileSystem.exist?(flag)
31
+ def execute_command(command, options)
32
+ case command.shift
33
+ when start_command
34
+ expect(options[:failonfail]).to eq(true)
35
+ raise(Puppet::ExecutionFailure, 'failed to start') if @running
36
+ @running = true
37
+ return 'started'
38
+ when status_command
39
+ expect(options[:failonfail]).to eq(false)
40
+ $CHILD_STATUS.expects(:exitstatus).at_least(1).returns(@running ? 0 : 1)
41
+ return @running ? 'running' : 'not running'
42
+ when stop_command
43
+ expect(options[:failonfail]).to eq(true)
44
+ raise(Puppet::ExecutionFailure, 'failed to stop') unless @running
45
+ @running = false
46
+ return 'stopped'
47
+ else
48
+ raise "unexpected command execution: #{command}"
49
+ end
38
50
  end
39
51
 
40
- it { should be }
52
+ before :each do
53
+ @running = false
54
+ executor.expects(:execute).at_least(1).with { |command, options| execute_command(command, options) }
55
+ end
41
56
 
42
57
  it "should invoke the start command if not running" do
43
- File.should_not be_file(flag)
44
58
  subject.start
45
- File.should be_file(flag)
46
59
  end
47
60
 
48
61
  it "should be stopped before being started" do
49
- subject.status.should == :stopped
62
+ expect(subject.status).to eq(:stopped)
50
63
  end
51
64
 
52
65
  it "should be running after being started" do
53
66
  subject.start
54
- subject.status.should == :running
67
+ expect(subject.status).to eq(:running)
55
68
  end
56
69
 
57
70
  it "should invoke the stop command when asked" do
58
71
  subject.start
59
- subject.status.should == :running
72
+ expect(subject.status).to eq(:running)
60
73
  subject.stop
61
- subject.status.should == :stopped
62
- File.should_not be_file(flag)
74
+ expect(subject.status).to eq(:stopped)
63
75
  end
64
76
 
65
- it "should start again even if already running" do
66
- subject.start
67
- subject.expects(:ucommand).with(:start)
77
+ it "should raise an error if started twice" do
68
78
  subject.start
79
+ expect {subject.start }.to raise_error(Puppet::Error, 'Could not start Service[test]: failed to start')
69
80
  end
70
81
 
71
- it "should stop again even if already stopped" do
72
- subject.stop
73
- subject.expects(:ucommand).with(:stop)
82
+ it "should raise an error if stopped twice" do
83
+ subject.start
74
84
  subject.stop
85
+ expect {subject.stop }.to raise_error(Puppet::Error, 'Could not stop Service[test]: failed to stop')
75
86
  end
76
87
  end
77
88
  end
@@ -7,6 +7,7 @@ describe provider_class do
7
7
  before :each do
8
8
  @provider = provider_class.new
9
9
  @provider.stubs(:initscript)
10
+ Facter.stubs(:value).with(:osfamily).returns 'FreeBSD'
10
11
  end
11
12
 
12
13
  it "should correctly parse rcvar for FreeBSD < 7" do
@@ -9,6 +9,7 @@ describe Puppet::Type.type(:service).provider(:gentoo) do
9
9
  FileTest.stubs(:file?).with('/sbin/rc-update').returns true
10
10
  FileTest.stubs(:executable?).with('/sbin/rc-update').returns true
11
11
  Facter.stubs(:value).with(:operatingsystem).returns 'Gentoo'
12
+ Facter.stubs(:value).with(:osfamily).returns 'Gentoo'
12
13
 
13
14
  # The initprovider (parent of the gentoo provider) does a stat call
14
15
  # before it even tries to execute an initscript. We use sshd in all the
@@ -208,5 +208,23 @@ describe Puppet::Type.type(:service).provider(:init) do
208
208
  provider.restart
209
209
  end
210
210
  end
211
+
212
+ describe "when starting a service on Solaris" do
213
+ it "should use ctrun" do
214
+ Facter.stubs(:value).with(:osfamily).returns 'Solaris'
215
+ provider.expects(:execute).with('/usr/bin/ctrun -l none /service/path/myservice start', {:failonfail => true, :override_locale => false, :squelch => false, :combine => true}).returns("")
216
+ $CHILD_STATUS.stubs(:exitstatus).returns(0)
217
+ provider.start
218
+ end
219
+ end
220
+
221
+ describe "when starting a service on RedHat" do
222
+ it "should not use ctrun" do
223
+ Facter.stubs(:value).with(:osfamily).returns 'RedHat'
224
+ provider.expects(:execute).with(['/service/path/myservice', :start], {:failonfail => true, :override_locale => false, :squelch => false, :combine => true}).returns("")
225
+ $CHILD_STATUS.stubs(:exitstatus).returns(0)
226
+ provider.start
227
+ end
228
+ end
211
229
  end
212
230
  end
@@ -10,6 +10,7 @@ describe provider_class do
10
10
  before :each do
11
11
  Puppet::Type.type(:service).stubs(:defaultprovider).returns described_class
12
12
  Facter.stubs(:value).with(:operatingsystem).returns :openbsd
13
+ Facter.stubs(:value).with(:osfamily).returns 'OpenBSD'
13
14
  end
14
15
 
15
16
  let :rcscripts do
@@ -20,6 +20,7 @@ describe provider_class, :as_platform => :posix do
20
20
  FileTest.stubs(:file?).with('/sbin/service').returns true
21
21
  FileTest.stubs(:executable?).with('/sbin/service').returns true
22
22
  Facter.stubs(:value).with(:operatingsystem).returns('CentOS')
23
+ Facter.stubs(:value).with(:osfamily).returns 'RedHat'
23
24
  end
24
25
 
25
26
  osfamily = [ 'RedHat', 'Suse' ]
@@ -119,6 +119,19 @@ describe Puppet::Type.type(:user).provider(:windows_adsi), :if => Puppet.feature
119
119
  expect{ provider.create }.to raise_error( Puppet::Error,
120
120
  /Cannot create user if group 'testuser' exists./ )
121
121
  end
122
+
123
+ it "should fail with an actionable message when trying to create an active directory user" do
124
+ resource[:name] = 'DOMAIN\testdomainuser'
125
+ Puppet::Util::Windows::ADSI::Group.expects(:exists?).with(resource[:name]).returns(false)
126
+ connection.expects(:Create)
127
+ connection.expects(:SetPassword)
128
+ connection.expects(:SetInfo).raises( WIN32OLERuntimeError.new("(in OLE method `SetInfo': )\n OLE error code:8007089A in Active Directory\n The specified username is invalid.\r\n\n HRESULT error code:0x80020009\n Exception occurred."))
129
+
130
+ expect{ provider.create }.to raise_error(
131
+ Puppet::Error,
132
+ /not able to create\/delete domain users/
133
+ )
134
+ end
122
135
  end
123
136
 
124
137
  it 'should be able to test whether a user exists' do
@@ -136,6 +149,14 @@ describe Puppet::Type.type(:user).provider(:windows_adsi), :if => Puppet.feature
136
149
  provider.delete
137
150
  end
138
151
 
152
+ it 'should not run commit on a deleted user' do
153
+ connection.expects(:Delete).with('user', 'testuser')
154
+ connection.expects(:SetInfo).never
155
+
156
+ provider.delete
157
+ provider.flush
158
+ end
159
+
139
160
  it 'should delete the profile if managehome is set' do
140
161
  resource[:managehome] = true
141
162
 
@@ -171,20 +171,57 @@ describe Puppet::Type.type(:zpool).provider(:zpool) do
171
171
  end
172
172
 
173
173
  context '#create' do
174
- before do
175
- resource[:disk] = "disk1"
174
+ context "when creating disks for a zpool" do
175
+ before do
176
+ resource[:disk] = "disk1"
177
+ end
178
+
179
+ it "should call create with the build_vdevs value" do
180
+ provider.expects(:zpool).with(:create, name, 'disk1')
181
+ provider.create
182
+ end
183
+
184
+ it "should call create with the 'spares' and 'log' values" do
185
+ resource[:spare] = ['value1']
186
+ resource[:log] = ['value2']
187
+ provider.expects(:zpool).with(:create, name, 'disk1', 'spare', 'value1', 'log', 'value2')
188
+ provider.create
189
+ end
176
190
  end
177
191
 
178
- it "should call create with the build_vdevs value" do
179
- provider.expects(:zpool).with(:create, name, 'disk1')
180
- provider.create
192
+ context "when creating mirrors for a zpool" do
193
+ it "executes 'create' for a single group of mirrored devices" do
194
+ resource[:mirror] = ["disk1 disk2"]
195
+ provider.expects(:zpool).with(:create, name, 'mirror', 'disk1', 'disk2')
196
+ provider.create
197
+ end
198
+
199
+ it "repeats the 'mirror' keyword between groups of mirrored devices" do
200
+ resource[:mirror] = ["disk1 disk2", "disk3 disk4"]
201
+ provider.expects(:zpool).with(:create, name, 'mirror', 'disk1', 'disk2', 'mirror', 'disk3', 'disk4')
202
+ provider.create
203
+ end
181
204
  end
182
205
 
183
- it "should call create with the 'spares' and 'log' values" do
184
- resource[:spare] = ['value1']
185
- resource[:log] = ['value2']
186
- provider.expects(:zpool).with(:create, name, 'disk1', 'spare', 'value1', 'log', 'value2')
187
- provider.create
206
+ describe "when creating raidz for a zpool" do
207
+ it "executes 'create' for a single raidz group" do
208
+ resource[:raidz] = ["disk1 disk2"]
209
+ provider.expects(:zpool).with(:create, name, 'raidz1', 'disk1', 'disk2')
210
+ provider.create
211
+ end
212
+
213
+ it "execute 'create' for a single raidz2 group" do
214
+ resource[:raidz] = ["disk1 disk2"]
215
+ resource[:raid_parity] = 'raidz2'
216
+ provider.expects(:zpool).with(:create, name, 'raidz2', 'disk1', 'disk2')
217
+ provider.create
218
+ end
219
+
220
+ it "repeats the 'raidz1' keyword between each group of raidz devices" do
221
+ resource[:raidz] = ["disk1 disk2", "disk3 disk4"]
222
+ provider.expects(:zpool).with(:create, name, 'raidz1', 'disk1', 'disk2', 'raidz1', 'disk3', 'disk4')
223
+ provider.create
224
+ end
188
225
  end
189
226
  end
190
227
 
@@ -93,7 +93,120 @@ describe Puppet::Util::Log do
93
93
 
94
94
  expect(logs.collect(&:message)).to include("Inner block", "Outer block")
95
95
  end
96
+
97
+ it 'includes backtrace for RuntimeError in log message when trace is enabled' do
98
+ logs = []
99
+ destination = Puppet::Test::LogCollector.new(logs)
100
+
101
+ Puppet::Util::Log.newdestination(destination)
102
+ Puppet::Util::Log.with_destination(destination) do
103
+ begin
104
+ raise RuntimeError, 'Oops'
105
+ rescue RuntimeError => e
106
+ Puppet.log_exception(e, :default, :trace => true)
107
+ end
108
+ end
109
+ expect(logs.size).to eq(1)
110
+ log = logs[0]
111
+ expect(log.message).to match('/log_spec.rb')
112
+ expect(log.backtrace).to be_nil
113
+ end
114
+
115
+ it 'excludes backtrace for RuntimeError in log message when trace is disabled' do
116
+ logs = []
117
+ destination = Puppet::Test::LogCollector.new(logs)
118
+
119
+ Puppet::Util::Log.newdestination(destination)
120
+ Puppet::Util::Log.with_destination(destination) do
121
+ begin
122
+ raise RuntimeError, 'Oops'
123
+ rescue RuntimeError => e
124
+ Puppet.log_exception(e)
125
+ end
126
+ end
127
+ expect(logs.size).to eq(1)
128
+ log = logs[0]
129
+ expect(log.message).to_not match('/log_spec.rb')
130
+ expect(log.backtrace).to be_nil
131
+ end
132
+
133
+ it "backtrace is Array in 'backtrace' and excluded from 'message' when logging ParseErrorWithIssue with trace enabled" do
134
+ logs = []
135
+ destination = Puppet::Test::LogCollector.new(logs)
136
+
137
+ Puppet::Util::Log.newdestination(destination)
138
+ Puppet::Util::Log.with_destination(destination) do
139
+ begin
140
+ raise Puppet::ParseErrorWithIssue.new('Oops', '/tmp/test.pp', 30, 15, nil, :SYNTAX_ERROR)
141
+ rescue RuntimeError => e
142
+ Puppet.log_exception(e, :default, :trace => true)
143
+ end
144
+ end
145
+ expect(logs.size).to eq(1)
146
+ log = logs[0]
147
+ expect(log.message).to_not match('/log_spec.rb')
148
+ expect(log.backtrace).to be_a(Array)
149
+ end
150
+
151
+ it "backtrace is excluded when logging ParseErrorWithIssue with trace disabled" do
152
+ logs = []
153
+ destination = Puppet::Test::LogCollector.new(logs)
154
+
155
+ Puppet::Util::Log.newdestination(destination)
156
+ Puppet::Util::Log.with_destination(destination) do
157
+ begin
158
+ raise Puppet::ParseErrorWithIssue.new('Oops', '/tmp/test.pp', 30, 15, nil, :SYNTAX_ERROR)
159
+ rescue RuntimeError => e
160
+ Puppet.log_exception(e)
161
+ end
162
+ end
163
+ expect(logs.size).to eq(1)
164
+ log = logs[0]
165
+ expect(log.message).to_not match('/log_spec.rb')
166
+ expect(log.backtrace).to be_nil
167
+ end
168
+
169
+ it 'includes position details for ParseError in log message' do
170
+ logs = []
171
+ destination = Puppet::Test::LogCollector.new(logs)
172
+
173
+ Puppet::Util::Log.newdestination(destination)
174
+ Puppet::Util::Log.with_destination(destination) do
175
+ begin
176
+ raise Puppet::ParseError.new('Oops', '/tmp/test.pp', 30, 15)
177
+ rescue RuntimeError => e
178
+ Puppet.log_exception(e)
179
+ end
180
+ end
181
+ expect(logs.size).to eq(1)
182
+ log = logs[0]
183
+ expect(log.message).to match(/ at \/tmp\/test\.pp:30:15/)
184
+ expect(log.message).to be(log.to_s)
185
+ end
186
+
187
+ it 'excludes position details for ParseErrorWithIssue from log message' do
188
+ logs = []
189
+ destination = Puppet::Test::LogCollector.new(logs)
190
+
191
+ Puppet::Util::Log.newdestination(destination)
192
+ Puppet::Util::Log.with_destination(destination) do
193
+ begin
194
+ raise Puppet::ParseErrorWithIssue.new('Oops', '/tmp/test.pp', 30, 15, nil, :SYNTAX_ERROR)
195
+ rescue RuntimeError => e
196
+ Puppet.log_exception(e)
197
+ end
198
+ end
199
+ expect(logs.size).to eq(1)
200
+ log = logs[0]
201
+ expect(log.message).to_not match(/ at \/tmp\/test\.pp:30:15/)
202
+ expect(log.to_s).to match(/ at \/tmp\/test\.pp:30:15/)
203
+ expect(log.issue_code).to eq(:SYNTAX_ERROR)
204
+ expect(log.file).to eq('/tmp/test.pp')
205
+ expect(log.line).to eq(30)
206
+ expect(log.pos).to eq(15)
207
+ end
96
208
  end
209
+
97
210
  describe Puppet::Util::Log::DestConsole do
98
211
  before do
99
212
  @console = Puppet::Util::Log::DestConsole.new
@@ -315,38 +315,118 @@ describe Puppet::Util::Windows::ADSI, :if => Puppet.features.microsoft_windows?
315
315
  group.members.should =~ names
316
316
  end
317
317
 
318
- it "should be able to add a list of users to a group" do
319
- names = ['DOMAIN\user1', 'user2']
320
- sids = [
321
- stub(:account => 'user1', :domain => 'DOMAIN'),
322
- stub(:account => 'user2', :domain => 'testcomputername'),
323
- stub(:account => 'user3', :domain => 'DOMAIN2'),
324
- ]
318
+ context "calling .set_members" do
319
+ it "should set the members of a group to only desired_members when inclusive" do
320
+ names = ['DOMAIN\user1', 'user2']
321
+ sids = [
322
+ stub(:account => 'user1', :domain => 'DOMAIN'),
323
+ stub(:account => 'user2', :domain => 'testcomputername'),
324
+ stub(:account => 'user3', :domain => 'DOMAIN2'),
325
+ ]
325
326
 
326
- # use stubbed objectSid on member to return stubbed SID
327
- Puppet::Util::Windows::SID.expects(:octet_string_to_sid_object).with([0]).returns(sids[0])
328
- Puppet::Util::Windows::SID.expects(:octet_string_to_sid_object).with([1]).returns(sids[1])
327
+ # use stubbed objectSid on member to return stubbed SID
328
+ Puppet::Util::Windows::SID.expects(:octet_string_to_sid_object).with([0]).returns(sids[0])
329
+ Puppet::Util::Windows::SID.expects(:octet_string_to_sid_object).with([1]).returns(sids[1])
329
330
 
330
- Puppet::Util::Windows::SID.expects(:name_to_sid_object).with('user2').returns(sids[1])
331
- Puppet::Util::Windows::SID.expects(:name_to_sid_object).with('DOMAIN2\user3').returns(sids[2])
331
+ Puppet::Util::Windows::SID.expects(:name_to_sid_object).with('user2').returns(sids[1])
332
+ Puppet::Util::Windows::SID.expects(:name_to_sid_object).with('DOMAIN2\user3').returns(sids[2])
332
333
 
333
- Puppet::Util::Windows::ADSI.expects(:sid_uri).with(sids[0]).returns("WinNT://DOMAIN/user1,user")
334
- Puppet::Util::Windows::ADSI.expects(:sid_uri).with(sids[2]).returns("WinNT://DOMAIN2/user3,user")
334
+ Puppet::Util::Windows::ADSI.expects(:sid_uri).with(sids[0]).returns("WinNT://DOMAIN/user1,user")
335
+ Puppet::Util::Windows::ADSI.expects(:sid_uri).with(sids[2]).returns("WinNT://DOMAIN2/user3,user")
335
336
 
336
- members = names.each_with_index.map{|n,i| stub(:Name => n, :objectSID => [i])}
337
- adsi_group.expects(:Members).returns members
337
+ members = names.each_with_index.map{|n,i| stub(:Name => n, :objectSID => [i])}
338
+ adsi_group.expects(:Members).returns members
338
339
 
339
- adsi_group.expects(:Remove).with('WinNT://DOMAIN/user1,user')
340
- adsi_group.expects(:Add).with('WinNT://DOMAIN2/user3,user')
340
+ adsi_group.expects(:Remove).with('WinNT://DOMAIN/user1,user')
341
+ adsi_group.expects(:Add).with('WinNT://DOMAIN2/user3,user')
341
342
 
342
- group.set_members(['user2', 'DOMAIN2\user3'])
343
- end
343
+ group.set_members(['user2', 'DOMAIN2\user3'])
344
+ end
344
345
 
345
- it "should raise an error when a username does not resolve to a SID" do
346
- expect {
347
- adsi_group.expects(:Members).returns []
348
- group.set_members(['foobar'])
349
- }.to raise_error(Puppet::Error, /Could not resolve username: foobar/)
346
+ it "should add the desired_members to an existing group when not inclusive" do
347
+ names = ['DOMAIN\user1', 'user2']
348
+ sids = [
349
+ stub(:account => 'user1', :domain => 'DOMAIN'),
350
+ stub(:account => 'user2', :domain => 'testcomputername'),
351
+ stub(:account => 'user3', :domain => 'DOMAIN2'),
352
+ ]
353
+
354
+ # use stubbed objectSid on member to return stubbed SID
355
+ Puppet::Util::Windows::SID.expects(:octet_string_to_sid_object).with([0]).returns(sids[0])
356
+ Puppet::Util::Windows::SID.expects(:octet_string_to_sid_object).with([1]).returns(sids[1])
357
+
358
+ Puppet::Util::Windows::SID.expects(:name_to_sid_object).with('user2').returns(sids[1])
359
+ Puppet::Util::Windows::SID.expects(:name_to_sid_object).with('DOMAIN2\user3').returns(sids[2])
360
+
361
+ Puppet::Util::Windows::ADSI.expects(:sid_uri).with(sids[2]).returns("WinNT://DOMAIN2/user3,user")
362
+
363
+ members = names.each_with_index.map{|n,i| stub(:Name => n, :objectSID => [i])}
364
+ adsi_group.expects(:Members).returns members
365
+
366
+ adsi_group.expects(:Remove).with('WinNT://DOMAIN/user1,user').never
367
+
368
+ adsi_group.expects(:Add).with('WinNT://DOMAIN2/user3,user')
369
+
370
+ group.set_members(['user2', 'DOMAIN2\user3'],false)
371
+ end
372
+
373
+ it "should return immediately when desired_members is nil" do
374
+ adsi_group.expects(:Members).never
375
+
376
+ adsi_group.expects(:Remove).never
377
+ adsi_group.expects(:Add).never
378
+
379
+ group.set_members(nil)
380
+ end
381
+
382
+ it "should remove all members when desired_members is empty and inclusive" do
383
+ names = ['DOMAIN\user1', 'user2']
384
+ sids = [
385
+ stub(:account => 'user1', :domain => 'DOMAIN'),
386
+ stub(:account => 'user2', :domain => 'testcomputername')
387
+ ]
388
+
389
+ # use stubbed objectSid on member to return stubbed SID
390
+ Puppet::Util::Windows::SID.expects(:octet_string_to_sid_object).with([0]).returns(sids[0])
391
+ Puppet::Util::Windows::SID.expects(:octet_string_to_sid_object).with([1]).returns(sids[1])
392
+
393
+ Puppet::Util::Windows::ADSI.expects(:sid_uri).with(sids[0]).returns("WinNT://DOMAIN/user1,user")
394
+ Puppet::Util::Windows::ADSI.expects(:sid_uri).with(sids[1]).returns("WinNT://testcomputername/user2,user")
395
+
396
+ members = names.each_with_index.map{|n,i| stub(:Name => n, :objectSID => [i])}
397
+ adsi_group.expects(:Members).returns members
398
+
399
+ adsi_group.expects(:Remove).with('WinNT://DOMAIN/user1,user')
400
+ adsi_group.expects(:Remove).with('WinNT://testcomputername/user2,user')
401
+
402
+ group.set_members([])
403
+ end
404
+
405
+ it "should do nothing when desired_members is empty and not inclusive" do
406
+ names = ['DOMAIN\user1', 'user2']
407
+ sids = [
408
+ stub(:account => 'user1', :domain => 'DOMAIN'),
409
+ stub(:account => 'user2', :domain => 'testcomputername')
410
+ ]
411
+ # use stubbed objectSid on member to return stubbed SID
412
+ Puppet::Util::Windows::SID.expects(:octet_string_to_sid_object).with([0]).returns(sids[0])
413
+ Puppet::Util::Windows::SID.expects(:octet_string_to_sid_object).with([1]).returns(sids[1])
414
+
415
+ members = names.each_with_index.map{|n,i| stub(:Name => n, :objectSID => [i])}
416
+ adsi_group.expects(:Members).returns members
417
+
418
+ adsi_group.expects(:Remove).never
419
+ adsi_group.expects(:Add).never
420
+
421
+ group.set_members([],false)
422
+ end
423
+
424
+ it "should raise an error when a username does not resolve to a SID" do
425
+ expect {
426
+ adsi_group.expects(:Members).returns []
427
+ group.set_members(['foobar'])
428
+ }.to raise_error(Puppet::Error, /Could not resolve username: foobar/)
429
+ end
350
430
  end
351
431
 
352
432
  it "should generate the correct URI" do
@@ -426,7 +506,7 @@ describe Puppet::Util::Windows::ADSI, :if => Puppet.features.microsoft_windows?
426
506
  end
427
507
 
428
508
  it "should warn on 2003" do
429
- connection.expects(:Delete).raises(RuntimeError,
509
+ connection.expects(:Delete).raises(WIN32OLERuntimeError,
430
510
  "Delete (WIN32OLERuntimeError)
431
511
  OLE error code:80041010 in SWbemServicesEx
432
512
  Invalid class