is_it_working-cbeer 1.0.11
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/.gitignore +2 -0
- data/Gemfile +3 -0
- data/License.txt +674 -0
- data/README.rdoc +75 -0
- data/Rakefile +17 -0
- data/VERSION +1 -0
- data/is_it_working.gemspec +23 -0
- data/lib/is_it_working/checks/action_mailer_check.rb +25 -0
- data/lib/is_it_working/checks/active_record_check.rb +28 -0
- data/lib/is_it_working/checks/dalli_check.rb +48 -0
- data/lib/is_it_working/checks/directory_check.rb +44 -0
- data/lib/is_it_working/checks/memcache_check.rb +46 -0
- data/lib/is_it_working/checks/ping_check.rb +53 -0
- data/lib/is_it_working/checks/url_check.rb +81 -0
- data/lib/is_it_working/filter.rb +55 -0
- data/lib/is_it_working/handler.rb +153 -0
- data/lib/is_it_working/status.rb +62 -0
- data/lib/is_it_working.rb +18 -0
- data/spec/action_mailer_check_spec.rb +51 -0
- data/spec/active_record_check_spec.rb +51 -0
- data/spec/dalli_check_spec.rb +53 -0
- data/spec/directory_check_spec.rb +70 -0
- data/spec/filter_spec.rb +46 -0
- data/spec/handler_spec.rb +140 -0
- data/spec/memecache_check_spec.rb +51 -0
- data/spec/ping_check_spec.rb +47 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/status_spec.rb +54 -0
- data/spec/url_check_spec.rb +144 -0
- metadata +180 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
module IsItWorking
|
2
|
+
# This class is used to pass the status of a monitoring check. Each status can have multiple
|
3
|
+
# messages added to it by calling the +ok+ or +fail+ methods. The status check will only be
|
4
|
+
# considered a success if all messages are ok.
|
5
|
+
class Status
|
6
|
+
# This class is used to contain individual status messages. Eache method can represent either
|
7
|
+
# and +ok+ message or a +fail+ message.
|
8
|
+
class Message
|
9
|
+
class <<self
|
10
|
+
attr_accessor :ok_states
|
11
|
+
end
|
12
|
+
|
13
|
+
self.ok_states = [:ok, :info]
|
14
|
+
|
15
|
+
attr_reader :message
|
16
|
+
attr_reader :state
|
17
|
+
|
18
|
+
|
19
|
+
def initialize(message, state)
|
20
|
+
@message = message
|
21
|
+
@state = state
|
22
|
+
end
|
23
|
+
|
24
|
+
def ok?
|
25
|
+
self.class.ok_states.include? state
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# The name of the status check for display purposes.
|
30
|
+
attr_reader :name
|
31
|
+
|
32
|
+
# The messages set on the status check.
|
33
|
+
attr_reader :messages
|
34
|
+
|
35
|
+
# The amount of time it takes to complete the status check.
|
36
|
+
attr_accessor :time
|
37
|
+
|
38
|
+
def initialize(name)
|
39
|
+
@name = name
|
40
|
+
@messages = []
|
41
|
+
end
|
42
|
+
|
43
|
+
# Add a message indicating that the check passed.
|
44
|
+
def ok(message)
|
45
|
+
@messages << Message.new(message, :ok)
|
46
|
+
end
|
47
|
+
|
48
|
+
def info(message)
|
49
|
+
@messages << Message.new(message, :info)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Add a message indicating that the check failed.
|
53
|
+
def fail(message)
|
54
|
+
@messages << Message.new(message, :fail)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns +true+ only if all checks were OK.
|
58
|
+
def success?
|
59
|
+
@messages.all?{|m| m.ok?}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
module IsItWorking
|
5
|
+
autoload :Check, File.expand_path("../is_it_working/check.rb", __FILE__)
|
6
|
+
autoload :Filter, File.expand_path("../is_it_working/filter.rb", __FILE__)
|
7
|
+
autoload :Handler, File.expand_path("../is_it_working/handler.rb", __FILE__)
|
8
|
+
autoload :Status, File.expand_path("../is_it_working/status.rb", __FILE__)
|
9
|
+
|
10
|
+
# Predefined checks
|
11
|
+
autoload :ActionMailerCheck, File.expand_path("../is_it_working/checks/action_mailer_check.rb", __FILE__)
|
12
|
+
autoload :ActiveRecordCheck, File.expand_path("../is_it_working/checks/active_record_check.rb", __FILE__)
|
13
|
+
autoload :DalliCheck, File.expand_path("../is_it_working/checks/dalli_check.rb", __FILE__)
|
14
|
+
autoload :DirectoryCheck, File.expand_path("../is_it_working/checks/directory_check.rb", __FILE__)
|
15
|
+
autoload :MemcacheCheck, File.expand_path("../is_it_working/checks/memcache_check.rb", __FILE__)
|
16
|
+
autoload :PingCheck, File.expand_path("../is_it_working/checks/ping_check.rb", __FILE__)
|
17
|
+
autoload :UrlCheck, File.expand_path("../is_it_working/checks/url_check.rb", __FILE__)
|
18
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe IsItWorking::ActionMailerCheck do
|
4
|
+
|
5
|
+
let(:status){ IsItWorking::Status.new(:ping) }
|
6
|
+
|
7
|
+
it "should succeed if the default mail host is accepting connections" do
|
8
|
+
ActionMailer::Base.smtp_settings[:address] = 'localhost'
|
9
|
+
ActionMailer::Base.smtp_settings[:port] = 25
|
10
|
+
TCPSocket.should_receive(:new).with('localhost', 25).and_return(mock(:socket, :close => true))
|
11
|
+
check = IsItWorking::ActionMailerCheck.new
|
12
|
+
check.call(status)
|
13
|
+
status.should be_success
|
14
|
+
status.messages.first.message.should == "ActionMailer::Base is accepting connections on port 25"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should succeed if the default mail host is not accepting connections" do
|
18
|
+
ActionMailer::Base.smtp_settings[:address] = 'localhost'
|
19
|
+
ActionMailer::Base.smtp_settings[:port] = 25
|
20
|
+
TCPSocket.should_receive(:new).with('localhost', 25).and_raise(Errno::ECONNREFUSED)
|
21
|
+
check = IsItWorking::ActionMailerCheck.new
|
22
|
+
check.call(status)
|
23
|
+
status.should_not be_success
|
24
|
+
status.messages.first.message.should == "ActionMailer::Base is not accepting connections on port 25"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should get the smtp configuration from a specified ActionMailer class" do
|
28
|
+
class IsItWorking::ActionMailerCheck::Tester < ActionMailer::Base
|
29
|
+
end
|
30
|
+
|
31
|
+
IsItWorking::ActionMailerCheck::Tester.smtp_settings[:address] = 'mail.example.com'
|
32
|
+
IsItWorking::ActionMailerCheck::Tester.smtp_settings[:port] = 'smtp'
|
33
|
+
TCPSocket.should_receive(:new).with('mail.example.com', 'smtp').and_return(mock(:socket, :close => true))
|
34
|
+
check = IsItWorking::ActionMailerCheck.new(:class => IsItWorking::ActionMailerCheck::Tester)
|
35
|
+
check.call(status)
|
36
|
+
status.should be_success
|
37
|
+
status.messages.first.message.should == "IsItWorking::ActionMailerCheck::Tester is accepting connections on port \"smtp\""
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should allow aliasing the ActionMailer host alias" do
|
41
|
+
ActionMailer::Base.smtp_settings[:address] = 'localhost'
|
42
|
+
ActionMailer::Base.smtp_settings[:port] = 25
|
43
|
+
TCPSocket.should_receive(:new).with('localhost', 25).and_return(mock(:socket, :close => true))
|
44
|
+
check = IsItWorking::ActionMailerCheck.new(:alias => "smtp host")
|
45
|
+
check.call(status)
|
46
|
+
status.should be_success
|
47
|
+
status.messages.first.message.should == "smtp host is accepting connections on port 25"
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe IsItWorking::ActiveRecordCheck do
|
4
|
+
|
5
|
+
let(:status){ IsItWorking::Status.new(:active_record) }
|
6
|
+
|
7
|
+
class IsItWorking::TestActiveRecord < ActiveRecord::Base
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should succeed if the ActiveRecord connection is active" do
|
11
|
+
connection = ActiveRecord::ConnectionAdapters::AbstractAdapter.new(mock(:connection))
|
12
|
+
connection.reconnect!
|
13
|
+
ActiveRecord::Base.stub!(:connection).and_return(connection)
|
14
|
+
check = IsItWorking::ActiveRecordCheck.new
|
15
|
+
check.call(status)
|
16
|
+
status.should be_success
|
17
|
+
status.messages.first.message.should == "ActiveRecord::Base.connection is active"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should allow specifying the class to check the connection for" do
|
21
|
+
connection = ActiveRecord::ConnectionAdapters::AbstractAdapter.new(mock(:connection))
|
22
|
+
connection.reconnect!
|
23
|
+
IsItWorking::TestActiveRecord.stub!(:connection).and_return(connection)
|
24
|
+
check = IsItWorking::ActiveRecordCheck.new(:class => IsItWorking::TestActiveRecord)
|
25
|
+
check.call(status)
|
26
|
+
status.should be_success
|
27
|
+
status.messages.first.message.should == "IsItWorking::TestActiveRecord.connection is active"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should succeed if the ActiveRecord connection can be reconnected" do
|
31
|
+
connection = ActiveRecord::ConnectionAdapters::AbstractAdapter.new(mock(:connection))
|
32
|
+
connection.disconnect!
|
33
|
+
ActiveRecord::Base.stub!(:connection).and_return(connection)
|
34
|
+
check = IsItWorking::ActiveRecordCheck.new
|
35
|
+
check.call(status)
|
36
|
+
status.should be_success
|
37
|
+
status.messages.first.message.should == "ActiveRecord::Base.connection is active"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should fail if the ActiveRecord connection is not active" do
|
41
|
+
connection = ActiveRecord::ConnectionAdapters::AbstractAdapter.new(mock(:connection))
|
42
|
+
connection.disconnect!
|
43
|
+
connection.stub!(:verify!)
|
44
|
+
ActiveRecord::Base.stub!(:connection).and_return(connection)
|
45
|
+
check = IsItWorking::ActiveRecordCheck.new
|
46
|
+
check.call(status)
|
47
|
+
status.should_not be_success
|
48
|
+
status.messages.first.message.should == "ActiveRecord::Base.connection is not active"
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe IsItWorking::DalliCheck do
|
4
|
+
|
5
|
+
let(:status){ IsItWorking::Status.new(:memcache) }
|
6
|
+
let(:memcache){ Dalli::Client.new(['cache-1.example.com', 'cache-2.example.com']) }
|
7
|
+
let(:servers){ memcache.send(:ring).servers }
|
8
|
+
|
9
|
+
it "should succeed if all servers are responding" do
|
10
|
+
check = IsItWorking::DalliCheck.new(:cache => memcache)
|
11
|
+
servers.first.should_receive(:alive?).and_return(true)
|
12
|
+
servers.last.should_receive(:alive?).and_return(true)
|
13
|
+
check.call(status)
|
14
|
+
status.should be_success
|
15
|
+
status.messages.first.message.should == "cache-1.example.com:11211 is available"
|
16
|
+
status.messages.last.message.should == "cache-2.example.com:11211 is available"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should fail if any server is not responding" do
|
20
|
+
check = IsItWorking::DalliCheck.new(:cache => memcache)
|
21
|
+
servers.first.should_receive(:alive?).and_return(true)
|
22
|
+
servers.last.should_receive(:alive?).and_return(false)
|
23
|
+
check.call(status)
|
24
|
+
status.should_not be_success
|
25
|
+
status.messages.first.message.should == "cache-1.example.com:11211 is available"
|
26
|
+
status.messages.last.message.should == "cache-2.example.com:11211 is not available"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should be able to get the MemCache object from an ActiveSupport::Cache" do
|
30
|
+
require 'active_support/cache'
|
31
|
+
require 'active_support/cache/dalli_store'
|
32
|
+
ActiveSupport::Cache::DalliStore.should_receive(:new).with('cache-1.example.com', 'cache-2.example.com').and_return(memcache)
|
33
|
+
rails_cache = ActiveSupport::Cache::DalliStore.new('cache-1.example.com', 'cache-2.example.com')
|
34
|
+
check = IsItWorking::DalliCheck.new(:cache => rails_cache)
|
35
|
+
servers.first.should_receive(:alive?).and_return(true)
|
36
|
+
servers.last.should_receive(:alive?).and_return(true)
|
37
|
+
check.call(status)
|
38
|
+
status.should be_success
|
39
|
+
status.messages.first.message.should == "cache-1.example.com:11211 is available"
|
40
|
+
status.messages.last.message.should == "cache-2.example.com:11211 is available"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should be able to alias the memcache host names in the output" do
|
44
|
+
check = IsItWorking::DalliCheck.new(:cache => memcache, :alias => "memcache")
|
45
|
+
servers.first.should_receive(:alive?).and_return(true)
|
46
|
+
servers.last.should_receive(:alive?).and_return(true)
|
47
|
+
check.call(status)
|
48
|
+
status.should be_success
|
49
|
+
status.messages.first.message.should == "memcache 1 is available"
|
50
|
+
status.messages.last.message.should == "memcache 2 is available"
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe IsItWorking::DirectoryCheck do
|
4
|
+
|
5
|
+
let(:status){ IsItWorking::Status.new(:directory) }
|
6
|
+
let(:directory_path){ File.expand_path(".") }
|
7
|
+
|
8
|
+
it "should fail if a directory can't be found" do
|
9
|
+
check = IsItWorking::DirectoryCheck.new(:path => File.expand_path("../no_such_thing", __FILE__))
|
10
|
+
check.call(status)
|
11
|
+
status.should_not be_success
|
12
|
+
status.messages.first.message.should include("does not exist")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should fail if a path isn't a directory" do
|
16
|
+
check = IsItWorking::DirectoryCheck.new(:path => __FILE__)
|
17
|
+
check.call(status)
|
18
|
+
status.should_not be_success
|
19
|
+
status.messages.first.message.should include("is not a directory")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should succeed if a directory exists" do
|
23
|
+
check = IsItWorking::DirectoryCheck.new(:path => directory_path)
|
24
|
+
File.should_receive(:stat).with(directory_path).and_return(mock(:stat, :directory? => true, :readable? => false, :writable? => false))
|
25
|
+
check.call(status)
|
26
|
+
status.should be_success
|
27
|
+
status.messages.first.message.should include("exists")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should fail if a directory is not readable" do
|
31
|
+
check = IsItWorking::DirectoryCheck.new(:path => directory_path, :permission => :read)
|
32
|
+
File.should_receive(:stat).with(directory_path).and_return(mock(:stat, :directory? => true, :readable? => false, :writable? => true))
|
33
|
+
check.call(status)
|
34
|
+
status.should_not be_success
|
35
|
+
status.messages.first.message.should include("is not readable")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should fail if a directory is not writable" do
|
39
|
+
check = IsItWorking::DirectoryCheck.new(:path => directory_path, :permission => :write)
|
40
|
+
File.should_receive(:stat).with(directory_path).and_return(mock(:stat, :directory? => true, :readable? => true, :writable? => false))
|
41
|
+
check.call(status)
|
42
|
+
status.should_not be_success
|
43
|
+
status.messages.first.message.should include("is not writable")
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should succeed if a directory exists and is readable" do
|
47
|
+
check = IsItWorking::DirectoryCheck.new(:path => directory_path, :permission => :read)
|
48
|
+
File.should_receive(:stat).with(directory_path).and_return(mock(:stat, :directory? => true, :readable? => true, :writable? => false))
|
49
|
+
check.call(status)
|
50
|
+
status.should be_success
|
51
|
+
status.messages.first.message.should include("exists with")
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should succeed if a directory exists and is writable" do
|
55
|
+
check = IsItWorking::DirectoryCheck.new(:path => directory_path, :permission => :write)
|
56
|
+
File.should_receive(:stat).with(directory_path).and_return(mock(:stat, :directory? => true, :readable? => false, :writable? => true))
|
57
|
+
check.call(status)
|
58
|
+
status.should be_success
|
59
|
+
status.messages.first.message.should include("exists with")
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should succeed if a directory exists and is readable and writable" do
|
63
|
+
check = IsItWorking::DirectoryCheck.new(:path => directory_path, :permission => [:read, :write])
|
64
|
+
File.should_receive(:stat).with(directory_path).and_return(mock(:stat, :directory? => true, :readable? => true, :writable? => true))
|
65
|
+
check.call(status)
|
66
|
+
status.should be_success
|
67
|
+
status.messages.first.message.should include("exists with")
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
data/spec/filter_spec.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe IsItWorking::Filter do
|
4
|
+
|
5
|
+
it "should have a name" do
|
6
|
+
filter = IsItWorking::Filter.new(:test, lambda{})
|
7
|
+
filter.name.should == :test
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should run a check and return a thread" do
|
11
|
+
check = lambda do |status|
|
12
|
+
status.ok("success")
|
13
|
+
end
|
14
|
+
|
15
|
+
filter = IsItWorking::Filter.new(:test, check)
|
16
|
+
runner = filter.run
|
17
|
+
status = runner.filter_status
|
18
|
+
runner.join
|
19
|
+
status.should be_success
|
20
|
+
status.messages.first.message.should == "success"
|
21
|
+
status.time.should_not be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should run a check and recue an errors" do
|
25
|
+
check = lambda do |status|
|
26
|
+
raise "boom!"
|
27
|
+
end
|
28
|
+
|
29
|
+
filter = IsItWorking::Filter.new(:test, check)
|
30
|
+
runner = filter.run
|
31
|
+
status = runner.filter_status
|
32
|
+
runner.join
|
33
|
+
status.should_not be_success
|
34
|
+
status.messages.first.message.should include("boom")
|
35
|
+
status.time.should_not be_nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should run multiple filters and return their statuses" do
|
39
|
+
filter_1 = IsItWorking::Filter.new(:test, lambda{|status| status.ok("OK")})
|
40
|
+
filter_2 = IsItWorking::Filter.new(:test, lambda{|status| status.fail("FAIL")})
|
41
|
+
statuses = IsItWorking::Filter.run_filters([filter_1, filter_2])
|
42
|
+
statuses.first.should be_success
|
43
|
+
statuses.last.should_not be_success
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe IsItWorking::Handler do
|
4
|
+
|
5
|
+
it "should lookup filters from the pre-defined checks" do
|
6
|
+
handler = IsItWorking::Handler.new do |h|
|
7
|
+
h.check :directory, :path => ".", :permissions => :read
|
8
|
+
end
|
9
|
+
response = handler.call({})
|
10
|
+
response.first.should == 200
|
11
|
+
response.last.flatten.join("").should include("OK")
|
12
|
+
response.last.flatten.join("").should include("directory")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should use blocks as filters" do
|
16
|
+
handler = IsItWorking::Handler.new do |h|
|
17
|
+
h.check :block do |status|
|
18
|
+
status.ok("Okey dokey")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
response = handler.call({})
|
22
|
+
response.first.should == 200
|
23
|
+
response.last.flatten.join("").should include("OK")
|
24
|
+
response.last.flatten.join("").should include("block - Okey dokey")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should use object as filters" do
|
28
|
+
handler = IsItWorking::Handler.new do |h|
|
29
|
+
h.check :lambda, lambda{|status| status.ok("A-okay")}
|
30
|
+
end
|
31
|
+
response = handler.call({})
|
32
|
+
response.first.should == 200
|
33
|
+
response.last.flatten.join("").should include("OK")
|
34
|
+
response.last.flatten.join("").should include("lambda - A-okay")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should create asynchronous filters by default" do
|
38
|
+
handler = IsItWorking::Handler.new do |h|
|
39
|
+
h.check :block do |status|
|
40
|
+
status.ok("Okey dokey")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
runner = IsItWorking::Filter::AsyncRunner.new{}
|
44
|
+
IsItWorking::Filter::AsyncRunner.should_receive(:new).and_return(runner)
|
45
|
+
response = handler.call({})
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should be able to create synchronous filters" do
|
49
|
+
handler = IsItWorking::Handler.new do |h|
|
50
|
+
h.check :block, :async => false do |status|
|
51
|
+
status.ok("Okey dokey")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
runner = IsItWorking::Filter::SyncRunner.new{}
|
55
|
+
IsItWorking::Filter::SyncRunner.should_receive(:new).and_return(runner)
|
56
|
+
response = handler.call({})
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should work with synchronous checks" do
|
60
|
+
handler = IsItWorking::Handler.new do |h|
|
61
|
+
h.check :block, :async => false do |status|
|
62
|
+
status.ok("Okey dokey")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
response = handler.call({})
|
66
|
+
response.first.should == 200
|
67
|
+
response.last.flatten.join("").should include("OK")
|
68
|
+
response.last.flatten.join("").should include("block - Okey dokey")
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should return a success response if all checks pass" do
|
72
|
+
handler = IsItWorking::Handler.new do |h|
|
73
|
+
h.check :block do |status|
|
74
|
+
status.ok("success")
|
75
|
+
end
|
76
|
+
h.check :block do |status|
|
77
|
+
status.ok("worked")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
response = handler.call({})
|
81
|
+
response.first.should == 200
|
82
|
+
response.last.flatten.join("").should include("block - success")
|
83
|
+
response.last.flatten.join("").should include("block - worked")
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should return an error response if any check fails" do
|
87
|
+
handler = IsItWorking::Handler.new do |h|
|
88
|
+
h.check :block do |status|
|
89
|
+
status.ok("success")
|
90
|
+
end
|
91
|
+
h.check :block do |status|
|
92
|
+
status.fail("down")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
response = handler.call({})
|
96
|
+
response.first.should == 500
|
97
|
+
response.last.flatten.join("").should include("block - success")
|
98
|
+
response.last.flatten.join("").should include("block - down")
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should be able to be used in a middleware stack with the route /is_it_working" do
|
102
|
+
app_response = [200, {"Content-Type" => "text/plain"}, ["OK"]]
|
103
|
+
app = lambda{|env| app_response}
|
104
|
+
check_called = false
|
105
|
+
stack = IsItWorking::Handler.new(app) do |h|
|
106
|
+
h.check(:test){|status| check_called = true; status.ok("Woot!")}
|
107
|
+
end
|
108
|
+
|
109
|
+
stack.call("PATH_INFO" => "/").should == app_response
|
110
|
+
check_called.should == false
|
111
|
+
stack.call("PATH_INFO" => "/is_it_working").last.flatten.join("").should include("Woot!")
|
112
|
+
check_called.should == true
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should be able to be used in a middleware stack with a custom route" do
|
116
|
+
app_response = [200, {"Content-Type" => "text/plain"}, ["OK"]]
|
117
|
+
app = lambda{|env| app_response}
|
118
|
+
check_called = false
|
119
|
+
stack = IsItWorking::Handler.new(app, "/woot") do |h|
|
120
|
+
h.check(:test){|status| check_called = true; status.ok("Woot!")}
|
121
|
+
end
|
122
|
+
|
123
|
+
stack.call("PATH_INFO" => "/is_it_working").should == app_response
|
124
|
+
check_called.should == false
|
125
|
+
stack.call("PATH_INFO" => "/woot").last.flatten.join("").should include("Woot!")
|
126
|
+
check_called.should == true
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should be able to synchronize access to a block" do
|
130
|
+
handler = IsItWorking::Handler.new
|
131
|
+
handler.synchronize{1}.should == 1
|
132
|
+
handler.synchronize{2}.should == 2
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should be able to set the host name reported in the output" do
|
136
|
+
handler = IsItWorking::Handler.new
|
137
|
+
handler.hostname = "woot"
|
138
|
+
handler.call("PATH_INFO" => "/is_it_working").last.join("").should include("woot")
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe IsItWorking::MemcacheCheck do
|
4
|
+
|
5
|
+
let(:status){ IsItWorking::Status.new(:memcache) }
|
6
|
+
let(:memcache){ MemCache.new(['cache-1.example.com', 'cache-2.example.com']) }
|
7
|
+
let(:servers){ memcache.servers }
|
8
|
+
|
9
|
+
it "should succeed if all servers are responding" do
|
10
|
+
check = IsItWorking::MemcacheCheck.new(:cache => memcache)
|
11
|
+
servers.first.should_receive(:socket).and_return(mock(:socket))
|
12
|
+
servers.last.should_receive(:socket).and_return(mock(:socket))
|
13
|
+
check.call(status)
|
14
|
+
status.should be_success
|
15
|
+
status.messages.first.message.should == "cache-1.example.com:11211 is available"
|
16
|
+
status.messages.last.message.should == "cache-2.example.com:11211 is available"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should fail if any server is not responding" do
|
20
|
+
check = IsItWorking::MemcacheCheck.new(:cache => memcache)
|
21
|
+
servers.first.should_receive(:socket).and_return(mock(:socket))
|
22
|
+
servers.last.should_receive(:socket).and_return(nil)
|
23
|
+
check.call(status)
|
24
|
+
status.should_not be_success
|
25
|
+
status.messages.first.message.should == "cache-1.example.com:11211 is available"
|
26
|
+
status.messages.last.message.should == "cache-2.example.com:11211 is not available"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should be able to get the MemCache object from an ActiveSupport::Cache" do
|
30
|
+
require 'active_support/cache'
|
31
|
+
rails_cache = ActiveSupport::Cache::MemCacheStore.new(memcache)
|
32
|
+
check = IsItWorking::MemcacheCheck.new(:cache => rails_cache)
|
33
|
+
servers.first.should_receive(:socket).and_return(mock(:socket))
|
34
|
+
servers.last.should_receive(:socket).and_return(mock(:socket))
|
35
|
+
check.call(status)
|
36
|
+
status.should be_success
|
37
|
+
status.messages.first.message.should == "cache-1.example.com:11211 is available"
|
38
|
+
status.messages.last.message.should == "cache-2.example.com:11211 is available"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be able to alias the memcache host names in the output" do
|
42
|
+
check = IsItWorking::MemcacheCheck.new(:cache => memcache, :alias => "memcache")
|
43
|
+
servers.first.should_receive(:socket).and_return(mock(:socket))
|
44
|
+
servers.last.should_receive(:socket).and_return(mock(:socket))
|
45
|
+
check.call(status)
|
46
|
+
status.should be_success
|
47
|
+
status.messages.first.message.should == "memcache 1 is available"
|
48
|
+
status.messages.last.message.should == "memcache 2 is available"
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe IsItWorking::PingCheck do
|
4
|
+
|
5
|
+
let(:status){ IsItWorking::Status.new(:ping) }
|
6
|
+
|
7
|
+
it "should succeed if the host is accepting connections on the specified port" do
|
8
|
+
server = TCPServer.new(51123)
|
9
|
+
begin
|
10
|
+
check = IsItWorking::PingCheck.new(:host => "localhost", :port => 51123)
|
11
|
+
check.call(status)
|
12
|
+
status.should be_success
|
13
|
+
status.messages.first.message.should == "localhost is accepting connections on port 51123"
|
14
|
+
ensure
|
15
|
+
server.close
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should fail if the host is not accepting connections on the specified port" do
|
20
|
+
check = IsItWorking::PingCheck.new(:host => "localhost", :port => 51123)
|
21
|
+
check.call(status)
|
22
|
+
status.should_not be_success
|
23
|
+
status.messages.first.message.should == "localhost is not accepting connections on port 51123"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should fail if the host cannot be found" do
|
27
|
+
check = IsItWorking::PingCheck.new(:host => "127.0.0.256", :port => 51123)
|
28
|
+
check.call(status)
|
29
|
+
status.should_not be_success
|
30
|
+
status.messages.first.message.should include("failed")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should fail if the server takes too long to respond" do
|
34
|
+
check = IsItWorking::PingCheck.new(:host => "127.0.0.255", :port => 51123, :timeout => 0.01)
|
35
|
+
check.call(status)
|
36
|
+
status.should_not be_success
|
37
|
+
status.messages.first.message.should == "127.0.0.255 did not respond on port 51123 within 0.01 seconds"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should be able to alias the host name in the output" do
|
41
|
+
check = IsItWorking::PingCheck.new(:host => "localhost", :port => 51123, :alias => "secret server")
|
42
|
+
check.call(status)
|
43
|
+
status.should_not be_success
|
44
|
+
status.messages.first.message.should == "secret server is not accepting connections on port 51123"
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/status_spec.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe IsItWorking::Status do
|
4
|
+
|
5
|
+
let(:status){ IsItWorking::Status.new(:test) }
|
6
|
+
|
7
|
+
it "should have a name" do
|
8
|
+
status.name.should == :test
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have errors" do
|
12
|
+
status.fail("boom")
|
13
|
+
status.should_not be_success
|
14
|
+
status.messages.size.should == 1
|
15
|
+
status.messages.first.should_not be_ok
|
16
|
+
status.messages.first.state.should == :fail
|
17
|
+
status.messages.first.message.should == "boom"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should have successes" do
|
21
|
+
status.ok("wow")
|
22
|
+
status.should be_success
|
23
|
+
status.messages.first.state.should == :ok
|
24
|
+
status.messages.size.should == 1
|
25
|
+
status.messages.first.should be_ok
|
26
|
+
status.messages.first.message.should == "wow"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should have successes and infos" do
|
30
|
+
status.ok("wow")
|
31
|
+
status.info("fyi")
|
32
|
+
status.should be_success
|
33
|
+
status.messages.each { |x| x.should be_ok }
|
34
|
+
status.messages.last.state.should == :info
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should have both errors and successes" do
|
38
|
+
status.fail("boom")
|
39
|
+
status.ok("wow")
|
40
|
+
status.should_not be_success
|
41
|
+
status.messages.size.should == 2
|
42
|
+
status.messages.first.should_not be_ok
|
43
|
+
status.messages.first.message.should == "boom"
|
44
|
+
status.messages.last.should be_ok
|
45
|
+
status.messages.last.message.should == "wow"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should have a time" do
|
49
|
+
status.time.should == nil
|
50
|
+
status.time = 0.1
|
51
|
+
status.time.should == 0.1
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|