puppet 2.6.7 → 2.6.8

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 (80) hide show
  1. data/CHANGELOG +49 -0
  2. data/install.rb +6 -2
  3. data/lib/puppet.rb +1 -1
  4. data/lib/puppet/application.rb +16 -8
  5. data/lib/puppet/application/agent.rb +2 -0
  6. data/lib/puppet/application/apply.rb +3 -0
  7. data/lib/puppet/application/master.rb +1 -1
  8. data/lib/puppet/configurer.rb +10 -1
  9. data/lib/puppet/defaults.rb +9 -0
  10. data/lib/puppet/file_serving/fileset.rb +1 -0
  11. data/lib/puppet/indirector/exec.rb +1 -2
  12. data/lib/puppet/indirector/report/yaml.rb +11 -0
  13. data/lib/puppet/node/environment.rb +1 -1
  14. data/lib/puppet/parameter.rb +2 -0
  15. data/lib/puppet/parameter/path.rb +42 -0
  16. data/lib/puppet/parser/compiler.rb +1 -1
  17. data/lib/puppet/parser/lexer.rb +3 -2
  18. data/lib/puppet/parser/parser_support.rb +0 -1
  19. data/lib/puppet/provider/exec/posix.rb +112 -0
  20. data/lib/puppet/provider/exec/shell.rb +17 -0
  21. data/lib/puppet/provider/group/groupadd.rb +3 -0
  22. data/lib/puppet/provider/nameservice/#directoryservice.rb# +519 -0
  23. data/lib/puppet/provider/package/gem.rb +2 -2
  24. data/lib/puppet/provider/package/macports.rb +106 -0
  25. data/lib/puppet/provider/service/debian.rb +6 -2
  26. data/lib/puppet/rails/inventory_node.rb +5 -0
  27. data/lib/puppet/reference/#providers.rb# +123 -0
  28. data/lib/puppet/resource/type_collection.rb +6 -1
  29. data/lib/puppet/simple_graph.rb +1 -1
  30. data/lib/puppet/transaction.rb +1 -1
  31. data/lib/puppet/transaction/report.rb +28 -10
  32. data/lib/puppet/type/cron.rb +3 -1
  33. data/lib/puppet/type/exec.rb +30 -167
  34. data/lib/puppet/type/file.rb +12 -1
  35. data/lib/puppet/type/file/source.rb +1 -0
  36. data/lib/puppet/type/group.rb +11 -1
  37. data/lib/puppet/type/service.rb +19 -11
  38. data/lib/puppet/util/command_line.rb +15 -12
  39. data/lib/puppet/util/command_line/puppetrun +0 -1
  40. data/lib/puppet/util/loadedfile.rb +1 -5
  41. data/lib/puppet/util/metric.rb +3 -5
  42. data/lib/puppet/util/plugins.rb +82 -0
  43. data/spec/integration/configurer_spec.rb +38 -5
  44. data/spec/integration/transaction_spec.rb +43 -42
  45. data/spec/lib/puppet_spec/verbose.rb +9 -0
  46. data/spec/shared_behaviours/path_parameters.rb +185 -0
  47. data/spec/spec_helper.rb +6 -0
  48. data/spec/unit/application/agent_spec.rb +7 -0
  49. data/spec/unit/application/apply_spec.rb +6 -0
  50. data/spec/unit/application/master_spec.rb +2 -2
  51. data/spec/unit/configurer_spec.rb +48 -0
  52. data/spec/unit/file_serving/fileset_spec.rb +8 -0
  53. data/spec/unit/indirector/certificate_status/#file_spec.rb# +188 -0
  54. data/spec/unit/indirector/exec_spec.rb +2 -3
  55. data/spec/unit/indirector/facts/inventory_active_record_spec.rb +5 -1
  56. data/spec/unit/indirector/report/yaml_spec.rb +38 -0
  57. data/spec/unit/node/environment_spec.rb +15 -14
  58. data/spec/unit/parameter/path_spec.rb +24 -0
  59. data/spec/unit/parser/compiler_spec.rb +1 -2
  60. data/spec/unit/parser/lexer_spec.rb +12 -0
  61. data/spec/unit/provider/exec/posix_spec.rb +120 -0
  62. data/spec/unit/provider/exec/shell_spec.rb +50 -0
  63. data/spec/unit/provider/group/groupadd_spec.rb +11 -1
  64. data/spec/unit/provider/package/gem_spec.rb +11 -1
  65. data/spec/unit/provider/package/macports_spec.rb +122 -0
  66. data/spec/unit/provider/service/debian_spec.rb +14 -2
  67. data/spec/unit/resource/#type_collection_spec.rb# +463 -0
  68. data/spec/unit/resource/type_collection_spec.rb +21 -17
  69. data/spec/unit/transaction/report_spec.rb +13 -2
  70. data/spec/unit/type/cron_spec.rb +466 -18
  71. data/spec/unit/type/exec_spec.rb +633 -106
  72. data/spec/unit/type/file/source_spec.rb +1 -0
  73. data/spec/unit/type/group_spec.rb +8 -1
  74. data/spec/unit/type_spec.rb +1 -1
  75. data/spec/unit/util/loadedfile_spec.rb +7 -0
  76. data/spec/unit/util/rdoc/parser_spec.rb +2 -1
  77. data/tasks/rake/git_workflow.rake +3 -1
  78. data/test/ral/type/exec.rb +87 -176
  79. metadata +21 -5
  80. data/lib/puppet/provider/package/darwinport.rb +0 -86
@@ -1,162 +1,689 @@
1
1
  #!/usr/bin/env ruby
2
-
3
2
  require File.dirname(__FILE__) + '/../../spec_helper'
4
3
 
5
4
  describe Puppet::Type.type(:exec) do
6
-
7
- def create_resource(command, output, exitstatus, returns = 0)
8
- @user_name = 'some_user_name'
5
+ def exec_tester(command, exitstatus = 0, rest = {})
6
+ @user_name = 'some_user_name'
9
7
  @group_name = 'some_group_name'
10
8
  Puppet.features.stubs(:root?).returns(true)
11
- @execer = Puppet::Type.type(:exec).new(:name => command, :path => @example_path, :user => @user_name, :group => @group_name, :returns => returns)
12
9
 
13
- status = stub "process"
14
- status.stubs(:exitstatus).returns(exitstatus)
10
+ output = rest.delete(:output) || ''
11
+ tries = rest[:tries] || 1
12
+
13
+ args = {
14
+ :name => command,
15
+ :path => @example_path,
16
+ :user => @user_name,
17
+ :group => @group_name,
18
+ :logoutput => false,
19
+ :loglevel => :err,
20
+ :returns => 0
21
+ }.merge(rest)
22
+
23
+ exec = Puppet::Type.type(:exec).new(args)
15
24
 
16
- Puppet::Util::SUIDManager.expects(:run_and_capture).with([command], @user_name, @group_name).returns([output, status])
25
+ status = stub "process", :exitstatus => exitstatus
26
+ Puppet::Util::SUIDManager.expects(:run_and_capture).times(tries).
27
+ with([command], @user_name, @group_name).returns([output, status])
28
+
29
+ return exec
17
30
  end
18
31
 
19
- def create_logging_resource(command, output, exitstatus, logoutput, loglevel, returns = 0)
20
- create_resource(command, output, exitstatus, returns)
21
- @execer[:logoutput] = logoutput
22
- @execer[:loglevel] = loglevel
32
+ before do
33
+ @command = Puppet.features.posix? ? '/bin/true whatever' : '"C:/Program Files/something.exe" whatever'
23
34
  end
24
35
 
25
- def expect_output(output, loglevel)
26
- output.split(/\n/).each do |line|
27
- @execer.property(:returns).expects(loglevel).with(line)
36
+ describe "when not stubbing the provider" do
37
+ before do
38
+ @executable = Puppet.features.posix? ? '/bin/true' : 'C:/Program Files/something.exe'
39
+ File.stubs(:exists?).returns false
40
+ File.stubs(:exists?).with(@executable).returns true
41
+ File.stubs(:exists?).with('/bin/false').returns true
42
+ @example_path = Puppet.features.posix? ? %w{/usr/bin /bin} : [ "C:/Program Files/something/bin", "C:/Ruby/bin" ]
43
+ File.stubs(:exists?).with(File.join(@example_path[0],"true")).returns true
44
+ File.stubs(:exists?).with(File.join(@example_path[0],"false")).returns true
45
+ end
46
+
47
+ it "should return :executed_command as its event" do
48
+ resource = Puppet::Type.type(:exec).new :command => @command
49
+ resource.parameter(:returns).event.name.should == :executed_command
50
+ end
51
+
52
+ describe "when execing" do
53
+ it "should use the 'run_and_capture' method to exec" do
54
+ exec_tester("true").refresh.should == :executed_command
55
+ end
56
+
57
+ it "should report a failure" do
58
+ proc { exec_tester('false', 1).refresh }.
59
+ should raise_error(Puppet::Error, /^false returned 1 instead of/)
60
+ end
61
+
62
+ it "should not report a failure if the exit status is specified in a returns array" do
63
+ proc { exec_tester("false", 1, :returns => [0, 1]).refresh }.should_not raise_error
64
+ end
65
+
66
+ it "should report a failure if the exit status is not specified in a returns array" do
67
+ proc { exec_tester('false', 1, :returns => [0, 100]).refresh }.
68
+ should raise_error(Puppet::Error, /^false returned 1 instead of/)
69
+ end
70
+
71
+ it "should log the output on success" do
72
+ output = "output1\noutput2\n"
73
+ exec_tester('false', 0, :output => output, :logoutput => true).refresh
74
+ output.split("\n").each do |line|
75
+ log = @logs.shift
76
+ log.level.should == :err
77
+ log.message.should == line
78
+ end
79
+ end
80
+
81
+ it "should log the output on failure" do
82
+ output = "output1\noutput2\n"
83
+ proc { exec_tester('false', 1, :output => output, :logoutput => true).refresh }.
84
+ should raise_error(Puppet::Error)
85
+
86
+ output.split("\n").each do |line|
87
+ log = @logs.shift
88
+ log.level.should == :err
89
+ log.message.should == line
90
+ end
91
+ end
92
+ end
93
+
94
+ describe "when logoutput=>on_failure is set" do
95
+ it "should log the output on failure" do
96
+ output = "output1\noutput2\n"
97
+ proc { exec_tester('false', 1, :output => output, :logoutput => :on_failure).refresh }.
98
+ should raise_error(Puppet::Error, /^false returned 1 instead of/)
99
+
100
+ output.split("\n").each do |line|
101
+ log = @logs.shift
102
+ log.level.should == :err
103
+ log.message.should == line
104
+ end
105
+ end
106
+
107
+ it "should log the output on failure when returns is specified as an array" do
108
+ output = "output1\noutput2\n"
109
+
110
+ proc {
111
+ exec_tester('false', 1, :output => output, :returns => [0, 100],
112
+ :logoutput => :on_failure).refresh
113
+ }.should raise_error(Puppet::Error, /^false returned 1 instead of/)
114
+
115
+ output.split("\n").each do |line|
116
+ log = @logs.shift
117
+ log.level.should == :err
118
+ log.message.should == line
119
+ end
120
+ end
121
+
122
+ it "shouldn't log the output on success" do
123
+ exec_tester('true', 0, :output => "a\nb\nc\n", :logoutput => :on_failure).refresh
124
+ @logs.should == []
125
+ end
126
+ end
127
+
128
+ it "shouldn't log the output on success when non-zero exit status is in a returns array" do
129
+ exec_tester("true", 100, :output => "a\n", :logoutput => :on_failure, :returns => [1, 100]).refresh
130
+ @logs.should == []
131
+ end
132
+
133
+ describe " when multiple tries are set," do
134
+ it "should repeat the command attempt 'tries' times on failure and produce an error" do
135
+ tries = 5
136
+ resource = exec_tester("false", 1, :tries => tries, :try_sleep => 0)
137
+ proc { resource.refresh }.should raise_error(Puppet::Error)
138
+ end
28
139
  end
29
140
  end
30
141
 
31
- before do
32
- @executable = Puppet.features.posix? ? '/bin/true' : 'C:/Program Files/something.exe'
33
- @command = Puppet.features.posix? ? '/bin/true whatever' : '"C:/Program Files/something.exe" whatever'
34
- File.stubs(:exists?).returns false
35
- File.stubs(:exists?).with(@executable).returns true
36
- @example_path = Puppet.features.posix? ? %w{/usr/bin /bin} : [ "C:/Program Files/something/bin", "C:/Ruby/bin" ]
37
- File.stubs(:exists?).with(File.join(@example_path[0],"true")).returns true
38
- File.stubs(:exists?).with(File.join(@example_path[0],"false")).returns true
142
+ it "should be able to autorequire files mentioned in the command" do
143
+ catalog = Puppet::Resource::Catalog.new
144
+ tmp = Puppet::Type.type(:file).new(:name => "/bin/foo")
145
+ catalog.add_resource tmp
146
+ execer = Puppet::Type.type(:exec).new(:name => "/bin/foo")
147
+ catalog.add_resource execer
148
+
149
+ catalog.relationship_graph.dependencies(execer).should == [tmp]
39
150
  end
40
151
 
41
- it "should return :executed_command as its event" do
42
- resource = Puppet::Type.type(:exec).new :command => @command
43
- resource.parameter(:returns).event.name.should == :executed_command
152
+ describe "when handling the path parameter" do
153
+ expect = %w{one two three four}
154
+ { "an array" => expect,
155
+ "a colon separated list" => "one:two:three:four",
156
+ "a semi-colon separated list" => "one;two;three;four",
157
+ "both array and colon lists" => ["one", "two:three", "four"],
158
+ "both array and semi-colon lists" => ["one", "two;three", "four"],
159
+ "colon and semi-colon lists" => ["one:two", "three;four"]
160
+ }.each do |test, input|
161
+ it "should accept #{test}" do
162
+ type = Puppet::Type.type(:exec).new(:name => @command, :path => input)
163
+ type[:path].should == expect
164
+ end
165
+ end
44
166
  end
45
167
 
46
- describe "when execing" do
168
+ describe "when setting user" do
169
+ it "should fail if we are not root" do
170
+ Puppet.features.stubs(:root?).returns(false)
171
+ expect { Puppet::Type.type(:exec).new(:name => @command, :user => 'input') }.
172
+ should raise_error Puppet::Error, /Parameter user failed/
173
+ end
47
174
 
48
- it "should use the 'run_and_capture' method to exec" do
49
- command = "true"
50
- create_resource(command, "", 0)
175
+ ['one', 2, 'root', 4294967295, 4294967296].each do |value|
176
+ it "should accept '#{value}' as user if we are root" do
177
+ Puppet.features.stubs(:root?).returns(true)
178
+ type = Puppet::Type.type(:exec).new(:name => @command, :user => value)
179
+ type[:user].should == value
180
+ end
181
+ end
182
+ end
51
183
 
52
- @execer.refresh.should == :executed_command
184
+ describe "when setting group" do
185
+ shared_examples_for "exec[:group]" do
186
+ ['one', 2, 'wheel', 4294967295, 4294967296].each do |value|
187
+ it "should accept '#{value}' without error or judgement" do
188
+ type = Puppet::Type.type(:exec).new(:name => @command, :group => value)
189
+ type[:group].should == value
190
+ end
191
+ end
53
192
  end
54
193
 
55
- it "should report a failure" do
56
- command = "false"
57
- create_resource(command, "", 1)
194
+ describe "when running as root" do
195
+ before :each do Puppet.features.stubs(:root?).returns(true) end
196
+ it_behaves_like "exec[:group]"
197
+ end
198
+
199
+ describe "when not running as root" do
200
+ before :each do Puppet.features.stubs(:root?).returns(false) end
201
+ it_behaves_like "exec[:group]"
202
+ end
203
+ end
204
+
205
+ describe "when setting cwd" do
206
+ it_should_behave_like "all path parameters", :cwd, :array => false do
207
+ def instance(path)
208
+ Puppet::Type.type(:exec).new(:name => '/bin/true', :cwd => path)
209
+ end
210
+ end
211
+ end
212
+
213
+ shared_examples_for "all exec command parameters" do |param|
214
+ { "relative" => "example", "absolute" => "/bin/example" }.sort.each do |name, command|
215
+ describe "if command is #{name}" do
216
+ before :each do
217
+ @param = param
218
+ end
58
219
 
59
- proc { @execer.refresh }.should raise_error(Puppet::Error)
220
+ def test(command, valid)
221
+ if @param == :name then
222
+ instance = Puppet::Type.type(:exec).new()
223
+ else
224
+ instance = Puppet::Type.type(:exec).new(:name => "/bin/true")
225
+ end
226
+ if valid then
227
+ instance.provider.expects(:validatecmd).returns(true)
228
+ else
229
+ instance.provider.expects(:validatecmd).raises(Puppet::Error, "from a stub")
230
+ end
231
+ instance[@param] = command
232
+ end
233
+
234
+ it "should work if the provider calls the command valid" do
235
+ expect { test(command, true) }.should_not raise_error
236
+ end
237
+
238
+ it "should fail if the provider calls the command invalid" do
239
+ expect { test(command, false) }.
240
+ should raise_error Puppet::Error, /Parameter #{@param} failed: from a stub/
241
+ end
242
+ end
60
243
  end
244
+ end
245
+
246
+ shared_examples_for "all exec command parameters that take arrays" do |param|
247
+ describe "when given an array of inputs" do
248
+ before :each do
249
+ @test = Puppet::Type.type(:exec).new(:name => "/bin/true")
250
+ end
61
251
 
62
- it "should not report a failure if the exit status is specified in a returns array" do
63
- command = "false"
64
- create_resource(command, "", 1, [0,1])
65
- proc { @execer.refresh }.should_not raise_error(Puppet::Error)
252
+ it "should accept the array when all commands return valid" do
253
+ input = %w{one two three}
254
+ @test.provider.expects(:validatecmd).times(input.length).returns(true)
255
+ @test[param] = input
256
+ @test[param].should == input
257
+ end
258
+
259
+ it "should reject the array when any commands return invalid" do
260
+ input = %w{one two three}
261
+ @test.provider.expects(:validatecmd).with(input.first).returns(false)
262
+ input[1..-1].each do |cmd|
263
+ @test.provider.expects(:validatecmd).with(cmd).returns(true)
264
+ end
265
+ @test[param] = input
266
+ @test[param].should == input
267
+ end
268
+
269
+ it "should reject the array when all commands return invalid" do
270
+ input = %w{one two three}
271
+ @test.provider.expects(:validatecmd).times(input.length).returns(false)
272
+ @test[param] = input
273
+ @test[param].should == input
274
+ end
66
275
  end
276
+ end
67
277
 
68
- it "should report a failure if the exit status is not specified in a returns array" do
69
- command = "false"
70
- create_resource(command, "", 1, [0,100])
71
- proc { @execer.refresh }.should raise_error(Puppet::Error)
278
+ describe "when setting refresh" do
279
+ it_should_behave_like "all exec command parameters", :refresh
280
+ end
281
+
282
+ describe "for simple parameters" do
283
+ before :each do
284
+ @exec = Puppet::Type.type(:exec).new(:name => '/bin/true')
72
285
  end
73
286
 
74
- it "should log the output on success" do
75
- #Puppet::Util::Log.newdestination :console
76
- command = "false"
77
- output = "output1\noutput2\n"
78
- create_logging_resource(command, output, 0, true, :err)
79
- expect_output(output, :err)
80
- @execer.refresh
287
+ describe "when setting env" do
288
+ it "should issue a deprecation warning" do
289
+ expect { @exec[:env] = 'foo=bar' }.should_not raise_error
290
+ @logs.first.message.should =~ /deprecate.*environment/
291
+ end
292
+
293
+ it "should update the value of env" do
294
+ data = ['foo=bar']
295
+ @exec[:env] = data
296
+ @exec[:env].should == data
297
+ end
298
+
299
+ it "should forward to environment" do
300
+ data = ['foo=bar']
301
+ @exec[:env] = data
302
+ @exec[:environment].should == data
303
+ end
304
+
305
+ it "should not override environment if both are set" do
306
+ pending "can't fix: too disruptive for 2.6, removed in 2.7"
307
+ # ...so this test is here to validate that we know about the problem.
308
+ # This ensures correct order of evaluation to trigger the bug; don't
309
+ # count on this happening in the constructor. --daniel 2011-03-01
310
+ @exec[:environment] = 'environment=true'
311
+ @exec[:env] = 'env=true'
312
+
313
+ @exec[:environment].should == "environment=true"
314
+ end
81
315
  end
82
316
 
83
- it "should log the output on failure" do
84
- #Puppet::Util::Log.newdestination :console
85
- command = "false"
86
- output = "output1\noutput2\n"
87
- create_logging_resource(command, output, 1, true, :err)
88
- expect_output(output, :err)
317
+ describe "when setting environment" do
318
+ { "single values" => "foo=bar",
319
+ "multiple values" => ["foo=bar", "baz=quux"],
320
+ }.each do |name, data|
321
+ it "should accept #{name}" do
322
+ @exec[:environment] = data
323
+ @exec[:environment].should == data
324
+ end
325
+ end
89
326
 
90
- proc { @execer.refresh }.should raise_error(Puppet::Error)
327
+ { "single values" => "foo",
328
+ "only values" => ["foo", "bar"],
329
+ "any values" => ["foo=bar", "baz"]
330
+ }.each do |name, data|
331
+ it "should reject #{name} without assignment" do
332
+ expect { @exec[:environment] = data }.
333
+ should raise_error Puppet::Error, /Invalid environment setting/
334
+ end
335
+ end
91
336
  end
92
337
 
338
+ describe "when setting timeout" do
339
+ [0, 0.1, 1, 10, 4294967295].each do |valid|
340
+ it "should accept '#{valid}' as valid" do
341
+ @exec[:timeout] = valid
342
+ @exec[:timeout].should == valid
343
+ end
344
+
345
+ it "should accept '#{valid}' in an array as valid" do
346
+ @exec[:timeout] = [valid]
347
+ @exec[:timeout].should == valid
348
+ end
349
+ end
350
+
351
+ ['1/2', '', 'foo', '5foo'].each do |invalid|
352
+ it "should reject '#{invalid}' as invalid" do
353
+ expect { @exec[:timeout] = invalid }.
354
+ should raise_error Puppet::Error, /The timeout must be a number/
355
+ end
356
+
357
+ it "should reject '#{invalid}' in an array as invalid" do
358
+ expect { @exec[:timeout] = [invalid] }.
359
+ should raise_error Puppet::Error, /The timeout must be a number/
360
+ end
361
+ end
362
+
363
+ it "should fail if timeout is exceeded" do
364
+ File.stubs(:exists?).with('/bin/sleep').returns(true)
365
+ File.stubs(:exists?).with('sleep').returns(false)
366
+ sleep_exec = Puppet::Type.type(:exec).new(:name => 'sleep 1', :path => ['/bin'], :timeout => '0.2')
367
+ lambda { sleep_exec.refresh }.should raise_error Puppet::Error, "Command exceeded timeout"
368
+ end
369
+
370
+ it "should convert timeout to a float" do
371
+ resource = Puppet::Type.type(:exec).new :command => "/bin/false", :timeout => "12"
372
+ resource[:timeout].should be_a(Float)
373
+ resource[:timeout].should == 12.0
374
+ end
375
+
376
+ it "should munge negative timeouts to 0.0" do
377
+ resource = Puppet::Type.type(:exec).new :command => "/bin/false", :timeout => "-12.0"
378
+ resource.parameter(:timeout).value.should be_a(Float)
379
+ resource.parameter(:timeout).value.should == 0.0
380
+ end
381
+ end
382
+
383
+ describe "when setting tries" do
384
+ [1, 10, 4294967295].each do |valid|
385
+ it "should accept '#{valid}' as valid" do
386
+ @exec[:tries] = valid
387
+ @exec[:tries].should == valid
388
+ end
389
+
390
+ if "REVISIT: too much test log spam" == "a good thing" then
391
+ it "should accept '#{valid}' in an array as valid" do
392
+ pending "inconsistent, but this is not supporting arrays, unlike timeout"
393
+ @exec[:tries] = [valid]
394
+ @exec[:tries].should == valid
395
+ end
396
+ end
397
+ end
398
+
399
+ [-3.5, -1, 0, 0.2, '1/2', '1_000_000', '+12', '', 'foo'].each do |invalid|
400
+ it "should reject '#{invalid}' as invalid" do
401
+ expect { @exec[:tries] = invalid }.
402
+ should raise_error Puppet::Error, /Tries must be an integer/
403
+ end
404
+
405
+ if "REVISIT: too much test log spam" == "a good thing" then
406
+ it "should reject '#{invalid}' in an array as invalid" do
407
+ pending "inconsistent, but this is not supporting arrays, unlike timeout"
408
+ expect { @exec[:tries] = [invalid] }.
409
+ should raise_error Puppet::Error, /Tries must be an integer/
410
+ end
411
+ end
412
+ end
413
+ end
414
+
415
+ describe "when setting try_sleep" do
416
+ [0, 0.2, 1, 10, 4294967295].each do |valid|
417
+ it "should accept '#{valid}' as valid" do
418
+ @exec[:try_sleep] = valid
419
+ @exec[:try_sleep].should == valid
420
+ end
421
+
422
+ if "REVISIT: too much test log spam" == "a good thing" then
423
+ it "should accept '#{valid}' in an array as valid" do
424
+ pending "inconsistent, but this is not supporting arrays, unlike timeout"
425
+ @exec[:try_sleep] = [valid]
426
+ @exec[:try_sleep].should == valid
427
+ end
428
+ end
429
+ end
430
+
431
+ { -3.5 => "cannot be a negative number",
432
+ -1 => "cannot be a negative number",
433
+ '1/2' => 'must be a number',
434
+ '1_000_000' => 'must be a number',
435
+ '+12' => 'must be a number',
436
+ '' => 'must be a number',
437
+ 'foo' => 'must be a number',
438
+ }.each do |invalid, error|
439
+ it "should reject '#{invalid}' as invalid" do
440
+ expect { @exec[:try_sleep] = invalid }.
441
+ should raise_error Puppet::Error, /try_sleep #{error}/
442
+ end
443
+
444
+ if "REVISIT: too much test log spam" == "a good thing" then
445
+ it "should reject '#{invalid}' in an array as invalid" do
446
+ pending "inconsistent, but this is not supporting arrays, unlike timeout"
447
+ expect { @exec[:try_sleep] = [invalid] }.
448
+ should raise_error Puppet::Error, /try_sleep #{error}/
449
+ end
450
+ end
451
+ end
452
+ end
453
+
454
+ describe "when setting refreshonly" do
455
+ [:true, :false].each do |value|
456
+ it "should accept '#{value}'" do
457
+ @exec[:refreshonly] = value
458
+ @exec[:refreshonly].should == value
459
+ end
460
+ end
461
+
462
+ [1, 0, "1", "0", "yes", "y", "no", "n"].each do |value|
463
+ it "should reject '#{value}'" do
464
+ expect { @exec[:refreshonly] = value }.
465
+ should raise_error(Puppet::Error,
466
+ /Invalid value #{value.inspect}\. Valid values are true, false/
467
+ )
468
+ end
469
+ end
470
+ end
471
+
472
+ describe "when setting creates" do
473
+ it_should_behave_like "all path parameters", :creates, :array => true do
474
+ def instance(path)
475
+ Puppet::Type.type(:exec).new(:name => '/bin/true', :creates => path)
476
+ end
477
+ end
478
+ end
93
479
  end
94
480
 
95
- describe "when logoutput=>on_failure is set" do
481
+ describe "when setting unless" do
482
+ it_should_behave_like "all exec command parameters", :unless
483
+ it_should_behave_like "all exec command parameters that take arrays", :unless
484
+ end
96
485
 
97
- it "should log the output on failure" do
98
- #Puppet::Util::Log.newdestination :console
99
- command = "false"
100
- output = "output1\noutput2\n"
101
- create_logging_resource(command, output, 1, :on_failure, :err)
102
- expect_output(output, :err)
486
+ describe "when setting onlyif" do
487
+ it_should_behave_like "all exec command parameters", :onlyif
488
+ it_should_behave_like "all exec command parameters that take arrays", :onlyif
489
+ end
103
490
 
104
- proc { @execer.refresh }.should raise_error(Puppet::Error)
491
+ describe "#check" do
492
+ before :each do
493
+ @test = Puppet::Type.type(:exec).new(:name => "/bin/true")
105
494
  end
106
495
 
107
- it "should log the output on failure when returns is specified as an array" do
108
- #Puppet::Util::Log.newdestination :console
109
- command = "false"
110
- output = "output1\noutput2\n"
111
- create_logging_resource(command, output, 1, :on_failure, :err, [0, 100])
112
- expect_output(output, :err)
496
+ describe ":refreshonly" do
497
+ { :true => false, :false => true }.each do |input, result|
498
+ it "should return '#{result}' when given '#{input}'" do
499
+ @test[:refreshonly] = input
500
+ @test.check_all_attributes.should == result
501
+ end
502
+ end
503
+ end
504
+
505
+ describe ":creates" do
506
+ before :all do
507
+ @exist = "/"
508
+ @unexist = "/this/path/should/never/exist"
509
+ while FileTest.exist?(@unexist) do @unexist += "/foo" end
510
+ end
511
+
512
+ context "with a single item" do
513
+ it "should run when the item does not exist" do
514
+ @test[:creates] = @unexist
515
+ @test.check_all_attributes.should == true
516
+ end
517
+
518
+ it "should not run when the item exists" do
519
+ @test[:creates] = @exist
520
+ @test.check_all_attributes.should == false
521
+ end
522
+ end
523
+
524
+ context "with an array with one item" do
525
+ it "should run when the item does not exist" do
526
+ @test[:creates] = [@unexist]
527
+ @test.check_all_attributes.should == true
528
+ end
529
+
530
+ it "should not run when the item exists" do
531
+ @test[:creates] = [@exist]
532
+ @test.check_all_attributes.should == false
533
+ end
534
+ end
535
+
536
+ context "with an array with multiple items" do
537
+ it "should run when all items do not exist" do
538
+ @test[:creates] = [@unexist] * 3
539
+ @test.check_all_attributes.should == true
540
+ end
541
+
542
+ it "should not run when one item exists" do
543
+ @test[:creates] = [@unexist, @exist, @unexist]
544
+ @test.check_all_attributes.should == false
545
+ end
113
546
 
114
- proc { @execer.refresh }.should raise_error(Puppet::Error)
547
+ it "should not run when all items exist" do
548
+ @test[:creates] = [@exist] * 3
549
+ end
550
+ end
115
551
  end
116
552
 
117
- it "shouldn't log the output on success" do
118
- #Puppet::Util::Log.newdestination :console
119
- command = "true"
120
- output = "output1\noutput2\n"
121
- create_logging_resource(command, output, 0, :on_failure, :err)
122
- @execer.property(:returns).expects(:err).never
123
- @execer.refresh
553
+ { :onlyif => { :pass => false, :fail => true },
554
+ :unless => { :pass => true, :fail => false },
555
+ }.each do |param, sense|
556
+ describe ":#{param}" do
557
+ before :each do
558
+ @pass = "/magic/pass"
559
+ @fail = "/magic/fail"
560
+
561
+ @pass_status = stub('status', :exitstatus => sense[:pass] ? 0 : 1)
562
+ @fail_status = stub('status', :exitstatus => sense[:fail] ? 0 : 1)
563
+
564
+ @test.provider.stubs(:checkexe).returns(true)
565
+ [true, false].each do |check|
566
+ @test.provider.stubs(:run).with(@pass, check).
567
+ returns(['test output', @pass_status])
568
+ @test.provider.stubs(:run).with(@fail, check).
569
+ returns(['test output', @fail_status])
570
+ end
571
+ end
572
+
573
+ context "with a single item" do
574
+ it "should run if the command exits non-zero" do
575
+ @test[param] = @fail
576
+ @test.check_all_attributes.should == true
577
+ end
578
+
579
+ it "should not run if the command exits zero" do
580
+ @test[param] = @pass
581
+ @test.check_all_attributes.should == false
582
+ end
583
+ end
584
+
585
+ context "with an array with a single item" do
586
+ it "should run if the command exits non-zero" do
587
+ @test[param] = [@fail]
588
+ @test.check_all_attributes.should == true
589
+ end
590
+
591
+ it "should not run if the command exits zero" do
592
+ @test[param] = [@pass]
593
+ @test.check_all_attributes.should == false
594
+ end
595
+ end
596
+
597
+ context "with an array with multiple items" do
598
+ it "should run if all the commands exits non-zero" do
599
+ @test[param] = [@fail] * 3
600
+ @test.check_all_attributes.should == true
601
+ end
602
+
603
+ it "should not run if one command exits zero" do
604
+ @test[param] = [@pass, @fail, @pass]
605
+ @test.check_all_attributes.should == false
606
+ end
607
+
608
+ it "should not run if all command exits zero" do
609
+ @test[param] = [@pass] * 3
610
+ @test.check_all_attributes.should == false
611
+ end
612
+ end
613
+ end
124
614
  end
125
615
  end
126
616
 
127
- it "shouldn't log the output on success when non-zero exit status is in a returns array" do
128
- #Puppet::Util::Log.newdestination :console
129
- command = "true"
130
- output = "output1\noutput2\n"
131
- create_logging_resource(command, output, 100, :on_failure, :err, [1,100])
132
- @execer.property(:returns).expects(:err).never
133
- @execer.refresh
617
+ describe "#retrieve" do
618
+ before :each do
619
+ @exec_resource = Puppet::Type.type(:exec).new(:name => "/bogus/cmd")
620
+ end
621
+
622
+ it "should return :notrun when check_all_attributes returns true" do
623
+ @exec_resource.stubs(:check_all_attributes).returns true
624
+ @exec_resource.retrieve[:returns].should == :notrun
625
+ end
626
+
627
+ it "should return default exit code 0 when check_all_attributes returns false" do
628
+ @exec_resource.stubs(:check_all_attributes).returns false
629
+ @exec_resource.retrieve[:returns].should == ['0']
630
+ end
631
+
632
+ it "should return the specified exit code when check_all_attributes returns false" do
633
+ @exec_resource.stubs(:check_all_attributes).returns false
634
+ @exec_resource[:returns] = 42
635
+ @exec_resource.retrieve[:returns].should == ["42"]
636
+ end
134
637
  end
135
638
 
136
- describe " when multiple tries are set," do
639
+ describe "#output" do
640
+ before :each do
641
+ @exec_resource = Puppet::Type.type(:exec).new(:name => "/bogus/cmd")
642
+ end
643
+
644
+ it "should return the provider's run output" do
645
+ provider = stub 'provider'
646
+ status = stubs "process_status"
647
+ status.stubs(:exitstatus).returns("0")
648
+ provider.expects(:run).returns(["silly output", status])
649
+ @exec_resource.stubs(:provider).returns(provider)
137
650
 
138
- it "should repeat the command attempt 'tries' times on failure and produce an error" do
139
- Puppet.features.stubs(:root?).returns(true)
140
- command = "false"
141
- user = "user"
142
- group = "group"
143
- tries = 5
144
- retry_exec = Puppet::Type.type(:exec).new(:name => command, :path => %w{/usr/bin /bin}, :user => user, :group => group, :returns => 0, :tries => tries, :try_sleep => 0)
145
- status = stub "process"
146
- status.stubs(:exitstatus).returns(1)
147
- Puppet::Util::SUIDManager.expects(:run_and_capture).with([command], user, group).times(tries).returns(["", status])
148
- proc { retry_exec.refresh }.should raise_error(Puppet::Error)
651
+ @exec_resource.refresh
652
+ @exec_resource.output.should == 'silly output'
149
653
  end
150
654
  end
151
655
 
152
- it "should be able to autorequire files mentioned in the command" do
153
- catalog = Puppet::Resource::Catalog.new
154
- catalog.add_resource Puppet::Type.type(:file).new(:name => @executable)
155
- @execer = Puppet::Type.type(:exec).new(:name => @command)
156
- catalog.add_resource @execer
656
+ describe "#refresh" do
657
+ before :each do
658
+ @exec_resource = Puppet::Type.type(:exec).new(:name => "/bogus/cmd")
659
+ end
660
+
661
+ it "should call provider run with the refresh parameter if it is set" do
662
+ provider = stub 'provider'
663
+ @exec_resource.stubs(:provider).returns(provider)
664
+ @exec_resource.stubs(:[]).with(:refresh).returns('/myother/bogus/cmd')
665
+ provider.expects(:run).with('/myother/bogus/cmd')
157
666
 
158
- rels = @execer.autorequire
159
- rels[0].should be_instance_of(Puppet::Relationship)
160
- rels[0].target.should equal(@execer)
667
+ @exec_resource.refresh
668
+ end
669
+
670
+ it "should call provider run with the specified command if the refresh parameter is not set" do
671
+ provider = stub 'provider'
672
+ status = stubs "process_status"
673
+ status.stubs(:exitstatus).returns("0")
674
+ provider.expects(:run).with('/bogus/cmd').returns(["silly output", status])
675
+ @exec_resource.stubs(:provider).returns(provider)
676
+
677
+ @exec_resource.refresh
678
+ end
679
+
680
+ it "should not run the provider if check_all_attributes is false" do
681
+ @exec_resource.stubs(:check_all_attributes).returns false
682
+ provider = stub 'provider'
683
+ provider.expects(:run).never
684
+ @exec_resource.stubs(:provider).returns(provider)
685
+
686
+ @exec_resource.refresh
687
+ end
161
688
  end
162
689
  end