oneblackbear-obbistrano 1.0.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.
Files changed (3) hide show
  1. data/README.txt +23 -0
  2. data/capfile +476 -0
  3. metadata +74 -0
data/README.txt ADDED
@@ -0,0 +1,23 @@
1
+ h1. Automated Server and application deployment
2
+
3
+ h2. Server-wide setup
4
+
5
+ @cap host:setup -s h=xxxx@
6
+ Ensures that there is a setup for each app on the specified server.
7
+ Includes setup of a user, group, apache vhost, mysql login for each app.
8
+
9
+ @cap host:backup -s h=xxxx@
10
+ Trigger a backup of each application stored on the specified server.
11
+
12
+ @cap host:s3backup -s h=xxxx@
13
+ Triggers an Amazon S3 backup of the backup folder.
14
+
15
+
16
+
17
+ h2. Application Level Setup
18
+
19
+ @cap app:deploy -s a=xxxx@
20
+
21
+
22
+ cap app:
23
+
data/capfile ADDED
@@ -0,0 +1,476 @@
1
+ require 'rubygems'
2
+ require 'activeresource'
3
+
4
+ TTL = 86400
5
+ API_PASSWORD = fetch "slicehost_api_key", false
6
+
7
+ class Record < ActiveResource::Base
8
+ self.site = "https://#{API_PASSWORD}@api.slicehost.com/"
9
+ end
10
+
11
+ class Zone < ActiveResource::Base
12
+ self.site = "https://#{API_PASSWORD}@api.slicehost.com/"
13
+ end
14
+
15
+ class Slice < ActiveResource::Base
16
+ self.site = "https://#{API_PASSWORD}@api.slicehost.com/"
17
+ end
18
+
19
+
20
+ desc "Setup Application Config"
21
+ task :config_setup do
22
+ # options = YAML.load(File.read("config.yml"))
23
+ # set :working_server, h rescue nil
24
+ # set :working_app, a rescue nil
25
+ set :root_pass, root rescue nil
26
+ end
27
+ #
28
+ # task :config_write do
29
+ # File.open('config.yml', 'w') { |f| f.puts options.to_yaml }
30
+ # #puts "Hello I'm about to mangle your config file"
31
+ # end
32
+
33
+ namespace :slicehost do
34
+
35
+ desc "Sets up slicehost DNS for each of the servers specified with a role of web."
36
+ task :setup do
37
+ get_slice_ip
38
+ servers = find_servers :roles => :web
39
+ servers.each do |s|
40
+ if !zone = Zone.find(:first, :params => {:origin => "#{s}."})
41
+ zone = Zone.new(:origin => s, :ttl => TTL)
42
+ zone.save
43
+ end
44
+ recordOne = Record.new(:record_type => 'A', :zone_id => zone.id, :name => 'www', :data => "#{slice_ip}")
45
+ recordTwo = Record.new(:record_type => 'A', :zone_id => zone.id, :name => '@', :data => "#{slice_ip}")
46
+ recordThree = Record.new(:record_type => 'A', :zone_id => zone.id, :name => 'beta', :data => "#{slice_ip}")
47
+ recordFour = Record.new(:record_type => 'A', :zone_id => zone.id, :name => zone.origin, :data => "#{slice_ip}")
48
+ recordFive = Record.new(:record_type => 'NS', :zone_id => zone.id, :name => zone.origin, :data => 'ns1.slicehost.net.')
49
+ recordSix = Record.new(:record_type => 'NS', :zone_id => zone.id, :name => zone.origin, :data => 'ns2.slicehost.net.')
50
+ recordSeven = Record.new(:record_type => 'NS', :zone_id => zone.id, :name => zone.origin, :data => 'ns3.slicehost.net.')
51
+ [recordOne, recordTwo, recordThree, recordFour, recordFive, recordSix, recordSeven].each {|r| r.save}
52
+ end
53
+ end
54
+
55
+ task :get_slice_ip do
56
+ set :slice_ip, get_ip(fetch("host", false))
57
+ end
58
+
59
+ desc "Sets up slicehost DNS for Google Apps usage on each of the servers specified with a role of web."
60
+ task :googleapps do
61
+ API_PASSWORD = "#{slicehost_api_key}"
62
+ mx_records = <<-RECORD
63
+ ASPMX.L.GOOGLE.COM.
64
+ ALT1.ASPMX.L.GOOGLE.COM.
65
+ ALT2.ASPMX.L.GOOGLE.COM.
66
+ ASPMX2.GOOGLEMAIL.COM.
67
+ ASPMX3.GOOGLEMAIL.COM.
68
+ RECORD
69
+ servers = find_servers :roles => :web
70
+ servers.each do |s|
71
+ mx_aux = %w[5 10 10 20 20 30 ]
72
+ aux_count = 0
73
+ zone = Zone.find(:first, :params => {:origin => "#{s}."})
74
+ mx_records.each do |rec|
75
+ r = Record.new(:record_type => 'MX', :zone_id => zone.id, :name => "#{s}." , :data => "#{rec}", :aux => mx_aux[aux_count])
76
+ r.save
77
+ aux_count =+ 1
78
+ end
79
+ recordOne = Record.new(:record_type => 'CNAME', :zone_id => zone.id, :name => 'mail', :data => "ghs.google.com.")
80
+ recordTwo = Record.new(:record_type => 'CNAME', :zone_id => zone.id, :name => 'docs', :data => "ghs.google.com.")
81
+ [recordOne, recordTwo].each {|r| r.save}
82
+ end
83
+ end
84
+
85
+ end
86
+
87
+
88
+
89
+
90
+ namespace :host do
91
+
92
+ desc "Checks we have information to proceed with server operations"
93
+ task :config_check do
94
+ config_setup
95
+ "#{working_server}" rescue @parent.logger.log 0,"You need to specify a host to run the operation on. Use cap task -s h=yourhost"
96
+ @use_applications = [ ]
97
+ options["apps"].each do |app, settings|
98
+ @use_applications << app if settings["server"]==working_server
99
+ end
100
+ end
101
+
102
+
103
+ desc "Performs a local backup of the applications and databases on the server"
104
+ task :backup do
105
+ config_check
106
+ @use_applications.each do |app|
107
+ set :working_app, app
108
+ @parent.app.backup
109
+ end
110
+ end
111
+
112
+ desc "Backs up the local backup folder to remote Amazon S3 storage"
113
+ task :s3backup do
114
+ config_check
115
+ end
116
+
117
+
118
+
119
+ end
120
+
121
+ namespace :app do
122
+
123
+
124
+ task :config_check do
125
+ config_setup
126
+ databases rescue set(:databases, ["#{application}"])
127
+ end
128
+
129
+ task :needs_root do
130
+ config_check
131
+ puts "*** This operation needs root access - Please pass in a root password using -s root=password" if !defined? "#{root_pass}"
132
+ exit if !defined? "#{root_pass}"
133
+ end
134
+
135
+
136
+
137
+ # =============================================================================
138
+ # DEPLOYING APPLICATIONS
139
+ # =============================================================================
140
+
141
+ desc "Uses the specified repository to deploy an application. Also checks for correct versions of PHPWax and plugins."
142
+ task :deploy do
143
+ config_check
144
+ deploy_check
145
+ php_wax_deploy if defined? "#{phpwax}"
146
+ cms_deploy if defined? "#{cms}"
147
+ end
148
+
149
+ task :deploy_check do
150
+ fetch "repository" rescue abort "You have not specified a repository for this application"
151
+ git_deploy if repository.include? "git"
152
+ svn_deploy if repository.include? "svn"
153
+ end
154
+
155
+ task :git_deploy do
156
+ begin
157
+ run "ls #{deploy_to}/.git"
158
+ rescue
159
+ run "git init"
160
+ run "git remote add origin #{repository}"
161
+ end
162
+ run "git pull origin #{branch}"
163
+ end
164
+
165
+ task :svn_deploy do
166
+ run "svn export #{repository} #{deploy_to} --force"
167
+ end
168
+
169
+ task :cms_deploy do
170
+ begin
171
+ run "ls plugins/cms/.git"
172
+ rescue
173
+ run "mkdir -p plugins/cms"
174
+ run "cd plugins/cms && git init"
175
+ run "cd plugins/cms && git remote add origin git://github.com:phpwax/wildfire.git"
176
+ end
177
+ run "cd plugins/cms && git checkout #{cms}"
178
+ end
179
+
180
+ task :php_wax_deploy do
181
+ begin
182
+ run "ls wax/.git"
183
+ rescue
184
+ run "mkdir wax"
185
+ run "cd wax && git init"
186
+ run "cd wax && git remote add origin git://github.com/phpwax/phpwax.git"
187
+ run "cd wax && git pull origin master"
188
+ end
189
+ run "cd wax && git checkout #{phpwax}"
190
+ end
191
+
192
+ ####### ##############
193
+
194
+
195
+ # =============================================================================
196
+ # GENERAL ADMIN FOR APPLICATIONS
197
+ # =============================================================================
198
+
199
+ desc "Restarts the Apache Server."
200
+ task :restart do
201
+ config_check
202
+ needs_root
203
+ with_user("root", "#{root_pass}") do
204
+ run "/etc/rc.d/init.d/httpd restart"
205
+ end
206
+ end
207
+
208
+ task :clearcache do
209
+ run "rm -f tmp/cache/*"
210
+ end
211
+
212
+ task :clearlogs do
213
+ run "rm -f tmp/log/*"
214
+ end
215
+
216
+
217
+ # =============================================================================
218
+ # BACKING UP APPLICATIONS
219
+ # =============================================================================
220
+
221
+ desc "Starts the backup process by checking which type to perform then performs the necessary back ups."
222
+ task :backup do
223
+ config_check
224
+ needs_root
225
+ backup_check
226
+ end
227
+
228
+ task :backup_check do
229
+ if defined? "#{repository}"
230
+ if repository.include? "git"
231
+ git_mysql_backup
232
+ upload_only_backup
233
+ elsif repository.include? "svn"
234
+ standard_mysql_backup
235
+ upload_only_backup
236
+ end
237
+ else
238
+ puts "No repository for #{application}"
239
+ standard_mysql_backup
240
+ simple_fs_backup
241
+ end
242
+ end
243
+
244
+ task :simple_fs_backup do
245
+ with_user("root", "#{root_pass}") do
246
+ run "mkdir -p /backup/#{application}"
247
+ run "rsync -avzh /home/#{application}/ /backup/#{application}/"
248
+ end
249
+ end
250
+
251
+ task :upload_only_backup do
252
+ with_user("root", "#{root_pass}") do
253
+ run "mkdir -p /backup/#{application}"
254
+ run "rsync -avzh /home/#{application}/public/files/ /backup/#{application}/"
255
+ end
256
+ end
257
+
258
+ task :standard_mysql_backup do
259
+ run "mkdir -p public/files"
260
+ databases.each do |db|
261
+ run "mysqldump #{db} --skip-comments --add-drop-table -u#{user} -p#{password} > public/files/#{db}.sql";
262
+ end
263
+ upload_only_backup
264
+ end
265
+
266
+ task :git_mysql_backup do
267
+ transaction do
268
+ run "mkdir -p tmp/backup"
269
+ run "ln -s ../../.git/ tmp/backup/.git"
270
+ begin
271
+ run "cd tmp/backup && git branch db"
272
+ run "cd tmp/backup && git branch -d db"
273
+ rescue
274
+ end
275
+ run "cd tmp/backup && git symbolic-ref HEAD refs/heads/db"
276
+ run "cd tmp/backup && mv .git/index .git/index_old"
277
+ databases.each do |db|
278
+ run "cd tmp/backup && mysqldump #{db} --skip-comments --add-drop-table -u#{user} -p#{password} > #{db}.sql";
279
+ end
280
+ run "cd tmp/backup && git add ."
281
+ run "cd tmp/backup && git commit -m 'database update'" rescue ""
282
+ run "cd tmp/backup && git push origin db"
283
+ run "rm -Rf ./tmp/backup"
284
+ run "mv -f .git/index_old .git/index" rescue ""
285
+ run "git symbolic-ref HEAD refs/heads/#{branch}"
286
+ on_rollback do
287
+ run "rm -Rf ./tmp/backup"
288
+ run "mv -f .git/index_old .git/index" rescue ""
289
+ run "git symbolic-ref HEAD refs/heads/#{branch}"
290
+ end
291
+ end
292
+ end
293
+
294
+ # =============================================================================
295
+ # RESTORING BACKED-UP APPLICATIONS
296
+ # =============================================================================
297
+
298
+ desc "Restores a backed up application, database and other files."
299
+ task :restore do
300
+ if defined? repository
301
+ if repository.include? "git"
302
+ upload_only_restore
303
+ git_mysql_restore
304
+ elsif repository.include? "svn"
305
+ upload_only_restore
306
+ standard_mysql_restore
307
+ end
308
+ else
309
+ simple_fs_restore
310
+ standard_mysql_restore
311
+ end
312
+ end
313
+
314
+ task :upload_only_restore do
315
+ with_user("root", "#{root_pass}") do
316
+ run "rsync -avzh /backup/#{application}/ /home/#{application}/public/files/"
317
+ end
318
+ end
319
+
320
+ task :git_mysql_restore do
321
+ run "mkdir -p tmp/backup"
322
+ run "ln -s ../../ tmp/backup/.git"
323
+ run "cd tmp/backup && git symbolic-ref HEAD refs/heads/db"
324
+ run "cd tmp/backup && mv .git/index .git/index_old"
325
+ "#{databases}".each do |db|
326
+ run "cd tmp/backup && mysql #{db} -u#{user} -p#{password} < #{db}.sql"
327
+ end
328
+ run "rm -Rf ./tmp/backup"
329
+ run "mv -f .git/index_old .git/index" rescue ""
330
+ run "git symbolic-ref HEAD refs/heads/#{branch}"
331
+ end
332
+
333
+ desc "Just runs rSync back to the home directory"
334
+ task :simple_fs_restore do
335
+ with_user("root", "#{root_pass}") do
336
+ run "rsync -avzh /backup/#{application}/ /home/#{application}/"
337
+ end
338
+ end
339
+
340
+ task :standard_mysql_restore do
341
+ "#{databases}".each do |db|
342
+ run "cd tmp/backup && mysql #{db} -u#{user} -p#{password} < public/files/#{db}.sql"
343
+ end
344
+ end
345
+
346
+ # =============================================================================
347
+ # USER AND APPLICATION SETUP AND INITIALISATION
348
+ # =============================================================================
349
+
350
+ desc "General setup task which creates a new user on the host, sets up a mysql database and login, creates an apache vhost file and finally generates an ssh key for the user."
351
+ task :setup do
352
+ config_check
353
+ try_login
354
+ setup_mysql
355
+ vhost
356
+ ssh_key
357
+ end
358
+
359
+
360
+ task :setup_user do
361
+ needs_root
362
+ set :user_to_add, "#{user}"
363
+ set :passwd_to_add, "#{password}"
364
+ with_user("root", "#{root_pass}") do
365
+ run "useradd -p `openssl passwd #{passwd_to_add}` #{user_to_add}"
366
+ end
367
+ end
368
+
369
+ task :setup_mysql do
370
+ with_user("root", "#{root_pass}") do
371
+ "#{databases}".each do |db|
372
+ run "mysql -uroot -p#{root_pass} -e 'CREATE DATABASE #{db}'"
373
+ run "musql -uroot -p#{root_pass} -e 'GRANT ALL PRIVILEGES ON `#{db}` . * TO '#{user_to_add}'@'localhost' IDENTIFIED BY '#{passwd_to_add}';"
374
+ end
375
+ end
376
+
377
+ end
378
+
379
+ task :try_login do
380
+ config_check
381
+ begin
382
+ run "ls"
383
+ puts "Logged in ok"
384
+ rescue
385
+ print "==== The user does not yet exist. Would you like to create? [Y/N]"
386
+ line = STDIN.gets.upcase.strip
387
+ puts "*** Could not continue as the login does not exist" if line !="Y"
388
+ exit if line != "Y"
389
+ setup_user
390
+ end
391
+ end
392
+
393
+ desc "Creates or gets an ssh key for the application"
394
+ task :ssh_key do
395
+ config_check
396
+ begin
397
+ run "cat .ssh/id_rsa.pub"
398
+ rescue
399
+ run "ssh-keygen -t rsa -f .ssh/id_rsa -N ''"
400
+ run "cat .ssh/id_rsa.pub"
401
+ end
402
+ end
403
+
404
+ desc "Creates an Apache virtual host file"
405
+ task :vhost do
406
+ config_check
407
+ needs_root
408
+ with_user("root", "#{root_pass}") do
409
+ public_ip = ""
410
+ run "ifconfig eth0 | grep inet | awk '{print $2}' | sed 's/addr://'" do |_, _, public_ip| end
411
+ public_ip = public_ip.strip
412
+ f = File.open('templates/apache_vhost.erb')
413
+ contents = f.read
414
+ f.close
415
+ buffer = ERB.new(contents)
416
+ config = buffer.result(binding())
417
+ put config, "/etc/httpd/conf.d/#{application}-apache-vhost.conf"
418
+ end
419
+
420
+ end
421
+
422
+ # =============================================================================
423
+ # +MIGRATING+ APPLICATIONS
424
+ # =============================================================================
425
+
426
+ desc "Runs a backup of an application, copies to another server and then sets up on new server"
427
+ task :copy_site do
428
+ config_check
429
+ needs_root
430
+ backup
431
+ print "==== Which server would you like to copy #{application} to? [Full Domain Name] "
432
+ line = STDIN.gets.strip
433
+ begin
434
+ new_server = options["servers"][line]["domain"]
435
+ rescue
436
+ puts "*** Can't find that new server in the config"
437
+ exit
438
+ end
439
+ with_user("root", "#{root_pass}") do
440
+ run "rsync -avzh . -e ssh root@#{new_server}:/backup/#{application}/ --exclude 'tmp/*' --exclude '.git/*'"
441
+ end
442
+ options["apps"]["#{application}"]["server"] = line
443
+ config_write
444
+ try_login
445
+ restore
446
+ end
447
+
448
+ end
449
+
450
+
451
+ def get_ip(domain)
452
+ require 'socket'
453
+ t = TCPSocket.gethostbyname(domain)
454
+ t[3]
455
+ end
456
+
457
+ def with_user(new_user, new_pass, &block)
458
+ old_user, old_pass = user, password
459
+ set :user, new_user
460
+ set :password, new_pass
461
+ close_sessions
462
+ yield
463
+ set :user, old_user
464
+ set :password, old_pass
465
+ close_sessions
466
+ end
467
+ def close_sessions
468
+ sessions.values.each { |session| session.close }
469
+ sessions.clear
470
+ end
471
+
472
+
473
+
474
+
475
+
476
+
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oneblackbear-obbistrano
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Ross Riley
8
+ - One Black Bear
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-03-14 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: capistrano
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "2"
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: activeresource
28
+ type: :runtime
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "2"
35
+ version:
36
+ description: An extension to Capistrano to allow deploys to Slicehost for One Black Bear
37
+ email: ross@oneblackbear.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ files:
45
+ - README.txt
46
+ - capfile
47
+ has_rdoc: false
48
+ homepage: http://github.com/oneblackbear/obbistrano
49
+ post_install_message:
50
+ rdoc_options: []
51
+
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.2.0
70
+ signing_key:
71
+ specification_version: 2
72
+ summary: Adds extra namespaces to Capistrano to allow simple setup, deploys and maintenance.
73
+ test_files: []
74
+