elbping 0.0.13 → 0.0.14
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -3
- data/elbping.gemspec +1 -1
- data/lib/elbping/cli.rb +2 -8
- data/lib/elbping/display.rb +2 -1
- data/lib/elbping/resolver.rb +47 -3
- data/test/test_resolver.rb +4 -8
- metadata +1 -1
data/README.md
CHANGED
@@ -31,7 +31,6 @@ something like the following will work:
|
|
31
31
|
```
|
32
32
|
$ elbping
|
33
33
|
Usage: ./bin/elbping [options] <elb uri>
|
34
|
-
-N, --nameserver NAMESERVER Use NAMESERVER to perform DNS queries (default: ns-941.amazon.com)
|
35
34
|
-L, --verb-length LENGTH Use verb LENGTH characters long (default: 128)
|
36
35
|
-W, --timeout SECONDS Use timeout of SECONDS for HTTP requests (default: 10)
|
37
36
|
-w, --wait SECONDS Wait SECONDS between pings (default: 0)
|
@@ -52,7 +51,7 @@ something like the following will work:
|
|
52
51
|
4 requests, 4 responses, 0% loss
|
53
52
|
min/avg/max = 188/189/192 ms
|
54
53
|
--- total statistics ---
|
55
|
-
8 requests, 8 responses, 0% loss
|
54
|
+
8 requests, 8 responses, 0% loss, 2 nodes
|
56
55
|
min/avg/max = 188/189/192 ms
|
57
56
|
```
|
58
57
|
|
@@ -64,7 +63,6 @@ enviromment variables are checked and, if no command line argument
|
|
64
63
|
overrides it, its value is used in place of the default:
|
65
64
|
|
66
65
|
* ``PING_ELB_VERBLEN`` - Size of the HTTP verb to use when pinging an ELB
|
67
|
-
* ``PING_ELB_NS`` - DNS server to query the list of ELB nodes from
|
68
66
|
* ``PING_ELB_PINGCOUNT`` - The number of pings to send before exiting. Zero means never quit.
|
69
67
|
* ``PING_ELB_TIMEOUT`` - The connect and read timeouts to use when sending the request to the ELB node (in seconds)
|
70
68
|
* ``PING_ELB_WAIT`` - The amount of time (in seconds) to wait between volleys of pings
|
data/elbping.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'elbping'
|
3
|
-
s.version = '0.0.
|
3
|
+
s.version = '0.0.14'
|
4
4
|
s.date = '2013-08-13'
|
5
5
|
s.summary = "Small tool to 'ping' the nodes that make up an Amazon Elastic Load Balancer"
|
6
6
|
s.description = "elbping is a tool to ping all of the nodes behind an Amazon Elastic Load Balancer. It only works for ELBs in HTTP mode and works by triggering an HTTP 405 (METHOD NOT ALLOWED) error caused when the ELB receives a HTTP verb that is too long."
|
data/lib/elbping/cli.rb
CHANGED
@@ -16,7 +16,6 @@ module ElbPing
|
|
16
16
|
# Set up default options
|
17
17
|
OPTIONS = {}
|
18
18
|
OPTIONS[:verb_len] = ENV['PING_ELB_VERBLEN'] || 128
|
19
|
-
OPTIONS[:nameserver] = ENV['PING_ELB_NS'] || 'ns-941.amazon.com'
|
20
19
|
OPTIONS[:count] = ENV['PING_ELB_PINGCOUNT'] || 0
|
21
20
|
OPTIONS[:timeout] = ENV['PING_ELB_TIMEOUT'] || 10
|
22
21
|
OPTIONS[:wait] = ENV['PING_ELB_WAIT'] || 0
|
@@ -25,10 +24,6 @@ module ElbPing
|
|
25
24
|
PARSER = OptionParser.new do |opts|
|
26
25
|
opts.banner = "Usage: #{$0} [options] <elb uri>"
|
27
26
|
|
28
|
-
opts.on("-N NAMESERVER", "--nameserver NAMESERVER",
|
29
|
-
"Use NAMESERVER to perform DNS queries (default: #{OPTIONS[:nameserver]})") do |ns|
|
30
|
-
OPTIONS[:nameserver] = ns
|
31
|
-
end
|
32
27
|
opts.on("-L LENGTH", "--verb-length LENGTH", Integer,
|
33
28
|
"Use verb LENGTH characters long (default: #{OPTIONS[:verb_len]})") do |n|
|
34
29
|
OPTIONS[:verb_len] = n
|
@@ -88,11 +83,10 @@ module ElbPing
|
|
88
83
|
# Discover ELB nodes
|
89
84
|
#
|
90
85
|
# TODO: Perhaps some retry logic
|
91
|
-
nameserver = OPTIONS[:nameserver]
|
92
86
|
begin
|
93
|
-
nodes = ElbPing::Resolver.find_elb_nodes elb_uri.host
|
87
|
+
nodes = ElbPing::Resolver.find_elb_nodes elb_uri.host
|
94
88
|
rescue StandardError => e
|
95
|
-
ElbPing::Display.error "Unable to query DNS for #{elb_uri.host}
|
89
|
+
ElbPing::Display.error "Unable to query DNS for #{elb_uri.host}"
|
96
90
|
ElbPing::Display.debug e
|
97
91
|
exit(false)
|
98
92
|
end
|
data/lib/elbping/display.rb
CHANGED
@@ -28,6 +28,7 @@ module ElbPing
|
|
28
28
|
|
29
29
|
def self.debug(exception)
|
30
30
|
if ENV["DEBUG"]
|
31
|
+
self.out "DEBUG: #{exception.message}"
|
31
32
|
self.out "DEBUG: #{exception.backtrace}"
|
32
33
|
end
|
33
34
|
end
|
@@ -67,7 +68,7 @@ module ElbPing
|
|
67
68
|
|
68
69
|
loss_pct = (stats.total_loss * 100).to_i
|
69
70
|
self.out '--- total statistics ---'
|
70
|
-
self.out "#{stats.total[:requests]} requests, #{stats.total[:responses]} responses, #{loss_pct}% loss"
|
71
|
+
self.out "#{stats.total[:requests]} requests, #{stats.total[:responses]} responses, #{loss_pct}% loss, #{stats.nodes.size} nodes"
|
71
72
|
self.out "min/avg/max = #{stats.total[:latencies].min}/#{stats.total[:latencies].mean}/#{stats.total[:latencies].max} ms"
|
72
73
|
end
|
73
74
|
end
|
data/lib/elbping/resolver.rb
CHANGED
@@ -2,24 +2,68 @@
|
|
2
2
|
require 'resolv'
|
3
3
|
require 'elbping/tcp_dns.rb'
|
4
4
|
|
5
|
+
# TODO: Raise own exceptions
|
6
|
+
|
5
7
|
module ElbPing
|
6
8
|
# Handles all DNS resolution and, more specifically, ELB node discovery
|
7
9
|
module Resolver
|
8
10
|
|
11
|
+
# Find addresses authoritative DNS server
|
12
|
+
#
|
13
|
+
# Arguments:
|
14
|
+
# target: (string) ELB hostname
|
15
|
+
# timeout: (fixnum) in seconds
|
16
|
+
#
|
17
|
+
# Could raise:
|
18
|
+
# * Timeout::Error
|
19
|
+
# * ArgumentError
|
20
|
+
|
21
|
+
def self.find_elb_ns(target, timeout=5)
|
22
|
+
resp = nil
|
23
|
+
|
24
|
+
unless target.end_with? ".elb.amazonaws.com"
|
25
|
+
raise ArgumentError, "Not an Amazon ELB hostname"
|
26
|
+
end
|
27
|
+
|
28
|
+
Timeout::timeout(timeout) do
|
29
|
+
Resolv::DNS.open do |sysdns|
|
30
|
+
resp = sysdns.getresources target, Resolv::DNS::Resource::IN::NS
|
31
|
+
unless resp
|
32
|
+
raise ArgumentError, "Could not find Amazon nameserver for ELB"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
nameservers = resp.map { |ns| ns.name.to_s }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
9
39
|
# Resolve an ELB address to a list of node IPs. Should always return a list
|
10
40
|
# as long as the server responded, even if it's empty.
|
11
41
|
#
|
12
42
|
# Arguments:
|
13
43
|
# target: (string)
|
14
|
-
# nameservers: (array) of strings
|
15
44
|
# timeout: (fixnum)
|
16
45
|
#
|
17
46
|
# Could raise:
|
18
47
|
# * Timeout::Error
|
19
|
-
# *
|
48
|
+
# * ArgumentError
|
49
|
+
|
50
|
+
def self.find_elb_nodes(target, timeout=5)
|
51
|
+
raise ArgumentError, "Could not query DNS" if target.nil?
|
20
52
|
|
21
|
-
def self.find_elb_nodes(target, nameservers, timeout=5)
|
22
53
|
resp = nil
|
54
|
+
|
55
|
+
unless target.end_with? ".elb.amazonaws.com"
|
56
|
+
Timeout::timeout(timeout) do
|
57
|
+
Resolv::DNS.open do |sysdns|
|
58
|
+
resp = sysdns.getresources target, Resolv::DNS::Resource::IN::CNAME
|
59
|
+
cname = resp[0].name.to_s if resp and resp.size > 0
|
60
|
+
return find_elb_nodes(cname, timeout)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
nameservers = find_elb_ns target, timeout
|
66
|
+
|
23
67
|
Timeout::timeout(timeout) do
|
24
68
|
TcpDNS.open :nameserver => nameservers, :search => '', :ndots => 1 do |dns|
|
25
69
|
# TODO: Exceptions
|
data/test/test_resolver.rb
CHANGED
@@ -2,18 +2,14 @@
|
|
2
2
|
require 'test/unit'
|
3
3
|
require 'elbping/resolver.rb'
|
4
4
|
|
5
|
-
DEFAULT_NS = ENV['TEST_NS'] || 'ns-941.amazon.com'
|
6
5
|
DEFAULT_GOOD_ELB = ENV['TEST_GOOD_ELB'] || 'test-elb-868888812.us-east-1.elb.amazonaws.com' # feels dirty
|
7
6
|
|
8
7
|
class TestResolver< Test::Unit::TestCase
|
9
8
|
def test_bad_queries
|
10
9
|
["fake.amazonaws.com", "google.com", "nxdomain.asdf"].each { |tgt|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
#assert_raise Timeout::Error do
|
15
|
-
# ElbPing::Resolver.find_elb_nodes(tgt, DEFAULT_NS)
|
16
|
-
#end
|
10
|
+
assert_raise ArgumentError do
|
11
|
+
ElbPing::Resolver.find_elb_nodes(tgt)
|
12
|
+
end
|
17
13
|
}
|
18
14
|
end
|
19
15
|
|
@@ -21,7 +17,7 @@ class TestResolver< Test::Unit::TestCase
|
|
21
17
|
def test_good_query
|
22
18
|
resp = nil
|
23
19
|
assert_nothing_raised do
|
24
|
-
resp = ElbPing::Resolver.find_elb_nodes(DEFAULT_GOOD_ELB
|
20
|
+
resp = ElbPing::Resolver.find_elb_nodes(DEFAULT_GOOD_ELB)
|
25
21
|
end
|
26
22
|
# I don't actually care what the results are, only that they are a list
|
27
23
|
assert_equal resp.class, Array
|