on_strum-healthcheck 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 +7 -0
- data/.circleci/config.yml +213 -0
- data/.circleci/gemspecs/compatible +25 -0
- data/.circleci/gemspecs/latest +33 -0
- data/.circleci/linter_configs/.bundler-audit.yml +4 -0
- data/.circleci/linter_configs/.commitspell.yml +30 -0
- data/.circleci/linter_configs/.cspell.yml +31 -0
- data/.circleci/linter_configs/.fasterer.yml +4 -0
- data/.circleci/linter_configs/.lefthook.yml +44 -0
- data/.circleci/linter_configs/.markdownlint.yml +9 -0
- data/.circleci/linter_configs/.rubocop.yml +137 -0
- data/.circleci/linter_configs/.yamllint.yml +7 -0
- data/.circleci/scripts/changeloglint.sh +22 -0
- data/.circleci/scripts/commitspell.sh +22 -0
- data/.circleci/scripts/release.sh +69 -0
- data/.circleci/scripts/set_publisher_credentials.sh +12 -0
- data/.codeclimate.yml +17 -0
- data/.github/BRANCH_NAMING_CONVENTION.md +36 -0
- data/.github/DEVELOPMENT_ENVIRONMENT_GUIDE.md +26 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +28 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +27 -0
- data/.github/ISSUE_TEMPLATE/issue_report.md +32 -0
- data/.github/ISSUE_TEMPLATE/question.md +22 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +49 -0
- data/.gitignore +11 -0
- data/.reek.yml +39 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +9 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +48 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +224 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/on_strum/healthcheck/configuration.rb +141 -0
- data/lib/on_strum/healthcheck/core.rb +22 -0
- data/lib/on_strum/healthcheck/error/configuration/argument_type.rb +15 -0
- data/lib/on_strum/healthcheck/error/configuration/enpoint_pattern.rb +15 -0
- data/lib/on_strum/healthcheck/error/configuration/http_status_failure.rb +15 -0
- data/lib/on_strum/healthcheck/error/configuration/http_status_success.rb +15 -0
- data/lib/on_strum/healthcheck/error/configuration/not_callable_service.rb +15 -0
- data/lib/on_strum/healthcheck/error/configuration/not_configured.rb +15 -0
- data/lib/on_strum/healthcheck/error/configuration/unknown_service.rb +15 -0
- data/lib/on_strum/healthcheck/rack_middleware.rb +28 -0
- data/lib/on_strum/healthcheck/resolver.rb +85 -0
- data/lib/on_strum/healthcheck/version.rb +7 -0
- data/lib/on_strum/healthcheck.rb +25 -0
- data/on_strum-healthcheck.gemspec +28 -0
- metadata +164 -0
data/README.md
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
# 
|
2
|
+
|
3
|
+
[](https://codeclimate.com/github/on-strum/ruby-on-strum-healthcheck/maintainability)
|
4
|
+
[](https://codeclimate.com/github/on-strum/ruby-on-strum-healthcheck/test_coverage)
|
5
|
+
[](https://circleci.com/gh/on-strum/ruby-on-strum-healthcheck/tree/master)
|
6
|
+
[](https://badge.fury.io/rb/ruby_healthcheck)
|
7
|
+
[](https://rubygems.org/gems/ruby_healthcheck)
|
8
|
+
[](LICENSE.txt)
|
9
|
+
[](CODE_OF_CONDUCT.md)
|
10
|
+
|
11
|
+
Simple configurable application healthcheck rack middleware. This middleware allows you to embed healthcheck endpoints into your rack based application to perform healthcheck probes. Make your application compatible with [Docker](https://docs.docker.com/reference/dockerfile/#healthcheck)/[Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-liveness-http-request) healthchecks in a seconds.
|
12
|
+
|
13
|
+
## Table of Contents
|
14
|
+
|
15
|
+
- [Features](#features)
|
16
|
+
- [Requirements](#requirements)
|
17
|
+
- [Installation](#installation)
|
18
|
+
- [Configuring](#configuring)
|
19
|
+
- [Usage](#usage)
|
20
|
+
- [Rack](#rack)
|
21
|
+
- [Roda](#roda)
|
22
|
+
- [Hanami](#hanami)
|
23
|
+
- [Rails](#rails)
|
24
|
+
- [Contributing](#contributing)
|
25
|
+
- [License](#license)
|
26
|
+
- [Code of Conduct](#code-of-conduct)
|
27
|
+
- [Credits](#credits)
|
28
|
+
- [Versioning](#versioning)
|
29
|
+
- [Changelog](CHANGELOG.md)
|
30
|
+
|
31
|
+
## Features
|
32
|
+
|
33
|
+
- Built-in default configuration
|
34
|
+
- Configurable services for startup/liveness/readiness probes
|
35
|
+
- Configurable root endpoints namespace
|
36
|
+
- Configurable startup/liveness/readiness probes endpoints
|
37
|
+
- Configurable successful/failure response statuses
|
38
|
+
|
39
|
+
## Requirements
|
40
|
+
|
41
|
+
Ruby MRI 2.5.0+
|
42
|
+
|
43
|
+
## Installation
|
44
|
+
|
45
|
+
Add this line to your application's Gemfile:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
gem 'on_strum-healthcheck'
|
49
|
+
```
|
50
|
+
|
51
|
+
And then execute:
|
52
|
+
|
53
|
+
```bash
|
54
|
+
bundle
|
55
|
+
```
|
56
|
+
|
57
|
+
Or install it yourself as:
|
58
|
+
|
59
|
+
```bash
|
60
|
+
gem install on_strum-healthcheck
|
61
|
+
```
|
62
|
+
|
63
|
+
## Configuring
|
64
|
+
|
65
|
+
To start working with this gem, you must configure it first as in the example below:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# config/initializers/on_strum_healthcheck.rb
|
69
|
+
|
70
|
+
require 'on_strum/healthcheck'
|
71
|
+
|
72
|
+
OnStrum::Healthcheck.configure do |config|
|
73
|
+
# Optional parameter. The list of services that can be triggered
|
74
|
+
# during running probes. Each value of this hash should be callable
|
75
|
+
# and return boolean.
|
76
|
+
# It is equal to empty hash by default.
|
77
|
+
config.services = {
|
78
|
+
postges: -> { true },
|
79
|
+
redis: -> { true },
|
80
|
+
rabbit: -> { false }
|
81
|
+
}
|
82
|
+
|
83
|
+
# Optional parameter. The list of services that will be checked
|
84
|
+
# during running startup probe. As array items must be used an
|
85
|
+
# existing keys, defined in config.services.
|
86
|
+
# It is equal to empty array by default.
|
87
|
+
config.services_startup = %i[postges]
|
88
|
+
|
89
|
+
# Optional parameter. The list of services that will be checked
|
90
|
+
# during running liveness probe. As array items must be used an
|
91
|
+
# existing keys, defined in config.services.
|
92
|
+
# It is equal to empty array by default.
|
93
|
+
config.services_liveness = %i[redis]
|
94
|
+
|
95
|
+
# Optional parameter. The list of services that will be checked
|
96
|
+
# during running liveness probe. As array items must be used an
|
97
|
+
# existing keys, defined in config.services.
|
98
|
+
# It is equal to empty array by default.
|
99
|
+
config.services_readiness = %i[postges redis rabbit]
|
100
|
+
|
101
|
+
# Optional parameter. The name of middleware's root
|
102
|
+
# endpoints namespace. Use '/' if you want to use root
|
103
|
+
# namespace. It is equal to /healthcheck by default.
|
104
|
+
config.endpoints_namespace = '/application-healthcheck'
|
105
|
+
|
106
|
+
# Optional parameter. The startup endpoint path.
|
107
|
+
# It is equal to /startup by default.
|
108
|
+
config.endpoint_startup = '/startup-probe'
|
109
|
+
|
110
|
+
# Optional parameter. The liveness endpoint path.
|
111
|
+
# It is equal to /liveness by default.
|
112
|
+
config.endpoint_liveness = '/liveness-probe'
|
113
|
+
|
114
|
+
# Optional parameter. The readiness endpoint path.
|
115
|
+
# It is equal to /readiness by default.
|
116
|
+
config.endpoint_readiness = '/readiness-probe'
|
117
|
+
|
118
|
+
# Optional parameter. The HTTP successful status
|
119
|
+
# for startup probe. It is equal to 200 by default.
|
120
|
+
config.endpoint_startup_status_success = 201
|
121
|
+
|
122
|
+
# Optional parameter. The HTTP successful status
|
123
|
+
# for liveness probe. It is equal to 200 by default.
|
124
|
+
config.endpoint_liveness_status_success = 202
|
125
|
+
|
126
|
+
# Optional parameter. The HTTP successful status
|
127
|
+
# for readiness probe. It is equal to 200 by default.
|
128
|
+
config.endpoint_readiness_status_success = 203
|
129
|
+
|
130
|
+
# Optional parameter. The HTTP failure status
|
131
|
+
# for startup probe. It is equal to 500 by default.
|
132
|
+
config.endpoint_startup_status_failure = 501
|
133
|
+
|
134
|
+
# Optional parameter. The HTTP failure status
|
135
|
+
# for liveness probe. It is equal to 500 by default.
|
136
|
+
config.endpoint_liveness_status_failure = 502
|
137
|
+
|
138
|
+
# Optional parameter. The HTTP failure status
|
139
|
+
# for readiness probe. It is equal to 500 by default.
|
140
|
+
config.endpoint_readiness_status_failure = 503
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
144
|
+
## Usage
|
145
|
+
|
146
|
+
Please note, to start using this middleware you should configure `OnStrum::Healthcheck` before and then you should to add `OnStrum::Healthcheck::RackMiddleware` on the top of middlewares list.
|
147
|
+
|
148
|
+
### Rack
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
require 'rack'
|
152
|
+
require 'on_strum/healthcheck'
|
153
|
+
|
154
|
+
OnStrum::Healthcheck.configure
|
155
|
+
|
156
|
+
RackCascade = Rack::Builder.app do
|
157
|
+
use OnStrum::Healthcheck::RackMiddleware
|
158
|
+
run YourApplication
|
159
|
+
end
|
160
|
+
```
|
161
|
+
|
162
|
+
### Roda
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
require 'roda'
|
166
|
+
require 'on_strum/healthcheck'
|
167
|
+
|
168
|
+
OnStrum::Healthcheck.configure
|
169
|
+
|
170
|
+
class YourApplication < Roda
|
171
|
+
use OnStrum::Healthcheck::RackMiddleware
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
### Hanami
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
# config/initializers/on_strum_healthcheck.rb
|
179
|
+
|
180
|
+
require 'on_strum/healthcheck'
|
181
|
+
|
182
|
+
OnStrum::Healthcheck.configure
|
183
|
+
|
184
|
+
# config/environment.rb
|
185
|
+
|
186
|
+
Hanami.configure do
|
187
|
+
middleware.use MyRackMiddleware
|
188
|
+
end
|
189
|
+
```
|
190
|
+
|
191
|
+
### Rails
|
192
|
+
|
193
|
+
```ruby
|
194
|
+
# config/initializers/on_strum_healthcheck.rb
|
195
|
+
|
196
|
+
require 'on_strum/healthcheck'
|
197
|
+
|
198
|
+
OnStrum::Healthcheck.configure
|
199
|
+
|
200
|
+
# config/application.rb
|
201
|
+
|
202
|
+
config.middleware.use OnStrum::Healthcheck::RackMiddleware
|
203
|
+
```
|
204
|
+
|
205
|
+
## Contributing
|
206
|
+
|
207
|
+
Bug reports and pull requests are welcome on GitHub at <https://github.com/on-strum/ruby-on-strum-healthcheck>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. Please check the [open tickets](https://github.com/on-strum/ruby-on-strum-healthcheck/issues). Be sure to follow Contributor Code of Conduct below and our [Contributing Guidelines](CONTRIBUTING.md).
|
208
|
+
|
209
|
+
## License
|
210
|
+
|
211
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
212
|
+
|
213
|
+
## Code of Conduct
|
214
|
+
|
215
|
+
Everyone interacting in the `on_strum-healthcheck` project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](CODE_OF_CONDUCT.md).
|
216
|
+
|
217
|
+
## Credits
|
218
|
+
|
219
|
+
- [The Contributors](https://github.com/on-strum/ruby-on-strum-healthcheck/graphs/contributors) for code and awesome suggestions
|
220
|
+
- [The Stargazers](https://github.com/on-strum/ruby-on-strum-healthcheck/stargazers) for showing their support
|
221
|
+
|
222
|
+
## Versioning
|
223
|
+
|
224
|
+
`on_strum-healthcheck` uses [Semantic Versioning 2.0.0](https://semver.org)
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'on_strum/healthcheck'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnStrum
|
4
|
+
module Healthcheck
|
5
|
+
class Configuration
|
6
|
+
ATTRIBUTES = %i[
|
7
|
+
services
|
8
|
+
services_startup
|
9
|
+
services_liveness
|
10
|
+
services_readiness
|
11
|
+
endpoints_namespace
|
12
|
+
endpoint_startup
|
13
|
+
endpoint_liveness
|
14
|
+
endpoint_readiness
|
15
|
+
endpoint_startup_status_success
|
16
|
+
endpoint_liveness_status_success
|
17
|
+
endpoint_readiness_status_success
|
18
|
+
endpoint_startup_status_failure
|
19
|
+
endpoint_liveness_status_failure
|
20
|
+
endpoint_readiness_status_failure
|
21
|
+
].freeze
|
22
|
+
ENDPOINTS_NAMESPACE = '/healthcheck'
|
23
|
+
ENDPOINT_STARTUP = '/startup'
|
24
|
+
ENDPOINT_LIVENESS = '/liveness'
|
25
|
+
ENDPOINT_READINESS = '/readiness'
|
26
|
+
DEFAULT_HTTP_STATUS_SUCCESS = 200
|
27
|
+
DEFAULT_HTTP_STATUS_FAILURE = 500
|
28
|
+
AVILABLE_HTTP_STATUSES_SUCCESS = (DEFAULT_HTTP_STATUS_SUCCESS..226).freeze
|
29
|
+
AVILABLE_HTTP_STATUSES_FAILURE = (DEFAULT_HTTP_STATUS_FAILURE..511).freeze
|
30
|
+
|
31
|
+
Settings = ::Struct.new(*OnStrum::Healthcheck::Configuration::ATTRIBUTES, keyword_init: true) do
|
32
|
+
def update(&block)
|
33
|
+
return self unless block
|
34
|
+
|
35
|
+
tap(&block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader(*OnStrum::Healthcheck::Configuration::ATTRIBUTES)
|
40
|
+
|
41
|
+
def initialize(&block)
|
42
|
+
configuration_settings = build_configuration_settings(&block)
|
43
|
+
OnStrum::Healthcheck::Configuration::ATTRIBUTES.each do |attribute|
|
44
|
+
public_send(:"#{attribute}=", configuration_settings.public_send(attribute))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
OnStrum::Healthcheck::Configuration::ATTRIBUTES.each do |attribute|
|
49
|
+
define_method(:"#{attribute}=") do |argument|
|
50
|
+
validate_attribute(__method__, attribute, argument)
|
51
|
+
instance_variable_set(:"@#{attribute}", argument)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def build_configuration_settings(&block) # rubocop:disable Metrics/MethodLength
|
58
|
+
OnStrum::Healthcheck::Configuration::Settings.new(
|
59
|
+
services: {},
|
60
|
+
services_startup: [],
|
61
|
+
services_liveness: [],
|
62
|
+
services_readiness: [],
|
63
|
+
endpoints_namespace: OnStrum::Healthcheck::Configuration::ENDPOINTS_NAMESPACE,
|
64
|
+
endpoint_startup: OnStrum::Healthcheck::Configuration::ENDPOINT_STARTUP,
|
65
|
+
endpoint_liveness: OnStrum::Healthcheck::Configuration::ENDPOINT_LIVENESS,
|
66
|
+
endpoint_readiness: OnStrum::Healthcheck::Configuration::ENDPOINT_READINESS,
|
67
|
+
endpoint_startup_status_success: OnStrum::Healthcheck::Configuration::DEFAULT_HTTP_STATUS_SUCCESS,
|
68
|
+
endpoint_liveness_status_success: OnStrum::Healthcheck::Configuration::DEFAULT_HTTP_STATUS_SUCCESS,
|
69
|
+
endpoint_readiness_status_success: OnStrum::Healthcheck::Configuration::DEFAULT_HTTP_STATUS_SUCCESS,
|
70
|
+
endpoint_startup_status_failure: OnStrum::Healthcheck::Configuration::DEFAULT_HTTP_STATUS_FAILURE,
|
71
|
+
endpoint_liveness_status_failure: OnStrum::Healthcheck::Configuration::DEFAULT_HTTP_STATUS_FAILURE,
|
72
|
+
endpoint_readiness_status_failure: OnStrum::Healthcheck::Configuration::DEFAULT_HTTP_STATUS_FAILURE
|
73
|
+
).update(&block)
|
74
|
+
end
|
75
|
+
|
76
|
+
def validate_attribute(method, attribute, value) # rubocop:disable Metrics/AbcSize
|
77
|
+
raise_unless(OnStrum::Healthcheck::Error::Configuration::ArgumentType, method, *validator_argument_type(attribute, value))
|
78
|
+
case attribute
|
79
|
+
when OnStrum::Healthcheck::Configuration::ATTRIBUTES[0]
|
80
|
+
raise_unless(OnStrum::Healthcheck::Error::Configuration::NotCallableService, method, *validator_services_callable(value))
|
81
|
+
when *OnStrum::Healthcheck::Configuration::ATTRIBUTES[1..3]
|
82
|
+
raise_unless(OnStrum::Healthcheck::Error::Configuration::UnknownService, method, *validator_services_conformity(value))
|
83
|
+
when *OnStrum::Healthcheck::Configuration::ATTRIBUTES[4..7]
|
84
|
+
raise_unless(OnStrum::Healthcheck::Error::Configuration::EnpointPattern, method, *validator_endpoint(value))
|
85
|
+
when *OnStrum::Healthcheck::Configuration::ATTRIBUTES[8..10]
|
86
|
+
raise_unless(OnStrum::Healthcheck::Error::Configuration::HttpStatusSuccess, method, *validator_http_status_success(value))
|
87
|
+
when *OnStrum::Healthcheck::Configuration::ATTRIBUTES[11..13]
|
88
|
+
raise_unless(OnStrum::Healthcheck::Error::Configuration::HttpStatusFailure, method, *validator_http_status_failure(value))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def validator_argument_type(method_name, argument)
|
93
|
+
[
|
94
|
+
argument,
|
95
|
+
argument.is_a?(
|
96
|
+
case method_name
|
97
|
+
when :services then ::Hash
|
98
|
+
when *OnStrum::Healthcheck::Configuration::ATTRIBUTES[1..3] then ::Array
|
99
|
+
when *OnStrum::Healthcheck::Configuration::ATTRIBUTES[4..7] then ::String
|
100
|
+
when *OnStrum::Healthcheck::Configuration::ATTRIBUTES[8..13] then ::Integer
|
101
|
+
end
|
102
|
+
)
|
103
|
+
]
|
104
|
+
end
|
105
|
+
|
106
|
+
def validator_endpoint(argument)
|
107
|
+
[argument, argument[%r{\A/.*\z}]]
|
108
|
+
end
|
109
|
+
|
110
|
+
def validator_http_status_success(argument)
|
111
|
+
[argument, OnStrum::Healthcheck::Configuration::AVILABLE_HTTP_STATUSES_SUCCESS.include?(argument)]
|
112
|
+
end
|
113
|
+
|
114
|
+
def validator_http_status_failure(argument)
|
115
|
+
[argument, OnStrum::Healthcheck::Configuration::AVILABLE_HTTP_STATUSES_FAILURE.include?(argument)]
|
116
|
+
end
|
117
|
+
|
118
|
+
def validator_services_callable(services_to_check, target_service = nil)
|
119
|
+
result = services_to_check.all? do |service_name, service_context|
|
120
|
+
target_service = service_name
|
121
|
+
service_context.respond_to?(:call)
|
122
|
+
end
|
123
|
+
|
124
|
+
[target_service, result]
|
125
|
+
end
|
126
|
+
|
127
|
+
def validator_services_conformity(services_to_check, target_service = nil)
|
128
|
+
result = services_to_check.all? do |service_name|
|
129
|
+
target_service = service_name
|
130
|
+
services.key?(service_name)
|
131
|
+
end
|
132
|
+
|
133
|
+
[target_service, result]
|
134
|
+
end
|
135
|
+
|
136
|
+
def raise_unless(exception_class, argument_name, argument_context, condition)
|
137
|
+
raise exception_class.new(argument_context, argument_name) unless condition
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnStrum
|
4
|
+
module Healthcheck
|
5
|
+
module Error
|
6
|
+
module Configuration
|
7
|
+
require_relative 'error/configuration/argument_type'
|
8
|
+
require_relative 'error/configuration/unknown_service'
|
9
|
+
require_relative 'error/configuration/not_callable_service'
|
10
|
+
require_relative 'error/configuration/enpoint_pattern'
|
11
|
+
require_relative 'error/configuration/http_status_success'
|
12
|
+
require_relative 'error/configuration/http_status_failure'
|
13
|
+
require_relative 'error/configuration/not_configured'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
require_relative 'version'
|
18
|
+
require_relative 'configuration'
|
19
|
+
require_relative 'resolver'
|
20
|
+
require_relative 'rack_middleware'
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnStrum
|
4
|
+
module Healthcheck
|
5
|
+
module Error
|
6
|
+
module Configuration
|
7
|
+
ArgumentType = ::Class.new(::ArgumentError) do
|
8
|
+
def initialize(arg_value, arg_name)
|
9
|
+
super("#{arg_value} is not a valid #{arg_name}")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnStrum
|
4
|
+
module Healthcheck
|
5
|
+
module Error
|
6
|
+
module Configuration
|
7
|
+
EnpointPattern = ::Class.new(::ArgumentError) do
|
8
|
+
def initialize(arg_value, arg_name)
|
9
|
+
super("#{arg_value} does not match a valid enpoint pattern for #{arg_name}")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnStrum
|
4
|
+
module Healthcheck
|
5
|
+
module Error
|
6
|
+
module Configuration
|
7
|
+
HttpStatusFailure = ::Class.new(::ArgumentError) do
|
8
|
+
def initialize(arg_value, arg_name)
|
9
|
+
super("Status #{arg_value} is wrong HTTP failure status for #{arg_name}. It should be in the range 500-511")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnStrum
|
4
|
+
module Healthcheck
|
5
|
+
module Error
|
6
|
+
module Configuration
|
7
|
+
HttpStatusSuccess = ::Class.new(::ArgumentError) do
|
8
|
+
def initialize(arg_value, arg_name)
|
9
|
+
super("Status #{arg_value} is wrong HTTP successful status for #{arg_name}. It should be in the range 200-226")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnStrum
|
4
|
+
module Healthcheck
|
5
|
+
module Error
|
6
|
+
module Configuration
|
7
|
+
NotCallableService = ::Class.new(::ArgumentError) do
|
8
|
+
def initialize(service_name, services_setter)
|
9
|
+
super("Service #{service_name} is not callable. All values for #{services_setter} should be a callable objects")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnStrum
|
4
|
+
module Healthcheck
|
5
|
+
module Error
|
6
|
+
module Configuration
|
7
|
+
NotConfigured = ::Class.new(::RuntimeError) do
|
8
|
+
def initialize
|
9
|
+
super('The configuration is empty. Please use OnStrum::Healthcheck.configure before')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnStrum
|
4
|
+
module Healthcheck
|
5
|
+
module Error
|
6
|
+
module Configuration
|
7
|
+
UnknownService = ::Class.new(::ArgumentError) do
|
8
|
+
def initialize(service_name, services_setter)
|
9
|
+
super("Unknown #{service_name} service name for #{services_setter}. You should define it in config.services firstly")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnStrum
|
4
|
+
module Healthcheck
|
5
|
+
class RackMiddleware
|
6
|
+
def initialize(
|
7
|
+
app,
|
8
|
+
resolver = OnStrum::Healthcheck::Resolver,
|
9
|
+
counfigured = !!OnStrum::Healthcheck.configuration,
|
10
|
+
*
|
11
|
+
)
|
12
|
+
@app = app
|
13
|
+
@resolver = resolver
|
14
|
+
@counfigured = counfigured
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
raise OnStrum::Healthcheck::Error::Configuration::NotConfigured unless counfigured
|
19
|
+
|
20
|
+
resolver.call(env) || app.call(env)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :app, :resolver, :counfigured
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnStrum
|
4
|
+
module Healthcheck
|
5
|
+
class Resolver
|
6
|
+
require 'rack'
|
7
|
+
require 'securerandom'
|
8
|
+
require 'json'
|
9
|
+
|
10
|
+
PROBE_ENDPOINTS = %i[endpoint_startup endpoint_liveness endpoint_readiness].freeze
|
11
|
+
CONTENT_TYPE = { 'Content-Type' => 'application/json' }.freeze
|
12
|
+
JSONAPI_RESPONSE_TYPE = 'application-healthcheck'
|
13
|
+
ROOT_NAMESPACE = '/'
|
14
|
+
|
15
|
+
def self.call(rack_env)
|
16
|
+
new(rack_env).call
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(rack_env)
|
20
|
+
@request = ::Rack::Request.new(rack_env)
|
21
|
+
end
|
22
|
+
|
23
|
+
def call
|
24
|
+
return unless probe_name
|
25
|
+
|
26
|
+
[response_status, OnStrum::Healthcheck::Resolver::CONTENT_TYPE, [response_jsonapi]]
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :request
|
32
|
+
|
33
|
+
def configuration
|
34
|
+
OnStrum::Healthcheck.configuration
|
35
|
+
end
|
36
|
+
|
37
|
+
def root_namespace
|
38
|
+
@root_namespace ||= configuration.endpoints_namespace
|
39
|
+
end
|
40
|
+
|
41
|
+
def root_namespace?
|
42
|
+
root_namespace.eql?(OnStrum::Healthcheck::Resolver::ROOT_NAMESPACE)
|
43
|
+
end
|
44
|
+
|
45
|
+
OnStrum::Healthcheck::Resolver::PROBE_ENDPOINTS.each do |method|
|
46
|
+
define_method(method) do
|
47
|
+
target_endpoint = configuration.public_send(method)
|
48
|
+
root_namespace? ? target_endpoint : "#{root_namespace}#{target_endpoint}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def probe_name
|
53
|
+
@probe_name ||=
|
54
|
+
case request.path
|
55
|
+
when endpoint_startup then :startup
|
56
|
+
when endpoint_liveness then :liveness
|
57
|
+
when endpoint_readiness then :readiness
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def probe_result
|
62
|
+
@probe_result ||=
|
63
|
+
configuration.public_send(:"services_#{probe_name}").each_with_object({}) do |service_name, response|
|
64
|
+
response[service_name] = configuration.services[service_name].call
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def response_status
|
69
|
+
configuration.public_send(
|
70
|
+
probe_result.values.all? ? :"endpoint_#{probe_name}_status_success" : :"endpoint_#{probe_name}_status_failure"
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
def response_jsonapi
|
75
|
+
{
|
76
|
+
data: {
|
77
|
+
id: ::SecureRandom.uuid,
|
78
|
+
type: OnStrum::Healthcheck::Resolver::JSONAPI_RESPONSE_TYPE,
|
79
|
+
attributes: probe_result
|
80
|
+
}
|
81
|
+
}.to_json
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'healthcheck/core'
|
4
|
+
|
5
|
+
module OnStrum
|
6
|
+
module Healthcheck
|
7
|
+
class << self
|
8
|
+
def configuration(&block)
|
9
|
+
@configuration ||= begin
|
10
|
+
return unless block
|
11
|
+
|
12
|
+
OnStrum::Healthcheck::Configuration.new(&block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def configure(&block)
|
17
|
+
configuration(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset_configuration!
|
21
|
+
@configuration = nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|