jemmyw-sprinkle 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. data/CREDITS +21 -0
  2. data/History.txt +4 -0
  3. data/MIT-LICENSE +20 -0
  4. data/Manifest.txt +104 -0
  5. data/README.txt +241 -0
  6. data/Rakefile +4 -0
  7. data/bin/sprinkle +86 -0
  8. data/config/hoe.rb +70 -0
  9. data/config/requirements.rb +17 -0
  10. data/examples/packages/build_essential.rb +9 -0
  11. data/examples/packages/databases/mysql.rb +13 -0
  12. data/examples/packages/databases/sqlite3.rb +16 -0
  13. data/examples/packages/phusion.rb +55 -0
  14. data/examples/packages/ruby/rails.rb +9 -0
  15. data/examples/packages/ruby/ruby.rb +17 -0
  16. data/examples/packages/ruby/rubygems.rb +17 -0
  17. data/examples/packages/scm/git.rb +11 -0
  18. data/examples/packages/scm/subversion.rb +4 -0
  19. data/examples/packages/servers/apache.rb +15 -0
  20. data/examples/rails/README +15 -0
  21. data/examples/rails/deploy.rb +2 -0
  22. data/examples/rails/packages/database.rb +9 -0
  23. data/examples/rails/packages/essential.rb +9 -0
  24. data/examples/rails/packages/rails.rb +28 -0
  25. data/examples/rails/packages/scm.rb +11 -0
  26. data/examples/rails/packages/search.rb +11 -0
  27. data/examples/rails/packages/server.rb +28 -0
  28. data/examples/rails/rails.rb +73 -0
  29. data/examples/sprinkle/sprinkle.rb +38 -0
  30. data/lib/sprinkle/actors/actors.rb +17 -0
  31. data/lib/sprinkle/actors/capistrano.rb +147 -0
  32. data/lib/sprinkle/actors/local.rb +50 -0
  33. data/lib/sprinkle/actors/ssh.rb +81 -0
  34. data/lib/sprinkle/actors/vlad.rb +65 -0
  35. data/lib/sprinkle/configurable.rb +31 -0
  36. data/lib/sprinkle/deployment.rb +77 -0
  37. data/lib/sprinkle/extensions/arbitrary_options.rb +10 -0
  38. data/lib/sprinkle/extensions/array.rb +5 -0
  39. data/lib/sprinkle/extensions/blank_slate.rb +5 -0
  40. data/lib/sprinkle/extensions/dsl_accessor.rb +15 -0
  41. data/lib/sprinkle/extensions/string.rb +10 -0
  42. data/lib/sprinkle/extensions/symbol.rb +7 -0
  43. data/lib/sprinkle/installers/apt.rb +52 -0
  44. data/lib/sprinkle/installers/bsd_port.rb +33 -0
  45. data/lib/sprinkle/installers/custom.rb +28 -0
  46. data/lib/sprinkle/installers/deb.rb +38 -0
  47. data/lib/sprinkle/installers/freebsd_pkg.rb +37 -0
  48. data/lib/sprinkle/installers/gem.rb +63 -0
  49. data/lib/sprinkle/installers/installer.rb +120 -0
  50. data/lib/sprinkle/installers/mac_port.rb +38 -0
  51. data/lib/sprinkle/installers/openbsd_pkg.rb +47 -0
  52. data/lib/sprinkle/installers/opensolaris_pkg.rb +43 -0
  53. data/lib/sprinkle/installers/push_text.rb +45 -0
  54. data/lib/sprinkle/installers/rake.rb +37 -0
  55. data/lib/sprinkle/installers/rpm.rb +37 -0
  56. data/lib/sprinkle/installers/source.rb +179 -0
  57. data/lib/sprinkle/installers/yum.rb +37 -0
  58. data/lib/sprinkle/package.rb +293 -0
  59. data/lib/sprinkle/policy.rb +126 -0
  60. data/lib/sprinkle/script.rb +23 -0
  61. data/lib/sprinkle/verifiers/directory.rb +16 -0
  62. data/lib/sprinkle/verifiers/dpkg.rb +14 -0
  63. data/lib/sprinkle/verifiers/executable.rb +36 -0
  64. data/lib/sprinkle/verifiers/file.rb +26 -0
  65. data/lib/sprinkle/verifiers/process.rb +21 -0
  66. data/lib/sprinkle/verifiers/ruby.rb +25 -0
  67. data/lib/sprinkle/verifiers/symlink.rb +30 -0
  68. data/lib/sprinkle/verifiers/user.rb +11 -0
  69. data/lib/sprinkle/verify.rb +114 -0
  70. data/lib/sprinkle/version.rb +9 -0
  71. data/lib/sprinkle.rb +32 -0
  72. data/script/destroy +14 -0
  73. data/script/generate +14 -0
  74. data/spec/spec.opts +1 -0
  75. data/spec/spec_helper.rb +17 -0
  76. data/spec/sprinkle/actors/capistrano_spec.rb +194 -0
  77. data/spec/sprinkle/actors/local_spec.rb +29 -0
  78. data/spec/sprinkle/configurable_spec.rb +46 -0
  79. data/spec/sprinkle/deployment_spec.rb +80 -0
  80. data/spec/sprinkle/extensions/array_spec.rb +19 -0
  81. data/spec/sprinkle/extensions/string_spec.rb +21 -0
  82. data/spec/sprinkle/installers/apt_spec.rb +70 -0
  83. data/spec/sprinkle/installers/bsd_port_spec.rb +42 -0
  84. data/spec/sprinkle/installers/custom_spec.rb +29 -0
  85. data/spec/sprinkle/installers/freebsd_pkg_spec.rb +49 -0
  86. data/spec/sprinkle/installers/gem_spec.rb +91 -0
  87. data/spec/sprinkle/installers/installer_spec.rb +151 -0
  88. data/spec/sprinkle/installers/mac_port_spec.rb +42 -0
  89. data/spec/sprinkle/installers/openbsd_pkg_spec.rb +49 -0
  90. data/spec/sprinkle/installers/opensolaris_pkg_spec.rb +49 -0
  91. data/spec/sprinkle/installers/push_text_spec.rb +55 -0
  92. data/spec/sprinkle/installers/rake_spec.rb +29 -0
  93. data/spec/sprinkle/installers/rpm_spec.rb +50 -0
  94. data/spec/sprinkle/installers/source_spec.rb +331 -0
  95. data/spec/sprinkle/installers/yum_spec.rb +49 -0
  96. data/spec/sprinkle/package_spec.rb +452 -0
  97. data/spec/sprinkle/policy_spec.rb +133 -0
  98. data/spec/sprinkle/script_spec.rb +51 -0
  99. data/spec/sprinkle/sprinkle_spec.rb +25 -0
  100. data/spec/sprinkle/verify_spec.rb +185 -0
  101. data/sprinkle.gemspec +45 -0
  102. data/tasks/deployment.rake +34 -0
  103. data/tasks/environment.rake +7 -0
  104. data/tasks/rspec.rake +21 -0
  105. metadata +199 -0
@@ -0,0 +1,452 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Sprinkle::Package do
4
+ include Sprinkle::Package
5
+
6
+ before do
7
+ @name = :package_name
8
+ @empty = Proc.new { }
9
+ @opts = { }
10
+ end
11
+
12
+ # Kind of a messy way to do this but it works and DRYs out
13
+ # the specs. Checks to make sure an installer is receiving
14
+ # the block passed to it throught the package block.
15
+ def check_block_forwarding_on(installer)
16
+ eval(<<CODE, binding, __FILE__, __LINE__)
17
+ pre_count = 0
18
+ lambda {
19
+ pkg = package @name do
20
+ #{installer} 'archive' do
21
+ pre :install, 'preOp'
22
+ end
23
+ end
24
+
25
+ pre_count = pkg.operations.last.instance_variable_get(:@pre)[:install].length
26
+ }.should change { pre_count }.by(1)
27
+ CODE
28
+ end
29
+
30
+ # More of Mitchell's meta-programming to dry up specs.
31
+ def create_package_with_blank_verify(n = 1)
32
+ eval(<<CODE, binding, __FILE__, __LINE__)
33
+ @pkg = package @name do
34
+ gem 'gem'
35
+ #{"verify 'stuff happens' do; end\n" * n}
36
+ end
37
+ CODE
38
+ end
39
+
40
+ describe 'when created' do
41
+
42
+ it 'should be invalid without a block descriptor' do
43
+ lambda { package @name }.should raise_error
44
+ end
45
+
46
+ it 'should be invalid without a name' do
47
+ lambda { package nil, &@empty }.should raise_error
48
+ lambda { package @name, &@empty }.should_not raise_error
49
+ end
50
+
51
+ it 'should optionally accept a description' do
52
+ pkg = package @name do
53
+ description 'my package description'
54
+ end
55
+ pkg.description.should == 'my package description'
56
+ end
57
+
58
+ it 'should optionally accept a version' do
59
+ pkg = package @name do
60
+ version '2.0.2'
61
+ end
62
+ pkg.version.should == '2.0.2'
63
+ end
64
+
65
+ it 'should optionally accept an installer' do
66
+ pkg = package @name do
67
+ gem 'rails'
68
+ end
69
+ pkg.operations.last.should_not be_nil
70
+ end
71
+
72
+ it 'should optionally accept dependencies' do
73
+ pkg = package @name do
74
+ requires :webserver, :database
75
+ end
76
+ pkg.dependencies.should == [:webserver, :database]
77
+ end
78
+
79
+ it 'should optionally accept recommended dependencies' do
80
+ pkg = package @name do
81
+ recommends :webserver, :database
82
+ end
83
+ pkg.recommends.should == [:webserver, :database]
84
+ end
85
+
86
+ it 'should optionally define a virtual package implementation' do
87
+ pkg = package @name, :provides => :database do; end
88
+ pkg.provides.should == :database
89
+ end
90
+
91
+ it 'should be able to represent itself as a string' do
92
+ pkg = package @name do; end
93
+ pkg.to_s.should == @name
94
+ end
95
+
96
+ end
97
+
98
+ describe 'helper method' do
99
+
100
+ it 'should added new packages to the global package hash' do
101
+ pkg = package @name do; end
102
+ Sprinkle::Package::PACKAGES[@name].should == pkg
103
+ end
104
+
105
+ it 'should add the new package to the provides list if specified' do
106
+ pkg = package @name, :provides => :database do; end
107
+ Sprinkle::Package::PACKAGES[:database].last.should == pkg
108
+ end
109
+
110
+ end
111
+
112
+ describe 'installer configuration' do
113
+
114
+ it 'should optionally accept an apt installer' do
115
+ pkg = package @name do
116
+ apt %w( deb1 deb2 )
117
+ end
118
+ pkg.should respond_to(:apt)
119
+ pkg.operations.last.class.should == Sprinkle::Installers::Apt
120
+ end
121
+
122
+ it 'should optionally accept an rpm installer' do
123
+ pkg = package @name do
124
+ rpm %w( rpm1 rpm2 )
125
+ end
126
+ pkg.should respond_to(:rpm)
127
+ pkg.operations.last.class.should == Sprinkle::Installers::Rpm
128
+ end
129
+
130
+ it 'should optionally accept a gem installer' do
131
+ pkg = package @name do
132
+ gem 'gem'
133
+ end
134
+ pkg.should respond_to(:gem)
135
+ pkg.operations.last.class.should == Sprinkle::Installers::Gem
136
+ end
137
+
138
+ it 'should optionally accept a source installer' do
139
+ pkg = package @name do
140
+ source 'archive'
141
+ end
142
+ pkg.should respond_to(:source)
143
+ pkg.operations.last.class.should == Sprinkle::Installers::Source
144
+ end
145
+
146
+ end
147
+
148
+ describe 'with a source installer' do
149
+
150
+ it 'should optionally accept a block containing customisations' do
151
+ pkg = package @name do
152
+ source 'archive' do; end
153
+ end
154
+ pkg.should respond_to(:source)
155
+ pkg.operations.last.class.should == Sprinkle::Installers::Source
156
+ end
157
+
158
+ it 'should forward block to installer superclass' do
159
+ check_block_forwarding_on(:source)
160
+ end
161
+
162
+ it 'should automatically add a build essential recommendation' do
163
+ pkg = package @name do
164
+ source 'archive'
165
+ end
166
+ pkg.recommends.should include(:build_essential)
167
+ end
168
+
169
+ end
170
+
171
+ describe 'with an apt installer' do
172
+ it 'should forward block to installer superclass' do
173
+ check_block_forwarding_on(:apt)
174
+ end
175
+ end
176
+
177
+ describe 'with an rpm installer' do
178
+ it 'should forward block to installer superclass' do
179
+ check_block_forwarding_on(:rpm)
180
+ end
181
+ end
182
+
183
+ describe 'with an gem installer' do
184
+
185
+ it 'should automatically add a rubygems recommendation' do
186
+ pkg = package @name do
187
+ gem 'gem'
188
+ end
189
+ pkg.recommends.should include(:rubygems)
190
+ end
191
+
192
+ it 'should forward block to installer superclass' do
193
+ check_block_forwarding_on(:gem)
194
+ end
195
+
196
+ end
197
+
198
+ describe 'with a custom installer' do
199
+ it 'should forward block to installer superclass' do
200
+ check_block_forwarding_on(:custom)
201
+ end
202
+ end
203
+
204
+ describe 'when processing' do
205
+
206
+ before do
207
+ @deployment = mock(Sprinkle::Deployment)
208
+ @roles = [ :app, :db ]
209
+ @installer = mock(Sprinkle::Installers::Installer, :defaults => true, :process => true, :responds_to? => true)
210
+ @package = package @name do; end
211
+ end
212
+
213
+ describe 'with an installer' do
214
+
215
+ before do
216
+ @package.operations = [@installer]
217
+ end
218
+
219
+ it 'should configure itself against the deployment context' do
220
+ @installer.should_receive(:defaults).with(@deployment).and_return
221
+ @deployment.should_receive(:find_servers).with(:app).and_return(['app1.example.com'])
222
+ @deployment.should_receive(:find_servers).with(:db).and_return(['db1.example.com'])
223
+ end
224
+
225
+ it 'should request the installer to process itself' do
226
+ @installer.should_receive(:process).with('app1.example.com').and_return
227
+ @installer.should_receive(:process).with('db1.example.com').and_return
228
+ @deployment.should_receive(:find_servers).with(:app).and_return(['app1.example.com'])
229
+ @deployment.should_receive(:find_servers).with(:db).and_return(['db1.example.com'])
230
+ end
231
+
232
+ after do
233
+ @package.process(@deployment, @roles)
234
+ end
235
+ end
236
+
237
+ describe 'without an installer' do
238
+
239
+ it 'should not request the installer to process if the package is a metapackage' do
240
+ @installer.should_not_receive(:process)
241
+ @package.process(@deployment, @roles)
242
+ end
243
+
244
+ end
245
+
246
+ describe 'with verifications' do
247
+ before do
248
+ @pkg = create_package_with_blank_verify(3)
249
+ @pkg.operations = [@installer]
250
+ @installer.stub!(:defaults)
251
+ @installer.stub!(:process)
252
+ end
253
+
254
+ describe 'with forcing' do
255
+ before do
256
+ # Being explicit
257
+ Sprinkle::OPTIONS[:force] = true
258
+ end
259
+
260
+ it 'should process verifications only once' do
261
+ @pkg.should_receive(:process_verifications).twice
262
+ @deployment.should_receive(:find_servers).with(:app).and_return(['app1.example.com'])
263
+ @deployment.should_receive(:find_servers).with(:db).and_return(['db1.example.com'])
264
+ @pkg.process(@deployment, @roles)
265
+ end
266
+
267
+ after do
268
+ # Being explicit
269
+ Sprinkle::OPTIONS[:force] = false
270
+ end
271
+ end
272
+
273
+ describe 'without forcing' do
274
+ before do
275
+ # Being explicit
276
+ Sprinkle::OPTIONS[:force] = false
277
+ end
278
+
279
+ it 'should process verifications twice' do
280
+ @pkg.should_receive(:process_verifications).once.with(@deployment, 'app1.example.com', true).and_raise(Sprinkle::VerificationFailed.new(@pkg, ''))
281
+ @pkg.should_receive(:process_verifications).once.with(@deployment, 'app1.example.com').and_raise(Sprinkle::VerificationFailed.new(@pkg, ''))
282
+ @deployment.should_receive(:find_servers).with(:app).and_return(['app1.example.com'])
283
+ end
284
+
285
+ it 'should continue with installation if pre-verification fails' do
286
+ @pkg.should_receive(:process_verifications).twice.and_raise(Sprinkle::VerificationFailed.new(@pkg, ''))
287
+ @installer.should_receive(:defaults)
288
+ @installer.should_receive(:process)
289
+ @deployment.should_receive(:find_servers).with(:app).and_return(['app1.example.com'])
290
+ end
291
+
292
+ it 'should only process verifications once and should not process installer if verifications succeed' do
293
+ @pkg.should_receive(:process_verifications).twice.and_return(nil)
294
+ @installer.should_not_receive(:defaults)
295
+ @installer.should_not_receive(:process)
296
+ @deployment.should_receive(:find_servers).with(:app).and_return(['app1.example.com'])
297
+ @deployment.should_receive(:find_servers).with(:db).and_return(['db1.example.com'])
298
+ end
299
+
300
+ after do
301
+ begin
302
+ @pkg.process(@deployment, @roles)
303
+ rescue Sprinkle::VerificationFailed => e; end
304
+ end
305
+ end
306
+ end
307
+
308
+ end
309
+
310
+ describe 'when processing verifications' do
311
+ before do
312
+ @deployment = mock(Sprinkle::Deployment)
313
+ @roles = [ :app, :db ]
314
+ @installer = mock(Sprinkle::Installers::Installer, :defaults => true, :process => true)
315
+ @pkg = create_package_with_blank_verify(3)
316
+ @pkg.operations << @installer
317
+ @installer.stub!(:defaults)
318
+ @installer.stub!(:process)
319
+ @logger = mock(ActiveSupport::BufferedLogger, :debug => true, :debug? => true)
320
+ @logger.stub!(:info)
321
+ end
322
+
323
+ it 'should request _each_ verification to configure itself against the deployment context' do
324
+ @pkg.verifications.each do |v|
325
+ v.should_receive(:defaults).with(@deployment).once
326
+ v.stub!(:process)
327
+ end
328
+ end
329
+
330
+ it 'should request _each_ verification to process' do
331
+ @pkg.verifications.each do |v|
332
+ v.stub!(:defaults)
333
+ v.should_receive(:process).with(@roles).once
334
+ end
335
+ end
336
+
337
+ it 'should enter a log info event to notify user whats happening' do
338
+ @pkg.verifications.each do |v|
339
+ v.stub!(:defaults)
340
+ v.stub!(:process)
341
+ end
342
+
343
+ @pkg.should_receive(:logger).once.and_return(@logger)
344
+ end
345
+
346
+ after do
347
+ @pkg.process_verifications(@deployment, @roles)
348
+ end
349
+ end
350
+
351
+ describe 'hierarchies' do
352
+
353
+ before do
354
+ @a = package :a do; requires :b; end
355
+ @b = package :b do; requires :c; end
356
+ @c = package :c do; recommends :d; end
357
+ @d = package :d do; end
358
+ end
359
+
360
+ it 'should be able to return a dependency hierarchy tree' do
361
+ @a.tree.flatten.should == [ @d, @c, @b, @a ]
362
+ @b.tree.flatten.should == [ @d, @c, @b ]
363
+ @c.tree.flatten.should == [ @d, @c ]
364
+ @d.tree.flatten.should == [ @d ]
365
+ end
366
+
367
+ describe 'with missing recommendations' do
368
+
369
+ before do
370
+ @d.recommends :e
371
+ end
372
+
373
+ it 'should ignore missing recommendations' do
374
+ @d.tree.flatten.should == [ @d ]
375
+ end
376
+
377
+ end
378
+
379
+ it 'should optionally accept a block to call upon item in the tree during hierarchy traversal' do
380
+ @count = 0
381
+ @a.tree do
382
+ @count += 1
383
+ end
384
+ @count.should == 3
385
+ end
386
+
387
+ it 'should maintain a depth count of how deep the hierarchy is' do
388
+ @b.should_receive(:tree).with(2).and_return([@b])
389
+ @a.tree do; end
390
+ end
391
+
392
+ end
393
+
394
+ describe 'virtual package dependencies' do
395
+ before do
396
+ @a = package :a do; requires :virtual ; end
397
+ @v1 = package :v1, :provides => :virtual do; end
398
+ @v2 = package :v2, :provides => :virtual do; end
399
+ end
400
+
401
+ it 'should select package for an array' do
402
+ @a.should_receive(:select_package).with(:virtual, [@v1,@v2]).and_return(@v1)
403
+ @a.tree do; end
404
+ end
405
+ end
406
+
407
+ describe 'with missing dependencies' do
408
+
409
+ before do
410
+ @pkg = package @name do
411
+ gem 'gem'
412
+ requires :missing
413
+ end
414
+ end
415
+
416
+ it 'should raise an error if a package is missing' do
417
+ lambda { @pkg.tree }.should raise_error
418
+ end
419
+
420
+ end
421
+
422
+ describe 'with verifications' do
423
+ it 'should create a Sprinkle::Verification object for the verify block' do
424
+ Sprinkle::Verify.should_receive(:new).once
425
+
426
+ create_package_with_blank_verify
427
+ end
428
+
429
+ it 'should create multiple Sprinkle::Verification objects for multiple verify blocks' do
430
+ Sprinkle::Verify.should_receive(:new).twice
431
+
432
+ create_package_with_blank_verify(2)
433
+ end
434
+
435
+ it 'should add each Sprinkle::Verificaton object to the @verifications array' do
436
+ @pkg = create_package_with_blank_verify(3)
437
+ @pkg.verifications.length.should eql(3)
438
+ end
439
+
440
+ it 'should initialize Sprinkle::Verification with the package name, description, and block' do
441
+ Sprinkle::Verify.should_receive(:new) do |pkg, desc|
442
+ pkg.name.should eql(@name)
443
+ desc.should eql('stuff happens')
444
+ end
445
+
446
+ # We do a should_not raise_error because if a block was NOT passed, an error
447
+ # is raised. This is specced in verification_spec.rb
448
+ lambda { create_package_with_blank_verify }.should_not raise_error
449
+ end
450
+ end
451
+
452
+ end
@@ -0,0 +1,133 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Sprinkle::Policy do
4
+ include Sprinkle::Policy
5
+
6
+ before do
7
+ @name = 'a policy'
8
+ end
9
+
10
+ describe 'when created' do
11
+
12
+ it 'should be invalid without a name' do
13
+ lambda { policy nil }.should raise_error
14
+ end
15
+
16
+ it 'should be invalid without role definitions' do
17
+ lambda { policy @name do; end }.should raise_error
18
+ lambda { policy @name, :roles => :app do; end }.should_not raise_error
19
+ end
20
+
21
+ it 'should optionally accept package dependencies' do
22
+ p = policy @name, :roles => :app do; end
23
+ p.should respond_to(:requires)
24
+ p.requires :appserver
25
+ p.packages.should == [ :appserver ]
26
+ end
27
+
28
+ it 'should accept package dependencies using the configures alias' do
29
+ p = policy @name, :roles => :app do; end
30
+ p.should respond_to(:configures)
31
+ p.configures :appserver
32
+ p.packages.should == [ :appserver ]
33
+ end
34
+
35
+ it 'should optionally accept package dependencies with versions' do
36
+ p = policy @name, :roles => :app do; end
37
+ p.requires :appserver, :version => 2
38
+ p.packages.should == [ :appserver ]
39
+ pending 'requires version checking implementation'
40
+ end
41
+
42
+ it 'should add itself to the global policy list' do
43
+ sz = Sprinkle::Policy::POLICIES.size
44
+ p = policy @name, :roles => :app do; end
45
+ Sprinkle::Policy::POLICIES.size.should == sz + 1
46
+ Sprinkle::Policy::POLICIES.last.should == p
47
+ end
48
+
49
+ end
50
+
51
+ describe 'with packages' do
52
+ include Sprinkle::Package
53
+
54
+ before do
55
+ @deployment = mock(Sprinkle::Deployment)
56
+ Sprinkle::Package::PACKAGES.clear # reset full package list before each spec is run
57
+
58
+ @a = package :a do; requires :b; requires :c; end
59
+ @b = package :b, :provides => :xyz do; end
60
+ @c = package :c, :provides => :abc do; end
61
+ @d = package :d, :provides => :abc do; end
62
+
63
+ @policy = policy :test, :roles => :app do; requires :a; end
64
+ $terminal.stub!(:choose).and_return(:c) # stub out highline asking questions
65
+ end
66
+
67
+ describe 'when applying' do
68
+ include Sprinkle::Package
69
+
70
+ it 'should determine the packages to install via the hierarchy dependency tree of each package in the policy' do
71
+ @a.should_receive(:process).and_return
72
+ @b.should_receive(:process).and_return
73
+ @c.should_receive(:process).and_return
74
+ @d.should_not_receive(:process)
75
+ end
76
+
77
+ it 'should normalize (ie remove duplicates from) the installation order of all packages including dependencies' do
78
+ @e = package :e do; requires :b; end
79
+ @policy.requires :e
80
+
81
+ @a.should_receive(:process).once.and_return
82
+ @b.should_receive(:process).once.and_return
83
+ @c.should_receive(:process).once.and_return
84
+ @d.should_not_receive(:process)
85
+ @e.should_receive(:process).once.and_return
86
+ end
87
+ end
88
+
89
+ describe 'containing package dependencies with versions' do
90
+
91
+ it 'should be invalid if the specified package does not exist'
92
+ it 'should ignore any packages of the same name that have other versions'
93
+ it 'should select the correct package version when applying'
94
+
95
+ end
96
+
97
+ describe 'containing virtual packages' do
98
+
99
+ it 'should automatically select a concrete package implementation for a virtual one when there exists only one possible selection' do
100
+ @policy = policy :virtual, :roles => :app do; requires :xyz; end
101
+ Sprinkle::Package::PACKAGES[:xyz].should == [ @b ]
102
+ end
103
+
104
+ it 'should ask the user for the concrete package implementation to use for a virtual one when more than one possible choice exists' do
105
+ @policy = policy :virtual, :roles => :app do; requires :abc; end
106
+ Sprinkle::Package::PACKAGES[:abc].should include(@c)
107
+ Sprinkle::Package::PACKAGES[:abc].should include(@d)
108
+ $terminal.should_receive(:choose).and_return(:c)
109
+ end
110
+
111
+ end
112
+
113
+ after do
114
+ @policy.process(@deployment)
115
+ end
116
+ end
117
+ end
118
+
119
+ describe Sprinkle::Policy, 'with missing packages' do
120
+
121
+ before do
122
+ @deployment = mock(Sprinkle::Deployment)
123
+ Sprinkle::Package::PACKAGES.clear # reset full package list before each spec is run
124
+
125
+ @policy = policy :test, :roles => :app do; requires :z; end
126
+ $terminal.stub!(:choose).and_return(:c) # stub out highline asking questions
127
+ end
128
+
129
+ it 'should raise an error if a package is missing' do
130
+ lambda { @policy.process(@deployment) }.should raise_error
131
+ end
132
+
133
+ end
@@ -0,0 +1,51 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Sprinkle::Script, 'class' do
4
+
5
+ it 'should define a entry point into the system' do
6
+ Sprinkle::Script.should respond_to(:sprinkle)
7
+ end
8
+
9
+ end
10
+
11
+ describe Sprinkle::Script, 'when given a script' do
12
+
13
+ before do
14
+ @script = 'script'
15
+ @filename = 'filename'
16
+
17
+ @sprinkle = Sprinkle::Script.new
18
+ Sprinkle::Script.stub!(:new).and_return(@sprinkle)
19
+ end
20
+
21
+ it 'should create a new sprinkle instance' do
22
+ Sprinkle::Script.should_receive(:new).and_return(@sprinkle)
23
+ Sprinkle::Script.sprinkle @script
24
+ end
25
+
26
+ it 'should evaulate the sprinkle script against the instance' do
27
+ @sprinkle.should_receive(:instance_eval).and_return
28
+ Sprinkle::Script.sprinkle @script
29
+ end
30
+
31
+ it 'should specify the filename if given for line number errors' do
32
+ @sprinkle.should_receive(:instance_eval).with(@script, @filename).and_return
33
+ Sprinkle::Script.sprinkle @script, @filename
34
+ end
35
+
36
+ it 'should specify a filename of __SCRIPT__ by default if none is provided' do
37
+ @sprinkle.should_receive(:instance_eval).with(@script, '__SCRIPT__').and_return
38
+ Sprinkle::Script.sprinkle @script
39
+ end
40
+
41
+ it 'should automatically run in production mode by default' do
42
+ @sprinkle.should_receive(:instance_eval).with(@script, '__SCRIPT__').and_return
43
+ Sprinkle::Script.sprinkle @script
44
+ end
45
+
46
+ it 'should ask the Sprinkle instance to process the data from the script' do
47
+ @sprinkle.should_receive(:sprinkle)
48
+ Sprinkle::Script.sprinkle @script
49
+ end
50
+
51
+ end
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Sprinkle do
4
+
5
+ it 'should automatically extend Object to support package, policy and deployment DSL keywords' do
6
+ %w( package policy deployment ).each do |keyword|
7
+ Object.should respond_to(keyword.to_sym)
8
+ end
9
+ end
10
+
11
+ it 'should default to production mode' do
12
+ Sprinkle::OPTIONS[:testing].should be_false
13
+ end
14
+
15
+ it 'should automatically create a logger object on Kernel' do
16
+ Object.should respond_to(:logger)
17
+ logger.should_not be_nil
18
+ logger.class.should == ActiveSupport::BufferedLogger
19
+ end
20
+
21
+ it 'should create a logger of level INFO' do
22
+ logger.level.should == ActiveSupport::BufferedLogger::Severity::INFO
23
+ end
24
+
25
+ end