right_support 2.6.8 → 2.6.9
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.
@@ -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
|
|