capistrano-lemur 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in capistrano-lemur.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Jordan Babe
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Capistrano::Lemur
2
+
3
+ A collection or Capistrano recipes for a LEMUR (Linux/Nginx/Mysql/Unicorn/Rails) stack
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'capistrano-lemur'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install capistrano-lemur
18
+
19
+ ## Usage
20
+
21
+ Add this line to your application's Capfile:
22
+
23
+ require 'capistrano/lemur/mysql'
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/capistrano-lemur/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Jordan Babe"]
6
+ gem.email = ["jorbabe@gmail.com"]
7
+ gem.description = %q{Recipes for deploying a LEMUR (Linux/Nginx/Mysql/Unicorn/Rails) stack. Some of it is pulled from an existing application}
8
+ gem.summary = %q{Collection of Capistrano recipes for deploying a LEMUR (Linux/Nginx/Mysql/Unicorn/Rails) stack}
9
+ gem.homepage = "https://github.com/jbabe/capistrano-lemur"
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "capistrano-lemur"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Capistrano::Lemur::VERSION
17
+
18
+ gem.add_dependency "capistrano", "~> 2.11.2"
19
+
20
+ end
@@ -0,0 +1,8 @@
1
+ # Keep it simple (and un-dry) for now
2
+ require 'capistrano/lemur/mysql'
3
+ require 'capistrano/lemur/unicorn'
4
+ require 'capistrano/lemur/nginx'
5
+ require 'capistrano/lemur/db'
6
+ require 'capistrano/lemur/outage'
7
+ require 'capistrano/lemur/filesystem'
8
+ require 'capistrano/lemur/bundler'
@@ -0,0 +1,14 @@
1
+ Capistrano::Configuration.instance.load do
2
+ namespace :bundler do
3
+ task :create_symlink, :roles => :app do
4
+ shared_dir = File.join(shared_path, 'bundle')
5
+ release_dir = File.join(current_release, '.bundle')
6
+ run("mkdir -p #{shared_dir} && ln -s #{shared_dir} #{release_dir}")
7
+ end
8
+
9
+ task :bundle_new_release, :roles => :app do
10
+ #bundler.create_symlink
11
+ run "cd #{current_path} && bundle install --deployment --quiet --without development test cucumber"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,56 @@
1
+ Capistrano::Configuration.instance.load do
2
+
3
+ set(:migrate_target) { "current" }
4
+
5
+ namespace :db do
6
+ desc "LMR Setup application schema"
7
+ task :setup do
8
+ run "cd #{current_path}; bundle exec rake RAILS_ENV=#{rails_env} db:create"
9
+ end
10
+
11
+ desc "LMR Export the database into the db/ folder"
12
+ task :backup, :only => {:primary => true}, :except => { :no_release => true } do
13
+ run "cd #{current_path}; bundle exec rake RAILS_ENV=#{rails_env} db:data:backup"
14
+ end
15
+
16
+ desc "LMR Export the database into the db/ folder"
17
+ task :restore, :only => {:primary => true}, :except => { :no_release => true } do
18
+ confirm = Capistrano::CLI.ui.ask "This is a dangerous task. Type 'yes sir' to continue."
19
+ exit unless confirm.downcase == 'yes sir'
20
+ run "cd #{current_path}; bundle exec rake RAILS_ENV=#{rails_env} db:data:restore"
21
+ end
22
+
23
+ desc "LMR Export the database into the db/ folder"
24
+ task :restore_from_staging, :only => {:primary => true}, :except => { :no_release => true } do
25
+ confirm = Capistrano::CLI.ui.ask "This is a dangerous task. Type 'yes sir' to continue."
26
+ exit unless confirm.downcase == 'yes sir'
27
+ run "cd #{current_path}; bundle exec rake RAILS_ENV=#{rails_env} db:data:restore_from_staging"
28
+ end
29
+
30
+ desc "LMR Export the database into the db/ folder"
31
+ task :restore_from_production, :only => {:primary => true}, :except => { :no_release => true } do
32
+ confirm = Capistrano::CLI.ui.ask "This is a dangerous task. Type 'yes sir' to continue."
33
+ exit unless confirm.downcase == 'yes sir'
34
+ run "cd #{current_path}; bundle exec rake RAILS_ENV=#{rails_env} db:data:restore_from_production"
35
+ end
36
+
37
+ desc "LMR Wipe tables then rerun all migrations and seed database"
38
+ task :remigrate, :only => {:primary => true}, :except => { :no_release => true } do
39
+ confirm = Capistrano::CLI.ui.ask "This is a dangerous task. Type 'yes sir' to continue."
40
+ exit unless confirm.downcase == 'yes sir'
41
+ backup
42
+ run "cd #{current_path}; bundle exec rake RAILS_ENV=#{rails_env} db:remigrate"
43
+ end
44
+
45
+ desc "Seed the database on already deployed code"
46
+ task :seed, :only => {:primary => true}, :except => { :no_release => true } do
47
+ confirm = Capistrano::CLI.ui.ask "This is a dangerous task. Type 'yes sir' to continue."
48
+ exit unless confirm.downcase == 'yes sir'
49
+ run "cd #{current_path}; bundle exec rake RAILS_ENV=#{rails_env} db:seed"
50
+ end
51
+
52
+ end
53
+
54
+
55
+
56
+ end
@@ -0,0 +1,27 @@
1
+ require 'pathname'
2
+
3
+ Capistrano::Configuration.instance.load do
4
+
5
+ namespace :filesystem do
6
+
7
+ desc "Iterate over 'app_symlinks' hash: { '/path/to/src1' => '/path/to/dest2', '/path/to/src2' => '/path/to/dest2'}"
8
+ task :create_symlinks do
9
+ fetch(:app_symlinks).each_pair do |src, dest|
10
+ run "if [ ! -L #{lemur_fullpath(dest)} ]; then ln -s #{lemur_fullpath(src)} #{lemur_fullpath(dest)}; fi"
11
+ end
12
+ end
13
+
14
+ desc "Create all directories in 'app_directories' array"
15
+ task :create_directories do
16
+ fetch(:app_directories).each do |directory|
17
+ run "mkdir -p #{lemur_fullpath(directory)}"
18
+ end
19
+ end
20
+
21
+ def lemur_fullpath(path)
22
+ Pathname.new(path).relative? ? File.join(current_path, path) : path
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,52 @@
1
+ Capistrano::Configuration.instance.load do
2
+
3
+ namespace :mysql do
4
+
5
+ desc "LMR Create default db and user. TODO: Make this idempotent"
6
+ task :create_users, :roles => :db, :except => { :no_release => true } do
7
+
8
+ db_config = YAML::load_file("config/database.yml")
9
+ db_user = db_config[rails_env.to_s]["username"]
10
+ db_password = db_config[rails_env.to_s]["password"]
11
+ db_name = db_config[rails_env.to_s]["database"]
12
+
13
+ sudo "ls -al" #So we don't get prompted on the line below.....
14
+ db_root_password = capture("sudo cat /var/cache/local/preseeding/mysql-server.seed").split(" ")[3]
15
+
16
+
17
+ servers = roles[:app].collect {|r| r.host}
18
+ servers << "localhost"
19
+
20
+
21
+ servers.each do |server|
22
+
23
+ check_user = capture("mysql --user=root -p#{db_root_password} -B -N -e \"select count(*) from mysql.user where host = '#{server}' and user = '#{db_user}';\"").chomp.to_i
24
+ run "mysql --user=root -p#{db_root_password} -e \"CREATE USER '#{db_user}'@'#{server}' IDENTIFIED BY '#{db_password}'\"" unless check_user == 1
25
+ run "mysql --user=root -p#{db_root_password} -e \"GRANT CREATE ON *.* TO '#{db_user}'@'#{server}'\""
26
+ run "mysql --user=root -p#{db_root_password} -e \"GRANT ALL PRIVILEGES ON #{db_name}.* TO '#{db_user}'@'#{server}' IDENTIFIED BY '#{db_password}' WITH GRANT OPTION\""
27
+ run "mysql --user=root -p#{db_root_password} -e \"FLUSH PRIVILEGES;\""
28
+ end
29
+
30
+ end
31
+
32
+ desc "LMR Setup application schema"
33
+ task :setup, :only => {:primary => true}, :except => { :no_release => true } do
34
+ run "cd #{current_path}; bundle exec rake RAILS_ENV=#{rails_env} db:create"
35
+ end
36
+
37
+ desc "LMR db:migration"
38
+ task :migrate, :only => {:primary => true}, :except => { :no_release => true } do
39
+ run "cd #{current_path}; bundle exec rake RAILS_ENV=#{rails_env} db:migrate"
40
+ end
41
+
42
+ desc "LMR seed the database on already deployed code"
43
+ task :seed, :only => {:primary => true}, :except => { :no_release => true } do
44
+ confirm = Capistrano::CLI.ui.ask "This is a dangerous task. Type Y to continue."
45
+ exit unless confirm.downcase == 'y'
46
+ run "cd #{current_path}; bundle exec rake RAILS_ENV=#{rails_env} db:seed"
47
+ end
48
+
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,53 @@
1
+ Capistrano::Configuration.instance.load do
2
+ namespace :nginx do
3
+
4
+ set(:nginx_path) { "/etc/nginx" }
5
+ set(:nginx_cmd) {"/etc/init.d/nginx"}
6
+
7
+ desc "LMR Copy application nginx config into sites-available and symlink into sites-enabled"
8
+ task :setup, :roles => :web do
9
+ confirm = Capistrano::CLI.ui.ask "This is a dangerous task. Type 'yes sir' to continue."
10
+ if confirm.downcase == 'yes sir'
11
+ location = Capistrano::CLI.ui.ask "Filename of nginx config file (blank for default of config/nginx.#{stage})?"
12
+ location = "nginx.#{stage}" if location.nil? or location.length < 1
13
+ # Backup the old config and copy app config
14
+ run "cp #{nginx_path}/sites-available/#{application} #{nginx_path}/sites-available/#{application}.#{Time.now.strftime("%Y%m%d_%I%M")} && cp #{current_path}/config/#{location} #{nginx_path}/sites-available/#{application}"
15
+ run "if [ ! -L #{nginx_path}/sites-enabled/#{application} ]; then ln -s #{nginx_path}/sites-available/#{application} #{nginx_path}/sites-enabled/#{application}; fi"
16
+ else
17
+ puts "Nginx configuration change aborted"
18
+ exit
19
+ end
20
+ end
21
+
22
+ task :test_config, :roles => :web do
23
+ sudo "#{nginx_cmd} configtest"
24
+ end
25
+
26
+ desc "LMR Restart only primary node"
27
+ task :restart_primary, :roles => :web, :only => {:primary => true} do
28
+ restart
29
+ end
30
+
31
+ desc "LMR Restart only secondary node"
32
+ task :restart_secondary, :roles => :web, :except => {:primary => true} do
33
+ restart
34
+ end
35
+
36
+ desc "LMR Restart all Nginx nodes"
37
+ task :restart_all, :roles => :web do
38
+ restart
39
+ end
40
+
41
+
42
+ def restart
43
+ confirm = Capistrano::CLI.ui.ask "This is a dangerous task. Type 'yes sir' to continue."
44
+ if confirm.downcase == "yes sir"
45
+ sudo "#{nginx_cmd} restart"
46
+ else
47
+ puts "Restart aborted"
48
+ exit
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,70 @@
1
+ require 'capistrano'
2
+
3
+ # TODO: use the built in Capistrano web:disable by setting:
4
+ # maintenance_basename (path to html)
5
+ # maintenance_template_path (path to erb)
6
+
7
+ module Capistrano::Lemur::Outage
8
+ def self.load_into(configuration)
9
+ configuration.load do
10
+
11
+ set(:outage_templates) { ["membership_outage.html","registration_outage.html"] }
12
+
13
+
14
+ namespace :web do
15
+
16
+ desc "LMR Serve up a custom maintenance page."
17
+ task :disable, :roles => :web do
18
+ Capistrano::Lemur::Outage.disable_template
19
+ end
20
+
21
+ desc "LMR Remove a custom maintenance page."
22
+ task :enable, :roles => :web do
23
+ Capistrano::Lemur::Outage.enable_template
24
+ end
25
+
26
+ end
27
+
28
+ namespace :membership do
29
+
30
+ desc "LMR Serve up a custom maintenance page."
31
+ task :disable, :roles => :web do
32
+ Capistrano::Lemur::Outage.disable_template(outage_templates)
33
+ end
34
+
35
+ desc "LMR Remove a custom maintenance page."
36
+ task :enable, :roles => :web do
37
+ Capistrano::Lemur::Outage.enable_template(outage_templates)
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+ end
44
+
45
+
46
+ def self.enable_template(templates = Array("maintenance.html") )
47
+ templates.each do |template|
48
+ require 'erb'
49
+ on_rollback { run "rm #{current_path}/public/system/#{template}" }
50
+
51
+ reason = ENV['REASON']
52
+ deadline = ENV['UNTIL']
53
+
54
+ file = File.read(File.join("app/views/system/#{template}.erb"))
55
+ page = ERB.new(file).result(binding)
56
+ put(page, "#{current_path}/public/system/#{template}", :mode => 0644)
57
+ end
58
+ end
59
+
60
+ def self.disable_template(templates = Array("maintenance.html") )
61
+ templates.each do |template|
62
+ run "rm #{current_path}/public/system/#{template}"
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ if Capistrano::Configuration.instance
69
+ Capistrano::Lemur::Outage.load_into(Capistrano::Configuration.instance)
70
+ end
@@ -0,0 +1,49 @@
1
+ Capistrano::Configuration.instance.load do
2
+
3
+ # TODO: make this more generic once we start using in multiple apps
4
+ namespace :deploy do
5
+
6
+ # override default tasks to make capistrano happy
7
+ desc "LMR Start unicorn"
8
+ task :start, :roles => :app do
9
+ # start_primary
10
+ start_secondary unless (find_servers :roles => :app, :except => {:primary => true}).empty?
11
+ end
12
+
13
+ desc "LMR Start unicorn on primary server"
14
+ task :start_primary, :roles => :app, :only => { :primary => true } do
15
+ run "cd #{current_path} && server=primary bundle exec unicorn -c #{current_path}/config/unicorn.rb -E #{rails_env} -D"
16
+ end
17
+
18
+ desc "LMR Start unicorn on secondary server(s)"
19
+ task :start_secondary, :roles => :app, :except => { :primary => true } do
20
+ run "cd #{current_path} && server=secondary bundle exec unicorn -c #{current_path}/config/unicorn.rb -E #{rails_env} -D"
21
+ end
22
+
23
+ desc "LMR Start unicorn on primary server"
24
+ task :stop_primary, :roles => :app, :only => { :primary => true } do
25
+ run "kill -QUIT `cat #{current_path}/tmp/pids/unicorn.pid`"
26
+ sleep 2
27
+ start_primary
28
+ end
29
+
30
+ desc "LMR Start unicorn on secondary server(s)"
31
+ task :stop_secondary, :roles => :app, :except => { :primary => true } do
32
+ run "kill -QUIT `cat #{current_path}/tmp/pids/unicorn.pid`"
33
+ sleep 2
34
+ start_secondary
35
+ end
36
+
37
+ desc "LMR Kick unicorn"
38
+ task :restart, :roles => :app do
39
+ run "kill -USR2 `cat #{current_path}/tmp/pids/unicorn.pid`"
40
+ end
41
+
42
+ desc "LMR Kill a unicorn"
43
+ task :stop, :roles => :app do
44
+ run "kill -QUIT `cat #{current_path}/tmp/pids/unicorn.pid`"
45
+ end
46
+ end
47
+
48
+
49
+ end
@@ -0,0 +1,5 @@
1
+ module Capistrano
2
+ module Lemur
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ require "capistrano-lemur/version"
2
+
3
+ module Capistrano
4
+ module Lemur
5
+ # Your code goes here...
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-lemur
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jordan Babe
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-29 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: capistrano
16
+ requirement: &2154219440 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.11.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2154219440
25
+ description: Recipes for deploying a LEMUR (Linux/Nginx/Mysql/Unicorn/Rails) stack.
26
+ Some of it is pulled from an existing application
27
+ email:
28
+ - jorbabe@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - Gemfile
35
+ - LICENSE
36
+ - README.md
37
+ - Rakefile
38
+ - capistrano-lemur.gemspec
39
+ - lib/capistrano-lemur.rb
40
+ - lib/capistrano-lemur/version.rb
41
+ - lib/capistrano/lemur/all.rb
42
+ - lib/capistrano/lemur/bundler.rb
43
+ - lib/capistrano/lemur/db.rb
44
+ - lib/capistrano/lemur/filesystem.rb
45
+ - lib/capistrano/lemur/mysql.rb
46
+ - lib/capistrano/lemur/nginx.rb
47
+ - lib/capistrano/lemur/outage.rb
48
+ - lib/capistrano/lemur/unicorn.rb
49
+ homepage: https://github.com/jbabe/capistrano-lemur
50
+ licenses: []
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubyforge_project:
69
+ rubygems_version: 1.8.8
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: Collection of Capistrano recipes for deploying a LEMUR (Linux/Nginx/Mysql/Unicorn/Rails)
73
+ stack
74
+ test_files: []