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 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
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'elbping'
3
- s.version = '0.0.13'
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."
@@ -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, nameserver
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} using #{nameserver}"
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
@@ -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
@@ -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
@@ -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
- assert_equal [], ElbPing::Resolver.find_elb_nodes(tgt, DEFAULT_NS)
12
-
13
- # I think something internal to Resolv is returning nil in tcp mode
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, DEFAULT_NS)
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elbping
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.0.14
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: