litmus_paper 1.2.0 → 1.3.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 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