philae 0.3.0 → 0.5.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/lib/philae/collection_probe.rb +54 -0
- data/lib/philae/docker_probe.rb +5 -5
- data/lib/philae/etcd_cluster_probe.rb +30 -0
- data/lib/philae/http_probe.rb +10 -1
- data/lib/philae/nsq_cluster_probe.rb +46 -0
- data/lib/philae/nsq_probe.rb +4 -3
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ffa3d30f51168d0d1ae72b1689900daf71eeb832aa9434f2c8d13040b962e156
|
4
|
+
data.tar.gz: e2eca87f43d64cf211f8d8705032f35378473c53e50dad83520bf408fbfcf857
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 186c411027e257cd9d2b482c2228e0bdc1cd8be2f68730b40ff23329ecd8b544afed4866fdad86625ecd57d3ce6a31a6627c4450110846885d8c6389e6005bae
|
7
|
+
data.tar.gz: 19377fb811659ff0a3339f223ff1502ed3678e2e9626476338811caa7e258c27676ae63f4ddb8fd1147a7bd683af5a0b6a700e386302892530637d44d4d75b75
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Philae
|
2
|
+
class CollectionProbe
|
3
|
+
def initialize(*args)
|
4
|
+
raise ArgumentError, "can't be instantiate, use specialized class"
|
5
|
+
end
|
6
|
+
|
7
|
+
def probes
|
8
|
+
raise ArgumentError, 'specialized class should implement :probes'
|
9
|
+
end
|
10
|
+
|
11
|
+
def check
|
12
|
+
results = []
|
13
|
+
result_queue = Queue.new
|
14
|
+
probes.each do |probe|
|
15
|
+
Thread.new do
|
16
|
+
begin
|
17
|
+
result = probe.check
|
18
|
+
rescue StandardError => e
|
19
|
+
result = {
|
20
|
+
healthy: false,
|
21
|
+
error: "probe #{probe.name} check failed: #{e.class} - #{e.message}",
|
22
|
+
}
|
23
|
+
end
|
24
|
+
result[:probe] = probe
|
25
|
+
result_queue.push result
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
loop do
|
30
|
+
results.push result_queue.pop
|
31
|
+
break if results.count == probes.length
|
32
|
+
end
|
33
|
+
|
34
|
+
failed_results = results.select do |result|
|
35
|
+
result[:healthy] == false
|
36
|
+
end
|
37
|
+
|
38
|
+
error = failed_results.map do |result|
|
39
|
+
msg = "#{result[:probe].name}: #{result[:comment]} "
|
40
|
+
msg += result[:code] if result[:code]
|
41
|
+
msg += result[:error] if result[:error]
|
42
|
+
next msg
|
43
|
+
end.join(', ')
|
44
|
+
|
45
|
+
if failed_results.count == probes.count
|
46
|
+
return { healthy: false, comment: "All #{name} nodes are down", error: error }
|
47
|
+
elsif failed_results.count > 0
|
48
|
+
return { healthy: true, comment: "#{failed_results.count} #{name} nodes are down: #{error}" }
|
49
|
+
else
|
50
|
+
return { healthy: true, comment: '' }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/philae/docker_probe.rb
CHANGED
@@ -4,19 +4,19 @@ module Philae
|
|
4
4
|
class DockerProbe
|
5
5
|
attr_reader :name
|
6
6
|
|
7
|
-
def initialize(name, endpoint = '/var/run/docker.sock', options =
|
7
|
+
def initialize(name, endpoint = '/var/run/docker.sock', options = {})
|
8
8
|
@name = name
|
9
9
|
@endpoint = endpoint
|
10
|
-
@docker_options = options
|
10
|
+
@docker_options = {read_timeout: 50, connect_timeout: 50}.merge(options)
|
11
11
|
end
|
12
12
|
|
13
13
|
def check
|
14
14
|
Docker.url = @endpoint
|
15
|
-
Docker.options = @docker_options
|
15
|
+
Docker.options = @docker_options
|
16
16
|
begin
|
17
17
|
Docker::Container.all
|
18
|
-
rescue
|
19
|
-
return { healthy: false, comment:
|
18
|
+
rescue => e
|
19
|
+
return { healthy: false, comment: "Unable to communicate with docker (#{e.message})" }
|
20
20
|
end
|
21
21
|
|
22
22
|
return { healthy: true, comment: '' }
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'collection_probe'
|
2
|
+
require_relative 'etcd_probe'
|
3
|
+
|
4
|
+
module Philae
|
5
|
+
class EtcdClusterProbe < CollectionProbe
|
6
|
+
attr_reader :name, :etcd_probes
|
7
|
+
|
8
|
+
# @param [Integer] read_timeout Timeout in second for the HTTP request
|
9
|
+
def initialize(name, endpoints, read_timeout: 1, cacert: nil, ssl_cert: nil, ssl_key: nil)
|
10
|
+
raise ArgumentError, 'empty endpoints' if endpoints.nil? || endpoints.empty?
|
11
|
+
|
12
|
+
@etcd_probes = endpoints.map do |endpoint|
|
13
|
+
endpoint_uri = URI(endpoint)
|
14
|
+
next EtcdProbe.new(
|
15
|
+
"#{name}-#{endpoint_uri.host}-#{endpoint_uri.port}",
|
16
|
+
endpoint_uri.host,
|
17
|
+
endpoint_uri.port,
|
18
|
+
read_timeout: read_timeout, cacert: cacert,
|
19
|
+
ssl_cert: ssl_cert, ssl_key: ssl_key,
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
@name = name
|
24
|
+
end
|
25
|
+
|
26
|
+
def probes
|
27
|
+
return @etcd_probes
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/philae/http_probe.rb
CHANGED
@@ -11,12 +11,13 @@ module Philae
|
|
11
11
|
# key: "path/to/key",
|
12
12
|
# ca: "path/to/ca"
|
13
13
|
# }
|
14
|
-
def initialize(name, uri, username = nil, password = nil, tls_context = nil)
|
14
|
+
def initialize(name, uri, username = nil, password = nil, tls_context = nil, timeout = nil)
|
15
15
|
@name = name
|
16
16
|
@uri = uri
|
17
17
|
@username = username
|
18
18
|
@password = password
|
19
19
|
@tls_context = tls_context
|
20
|
+
@timeout = timeout
|
20
21
|
end
|
21
22
|
|
22
23
|
def check
|
@@ -32,6 +33,14 @@ module Philae
|
|
32
33
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
33
34
|
end
|
34
35
|
end
|
36
|
+
|
37
|
+
if !@timeout.nil?
|
38
|
+
http.read_timeout = @timeout
|
39
|
+
http.open_timeout = @timeout
|
40
|
+
http.write_timeout = @timeout
|
41
|
+
http.ssl_timeout = @timeout
|
42
|
+
end
|
43
|
+
|
35
44
|
req = Net::HTTP::Get.new(uri)
|
36
45
|
req.basic_auth @username, @password if !@username.nil? || !@password.nil?
|
37
46
|
resp = http.start do |httpconn|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative 'collection_probe.rb'
|
2
|
+
require_relative 'nsq_probe.rb'
|
3
|
+
|
4
|
+
module Philae
|
5
|
+
class NSQClusterProbe < CollectionProbe
|
6
|
+
DEFAULT_HTTP_PORT = 4152
|
7
|
+
|
8
|
+
attr_reader :name, :nsq_probes
|
9
|
+
|
10
|
+
def self.new_from_env(name, opts = {})
|
11
|
+
if ENV['NSQD_HOSTS'].nil? || ENV['NSQD_HTTP_PORT'].nil?
|
12
|
+
raise ArgumentError, 'no NSQD_HOSTS and NSQD_HTTP_PORT defined'
|
13
|
+
end
|
14
|
+
|
15
|
+
tls_context = nil
|
16
|
+
if ENV['NSQD_TLS'] == 'true'
|
17
|
+
tls_context = {
|
18
|
+
cert: ENV['NSQD_TLS_CERT'],
|
19
|
+
key: ENV['NSQD_TLS_KEY'],
|
20
|
+
ca: ENV['NSQD_TLS_CACERT'],
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
http_hosts = ENV['NSQD_HOSTS'].split(',').map do |host|
|
25
|
+
host.split(':')[0] + ":#{ENV['NSQD_HTTP_PORT']}"
|
26
|
+
end
|
27
|
+
|
28
|
+
new(name, http_hosts, tls_context, opts)
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(name, hosts, tls_context = nil, opts = {})
|
32
|
+
raise ArgumentError, 'should have at least one host' if hosts.nil? || hosts.empty?
|
33
|
+
|
34
|
+
@name = name
|
35
|
+
@nsq_probes = hosts.map do |hostport|
|
36
|
+
host, port = hostport.split(':')
|
37
|
+
port = DEFAULT_HTTP_PORT if port.nil?
|
38
|
+
next Philae::NSQProbe.new("#{name}-#{host}-#{port}", host, port, tls_context, opts)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def probes
|
43
|
+
@nsq_probes
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/philae/nsq_probe.rb
CHANGED
@@ -2,19 +2,19 @@ require File.join File.dirname(__FILE__), 'http_probe.rb'
|
|
2
2
|
|
3
3
|
module Philae
|
4
4
|
class NSQProbe < HttpProbe
|
5
|
-
def self.new_from_env(name)
|
5
|
+
def self.new_from_env(name, opts = {})
|
6
6
|
if ENV["NSQD_TLS"] == "true"
|
7
7
|
return self.new(name, ENV["NSQD_HOST"], ENV["NSQD_HTTP_PORT"], {
|
8
8
|
cert: ENV["NSQD_TLS_CERT"],
|
9
9
|
key: ENV["NSQD_TLS_KEY"],
|
10
10
|
ca: ENV["NSQD_TLS_CACERT"],
|
11
|
-
})
|
11
|
+
}, opts)
|
12
12
|
else
|
13
13
|
return self.new(name, ENV["NSQD_HOST"], ENV["NSQD_HTTP_PORT"])
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
def initialize(name, host, port = 4151, tls_context = nil)
|
17
|
+
def initialize(name, host, port = 4151, tls_context = nil, opts = {})
|
18
18
|
@name = name
|
19
19
|
scheme = "http"
|
20
20
|
if !tls_context.nil?
|
@@ -22,6 +22,7 @@ module Philae
|
|
22
22
|
end
|
23
23
|
@uri = "#{scheme}://#{host}:#{port}/ping"
|
24
24
|
@tls_context = tls_context
|
25
|
+
@timeout = opts.fetch(:timeout, 5)
|
25
26
|
end
|
26
27
|
end
|
27
28
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: philae
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- leo@scalingo.com
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2022-01-03 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: docker-api
|
@@ -68,6 +68,20 @@ dependencies:
|
|
68
68
|
- - "~>"
|
69
69
|
- !ruby/object:Gem::Version
|
70
70
|
version: '2.4'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: pg
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - "~>"
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0.18'
|
78
|
+
type: :runtime
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - "~>"
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0.18'
|
71
85
|
description:
|
72
86
|
email: hello@scalingo.com
|
73
87
|
executables: []
|
@@ -75,10 +89,13 @@ extensions: []
|
|
75
89
|
extra_rdoc_files: []
|
76
90
|
files:
|
77
91
|
- lib/philae.rb
|
92
|
+
- lib/philae/collection_probe.rb
|
78
93
|
- lib/philae/docker_probe.rb
|
94
|
+
- lib/philae/etcd_cluster_probe.rb
|
79
95
|
- lib/philae/etcd_probe.rb
|
80
96
|
- lib/philae/http_probe.rb
|
81
97
|
- lib/philae/mongo_probe.rb
|
98
|
+
- lib/philae/nsq_cluster_probe.rb
|
82
99
|
- lib/philae/nsq_probe.rb
|
83
100
|
- lib/philae/pgsql_probe.rb
|
84
101
|
- lib/philae/philae_probe.rb
|
@@ -103,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
120
|
- !ruby/object:Gem::Version
|
104
121
|
version: '0'
|
105
122
|
requirements: []
|
106
|
-
rubygems_version: 3.
|
123
|
+
rubygems_version: 3.2.22
|
107
124
|
signing_key:
|
108
125
|
specification_version: 4
|
109
126
|
summary: Provide an health check API
|