Getting hold of server specific config in a task - how to?

15 views
Skip to first unread message

David Collie

unread,
Feb 9, 2007, 6:41:26 AM2/9/07
to capis...@googlegroups.com
Hi all

I want to get hold of the server that a task is being run for. Say for example I have:

role :db,  db1.example.com, :primary => true
role :db,  db2.example.com

When I run a task that has :roles => :db specified I would like, inside the task, to get hold of the name each server that the task is being executed for. My reasoning behind this is to deploy customised configuration files per database server (to support MySQL dual master replication). So actually what I want to do is this:

role :db,  db1.example.com, :primary => true, :server_id => 1, :master_host => db2.example.com
role :db,  db2.example.com, :server_id => 2, :master_host => db1.example.com

Then inside my task I want to pass this server specific config information to a render call:

task :config_mysql_replication, :roles => db do
render(:file => "my.cnf", {HASH OF SERVER SPECIFIC DETAILS (:master_host etc)})
end

Anyone know if this is possible?

Thanks,

-Dave
Web Applications for Healthcare






Jamis Buck

unread,
Feb 9, 2007, 10:12:59 AM2/9/07
to capis...@googlegroups.com
David,

You _can_ get at the individual servers, but note that things like
'put' work on all servers configured for the current task, not on
specific servers, so you'd have to jump through a lot of hoops. A
better way would probably be to do something like this:

task :config_mysql_replication_for_db1, :hosts =>
"db1.example.com" do
...
end

task :config_mysql_replication_for_db2, :hosts =>
"db2.example.com" do
...
end

And so forth. Judicial use of metaprogramming can make that much drier:

DB_SERVERS = %w(db1 db2)

primary = true
DB_SERVERS.each do |server|
role :db, "#{server}.example.com", :primary => primary
primary = false

task :"config_mysql_replication_for_#{server}", :hosts => "#
{server}.example.com" do
...
end
end

task :config_mysql_replication do
DB_SERVERS.each do |server|
send "config_mysql_replication_for_#{server}"
end
end

THAT SAID, there is probably an even cleaner way of doing it. If you
have a script on each server that knows how to build my.cnf for its
current host, doing this all from cap is as easy as:

task :config_mysql_replication, :roles => :db do

run "/path/to/builder_script.rb"
end

- Jamis

David Collie

unread,
Feb 9, 2007, 1:00:50 PM2/9/07
to Capistrano
Jamis

Thanks for the quick reply. I'll pursue the judicial use of
metaprogramming ;-)

Dave

Neil Wilson

unread,
Feb 11, 2007, 3:37:09 AM2/11/07
to Capistrano
Bear in mind that if you do that you will serialise the capistrano
calls and that can massively increase the time it takes to run tasks
if you have a large estate of servers.

To retain parallellism you really need to look at deploying scripts to
the server that handle the server specific stuff.

My favourite approach is to upload a YML file that has the data for
*all* the servers in it and then use my 'std.ruby' command from the
'vmbuilder_plugins' Gem to run some ruby on the remote server that
loads the YML file and accesses the data specific the server based on
the result of a 'hostname' call.

NeilW

Reply all
Reply to author
Forward
0 new messages