right_support 2.6.17 → 2.7.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.
- data/.rspec +4 -0
- data/CHANGELOG.rdoc +37 -0
- data/Gemfile +29 -0
- data/Gemfile.lock +111 -0
- data/README.rdoc +2 -0
- data/Rakefile +62 -0
- data/VERSION +1 -0
- data/features/balancer_error_handling.feature +34 -0
- data/features/balancer_health_check.feature +33 -0
- data/features/continuous_integration.feature +51 -0
- data/features/continuous_integration_cucumber.feature +28 -0
- data/features/continuous_integration_rspec1.feature +28 -0
- data/features/continuous_integration_rspec2.feature +28 -0
- data/features/http_client_timeout.feature +19 -0
- data/features/serialization.feature +95 -0
- data/features/step_definitions/http_client_steps.rb +27 -0
- data/features/step_definitions/request_balancer_steps.rb +93 -0
- data/features/step_definitions/ruby_steps.rb +176 -0
- data/features/step_definitions/serialization_steps.rb +96 -0
- data/features/step_definitions/server_steps.rb +134 -0
- data/features/support/env.rb +138 -0
- data/features/support/file_utils_bundler_mixin.rb +45 -0
- data/lib/right_support/ci/java_cucumber_formatter.rb +22 -8
- data/lib/right_support/ci/java_spec_formatter.rb +26 -8
- data/lib/right_support/ci/rake_task.rb +3 -0
- data/lib/right_support/ci.rb +24 -0
- data/lib/right_support/crypto/signed_hash.rb +22 -0
- data/lib/right_support/data/serializer.rb +24 -2
- data/lib/right_support/net/address_helper.rb +20 -8
- data/lib/right_support/net/dns.rb +20 -8
- data/lib/right_support/net/http_client.rb +22 -0
- data/lib/right_support/net/request_balancer.rb +27 -21
- data/lib/right_support/net/s3_helper.rb +20 -8
- data/lib/right_support/net/ssl/open_ssl_patch.rb +22 -0
- data/lib/right_support/net/ssl.rb +20 -8
- data/lib/right_support/ruby/easy_singleton.rb +22 -0
- data/lib/right_support/ruby/object_extensions.rb +22 -0
- data/lib/right_support/ruby/string_extensions.rb +1 -1
- data/lib/right_support.rb +13 -10
- data/right_support.gemspec +180 -18
- data/right_support.rconf +8 -0
- data/spec/config/feature_set_spec.rb +83 -0
- data/spec/crypto/signed_hash_spec.rb +60 -0
- data/spec/data/hash_tools_spec.rb +471 -0
- data/spec/data/uuid_spec.rb +45 -0
- data/spec/db/cassandra_model_part1_spec.rb +84 -0
- data/spec/db/cassandra_model_part2_spec.rb +73 -0
- data/spec/db/cassandra_model_spec.rb +359 -0
- data/spec/fixtures/encrypted_priv_rsa.pem +30 -0
- data/spec/fixtures/good_priv_dsa.pem +12 -0
- data/spec/fixtures/good_priv_rsa.pem +15 -0
- data/spec/fixtures/good_pub_dsa.ssh +1 -0
- data/spec/fixtures/good_pub_rsa.pem +5 -0
- data/spec/fixtures/good_pub_rsa.ssh +1 -0
- data/spec/log/exception_logger_spec.rb +76 -0
- data/spec/log/filter_logger_spec.rb +8 -0
- data/spec/log/mixin_spec.rb +62 -0
- data/spec/log/multiplexer_spec.rb +54 -0
- data/spec/log/null_logger_spec.rb +36 -0
- data/spec/log/system_logger_spec.rb +92 -0
- data/spec/net/address_helper_spec.rb +57 -0
- data/spec/net/balancing/health_check_spec.rb +382 -0
- data/spec/net/balancing/round_robin_spec.rb +15 -0
- data/spec/net/balancing/sticky_policy_spec.rb +92 -0
- data/spec/net/dns_spec.rb +152 -0
- data/spec/net/http_client_spec.rb +171 -0
- data/spec/net/request_balancer_spec.rb +579 -0
- data/spec/net/s3_helper_spec.rb +160 -0
- data/spec/net/ssl_spec.rb +42 -0
- data/spec/net/string_encoder_spec.rb +58 -0
- data/spec/rack/log_setter_spec.rb +5 -0
- data/spec/rack/request_logger_spec.rb +68 -0
- data/spec/rack/request_tracker_spec.rb +5 -0
- data/spec/ruby/easy_singleton_spec.rb +72 -0
- data/spec/ruby/object_extensions_spec.rb +27 -0
- data/spec/ruby/string_extensions_spec.rb +98 -0
- data/spec/spec_helper.rb +181 -0
- data/spec/stats/activity_spec.rb +193 -0
- data/spec/stats/exceptions_spec.rb +123 -0
- data/spec/stats/helpers_spec.rb +603 -0
- data/spec/validation/openssl_spec.rb +37 -0
- data/spec/validation/ssh_spec.rb +39 -0
- metadata +218 -19
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RightSupport::Net::DNS do
|
4
|
+
include SpecHelper::SocketMocking
|
5
|
+
|
6
|
+
subject { RightSupport::Net::DNS } #the module itself
|
7
|
+
|
8
|
+
context :resolve_all_ip_addresses do
|
9
|
+
before(:all) do
|
10
|
+
@hostnames = ['1.1.1.1', '2.2.2.2', '3.3.3.3']
|
11
|
+
@hostnames .each do |hostname|
|
12
|
+
flexmock(Socket).should_receive(:getaddrinfo).with(hostname, 443, Socket::AF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP).once.and_return([[0,0,0,hostname]])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
it 'resolves all ip addresses for specified array of endpoints' do
|
16
|
+
@resolved_hostnames = subject.resolve_all_ip_addresses(@hostnames)
|
17
|
+
(@resolved_hostnames - @hostnames).should be_eql([])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
context :resolve do
|
23
|
+
context 'given default :retry => 3' do
|
24
|
+
let(:endpoint) { 'www.example.com' }
|
25
|
+
let(:output) { ['1.1.1.1', '2.2.2.2'] }
|
26
|
+
|
27
|
+
it 'retries SocketError' do
|
28
|
+
mock_getaddrinfo('www.example.com', SocketError)
|
29
|
+
mock_getaddrinfo('www.example.com', ['1.1.1.1', '2.2.2.2'])
|
30
|
+
|
31
|
+
subject.resolve(endpoint).should == output
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'stops retrying SocketError after three attempts' do
|
35
|
+
mock_getaddrinfo('www.example.com', SocketError, 3)
|
36
|
+
|
37
|
+
expect { subject.resolve(endpoint) }.to raise_error(SocketError)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'does not rescue other exceptions' do
|
41
|
+
mock_getaddrinfo('www.example.com', ArgumentError)
|
42
|
+
|
43
|
+
expect { subject.resolve(endpoint) }.to raise_error(ArgumentError)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'given :retry => 0' do
|
48
|
+
it 'does not retry SocketError' do
|
49
|
+
mock_getaddrinfo('www.example.com', SocketError)
|
50
|
+
|
51
|
+
expect { subject.resolve('www.example.com', :retry=>0) }.to raise_error(SocketError)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'given various endpoint formats' do
|
56
|
+
context 'e.g. a DNS hostname' do
|
57
|
+
let(:endpoint) { 'www.example.com' }
|
58
|
+
let(:output) { ['1.1.1.1', '2.2.2.2'] }
|
59
|
+
|
60
|
+
it 'resolves to IP addresses' do
|
61
|
+
mock_getaddrinfo('www.example.com', ['1.1.1.1', '2.2.2.2'])
|
62
|
+
subject.resolve(endpoint).should == output
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'e.g. an IPv4 address' do
|
67
|
+
let(:endpoint) { '127.0.0.1' }
|
68
|
+
let(:output) { ['127.0.0.1'] }
|
69
|
+
|
70
|
+
it 'resolves to the same address' do
|
71
|
+
mock_getaddrinfo('127.0.0.1', ['127.0.0.1'])
|
72
|
+
subject.resolve(endpoint).should == output
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'e.g. an HTTP URL' do
|
77
|
+
let(:endpoint) { 'http://www.example.com' }
|
78
|
+
let(:output) { ['http://1.1.1.1', 'http://2.2.2.2'] }
|
79
|
+
|
80
|
+
it 'resolves to URLs with addresses substituted' do
|
81
|
+
mock_getaddrinfo('www.example.com', ['1.1.1.1', '2.2.2.2'])
|
82
|
+
subject.resolve(endpoint).should == output
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'with a path component' do
|
86
|
+
let(:endpoint) { 'http://www.example.com/foo/bar' }
|
87
|
+
let(:output) { ['http://1.1.1.1/foo/bar', 'http://2.2.2.2/foo/bar'] }
|
88
|
+
|
89
|
+
it 'resolves to URLs with path component preserved' do
|
90
|
+
mock_getaddrinfo('www.example.com', ['1.1.1.1', '2.2.2.2'])
|
91
|
+
subject.resolve(endpoint).should == output
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# The double slash in a URI indicates that an authority follows. The authority
|
97
|
+
# is interpreted as a hostname for most URL schemes we are interested in. We
|
98
|
+
# can't deal with URLs unless they have a clear authority/hostname that we
|
99
|
+
# can substitute.
|
100
|
+
#
|
101
|
+
# For more information, see: http://tools.ietf.org/html/rfc3986#section-3
|
102
|
+
context 'e.g. a URI without an authority' do
|
103
|
+
let(:endpoint) { 'urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66' }
|
104
|
+
|
105
|
+
it 'raises URI::InvalidURIError' do
|
106
|
+
lambda do
|
107
|
+
subject.resolve(endpoint)
|
108
|
+
end.should raise_error(URI::InvalidURIError)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'e.g. several hostnames' do
|
113
|
+
let(:endpoints) { ['www.example.com', 'www.example.net'] }
|
114
|
+
let(:output) { ['1.1.1.1', '2.2.2.2', '3.3.3.3', '4.4.4.4'] }
|
115
|
+
|
116
|
+
it 'resolves to IP addresses' do
|
117
|
+
mock_getaddrinfo('www.example.com', ['1.1.1.1', '2.2.2.2'])
|
118
|
+
mock_getaddrinfo('www.example.net', ['3.3.3.3', '4.4.4.4'])
|
119
|
+
|
120
|
+
subject.resolve(endpoints).sort.should == output
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'e.g. several HTTP URLs' do
|
125
|
+
let(:endpoints) { ['http://www.example.com', 'http://www.example.net'] }
|
126
|
+
let(:output) { ['http://1.1.1.1', 'http://2.2.2.2', 'http://3.3.3.3', 'http://4.4.4.4'] }
|
127
|
+
|
128
|
+
it 'resolves to URLs with addresses substituted' do
|
129
|
+
mock_getaddrinfo('www.example.com', ['1.1.1.1', '2.2.2.2'])
|
130
|
+
mock_getaddrinfo('www.example.net', ['3.3.3.3', '4.4.4.4'])
|
131
|
+
|
132
|
+
subject.resolve(endpoints).sort.should == output.sort
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context :resolve_with_hostnames do
|
139
|
+
context 'given common inputs' do
|
140
|
+
let(:endpoints) { ['www.example1.com','www.example2.com'] }
|
141
|
+
let(:output) { {'www.example1.com'=>['1.1.1.1', '2.2.2.2'],
|
142
|
+
'www.example2.com'=>['3.3.3.3', '4.4.4.4']} }
|
143
|
+
|
144
|
+
it 'resolves to IP addresses' do
|
145
|
+
mock_getaddrinfo('www.example1.com', ['1.1.1.1', '2.2.2.2'])
|
146
|
+
mock_getaddrinfo('www.example2.com', ['3.3.3.3', '4.4.4.4'])
|
147
|
+
subject.resolve_with_hostnames(endpoints).should == output
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RightSupport::Net::HTTPClient do
|
4
|
+
it 'has a distinct method for common HTTP verbs' do
|
5
|
+
@http_client = RightSupport::Net::HTTPClient.new()
|
6
|
+
@http_client.should respond_to(:get)
|
7
|
+
@http_client.should respond_to(:post)
|
8
|
+
@http_client.should respond_to(:put)
|
9
|
+
@http_client.should respond_to(:delete)
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'with defaults passed to initializer' do
|
13
|
+
before(:all) do
|
14
|
+
@http_client = RightSupport::Net::HTTPClient.new(:open_timeout=>999, :timeout=>101010,
|
15
|
+
:headers=>{:moo=>:bah})
|
16
|
+
end
|
17
|
+
|
18
|
+
context :process_query_string do
|
19
|
+
it 'process nil url and params' do
|
20
|
+
@http_client.instance_eval { process_query_string }.should == ''
|
21
|
+
end
|
22
|
+
it 'process empty String params' do
|
23
|
+
url = '/moo'
|
24
|
+
params = ''
|
25
|
+
@http_client.instance_eval { process_query_string(url, params) }.should == '/moo'
|
26
|
+
end
|
27
|
+
it 'process params just with question mark' do
|
28
|
+
url = '/moo'
|
29
|
+
params = '?'
|
30
|
+
@http_client.instance_eval { process_query_string(url, params) }.should == '/moo'
|
31
|
+
end
|
32
|
+
it 'process String params with question mark in the beginning' do
|
33
|
+
url = '/moo'
|
34
|
+
params = '?a=b'
|
35
|
+
@http_client.instance_eval { process_query_string(url, params) }.should == '/moo?a=b'
|
36
|
+
end
|
37
|
+
it 'process String params without question mark in the beginning' do
|
38
|
+
url = '/moo'
|
39
|
+
params = 'a=b&c=d'
|
40
|
+
@http_client.instance_eval { process_query_string(url, params) }.should == '/moo?a=b&c=d'
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when converting with Addressable::URI' do
|
44
|
+
it 'process raw Hash params' do
|
45
|
+
url = '/moo'
|
46
|
+
params = {:a=>:b}
|
47
|
+
@http_client.instance_eval { process_query_string(url, params) }.should == '/moo?a=b'
|
48
|
+
end
|
49
|
+
it 'process Hash params with hash inside' do
|
50
|
+
url = '/moo'
|
51
|
+
params = {:a=>{:b=>:c}}
|
52
|
+
@http_client.instance_eval { process_query_string(url, params) }.should == '/moo?a[b]=c'
|
53
|
+
end
|
54
|
+
it 'process Hash params with array inside' do
|
55
|
+
url = '/moo'
|
56
|
+
params = {:a=>['b','c']}
|
57
|
+
@http_client.instance_eval { process_query_string(url, params) }.should == '/moo?a[0]=b&a[1]=c'
|
58
|
+
end
|
59
|
+
it 'process Hash params with nested array inside' do
|
60
|
+
url = '/moo'
|
61
|
+
params = {:a=>{:b=>:c,:d=>['e','f'],:g=>{:h=>'i'}},:j=>'k'}
|
62
|
+
@http_client.instance_eval { process_query_string(url, params) }.should ==
|
63
|
+
'/moo?a[b]=c&a[d][0]=e&a[d][1]=f&a[g][h]=i&j=k'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when converting directly' do
|
68
|
+
before(:each) do
|
69
|
+
flexmock(@http_client).should_receive(:require_succeeds?).with('addressable/uri').and_return(false)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'process raw Hash params' do
|
73
|
+
url = '/moo'
|
74
|
+
params = {:a=>:b}
|
75
|
+
@http_client.instance_eval { process_query_string(url, params) }.should == '/moo?a=b'
|
76
|
+
end
|
77
|
+
it 'process Hash params with hash inside' do
|
78
|
+
url = '/moo'
|
79
|
+
params = {:a=>{:b=>:c}}
|
80
|
+
@http_client.instance_eval { process_query_string(url, params) }.should == '/moo?a%5Bb%5D=c'
|
81
|
+
end
|
82
|
+
it 'process Hash params with array inside' do
|
83
|
+
url = '/moo'
|
84
|
+
params = {:a=>['b','c']}
|
85
|
+
@http_client.instance_eval { process_query_string(url, params) }.should == '/moo?a%5B%5D=b&a%5B%5D=c'
|
86
|
+
end
|
87
|
+
it 'process Hash params with nested array inside' do
|
88
|
+
url = '/moo'
|
89
|
+
params = {:a=>{:b=>:c,:d=>['e','f'],:g=>{:h=>'i'}},:j=>'k'}
|
90
|
+
@http_client.instance_eval { process_query_string(url, params) }.should ==
|
91
|
+
'/moo?a%5Bb%5D=c&a%5Bd%5D%5B%5D=e&a%5Bd%5D%5B%5D=f&a%5Bg%5D%5Bh%5D=i&j=k'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context :request do
|
97
|
+
it 'uses default options on every request' do
|
98
|
+
p = {:method=>:get,
|
99
|
+
:timeout=>101010,
|
100
|
+
:open_timeout=>999,
|
101
|
+
:url=>'/moo', :headers=>{:moo=>:bah}}
|
102
|
+
flexmock(RestClient::Request).should_receive(:execute).with(p)
|
103
|
+
@http_client.get('/moo')
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'allows defaults to be overridden' do
|
107
|
+
p = {:method=>:get,
|
108
|
+
:timeout=>101010,
|
109
|
+
:open_timeout=>3,
|
110
|
+
:url=>'/moo', :headers=>{:joe=>:blow}}
|
111
|
+
flexmock(RestClient::Request).should_receive(:execute).with(p)
|
112
|
+
@http_client.get('/moo', :open_timeout=>3, :headers=>{:joe=>:blow})
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context :request do
|
118
|
+
before(:each) do
|
119
|
+
r = 'this is a short mock REST response'
|
120
|
+
flexmock(RestClient::Request).should_receive(:execute).and_return(r).by_default
|
121
|
+
@http_client = RightSupport::Net::HTTPClient.new()
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'given just a URL' do
|
125
|
+
it 'succeeds' do
|
126
|
+
p = {:method=>:get,
|
127
|
+
:timeout=>RightSupport::Net::HTTPClient::DEFAULT_OPTIONS[:timeout],
|
128
|
+
:open_timeout=>RightSupport::Net::HTTPClient::DEFAULT_OPTIONS[:open_timeout],
|
129
|
+
:url=>'/moo', :headers=>{}}
|
130
|
+
flexmock(RestClient::Request).should_receive(:execute).with(p)
|
131
|
+
|
132
|
+
@http_client.get('/moo')
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'given a URL and headers' do
|
137
|
+
it 'succeeds' do
|
138
|
+
p = {:method=>:get,
|
139
|
+
:timeout=>RightSupport::Net::HTTPClient::DEFAULT_OPTIONS[:timeout],
|
140
|
+
:open_timeout=>RightSupport::Net::HTTPClient::DEFAULT_OPTIONS[:open_timeout],
|
141
|
+
:url=>'/moo', :headers=>{:mrm=>1, :blah=>:foo}}
|
142
|
+
flexmock(RestClient::Request).should_receive(:execute).with(p)
|
143
|
+
|
144
|
+
@http_client.get('/moo', {:headers => {:mrm=>1, :blah=>:foo}})
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
context 'given a timeout, no headers, and a URL' do
|
150
|
+
it 'succeeds' do
|
151
|
+
p = {:method=>:get,
|
152
|
+
:timeout=>42,
|
153
|
+
:open_timeout => RightSupport::Net::HTTPClient::DEFAULT_OPTIONS[:open_timeout],
|
154
|
+
:url=>'/moo', :headers=>{}}
|
155
|
+
flexmock(RestClient::Request).should_receive(:execute).with(p)
|
156
|
+
|
157
|
+
@http_client.get('/moo', {:timeout => 42})
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context 'given a URL and any other parameters' do
|
162
|
+
it 'succeeds' do
|
163
|
+
p = { :method=>:get, :timeout=>RightSupport::Net::HTTPClient::DEFAULT_OPTIONS[:timeout],
|
164
|
+
:url=>'/moo', :headers=>{},:open_timeout => 1, :payload=>{:foo => :bar} }
|
165
|
+
flexmock(RestClient::Request).should_receive(:execute).with(p)
|
166
|
+
|
167
|
+
@http_client.get('/moo', :open_timeout => 1, :payload=>{:foo => :bar})
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|