making those sub-tasks use the proper roles.

230 views
Skip to first unread message

bryanl

unread,
May 6, 2008, 11:49:43 AM5/6/08
to Capistrano
’ve been knee deep in capistrano lately, and I’ve come across in
interesting behavior:

Say you have the following:

role :app, "app"
role :web, "web"

task :run_on_web, :roles => :web do
do_something_on_server
end

task :run_on_app, :roles => :app do
do_something_on_server
end

task :do_something_on_server do
run "/usr/sbin/something"
end

If you run the run_on_web task, it will execute the
do_something_on_server task using all roles. This isn’t the behavior
you most expected most likely. The secret to making this work is to
set ENV[‘HOSTS’] match your the set of hosts you are interested in.
After you are done you’ll want to set ENV[‘HOSTS’] hosts back to it’s
original contents. I’ve whipped up a quick method to make this even
easier.

def with_role(role, &block)
original, ENV['HOSTS'] = ENV['HOSTS'], find_servers(:roles
=>role).map{|d| d.host}.join(",")
begin
yield
ensure
ENV['HOSTS'] = original
end
end
You can call it like this:


role :app, "app"
role :web, "web"

task :run_on_web, :roles => :web do
with_role :web do
do_something_on_server
end
end

task :run_on_app, :roles => :app do
with_role :app do
do_something_on_server
end
end

task :do_something_on_server do
run "/usr/sbin/something"
end


Hopefully this helps someone.

(also posted here: http://smartic.us/2008/5/6/keeping-capistrano-in-check-ensuring-roles-are-respected-in-sub-tasks)

Jamis Buck

unread,
May 6, 2008, 10:06:21 PM5/6/08
to capis...@googlegroups.com
Thanks, Bryan. The existing behavior is definitely surprising in some
situations, but not in others. Consider an imaginary task like the
following:

task :start_cold do
deploy.update
start_web_server
deploy.migrate
start_listeners
end

In this case, the :start_cold task itself applies to all servers
(because of the absense of a :roles or :hosts key). The deploy.update
call applies to all :app, :web, and :db servers. The start_web_server
would probably only apply to :web. deploy.migrate works only on :db
(:primary => true). And start_listeners would probably just run on :app.

That said, I can see the value in something like this:

task :do_something_on_server, :scope => :inherit do
# ...
end

Where the roles for the task inherit from the task that invoked it.
Maybe there's a cleaner way to do this, even. Anyone want to try their
hand a patch?

- Jamis

Reply all
Reply to author
Forward
0 new messages