powcloud-sprinkle 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/.gitignore +5 -0
  2. data/CREDITS +33 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.markdown +241 -0
  5. data/Rakefile +50 -0
  6. data/VERSION +1 -0
  7. data/bin/sprinkle +90 -0
  8. data/examples/packages/build_essential.rb +9 -0
  9. data/examples/packages/databases/mysql.rb +13 -0
  10. data/examples/packages/databases/sqlite3.rb +16 -0
  11. data/examples/packages/phusion.rb +55 -0
  12. data/examples/packages/ruby/rails.rb +9 -0
  13. data/examples/packages/ruby/ruby.rb +17 -0
  14. data/examples/packages/ruby/rubygems.rb +17 -0
  15. data/examples/packages/scm/git.rb +11 -0
  16. data/examples/packages/scm/subversion.rb +4 -0
  17. data/examples/packages/servers/apache.rb +15 -0
  18. data/examples/rails/README +15 -0
  19. data/examples/rails/deploy.rb +2 -0
  20. data/examples/rails/packages/database.rb +9 -0
  21. data/examples/rails/packages/essential.rb +9 -0
  22. data/examples/rails/packages/rails.rb +29 -0
  23. data/examples/rails/packages/scm.rb +11 -0
  24. data/examples/rails/packages/search.rb +11 -0
  25. data/examples/rails/packages/server.rb +28 -0
  26. data/examples/rails/rails.rb +73 -0
  27. data/examples/sprinkle/sprinkle.rb +38 -0
  28. data/lib/sprinkle/actors/actors.rb +17 -0
  29. data/lib/sprinkle/actors/capistrano.rb +140 -0
  30. data/lib/sprinkle/actors/local.rb +37 -0
  31. data/lib/sprinkle/actors/ssh.rb +123 -0
  32. data/lib/sprinkle/actors/vlad.rb +78 -0
  33. data/lib/sprinkle/configurable.rb +31 -0
  34. data/lib/sprinkle/deployment.rb +73 -0
  35. data/lib/sprinkle/extensions/arbitrary_options.rb +10 -0
  36. data/lib/sprinkle/extensions/array.rb +5 -0
  37. data/lib/sprinkle/extensions/blank_slate.rb +5 -0
  38. data/lib/sprinkle/extensions/dsl_accessor.rb +15 -0
  39. data/lib/sprinkle/extensions/string.rb +10 -0
  40. data/lib/sprinkle/extensions/symbol.rb +7 -0
  41. data/lib/sprinkle/installers/apt.rb +52 -0
  42. data/lib/sprinkle/installers/binary.rb +46 -0
  43. data/lib/sprinkle/installers/bsd_port.rb +33 -0
  44. data/lib/sprinkle/installers/deb.rb +38 -0
  45. data/lib/sprinkle/installers/freebsd_pkg.rb +37 -0
  46. data/lib/sprinkle/installers/freebsd_portinstall.rb +36 -0
  47. data/lib/sprinkle/installers/gem.rb +64 -0
  48. data/lib/sprinkle/installers/install_package.rb +79 -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/noop.rb +20 -0
  52. data/lib/sprinkle/installers/openbsd_pkg.rb +47 -0
  53. data/lib/sprinkle/installers/opensolaris_pkg.rb +43 -0
  54. data/lib/sprinkle/installers/push_text.rb +45 -0
  55. data/lib/sprinkle/installers/rake.rb +37 -0
  56. data/lib/sprinkle/installers/rpm.rb +37 -0
  57. data/lib/sprinkle/installers/smart.rb +29 -0
  58. data/lib/sprinkle/installers/source.rb +190 -0
  59. data/lib/sprinkle/installers/transfer.rb +164 -0
  60. data/lib/sprinkle/installers/yum.rb +37 -0
  61. data/lib/sprinkle/package.rb +309 -0
  62. data/lib/sprinkle/policy.rb +125 -0
  63. data/lib/sprinkle/script.rb +23 -0
  64. data/lib/sprinkle/verifiers/directory.rb +16 -0
  65. data/lib/sprinkle/verifiers/executable.rb +53 -0
  66. data/lib/sprinkle/verifiers/file.rb +26 -0
  67. data/lib/sprinkle/verifiers/package.rb +26 -0
  68. data/lib/sprinkle/verifiers/process.rb +21 -0
  69. data/lib/sprinkle/verifiers/rpm.rb +21 -0
  70. data/lib/sprinkle/verifiers/ruby.rb +25 -0
  71. data/lib/sprinkle/verifiers/symlink.rb +30 -0
  72. data/lib/sprinkle/verify.rb +114 -0
  73. data/lib/sprinkle.rb +32 -0
  74. data/script/console +8 -0
  75. data/script/destroy +14 -0
  76. data/script/generate +14 -0
  77. data/spec/spec.opts +1 -0
  78. data/spec/spec_helper.rb +17 -0
  79. data/spec/sprinkle/actors/capistrano_spec.rb +265 -0
  80. data/spec/sprinkle/actors/local_spec.rb +29 -0
  81. data/spec/sprinkle/configurable_spec.rb +46 -0
  82. data/spec/sprinkle/deployment_spec.rb +80 -0
  83. data/spec/sprinkle/extensions/array_spec.rb +19 -0
  84. data/spec/sprinkle/extensions/string_spec.rb +21 -0
  85. data/spec/sprinkle/installers/apt_spec.rb +70 -0
  86. data/spec/sprinkle/installers/bsd_port_spec.rb +42 -0
  87. data/spec/sprinkle/installers/freebsd_pkg_spec.rb +49 -0
  88. data/spec/sprinkle/installers/freebsd_portinstall_spec.rb +42 -0
  89. data/spec/sprinkle/installers/gem_spec.rb +107 -0
  90. data/spec/sprinkle/installers/installer_spec.rb +151 -0
  91. data/spec/sprinkle/installers/mac_port_spec.rb +42 -0
  92. data/spec/sprinkle/installers/noop_spec.rb +23 -0
  93. data/spec/sprinkle/installers/openbsd_pkg_spec.rb +49 -0
  94. data/spec/sprinkle/installers/opensolaris_pkg_spec.rb +49 -0
  95. data/spec/sprinkle/installers/push_text_spec.rb +66 -0
  96. data/spec/sprinkle/installers/rake_spec.rb +29 -0
  97. data/spec/sprinkle/installers/rpm_spec.rb +50 -0
  98. data/spec/sprinkle/installers/source_spec.rb +371 -0
  99. data/spec/sprinkle/installers/transfer_spec.rb +98 -0
  100. data/spec/sprinkle/installers/yum_spec.rb +49 -0
  101. data/spec/sprinkle/package_spec.rb +466 -0
  102. data/spec/sprinkle/policy_spec.rb +126 -0
  103. data/spec/sprinkle/script_spec.rb +51 -0
  104. data/spec/sprinkle/sprinkle_spec.rb +25 -0
  105. data/spec/sprinkle/verify_spec.rb +174 -0
  106. metadata +244 -0
data/lib/sprinkle.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+
4
+ # Use active supports auto load mechanism
5
+ ActiveSupport::Dependencies.load_paths << File.dirname(__FILE__)
6
+
7
+ # Configure active support to log auto-loading of dependencies
8
+ #ActiveSupport::Dependencies::RAILS_DEFAULT_LOGGER = Logger.new($stdout)
9
+ #ActiveSupport::Dependencies.log_activity = true
10
+
11
+ # Load up extensions to existing classes
12
+ Dir[File.dirname(__FILE__) + '/sprinkle/extensions/*.rb'].each { |e| require e }
13
+ # Load up the verifiers so they can register themselves
14
+ Dir[File.dirname(__FILE__) + '/sprinkle/verifiers/*.rb'].each { |e| require e }
15
+
16
+ # Configuration options
17
+ module Sprinkle
18
+ OPTIONS = { :testing => false, :verbose => false, :force => false }
19
+ end
20
+
21
+ # Object is extended to give the package, policy, and deployment methods. To
22
+ # read about each method, see the corresponding module which is included.
23
+ #--
24
+ # Define a logging target and understand packages, policies and deployment DSL
25
+ #++
26
+ class Object
27
+ include Sprinkle::Package, Sprinkle::Policy, Sprinkle::Deployment
28
+
29
+ def logger # :nodoc:
30
+ @@__log__ ||= ActiveSupport::BufferedLogger.new($stdout, ActiveSupport::BufferedLogger::Severity::INFO)
31
+ end
32
+ end
data/script/console ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/sprinkle.rb'}"
7
+ puts "Loading sprinkle gem"
8
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,17 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+ require 'sprinkle'
11
+
12
+ module Kernel
13
+ def logger
14
+ @@__log_file__ ||= StringIO.new
15
+ @@__log__ = ActiveSupport::BufferedLogger.new @@__log_file__
16
+ end
17
+ end
@@ -0,0 +1,265 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Sprinkle::Actors::Capistrano do
4
+
5
+ before do
6
+ @recipes = 'deploy'
7
+ @cap = ::Capistrano::Configuration.new
8
+ ::Capistrano::Configuration.stub!(:new).and_return(@cap)
9
+ @cap.stub!(:load).and_return
10
+ end
11
+
12
+ def create_cap(&block)
13
+ Sprinkle::Actors::Capistrano.new &block
14
+ end
15
+
16
+ describe 'when created' do
17
+
18
+ it 'should create a new capistrano object' do
19
+ ::Capistrano::Configuration.should_receive(:new).and_return(@cap)
20
+ create_cap
21
+ end
22
+
23
+ describe 'when verbose' do
24
+
25
+ before do
26
+ Sprinkle::OPTIONS[:verbose] = true
27
+ end
28
+
29
+ it 'should set verbose logging on the capistrano object' do
30
+ @cap = create_cap
31
+ @cap.config.logger.level.should == ::Capistrano::Logger::INFO
32
+ end
33
+
34
+ end
35
+
36
+ describe 'when not verbose' do
37
+
38
+ before do
39
+ Sprinkle::OPTIONS[:verbose] = false
40
+ end
41
+
42
+ it 'should set quiet logging on the capistrano object' do
43
+ @cap = create_cap
44
+ @cap.config.logger.level.should == ::Capistrano::Logger::IMPORTANT
45
+ end
46
+
47
+ end
48
+
49
+ describe 'with a block' do
50
+
51
+ before do
52
+ @actor = create_cap do
53
+ recipes 'cool gear' # default is deploy
54
+ end
55
+ end
56
+
57
+ it 'should evaluate the block against the actor instance' do
58
+ @actor.loaded_recipes.should include('cool gear')
59
+ end
60
+
61
+ end
62
+
63
+ describe 'without a block' do
64
+
65
+ it 'should automatically load the default capistrano configuration' do
66
+ @cap.should_receive(:load).with('deploy').and_return
67
+ end
68
+
69
+ after do
70
+ @actor = create_cap
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+
77
+ describe 'recipes' do
78
+
79
+ it 'should add the recipe location to an internal store' do
80
+ @cap = create_cap do
81
+ recipes 'deploy'
82
+ end
83
+ @cap.loaded_recipes.should == [ @recipes ]
84
+ end
85
+
86
+ it 'should load the given recipe' do
87
+ @cap.should_receive(:load).with(@recipes).and_return
88
+ create_cap
89
+ end
90
+
91
+ end
92
+
93
+ describe 'processing commands' do
94
+
95
+ before do
96
+ @commands = %w( op1 op2 )
97
+ @roles = %w( app )
98
+ @name = 'name'
99
+
100
+ @cap = create_cap do; recipes 'deploy'; end
101
+ @cap.stub!(:run).and_return
102
+
103
+ @testing_errors = false
104
+ end
105
+
106
+ it 'should dynamically create a capistrano task containing the commands' do
107
+ @cap.config.should_receive(:task).and_return
108
+ end
109
+
110
+ it 'should invoke capistrano task after creation' do
111
+ @cap.should_receive(:run).with(@name).and_return
112
+ end
113
+
114
+ it 'should raise capistrano errors when suppressing parameter is not set' do
115
+ @testing_errors = true
116
+
117
+ @cap.should_receive(:run).and_raise(::Capistrano::CommandError)
118
+ lambda { @cap.process @name, @commands, @roles }.should raise_error(::Capistrano::CommandError)
119
+ end
120
+
121
+ it 'should not raise errors and instead return false when suppressing parameter is set' do
122
+ @testing_errors = true
123
+
124
+ @cap.should_receive(:run).and_raise(::Capistrano::CommandError)
125
+
126
+ value = nil
127
+ lambda { value = @cap.process(@name, @commands, @roles, true) }.should_not raise_error(::Capistrano::CommandError)
128
+
129
+ value.should_not be
130
+ end
131
+
132
+ after do
133
+ @cap.process @name, @commands, @roles unless @testing_errors
134
+ end
135
+
136
+ end
137
+
138
+ describe 'transferring files' do
139
+
140
+ before do
141
+ @source = 'source'
142
+ @dest = 'dest'
143
+ @roles = %w( app )
144
+ @name = 'name'
145
+
146
+ @cap = create_cap do; recipes 'deploy'; end
147
+ @cap.stub!(:run).and_return
148
+
149
+ @testing_errors = false
150
+ end
151
+
152
+ it 'should dynamically create a capistrano task containing calling upload' do
153
+ @cap.config.should_receive(:task).and_return
154
+ end
155
+
156
+ it 'should invoke capistrano task after creation' do
157
+ @cap.should_receive(:run).with(@name).and_return
158
+ end
159
+
160
+ it 'should raise capistrano errors when suppressing parameter is not set' do
161
+ @testing_errors = true
162
+
163
+ @cap.should_receive(:run).and_raise(::Capistrano::CommandError)
164
+ lambda { @cap.process @name, @commands, @roles }.should raise_error(::Capistrano::CommandError)
165
+ end
166
+
167
+ it 'should not raise errors and instead return false when suppressing parameter is set' do
168
+ @testing_errors = true
169
+
170
+ @cap.should_receive(:run).and_raise(::Capistrano::CommandError)
171
+
172
+ value = nil
173
+ lambda { value = @cap.process(@name, @commands, @roles, true) }.should_not raise_error(::Capistrano::CommandError)
174
+
175
+ value.should_not be
176
+ end
177
+
178
+ after do
179
+ @cap.transfer @name, @source, @dest, @roles unless @testing_errors
180
+ end
181
+ end
182
+
183
+ describe 'generated task' do
184
+
185
+ before do
186
+ @commands = %w( op1 op2 )
187
+ @roles = %w( app )
188
+ @name = 'name'
189
+
190
+ @cap = create_cap do; recipes 'deploy'; end
191
+ @cap.config.stub!(:fetch).and_return(:sudo)
192
+ @cap.config.stub!(:invoke_command).and_return
193
+ end
194
+
195
+ it 'should use sudo to invoke commands when so configured' do
196
+ @cap.config.should_receive(:fetch).with(:run_method, :sudo).and_return(:sudo)
197
+ end
198
+
199
+ it 'should run the supplied commands' do
200
+ @cap.config.should_receive(:invoke_command).with('op1', :via => :sudo).ordered.and_return
201
+ @cap.config.should_receive(:invoke_command).with('op2', :via => :sudo).ordered.and_return
202
+ end
203
+
204
+ it 'should be applicable for the supplied roles' do
205
+ @cap.stub!(:run).and_return
206
+ @cap.config.should_receive(:task).with(:install_name, :roles => @roles).and_return
207
+ end
208
+
209
+ after do
210
+ @cap.process @name, @commands, @roles
211
+ end
212
+
213
+ end
214
+
215
+ describe 'generated transfer' do
216
+ before do
217
+ @source = 'source'
218
+ @dest = 'dest'
219
+ @roles = %w( app )
220
+ @name = 'name'
221
+
222
+ @cap = create_cap do; recipes 'deploy'; end
223
+ @cap.config.stub!(:upload).and_return
224
+ end
225
+
226
+ it 'should call upload with the source and destination via :scp' do
227
+ @cap.config.should_receive(:upload).with(@source, @dest, :via => :scp, :recursive => true).and_return
228
+ end
229
+
230
+ it 'should be applicable for the supplied roles' do
231
+ @cap.stub!(:run).and_return
232
+ @cap.config.should_receive(:task).with(:install_name, :roles => @roles).and_return
233
+ end
234
+
235
+ after do
236
+ @cap.transfer @name, @source, @dest, @roles
237
+ end
238
+ end
239
+
240
+ describe 'generated transfer when recursive is false' do
241
+ before do
242
+ @source = 'source'
243
+ @dest = 'dest'
244
+ @roles = %w( app )
245
+ @name = 'name'
246
+
247
+ @cap = create_cap do; recipes 'deploy'; end
248
+ @cap.config.stub!(:upload).and_return
249
+ end
250
+
251
+ it 'should call upload with the source and destination via :scp' do
252
+ @cap.config.should_receive(:upload).with(@source, @dest, :via => :scp, :recursive => false).and_return
253
+ end
254
+
255
+ it 'should be applicable for the supplied roles' do
256
+ @cap.stub!(:run).and_return
257
+ @cap.config.should_receive(:task).with(:install_name, :roles => @roles).and_return
258
+ end
259
+
260
+ after do
261
+ @cap.transfer @name, @source, @dest, @roles, false
262
+ end
263
+ end
264
+
265
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Sprinkle::Actors::Local do
4
+
5
+ before do
6
+ @local = Sprinkle::Actors::Local.new
7
+ end
8
+
9
+ describe 'when processing commands' do
10
+
11
+ before do
12
+ @commands = %w( op1 op2 )
13
+ @roles = %w( app )
14
+ @name = 'name'
15
+
16
+ @local.stub!(:system).and_return
17
+ end
18
+
19
+ it 'should run the commands on the local system' do
20
+ @local.should_receive(:system).twice.and_return
21
+ end
22
+
23
+ after do
24
+ @local.process @name, @commands, @roles
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Sprinkle::Configurable do
4
+ module MyPrefix
5
+ class Configurable
6
+ include Sprinkle::Configurable
7
+ end
8
+ end
9
+
10
+ before do
11
+ @configurable = MyPrefix::Configurable.new
12
+ @default = Proc.new { }
13
+ @defaults = { :configurable => @default }
14
+ @deployment.stub!(:defaults).and_return(@defaults)
15
+ @deployment.stub!(:style)
16
+ end
17
+
18
+ it 'should be configurable via external defaults' do
19
+ @configurable.should respond_to(:defaults)
20
+ end
21
+
22
+ it 'should select the defaults for the particular concrete installer class' do
23
+ @deployment.should_receive(:defaults).and_return(@defaults)
24
+ @defaults.should_receive(:[]).with(:configurable).and_return(@default)
25
+ end
26
+
27
+ it 'should configure the installer delivery mechansim' do
28
+ @configurable.should_receive(:instance_eval)
29
+ end
30
+
31
+ it 'should maintain an options hash set arbitrarily via method missing' do
32
+ @configurable.instance_eval do
33
+ hsv 'gts'
34
+ end
35
+ @configurable.hsv.should == 'gts'
36
+ end
37
+
38
+ it 'should allow the delivery instance variable to be accessed' do
39
+ @configurable.delivery = "string"
40
+ @configurable.instance_variable_get(:@delivery).should eql("string")
41
+ end
42
+
43
+ after do
44
+ @configurable.defaults(@deployment)
45
+ end
46
+ end
@@ -0,0 +1,80 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Sprinkle::Deployment do
4
+ include Sprinkle::Deployment
5
+
6
+ def create_deployment(&block)
7
+ deployment do
8
+ delivery :capistrano, &block
9
+
10
+ source do
11
+ prefix '/usr/local'
12
+ end
13
+ end
14
+ end
15
+
16
+ describe 'when created' do
17
+
18
+ it 'should be invalid without a block descriptor' do
19
+ lambda { deployment }.should raise_error
20
+ end
21
+
22
+ it 'should be invalid without a delivery method' do
23
+ lambda { @deployment = deployment do; end }.should raise_error
24
+ end
25
+
26
+ it 'should optionally accept installer defaults' do
27
+ @deployment = create_deployment
28
+ @deployment.should respond_to(:source)
29
+ end
30
+
31
+ it 'should provide installer defaults as a proc when requested' do
32
+ @deployment = create_deployment
33
+ @deployment.defaults[:source].class.should == Proc
34
+ end
35
+
36
+ end
37
+
38
+ describe 'delivery specification' do
39
+
40
+ before do
41
+ @actor = mock(Sprinkle::Actors::Capistrano)
42
+ Sprinkle::Actors::Capistrano.stub!(:new).and_return(@actor)
43
+ end
44
+
45
+ it 'should automatically instantiate the delivery type' do
46
+ @deployment = create_deployment
47
+ @deployment.style.should == @actor
48
+ end
49
+
50
+ it 'should optionally accept a block to pass to the actor' do
51
+ lambda { @deployment = create_deployment }.should_not raise_error
52
+ end
53
+
54
+ describe 'with a block' do
55
+
56
+ it 'should pass the block to the actor for configuration' do
57
+ @deployment = create_deployment do; recipes 'deploy'; end
58
+ end
59
+
60
+ end
61
+ end
62
+
63
+ describe 'when processing policies' do
64
+
65
+ before do
66
+ @policy = mock(Policy, :process => true)
67
+ POLICIES = [ @policy ]
68
+ @deployment = create_deployment
69
+ end
70
+
71
+ it 'should apply all policies, passing itself as the deployment context' do
72
+ @policy.should_receive(:process).with(@deployment).and_return
73
+ end
74
+
75
+ after do
76
+ @deployment.process
77
+ end
78
+ end
79
+
80
+ end