How do you define the same tasks differently for different roles in Capistrano?
I'm using Capistrano to handle my deployment, and I've got two different rol开发者_JAVA技巧es in my setup - :web and :processing. They both have the usual :deploy tasks, but the :restart task needs to be different for the two types of server.
So my first attempt was something like this:
task :restart, :roles => :web do
run "... web related restart stuff ..."
end
task :restart, :roles => :processing do
run "... processing related restart stuff ..."
end
Which doesn't work, because the second :restart (for :processing role) replaces the first :restart (for the :web role), and the :web :restart never happens.
I had a quick look around to see if I could write conditional code depending on which role (or roles) a server might be in when the task is run but there's next to no documentation out there for that kind of thing. Any ideas?
You should use namespaces:
namespace :web do
desc "Restart web servers"
task :restart, :roles => :web do
# Restart Magic Here
end
end
namespace :process do
desc "Restart process servers"
task :restart, :roles => :process do
# Restart magic here
end
end
# Optionally:
task :restart do
web.restart
process.restart
end
That's what you're looking for I think!
Also, to use these on the command line, you would use
$ cap <stage> # (if using multistage)
$ cap web:restart # Restarts web servers
$ cap process:restart # Restarts process servers
$ cap restart # Restarts both process and web servers
(Source: I'm the Capistrano maintainer.)
You should use 'parallel' instead of 'run' in this case:
task :restart do
parallel do |session|
session.when "in?(:web)", "...substitute run command contents here...."
session.when "in?(:process)", "...substitute run command contents here...."
end
end
If you are going to use something except 'run' in different tasks you'd better stick to one of the other answers.
More info on 'parallel' command can be found here: https://github.com/capistrano/capistrano/wiki/2.x-DSL-Action-Invokation-Parallel
If you need to call the default deploy
task, and do some custom restarting, etc. I came up with this solution:
# Servers
server "importerhost.com", :app, :web, :db, :importer, :primary => true
server "backuphost.com", :app, :web, :db, :backup, :primary => true
set :deploy_to, "/apps/appname"
# Ensure deploy before restart
before 'importer:deploy', 'deploy'
before 'backup:deploy', 'deploy'
# Importer
namespace :importer do
desc "Restart importer service"
task :deploy, :roles => :importer do
sudo "cp #{current_release}/config/importer.conf /etc/init/importer.conf"
sudo "service importer restart N=1"
sudo "service importer restart N=2"
end
end
# Backup
namespace :backup do
desc "Restart backup service"
task :deploy, :roles => :backup do
sudo "cp #{current_release}/config/backup.conf /etc/init/backup.conf"
sudo "service backup restart"
end
end
And then simply deploy with cap ROLES=importer importer:deploy
or cap ROLES=backup backup:deploy
. This gave me the freedom to deploy the same source code to different servers, and execute completely different tasks after the actual deployment.
精彩评论