on_strum-healthcheck 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
# ![OnStrum::Healthcheck - Simple configurable application healthcheck rack middleware](https://repository-images.githubusercontent.com/769335579/9094eefe-bfc8-483d-9a65-e406d1eb92c6)
|
2
|
+
|
3
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/b4dc21883d489d67fbef/maintainability)](https://codeclimate.com/github/on-strum/ruby-on-strum-healthcheck/maintainability)
|
4
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/b4dc21883d489d67fbef/test_coverage)](https://codeclimate.com/github/on-strum/ruby-on-strum-healthcheck/test_coverage)
|
5
|
+
[![CircleCI](https://circleci.com/gh/on-strum/ruby-on-strum-healthcheck/tree/master.svg?style=svg)](https://circleci.com/gh/on-strum/ruby-on-strum-healthcheck/tree/master)
|
6
|
+
[![Gem Version](https://badge.fury.io/rb/ruby_healthcheck.svg)](https://badge.fury.io/rb/ruby_healthcheck)
|
7
|
+
[![Downloads](https://img.shields.io/gem/dt/ruby_healthcheck.svg?colorA=004d99&colorB=0073e6)](https://rubygems.org/gems/ruby_healthcheck)
|
8
|
+
[![GitHub](https://img.shields.io/github/license/on-strum/ruby-on-strum-healthcheck)](LICENSE.txt)
|
9
|
+
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v1.4%20adopted-ff69b4.svg)](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
|