Skip to content

Instantly share code, notes, and snippets.

@vincentbernat
Created December 17, 2013 22:59
Show Gist options
  • Save vincentbernat/8014225 to your computer and use it in GitHub Desktop.
Save vincentbernat/8014225 to your computer and use it in GitHub Desktop.
Rakefile for running parallel serverspec
require 'rake'
require 'rspec/core/rake_task'
require 'xpool'
require 'colorize'
$REPORTS = "./reports" # Where to store JSON reports
$PARALLEL = 10 # How many parallel tasks should we run?
# Return all roles of a given host
def roles(host)
roles = [ "all" ]
case host
when /^blm-web-/
roles << "web"
when /^blm-memc-/
roles << "memcache"
when /^blm-lb-/
roles << "lb"
when /^blm-bigdata-/
roles << "bigdata"
when /^blm-proxy-/
roles << "proxy"
end
return roles
end
# Run RSpec in the background. It is important to define this before
# creating a pool.
class BackgroundServerspecTask
def run(verbose, target, command)
print "[..] ".blue if verbose
puts target if verbose
ENV['TARGET_HOST'] = target
system(command)
print "[OK] ".green if verbose
puts target if verbose
end
def recover(e)
print "[ERROR] ".red
puts e.to_s
end
end
# Special version of RakeTask that will be executed using a process
# pool. This process pool is handled by xpool.
class ServerspecTask < RSpec::Core::RakeTask
attr_accessor :target
@@pool = XPool.new $PARALLEL
def self.shutdown
@@pool.shutdown
end
def run_task(verbose)
@rspec_opts = ["--format", "json", "--out", "#{$REPORTS}/report-#{target}.json"]
command = spec_command
@@pool.schedule BackgroundServerspecTask.new, verbose, target, command
end
end
hosts = File.foreach(ENV["HOSTS"] || "./hosts")
.map { |line| line.strip }
.map do |host|
{
:name => host.strip,
:roles => roles(host.strip),
}
end
desc "Run serverspec to all hosts"
task :spec => "check:server:all"
namespace :check do
# Per server tasks
namespace :server do
desc "Run serverspec to all hosts"
task :all => hosts.map { |h| "check:server:" + h[:name] }
hosts.each do |host|
desc "Run serverspec to host #{host[:name]}"
ServerspecTask.new(host[:name].to_sym) do |t|
t.target = host[:name]
t.pattern = './spec/{' + host[:roles].join(",") + '}*_spec.rb'
end
end
end
# Per role tasks
namespace :role do
roles = hosts.map {|h| h[:roles]}
roles = roles.flatten.uniq
roles.each do |role|
hosts.select { |h| h[:roles].include? role }.each do |host|
desc "Run serverspec to role #{role}"
ServerspecTask.new(role.to_sym) do |t|
t.target = host[:name]
t.pattern = "./spec/#{role}/*_spec.rb"
end
end
end
end
end
namespace :reports do
desc "Clean up old reports"
task :clean do
FileUtils.rm_rf $REPORTS
end
end
check_tasks = Rake.application.top_level_tasks.select { |task| task.start_with?("check:") }
puts check_tasks
if not check_tasks.empty? then
# Before starting, cleanup reports
Rake::Task[check_tasks.first].enhance [ "reports:clean" ]
end
Kernel.at_exit do
ServerspecTask.shutdown
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment