rack-ecg 0.0.5 → 0.1.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.
- checksums.yaml +5 -5
- data/.github/workflows/main.yml +22 -0
- data/.rubocop.yml +21 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +69 -0
- data/Gemfile +1 -0
- data/README.md +39 -31
- data/Rakefile +10 -1
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/examples/basic.ru +3 -2
- data/examples/checks.ru +3 -2
- data/examples/hook.ru +17 -0
- data/examples/mounted_path.ru +3 -2
- data/examples/parameters.ru +6 -5
- data/examples/stand_alone.ru +2 -1
- data/lib/rack-ecg.rb +1 -0
- data/lib/rack/ecg.rb +26 -12
- data/lib/rack/ecg/check.rb +23 -3
- data/lib/rack/ecg/check/active_record_connection.rb +4 -0
- data/lib/rack/ecg/check/error.rb +3 -3
- data/lib/rack/ecg/check/git_revision.rb +4 -1
- data/lib/rack/ecg/check/http.rb +3 -3
- data/lib/rack/ecg/check/migration_version.rb +4 -1
- data/lib/rack/ecg/check/redis_connection.rb +6 -0
- data/lib/rack/ecg/check/sequel_connection.rb +9 -2
- data/lib/rack/ecg/check_factory.rb +1 -0
- data/lib/rack/ecg/check_registry.rb +15 -2
- data/lib/rack/ecg/version.rb +3 -1
- data/rack-ecg.gemspec +31 -14
- metadata +79 -36
- data/.travis.yml +0 -28
- data/gemfiles/rack_v1.gemfile +0 -4
- data/spec/check_factory_spec.rb +0 -59
- data/spec/check_registry_spec.rb +0 -23
- data/spec/rack_middleware_spec.rb +0 -246
- data/spec/spec_helper.rb +0 -23
data/.travis.yml
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
sudo: false
|
3
|
-
cache: bundler
|
4
|
-
|
5
|
-
rvm:
|
6
|
-
- 1.9.3
|
7
|
-
- 2.0
|
8
|
-
- 2.1
|
9
|
-
- 2.2.5
|
10
|
-
- 2.3.1
|
11
|
-
- ruby-head
|
12
|
-
- jruby
|
13
|
-
|
14
|
-
gemfile:
|
15
|
-
- Gemfile
|
16
|
-
- gemfiles/rack_v1.gemfile
|
17
|
-
|
18
|
-
matrix:
|
19
|
-
allow_failures:
|
20
|
-
- rvm: ruby-head
|
21
|
-
- rvm: jruby
|
22
|
-
exclude:
|
23
|
-
- rvm: 1.9.3
|
24
|
-
gemfile: Gemfile
|
25
|
-
- rvm: 2.0
|
26
|
-
gemfile: Gemfile
|
27
|
-
- rvm: 2.1
|
28
|
-
gemfile: Gemfile
|
data/gemfiles/rack_v1.gemfile
DELETED
data/spec/check_factory_spec.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
RSpec.describe Rack::ECG::CheckFactory do
|
2
|
-
class MyCheckClass; end
|
3
|
-
class MyOtherCheckClass; def initialize(params); end; end
|
4
|
-
|
5
|
-
let(:definitions) { [] }
|
6
|
-
let(:default_checks) { [] }
|
7
|
-
subject(:check_factory) { Rack::ECG::CheckFactory.new(definitions, default_checks) }
|
8
|
-
|
9
|
-
describe "#build" do
|
10
|
-
context "with a class that does not take params" do
|
11
|
-
let(:check_class) { spy(MyCheckClass) }
|
12
|
-
|
13
|
-
it "builds the specified class" do
|
14
|
-
expect { check_factory.build(check_class) }.not_to raise_error
|
15
|
-
expect(check_class).to have_received(:new).with(no_args)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
context "with a class that does not take params" do
|
20
|
-
let(:check_class) { spy(MyOtherCheckClass) }
|
21
|
-
let(:check_parameters) { double }
|
22
|
-
it "builds the specified class" do
|
23
|
-
expect { check_factory.build(check_class, check_parameters) }.not_to raise_error
|
24
|
-
expect(check_class).to have_received(:new).with(check_parameters)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe "#build_all" do
|
30
|
-
context "with defined checks" do
|
31
|
-
let(:definitions) { [:my_check, [:my_other_check, {foo: 'bar'}]] }
|
32
|
-
let(:check_class) { spy(MyCheckClass) }
|
33
|
-
let(:other_check_class) { spy(MyOtherCheckClass) }
|
34
|
-
before do
|
35
|
-
allow(Rack::ECG::CheckRegistry).to receive(:lookup).with(:my_check).and_return(check_class)
|
36
|
-
allow(Rack::ECG::CheckRegistry).to receive(:lookup).with(:my_other_check).and_return(other_check_class)
|
37
|
-
end
|
38
|
-
|
39
|
-
it "builds all registered checks" do
|
40
|
-
check_factory.build_all
|
41
|
-
expect(check_class).to have_received(:new).with(no_args)
|
42
|
-
expect(other_check_class).to have_received(:new).with(foo: 'bar')
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
context "with defined default checks" do
|
47
|
-
let(:default_checks) { [:http] }
|
48
|
-
let(:http_class) { spy(Rack::ECG::Check::Http) }
|
49
|
-
before do
|
50
|
-
allow(Rack::ECG::CheckRegistry).to receive(:lookup).with(:http).and_return(http_class)
|
51
|
-
end
|
52
|
-
|
53
|
-
it "builds registered default checks" do
|
54
|
-
check_factory.build_all
|
55
|
-
expect(http_class).to have_received(:new).with(no_args)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
data/spec/check_registry_spec.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
|
2
|
-
RSpec.describe Rack::ECG::CheckRegistry do
|
3
|
-
class MyCheckClass; end
|
4
|
-
subject(:check_registry) { described_class }
|
5
|
-
|
6
|
-
before do
|
7
|
-
check_registry.register(:my_check, MyCheckClass)
|
8
|
-
end
|
9
|
-
|
10
|
-
describe ".lookup" do
|
11
|
-
context "with a registered class" do
|
12
|
-
it "returns the registered class" do
|
13
|
-
expect(check_registry.lookup(:my_check)).to eq(MyCheckClass)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
context "when the class is not registered" do
|
18
|
-
it "raises an error" do
|
19
|
-
expect { check_registry.lookup(:my_other_check) }.to raise_error(Rack::ECG::CheckRegistry::CheckNotRegistered)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,246 +0,0 @@
|
|
1
|
-
require "open3"
|
2
|
-
require "stringio"
|
3
|
-
|
4
|
-
RSpec.describe "when used as middleware" do
|
5
|
-
let(:app) {
|
6
|
-
opts = options
|
7
|
-
Rack::Builder.new do
|
8
|
-
use Rack::ECG, opts
|
9
|
-
run lambda {|env|
|
10
|
-
if env["PATH_INFO"] == "/hello/world"
|
11
|
-
[200, {}, ["Hello, World"]]
|
12
|
-
else
|
13
|
-
[404, {}, ["Goodbye, World"]]
|
14
|
-
end
|
15
|
-
}
|
16
|
-
end
|
17
|
-
}
|
18
|
-
let(:options) {
|
19
|
-
{} # empty default
|
20
|
-
}
|
21
|
-
|
22
|
-
context "main app" do
|
23
|
-
it "responds OK for normal requests" do
|
24
|
-
get "/hello/world"
|
25
|
-
expect(last_response).to be_ok
|
26
|
-
end
|
27
|
-
|
28
|
-
it "doesn't include an X-Rack-ECG-Version custom header" do
|
29
|
-
get "/hello/world"
|
30
|
-
expect(last_response.header["X-Rack-ECG-Version"]).to be_nil
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context "ecg app" do
|
35
|
-
it "responds " do
|
36
|
-
get "/_ecg"
|
37
|
-
expect(last_response).to be_ok
|
38
|
-
end
|
39
|
-
|
40
|
-
it "includes an X-Rack-ECG-Version custom header" do
|
41
|
-
get "/_ecg"
|
42
|
-
expect(last_response.header["X-Rack-ECG-Version"]).to eq(Rack::ECG::VERSION)
|
43
|
-
end
|
44
|
-
|
45
|
-
context "when `at` config option is set" do
|
46
|
-
let(:options) {
|
47
|
-
{at: "/health_check"}
|
48
|
-
}
|
49
|
-
|
50
|
-
it "responds from that path" do
|
51
|
-
get "/health_check"
|
52
|
-
expect(last_response.header["X-Rack-ECG-Version"]).to eq(Rack::ECG::VERSION)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context "when all checks pass" do
|
57
|
-
it "has a success error code" do
|
58
|
-
get "_ecg"
|
59
|
-
expect(last_response.status).to eq(200)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context "when a checks errors" do
|
64
|
-
let(:options) {
|
65
|
-
{ checks: [:error] }
|
66
|
-
}
|
67
|
-
it "has a success error code" do
|
68
|
-
get "_ecg"
|
69
|
-
expect(last_response.status).to eq(500)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
context "when hook config option is set" do
|
74
|
-
let(:hook_proc) { instance_double(Proc) }
|
75
|
-
let(:options) {
|
76
|
-
{ hook: hook_proc, checks: :error }
|
77
|
-
}
|
78
|
-
|
79
|
-
it "executes the hook proc with success status and check results as params" do
|
80
|
-
expect(hook_proc).to receive(:call) do |success, check_results|
|
81
|
-
expect(success).to be_falsey
|
82
|
-
expect(check_results).to have_key(:error)
|
83
|
-
end
|
84
|
-
get "_ecg"
|
85
|
-
expect(last_response.status).to eq(500)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
context "git revision" do
|
90
|
-
let(:options) {
|
91
|
-
{ checks: [:git_revision] }
|
92
|
-
}
|
93
|
-
context "when available" do
|
94
|
-
let(:sha) { "cafe1234" }
|
95
|
-
it "is reported" do
|
96
|
-
expect(Open3).to receive(:popen3).
|
97
|
-
with("git rev-parse HEAD").
|
98
|
-
and_return([
|
99
|
-
nil, # stdin
|
100
|
-
StringIO.new(sha + "\n"), # stdout
|
101
|
-
StringIO.new(), # stderr
|
102
|
-
double(value: double(Process::Status, success?: true)) # wait thread & process status
|
103
|
-
])
|
104
|
-
get "/_ecg"
|
105
|
-
expect(json_body["git_revision"]["status"]).to eq("ok")
|
106
|
-
expect(json_body["git_revision"]["value"]).to eq(sha)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
context "when not available" do
|
111
|
-
let(:error_message) { "git had a sad" }
|
112
|
-
it "is reported" do
|
113
|
-
expect(Open3).to receive(:popen3).
|
114
|
-
with("git rev-parse HEAD").
|
115
|
-
and_return([
|
116
|
-
nil, # stdin
|
117
|
-
StringIO.new(), # stdout
|
118
|
-
StringIO.new(error_message + "\n"), # stderr
|
119
|
-
double(value: double(Process::Status, success?: false)) # wait thread & process status
|
120
|
-
])
|
121
|
-
get "/_ecg"
|
122
|
-
expect(json_body["git_revision"]["status"]).to eq("error")
|
123
|
-
expect(json_body["git_revision"]["value"]).to eq("git had a sad")
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
context "migration version" do
|
129
|
-
let(:options) {
|
130
|
-
{ checks: [:migration_version] }
|
131
|
-
}
|
132
|
-
let(:connection) { double("connection") }
|
133
|
-
let(:version) { "123456" }
|
134
|
-
|
135
|
-
context "when available" do
|
136
|
-
it "is reported" do
|
137
|
-
class ActiveRecord
|
138
|
-
class Base
|
139
|
-
def self.connection
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
expect(ActiveRecord::Base).to receive(:connection).and_return(connection)
|
144
|
-
expect(connection).to receive(:select_value).
|
145
|
-
with("select max(version) from schema_migrations").
|
146
|
-
and_return(version)
|
147
|
-
get "/_ecg"
|
148
|
-
expect(json_body["migration_version"]["status"]).to eq("ok")
|
149
|
-
expect(json_body["migration_version"]["value"]).to eq(version)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
context "when not available" do
|
154
|
-
it "is reported" do
|
155
|
-
Object.send(:remove_const, :ActiveRecord) if defined?(ActiveRecord)
|
156
|
-
get "/_ecg"
|
157
|
-
expect(json_body["migration_version"]["status"]).to eq("error")
|
158
|
-
expect(json_body["migration_version"]["value"]).to eq("ActiveRecord not found")
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
context "active_record" do
|
164
|
-
let(:options) {
|
165
|
-
{ checks: [:active_record] }
|
166
|
-
}
|
167
|
-
context "when available" do
|
168
|
-
let(:active) { true }
|
169
|
-
let(:connection) { double("connection") }
|
170
|
-
it "is reported" do
|
171
|
-
class ActiveRecord
|
172
|
-
class Base
|
173
|
-
def self.connection
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
expect(ActiveRecord::Base).to receive(:connection).and_return(connection)
|
178
|
-
expect(connection).to receive(:active?).and_return(active)
|
179
|
-
get "/_ecg"
|
180
|
-
expect(json_body["active_record"]["status"]).to eq("ok")
|
181
|
-
expect(json_body["active_record"]["value"]).to eq(active.to_s)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
context "when not available" do
|
186
|
-
it "is reported" do
|
187
|
-
Object.send(:remove_const, :ActiveRecord) if defined?(ActiveRecord)
|
188
|
-
get "/_ecg"
|
189
|
-
expect(json_body["active_record"]["status"]).to eq("error")
|
190
|
-
expect(json_body["active_record"]["value"]).to eq("ActiveRecord not found")
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
context "redis" do
|
196
|
-
let(:options) {
|
197
|
-
{ checks: [:redis] }
|
198
|
-
}
|
199
|
-
context "when available" do
|
200
|
-
let(:instance) { double("current") }
|
201
|
-
let(:connected) { true }
|
202
|
-
it "is reported" do
|
203
|
-
class Redis
|
204
|
-
def self.current
|
205
|
-
end
|
206
|
-
end
|
207
|
-
expect(Redis).to receive(:current).and_return(instance)
|
208
|
-
expect(instance).to receive(:connected?).and_return(connected)
|
209
|
-
get "/_ecg"
|
210
|
-
expect(json_body["redis"]["status"]).to eq("ok")
|
211
|
-
expect(json_body["redis"]["value"]).to eq(connected.to_s)
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
context "when not available" do
|
216
|
-
it "is reported" do
|
217
|
-
Object.send(:remove_const, :Redis) if defined?(Redis)
|
218
|
-
get "/_ecg"
|
219
|
-
expect(json_body["redis"]["status"]).to eq("error")
|
220
|
-
expect(json_body["redis"]["value"]).to eq("Redis not found")
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
context "sequel" do
|
226
|
-
let(:options) {
|
227
|
-
{ checks: [[:sequel, {name: 'My Awesome DB', connection: 'sqlite://'}]] }
|
228
|
-
}
|
229
|
-
let(:instance) { double("sequel_db") }
|
230
|
-
|
231
|
-
context "when available" do
|
232
|
-
it "is reported" do
|
233
|
-
class Sequel
|
234
|
-
def self.connect(_)
|
235
|
-
end
|
236
|
-
end
|
237
|
-
expect(Sequel).to receive(:connect).with('sqlite://').and_yield(instance)
|
238
|
-
expect(instance).to receive(:test_connection).and_return(true)
|
239
|
-
get "/_ecg"
|
240
|
-
expect(json_body["sequel_my_awesome_db"]["status"]).to eq("ok")
|
241
|
-
expect(json_body["sequel_my_awesome_db"]["value"]).to eq("true")
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'rspec'
|
2
|
-
require 'rack/test'
|
3
|
-
require 'rack/ecg'
|
4
|
-
|
5
|
-
RSpec.configure do |config|
|
6
|
-
config.expect_with :rspec do |expectations|
|
7
|
-
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
8
|
-
end
|
9
|
-
|
10
|
-
config.mock_with :rspec do |mocks|
|
11
|
-
mocks.verify_partial_doubles = true
|
12
|
-
end
|
13
|
-
|
14
|
-
config.disable_monkey_patching!
|
15
|
-
|
16
|
-
config.warnings = true
|
17
|
-
|
18
|
-
config.include Rack::Test::Methods
|
19
|
-
|
20
|
-
def json_body
|
21
|
-
@json_body ||= JSON.parse(last_response.body)
|
22
|
-
end
|
23
|
-
end
|