crafterm-sprinkle 0.1.0
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.
- data/CREDITS +11 -0
- data/History.txt +4 -0
- data/MIT-LICENSE +20 -0
- data/Manifest.txt +55 -0
- data/README.txt +218 -0
- data/Rakefile +4 -0
- data/bin/sprinkle +79 -0
- data/config/hoe.rb +70 -0
- data/config/requirements.rb +17 -0
- data/examples/merb/deploy.rb +5 -0
- data/examples/rails/README +15 -0
- data/examples/rails/deploy.rb +2 -0
- data/examples/rails/packages/database.rb +9 -0
- data/examples/rails/packages/essential.rb +6 -0
- data/examples/rails/packages/rails.rb +28 -0
- data/examples/rails/packages/search.rb +11 -0
- data/examples/rails/packages/server.rb +28 -0
- data/examples/rails/rails.rb +71 -0
- data/lib/sprinkle/actors/capistrano.rb +80 -0
- data/lib/sprinkle/deployment.rb +33 -0
- data/lib/sprinkle/extensions/arbitrary_options.rb +10 -0
- data/lib/sprinkle/extensions/array.rb +7 -0
- data/lib/sprinkle/extensions/blank_slate.rb +5 -0
- data/lib/sprinkle/extensions/dsl_accessor.rb +15 -0
- data/lib/sprinkle/extensions/string.rb +10 -0
- data/lib/sprinkle/extensions/symbol.rb +7 -0
- data/lib/sprinkle/installers/apt.rb +20 -0
- data/lib/sprinkle/installers/gem.rb +31 -0
- data/lib/sprinkle/installers/installer.rb +47 -0
- data/lib/sprinkle/installers/rake.rb +16 -0
- data/lib/sprinkle/installers/source.rb +137 -0
- data/lib/sprinkle/package.rb +76 -0
- data/lib/sprinkle/policy.rb +84 -0
- data/lib/sprinkle/script.rb +13 -0
- data/lib/sprinkle/version.rb +9 -0
- data/lib/sprinkle.rb +29 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/sprinkle/actors/capistrano_spec.rb +150 -0
- data/spec/sprinkle/deployment_spec.rb +80 -0
- data/spec/sprinkle/extensions/array_spec.rb +19 -0
- data/spec/sprinkle/extensions/string_spec.rb +21 -0
- data/spec/sprinkle/installers/apt_spec.rb +46 -0
- data/spec/sprinkle/installers/gem_spec.rb +64 -0
- data/spec/sprinkle/installers/installer_spec.rb +125 -0
- data/spec/sprinkle/installers/source_spec.rb +315 -0
- data/spec/sprinkle/package_spec.rb +203 -0
- data/spec/sprinkle/policy_spec.rb +110 -0
- data/spec/sprinkle/script_spec.rb +51 -0
- data/spec/sprinkle/sprinkle_spec.rb +25 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- metadata +137 -0
@@ -0,0 +1,315 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe Sprinkle::Installers::Source do
|
4
|
+
include Sprinkle::Deployment
|
5
|
+
|
6
|
+
before do
|
7
|
+
@source = 'ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p111.tar.gz'
|
8
|
+
|
9
|
+
@deployment = deployment do
|
10
|
+
delivery :capistrano
|
11
|
+
source do
|
12
|
+
prefix '/usr'
|
13
|
+
archives '/usr/archives'
|
14
|
+
builds '/usr/builds'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
@installer = create_source @source do
|
19
|
+
prefix '/usr/local'
|
20
|
+
archives '/usr/local/archives'
|
21
|
+
builds '/usr/local/builds'
|
22
|
+
|
23
|
+
enable %w( headers ssl deflate so )
|
24
|
+
disable %w( cache proxy rewrite )
|
25
|
+
|
26
|
+
with %w( debug extras )
|
27
|
+
without %w( fancyisms )
|
28
|
+
end
|
29
|
+
|
30
|
+
@installer.defaults(@deployment)
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_source(source, version = nil, &block)
|
34
|
+
@package = mock(Sprinkle::Package, :name => 'package', :version => version)
|
35
|
+
Sprinkle::Installers::Source.new(@package, source, &block)
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'when created' do
|
39
|
+
|
40
|
+
it 'should accept a source archive name to install' do
|
41
|
+
@installer.source.should == @source
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'before installation' do
|
47
|
+
|
48
|
+
before do
|
49
|
+
@settings = { :prefix => '/usr/local', :archives => '/usr/local/tmp', :builds => '/usr/local/stage' }
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should fail if no installation area has been specified' do
|
53
|
+
@settings.delete(:prefix)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should fail if no build area has been specified' do
|
57
|
+
@settings.delete(:builds)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should fail if no source download area has been specified' do
|
61
|
+
@settings.delete(:archives)
|
62
|
+
end
|
63
|
+
|
64
|
+
after do
|
65
|
+
@settings.each { |k, v| @installer.send k, v }
|
66
|
+
lambda { @installer.install_sequence }.should raise_error
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
describe 'customized configuration' do
|
72
|
+
|
73
|
+
it 'should support specification of "enable" options' do
|
74
|
+
@installer.enable.should == %w( headers ssl deflate so )
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should support specification of "disable" options' do
|
78
|
+
@installer.disable.should == %w( cache proxy rewrite )
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should support specification of "with" options' do
|
82
|
+
@installer.with.should == %w( debug extras )
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should support specification of "without" options' do
|
86
|
+
@installer.without.should == %w( fancyisms )
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should support customized build area' do
|
90
|
+
@installer.prefix.should == '/usr/local'
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should support customized source area' do
|
94
|
+
@installer.archives.should == '/usr/local/archives'
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should support customized install area' do
|
98
|
+
@installer.builds.should == '/usr/local/builds'
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
describe 'during gnu source archive style installation' do
|
104
|
+
|
105
|
+
it 'should prepare the build, installation and source archives area' do
|
106
|
+
@installer.should_receive(:prepare).and_return(
|
107
|
+
[
|
108
|
+
'mkdir -p /usr/local',
|
109
|
+
'mkdir -p /usr/local/builds',
|
110
|
+
'mkdir -p /usr/local/archives'
|
111
|
+
]
|
112
|
+
)
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should download the source archive' do
|
117
|
+
@installer.should_receive(:download).and_return(
|
118
|
+
[
|
119
|
+
"wget -cq --directory-prefix='/usr/local/archives' #{@source}"
|
120
|
+
]
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should extract the source archive' do
|
125
|
+
@installer.should_receive(:extract).and_return(
|
126
|
+
[
|
127
|
+
"bash -c 'cd /usr/local/builds && tar xzf /usr/local/archives/ruby-1.8.6-p111.tar.gz"
|
128
|
+
]
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should configure the source' do
|
133
|
+
enable = %w( headers ssl deflate so ).inject([]) { |m, value| m << "--enable-#{value}"; m }
|
134
|
+
disable = %w( cache proxy rewrite ).inject([]) { |m, value| m << "--disable-#{value}"; m }
|
135
|
+
|
136
|
+
with = %w( debug extras ).inject([]) { |m, value| m << "--with-#{value}"; m }
|
137
|
+
without = %w( fancyisms ).inject([]) { |m, value| m << "--without-#{value}"; m }
|
138
|
+
|
139
|
+
options = "#{enable.join(' ')} #{disable.join(' ')} #{with.join(' ')} #{without.join(' ')}"
|
140
|
+
|
141
|
+
@installer.should_receive(:build).and_return(
|
142
|
+
[
|
143
|
+
"bash -c 'cd /usr/local/builds && ./configure --silent --prefix /usr/local #{options} > #{@package.name}-configure.log 2>&1'"
|
144
|
+
]
|
145
|
+
)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should build the source' do
|
149
|
+
@installer.should_receive(:build).and_return(
|
150
|
+
[
|
151
|
+
"bash -c 'cd /usr/local/builds && make > #{@package.name}-build.log 2>&1'"
|
152
|
+
]
|
153
|
+
)
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'should install the source' do
|
157
|
+
@installer.should_receive(:install).and_return(
|
158
|
+
[
|
159
|
+
"bash -c 'cd /usr/local/builds && make install > #{@package.name}-install.log 2>&1'"
|
160
|
+
]
|
161
|
+
)
|
162
|
+
end
|
163
|
+
|
164
|
+
describe 'during a customized install' do
|
165
|
+
|
166
|
+
before do
|
167
|
+
@installer = create_source @source do
|
168
|
+
custom_install 'ruby setup.rb'
|
169
|
+
end
|
170
|
+
|
171
|
+
@installer.defaults(@deployment)
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'should store the custom insatll commands' do
|
175
|
+
@installer.options[:custom_install].should == 'ruby setup.rb'
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'should identify as having a custom install command' do
|
179
|
+
@installer.should be_custom_install
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'should not configure the source automatically' do
|
183
|
+
@installer.should_receive(:configure).and_return([])
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'should not build the source automatically' do
|
187
|
+
@installer.should_receive(:build).and_return([])
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should install the source using a custom installation command' do
|
191
|
+
@installer.send(:custom_install_commands).should == [ "bash -c 'cd /usr/builds/ruby-1.8.6-p111 && ruby setup.rb >> package-install.log 2>&1'" ]
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'should be run relative to the source build area' do
|
195
|
+
@installer.send(:custom_install_commands).first.should =~ %r{cd /usr/builds/ruby-1.8.6-p111}
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
after do
|
201
|
+
@installer.send :install_sequence
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
describe 'pre stage commands' do
|
207
|
+
|
208
|
+
before do
|
209
|
+
@commands = {
|
210
|
+
:prepare => %w( prepare1 prepare2 ),
|
211
|
+
:download => %w( down1 down2 ),
|
212
|
+
:extract => %w( ex1 ex2 ),
|
213
|
+
:configure => %w( conf1 conf2 ),
|
214
|
+
:build => %w( build1 build2 ),
|
215
|
+
:install => %w( install1 install2 )
|
216
|
+
}
|
217
|
+
|
218
|
+
@installer = create_source @source
|
219
|
+
@commands.each { |k, v| @installer.pre k, *v }
|
220
|
+
@installer.defaults(@deployment)
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'should run all pre-prepare commands' do
|
224
|
+
@commands.each { |k, v| @installer.should_receive(:pre_commands).with(k).and_return(v) }
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'should be run relative to the source build area' do
|
228
|
+
@commands.each { |stage, command| @installer.send(:pre_commands, stage).first.should =~ %r{cd /usr/builds/ruby-1.8.6-p111} }
|
229
|
+
end
|
230
|
+
|
231
|
+
after do
|
232
|
+
@installer.send :install_sequence
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
describe 'post stage commands' do
|
238
|
+
|
239
|
+
before do
|
240
|
+
@commands = {
|
241
|
+
:prepare => %w( prepare1 prepare2 ),
|
242
|
+
:download => %w( down1 down2 ),
|
243
|
+
:extract => %w( ex1 ex2 ),
|
244
|
+
:configure => %w( conf1 conf2 ),
|
245
|
+
:build => %w( build1 build2 ),
|
246
|
+
:install => %w( install1 install2 )
|
247
|
+
}
|
248
|
+
|
249
|
+
@installer = create_source @source
|
250
|
+
@commands.each { |k, v| @installer.post k, *v }
|
251
|
+
@installer.defaults(@deployment)
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'should run all post-prepare commands' do
|
255
|
+
@commands.each { |k, v| @installer.should_receive(:post_commands).with(k).and_return(v) }
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'should be run relative to the source build area' do
|
259
|
+
@commands.each { |stage, command| @installer.send(:post_commands, stage).first.should =~ %r{cd /usr/builds/ruby-1.8.6-p111} }
|
260
|
+
end
|
261
|
+
|
262
|
+
after do
|
263
|
+
@installer.send :install_sequence
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
describe 'install sequence' do
|
269
|
+
|
270
|
+
it 'should prepare, then download, then extract, then configure, then build, then install' do
|
271
|
+
%w( prepare download extract configure build install ).each do |stage|
|
272
|
+
@installer.should_receive(stage).ordered.and_return([])
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
after do
|
277
|
+
@installer.send :install_sequence
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
281
|
+
|
282
|
+
describe 'source extraction' do
|
283
|
+
|
284
|
+
it 'should support tgz archives' do
|
285
|
+
@installer.source = 'blah.tgz'
|
286
|
+
@extraction = 'tar xzf'
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'should support tar.gz archives' do
|
290
|
+
@installer.source = 'blah.tgz'
|
291
|
+
@extraction = 'tar xzf'
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'should support tar.bz2 archives' do
|
295
|
+
@installer.source = 'blah.tar.bz2'
|
296
|
+
@extraction = 'tar xjf'
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'should support tb2 archives' do
|
300
|
+
@installer.source = 'blah.tb2'
|
301
|
+
@extraction = 'tar xjf'
|
302
|
+
end
|
303
|
+
|
304
|
+
it 'should support zip archives' do
|
305
|
+
@installer.source = 'blah.zip'
|
306
|
+
@extraction = 'unzip'
|
307
|
+
end
|
308
|
+
|
309
|
+
after do
|
310
|
+
@installer.send(:extract_command).should == @extraction
|
311
|
+
end
|
312
|
+
|
313
|
+
end
|
314
|
+
|
315
|
+
end
|
@@ -0,0 +1,203 @@
|
|
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
|
+
describe Sprinkle::Package, 'when created' do
|
13
|
+
|
14
|
+
it 'should be invalid without a block descriptor' do
|
15
|
+
lambda { package @name }.should raise_error
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should be invalid without a name' do
|
19
|
+
lambda { package nil, &@empty }.should raise_error
|
20
|
+
lambda { package @name, &@empty }.should_not raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should optionally accept a description' do
|
24
|
+
pkg = package @name do
|
25
|
+
description 'my package description'
|
26
|
+
end
|
27
|
+
pkg.description.should == 'my package description'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should optionally accept a version' do
|
31
|
+
pkg = package @name do
|
32
|
+
version '2.0.2'
|
33
|
+
end
|
34
|
+
pkg.version.should == '2.0.2'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should optionally accept an installer' do
|
38
|
+
pkg = package @name do
|
39
|
+
gem 'rails'
|
40
|
+
end
|
41
|
+
pkg.installer.should_not be_nil
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should optionally accept dependencies' do
|
45
|
+
pkg = package @name do
|
46
|
+
requires :webserver, :database
|
47
|
+
end
|
48
|
+
pkg.dependencies.should == [:webserver, :database]
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should optionally define a virtual package implementation' do
|
52
|
+
pkg = package @name, :provides => :database do; end
|
53
|
+
pkg.provides.should == :database
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should be able to represent itself as a string' do
|
57
|
+
pkg = package @name do; end
|
58
|
+
pkg.to_s.should == @name
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
describe Sprinkle::Package, 'helper method' do
|
64
|
+
|
65
|
+
it 'should added new packages to the global package hash' do
|
66
|
+
pkg = package @name do; end
|
67
|
+
Sprinkle::Package::PACKAGES[@name].should == pkg
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should add the new package to the provides list if specified' do
|
71
|
+
pkg = package @name, :provides => :database do; end
|
72
|
+
Sprinkle::Package::PACKAGES[:database].last.should == pkg
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
describe Sprinkle::Package, 'installer configuration' do
|
78
|
+
|
79
|
+
it 'should optionally accept an apt installer' do
|
80
|
+
pkg = package @name do
|
81
|
+
apt %w( deb1 deb2 )
|
82
|
+
end
|
83
|
+
pkg.should respond_to(:apt)
|
84
|
+
pkg.installer.class.should == Sprinkle::Installers::Apt
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should optionally accept a gem installer' do
|
88
|
+
pkg = package @name do
|
89
|
+
gem 'gem'
|
90
|
+
end
|
91
|
+
pkg.should respond_to(:gem)
|
92
|
+
pkg.installer.class.should == Sprinkle::Installers::Gem
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should optionally accept a source installer' do
|
96
|
+
pkg = package @name do
|
97
|
+
source 'archive'
|
98
|
+
end
|
99
|
+
pkg.should respond_to(:source)
|
100
|
+
pkg.installer.class.should == Sprinkle::Installers::Source
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
describe Sprinkle::Package, 'with a source installer' do
|
106
|
+
|
107
|
+
it 'should optionally accept a block containing customisations' do
|
108
|
+
pkg = package @name do
|
109
|
+
source 'archive' do; end
|
110
|
+
end
|
111
|
+
pkg.should respond_to(:source)
|
112
|
+
pkg.installer.class.should == Sprinkle::Installers::Source
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should automatically add a build essential dependency' do
|
116
|
+
pkg = package @name do
|
117
|
+
source 'archive'
|
118
|
+
end
|
119
|
+
pkg.dependencies.should include(:build_essential)
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
describe Sprinkle::Package, 'with an gem installer' do
|
125
|
+
|
126
|
+
it 'should automatically add a rubygems dependency' do
|
127
|
+
pkg = package @name do
|
128
|
+
gem 'gem'
|
129
|
+
end
|
130
|
+
pkg.dependencies.should include(:rubygems)
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
describe Sprinkle::Package, 'when processing' do
|
136
|
+
|
137
|
+
before do
|
138
|
+
@deployment = mock(Sprinkle::Deployment)
|
139
|
+
@roles = [ :app, :db ]
|
140
|
+
@installer = mock(Sprinkle::Installers::Installer, :defaults => true, :process => true)
|
141
|
+
@package = package @name do; end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe Sprinkle::Package, 'with an installer' do
|
145
|
+
|
146
|
+
before do
|
147
|
+
@package.installer = @installer
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should configure itself against the deployment context' do
|
151
|
+
@installer.should_receive(:defaults).with(@deployment).and_return
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should request the installer to process itself' do
|
155
|
+
@installer.should_receive(:process).with(@roles).and_return
|
156
|
+
end
|
157
|
+
|
158
|
+
after do
|
159
|
+
@package.process(@deployment, @roles)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe Sprinkle::Package, 'without an installer' do
|
164
|
+
|
165
|
+
it 'should not request the installer to process if the package is a metapackage' do
|
166
|
+
@installer.should_not_receive(:process)
|
167
|
+
@package.process(@deployment, @roles)
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
describe Sprinkle::Package, 'hierarchies' do
|
175
|
+
|
176
|
+
before do
|
177
|
+
@a = package :a do; requires :b; end
|
178
|
+
@b = package :b do; requires :c; end
|
179
|
+
@c = package :c do; end
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'should be able to return a dependency hierarchy tree' do
|
183
|
+
@a.tree.flatten.should == [ @c, @b, @a ]
|
184
|
+
@b.tree.flatten.should == [ @c, @b ]
|
185
|
+
@c.tree.flatten.should == [ @c ]
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'should optionally accept a block to call upon item in the tree during hierarchy traversal' do
|
189
|
+
@count = 0
|
190
|
+
@a.tree do
|
191
|
+
@count += 1
|
192
|
+
end
|
193
|
+
@count.should == 2
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'should maintain a depth count of how deep the hierarchy is' do
|
197
|
+
@b.should_receive(:tree).with(2).and_return([@b])
|
198
|
+
@a.tree do; end
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
@@ -0,0 +1,110 @@
|
|
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 optionally accept package dependencies with versions' do
|
29
|
+
p = policy @name, :roles => :app do; end
|
30
|
+
p.requires :appserver, :version => 2
|
31
|
+
p.packages.should == [ :appserver ]
|
32
|
+
pending 'requires version checking implementation'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should add itself to the global policy list' do
|
36
|
+
sz = Sprinkle::Policy::POLICIES.size
|
37
|
+
p = policy @name, :roles => :app do; end
|
38
|
+
Sprinkle::Policy::POLICIES.size.should == sz + 1
|
39
|
+
Sprinkle::Policy::POLICIES.last.should == p
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'with packages' do
|
45
|
+
include Sprinkle::Package
|
46
|
+
|
47
|
+
before do
|
48
|
+
@deployment = mock(Sprinkle::Deployment)
|
49
|
+
Sprinkle::Package::PACKAGES.clear # reset full package list before each spec is run
|
50
|
+
|
51
|
+
@a = package :a do; requires :b; requires :c; end
|
52
|
+
@b = package :b, :provides => :xyz do; end
|
53
|
+
@c = package :c, :provides => :abc do; end
|
54
|
+
@d = package :d, :provides => :abc do; end
|
55
|
+
|
56
|
+
@policy = policy :test, :roles => :app do; requires :a; end
|
57
|
+
$terminal.stub!(:choose).and_return(:c) # stub out highline asking questions
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'when applying' do
|
61
|
+
include Sprinkle::Package
|
62
|
+
|
63
|
+
it 'should determine the packages to install via the hierarchy dependency tree of each package in the policy' do
|
64
|
+
@a.should_receive(:process).and_return
|
65
|
+
@b.should_receive(:process).and_return
|
66
|
+
@c.should_receive(:process).and_return
|
67
|
+
@d.should_not_receive(:process)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should normalize (ie remove duplicates from) the installation order of all packages including dependencies' do
|
71
|
+
@e = package :e do; requires :b; end
|
72
|
+
@policy.requires :e
|
73
|
+
|
74
|
+
@a.should_receive(:process).once.and_return
|
75
|
+
@b.should_receive(:process).once.and_return
|
76
|
+
@c.should_receive(:process).once.and_return
|
77
|
+
@d.should_not_receive(:process)
|
78
|
+
@e.should_receive(:process).once.and_return
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'containing package dependencies with versions' do
|
83
|
+
|
84
|
+
it 'should be invalid if the specified package does not exist'
|
85
|
+
it 'should ignore any packages of the same name that have other versions'
|
86
|
+
it 'should select the correct package version when applying'
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'containing virtual packages' do
|
91
|
+
|
92
|
+
it 'should automatically select a concrete package implementation for a virtual one when there exists only one possible selection' do
|
93
|
+
@policy = policy :virtual, :roles => :app do; requires :xyz; end
|
94
|
+
Sprinkle::Package::PACKAGES[:xyz].should == [ @b ]
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should ask the user for the concrete package implementation to use for a virtual one when more than one possible choice exists' do
|
98
|
+
@policy = policy :virtual, :roles => :app do; requires :abc; end
|
99
|
+
Sprinkle::Package::PACKAGES[:abc].should include(@c)
|
100
|
+
Sprinkle::Package::PACKAGES[:abc].should include(@d)
|
101
|
+
$terminal.should_receive(:choose).and_return(:c)
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
after do
|
107
|
+
@policy.process(@deployment)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
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
|