litmus_paper 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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