health-reporter 0.2.1 → 0.3.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 +4 -4
- data/Dockerfile +1 -1
- data/lib/health_reporter/reporter.rb +25 -4
- data/lib/health_reporter/version.rb +1 -1
- data/spec/reporter.rb +353 -173
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0becc469072443dc5e1b63ec1ab05d9ef71fec7cffbb9a5213c7dbfde6ce5a89
|
4
|
+
data.tar.gz: de579186d0b529f2b2128536b73eacd6e8b21ae5ea9fe9198b77605808fca931
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd59fcf68ab839f83ece80d0a734488a055dbc757d71273258328b0908f1af0716ea9a520ab155f31af07dc58cdb9f86d7dd63ea6897aef1930f2503c1d8e57f
|
7
|
+
data.tar.gz: 011b07b0351210e19ba04c8376614cbc30f4f899143662c822907d364b986c4a4587ae0685b5d20f6197d896f7654e7adfa9262ebd605682787ad4284cf19e07
|
data/Dockerfile
CHANGED
@@ -46,11 +46,22 @@ class HealthReporter
|
|
46
46
|
@@dependencies = {}
|
47
47
|
end
|
48
48
|
|
49
|
+
def self.register_dependencies(provided_dependencies = [])
|
50
|
+
provided_dependencies.map{ |dependency|
|
51
|
+
symbolized_dependency = Hash[dependency.map{|(k,v)| [k.to_sym,v]}]
|
52
|
+
raise 'url not defined for dependency' unless symbolized_dependency[:url]
|
53
|
+
add_defaults(symbolized_dependency)
|
54
|
+
dependencies[symbolized_dependency[:url]] = symbolized_dependency
|
55
|
+
dependencies[symbolized_dependency[:url]].delete(:url)
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
49
59
|
def self.dependencies
|
50
60
|
@@dependencies
|
51
61
|
end
|
52
62
|
|
53
63
|
def self.register_dependency(url:, code: 200, timeout: 2)
|
64
|
+
$stderr.puts "The HealthReporter method register_dependency is depreciated. Use fully featured register_dependencies method instead"
|
54
65
|
raise "Configured URL #{url} is invalid" unless url =~ URI::regexp
|
55
66
|
dependencies[url] = { :code => code, :timeout => timeout }
|
56
67
|
end
|
@@ -64,6 +75,11 @@ class HealthReporter
|
|
64
75
|
|
65
76
|
private
|
66
77
|
|
78
|
+
def self.add_defaults(dependency)
|
79
|
+
dependency[:code] |= 200
|
80
|
+
dependency[:timeout] |= 2
|
81
|
+
end
|
82
|
+
|
67
83
|
def self.perform_health_check
|
68
84
|
@@last_check_time = Time.now
|
69
85
|
@@healthy = sanitize(@@self_test.call)
|
@@ -81,12 +97,17 @@ class HealthReporter
|
|
81
97
|
end
|
82
98
|
|
83
99
|
def self.check_dependency(url:, configuration:)
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
request
|
100
|
+
connection ||= Faraday.new(:url => url) do |faraday|
|
101
|
+
faraday.options[:open_timeout] = configuration[:timeout]
|
102
|
+
faraday.options[:timeout] = configuration[:timeout]
|
103
|
+
faraday.request(:url_encoded)
|
104
|
+
faraday.adapter Faraday.default_adapter
|
105
|
+
puts configuration
|
106
|
+
faraday.basic_auth(configuration[:username], configuration[:password]) if configuration[:username]
|
88
107
|
end
|
89
108
|
|
109
|
+
response = connection.get
|
110
|
+
|
90
111
|
unless response.status == configuration[:code]
|
91
112
|
raise "Response expected to be #{configuration[:code]} but is #{response.status}"
|
92
113
|
end
|
data/spec/reporter.rb
CHANGED
@@ -18,7 +18,7 @@ describe HealthReporter do
|
|
18
18
|
reset_lambda_runner_spy
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
describe '#self_test' do
|
22
22
|
it 'remembers the self-test lambda passed to it' do
|
23
23
|
test_lambda = lambda{ 'ab' == 'cd' }
|
24
24
|
subject.self_test = test_lambda
|
@@ -32,29 +32,35 @@ describe HealthReporter do
|
|
32
32
|
expect(subject.healthy?).to be false
|
33
33
|
expect(spy_lambda_was_run?).to eq true
|
34
34
|
end
|
35
|
+
end
|
35
36
|
|
37
|
+
describe '#healthy_cache_ttl' do
|
36
38
|
it 'remembers the cache ttl when healthy' do
|
37
39
|
subject.healthy_cache_ttl = 10
|
38
40
|
expect(subject.healthy_cache_ttl).to eq 10
|
39
41
|
end
|
42
|
+
end
|
40
43
|
|
44
|
+
describe '#unhealthy_cache_ttl' do
|
41
45
|
it 'remembers the cache ttl when not healthy' do
|
42
46
|
subject.unhealthy_cache_ttl = 5
|
43
47
|
expect(subject.unhealthy_cache_ttl).to eq 5
|
44
48
|
end
|
49
|
+
end
|
45
50
|
|
46
|
-
|
51
|
+
describe '#register_dependency' do
|
52
|
+
it 'remembers when you add a dependency' do
|
47
53
|
subject.register_dependency(url: 'https://hardware-store/status', code: 123, timeout: 1)
|
48
54
|
expect(subject.dependencies).to eq({
|
49
55
|
'https://hardware-store/status' => { :code => 123, :timeout => 1 }
|
50
56
|
})
|
51
57
|
end
|
52
58
|
|
53
|
-
it 'validates the urls of the
|
59
|
+
it 'validates the urls of the dependency during registration' do
|
54
60
|
expect{subject.register_dependency(url: 'no-valid-url')}.to raise_error RuntimeError, "Configured URL no-valid-url is invalid"
|
55
61
|
end
|
56
62
|
|
57
|
-
it 'adds
|
63
|
+
it 'adds dependency without removing the dependencies already registered' do
|
58
64
|
subject.register_dependency(url: 'https://hardware-store/status', code: 123, timeout: 1)
|
59
65
|
subject.register_dependency(url: 'https://grocery-store/status', code: 123, timeout: 1)
|
60
66
|
expect(subject.dependencies).to eq({
|
@@ -74,214 +80,388 @@ describe HealthReporter do
|
|
74
80
|
'https://grocery-store/status' => { :code => 123, :timeout => 1 }
|
75
81
|
})
|
76
82
|
end
|
77
|
-
|
78
|
-
it 'clears the cache when requested' do
|
79
|
-
subject.healthy?
|
80
|
-
expect(subject.class_variable_get('@@healthy')).to be true
|
81
|
-
expect(subject.class_variable_get('@@last_check_time')).to_not be nil
|
82
|
-
subject.clear_cache
|
83
|
-
expect(subject.class_variable_get('@@healthy')).to be nil
|
84
|
-
expect(subject.class_variable_get('@@last_check_time')).to be nil
|
85
|
-
end
|
86
83
|
end
|
87
84
|
|
88
|
-
context 'when exercising self-test lambda' do
|
89
|
-
it 'allows true to be returned by self-test lambda' do
|
90
|
-
test_lambda = lambda{ true }
|
91
|
-
subject.self_test = test_lambda
|
92
|
-
expect(subject.healthy?).to be true
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'allows false to be returned by self-test lambda' do
|
96
|
-
test_lambda = lambda{ false }
|
97
|
-
subject.self_test = test_lambda
|
98
|
-
expect(subject.healthy?).to be false
|
99
|
-
end
|
100
85
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
86
|
+
def self.register_dependencies(provided_dependencies = [])
|
87
|
+
provided_dependencies.map{ |dependency|
|
88
|
+
@@dependencies[url] = dependency.delete(:url)
|
89
|
+
}
|
106
90
|
end
|
107
91
|
|
108
|
-
context 'when initialized without any parameters' do
|
109
|
-
it 'sets the default self-test lambda to { true }' do
|
110
|
-
expect(subject.healthy?).to eq true
|
111
|
-
end
|
112
92
|
|
113
|
-
|
114
|
-
|
93
|
+
describe '#register_dependencies' do
|
94
|
+
let(:provided_test_dependencies_with_string_keys) {
|
95
|
+
[
|
96
|
+
{
|
97
|
+
"url" => "https://cake-place/health",
|
98
|
+
"code" => 200,
|
99
|
+
"timeout" => 3
|
100
|
+
},
|
101
|
+
{
|
102
|
+
"url" => "https://coffee-place/status",
|
103
|
+
"code" => 200,
|
104
|
+
"timeout" => 3
|
105
|
+
},
|
106
|
+
{
|
107
|
+
"url" => "http://postoffice/status",
|
108
|
+
"code" => 200,
|
109
|
+
"timeout" => 3
|
110
|
+
},
|
111
|
+
{
|
112
|
+
"url" => "http://postoffice/status",
|
113
|
+
"code" => 200,
|
114
|
+
"timeout" => 3,
|
115
|
+
"authorization_token" => "api_token"
|
116
|
+
},
|
117
|
+
{
|
118
|
+
"url" => "http://duplicated/status",
|
119
|
+
"code" => 200,
|
120
|
+
"timeout" => 3,
|
121
|
+
"authorization_token" => "api_token"
|
122
|
+
},
|
123
|
+
{
|
124
|
+
"url" => "http://duplicated/status",
|
125
|
+
"code" => 200,
|
126
|
+
"timeout" => 3,
|
127
|
+
"authorization_token" => "api_token"
|
128
|
+
},
|
129
|
+
{
|
130
|
+
"url" => "https://pizza-place/health",
|
131
|
+
"code" => 204,
|
132
|
+
"timeout" => 2,
|
133
|
+
"username" => "checker",
|
134
|
+
"password" => "checking"
|
135
|
+
}
|
136
|
+
]
|
137
|
+
}
|
138
|
+
let(:provided_test_dependencies_with_symbol_keys) {
|
139
|
+
[
|
140
|
+
{
|
141
|
+
url: "https://cake-place/health",
|
142
|
+
code: 200,
|
143
|
+
timeout: 3
|
144
|
+
},
|
145
|
+
{
|
146
|
+
url: "https://coffee-place/status",
|
147
|
+
code: 200,
|
148
|
+
timeout: 3
|
149
|
+
},
|
150
|
+
{
|
151
|
+
url: "http://postoffice/status",
|
152
|
+
code: 200,
|
153
|
+
timeout: 3
|
154
|
+
},
|
155
|
+
{
|
156
|
+
url: "http://postoffice/status",
|
157
|
+
code: 200,
|
158
|
+
timeout: 3,
|
159
|
+
authorization_token: "api_token"
|
160
|
+
},
|
161
|
+
{
|
162
|
+
url: "http://duplicated/status",
|
163
|
+
code: 200,
|
164
|
+
timeout: 3,
|
165
|
+
authorization_token: "api_token"
|
166
|
+
},
|
167
|
+
{
|
168
|
+
url: "http://duplicated/status",
|
169
|
+
code: 200,
|
170
|
+
timeout: 3,
|
171
|
+
authorization_token: "api_token"
|
172
|
+
},
|
173
|
+
{
|
174
|
+
url: "https://pizza-place/health",
|
175
|
+
code: 204,
|
176
|
+
timeout: 2,
|
177
|
+
username: "checker",
|
178
|
+
password: "checking"
|
179
|
+
}
|
180
|
+
]
|
181
|
+
}
|
182
|
+
let(:expected_dependencies) {
|
183
|
+
{
|
184
|
+
"https://cake-place/health" => {
|
185
|
+
code: 200,
|
186
|
+
timeout: 3
|
187
|
+
},
|
188
|
+
"https://coffee-place/status" => {
|
189
|
+
code: 200,
|
190
|
+
timeout: 3
|
191
|
+
},
|
192
|
+
"http://postoffice/status" => {
|
193
|
+
code: 200,
|
194
|
+
timeout: 3,
|
195
|
+
authorization_token: "api_token"
|
196
|
+
},
|
197
|
+
"http://duplicated/status" => {
|
198
|
+
code: 200,
|
199
|
+
timeout: 3,
|
200
|
+
authorization_token: "api_token"
|
201
|
+
},
|
202
|
+
"https://pizza-place/health" => {
|
203
|
+
code: 204,
|
204
|
+
timeout: 2,
|
205
|
+
username: "checker",
|
206
|
+
password: "checking"
|
207
|
+
}
|
208
|
+
}
|
209
|
+
}
|
210
|
+
it 'remembers when you add the dependencies with string keys' do
|
211
|
+
subject.register_dependencies(provided_test_dependencies_with_string_keys)
|
212
|
+
expect(subject.dependencies).to eq(expected_dependencies)
|
115
213
|
end
|
116
|
-
|
117
|
-
|
118
|
-
expect(subject.
|
214
|
+
it 'remembers when you add the dependencies with symbol keys' do
|
215
|
+
subject.register_dependencies(provided_test_dependencies_with_symbol_keys)
|
216
|
+
expect(subject.dependencies).to eq(expected_dependencies)
|
119
217
|
end
|
120
|
-
end
|
121
218
|
|
122
|
-
|
123
|
-
it 'calls the configured self-test lambda and returns health' do
|
124
|
-
subject.self_test = spy_lambda_returning_false
|
125
|
-
expect(subject.healthy?).to be false
|
126
|
-
expect(spy_lambda_was_run?).to eq true
|
127
|
-
end
|
219
|
+
|
128
220
|
end
|
129
221
|
|
130
|
-
|
131
|
-
|
132
|
-
subject.
|
133
|
-
subject.healthy
|
134
|
-
|
222
|
+
describe '#clear_cache' do
|
223
|
+
it 'clears the cache when requested' do
|
224
|
+
subject.healthy?
|
225
|
+
expect(subject.class_variable_get('@@healthy')).to be true
|
226
|
+
expect(subject.class_variable_get('@@last_check_time')).to_not be nil
|
227
|
+
subject.clear_cache
|
228
|
+
expect(subject.class_variable_get('@@healthy')).to be nil
|
229
|
+
expect(subject.class_variable_get('@@last_check_time')).to be nil
|
135
230
|
end
|
231
|
+
end
|
136
232
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
end
|
143
|
-
|
144
|
-
it 'does not call the registered self-test lambda' do
|
145
|
-
subject.healthy? #request here and test if it was run in expect below
|
146
|
-
expect(spy_lambda_was_run?).to eq false
|
147
|
-
end
|
148
|
-
it 'returns the current healthy state' do
|
233
|
+
describe '#healthy?' do
|
234
|
+
context 'when exercising self-test lambda' do
|
235
|
+
it 'allows true to be returned by self-test lambda' do
|
236
|
+
test_lambda = lambda{ true }
|
237
|
+
subject.self_test = test_lambda
|
149
238
|
expect(subject.healthy?).to be true
|
150
239
|
end
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
subject.
|
156
|
-
subject.healthy_cache_ttl = 3
|
157
|
-
Timecop.freeze(Time.now + 5)
|
240
|
+
|
241
|
+
it 'allows false to be returned by self-test lambda' do
|
242
|
+
test_lambda = lambda{ false }
|
243
|
+
subject.self_test = test_lambda
|
244
|
+
expect(subject.healthy?).to be false
|
158
245
|
end
|
159
|
-
|
160
|
-
it '
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
it 'returns the current healthy state' do
|
165
|
-
expect(subject.healthy?).to be true
|
246
|
+
|
247
|
+
it 'raises an exception when non-boolean values are returned by self-test lambda' do
|
248
|
+
test_lambda = lambda{ "I don't feel well..." }
|
249
|
+
subject.self_test = test_lambda
|
250
|
+
expect{subject.healthy?}.to raise_error RuntimeError, "Invalid non-boolean response from registered self-check lambda: I don't feel well..."
|
166
251
|
end
|
167
252
|
end
|
168
|
-
|
169
|
-
context 'when
|
170
|
-
|
171
|
-
subject.
|
172
|
-
subject.healthy_cache_ttl = 10
|
173
|
-
Timecop.freeze(Time.now + 5)
|
253
|
+
|
254
|
+
context 'when initialized without any parameters' do
|
255
|
+
it 'sets the default self-test lambda to { true }' do
|
256
|
+
expect(subject.healthy?).to eq true
|
174
257
|
end
|
175
|
-
|
176
|
-
it '
|
177
|
-
subject.
|
178
|
-
expect(spy_lambda_was_run?).to eq false
|
258
|
+
|
259
|
+
it 'sets the default healthy state cache ttl to 60 seconds' do
|
260
|
+
expect(subject.healthy_cache_ttl).to eq 60
|
179
261
|
end
|
180
|
-
|
181
|
-
|
262
|
+
|
263
|
+
it 'sets the default unhealthy state cache ttl to 30 seconds' do
|
264
|
+
expect(subject.unhealthy_cache_ttl).to eq 30
|
182
265
|
end
|
183
266
|
end
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
subject.self_test = spy_lambda_returning_false
|
189
|
-
subject.healthy? #force the self-test
|
190
|
-
reset_lambda_runner_spy #reset the spy so that we can see if it was run or not
|
191
|
-
end
|
192
|
-
|
193
|
-
context 'when neither healty-cache-ttl nor unhealty-cache-ttl has expired' do
|
194
|
-
before(:each) do
|
195
|
-
subject.unhealthy_cache_ttl = 10
|
196
|
-
subject.healthy_cache_ttl = 10
|
197
|
-
Timecop.freeze(Time.now + 5)
|
198
|
-
end
|
199
|
-
|
200
|
-
it 'does not call the registered self-test lambda' do
|
201
|
-
subject.healthy? #request here and test if it was run in expect below
|
202
|
-
expect(spy_lambda_was_run?).to eq false
|
203
|
-
end
|
204
|
-
it 'returns the current unhealthy state' do
|
267
|
+
|
268
|
+
context 'when calling health check for first time (no cached health state)' do
|
269
|
+
it 'calls the configured self-test lambda and returns health' do
|
270
|
+
subject.self_test = spy_lambda_returning_false
|
205
271
|
expect(subject.healthy?).to be false
|
272
|
+
expect(spy_lambda_was_run?).to eq true
|
206
273
|
end
|
207
274
|
end
|
208
|
-
|
209
|
-
context 'when
|
275
|
+
|
276
|
+
context 'when current state is healty' do
|
210
277
|
before(:each) do
|
211
|
-
subject.
|
212
|
-
subject.
|
213
|
-
|
278
|
+
subject.self_test = spy_lambda_returning_true
|
279
|
+
subject.healthy? #force the self-test
|
280
|
+
reset_lambda_runner_spy #reset the spy so that we can see if it was run or not
|
214
281
|
end
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
282
|
+
|
283
|
+
context 'when neither healty-cache-ttl nor unhealty-cache-ttl has expired' do
|
284
|
+
before(:each) do
|
285
|
+
subject.unhealthy_cache_ttl = 10
|
286
|
+
subject.healthy_cache_ttl = 10
|
287
|
+
Timecop.freeze(Time.now + 5)
|
288
|
+
end
|
289
|
+
|
290
|
+
it 'does not call the registered self-test lambda' do
|
291
|
+
subject.healthy? #request here and test if it was run in expect below
|
292
|
+
expect(spy_lambda_was_run?).to eq false
|
293
|
+
end
|
294
|
+
it 'returns the current healthy state' do
|
295
|
+
expect(subject.healthy?).to be true
|
296
|
+
end
|
219
297
|
end
|
220
|
-
|
221
|
-
|
298
|
+
|
299
|
+
context 'when healty-cache-ttl has expired' do
|
300
|
+
before do
|
301
|
+
subject.unhealthy_cache_ttl = 10
|
302
|
+
subject.healthy_cache_ttl = 3
|
303
|
+
Timecop.freeze(Time.now + 5)
|
304
|
+
end
|
305
|
+
|
306
|
+
it 'calls the registered self-test lambda' do
|
307
|
+
subject.healthy? #request here and test if it was run in expect below
|
308
|
+
expect(spy_lambda_was_run?).to eq true
|
309
|
+
end
|
310
|
+
it 'returns the current healthy state' do
|
311
|
+
expect(subject.healthy?).to be true
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context 'when unhealty-cache-ttl has expired' do
|
316
|
+
before(:each) do
|
317
|
+
subject.unhealthy_cache_ttl = 3
|
318
|
+
subject.healthy_cache_ttl = 10
|
319
|
+
Timecop.freeze(Time.now + 5)
|
320
|
+
end
|
321
|
+
|
322
|
+
it 'does not call the registered self-test lambda' do
|
323
|
+
subject.healthy? #request here and test if it was run in expect below
|
324
|
+
expect(spy_lambda_was_run?).to eq false
|
325
|
+
end
|
326
|
+
it 'returns the current healthy state' do
|
327
|
+
expect(subject.healthy?).to be true
|
328
|
+
end
|
222
329
|
end
|
223
330
|
end
|
224
|
-
|
225
|
-
context 'when
|
331
|
+
|
332
|
+
context 'when current state is unhealty' do
|
226
333
|
before(:each) do
|
227
|
-
subject.
|
228
|
-
subject.
|
229
|
-
|
334
|
+
subject.self_test = spy_lambda_returning_false
|
335
|
+
subject.healthy? #force the self-test
|
336
|
+
reset_lambda_runner_spy #reset the spy so that we can see if it was run or not
|
230
337
|
end
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
338
|
+
|
339
|
+
context 'when neither healty-cache-ttl nor unhealty-cache-ttl has expired' do
|
340
|
+
before(:each) do
|
341
|
+
subject.unhealthy_cache_ttl = 10
|
342
|
+
subject.healthy_cache_ttl = 10
|
343
|
+
Timecop.freeze(Time.now + 5)
|
344
|
+
end
|
345
|
+
|
346
|
+
it 'does not call the registered self-test lambda' do
|
347
|
+
subject.healthy? #request here and test if it was run in expect below
|
348
|
+
expect(spy_lambda_was_run?).to eq false
|
349
|
+
end
|
350
|
+
it 'returns the current unhealthy state' do
|
351
|
+
expect(subject.healthy?).to be false
|
352
|
+
end
|
235
353
|
end
|
236
|
-
|
237
|
-
|
354
|
+
|
355
|
+
context 'when healty-cache-ttl has expired' do
|
356
|
+
before(:each) do
|
357
|
+
subject.unhealthy_cache_ttl = 10
|
358
|
+
subject.healthy_cache_ttl = 3
|
359
|
+
Timecop.freeze(Time.now + 5)
|
360
|
+
end
|
361
|
+
|
362
|
+
it 'does not call the registered self-test lambda' do
|
363
|
+
subject.healthy? #request here and test if it was run in expect below
|
364
|
+
expect(spy_lambda_was_run?).to eq false
|
365
|
+
end
|
366
|
+
it 'returns the current unhealthy state' do
|
367
|
+
expect(subject.healthy?).to be false
|
368
|
+
end
|
238
369
|
end
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
370
|
+
|
371
|
+
context 'when unhealty-cache-ttl has expired' do
|
372
|
+
before(:each) do
|
373
|
+
subject.unhealthy_cache_ttl = 3
|
374
|
+
subject.healthy_cache_ttl = 10
|
375
|
+
Timecop.freeze(Time.now + 5)
|
376
|
+
end
|
377
|
+
|
378
|
+
it 'calls the registered self-test lambda' do
|
379
|
+
subject.healthy? #request here and test if it was run in expect below
|
380
|
+
expect(spy_lambda_was_run?).to eq true
|
381
|
+
end
|
382
|
+
it 'returns the current unhealthy state' do
|
383
|
+
expect(subject.healthy?).to be false
|
384
|
+
end
|
248
385
|
end
|
249
386
|
end
|
250
|
-
|
251
|
-
context 'when
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
387
|
+
|
388
|
+
context 'when checking dependencies' do
|
389
|
+
context 'when there are no dependencies registered' do
|
390
|
+
it 'only performs the self-test' do
|
391
|
+
subject.self_test = spy_lambda_returning_false
|
392
|
+
expect(subject.healthy?).to be false
|
393
|
+
expect(spy_lambda_was_run?).to eq true
|
394
|
+
end
|
256
395
|
end
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
396
|
+
|
397
|
+
context 'when there are multiple dependencies registered' do
|
398
|
+
before(:each) do
|
399
|
+
subject.register_dependency(url: 'https://hardware-store/status')
|
400
|
+
subject.register_dependency(url: 'https://grocery-store/status')
|
401
|
+
subject.self_test = spy_lambda_returning_true
|
402
|
+
end
|
403
|
+
|
404
|
+
it 'performs the self-test and checks all dependencies' do
|
405
|
+
stub_request(:get, "https://hardware-store/status").to_return(:status => 200, :body => "", :headers => {})
|
406
|
+
stub_request(:get, "https://grocery-store/status").to_return(:status => 200, :body => "", :headers => {})
|
407
|
+
expect(subject.healthy?).to be true
|
408
|
+
expect(spy_lambda_was_run?).to eq true
|
409
|
+
end
|
410
|
+
|
411
|
+
it 'indicates healthy if all of the dependencies are healthy' do
|
412
|
+
stub_request(:get, "https://hardware-store/status").to_return(:status => 200, :body => "", :headers => {})
|
413
|
+
stub_request(:get, "https://grocery-store/status").to_return(:status => 200, :body => "", :headers => {})
|
414
|
+
expect(subject.healthy?).to be true
|
415
|
+
expect(spy_lambda_was_run?).to eq true
|
416
|
+
end
|
417
|
+
|
418
|
+
it 'raises a detailed exception indicating why a dependency was determined to be unhealthy state was uncached' do
|
419
|
+
stub_request(:get, "https://hardware-store/status").to_return(:status => 500, :body => "", :headers => {})
|
420
|
+
stub_request(:get, "https://grocery-store/status").to_return(:status => 200, :body => "", :headers => {})
|
421
|
+
expect{subject.healthy?}.to raise_error RuntimeError, "Dependency <https://hardware-store/status> failed check due to RuntimeError: Response expected to be 200 but is 500"
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'indicates cached unhealthy state if it is unhealthy because a dependency was unhealthy' do
|
425
|
+
stub_request(:get, "https://hardware-store/status").to_return(:status => 500, :body => "", :headers => {})
|
426
|
+
stub_request(:get, "https://grocery-store/status").to_return(:status => 200, :body => "", :headers => {})
|
427
|
+
expect{subject.healthy?}.to raise_error RuntimeError, "Dependency <https://hardware-store/status> failed check due to RuntimeError: Response expected to be 200 but is 500"
|
428
|
+
reset_lambda_runner_spy
|
429
|
+
expect(subject.healthy?).to be false
|
430
|
+
expect(spy_lambda_was_run?).to eq false
|
431
|
+
end
|
263
432
|
end
|
264
433
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
434
|
+
context 'when a dependency requires basic auth' do
|
435
|
+
let(:test_dependencies_with_basic_auth) {
|
436
|
+
[
|
437
|
+
{
|
438
|
+
url: "https://pizza-place/health",
|
439
|
+
code: 204,
|
440
|
+
timeout: 2,
|
441
|
+
username: "check_user",
|
442
|
+
password: "check_password"
|
443
|
+
}
|
444
|
+
]
|
445
|
+
}
|
446
|
+
|
447
|
+
before(:each) do
|
448
|
+
subject.register_dependencies(test_dependencies_with_basic_auth)
|
449
|
+
end
|
450
|
+
|
451
|
+
it 'reaches out to the dependency using a basic auth and dependency have good health' do
|
452
|
+
stub_request(:get, "https://pizza-place/health").
|
453
|
+
with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Basic Y2hlY2tfdXNlcjpjaGVja19wYXNzd29yZA==', 'User-Agent'=>'Faraday v0.15.2'}).
|
454
|
+
to_return(:status => 204, :body => "", :headers => {})
|
455
|
+
expect(subject.healthy?).to be true
|
456
|
+
end
|
457
|
+
|
458
|
+
it 'reaches out to the dependency using a basic auth and dependency does not have good health' do
|
459
|
+
stub_request(:get, "https://pizza-place/health").
|
460
|
+
with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Basic Y2hlY2tfdXNlcjpjaGVja19wYXNzd29yZA==', 'User-Agent'=>'Faraday v0.15.2'}).
|
461
|
+
to_return(:status => 500, :body => "", :headers => {})
|
462
|
+
expect{subject.healthy?}.to raise_error RuntimeError, "Dependency <https://pizza-place/health> failed check due to RuntimeError: Response expected to be 204 but is 500"
|
463
|
+
expect(subject.healthy?).to be false
|
464
|
+
end
|
285
465
|
end
|
286
466
|
end
|
287
467
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: health-reporter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Barney de Villiers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|