litmus_paper 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MjFkOWE0OWYyNzFhOGZmNTgyN2ZmZGI0YzNiZWJhN2I1OTNjNzAwYQ==
5
+ data.tar.gz: !binary |-
6
+ NzNlMDI0OTAwMzk3MDQ3YjQyYmQ1ZDNjODMwZDZkMTRiYmRmZTQ5NA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NzQwZjVkNzA3NmNkZWE5YTM4NGM4ZmJkMmMzOGE5MzBmOWJmYWFiOTg2ZGMx
10
+ MjRmZTZlMzRjZDY1YTVkNTYxNjg1MDIzYzJjMWM4ZTRjYjJhYmUyYTZiNDdm
11
+ OTEwMGFlOWZlOGUyZjEyZjY4NmQ5NWZhMDBkOGQ1MDllMWFjMmI=
12
+ data.tar.gz: !binary |-
13
+ MTJkYmU2NzU0NDY2MmJiZDVhNWMyNzUzZDQyYmUzN2MwYWRlZjRiMmJlMzdj
14
+ MWE1ZWY0NzU5MTcwM2VhMjJhY2I3MDVkM2QzNWJhYjZhMmVjMWZiZDBiYTU2
15
+ NzJhMmE0NmFiNGVmMGIzOTk3YzdmZDQwMzc2OTcxZTE2Y2Q5YmM=
data/README.md CHANGED
@@ -179,6 +179,12 @@ Here are all the types of checks currently implemented:
179
179
  - `big_brother_service` (`Metric::BigBrotherService`): Used in conjunction with [Big Brother](https://github.com/braintree/big_brother), reports health based on the overall health of another load balanced service.
180
180
  * service
181
181
 
182
+ - `haproxy_backends_health` (`Metric::HaproxyBackendsHealth`): Checks UP/DOWN status across a set of servers in a Haproxy cluster and computes a litmus weight based on the HAProxy weights of the servers which have an UP status.
183
+ * weight (0-100)
184
+ * haproxy socket
185
+ * cluster
186
+ * timeout (defaults to 2s)
187
+
182
188
  ### HAProxy agent check configuration
183
189
 
184
190
  Litmus paper can also report health checks in HAProxy agent check format. The agent check functionality takes the health data from a service health check, and exposes it on a different port in the format HAProxy expects.
@@ -79,6 +79,11 @@ module LitmusPaper
79
79
  command = check_config.delete(:command)
80
80
  weight = check_config.delete(:weight)
81
81
  Metric::Script.new(command, weight, check_config)
82
+ when :haproxy_backends_health
83
+ weight = check_config.delete(:weight)
84
+ domain_socket = dep_config.delete(:domain_socket)
85
+ cluster = dep_config.delete(:cluster)
86
+ Metric::HaproxyBackendsHealth.new(weight, domain_socket, cluster, check_config)
82
87
  end
83
88
  end
84
89
  end
@@ -1,8 +1,10 @@
1
- require 'csv'
1
+ require 'litmus_paper/haproxy_util'
2
2
 
3
3
  module LitmusPaper
4
4
  module Dependency
5
5
  class HaproxyBackends
6
+ include LitmusPaper::HaproxyUtil
7
+
6
8
  def initialize(domain_socket, cluster, options = {})
7
9
  @domain_socket = domain_socket
8
10
  @cluster = cluster
@@ -10,8 +12,7 @@ module LitmusPaper
10
12
  end
11
13
 
12
14
  def available?
13
- stats = _parse_stats(_fetch_stats)
14
- backend = _find_backend(stats, @cluster)
15
+ backend = find_backend(@domain_socket, @timeout, @cluster)
15
16
 
16
17
  if backend['weight'].to_i == 0
17
18
  LitmusPaper.logger.info(
@@ -31,27 +32,6 @@ module LitmusPaper
31
32
  def to_s
32
33
  "Dependency::HaproxyBackends(#{@domain_socket}, #{@cluster})"
33
34
  end
34
-
35
- def _find_backend(stats, cluster)
36
- stats.detect do |line|
37
- line['# pxname'] == cluster && line['svname'] == 'BACKEND'
38
- end
39
- end
40
-
41
- def _parse_stats(csv)
42
- stats = CSV.parse(csv)
43
- headers = stats.shift
44
- stats.map { |stat| Hash[headers.zip(stat)] }
45
- end
46
-
47
- def _fetch_stats
48
- Timeout.timeout(@timeout) do
49
- UNIXSocket.open(@domain_socket) do |socket|
50
- socket.send("show stat\n", 0)
51
- socket.read
52
- end
53
- end
54
- end
55
35
  end
56
36
  end
57
37
  end
@@ -0,0 +1,39 @@
1
+ require 'csv'
2
+
3
+ module LitmusPaper
4
+ module HaproxyUtil
5
+ def find_servers(socket, timeout, cluster)
6
+ stats = _get_stats(socket, timeout)
7
+ stats.select do |line|
8
+ line['# pxname'] == cluster && line['svname'] !~ /BACKEND|FRONTEND/
9
+ end
10
+ end
11
+
12
+ def find_backend(socket, timeout, cluster)
13
+ stats = _get_stats(socket, timeout)
14
+ stats.detect do |line|
15
+ line['# pxname'] == cluster && line['svname'] == 'BACKEND'
16
+ end
17
+ end
18
+
19
+ def _get_stats(socket, timeout)
20
+ _parse_stats(_fetch_stats(socket, timeout))
21
+ end
22
+
23
+ def _fetch_stats(socket, timeout)
24
+ Timeout.timeout(timeout) do
25
+ UNIXSocket.open(socket) do |socket|
26
+ socket.send("show stat\n", 0)
27
+ socket.read
28
+ end
29
+ end
30
+ end
31
+
32
+ def _parse_stats(csv)
33
+ stats = CSV.parse(csv)
34
+ headers = stats.shift
35
+ stats.map { |stat| Hash[headers.zip(stat)] }
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,33 @@
1
+ require 'litmus_paper/haproxy_util'
2
+
3
+ module LitmusPaper
4
+ module Metric
5
+ class HaproxyBackendsHealth
6
+ include LitmusPaper::HaproxyUtil
7
+
8
+ def initialize(weight, domain_socket, cluster, options = {})
9
+ @weight = weight
10
+ @domain_socket = domain_socket
11
+ @cluster = cluster
12
+ @timeout = options.fetch(:timeout_seconds, 2)
13
+ end
14
+
15
+ def current_health
16
+ servers = find_servers(@domain_socket, @timeout, @cluster)
17
+
18
+ up_weight = servers
19
+ .select { |server| server["status"] == "UP" }
20
+ .inject(0) { |sum, server| sum + server["weight"].to_f }
21
+
22
+ total_weight = servers
23
+ .inject(0) { |sum, server| sum + server["weight"].to_f }
24
+
25
+ ((up_weight / total_weight) * @weight).to_i
26
+ end
27
+
28
+ def to_s
29
+ "Metric::HaproxyBackendsHealth(#{@weight}, #{@cluster})"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module LitmusPaper
2
- VERSION = "1.2.0"
2
+ VERSION = "1.3.0"
3
3
  end
data/lib/litmus_paper.rb CHANGED
@@ -22,11 +22,13 @@ require 'litmus_paper/dependency/haproxy_backends'
22
22
  require 'litmus_paper/dependency/http'
23
23
  require 'litmus_paper/dependency/script'
24
24
  require 'litmus_paper/dependency/tcp'
25
+ require 'litmus_paper/haproxy_util'
25
26
  require 'litmus_paper/health'
26
27
  require 'litmus_paper/logger'
27
28
  require 'litmus_paper/metric/big_brother_service'
28
29
  require 'litmus_paper/metric/constant_metric'
29
30
  require 'litmus_paper/metric/cpu_load'
31
+ require 'litmus_paper/metric/haproxy_backends_health'
30
32
  require 'litmus_paper/metric/internet_health'
31
33
  require 'litmus_paper/metric/script'
32
34
  require 'litmus_paper/service'
@@ -11,7 +11,7 @@ describe LitmusPaper::AgentCheckServer do
11
11
  port_open = false
12
12
  while ! port_open do
13
13
  begin
14
- TCPSocket.new('localhost', 9191)
14
+ TCPSocket.new('127.0.0.1', 9191)
15
15
  rescue StandardError => e
16
16
  sleep 0.1
17
17
  next
@@ -26,12 +26,12 @@ describe LitmusPaper::AgentCheckServer do
26
26
 
27
27
  describe "The agent-check text protocol" do
28
28
  it "returns the health from a passing test" do
29
- TCPSocket.open('localhost', 9191) do |s|
29
+ TCPSocket.open('127.0.0.1', 9191) do |s|
30
30
  s.gets.should match(/ready\tup\t\d+%\r\n/)
31
31
  end
32
32
  end
33
33
  it "returns the health from a failing test" do
34
- TCPSocket.open('localhost', 9192) do |s|
34
+ TCPSocket.open('127.0.0.1', 9192) do |s|
35
35
  s.gets.should match(/down\t0%\r\n/)
36
36
  end
37
37
  end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe LitmusPaper::Metric::HaproxyBackendsHealth do
4
+ describe "#current_health" do
5
+ before(:each) do
6
+ FileUtils.rm_rf("/tmp/stub-haproxy-stats")
7
+ system "spec/support/haproxy_test_socket /tmp/stub-haproxy-stats &"
8
+ sleep 1
9
+ end
10
+
11
+ it "should report as 33 if 2/3 of the nodes are down (yellow cluster)" do
12
+ health = LitmusPaper::Metric::HaproxyBackendsHealth.new(100, "/tmp/stub-haproxy-stats", "yellow_cluster")
13
+ health.current_health.should == 33
14
+ end
15
+
16
+
17
+ it "should report as 0 if all of the nodes are down (orange cluster)" do
18
+ health = LitmusPaper::Metric::HaproxyBackendsHealth.new(100, "/tmp/stub-haproxy-stats", "orange_cluster")
19
+ health.current_health.should == 0
20
+ end
21
+
22
+ it "should report as 100 if all of the nodes are up (green cluster)" do
23
+ health = LitmusPaper::Metric::HaproxyBackendsHealth.new(100, "/tmp/stub-haproxy-stats", "green_cluster")
24
+ health.current_health.should == 100
25
+ end
26
+
27
+ it "uses weight in calculating the health (yellow)" do
28
+ health = LitmusPaper::Metric::HaproxyBackendsHealth.new(50, "/tmp/stub-haproxy-stats", "yellow_cluster")
29
+ health.current_health.should == 16
30
+ end
31
+ end
32
+
33
+ describe "#to_s" do
34
+ it "is the name of the class and the cluster name " do
35
+ metric = LitmusPaper::Metric::HaproxyBackendsHealth.new(100, "/tmp/stub-haproxy-stats", "green_cluster")
36
+ metric.to_s.should == "Metric::HaproxyBackendsHealth(100, green_cluster)"
37
+ end
38
+ end
39
+ end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe LitmusPaper::Dependency::TCP do
3
+ describe LitmusPaper::Metric::InternetHealth do
4
4
 
5
5
  describe "#current_health" do
6
6
  before(:all) do
@@ -85,11 +85,11 @@ describe LitmusPaper::Dependency::TCP do
85
85
  internet_health = LitmusPaper::Metric::InternetHealth.new(
86
86
  100,
87
87
  [
88
- "127.0.0.1:6000",
89
- "127.0.0.1:6001",
90
88
  "127.0.0.1:6002",
91
89
  "127.0.0.1:6003",
92
90
  "127.0.0.1:6004",
91
+ "127.0.0.1:6005",
92
+ "127.0.0.1:6006",
93
93
  ],
94
94
  )
95
95
  internet_health.current_health.should == 0
@@ -25,6 +25,10 @@ orange,FRONTEND,,,0,0,2000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,5,0,,,,0,0,0,0,,,,,,,,
25
25
  orange_cluster,orange1,0,0,0,0,,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,0,35,0,,1,6,1,,0,,2,0,,0,L4OK,,5,,,,,,,0,,,,0,0,
26
26
  orange_cluster,orange2,0,0,0,0,,0,0,0,,0,,0,0,0,0,DOWN,1,1,0,0,0,35,0,,1,6,1,,0,,2,0,,0,L4OK,,5,,,,,,,0,,,,0,0,
27
27
  orange_cluster,BACKEND,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,DOWN,0,0,0,,0,35,0,,1,6,0,,0,,1,0,,0,,,,,,,,,,,,,,0,0,
28
+ green,FRONTEND,,,0,0,2000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,5,0,,,,0,0,0,0,,,,,,,,,,,0,0,0,,,
29
+ green_cluster,orange1,0,0,0,0,,0,0,0,,0,,0,0,0,0,UP,1,1,0,0,0,35,0,,1,6,1,,0,,2,0,,0,L4OK,,5,,,,,,,0,,,,0,0,
30
+ green_cluster,orange2,0,0,0,0,,0,0,0,,0,,0,0,0,0,UP,1,1,0,0,0,35,0,,1,6,1,,0,,2,0,,0,L4OK,,5,,,,,,,0,,,,0,0,
31
+ green_cluster,BACKEND,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,UP,0,0,0,,0,35,0,,1,6,0,,0,,1,0,,0,,,,,,,,,,,,,,0,0,
28
32
  DATA
29
33
  socket.close
30
34
  rescue Errno::EPIPE
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: litmus_paper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
5
- prerelease:
4
+ version: 1.3.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Braintreeps
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2018-04-24 00:00:00.000000000 Z
11
+ date: 2018-06-11 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: sinatra
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: remote_syslog_logger
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,7 +41,6 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: unicorn
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ~>
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ~>
60
53
  - !ruby/object:Gem::Version
@@ -62,7 +55,6 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: colorize
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ! '>='
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ! '>='
76
67
  - !ruby/object:Gem::Version
@@ -78,7 +69,6 @@ dependencies:
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: rspec
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
73
  - - ~>
84
74
  - !ruby/object:Gem::Version
@@ -86,7 +76,6 @@ dependencies:
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
80
  - - ~>
92
81
  - !ruby/object:Gem::Version
@@ -94,7 +83,6 @@ dependencies:
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: rack-test
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
87
  - - ~>
100
88
  - !ruby/object:Gem::Version
@@ -102,7 +90,6 @@ dependencies:
102
90
  type: :development
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
94
  - - ~>
108
95
  - !ruby/object:Gem::Version
@@ -110,7 +97,6 @@ dependencies:
110
97
  - !ruby/object:Gem::Dependency
111
98
  name: rake
112
99
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
100
  requirements:
115
101
  - - ~>
116
102
  - !ruby/object:Gem::Version
@@ -118,7 +104,6 @@ dependencies:
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
107
  requirements:
123
108
  - - ~>
124
109
  - !ruby/object:Gem::Version
@@ -126,7 +111,6 @@ dependencies:
126
111
  - !ruby/object:Gem::Dependency
127
112
  name: rake_commit
128
113
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
114
  requirements:
131
115
  - - ~>
132
116
  - !ruby/object:Gem::Version
@@ -134,7 +118,6 @@ dependencies:
134
118
  type: :development
135
119
  prerelease: false
136
120
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
121
  requirements:
139
122
  - - ~>
140
123
  - !ruby/object:Gem::Version
@@ -183,11 +166,13 @@ files:
183
166
  - lib/litmus_paper/dependency/http.rb
184
167
  - lib/litmus_paper/dependency/script.rb
185
168
  - lib/litmus_paper/dependency/tcp.rb
169
+ - lib/litmus_paper/haproxy_util.rb
186
170
  - lib/litmus_paper/health.rb
187
171
  - lib/litmus_paper/logger.rb
188
172
  - lib/litmus_paper/metric/big_brother_service.rb
189
173
  - lib/litmus_paper/metric/constant_metric.rb
190
174
  - lib/litmus_paper/metric/cpu_load.rb
175
+ - lib/litmus_paper/metric/haproxy_backends_health.rb
191
176
  - lib/litmus_paper/metric/internet_health.rb
192
177
  - lib/litmus_paper/metric/script.rb
193
178
  - lib/litmus_paper/service.rb
@@ -213,6 +198,7 @@ files:
213
198
  - spec/litmus_paper/metric/big_brother_service_spec.rb
214
199
  - spec/litmus_paper/metric/constant_metric_spec.rb
215
200
  - spec/litmus_paper/metric/cpu_load_spec.rb
201
+ - spec/litmus_paper/metric/haproxy_backends_health_spec.rb
216
202
  - spec/litmus_paper/metric/internet_health_spec.rb
217
203
  - spec/litmus_paper/metric/script_spec.rb
218
204
  - spec/litmus_paper/service_spec.rb
@@ -244,27 +230,26 @@ files:
244
230
  - spec/support/test.unicorn.config
245
231
  homepage: https://github.com/braintree/litmus_paper
246
232
  licenses: []
233
+ metadata: {}
247
234
  post_install_message:
248
235
  rdoc_options: []
249
236
  require_paths:
250
237
  - lib
251
238
  required_ruby_version: !ruby/object:Gem::Requirement
252
- none: false
253
239
  requirements:
254
240
  - - ! '>='
255
241
  - !ruby/object:Gem::Version
256
242
  version: '0'
257
243
  required_rubygems_version: !ruby/object:Gem::Requirement
258
- none: false
259
244
  requirements:
260
245
  - - ! '>='
261
246
  - !ruby/object:Gem::Version
262
247
  version: '0'
263
248
  requirements: []
264
249
  rubyforge_project:
265
- rubygems_version: 1.8.23
250
+ rubygems_version: 2.6.14
266
251
  signing_key:
267
- specification_version: 3
252
+ specification_version: 4
268
253
  summary: Backend health tester for HA Services, partner project of big_brother
269
254
  test_files:
270
255
  - spec/litmus_paper/agent_check_handler_spec.rb
@@ -282,6 +267,7 @@ test_files:
282
267
  - spec/litmus_paper/metric/big_brother_service_spec.rb
283
268
  - spec/litmus_paper/metric/constant_metric_spec.rb
284
269
  - spec/litmus_paper/metric/cpu_load_spec.rb
270
+ - spec/litmus_paper/metric/haproxy_backends_health_spec.rb
285
271
  - spec/litmus_paper/metric/internet_health_spec.rb
286
272
  - spec/litmus_paper/metric/script_spec.rb
287
273
  - spec/litmus_paper/service_spec.rb