litmus_paper 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm use ruby-1.8.7-p249@litmus_paper --create
1
+ rvm use ruby-1.9.3-p0@litmus_paper --create
data/.travis.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
3
+ - 1.9.1
4
4
  - 1.9.2
5
5
  - 1.9.3
data/bin/litmusctl CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'optparse'
4
- require 'litmus_paper'
4
+ require 'net/http'
5
5
  require 'litmus_paper/cli/admin'
6
6
 
7
7
  LitmusPaper::CLI::Admin.new.run
data/lib/litmus_paper.rb CHANGED
@@ -4,14 +4,24 @@ require 'net/https'
4
4
  require 'uri'
5
5
  require 'forwardable'
6
6
 
7
+ require 'async-rack'
7
8
  require 'sinatra/base'
8
- require 'facter'
9
- require 'syslog_logger'
9
+ require 'sinatra/synchrony'
10
+ require 'em-synchrony/em-http'
11
+ require 'em/syslog'
12
+
13
+ require 'thin'
14
+ require 'thin/callbacks'
15
+ require 'thin/backends/tcp_server_with_callbacks'
16
+ require 'thin/callback_rack_handler'
10
17
 
18
+ require 'facter'
11
19
  require 'facts/loadaverage'
12
20
 
13
21
  require 'litmus_paper/app'
14
22
  require 'litmus_paper/configuration'
23
+ require 'litmus_paper/deferred_facter'
24
+ require 'litmus_paper/dependency/haproxy_backends'
15
25
  require 'litmus_paper/dependency/http'
16
26
  require 'litmus_paper/dependency/tcp'
17
27
  require 'litmus_paper/health'
@@ -25,17 +35,17 @@ require 'litmus_paper/status_file'
25
35
  module LitmusPaper
26
36
  class << self
27
37
  attr_reader :services, :config_dir
28
- attr_accessor :logger
38
+ attr_accessor :logger, :config_file
29
39
  end
30
40
 
31
41
  self.logger = Logger.new
32
42
 
33
- def self.configure(filename)
34
- @config_file = filename
35
-
43
+ def self.configure!
44
+ LitmusPaper.logger.setup!
36
45
  begin
37
- @services = LitmusPaper::Configuration.new(filename).evaluate
38
- rescue Exception
46
+ @services = LitmusPaper::Configuration.new(@config_file).evaluate
47
+ rescue Exception => e
48
+ logger.info("Error in configuration #{e.message}")
39
49
  end
40
50
  end
41
51
 
@@ -44,7 +54,11 @@ module LitmusPaper
44
54
  end
45
55
 
46
56
  def self.reload
47
- configure(@config_file)
57
+ begin
58
+ @services = LitmusPaper::Configuration.new(@config_file).evaluate
59
+ rescue Exception => e
60
+ logger.info("Error in configuration #{e.message}")
61
+ end
48
62
  end
49
63
 
50
64
  def self.reset
@@ -53,3 +67,4 @@ module LitmusPaper
53
67
  end
54
68
 
55
69
  Signal.trap("HUP") { LitmusPaper.reload }
70
+
@@ -1,5 +1,9 @@
1
1
  module LitmusPaper
2
2
  class App < Sinatra::Base
3
+ register Sinatra::Synchrony
4
+ set :dump_errors, true
5
+ set :raise_errors, false
6
+
3
7
  get "/" do
4
8
  output = "Services monitored:\n"
5
9
  output += LitmusPaper.services.keys.join("\n")
@@ -44,7 +48,7 @@ module LitmusPaper
44
48
  end
45
49
 
46
50
  error do
47
- text 500, "Server Error"
51
+ text 500, "Server Error: " + env['sinatra.error'].message
48
52
  end
49
53
 
50
54
  def text(response_code, body, headers ={})
@@ -6,7 +6,7 @@ module LitmusPaper
6
6
  args, options = args.dup, {}
7
7
 
8
8
  opt_parser = OptionParser.new do |opts|
9
- opts.banner = "Usage: litmus [mongrel, thin, etc] [options]"
9
+ opts.banner = "Usage: litmus [options]"
10
10
  opts.on("-c", "--config=file", String,
11
11
  "Litmus configuration file", "Default: /etc/litmus.conf") { |v| options[:litmus_config] = v }
12
12
  opts.on("-D", "--data-dir=path", String,
@@ -31,7 +31,8 @@ module LitmusPaper
31
31
  opt_parser.parse! args
32
32
 
33
33
  options[:config] = File.expand_path("../../../config.ru", File.dirname(__FILE__))
34
- options[:server] = args.shift
34
+ options[:server] = 'thin-with-callbacks'
35
+ options[:backend] = Thin::Backends::TcpServerWithCallbacks
35
36
  options
36
37
  end
37
38
  end
@@ -46,8 +47,13 @@ module LitmusPaper
46
47
  exit 1
47
48
  end
48
49
 
49
- LitmusPaper.configure(options[:litmus_config])
50
+ LitmusPaper.config_file = options[:litmus_config]
50
51
  LitmusPaper.config_dir = options[:config_dir]
52
+
53
+ Thin::Callbacks.after_connect do
54
+ LitmusPaper.configure!
55
+ end
56
+
51
57
  super
52
58
  end
53
59
 
@@ -0,0 +1,14 @@
1
+ module LitmusPaper
2
+ class DeferredFacter
3
+ def self.value(key)
4
+ fiber = Fiber.current
5
+
6
+ EM.defer(
7
+ proc { Facter.value(key) },
8
+ proc { |value| fiber.resume(value) }
9
+ )
10
+
11
+ return Fiber.yield
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,70 @@
1
+ require 'csv'
2
+
3
+ module LitmusPaper
4
+ module Dependency
5
+ class HaproxyBackends
6
+
7
+ module HaproxyStatReader
8
+ def initialize(fiber)
9
+ @fiber = fiber
10
+ @stats = ""
11
+ end
12
+
13
+ def connection_completed
14
+ send_data("show stat\n")
15
+ end
16
+
17
+ def receive_data(data)
18
+ @stats << data
19
+ @fiber.resume(@stats) if finished?
20
+ end
21
+
22
+ def finished?
23
+ @stats =~ /\n\n\z/
24
+ end
25
+ end
26
+
27
+ def initialize(domain_socket, cluster)
28
+ @domain_socket = domain_socket
29
+ @cluster = cluster
30
+ end
31
+
32
+ def available?
33
+ stats = _parse_stats(_fetch_stats)
34
+ servers = _servers_in(stats, @cluster)
35
+
36
+ if not _any_up?(servers)
37
+ LitmusPaper.logger.info("None of the servers (#{servers.map{ |s| s['svname'] }.join(',')}) are up")
38
+ false
39
+ else
40
+ true
41
+ end
42
+ end
43
+
44
+ def _any_up?(servers)
45
+ available = servers.select { |s| s['status'] == "UP" }
46
+ available.size > 0
47
+ end
48
+
49
+ def _servers_in(stats, cluster)
50
+ stats.select do |line|
51
+ line['# pxname'] == cluster && !["FRONTEND", "BACKEND"].include?(line["svname"])
52
+ end
53
+ end
54
+
55
+ def _parse_stats(csv)
56
+ stats = CSV.parse(_fetch_stats)
57
+ headers = stats.shift
58
+ stats.map { |stat| Hash[headers.zip(stat)] }
59
+ end
60
+
61
+ def _fetch_stats
62
+ fiber = Fiber.current
63
+
64
+ connection = EM.connect_unix_domain(@domain_socket, HaproxyStatReader, fiber)
65
+
66
+ Fiber.yield
67
+ end
68
+ end
69
+ end
70
+ end
@@ -1,10 +1,12 @@
1
1
  module LitmusPaper
2
2
  module Dependency
3
3
  class HTTP
4
+ VALID_RESPONSE_CODES = (200..399).freeze
5
+
4
6
  def initialize(uri, options = {})
5
7
  @uri = uri
6
8
  @expected_content = Regexp.new(options.fetch(:content, '.*'))
7
- @method = options.fetch(:method, 'GET')
9
+ @method = options.fetch(:method, 'get')
8
10
  @ca_file = options[:ca_file]
9
11
  end
10
12
 
@@ -13,7 +15,7 @@ module LitmusPaper
13
15
  success = _successful_response?(response)
14
16
  matches = _body_matches?(response)
15
17
 
16
- LitmusPaper.logger.info("Available check to #{@uri} failed with status #{response.code}") unless success
18
+ LitmusPaper.logger.info("Available check to #{@uri} failed with status #{response.response_header.status}") unless success
17
19
  LitmusPaper.logger.info("Available check to #{@uri} did not match #{@expected_content}") unless matches
18
20
 
19
21
  success && matches
@@ -24,28 +26,18 @@ module LitmusPaper
24
26
 
25
27
  def _make_request
26
28
  uri = URI.parse(@uri)
27
- request = Net::HTTP.const_get(@method.capitalize).new(uri.normalize.path)
28
- request.set_form_data({})
29
-
30
- connection = Net::HTTP.new(uri.host, uri.port)
31
- if uri.scheme == "https"
32
- connection.use_ssl = true
33
- connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
34
- connection.ca_file = @ca_file unless @ca_file.nil?
35
- connection.verify_callback = proc { |preverify_ok, ssl_context| _verify_ssl_certificate(preverify_ok, ssl_context) }
36
- end
29
+ request_options = {}
30
+ request_options[:ssl] = {:verify_peer => true, :cert_chain_file => @ca_file} if uri.scheme == "https"
37
31
 
38
- connection.start do |http|
39
- http.request(request)
40
- end
32
+ EM::HttpRequest.new(@uri).send(@method.downcase, request_options)
41
33
  end
42
34
 
43
35
  def _successful_response?(response)
44
- response.is_a? Net::HTTPSuccess
36
+ VALID_RESPONSE_CODES.include? response.response_header.status
45
37
  end
46
38
 
47
39
  def _body_matches?(response)
48
- (response.body =~ @expected_content) ? true : false
40
+ (response.response =~ @expected_content) ? true : false
49
41
  end
50
42
 
51
43
  def _verify_ssl_certificate(preverify_ok, ssl_context)
@@ -1,18 +1,38 @@
1
1
  module LitmusPaper
2
2
  module Dependency
3
3
  class TCP
4
- def initialize(ip, port)
4
+ class EndpointAvailable < EM::Connection
5
+ def initialize(fiber, timeout, ip, port)
6
+ @fiber = fiber
7
+ @ip = ip
8
+ @port = port
9
+ EM.add_timer(timeout, method(:connection_timeout))
10
+ end
11
+
12
+ def connection_completed
13
+ close_connection
14
+ @fiber.resume(true)
15
+ end
16
+
17
+ def connection_timeout
18
+ LitmusPaper.logger.info("Available check to #{@ip}:#{@port} failed with a timeout")
19
+ @fiber.resume(false)
20
+ end
21
+ end
22
+
23
+ def initialize(ip, port, options = {})
5
24
  @ip, @port = ip, port
25
+ @timeout = options.fetch(:timeout, 2)
6
26
  end
7
27
 
8
28
  def available?
9
- Timeout.timeout(5) do
10
- socket = TCPSocket.new(@ip, @port)
11
- socket.close
29
+ fiber = Fiber.current
30
+
31
+ EM.connect(@ip, @port, EndpointAvailable, fiber, @timeout, @ip, @port) do |connection|
32
+ connection.set_pending_connect_timeout @timeout
12
33
  end
13
- true
14
- rescue Exception
15
- false
34
+
35
+ return Fiber.yield
16
36
  end
17
37
 
18
38
  def to_s
@@ -1,15 +1,15 @@
1
1
  module LitmusPaper
2
2
  class Logger
3
3
  extend Forwardable
4
- def_delegators :@syslog, :debug, :info
5
-
6
- def initialize
7
- @syslog = SyslogLogger.new("litmus_paper")
8
- end
4
+ def_delegators :EM, :debug, :info
9
5
 
10
6
  def write(message)
11
- @syslog.info(message)
7
+ info(message)
12
8
  end
13
9
 
10
+ def setup!
11
+ # @file = File.open("/tmp/error", "w")
12
+ EM.syslog_setup('0.0.0.0', 514)
13
+ end
14
14
  end
15
15
  end
@@ -7,7 +7,7 @@ module LitmusPaper
7
7
  "KB" => 1024
8
8
  }
9
9
 
10
- def initialize(weight, facter = Facter)
10
+ def initialize(weight, facter = DeferredFacter)
11
11
  @weight = weight
12
12
  @facter = facter
13
13
  end
@@ -1,7 +1,7 @@
1
1
  module LitmusPaper
2
2
  module Metric
3
3
  class CPULoad
4
- def initialize(weight, facter = Facter)
4
+ def initialize(weight, facter = DeferredFacter)
5
5
  @weight = weight
6
6
  @facter = facter
7
7
  end
@@ -1,3 +1,3 @@
1
1
  module LitmusPaper
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,41 @@
1
+ # inlined from sinatra-synchrony
2
+ require 'sinatra/base'
3
+ require 'rack/fiber_pool'
4
+ require 'eventmachine'
5
+ require 'em-http-request'
6
+ require 'em-synchrony'
7
+ require 'em-resolv-replace'
8
+
9
+ module Sinatra
10
+ module Synchrony
11
+ def self.registered(app)
12
+ app.disable :threaded
13
+ end
14
+
15
+ def setup_sessions(builder)
16
+ builder.use Rack::FiberPool, {:rescue_exception => handle_exception } unless test?
17
+ super
18
+ end
19
+
20
+ def handle_exception
21
+ Proc.new do |env, e|
22
+ if settings.show_exceptions?
23
+ request = Sinatra::Request.new(env)
24
+ printer = Sinatra::ShowExceptions.new(proc{ raise e })
25
+ s, h, b = printer.call(env)
26
+ [s, h, b]
27
+ else
28
+ LitmusPaper.logger.info(e)
29
+ [500, {}, ""]
30
+ end
31
+ end
32
+ end
33
+
34
+ class << self
35
+ def overload_tcpsocket!
36
+ require 'sinatra/synchrony/tcpsocket'
37
+ end
38
+ end
39
+ end
40
+ register Synchrony
41
+ end
@@ -0,0 +1,20 @@
1
+ module Thin
2
+ module Backends
3
+ class TcpServerWithCallbacks < TcpServer
4
+ def initialize(host, port, options)
5
+ super(host, port)
6
+ end
7
+
8
+ def connect
9
+ super
10
+ Thin::Callbacks.after_connect_callbacks.each { |callback| callback.call }
11
+ end
12
+
13
+ def disconnect
14
+ Thin::Callbacks.before_disconnect_callbacks.each { |callback| callback.call }
15
+ super
16
+ end
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,14 @@
1
+ module Thin
2
+ class CallbackRackHandler
3
+ def self.run(app, options)
4
+ server = ::Thin::Server.new(options[:Host] || '0.0.0.0',
5
+ options[:Port] || 8080,
6
+ app,
7
+ options)
8
+ yield server if block_given?
9
+ server.start
10
+ end
11
+ end
12
+ end
13
+
14
+ Rack::Handler.register 'thin-with-callbacks', Thin::CallbackRackHandler
@@ -0,0 +1,19 @@
1
+ module Thin
2
+ class Callbacks
3
+ def self.after_connect_callbacks
4
+ @after_connect_callbacks ||= []
5
+ end
6
+
7
+ def self.after_connect(&block)
8
+ after_connect_callbacks << block
9
+ end
10
+
11
+ def self.before_disconnect_callbacks
12
+ @before_disconnect_callbacks ||= []
13
+ end
14
+
15
+ def self.before_disconnect(&block)
16
+ before_disconnect_callbacks << block
17
+ end
18
+ end
19
+ end
data/litmus_paper.gemspec CHANGED
@@ -5,8 +5,8 @@ Gem::Specification.new do |gem|
5
5
  gem.authors = ["Braintreeps"]
6
6
  gem.email = ["code@getbraintree.com"]
7
7
  gem.description = %q{Backend health tester for HA Services}
8
- gem.summary = %q{Backend health tester for HA Services}
9
- gem.homepage = ""
8
+ gem.summary = %q{Backend health tester for HA Services, partner project of big_brother}
9
+ gem.homepage = "https://github.com/braintree/litmus_paper"
10
10
 
11
11
  gem.files = `git ls-files`.split($\)
12
12
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -15,9 +15,18 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = LitmusPaper::VERSION
17
17
 
18
+ gem.required_ruby_version = '>= 1.9.1'
19
+
20
+ gem.add_dependency "thin", "~> 1.3.1"
21
+ gem.add_dependency "async-rack", "~> 0.5.1"
18
22
  gem.add_dependency "sinatra", "~> 1.3.2"
23
+ gem.add_dependency "rack-fiber_pool", "~> 0.9"
19
24
  gem.add_dependency "facter", "~> 1.6.7"
20
- gem.add_dependency "SyslogLogger", "1.4.1"
25
+ gem.add_dependency "eventmachine", "> 1.0.0.beta.1", "< 1.0.0.beta.100"
26
+ gem.add_dependency "em-http-request", "~> 1.0"
27
+ gem.add_dependency "em-synchrony", "~> 1.0"
28
+ gem.add_dependency "em-resolv-replace", "~> 1.1"
29
+ gem.add_dependency "em-syslog", "~> 0.0.2"
21
30
 
22
31
  gem.add_development_dependency "rspec", "2.9.0"
23
32
  gem.add_development_dependency "rack-test", "0.6.1"
@@ -237,7 +237,7 @@ describe LitmusPaper::App do
237
237
  get "/test/error"
238
238
  last_response.status.should == 500
239
239
  last_response.headers["Content-Type"].should == "text/plain"
240
- last_response.body.should == "Server Error"
240
+ last_response.body.should == "Server Error: an error"
241
241
  ensure
242
242
  app.environment = old_environment
243
243
  end
@@ -7,7 +7,8 @@ describe 'litmusctl' do
7
7
  end
8
8
 
9
9
  before(:all) do
10
- system "bundle exec ruby -I lib bin/litmus -p 9293 -d -D /tmp/litmus_paper -c #{TEST_CONFIG} -P /tmp/litmus.pid"
10
+ `env RACK_ENV=production bundle exec ruby -I lib bin/litmus -p 9293 -d -D #{LitmusPaper.config_dir} -c #{TEST_CONFIG} -P /tmp/litmus.pid`
11
+ SpecHelper.wait_for_service :host => '127.0.0.1', :port => 9293
11
12
  end
12
13
 
13
14
  after(:all) do
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe LitmusPaper::DeferredFacter do
4
+ run_in_reactor
5
+
6
+ describe "value" do
7
+ it "executes Facter access on another thread" do
8
+ processors = LitmusPaper::DeferredFacter.value("processorcount")
9
+ processors.should match(/\d+/)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe LitmusPaper::Dependency::HaproxyBackends do
4
+ run_in_reactor
5
+
6
+ module StubHaproxy
7
+ def receive_data(data)
8
+ send_data(<<-DATA)
9
+ # pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,dresp,ereq,econ,eresp,wretr,wredis,status,weight,act,bck,chkfail,chkdown,lastchg,downtime,qlimit,pid,iid,sid,throttle,lbtot,tracked,type,rate,rate_lim,rate_max,check_status,check_code,check_duration,hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5xx,hrsp_other,hanafail,req_rate,req_rate_max,req_tot,cli_abrt,srv_abrt,
10
+ stats,FRONTEND,,,0,0,2000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,1,0,,,,0,0,0,0,,,,0,0,0,0,0,0,,0,0,0,,,
11
+ stats_backend,BACKEND,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,UP,0,0,0,,0,35,0,,1,2,0,,0,,1,0,,0,,,,0,0,0,0,0,0,,,,,0,0,
12
+ yellow,FRONTEND,,,0,0,2000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,3,0,,,,0,0,0,0,,,,,,,,,,,0,0,0,,,
13
+ yellow_cluster,node1,0,0,0,0,,0,0,0,,0,,0,0,0,0,UP,1,1,0,0,1,35,35,,1,4,1,,0,,2,0,,0,L4CON,,0,,,,,,,0,,,,0,0,
14
+ yellow_cluster,node2,0,0,0,0,,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,35,35,,1,4,1,,0,,2,0,,0,L4CON,,0,,,,,,,0,,,,0,0,
15
+ yellow_cluster,node3,0,0,0,0,,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,1,34,34,,1,4,2,,0,,2,0,,0,L4CON,,0,,,,,,,0,,,,0,0,
16
+ yellow_cluster,BACKEND,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,UP,0,0,0,,1,34,34,,1,4,0,,0,,1,0,,0,,,,,,,,,,,,,,0,0,
17
+ orange,FRONTEND,,,0,0,2000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,5,0,,,,0,0,0,0,,,,,,,,,,,0,0,0,,,
18
+ orange_cluster,orange1,0,0,0,0,,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,0,35,0,,1,6,1,,0,,2,0,,0,L4OK,,5,,,,,,,0,,,,0,0,
19
+ orange_cluster,orange2,0,0,0,0,,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,0,35,0,,1,6,1,,0,,2,0,,0,L4OK,,5,,,,,,,0,,,,0,0,
20
+ orange_cluster,BACKEND,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,DOWN,1,1,0,,0,35,0,,1,6,0,,0,,1,0,,0,,,,,,,,,,,,,,0,0,
21
+
22
+ DATA
23
+ end
24
+ end
25
+
26
+ describe "available?" do
27
+ around(:each) do |spec|
28
+ begin
29
+ EM.start_unix_domain_server("/tmp/haproxy.#{Process.pid}", StubHaproxy)
30
+ spec.run
31
+ ensure
32
+ FileUtils.rm("/tmp/haproxy.#{Process.pid}")
33
+ end
34
+ end
35
+
36
+ it "is available if at least one backend is up" do
37
+ haproxy = LitmusPaper::Dependency::HaproxyBackends.new("/tmp/haproxy.#{Process.pid}", "yellow_cluster")
38
+ haproxy.should be_available
39
+ end
40
+
41
+ it "returns 0 if no nodes are available" do
42
+ haproxy = LitmusPaper::Dependency::HaproxyBackends.new("/tmp/haproxy.#{Process.pid}", "orange_cluster")
43
+ haproxy.should_not be_available
44
+ end
45
+ end
46
+ end
47
+
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe LitmusPaper::Dependency::HTTP do
4
+ run_in_reactor
5
+
4
6
  before(:all) do
5
7
  server_start = system "bundle exec rackup spec/support/http_test_server_config.ru --port 9294 --pid /tmp/http-test-server.pid --daemonize"
6
8
  SpecHelper.wait_for_service :host => '127.0.0.1', :port => 9294
@@ -29,7 +31,7 @@ describe LitmusPaper::Dependency::HTTP do
29
31
  SpecHelper.wait_for_service :host => '127.0.0.1', :port => 9295
30
32
 
31
33
  check = LitmusPaper::Dependency::HTTP.new(
32
- "https://localhost:9295/",
34
+ "https://127.0.0.1:9295",
33
35
  :ca_file => TEST_CA_CERT
34
36
  )
35
37
  check.should be_available
@@ -1,27 +1,29 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe LitmusPaper::Dependency::TCP do
4
- before(:all) do
5
- @server = TCPServer.new 3333
6
- end
7
-
8
- after(:all) do
9
- @server.close
10
- end
4
+ run_in_reactor
11
5
 
12
6
  describe "#available?" do
7
+ around(:each) do |spec|
8
+ begin
9
+ @server = EM.start_server('127.0.0.1', 3333)
10
+ spec.run
11
+ ensure
12
+ EM.stop_server @server if @server
13
+ end
14
+ end
13
15
  it "is true when it's able to reach the ip and port" do
14
16
  check = LitmusPaper::Dependency::TCP.new("127.0.0.1", 3333)
15
17
  check.should be_available
16
18
  end
17
19
 
18
20
  it "is false when the ip is not available" do
19
- check = LitmusPaper::Dependency::TCP.new("10.254.254.254", 3333)
21
+ check = LitmusPaper::Dependency::TCP.new("127.1.1.15", 3333, :timeout => 0.3)
20
22
  check.should_not be_available
21
23
  end
22
24
 
23
25
  it "is false when the port is not available" do
24
- check = LitmusPaper::Dependency::TCP.new("127.0.0.1", 3334)
26
+ check = LitmusPaper::Dependency::TCP.new("127.0.0.1", 3334, :timeout => 0.3)
25
27
  check.should_not be_available
26
28
  end
27
29
  end
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe LitmusPaper::Metric::AvailableMemory do
4
+ run_in_reactor
5
+
4
6
  describe "#current_health" do
5
7
  it "multiplies weight by memory available" do
6
8
  facter = StubFacter.new({"memorytotal" => "10 GB", "memoryfree" => "5 GB"})
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe LitmusPaper::Metric::CPULoad do
4
+ run_in_reactor
5
+
4
6
  describe "#current_health" do
5
7
  it "is the percent of available cpu capacity" do
6
8
  facter = StubFacter.new({"processorcount" => "4", "loadaverage" => "1.00 0.40 0.10"})
@@ -3,14 +3,16 @@ require 'spec_helper'
3
3
  describe LitmusPaper do
4
4
  describe 'configure' do
5
5
  it 'populates services from the config file' do
6
- LitmusPaper.configure(TEST_CONFIG)
6
+ LitmusPaper.config_file = TEST_CONFIG
7
+ LitmusPaper.configure!
7
8
  LitmusPaper.services.has_key?('test').should == true
8
9
  end
9
10
  end
10
11
 
11
12
  describe "reload" do
12
13
  it "will reconfigure the services" do
13
- LitmusPaper.configure(TEST_CONFIG)
14
+ LitmusPaper.config_file = TEST_CONFIG
15
+ LitmusPaper.configure!
14
16
  LitmusPaper.services["bar"] = :service
15
17
 
16
18
  LitmusPaper.reload
@@ -20,20 +22,18 @@ describe LitmusPaper do
20
22
  end
21
23
 
22
24
  it "keeps the old config if there are errors in the new config" do
23
- old_config_file = SpecHelper.create_temp_file(<<-END)
25
+ LitmusPaper.config_file = SpecHelper.create_temp_file(<<-END)
24
26
  service :old_service do |s|
25
27
  s.measure_health Metric::CPULoad, :weight => 100
26
28
  end
27
29
  END
28
- new_bad_config_file = SpecHelper.create_temp_file(<<-END)
30
+ LitmusPaper.configure!
31
+ LitmusPaper.config_file = SpecHelper.create_temp_file(<<-END)
29
32
  service :old_service do |s|
30
33
  syntax error here
31
34
  end
32
35
  END
33
- LitmusPaper.configure(old_config_file)
34
- LitmusPaper.services.keys.should == ["old_service"]
35
- LitmusPaper.configure(new_bad_config_file)
36
- LitmusPaper.services.keys.should == ["old_service"]
36
+ LitmusPaper.reload
37
37
  end
38
38
  end
39
39
  end
data/spec/spec_helper.rb CHANGED
@@ -14,6 +14,18 @@ RSpec.configure do |config|
14
14
  config.before :each do
15
15
  FileUtils.rm_rf(LitmusPaper.config_dir)
16
16
  LitmusPaper.reset
17
+ LitmusPaper.logger = NullLogger.new
18
+ end
19
+ end
20
+
21
+ def run_in_reactor(timeout = 5)
22
+ around(:each) do |spec|
23
+ EM.synchrony do
24
+ sig = EM.add_timer(timeout) { fail "timeout!"; EM.stop }
25
+ spec.run
26
+ EM.cancel_timer(sig)
27
+ EM.stop
28
+ end
17
29
  end
18
30
  end
19
31
 
data/spec/ssl/server.crt CHANGED
@@ -1,14 +1,14 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- MIICKTCCAZICCQCmNl8pjL8nPzANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJB
3
- VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
4
- cyBQdHkgTHRkMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTIwNjA0MjExOTU2WhcN
5
- MTMwNjA0MjExOTU2WjBZMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0
6
- ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDEwls
7
- b2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK9fPamtXwFv341C
8
- jHFvJ4QxkKqWDACimkksBorVBUdMqsYwR/b9Ig4EHjAir8pfP3fjl98z4qRoWotx
9
- gCSj6OARoMsfS1+JGK8AsQyimq3uCErEyPAgHgfJ7+XORl0pgg3Z67pfzAqBs7aF
10
- p8pbEAkMVBdA62qhFVWAZhsTUxdVAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAa98H
11
- JPpxhaVFzAYkG+AyuCyskCSzXWvBAlJZXYejMZlSCGiZb3F94KeAlfRT9xCH2U6i
12
- /AxXVwO3mdeTP9s4Q90ehPZ8yS+LUVh6kVUneADRx5f410sz/FYF5j2hbdom2Sca
13
- 42BOBxnbIKmkzJcm1uEU5fRag6GbWdzpoLNKHmA=
2
+ MIICKzCCAZQCCQDNHjwe58QzrjANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJV
3
+ UzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xEjAQBgNVBAoT
4
+ CUJyYWludHJlZTESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTEyMDYwNTIxNTYzMloX
5
+ DTEzMDYwNTIxNTYzMlowWjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCElsbGlub2lz
6
+ MRAwDgYDVQQHEwdDaGljYWdvMRIwEAYDVQQKEwlCcmFpbnRyZWUxEjAQBgNVBAMT
7
+ CTEyNy4wLjAuMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApqUJrh8TczVL
8
+ 9FRom1TM1CQ/3PfiYqQ2CNtJM3Zpw3g61g8POmgrUnExbIUA/h7Cn1IzzITX5IiE
9
+ P4orsElrgc+T+6E4DGBA1mOpbFP3AlpIV90+cAIDuZE6trgxeW0OjneSiGmSR+gv
10
+ NY7B8HA1HV38eIYnb0WlLOXrSTO2O0sCAwEAATANBgkqhkiG9w0BAQUFAAOBgQAb
11
+ GCVAF99klFo62Snqivm8Xg/siacNWx+NbFJT5FRH3yJEFTOboFBqIdjkw3Ez+FMZ
12
+ T4Buz5IUW0GH6iHFula2X9Yp28qdMaY2ftOegF2TubfIJMtYlK0iY+nrlKIRLVSe
13
+ XyKCau0+/NiQ+WHYrK/QVuGiC8b9Ol5R+zD1yJIH4g==
14
14
  -----END CERTIFICATE-----
data/spec/ssl/server.key CHANGED
@@ -1,15 +1,15 @@
1
1
  -----BEGIN RSA PRIVATE KEY-----
2
- MIICXQIBAAKBgQCvXz2prV8Bb9+NQoxxbyeEMZCqlgwAoppJLAaK1QVHTKrGMEf2
3
- /SIOBB4wIq/KXz9345ffM+KkaFqLcYAko+jgEaDLH0tfiRivALEMopqt7ghKxMjw
4
- IB4Hye/lzkZdKYIN2eu6X8wKgbO2hafKWxAJDFQXQOtqoRVVgGYbE1MXVQIDAQAB
5
- AoGANyPdAYKvgoYoZgPsoKXwaNIkyF4RPAnkNOmQzQoZdMeYUmRP3ErO8FU/IKdn
6
- WlwEWq/GyrlHo6XkAkAXqG2ZBITsQaWKRky8nuydsJTXyt3z09R17WpH6dYNSyw5
7
- wc9UyGg+u5+hHiAOuMMVPEpePB4gBAo/XIBHe4ApqY5ZkakCQQDpI+DV2UmNLUG3
8
- qKavyncY382Fctc/m2GbNn2+B+6tDDGFcs4XwwPGEHaP66U3Aa9AU2MS2dPSDRl1
9
- IPvpQsTLAkEAwJFOvxKsxMwZT7vhCNkc8fKGI5wkjXRpCL5pEDUdDHExUbmaCGra
10
- PfNMEBkIDL4wGVNLLDZtl3/AgiyGzTIwXwJBAOP/BVK841QgDSOp2BEUJDJ8M8Ys
11
- z9nRf7vFp2Se50fuI8PIyUmtmlQpJ3mJzpGjoRp8Mehug9rompvUPOcaN88CQH9a
12
- 2niV0jtpPEg2WlLuvCzrl3lPmAERfzGwNG3qoqaK6fJBzLRKbsHP+XsgAuniko79
13
- PlckPACZFelBp3ln+wMCQQCvuEg+qo97LutnrUWID67PHEp+2W7SButs6yMerSac
14
- TYokvi2xz9auzRvxHofQiBIKsMji51uLmW8CfFaC8kS4
2
+ MIICXQIBAAKBgQCmpQmuHxNzNUv0VGibVMzUJD/c9+JipDYI20kzdmnDeDrWDw86
3
+ aCtScTFshQD+HsKfUjPMhNfkiIQ/iiuwSWuBz5P7oTgMYEDWY6lsU/cCWkhX3T5w
4
+ AgO5kTq2uDF5bQ6Od5KIaZJH6C81jsHwcDUdXfx4hidvRaUs5etJM7Y7SwIDAQAB
5
+ AoGAAngRg6XsONnCTVVu01ZXTpFW7OQzU3jRYCI3nG6VtJK0dHV2qUvf0HHi5JO3
6
+ 5wv3oDqsj8wsErO/Gd3nNc5wrE6S1qGIRU/1wvVbEgB2AIGYuXuGLyR9nrUkwjHp
7
+ ztPIBtl0cgapSSQxYAQ2Apu/aQCaP3l4IKUdktYBKO7CkJkCQQDS9iCKGNV+Xz8X
8
+ 0flPJ3yKBndLr1g4sbEacGA/+V/CHhWyKk6RXjWOUTCTPECi2eyg3WJaGnq32BTN
9
+ DEZ6YJgtAkEAyjjTWMut/UfoNF6a8++yNjo17JrH/MtCAEphXZcUxEmubYkODR0v
10
+ wNELrstWOfkuGVTZm618RHM0J6LqfVsUVwJBAJ4CaeblqOrpbjlqNUDbQ4WiSDIx
11
+ GHQGa69w4jaoktezbu6uj4CEPrrlBuwQ4hzX+0uV5fe1A5u1xga7HgLFXNUCQA0d
12
+ 8H+S/p8uOd6jwFNQWfPwhKzrQUuhd4+DQ5uJgDxXNyw9tp6dJQrRxHs7D0XFZvsX
13
+ qOHTN/tMqbZkd+dXsBMCQQCgLIW0Og3LHubDCn9jNoz21Achi2kwI5AOXEnyHL2W
14
+ XvjJH6PM3/d9TpUVYCoj8PO5WoXCSt1DVpZ5ow28ad6M
15
15
  -----END RSA PRIVATE KEY-----
@@ -0,0 +1,11 @@
1
+ class NullLogger
2
+ def write(message)
3
+ end
4
+ def info(message)
5
+ end
6
+ def debug(message)
7
+ end
8
+
9
+ def setup!
10
+ end
11
+ end
metadata CHANGED
@@ -1,143 +1,182 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: litmus_paper
3
- version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 1
9
- - 0
10
- version: 0.1.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Braintreeps
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-06-04 00:00:00 -05:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: sinatra
12
+ date: 2012-06-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thin
16
+ requirement: &70350255865480 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.3.1
22
+ type: :runtime
23
23
  prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
24
+ version_requirements: *70350255865480
25
+ - !ruby/object:Gem::Dependency
26
+ name: async-rack
27
+ requirement: &70350255864360 !ruby/object:Gem::Requirement
25
28
  none: false
26
- requirements:
29
+ requirements:
27
30
  - - ~>
28
- - !ruby/object:Gem::Version
29
- hash: 31
30
- segments:
31
- - 1
32
- - 3
33
- - 2
31
+ - !ruby/object:Gem::Version
32
+ version: 0.5.1
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70350255864360
36
+ - !ruby/object:Gem::Dependency
37
+ name: sinatra
38
+ requirement: &70350255863320 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
34
43
  version: 1.3.2
35
44
  type: :runtime
36
- version_requirements: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: facter
39
45
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
46
+ version_requirements: *70350255863320
47
+ - !ruby/object:Gem::Dependency
48
+ name: rack-fiber_pool
49
+ requirement: &70350255862000 !ruby/object:Gem::Requirement
41
50
  none: false
42
- requirements:
51
+ requirements:
43
52
  - - ~>
44
- - !ruby/object:Gem::Version
45
- hash: 1
46
- segments:
47
- - 1
48
- - 6
49
- - 7
53
+ - !ruby/object:Gem::Version
54
+ version: '0.9'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70350255862000
58
+ - !ruby/object:Gem::Dependency
59
+ name: facter
60
+ requirement: &70350255860460 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
50
65
  version: 1.6.7
51
66
  type: :runtime
52
- version_requirements: *id002
53
- - !ruby/object:Gem::Dependency
54
- name: SyslogLogger
55
67
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
68
+ version_requirements: *70350255860460
69
+ - !ruby/object:Gem::Dependency
70
+ name: eventmachine
71
+ requirement: &70350255859680 !ruby/object:Gem::Requirement
57
72
  none: false
58
- requirements:
59
- - - "="
60
- - !ruby/object:Gem::Version
61
- hash: 5
62
- segments:
63
- - 1
64
- - 4
65
- - 1
66
- version: 1.4.1
73
+ requirements:
74
+ - - ! '>'
75
+ - !ruby/object:Gem::Version
76
+ version: 1.0.0.beta.1
77
+ - - <
78
+ - !ruby/object:Gem::Version
79
+ version: 1.0.0.beta.100
80
+ type: :runtime
81
+ prerelease: false
82
+ version_requirements: *70350255859680
83
+ - !ruby/object:Gem::Dependency
84
+ name: em-http-request
85
+ requirement: &70350255858120 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ~>
89
+ - !ruby/object:Gem::Version
90
+ version: '1.0'
67
91
  type: :runtime
68
- version_requirements: *id003
69
- - !ruby/object:Gem::Dependency
70
- name: rspec
71
92
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::Requirement
93
+ version_requirements: *70350255858120
94
+ - !ruby/object:Gem::Dependency
95
+ name: em-synchrony
96
+ requirement: &70350255857500 !ruby/object:Gem::Requirement
73
97
  none: false
74
- requirements:
75
- - - "="
76
- - !ruby/object:Gem::Version
77
- hash: 43
78
- segments:
79
- - 2
80
- - 9
81
- - 0
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '1.0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: *70350255857500
105
+ - !ruby/object:Gem::Dependency
106
+ name: em-resolv-replace
107
+ requirement: &70350255856860 !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ~>
111
+ - !ruby/object:Gem::Version
112
+ version: '1.1'
113
+ type: :runtime
114
+ prerelease: false
115
+ version_requirements: *70350255856860
116
+ - !ruby/object:Gem::Dependency
117
+ name: em-syslog
118
+ requirement: &70350255856040 !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ~>
122
+ - !ruby/object:Gem::Version
123
+ version: 0.0.2
124
+ type: :runtime
125
+ prerelease: false
126
+ version_requirements: *70350255856040
127
+ - !ruby/object:Gem::Dependency
128
+ name: rspec
129
+ requirement: &70350255855260 !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - =
133
+ - !ruby/object:Gem::Version
82
134
  version: 2.9.0
83
135
  type: :development
84
- version_requirements: *id004
85
- - !ruby/object:Gem::Dependency
86
- name: rack-test
87
136
  prerelease: false
88
- requirement: &id005 !ruby/object:Gem::Requirement
137
+ version_requirements: *70350255855260
138
+ - !ruby/object:Gem::Dependency
139
+ name: rack-test
140
+ requirement: &70350255854380 !ruby/object:Gem::Requirement
89
141
  none: false
90
- requirements:
91
- - - "="
92
- - !ruby/object:Gem::Version
93
- hash: 5
94
- segments:
95
- - 0
96
- - 6
97
- - 1
142
+ requirements:
143
+ - - =
144
+ - !ruby/object:Gem::Version
98
145
  version: 0.6.1
99
146
  type: :development
100
- version_requirements: *id005
101
- - !ruby/object:Gem::Dependency
102
- name: rake
103
147
  prerelease: false
104
- requirement: &id006 !ruby/object:Gem::Requirement
148
+ version_requirements: *70350255854380
149
+ - !ruby/object:Gem::Dependency
150
+ name: rake
151
+ requirement: &70350255853660 !ruby/object:Gem::Requirement
105
152
  none: false
106
- requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- hash: 3
110
- segments:
111
- - 0
112
- version: "0"
153
+ requirements:
154
+ - - ! '>='
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
113
157
  type: :development
114
- version_requirements: *id006
115
- - !ruby/object:Gem::Dependency
116
- name: rake_commit
117
158
  prerelease: false
118
- requirement: &id007 !ruby/object:Gem::Requirement
159
+ version_requirements: *70350255853660
160
+ - !ruby/object:Gem::Dependency
161
+ name: rake_commit
162
+ requirement: &70350255852600 !ruby/object:Gem::Requirement
119
163
  none: false
120
- requirements:
121
- - - "="
122
- - !ruby/object:Gem::Version
123
- hash: 17
124
- segments:
125
- - 0
126
- - 13
127
- version: "0.13"
164
+ requirements:
165
+ - - =
166
+ - !ruby/object:Gem::Version
167
+ version: '0.13'
128
168
  type: :development
129
- version_requirements: *id007
169
+ prerelease: false
170
+ version_requirements: *70350255852600
130
171
  description: Backend health tester for HA Services
131
- email:
172
+ email:
132
173
  - code@getbraintree.com
133
- executables:
174
+ executables:
134
175
  - litmus
135
176
  - litmusctl
136
177
  extensions: []
137
-
138
178
  extra_rdoc_files: []
139
-
140
- files:
179
+ files:
141
180
  - .gitignore
142
181
  - .rake_commit
143
182
  - .rvmrc
@@ -155,6 +194,8 @@ files:
155
194
  - lib/litmus_paper/cli/admin.rb
156
195
  - lib/litmus_paper/cli/server.rb
157
196
  - lib/litmus_paper/configuration.rb
197
+ - lib/litmus_paper/deferred_facter.rb
198
+ - lib/litmus_paper/dependency/haproxy_backends.rb
158
199
  - lib/litmus_paper/dependency/http.rb
159
200
  - lib/litmus_paper/dependency/tcp.rb
160
201
  - lib/litmus_paper/forced_health.rb
@@ -165,11 +206,17 @@ files:
165
206
  - lib/litmus_paper/service.rb
166
207
  - lib/litmus_paper/status_file.rb
167
208
  - lib/litmus_paper/version.rb
209
+ - lib/sinatra/synchrony.rb
210
+ - lib/thin/backends/tcp_server_with_callbacks.rb
211
+ - lib/thin/callback_rack_handler.rb
212
+ - lib/thin/callbacks.rb
168
213
  - litmus_paper.gemspec
169
214
  - spec/litmus_paper/app_spec.rb
170
215
  - spec/litmus_paper/cli/admin_spec.rb
171
216
  - spec/litmus_paper/cli/server_spec.rb
172
217
  - spec/litmus_paper/configuration_spec.rb
218
+ - spec/litmus_paper/deferred_facter_spec.rb
219
+ - spec/litmus_paper/dependency/haproxy_backends_spec.rb
173
220
  - spec/litmus_paper/dependency/http_spec.rb
174
221
  - spec/litmus_paper/dependency/tcp_spec.rb
175
222
  - spec/litmus_paper/health_spec.rb
@@ -189,49 +236,42 @@ files:
189
236
  - spec/support/http_test_server.rb
190
237
  - spec/support/http_test_server_config.ru
191
238
  - spec/support/never_available_dependency.rb
239
+ - spec/support/null_logger.rb
192
240
  - spec/support/stdout_logger.rb
193
241
  - spec/support/stub_facter.rb
194
242
  - spec/support/test.config
195
243
  - spec/support/test.d.config
196
- has_rdoc: true
197
- homepage: ""
244
+ homepage: https://github.com/braintree/litmus_paper
198
245
  licenses: []
199
-
200
246
  post_install_message:
201
247
  rdoc_options: []
202
-
203
- require_paths:
248
+ require_paths:
204
249
  - lib
205
- required_ruby_version: !ruby/object:Gem::Requirement
250
+ required_ruby_version: !ruby/object:Gem::Requirement
206
251
  none: false
207
- requirements:
208
- - - ">="
209
- - !ruby/object:Gem::Version
210
- hash: 3
211
- segments:
212
- - 0
213
- version: "0"
214
- required_rubygems_version: !ruby/object:Gem::Requirement
252
+ requirements:
253
+ - - ! '>='
254
+ - !ruby/object:Gem::Version
255
+ version: 1.9.1
256
+ required_rubygems_version: !ruby/object:Gem::Requirement
215
257
  none: false
216
- requirements:
217
- - - ">="
218
- - !ruby/object:Gem::Version
219
- hash: 3
220
- segments:
221
- - 0
222
- version: "0"
258
+ requirements:
259
+ - - ! '>='
260
+ - !ruby/object:Gem::Version
261
+ version: '0'
223
262
  requirements: []
224
-
225
263
  rubyforge_project:
226
- rubygems_version: 1.3.7
264
+ rubygems_version: 1.8.10
227
265
  signing_key:
228
266
  specification_version: 3
229
- summary: Backend health tester for HA Services
230
- test_files:
267
+ summary: Backend health tester for HA Services, partner project of big_brother
268
+ test_files:
231
269
  - spec/litmus_paper/app_spec.rb
232
270
  - spec/litmus_paper/cli/admin_spec.rb
233
271
  - spec/litmus_paper/cli/server_spec.rb
234
272
  - spec/litmus_paper/configuration_spec.rb
273
+ - spec/litmus_paper/deferred_facter_spec.rb
274
+ - spec/litmus_paper/dependency/haproxy_backends_spec.rb
235
275
  - spec/litmus_paper/dependency/http_spec.rb
236
276
  - spec/litmus_paper/dependency/tcp_spec.rb
237
277
  - spec/litmus_paper/health_spec.rb
@@ -251,6 +291,7 @@ test_files:
251
291
  - spec/support/http_test_server.rb
252
292
  - spec/support/http_test_server_config.ru
253
293
  - spec/support/never_available_dependency.rb
294
+ - spec/support/null_logger.rb
254
295
  - spec/support/stdout_logger.rb
255
296
  - spec/support/stub_facter.rb
256
297
  - spec/support/test.config