Skip to content

Commit

Permalink
Move to cap style deployment
Browse files Browse the repository at this point in the history
* Update task goes away
* Deploy runs each command on remote servers

Change-Id: Iadee24b1bcfbb0b7861757741f838a0f1e4f1e49
Reviewed-on: http://review.engineyard.com/115
Reviewed-by: Andre Arko <aarko@engineyard.com>
Tested-by: Andre Arko <aarko@engineyard.com>
  • Loading branch information
Andy Delcambre authored and indirect committed Mar 5, 2010
1 parent 2f42987 commit 79dad04
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 185 deletions.
1 change: 0 additions & 1 deletion lib/ey-deploy.rb
Expand Up @@ -6,7 +6,6 @@
require 'task'
require 'server'
require 'deploy'
require 'update'
require 'cli'
require 'configuration'

Expand Down
45 changes: 18 additions & 27 deletions lib/ey-deploy/cli.rb
Expand Up @@ -4,38 +4,29 @@

module EY
class CLI < Thor
class_option :migrate,
:type => :string,
:default => "rake db:migrate",
:desc => "Run migrations with this deploy",
:aliases => ["-m"]

class_option :branch, :type => :string,
:default => "master",
:desc => "Branch to deploy from, defaults to master",
:aliases => ["-b"]

class_option :repo, :type => :string,
:desc => "Remote repo to deploy",
:aliases => ["-r"]

method_option :app, :type => :string,
:required => true,
:desc => "Application to deploy",
:aliases => ["-a"]
method_option :migrate, :type => :string,
:default => "rake db:migrate",
:desc => "Run migrations with this deploy",
:aliases => ["-m"]

method_option :branch, :type => :string,
:default => "master",
:desc => "Branch to deploy from, defaults to master",
:aliases => ["-b"]

method_option :repo, :type => :string,
:desc => "Remote repo to deploy",
:aliases => ["-r"]

method_option :app, :type => :string,
:required => true,
:desc => "Application to deploy",
:aliases => ["-a"]
desc "deploy", "Deploy code from /data/<app>"
def deploy(default_task=:deploy)
EY::Deploy.run(options.merge("default_task" => default_task))
end

method_option :app, :type => :string,
:required => true,
:desc => "Application to deploy",
:aliases => ["-a"]
desc "update", "Update code locally, push to all other instances and run the deploy"
def update(default_task=:update)
EY::Update.run(options.merge("default_task" => default_task))
end

desc "check", "Check whether the client gem is compatible with the server gem"
def check(client_version, server_requirement)
Expand Down
41 changes: 41 additions & 0 deletions lib/ey-deploy/configuration.rb
Expand Up @@ -71,5 +71,46 @@ def environment
EY.node['environment']['framework_env']
end

def latest_release
all_releases.last
end

def previous_release(current=latest_release)
index = all_releases.index(current)
all_releases[index-1]
end

def oldest_release
all_releases.first
end

def all_releases
Dir.glob("#{release_dir}/*").sort
end

def framework_envs
"RAILS_ENV=#{environment} RACK_ENV=#{environment} MERB_ENV=#{environment}"
end

def current_path
File.join(deploy_to, "current")
end

def shared_path
File.join(deploy_to, "shared")
end

def release_dir
File.join(deploy_to, "releases")
end

def release_path
@release_path ||= File.join(release_dir, Time.now.utc.strftime("%Y%m%d%H%M%S"))
end

def exclusions
copy_exclude.map { |e| %|--exclude="#{e}"| }.join(' ')
end

end
end
121 changes: 43 additions & 78 deletions lib/ey-deploy/deploy.rb
Expand Up @@ -4,10 +4,13 @@

module EY
class DeployBase < Task
# task, default
# default task
def deploy
update_repository_cache
require_custom_tasks
push_code

puts "~> Starting full deploy"
Dir.chdir c.deploy_to

copy_repository_cache
bundle
Expand All @@ -19,34 +22,30 @@ def deploy
puts "~> finalizing deploy"
end

# task, default
def symlink_only
puts "~> Starting symlink deploy"
Dir.chdir c.deploy_to

copy_repository_cache
bundle
symlink
cleanup

puts "~> finalizing deploy"
# task
def push_code
EY::Server.all.each do |server|
server.push_code
end
end

# task
def restart
restart_command = case c.stack
when "nginx_unicorn"
"/etc/init.d/unicorn_#{c.app} restart"
when "nginx_mongrel"
"monit restart all -g #{c.app}"
when "nginx_passenger", "apache_passenger"
"touch #{c.latest_release}/tmp/restart.txt"
end
if restart_command
puts "~> restarting app: #{c.latest_release}"
sudo("cd #{c.current_path} && INLINEDIR=/tmp #{c.framework_envs} #{restart_command}")
roles :app_master, :app, :solo do
restart_command = case c.stack
when "nginx_unicorn"
"/etc/init.d/unicorn_#{c.app} restart"
when "nginx_mongrel"
"monit restart all -g #{c.app}"
when "nginx_passenger", "apache_passenger"
"touch #{c.latest_release}/tmp/restart.txt"
end
if restart_command
puts "~> restarting app: #{c.latest_release}"
sudo("cd #{c.current_path} && INLINEDIR=/tmp #{c.framework_envs} #{restart_command}")
end
callback(:after_restart)
end
callback(:after_restart)
end

# task
Expand Down Expand Up @@ -80,13 +79,15 @@ def rollback

# task
def migrate
if c.migrate?
callback(:before_restart)
sudo "ln -nfs #{c.shared_path}/config/database.yml #{c.latest_release}/config/database.yml"
sudo "ln -nfs #{c.shared_path}/log #{c.latest_release}/log"
puts "~> Migrating: cd #{c.latest_release} && sudo -u #{c.user} #{c.framework_envs} #{c.migration_command}"
sudo("chown -R #{c.user}:#{c.group} #{c.latest_release}")
sudo("cd #{c.latest_release} && sudo -u #{c.user} #{c.framework_envs} #{c.migration_command}")
roles :app_master, :solo do
if c.migrate?
callback(:before_restart)
sudo "ln -nfs #{c.shared_path}/config/database.yml #{c.latest_release}/config/database.yml"
sudo "ln -nfs #{c.shared_path}/log #{c.latest_release}/log"
puts "~> Migrating: cd #{c.latest_release} && sudo -u #{c.user} #{c.framework_envs} #{c.migration_command}"
sudo("chown -R #{c.user}:#{c.group} #{c.latest_release}")
sudo("cd #{c.latest_release} && sudo -u #{c.user} #{c.framework_envs} #{c.migration_command}")
end
end
end

Expand Down Expand Up @@ -137,56 +138,20 @@ def callback(what)
end
end

def initialize(*args)
super
class << config
def latest_release
all_releases.last
end

def previous_release(current=latest_release)
index = all_releases.index(current)
all_releases[index-1]
end

def oldest_release
all_releases.first
end

def all_releases
Dir.glob("#{release_dir}/*").sort
end

def framework_envs
"RAILS_ENV=#{environment} RACK_ENV=#{environment} MERB_ENV=#{environment}"
end

def current_path
File.join(deploy_to, "current")
end

def shared_path
File.join(deploy_to, "shared")
end

def release_dir
File.join(deploy_to, "releases")
end

def release_path
@release_path ||= File.join(release_dir, Time.now.utc.strftime("%Y%m%d%H%M%S"))
end

def exclusions
copy_exclude.map { |e| %|--exclude="#{e}"| }.join(' ')
end
end
end
end

class Deploy < DeployBase
def self.new(opts={})
# include the correct fetch strategy
include EY::Strategies.const_get(opts.strategy)::Helpers
super
end

def self.run(opts={})
dep = new(EY::Deploy::Configuration.new(opts))
conf = EY::Deploy::Configuration.new(opts)
EY::Server.repository_cache = conf.repository_cache

dep = new(conf)
dep.require_custom_tasks
dep.send(opts["default_task"])
end
Expand Down
29 changes: 14 additions & 15 deletions lib/ey-deploy/server.rb
@@ -1,5 +1,5 @@
module EY
class Server < Struct.new(:hostname, :role)
class Server < Struct.new(:hostname, :role, :name)
def self.repository_cache=(repo_cache)
@@repository_cache = repo_cache
end
Expand All @@ -10,6 +10,15 @@ def repository_cache

attr_writer :default_task

def self.from_roles(*roles)
roles = roles.flatten.compact!
return all if !roles || roles.include?(:all) || roles.empty?

all.select do |s|
roles.include?(s.role) || roles.include?(s.name)
end
end

def self.all
@servers ||= (app_slaves << db_master << db_slaves << utils << current).flatten.compact.uniq
end
Expand All @@ -20,7 +29,7 @@ def self.current

def self.app_slaves
@app_slaves ||= Array(EY.node["members"]).map do |slave|
new(slave, :app_slave)
new(slave, :app)
end
end

Expand All @@ -41,7 +50,7 @@ def self.db_slaves

def self.utils
EY.node["utility_instances"].map{|util| util["hostname"]}.each do |server|
new(server, :util)
new(server["hostname"], :util, server["name"])
end
end

Expand All @@ -51,7 +60,7 @@ def hash; hostname.hash; end
def ==(other); eql?(other); end

def local?
[:master, :solo].include?(role)
[:app_master, :solo].include?(role)
end

def push_code
Expand All @@ -62,24 +71,14 @@ def push_code

def run(command)
if local?
puts "Running command locally"
system("#{command.gsub(/\\"/, '"')}")
system(command)
else
puts "Running command remotely"
system("#{ssh_command} #{hostname} #{command}")
end
end

def ssh_command
"ssh -i /root/.ssh/internal"
end

def default_task
if [:master, :solo, :app_slave].include?(role)
"deploy"
else
"symlink_only"
end
end
end
end
26 changes: 16 additions & 10 deletions lib/ey-deploy/task.rb
Expand Up @@ -6,6 +6,7 @@ class Task

def initialize(conf)
@config = conf
@roles = :all
end

def require_custom_tasks
Expand All @@ -15,22 +16,27 @@ def require_custom_tasks
require File.join(c.repository_cache, deploy_file) if deploy_file
end

def roles(*task_roles)
raise "Roles must be passed a block" unless block_given?

begin
@roles = task_roles
yield
ensure
@roles = :all
end
end

def run(cmd)
res = `sudo -u #{c.user} sh -c "#{cmd} 2>&1"`
unless $? == 0
puts res
exit 1
EY::Server.from_roles(@roles).each do |server|
server.run %|sudo -u #{c.user} sh -c "#{cmd} 2>&1"|
end
res
end

def sudo(cmd)
res = `sh -c "#{cmd} 2>&1"`
unless $? == 0
puts res
exit 1
EY::Server.from_roles(@roles).each do |server|
server.run %|sh -c "#{cmd} 2>&1"|
end
res
end
end
end

0 comments on commit 79dad04

Please sign in to comment.