Skip to content

Instantly share code, notes, and snippets.

@arika
Created October 3, 2009 00:33
Show Gist options
  • Save arika/200278 to your computer and use it in GitHub Desktop.
Save arika/200278 to your computer and use it in GitHub Desktop.
An experimental helper. It makes Capistrano tasks that can refer its upstream hosts/roles
module UpstreamSupport
module Utils
def initialize(config)
@config = config
end
def to_ary
to_a
end
private
def method_missing(m, *arg)
to_a.__send__(m, *arg)
end
def detect_upstream_task(sym)
rtcf = @config.task_call_frames.reverse
rtcf.shift
utf = rtcf.detect do |tf|
opt = tf.task.options[sym]
opt && !opt.kind_of?(self.class)
end
utf ? utf.task : nil
end
end
class Hosts
include Utils
def to_a
return [] if ENV['HOSTS']
task = detect_upstream_task(:hosts)
task ? @config.find_servers_for_task(task) : []
end
end
class Roles
include Utils
def to_a
return [] if ENV['ROLES']
task = detect_upstream_task(:roles)
task ? task.options[:roles] : @config.roles.keys
end
end
module_function
def create(config)
[Hosts.new(config), Roles.new(config)]
end
end
#logger.level = Logger::INFO
uh, ur = UpstreamSupport.create(self)
def test_capture(*opt)
buf = Hash.new {|h, k| h[k] = "" }
run(*opt) do |ch, st, data|
buf[ch[:server]] << data
end
$result = buf.keys.sort.map {|k| buf[k].chomp }
end
def assert(expect, msg = nil)
unless expect.sort == $result.sort
text = "#{current_task.fully_qualified_name}"
text << ": #{msg}" if msg
text << "\n\texpect: #{expect.inspect}"
text << "\n\tresult: #{$result.inspect}"
raise CommandError, text
end
end
all_hosts = %w(host1 host2 host3 host4)
host1, host2, host3, host4 = all_hosts
roleA_hosts = [host1, host2]
roleB_hosts = [host3, host4]
role :roleA, *roleA_hosts
role :roleB, *roleB_hosts
other_hosts = %w(hostA hostB)
hostA, hostB = other_hosts
namespace :upstream_test do
task :root_task do
parent_task
end
task :parent_task do
child_task
end
task :child_task, :hosts => uh do
test_capture "echo $CAPISTRANO:HOST$"
end
task :test_no_arg1 do
root_task
assert all_hosts
end
task :test_no_arg2 do
parent_task
assert all_hosts
end
task :test_no_arg3 do
child_task
assert all_hosts
end
task :test_arg1, :hosts => other_hosts do
root_task
assert other_hosts
end
task :test_arg2, :hosts => other_hosts do
parent_task
assert other_hosts
end
task :test_arg3, :hosts => [host1] do
test_arg3_sub1
assert [host2]
end
task :test_arg3_sub1, :hosts => [host2] do
root_task
end
desc <<-E
this test has :roles option but task :child_task doesn't have :rules option.
:child_task should ignore upstream :roles option.
E
task :test_arg9, :roles => [:roleB] do
child_task
assert all_hosts
end
task :test_env1 do
ENV['HOSTS'] = other_hosts.join(',')
root_task
assert other_hosts
end
task :test_env2 do
ENV['ROLES'] = 'roleB'
root_task
assert roleB_hosts
end
task :default do
[
:test_no_arg1, :test_no_arg2, :test_no_arg3,
:test_arg1, :test_arg2, :test_arg3, :test_arg9,
:test_env1, :test_env2,
].each do |task|
begin
ENV.delete('HOSTS')
ENV.delete('ROLES')
find_and_execute_task(fully_qualified_name + ":#{task}")
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment