healthier 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 711f2ef8a3f208c3e4a4cc710fc86f73ff049a1734e0726caca32ef2d3c597f0
4
- data.tar.gz: ceb81192506fb5d7132840da224ac48bdb6f31d216dc2867da3d2afca0bd5576
3
+ metadata.gz: eecccdf413d2d1d9f36ad797d3cbaae04f6e7d8e4dd4b625e45e87968005942b
4
+ data.tar.gz: 6b36f60acf3243c8bb6e0fb230043c0f938e71315de9cbedb814a4ac13b9eacc
5
5
  SHA512:
6
- metadata.gz: 4c2b4a07809bdb88f6bd292ba9b284c5b6612ca525c0929341d4757aa01a6b98a56c3c0e60a160859e8e1b93d7c41cf13dfe9f1946997ec038b15d46b3516b8f
7
- data.tar.gz: 8b260ec426e1544f745843ede0eaa38719aa08dd75636aa6a839a65412b7308d8bc2f0a90eba950779b76571d6b8117b9cb73de389861f24f6307fe335cc4731
6
+ metadata.gz: d45139aea688c64f0411b285c433c354447a2818ccba8d1dc49033a36dd825f9cdda0863fb863b1a6be6b5ea666b1ef67ab64847a30053f4fa57d2f6c54b8ec9
7
+ data.tar.gz: eb1e0cb5f18bc67aaa790f2724744514520f5f55b53892bb600056100effcc139e4a351e230e3740d7e0eb59d075e851afb260be75ad9a9e90f6d9c8b57e15f3
data/README.md CHANGED
@@ -33,25 +33,37 @@ $ gem install healthier
33
33
  ```
34
34
 
35
35
  This will generate these two files:
36
+
36
37
  1. config/healthier.yml
38
+
37
39
  ```yaml
38
40
  ---
39
41
  healthier:
40
42
  depends_on:
41
- # Uncomment accordingly
42
- # - name: 'postgresql'
43
- # - name: 'mongodb'
44
- # - name: 'redis'
45
- # - name: 'rabbitmq'
43
+ # Uncomment accordingly
44
+ # - name: 'postgresql'
45
+ # config: {}
46
+ # - name: 'mongodb'
47
+ # config: {}
48
+ # - name: 'redis'
49
+ # config: {}
50
+ # - name: 'rabbitmq'
51
+ # config: {}
46
52
  ```
53
+ NOTE: In future, config above will accept a hash each service's configuration
54
+
47
55
  2. config/initializers/healthier.rb
56
+
48
57
  ```ruby
49
58
  Healthier.setup do |config|
59
+ # If you don't specify auth_mechanism, then it defaults to http_basic.
60
+ # Currently, only http_basic and bearer_token are supported
61
+ config.auth_mechanism = 'bearer_token'
50
62
  config.depends_on = config.healthier.call
51
63
  end
52
64
  ```
53
65
 
54
- In your application routes.rb file:
66
+ In your application routes.rb file(namespace according to your need):
55
67
 
56
68
  ```ruby
57
69
  mount Healthier::Engine => '/healthier'
@@ -64,6 +76,23 @@ USERNAME: 'demouser'
64
76
  PASSWORD: 'demouser@2023'
65
77
  ```
66
78
 
79
+ ENVs for Bearer token authentication:
80
+
81
+ ```bash
82
+ BEARER_TOKEN: 'e66cfadb3ce37a714fdf3df237dcfded9ed9a0f9ccb09e6a744d731e9214bae6fac7bf6d27cab3969702b7aa54c81fe1cff1842ac03b3d5f1a918e1f5061dcb80b80363976ae5f3b916c793fdfa5283ce5f387286152d62e2dcaa5c8c0f857ceb2cda045'
83
+ ```
84
+
85
+ However, if you want to leave the API open, just set:
86
+
87
+ ```ruby
88
+ Healthier.auth_mechanism = :none
89
+ ```
90
+
91
+ Example Curl:
92
+ ```curl
93
+ curl -H "Bearer b5f3396a876e4f2ec828d11514c94d95d2f2330d251496a78cbe0e9bc330d775" -H "Content-Type: application/json" 'https://migros.selise.dev/api/v2/cnc_rsp/healthier/ping'
94
+ ```
95
+
67
96
  ## Contributing
68
97
 
69
98
  Contribution directions go here.
@@ -3,12 +3,5 @@
3
3
  module Healthier
4
4
  # ApplicationController
5
5
  class ApplicationController < ActionController::Base
6
- include ActionController::HttpAuthentication::Basic::ControllerMethods
7
-
8
- before_action :authenticate_request
9
-
10
- def authenticate_request
11
- BasicAuthService.authorize(self)
12
- end
13
6
  end
14
7
  end
@@ -3,8 +3,22 @@
3
3
  module Healthier
4
4
  # Controller for performing health checks
5
5
  class ChecksController < ApplicationController
6
+ include ActionController::HttpAuthentication::Basic::ControllerMethods
7
+
8
+ before_action :authenticate_request
9
+
6
10
  def ping
7
11
  render json: Healthier::Engine.ping!
8
12
  end
13
+
14
+ protected
15
+
16
+ def authenticate_request
17
+ api_authenticator.authenticate
18
+ end
19
+
20
+ def api_authenticator
21
+ Healthier::ApiAuthenticator.new(self)
22
+ end
9
23
  end
10
24
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Checkers
4
+ # Mongodb health checker
5
+ class MongodbChecker
6
+ class << self
7
+ def check
8
+ raise 'Please make sure you have Mongodb installed' unless defined?(::Mongo::Client)
9
+
10
+ begin
11
+ @client = Mongo::Client.new(
12
+ ENV.fetch('MONGO_DB_URI', nil) || ['localhost:27017'],
13
+ max_retries: 2,
14
+ retry_interval: 1
15
+ )
16
+ @client.command(ping: 1)
17
+ true
18
+ rescue Mongo::Error::SocketError, Mongo::Error::NoServerAvailable
19
+ false
20
+ ensure
21
+ @client&.close
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Checkers
4
+ # Postgres health checker
5
+ class PostgresqlChecker
6
+ class << self
7
+ def check
8
+ raise 'Please make sure you have Postgres installed' unless defined?(::ActiveRecord::Base)
9
+
10
+ begin
11
+ # @conn = ::PG.connect(dbname: ENV['DATABASE_NAME'])
12
+ # @conn.exec('SELECT 1')
13
+ @conn = ActiveRecord::Base.connection
14
+ true
15
+ rescue ::PG::ConnectionBad
16
+ false
17
+ ensure
18
+ @conn&.close
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Checkers
4
+ # Rabbitmq health checker
5
+ class RabbitmqChecker
6
+ class << self
7
+ def check
8
+ raise 'Please make sure you have RabbitMQ installed' unless defined?(::Bunny)
9
+
10
+ begin
11
+ @conn = ::Bunny.new
12
+ @conn.start
13
+ channel = @conn.create_channel
14
+ queue = channel.queue('health_check')
15
+ queue.publish('ping')
16
+ true
17
+ rescue ::Bunny::Exception, ::Bunny::TCPConnectionFailed, ::Bunny::PossibleAuthenticationFailureError
18
+ false
19
+ ensure
20
+ @conn&.close
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Checkers
4
+ # Redis health checker
5
+ class RedisChecker
6
+ class << self
7
+ def check
8
+ raise 'Please make sure you have Redis installed' unless defined?(::Redis)
9
+
10
+ begin
11
+ @redis = Redis.new
12
+ @redis.ping == 'PONG'
13
+ rescue Redis::CannotConnectError
14
+ false
15
+ ensure
16
+ @redis&.close
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -10,6 +10,9 @@ module Healthier
10
10
  # frozen_string_literal: true
11
11
 
12
12
  Healthier.setup do |config|
13
+ # Currently, there are :basic_auth(default), :bearer_token for API authentication
14
+ # But if you want to leave the API open, then just set auth_mechanism to :none to skip authentication
15
+ # config.auth_mechanism = :bearer_token
13
16
  config.depends_on = config.healthier.call
14
17
  end
15
18
  RUBY
@@ -22,9 +25,13 @@ module Healthier
22
25
  # Uncomment accordingly
23
26
  depends_on:
24
27
  # - name: 'postgresql'
28
+ # config: {}
25
29
  # - name: 'mongodb'
30
+ # config: {}
26
31
  # - name: 'redis'
32
+ # config: {}
27
33
  # - name: 'rabbitmq'
34
+ # config: {}
28
35
  YAML
29
36
  end
30
37
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Healthier
4
+ # Engine
5
+ class ApiAuthenticator
6
+ attr_accessor :controller
7
+
8
+ def initialize(controller)
9
+ @controller = controller
10
+ end
11
+
12
+ def authenticate
13
+ return true if Healthier.auth_mechanism == :none
14
+
15
+ send("authenticate_with_#{Healthier.auth_mechanism}")
16
+ end
17
+
18
+ def authenticate_with_bearer_token
19
+ controller.authenticate_with_http_token do |token, _options|
20
+ ENV['BEARER_TOKEN'] == token
21
+ end
22
+ end
23
+
24
+ def authenticate_with_basic_auth
25
+ controller.authenticate_or_request_with_http_basic do |username, password|
26
+ username == ENV['USERNAME'] && password == ENV['PASSWORD']
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,35 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../checkers/mongodb_checker'
4
+ require_relative '../checkers/postgresql_checker'
5
+ require_relative '../checkers/rabbitmq_checker'
6
+ require_relative '../checkers/redis_checker'
7
+
3
8
  module Healthier
4
9
  # Engine
5
10
  class Engine < ::Rails::Engine
6
11
  isolate_namespace Healthier
7
12
 
8
- PING_CONF = HashWithIndifferentAccess.new(
9
- {
10
- postgresql: {
11
- pinger: -> { ActiveRecord::Base.connection },
12
- message: 'PostgreSQL service is not running. Please check your connection'
13
- },
14
- mongodb: {
15
- pinger: -> { Mongoid.default_client.command(ping: 1) },
16
- message: 'MongoDB service is not running. Please check your connection'
17
- },
18
- redis: {
19
- pinger: -> { Redis.new },
20
- message: 'Redis service is not running. Please check your connection'
21
- },
22
- rabbitmq: {
23
- pinger: -> { Bunny.new },
24
- message: 'RabbitMQ service is not running. Please check your connection'
25
- }
26
- }
27
- )
28
-
29
- # TODO: Refactor this whole code
30
- SUCCESS = 200
31
- FAILURE = 400
32
-
33
13
  def ping!
34
14
  conf['depends_on'].each_with_object({}) do |dependant, obj|
35
15
  obj[dependant['name']] = ping_it(dependant['name'])
@@ -41,9 +21,15 @@ module Healthier
41
21
  end
42
22
 
43
23
  def ping_it(service)
44
- return { status: SUCCESS, message: 'pong' } if PING_CONF[service]['pinger'].call
24
+ checked = checker(service).check
25
+
26
+ return { status: Healthier::SUCCESS, message: 'pong' } if checked == true
27
+
28
+ { status: Healthier::FAILURE, message: "#{service.camelize} service is not running. Please check your connection" }
29
+ end
45
30
 
46
- { status: FAILURE, message: PING_CONF[service]['message'] }
31
+ def checker(service)
32
+ "::Checkers::#{service.camelize}Checker".constantize
47
33
  end
48
34
  end
49
35
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Healthier
4
4
  # MAJOR.MINOR.PATCH
5
- VERSION = '0.1.4'
5
+ VERSION = '0.1.6'
6
6
  end
data/lib/healthier.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'healthier/version'
4
4
  require 'healthier/engine'
5
+ require 'healthier/api_authenticator'
5
6
 
6
7
  # Healthier
7
8
  module Healthier
@@ -9,6 +10,10 @@ module Healthier
9
10
  yield self
10
11
  end
11
12
 
13
+ SUCCESS = 200
14
+ FAILURE = 503
15
+
12
16
  mattr_accessor :healthier, default: -> { YAML.load_file(Rails.root.join('config/healthier.yml')) }
17
+ mattr_accessor :auth_mechanism, default: 'basic_auth'
13
18
  mattr_accessor :depends_on, default: {}
14
19
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: healthier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nima Yonten
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-10 00:00:00.000000000 Z
11
+ date: 2023-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -36,10 +36,14 @@ files:
36
36
  - Rakefile
37
37
  - app/controllers/healthier/application_controller.rb
38
38
  - app/controllers/healthier/checks_controller.rb
39
- - app/services/basic_auth_service.rb
40
39
  - config/routes.rb
40
+ - lib/checkers/mongodb_checker.rb
41
+ - lib/checkers/postgresql_checker.rb
42
+ - lib/checkers/rabbitmq_checker.rb
43
+ - lib/checkers/redis_checker.rb
41
44
  - lib/generators/healthier/config_generator.rb
42
45
  - lib/healthier.rb
46
+ - lib/healthier/api_authenticator.rb
43
47
  - lib/healthier/engine.rb
44
48
  - lib/healthier/version.rb
45
49
  - lib/tasks/healthier_tasks.rake
@@ -51,6 +55,7 @@ metadata:
51
55
  homepage_uri: https://github.com/selisebt/healthier
52
56
  source_code_uri: https://github.com/selisebt/healthier
53
57
  changelog_uri: https://github.com/selisebt/healthier
58
+ rubygems_mfa_required: 'true'
54
59
  post_install_message:
55
60
  rdoc_options: []
56
61
  require_paths:
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # This module authenticates the API with Basic Auth
4
- class BasicAuthService
5
- def self.authorize(controller)
6
- controller.authenticate_or_request_with_http_basic do |username, password|
7
- username == ENV['USERNAME'] && password == ENV['PASSWORD']
8
- end
9
- end
10
- end