Dynamically Defined Targets for Remote Tasks in Vlad
Typically things like Vlad and Capistrano make the assumption you already know where you want to run your tasks. They assume you already have some servers somewhere ticking over just fine and you want to do stuff on them according to some predetermined pattern.
However, what happens when you want to write some tasks you can run on any remote server? What happens if you don’t have any servers and you want to build some dynamically and then run some remote tasks on them?
Well, I’ve been asking these questions and I found an answer that helped me out and thought I’d share it here.
Using the dependency system of rake and the lazy role evaluation of vlad along with the fact that it provides some very useful public class methods (so they are presumably safe, rather than hacking into the internals with send or the like) I wrote the following simple test script:
task :server_config do
ssh_string = HighLine.new.ask 'Enter the SSH details of the server you want to connect to: '
Rake::RemoteTask.role :server, ssh_string
desc 'Run stuff on a server'
remote_task :server, :roles => :server do
run "echo 'hello i am a server'"
task :server => :server_config
What’s going on here is that I have a remote task using a role server which as of yet I haven’t defined. When I run
rake server that runs the server task. The server task is dependent on the server_config task which sets up a role ‘server’ with the given string (ideally something like firstname.lastname@example.org). The remote task then executes, evaluating the value of the role, which is now set to the users input, and connects to the server you’ve set at run time. How awesome is that?
Of course, this is a contrived example, you could use a system to setup roles automatically from other things rather than pulling in user input but the lesson to take away here is that is is possible to use vlad tasks on dynamically defined targets easily.