pinglish 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +3 -0
- data/README.md +0 -3
- data/lib/pinglish.rb +3 -8
- data/pinglish.gemspec +2 -1
- data/script/tests +1 -1
- data/test/check_test.rb +23 -0
- data/test/helper.rb +2 -0
- data/test/pinglish_test.rb +173 -3
- metadata +22 -2
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -22,9 +22,6 @@ conforms to the spec below.
|
|
22
22
|
0. The response __must__ return an `HTTP 503 SERVICE UNAVAILABLE`
|
23
23
|
status code if any health checks fail.
|
24
24
|
|
25
|
-
0. The response __must__ return an `HTTP 418 I'M A TEAPOT` status code
|
26
|
-
if the request asks for any content-type but `application/json`.
|
27
|
-
|
28
25
|
0. The response __must__ be of Content-Type `application/json;
|
29
26
|
charset=UTF-8`.
|
30
27
|
|
data/lib/pinglish.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "json"
|
2
2
|
require "timeout"
|
3
|
+
require "rack/request"
|
3
4
|
|
4
5
|
# This Rack middleware provides a "/_ping" endpoint for configurable
|
5
6
|
# system health checks. It's intended to be consumed by machines.
|
@@ -17,11 +18,6 @@ class Pinglish
|
|
17
18
|
|
18
19
|
MAX_TOTAL_TIME = 29
|
19
20
|
|
20
|
-
# This triple is returned if the request media type isn't
|
21
|
-
# "application/json".
|
22
|
-
|
23
|
-
TEAPOT = [418, HEADERS, ['{"teapot":"true"}']]
|
24
|
-
|
25
21
|
# Represents a check, which is a behavior block with a name and
|
26
22
|
# timeout in seconds.
|
27
23
|
|
@@ -64,7 +60,6 @@ class Pinglish
|
|
64
60
|
request = Rack::Request.new env
|
65
61
|
|
66
62
|
return @app.call env unless request.path == @path
|
67
|
-
return TEAPOT unless request.media_type == "application/json"
|
68
63
|
|
69
64
|
timeout MAX_TOTAL_TIME do
|
70
65
|
results = {}
|
@@ -135,11 +130,11 @@ class Pinglish
|
|
135
130
|
end
|
136
131
|
|
137
132
|
# Does `value` represent a check failure? This default
|
138
|
-
# implementation returns `true` for any value that is an Exception.
|
133
|
+
# implementation returns `true` for any value that is an Exception or false.
|
139
134
|
# Subclasses can override this method for different behavior.
|
140
135
|
|
141
136
|
def failure?(value)
|
142
|
-
value.is_a?
|
137
|
+
value.is_a?(Exception) || value == false
|
143
138
|
end
|
144
139
|
|
145
140
|
# Raise Pinglish::TooLong after `seconds` has elapsed. This default
|
data/pinglish.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
4
|
gem.name = "pinglish"
|
5
|
-
gem.version = "0.0.
|
5
|
+
gem.version = "0.0.1"
|
6
6
|
gem.authors = ["John Barnette", "Will Farrington"]
|
7
7
|
gem.email = ["jbarnette@github.com", "wfarr@github.com"]
|
8
8
|
gem.description = "A simple Rack middleware for checking app health."
|
@@ -15,4 +15,5 @@ Gem::Specification.new do |gem|
|
|
15
15
|
|
16
16
|
gem.add_dependency "rack"
|
17
17
|
gem.add_development_dependency "minitest", "~> 4.5"
|
18
|
+
gem.add_development_dependency "rack-test", "~> 0.6"
|
18
19
|
end
|
data/script/tests
CHANGED
data/test/check_test.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class PinglishCheckTest < MiniTest::Unit::TestCase
|
4
|
+
def test_initialize
|
5
|
+
check = Pinglish::Check.new(:db)
|
6
|
+
assert_equal :db, check.name
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_initialize_default_timeout
|
10
|
+
check = Pinglish::Check.new(:db)
|
11
|
+
assert_equal 1, check.timeout
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_initialize_override_timeout
|
15
|
+
check = Pinglish::Check.new(:db, :timeout => 2)
|
16
|
+
assert_equal 2, check.timeout
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_call
|
20
|
+
check = Pinglish::Check.new(:db) { :result_of_block }
|
21
|
+
assert_equal :result_of_block, check.call
|
22
|
+
end
|
23
|
+
end
|
data/test/helper.rb
ADDED
data/test/pinglish_test.rb
CHANGED
@@ -1,7 +1,177 @@
|
|
1
|
-
require "
|
1
|
+
require "helper"
|
2
|
+
require "rack/test"
|
2
3
|
|
3
4
|
class PinglishTest < MiniTest::Unit::TestCase
|
4
|
-
|
5
|
-
|
5
|
+
FakeApp = lambda { |env| [404, {}, []] }
|
6
|
+
|
7
|
+
def build_app(*args, &block)
|
8
|
+
Rack::Builder.new do |builder|
|
9
|
+
builder.use Pinglish, *args, &block
|
10
|
+
builder.run FakeApp
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_with_defaults
|
15
|
+
app = build_app
|
16
|
+
|
17
|
+
session = Rack::Test::Session.new(app)
|
18
|
+
session.get '/_ping'
|
19
|
+
assert_equal 200, session.last_response.status
|
20
|
+
assert_equal 'application/json; charset=UTF-8',
|
21
|
+
session.last_response.content_type
|
22
|
+
|
23
|
+
json = JSON.load(session.last_response.body)
|
24
|
+
assert json.key?('now')
|
25
|
+
assert_equal 'ok', json['status']
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_with_good_check
|
29
|
+
app = build_app do |ping|
|
30
|
+
ping.check(:db) { :up_and_at_em }
|
31
|
+
ping.check(:queue) { :pushin_and_poppin }
|
32
|
+
end
|
33
|
+
|
34
|
+
session = Rack::Test::Session.new(app)
|
35
|
+
session.get '/_ping'
|
36
|
+
|
37
|
+
assert_equal 'application/json; charset=UTF-8',
|
38
|
+
session.last_response.content_type
|
39
|
+
|
40
|
+
json = JSON.load(session.last_response.body)
|
41
|
+
assert json.key?('now')
|
42
|
+
assert_equal 'ok', json['status']
|
43
|
+
assert_equal 'up_and_at_em', json['db']
|
44
|
+
assert_equal 'pushin_and_poppin', json['queue']
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_with_unnamed_check
|
48
|
+
app = build_app do |ping|
|
49
|
+
ping.check { :yohoho }
|
50
|
+
end
|
51
|
+
|
52
|
+
session = Rack::Test::Session.new(app)
|
53
|
+
session.get '/_ping'
|
54
|
+
|
55
|
+
assert_equal 'application/json; charset=UTF-8',
|
56
|
+
session.last_response.content_type
|
57
|
+
|
58
|
+
json = JSON.load(session.last_response.body)
|
59
|
+
assert json.key?('now')
|
60
|
+
assert_equal 'ok', json['status']
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_with_check_that_raises
|
64
|
+
app = build_app do |ping|
|
65
|
+
ping.check(:db) { :ok }
|
66
|
+
ping.check(:raise) { raise 'nooooope' }
|
67
|
+
end
|
68
|
+
|
69
|
+
session = Rack::Test::Session.new(app)
|
70
|
+
session.get '/_ping'
|
71
|
+
|
72
|
+
assert_equal 503, session.last_response.status
|
73
|
+
assert_equal 'application/json; charset=UTF-8',
|
74
|
+
session.last_response.content_type
|
75
|
+
|
76
|
+
json = JSON.load(session.last_response.body)
|
77
|
+
assert json.key?('now')
|
78
|
+
assert_equal 'fail', json['status']
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_with_check_that_returns_false
|
82
|
+
app = build_app do |ping|
|
83
|
+
ping.check(:db) { :ok }
|
84
|
+
ping.check(:fail) { false }
|
85
|
+
end
|
86
|
+
|
87
|
+
session = Rack::Test::Session.new(app)
|
88
|
+
session.get '/_ping'
|
89
|
+
|
90
|
+
assert_equal 503, session.last_response.status
|
91
|
+
assert_equal 'application/json; charset=UTF-8',
|
92
|
+
session.last_response.content_type
|
93
|
+
|
94
|
+
json = JSON.load(session.last_response.body)
|
95
|
+
assert json.key?('now')
|
96
|
+
assert_equal 'fail', json['status']
|
97
|
+
assert_equal ['fail'], json['failures']
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_with_check_that_times_out
|
101
|
+
app = build_app do |ping|
|
102
|
+
ping.check(:db) { :ok }
|
103
|
+
ping.check(:long, :timeout => 0.001) { sleep 0.003 }
|
104
|
+
end
|
105
|
+
|
106
|
+
session = Rack::Test::Session.new(app)
|
107
|
+
session.get '/_ping'
|
108
|
+
|
109
|
+
assert_equal 503, session.last_response.status
|
110
|
+
assert_equal 'application/json; charset=UTF-8',
|
111
|
+
session.last_response.content_type
|
112
|
+
|
113
|
+
json = JSON.load(session.last_response.body)
|
114
|
+
assert json.key?('now')
|
115
|
+
assert_equal 'fail', json['status']
|
116
|
+
assert_equal ['long'], json['timeouts']
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_with_custom_path
|
120
|
+
app = build_app("/_piiiiing")
|
121
|
+
|
122
|
+
session = Rack::Test::Session.new(app)
|
123
|
+
session.get '/_piiiiing'
|
124
|
+
assert_equal 200, session.last_response.status
|
125
|
+
assert_equal 'application/json; charset=UTF-8',
|
126
|
+
session.last_response.content_type
|
127
|
+
|
128
|
+
json = JSON.load(session.last_response.body)
|
129
|
+
assert json.key?('now')
|
130
|
+
assert_equal 'ok', json['status']
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_check_without_name
|
134
|
+
pinglish = Pinglish.new(FakeApp)
|
135
|
+
check = pinglish.check { :ok }
|
136
|
+
assert_instance_of Pinglish::Check, check
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_check_with_name
|
140
|
+
pinglish = Pinglish.new(FakeApp)
|
141
|
+
check = pinglish.check(:db) { :ok }
|
142
|
+
assert_instance_of Pinglish::Check, check
|
143
|
+
assert_equal :db, check.name
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_failure_boolean
|
147
|
+
pinglish = Pinglish.new(FakeApp)
|
148
|
+
|
149
|
+
assert pinglish.failure?(Exception.new),
|
150
|
+
"Expected failure with exception to be true"
|
151
|
+
|
152
|
+
assert pinglish.failure?(false),
|
153
|
+
"Expected failure with false to be true"
|
154
|
+
|
155
|
+
assert !pinglish.failure?(true),
|
156
|
+
"Expected failure with true value to be false"
|
157
|
+
|
158
|
+
assert !pinglish.failure?(:ok),
|
159
|
+
"Expected failure with non-false and non-exception to be false"
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_timeout
|
163
|
+
pinglish = Pinglish.new(FakeApp)
|
164
|
+
begin
|
165
|
+
pinglish.timeout(0.001) { sleep 0.003 }
|
166
|
+
assert false, "Timeout did not happen, but should have."
|
167
|
+
rescue Pinglish::TooLong => e
|
168
|
+
# all good
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_timeout_boolean
|
173
|
+
pinglish = Pinglish.new(FakeApp)
|
174
|
+
assert_equal true, pinglish.timeout?(Pinglish::TooLong.new)
|
175
|
+
assert_equal false, pinglish.timeout?(Exception.new)
|
6
176
|
end
|
7
177
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pinglish
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-02-26 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rack
|
@@ -44,6 +44,22 @@ dependencies:
|
|
44
44
|
- - ~>
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '4.5'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rack-test
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.6'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ~>
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0.6'
|
47
63
|
description: A simple Rack middleware for checking app health.
|
48
64
|
email:
|
49
65
|
- jbarnette@github.com
|
@@ -62,6 +78,8 @@ files:
|
|
62
78
|
- script/bootstrap
|
63
79
|
- script/release
|
64
80
|
- script/tests
|
81
|
+
- test/check_test.rb
|
82
|
+
- test/helper.rb
|
65
83
|
- test/pinglish_test.rb
|
66
84
|
homepage: https://github.com/jbarnette/pinglish
|
67
85
|
licenses: []
|
@@ -88,4 +106,6 @@ signing_key:
|
|
88
106
|
specification_version: 3
|
89
107
|
summary: /_ping your way to freedom.
|
90
108
|
test_files:
|
109
|
+
- test/check_test.rb
|
110
|
+
- test/helper.rb
|
91
111
|
- test/pinglish_test.rb
|