health_check_rb 4.0.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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/linters.yml +27 -0
  3. data/.github/workflows/tests.yml +50 -0
  4. data/.gitignore +33 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +110 -0
  7. data/CHANGELOG +122 -0
  8. data/Gemfile +23 -0
  9. data/MIT-LICENSE +23 -0
  10. data/README.md +392 -0
  11. data/Rakefile +27 -0
  12. data/config/routes.rb +7 -0
  13. data/health_check_rb.gemspec +26 -0
  14. data/init.rb +3 -0
  15. data/lib/health_check_rb/base_health_check.rb +7 -0
  16. data/lib/health_check_rb/check/elasticsearch.rb +18 -0
  17. data/lib/health_check_rb/check/rabbitmq.rb +19 -0
  18. data/lib/health_check_rb/check/redis.rb +30 -0
  19. data/lib/health_check_rb/check/resque.rb +18 -0
  20. data/lib/health_check_rb/check/s3.rb +62 -0
  21. data/lib/health_check_rb/check/sidekiq.rb +20 -0
  22. data/lib/health_check_rb/health_check_controller.rb +80 -0
  23. data/lib/health_check_rb/health_check_routes.rb +18 -0
  24. data/lib/health_check_rb/middleware_health_check.rb +108 -0
  25. data/lib/health_check_rb/utils.rb +194 -0
  26. data/lib/health_check_rb/version.rb +5 -0
  27. data/lib/health_check_rb.rb +129 -0
  28. data/spec/dummy/Rakefile +8 -0
  29. data/spec/dummy/app/assets/config/manifest.js +1 -0
  30. data/spec/dummy/app/controllers/example_controller.rb +7 -0
  31. data/spec/dummy/config/database.yml +10 -0
  32. data/spec/dummy/config/initializers/health_check.rb +18 -0
  33. data/spec/dummy/config/initializers/middleware.rb +3 -0
  34. data/spec/dummy/config/routes.rb +5 -0
  35. data/spec/dummy/db/migrate/.keep +0 -0
  36. data/spec/dummy/fake_app.rb +18 -0
  37. data/spec/dummy/tmp/.keep +0 -0
  38. data/spec/fixtures/migrate/9_create_countries.rb +9 -0
  39. data/spec/health_check_rb_spec.rb +300 -0
  40. data/spec/spec_helper.rb +36 -0
  41. metadata +101 -0
@@ -0,0 +1,300 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe HealthCheckRb, type: :request do
6
+ context 'with /custom_route_prefix' do
7
+ it 'works with smtp server and valid custom_check' do
8
+ enable_custom_check do
9
+ mock_smtp_server do
10
+ get '/custom_route_prefix'
11
+ expect(response).to be_ok
12
+ end
13
+ end
14
+ end
15
+
16
+ it 'fails with no smtp server and valid custom_check' do
17
+ enable_custom_check do
18
+ get '/custom_route_prefix'
19
+ expect(response.status).to eq(550)
20
+ expect(response.body).to include 'health_check failed'
21
+ end
22
+ end
23
+
24
+ it 'fails with smtp server and invalid custom_check' do
25
+ mock_smtp_server do
26
+ get '/custom_route_prefix'
27
+ expect(response.status).to eq(550)
28
+ expect(response.body).to include 'health_check failed'
29
+ end
30
+ end
31
+ end
32
+
33
+ context 'with /custom_route_prefix/all' do
34
+ it 'works with smtp server and valid custom_check' do
35
+ enable_custom_check do
36
+ mock_smtp_server do
37
+ get '/custom_route_prefix/all'
38
+ expect(response).to be_ok
39
+ end
40
+ end
41
+ end
42
+
43
+ it 'fails with no smtp server and valid custom_check' do
44
+ enable_custom_check do
45
+ get '/custom_route_prefix/all'
46
+ expect(response.status).to eq(550)
47
+ expect(response.body).to include 'health_check failed'
48
+ end
49
+ end
50
+
51
+ it 'fails with smtp server and invalid custom_check' do
52
+ mock_smtp_server do
53
+ get '/custom_route_prefix/all'
54
+ expect(response.status).to eq(550)
55
+ expect(response.body).to include 'health_check failed'
56
+ end
57
+ end
58
+ end
59
+
60
+ context 'with /custom_route_prefix/migration' do
61
+ before { reconnect_database }
62
+
63
+ after do
64
+ Dir.glob('spec/dummy/db/migrate/*').each do |f|
65
+ FileUtils.rm f
66
+ end
67
+ FileUtils.rm 'spec/dummy/db/schema.rb' if File.exist? 'spec/dummy/db/schema.rb'
68
+ FileUtils.cd FakeApp.config.root do
69
+ ActiveRecord::Tasks::DatabaseTasks.drop_current
70
+ end
71
+ end
72
+
73
+ it 'works with no migration files' do
74
+ get '/custom_route_prefix/migration'
75
+ expect(response).to be_ok
76
+ end
77
+
78
+ it 'fails with pending migration files' do
79
+ FileUtils.cp 'spec/fixtures/migrate/9_create_countries.rb', 'spec/dummy/db/migrate/9_create_countries.rb'
80
+ FileUtils.cd FakeApp.config.root do
81
+ get '/custom_route_prefix/migration'
82
+ end
83
+ expect(response.status).to eq(550)
84
+ end
85
+
86
+ it 'works with applied migration files' do
87
+ FileUtils.cp 'spec/fixtures/migrate/9_create_countries.rb', 'spec/dummy/db/migrate/9_create_countries.rb'
88
+ FileUtils.cd FakeApp.config.root do
89
+ db_migrate
90
+ get '/custom_route_prefix/migration'
91
+ end
92
+ expect(response).to be_ok
93
+ end
94
+ end
95
+
96
+ describe '/custom_route_prefix/database' do
97
+ after do
98
+ Dir.glob('spec/dummy/db/migrate/*').each do |f|
99
+ FileUtils.rm f
100
+ end
101
+ FileUtils.rm 'spec/dummy/db/schema.rb' if File.exist? 'spec/dummy/db/schema.rb'
102
+ FileUtils.cd FakeApp.config.root do
103
+ ActiveRecord::Tasks::DatabaseTasks.drop_current
104
+ end
105
+ end
106
+
107
+ it 'works with no database' do
108
+ get '/custom_route_prefix/database'
109
+ expect(response).to be_ok
110
+ end
111
+
112
+ it 'works with valid database' do
113
+ FileUtils.cp 'spec/fixtures/migrate/9_create_countries.rb', 'spec/dummy/db/migrate/9_create_countries.rb'
114
+ FileUtils.cd FakeApp.config.root do
115
+ db_migrate
116
+ get '/custom_route_prefix/database'
117
+ end
118
+ expect(response).to be_ok
119
+ end
120
+
121
+ it 'fails with invalid database' do
122
+ disconnect_database
123
+ Rails.root.join('db/test.sqlite3').write('invalid')
124
+ get '/custom_route_prefix/database'
125
+ expect(response.status).to eq(550)
126
+ expect(response.body).to include 'health_check failed'
127
+ end
128
+ end
129
+
130
+ describe '/custom_route_prefix/email' do
131
+ it 'works with smtp server' do
132
+ mock_smtp_server do
133
+ get '/custom_route_prefix/email'
134
+ expect(response).to be_ok
135
+ end
136
+ end
137
+
138
+ it 'fails with no smtp server' do
139
+ get '/custom_route_prefix/email'
140
+ expect(response.status).to eq(550)
141
+ expect(response.body).to include 'health_check failed'
142
+ end
143
+ end
144
+
145
+ describe '/custom_route_prefix/pass (a custom check does nothing)' do
146
+ it 'works if another custom check is invalid' do
147
+ get '/custom_route_prefix/pass'
148
+ expect(response).to be_ok
149
+ end
150
+
151
+ it 'works if another custom check is valid' do
152
+ enable_custom_check do
153
+ get '/custom_route_prefix/pass'
154
+ expect(response).to be_ok
155
+ end
156
+ end
157
+ end
158
+
159
+ describe '/heath_check/custom' do
160
+ it 'works with valid custom check' do
161
+ enable_custom_check do
162
+ get '/custom_route_prefix/custom'
163
+ end
164
+ expect(response).to be_ok
165
+ end
166
+
167
+ it 'fails with invalid custom check' do
168
+ get '/custom_route_prefix/custom'
169
+ expect(response.status).to eq(550)
170
+ expect(response.body).to include 'health_check failed'
171
+ end
172
+
173
+ context 'with specified format' do
174
+ it 'returns plain text if client requests html format' do
175
+ enable_custom_check do
176
+ get '/custom_route_prefix/custom.html'
177
+ end
178
+ expect(response).to be_ok
179
+ expect(response.content_type).to include('text/plain')
180
+ end
181
+
182
+ it 'returns json if client requests json format' do
183
+ enable_custom_check do
184
+ get '/custom_route_prefix/custom.json'
185
+ end
186
+ expect(response).to be_ok
187
+ expect(response.content_type).to include('application/json')
188
+ expect(response.parsed_body).to include('healthy' => true, 'message' => 'custom_success_message')
189
+ end
190
+
191
+ it 'returns json if client requests json format and custom check is invalid' do
192
+ get '/custom_route_prefix/custom.json'
193
+ expect(response.status).to eq(555) # config.http_status_for_error_object = 555
194
+ expect(response.content_type).to include('application/json')
195
+ expect(response.parsed_body).to include('healthy' => false)
196
+ end
197
+
198
+ it 'returns xml if client requests xml format' do
199
+ enable_custom_check do
200
+ get '/custom_route_prefix/custom.xml'
201
+ end
202
+ expect(response).to be_ok
203
+ expect(response.content_type).to include('application/xml')
204
+ expect(response.body).to include('<healthy type="boolean">true</healthy>')
205
+ expect(response.body).to include('<message>custom_success_message</message>')
206
+ end
207
+
208
+ it 'returns xml if client requests xml format and custom check is invalid' do
209
+ get '/custom_route_prefix/custom.xml'
210
+ expect(response.status).to eq(555) # config.http_status_for_error_object = 555
211
+ expect(response.content_type).to include('application/xml')
212
+ expect(response.body).to include('<healthy type="boolean">false</healthy>')
213
+ end
214
+ end
215
+ end
216
+
217
+ describe '/custom_route_prefix/middleware' do
218
+ if ENV['MIDDLEWARE'] == 'true'
219
+ context 'when using middleware' do
220
+ it 'works with valid custom check' do
221
+ enable_custom_check do
222
+ get '/custom_route_prefix/middleware'
223
+ end
224
+ expect(response).to be_ok
225
+ end
226
+ end
227
+ end
228
+ if ENV['MIDDLEWARE'] != 'true'
229
+ context 'when not using middleware' do
230
+ it 'fails with invalid custom check' do
231
+ get '/custom_route_prefix/middleware'
232
+ expect(response.status).to eq(550)
233
+ expect(response.body).to include 'health_check failed'
234
+ end
235
+ end
236
+ end
237
+ end
238
+
239
+ context 'with whitelisted ip' do
240
+ after { HealthCheckRb.origin_ip_whitelist.clear }
241
+
242
+ it 'works with access from valid ip address' do
243
+ HealthCheckRb.origin_ip_whitelist << '127.0.0.1'
244
+ get '/custom_route_prefix/site'
245
+ expect(response).to be_ok
246
+ end
247
+
248
+ it 'fails with access from invalid ip address' do
249
+ HealthCheckRb.origin_ip_whitelist << '123.123.123.123'
250
+ get '/custom_route_prefix/site'
251
+ expect(response.status).to eq(403)
252
+ end
253
+
254
+ it 'does not affect paths other than health_check' do
255
+ HealthCheckRb.origin_ip_whitelist << '123.123.123.123'
256
+ get '/example'
257
+ expect(response).to be_ok
258
+ end
259
+ end
260
+
261
+ context 'with basic auth' do
262
+ before do
263
+ HealthCheckRb.basic_auth_username = 'username'
264
+ HealthCheckRb.basic_auth_password = 'password'
265
+ end
266
+
267
+ after do
268
+ HealthCheckRb.basic_auth_username = nil
269
+ HealthCheckRb.basic_auth_password = nil
270
+ end
271
+
272
+ it 'works with valid credentials' do
273
+ get '/custom_route_prefix/site',
274
+ headers: { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials('username', 'password') }
275
+ expect(response).to be_ok
276
+ end
277
+
278
+ it 'fails with wrong password' do
279
+ get '/custom_route_prefix/site',
280
+ headers: { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials('username', 'wrong_password') }
281
+ expect(response.status).to eq(401)
282
+ end
283
+
284
+ it 'fails with wrong username' do
285
+ get '/custom_route_prefix/site',
286
+ headers: { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials('wrong_username', 'password') }
287
+ expect(response.status).to eq(401)
288
+ end
289
+
290
+ it 'fails with no credentials' do
291
+ get '/custom_route_prefix/site'
292
+ expect(response.status).to eq(401)
293
+ end
294
+
295
+ it 'does not affect paths other than health_check' do
296
+ get '/example'
297
+ expect(response).to be_ok
298
+ end
299
+ end
300
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'dummy/fake_app'
4
+ require 'rspec/rails'
5
+ require 'smtp_mock/test_framework/rspec'
6
+
7
+ RSpec.configure do |config|
8
+ config.include SmtpMock::TestFramework::RSpec::Helper
9
+ end
10
+
11
+ # see https://github.com/mocktools/ruby-smtp-mock
12
+ def mock_smtp_server(&)
13
+ smtp_mock_server port: 3555 do
14
+ sleep 1
15
+ yield
16
+ end
17
+ end
18
+
19
+ def enable_custom_check(&)
20
+ File.write CUSTOM_CHECK_FILE_PATH, 'hello'
21
+ yield
22
+ ensure
23
+ FileUtils.rm CUSTOM_CHECK_FILE_PATH if File.exist? CUSTOM_CHECK_FILE_PATH
24
+ end
25
+
26
+ def disconnect_database
27
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection.disconnect!
28
+ end
29
+
30
+ def reconnect_database
31
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection.reconnect!
32
+ end
33
+
34
+ def db_migrate
35
+ system 'RAILS_ENV=test bundle exec rake db:migrate'
36
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: health_check_rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 4.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Ian Heggie
8
+ - Alexander Meindl
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2025-02-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: railties
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '5.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '5.0'
28
+ description: " \tSimple health check of Rails app for uptime monitoring with Pingdom,
29
+ NewRelic, EngineYard etc.\n"
30
+ email:
31
+ - ian@heggie.biz
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files:
35
+ - README.md
36
+ files:
37
+ - ".github/workflows/linters.yml"
38
+ - ".github/workflows/tests.yml"
39
+ - ".gitignore"
40
+ - ".rspec"
41
+ - ".rubocop.yml"
42
+ - CHANGELOG
43
+ - Gemfile
44
+ - MIT-LICENSE
45
+ - README.md
46
+ - Rakefile
47
+ - config/routes.rb
48
+ - health_check_rb.gemspec
49
+ - init.rb
50
+ - lib/health_check_rb.rb
51
+ - lib/health_check_rb/base_health_check.rb
52
+ - lib/health_check_rb/check/elasticsearch.rb
53
+ - lib/health_check_rb/check/rabbitmq.rb
54
+ - lib/health_check_rb/check/redis.rb
55
+ - lib/health_check_rb/check/resque.rb
56
+ - lib/health_check_rb/check/s3.rb
57
+ - lib/health_check_rb/check/sidekiq.rb
58
+ - lib/health_check_rb/health_check_controller.rb
59
+ - lib/health_check_rb/health_check_routes.rb
60
+ - lib/health_check_rb/middleware_health_check.rb
61
+ - lib/health_check_rb/utils.rb
62
+ - lib/health_check_rb/version.rb
63
+ - spec/dummy/Rakefile
64
+ - spec/dummy/app/assets/config/manifest.js
65
+ - spec/dummy/app/controllers/example_controller.rb
66
+ - spec/dummy/config/database.yml
67
+ - spec/dummy/config/initializers/health_check.rb
68
+ - spec/dummy/config/initializers/middleware.rb
69
+ - spec/dummy/config/routes.rb
70
+ - spec/dummy/db/migrate/.keep
71
+ - spec/dummy/fake_app.rb
72
+ - spec/dummy/tmp/.keep
73
+ - spec/fixtures/migrate/9_create_countries.rb
74
+ - spec/health_check_rb_spec.rb
75
+ - spec/spec_helper.rb
76
+ homepage: https://github.com/alphanodes/health_check_rb
77
+ licenses:
78
+ - MIT
79
+ metadata:
80
+ rubygems_mfa_required: 'true'
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '3.1'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubygems_version: 3.4.19
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: Simple health check of Rails app for uptime monitoring with Pingdom, NewRelic,
100
+ EngineYard etc.
101
+ test_files: []