Created
July 13, 2015 21:36
-
-
Save evantahler/9fa167a8be811fa710e2 to your computer and use it in GitHub Desktop.
Testing Ansibile with Vagrant and RSpec
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'net/ssh' | |
require "#{File.dirname(__FILE__)}/utils/gems.rb" | |
require "#{File.dirname(__FILE__)}/utils/multi_logger.rb" | |
require "#{File.dirname(__FILE__)}/utils/subprocess.rb" | |
class SpecHelper | |
class << self | |
@@booted = false | |
def ensure_booted | |
if @@booted | |
logger.write "test cluster already booted..." | |
else | |
boot | |
end | |
end | |
def ssh_config | |
return @config unless @config.nil? | |
@config = {} | |
lines = `vagrant ssh-config`.split("\n") | |
current_host = nil | |
lines.each do |line| | |
words = line.split(" ") | |
if words.length < 2 | |
next | |
elsif words.first == 'Host' | |
current_host = words.last | |
@config[current_host] = {} | |
else | |
@config[current_host][words.first] = words.last | |
end | |
end | |
@config | |
end | |
def logger | |
MultiLogger.new(STDOUT, log_file) | |
end | |
def log_file | |
File.expand_path("#{File.dirname(__FILE__)}/../log/test.log") | |
end | |
def boot | |
logger.write "[[ BOOT ]]", :purple | |
Utils::SubprocessWithLog.new("vagrant up --parallel --no-provision", "vagrant-boot", logger) | |
end | |
def provision | |
logger.write "[[ PROVISION ]]", :purple | |
# We only define 1 server to provision here, but the ansible inventory lists all nodes | |
Utils::SubprocessWithLog.new("vagrant provision", '*', logger) | |
end | |
def vagrant_ssh_key | |
"#{ENV['HOME']}/.vagrant.d/insecure_private_key" | |
end | |
def ssh_username | |
'vagrant' | |
end | |
def ssh_host | |
'127.0.0.1' | |
end | |
def ips | |
return @remote_ips unless @remote_ips.nil? | |
@remote_ips = [] | |
ssh_config.each do |name, data| | |
port = data['Port'].to_i | |
Net::SSH.start(ssh_host, ssh_username, { | |
port: port, | |
keys: [vagrant_ssh_key], | |
:paranoid => Net::SSH::Verifiers::Null.new | |
}) do |session| | |
remote_data = session.exec!('ifconfig -a') | |
possible_ips = remote_data.scan(/.*inet addr:(\S*)/) | |
possible_ips.each do |ip| | |
ip = ip.first | |
parts = ip.split(".") | |
next if parts.first == '127' | |
next if parts.first == '10' | |
@remote_ips << ip | |
end | |
end | |
end | |
@remote_ips | |
end | |
def remote_command(ip, command) | |
remote_data = nil | |
Net::SSH.start(ip, ssh_username, { | |
keys: [vagrant_ssh_key], | |
:paranoid => Net::SSH::Verifiers::Null.new | |
}) do |session| | |
remote_data = session.exec!(command) | |
end | |
remote_data | |
end | |
def remote_file(ip, path) | |
command = "sudo cat #{path}" #TODO: unsafe... but this is a test suite! | |
remote_command(ip, command) | |
end | |
end | |
end | |
RSpec.configure do |config| | |
config.before(:suite) do | |
SpecHelper.ensure_booted | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'bundler' | |
Bundler.require(:default) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'fileutils' | |
class MultiLogger | |
def initialize(*targets) | |
@targets = targets | |
ensure_files | |
end | |
def ensure_files | |
@targets.each do |t| | |
if t.class != IO | |
FileUtils.mkdir_p File.dirname(t) | |
FileUtils.touch t | |
end | |
end | |
end | |
def write(lines, color=:normal, to_clock=true) | |
date_string = Time.new.strftime('%Y-%m-%d %l:%M:%S') | |
lines.split("\n").each do |line| | |
@targets.each do |t| | |
formatted_line = "" | |
if t.class == IO | |
formatted_line = "[#{color}]" + line + "[/]" | |
formatted_line = "[light_cyan][#{date_string}][/] " + formatted_line if to_clock | |
# t.write(formatted_line) | |
Formatador.display_line(formatted_line) | |
else | |
formatted_line = line + "\r\n" | |
formatted_line = "[#{date_string}] " + formatted_line if to_clock | |
File.open(t,"a+") {|f| f.write(formatted_line) } | |
end | |
end | |
end | |
end | |
end | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'open3' | |
module Utils | |
class Subprocess | |
def initialize(cmd, &block) | |
# see: http://stackoverflow.com/a/1162850/83386 | |
Open3.popen3(ENV, cmd) do |stdin, stdout, stderr, thread| | |
{ :out => stdout, :err => stderr }.each do |key, stream| | |
Thread.new do | |
until (line = stream.gets).nil? do | |
if key == :out | |
yield line, nil, thread if block_given? | |
else | |
yield nil, line, thread if block_given? | |
end | |
end | |
end | |
end | |
thread.join # don't exit until the external process is done | |
end | |
end | |
end | |
class SubprocessWithLog | |
def initialize(cmd, name=nil, logger) | |
Utils::Subprocess.new(cmd) do |stdout, stderr, thread| | |
logger.write("[#{name}] #{stdout.to_s.strip}") if stdout | |
logger.write("[#{name}] #{stderr.to_s.strip}", :red) if stderr | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment