right_support 2.6.8 → 2.6.9
Sign up to get free protection for your applications and to get access to all the features.
@@ -9,11 +9,21 @@
|
|
9
9
|
# License Agreement between RightScale.com, Inc. and the licensee.
|
10
10
|
|
11
11
|
require 'socket'
|
12
|
+
require 'uri'
|
12
13
|
|
13
14
|
module RightSupport::Net
|
14
|
-
|
15
15
|
module DNS
|
16
|
+
DEFAULT_RESOLVE_OPTIONS = {
|
17
|
+
:address_family => Socket::AF_INET,
|
18
|
+
:socket_type => Socket::SOCK_STREAM,
|
19
|
+
:protocol => Socket::IPPROTO_TCP,
|
20
|
+
:retry => 3
|
21
|
+
}
|
16
22
|
|
23
|
+
# Resolve a set of DNS hostnames to the individual IP addresses to which they map. Only handles
|
24
|
+
# IPv4 addresses.
|
25
|
+
#
|
26
|
+
# @deprecated due to broken error handling - do not use; please use #resolve instead!
|
17
27
|
def self.resolve_all_ip_addresses(hostnames)
|
18
28
|
ips = []
|
19
29
|
hostnames = [hostnames] unless hostnames.respond_to?(:each)
|
@@ -35,6 +45,74 @@ module RightSupport::Net
|
|
35
45
|
ips
|
36
46
|
end
|
37
47
|
|
48
|
+
# Perform DNS resolution on a set of endpoints, where the endpoints may be hostnames or URIs.
|
49
|
+
# Expand out the list to include one entry per distinct address that is assigned to a given
|
50
|
+
# hostname, but preserve other aspects of the endpoints --. URIs will remain URIs with the
|
51
|
+
# same protocol, path-info, and so forth, but the hostname component will be resolved to IP
|
52
|
+
# addresses and the URI will be duplicated in the output, once for each distinct IP address.
|
53
|
+
#
|
54
|
+
# Although this method does accept IPv4 dotted-quad addresses as input, it does not accept
|
55
|
+
# IPv6 addresses. However, given hostnames or URIs as input, one _can_ resolve the hostnames
|
56
|
+
# to IPv6 addresses by specifying the appropriate address_family in the options.
|
57
|
+
#
|
58
|
+
# It should never be necessary to specify a different :socket_type or :protocol, but these
|
59
|
+
# options are exposed just in case.
|
60
|
+
#
|
61
|
+
# @param [Array<String>] endpoints a mixed list of hostnames, IPv4 addresses or URIs that contain them
|
62
|
+
# @option opts [Integer] :retry number of times to retry SocketError; default is 3
|
63
|
+
# @option opts [Integer] :address_family what kind of IP addresses to resolve; default is Socket::AF_INET (IPv4)
|
64
|
+
# @option opts [Integer] :socket_type socket-type context to pass to getaddrinfo, default is Socket::SOCK_STREAM
|
65
|
+
# @option opts [Integer] :protocol protocol context to pass to getaddrinfo, default is Socket::IPPROTO_TCP
|
66
|
+
#
|
67
|
+
# @return [Array<String>] larger list of endpoints with all hostnames resolved to IP addresses
|
68
|
+
#
|
69
|
+
# @raise URI::InvalidURIError if endpoints contains an invalid or URI
|
70
|
+
# @raise SocketError if endpoints contains an invalid or unresolvable hostname
|
71
|
+
def self.resolve(endpoints, opts={})
|
72
|
+
opts = DEFAULT_RESOLVE_OPTIONS.merge(opts)
|
73
|
+
endpoints = [endpoints] unless endpoints.respond_to?(:each)
|
74
|
+
|
75
|
+
resolved_endpoints = []
|
76
|
+
retries = 0
|
77
|
+
|
78
|
+
endpoints.each do |endpoint|
|
79
|
+
begin
|
80
|
+
if endpoint.include?(':')
|
81
|
+
# It contains a colon, therefore it must be a URI -- we don't support IPv6
|
82
|
+
uri = URI.parse(endpoint)
|
83
|
+
hostname = uri.host
|
84
|
+
raise URI::InvalidURIError, "Could not parse host component of URI" unless hostname
|
85
|
+
|
86
|
+
infos = Socket.getaddrinfo(hostname, nil,
|
87
|
+
opts[:address_family], opts[:socket_type], opts[:protocol])
|
88
|
+
|
89
|
+
infos.each do |info|
|
90
|
+
transformed_uri = uri.dup
|
91
|
+
transformed_uri.host = info[3]
|
92
|
+
resolved_endpoints << transformed_uri.to_s
|
93
|
+
end
|
94
|
+
else
|
95
|
+
# No colon; it's a hostname or IP address
|
96
|
+
infos = Socket.getaddrinfo(endpoint, nil,
|
97
|
+
opts[:address_family], opts[:socket_type], opts[:protocol])
|
98
|
+
|
99
|
+
infos.each do |info|
|
100
|
+
resolved_endpoints << info[3]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
rescue SocketError => e
|
104
|
+
retries += 1
|
105
|
+
if retries < opts[:retry]
|
106
|
+
retry
|
107
|
+
else
|
108
|
+
raise e
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
resolved_endpoints
|
114
|
+
end
|
115
|
+
|
38
116
|
end
|
39
117
|
end
|
40
118
|
|
@@ -112,12 +112,13 @@ module RightSupport::Net
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def resolve(endpoints)
|
115
|
-
|
115
|
+
resolved_endpoints = RightSupport::Net::DNS.resolve(endpoints)
|
116
116
|
@resolved_at = Time.now.to_i
|
117
|
-
endpoints
|
117
|
+
logger.info("RequestBalancer: resolved #{endpoints.inspect} to #{resolved_endpoints.inspect}")
|
118
|
+
resolved_endpoints
|
118
119
|
end
|
119
120
|
|
120
|
-
def
|
121
|
+
def need_resolve?
|
121
122
|
@options[:resolve] && Time.now.to_i - @resolved_at > @options[:resolve]
|
122
123
|
end
|
123
124
|
|
@@ -125,12 +126,20 @@ module RightSupport::Net
|
|
125
126
|
# creation time; however, the ordering of the endpoints does not change thereafter
|
126
127
|
# and the sequence is tried from the beginning for every request.
|
127
128
|
#
|
129
|
+
# If you pass the :resolve option, then the list of endpoints is treated as a list
|
130
|
+
# of hostnames (or URLs containing hostnames) and the list is expanded out into a
|
131
|
+
# larger list with each hostname replaced by several entries, one for each of its IP
|
132
|
+
# addresses. If a single DNS hostname is associated with multiple A records, the
|
133
|
+
# :resolve option allows the balancer to treat each backing server as a distinct
|
134
|
+
# endpoint with its own health state, etc.
|
135
|
+
#
|
128
136
|
# === Parameters
|
129
137
|
# endpoints(Array):: a set of network endpoints (e.g. HTTP URLs) to be load-balanced
|
130
138
|
#
|
131
139
|
# === Options
|
132
140
|
# retry:: a Class, array of Class or decision Proc to determine whether to keep retrying; default is to try all endpoints
|
133
141
|
# fatal:: a Class, array of Class, or decision Proc to determine whether an exception is fatal and should not be retried
|
142
|
+
# resolve(Integer):: how often to re-resolve DNS hostnames of endpoints; default is nil (never resolve)
|
134
143
|
# on_exception(Proc):: notification hook that accepts three arguments: whether the exception is fatal, the exception itself,
|
135
144
|
# and the endpoint for which the exception happened
|
136
145
|
# health_check(Proc):: callback that allows balancer to check an endpoint health; should raise an exception if the endpoint
|
@@ -197,7 +206,8 @@ module RightSupport::Net
|
|
197
206
|
# Return the first non-nil value provided by the block.
|
198
207
|
def request
|
199
208
|
raise ArgumentError, "Must call this method with a block" unless block_given?
|
200
|
-
|
209
|
+
|
210
|
+
if need_resolve?
|
201
211
|
@ips = self.resolve(@endpoints)
|
202
212
|
@policy.set_endpoints(@ips)
|
203
213
|
end
|
@@ -9,10 +9,12 @@
|
|
9
9
|
# License Agreement between RightScale.com, Inc. and the licensee.
|
10
10
|
|
11
11
|
module RightSupport::Net
|
12
|
-
# Class provides S3 functionality.
|
12
|
+
# Class that provides S3 functionality.
|
13
13
|
# As part of RightSupport S3Helper does not include Rightscale::S3 and Encryptor modules.
|
14
14
|
# This modules must be included in application.
|
15
15
|
#
|
16
|
+
# @deprecated do not use; please use RightServices::Util::S3Storage instead!
|
17
|
+
#
|
16
18
|
# Example:
|
17
19
|
#
|
18
20
|
# require 'right_support'
|
data/right_support.gemspec
CHANGED
@@ -7,8 +7,8 @@ spec = Gem::Specification.new do |s|
|
|
7
7
|
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
8
8
|
|
9
9
|
s.name = 'right_support'
|
10
|
-
s.version = '2.6.
|
11
|
-
s.date = '
|
10
|
+
s.version = '2.6.9'
|
11
|
+
s.date = '2013-01-01'
|
12
12
|
|
13
13
|
s.authors = ['Tony Spataro', 'Sergey Sergyenko', 'Ryan Williamson', 'Lee Kirchhoff', 'Sergey Enin', 'Alexey Karpik', 'Scott Messier']
|
14
14
|
s.email = 'support@rightscale.com'
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 5
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 2.6.
|
9
|
+
- 9
|
10
|
+
version: 2.6.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tony Spataro
|
@@ -21,7 +21,7 @@ autorequire:
|
|
21
21
|
bindir: bin
|
22
22
|
cert_chain: []
|
23
23
|
|
24
|
-
date:
|
24
|
+
date: 2013-01-01 00:00:00 -08:00
|
25
25
|
default_executable:
|
26
26
|
dependencies: []
|
27
27
|
|