Skip to content

Commit ed42302

Browse files
estolfopicandocodigo
authored andcommitted
[CLIENT] Update handling of publish_address in _nodes/http response
1 parent 39828ed commit ed42302

File tree

3 files changed

+294
-181
lines changed

3 files changed

+294
-181
lines changed

elasticsearch-transport/lib/elasticsearch/transport/transport/sniffer.rb

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ def hosts
3131
nodes = transport.perform_request('GET', '_nodes/http', {}, nil, nil,
3232
reload_on_failure: false).body
3333

34-
hosts = nodes['nodes'].map do |id,info|
34+
hosts = nodes['nodes'].map do |id, info|
3535
if info[PROTOCOL]
36-
host, port = info[PROTOCOL]['publish_address'].split(':')
36+
host, port = parse_publish_address(info[PROTOCOL]['publish_address'])
3737

3838
{ :id => id,
3939
:name => info['name'],
@@ -49,6 +49,29 @@ def hosts
4949
hosts
5050
end
5151
end
52+
53+
private
54+
55+
def parse_publish_address(publish_address)
56+
# publish_address is in the format hostname/ip:port
57+
if publish_address =~ /\//
58+
parts = publish_address.partition('/')
59+
[ parts[0], parse_address_port(parts[2])[1] ]
60+
else
61+
parse_address_port(publish_address)
62+
end
63+
end
64+
65+
def parse_address_port(publish_address)
66+
# address is ipv6
67+
if publish_address =~ /[\[\]]/
68+
if parts = publish_address.match(/\A\[(.+)\](?::(\d+))?\z/)
69+
[ parts[1], parts[2] ]
70+
end
71+
else
72+
publish_address.split(':')
73+
end
74+
end
5275
end
5376
end
5477
end
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
# Licensed to Elasticsearch B.V. under one or more contributor
2+
# license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright
4+
# ownership. Elasticsearch B.V. licenses this file to you under
5+
# the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
require 'spec_helper'
19+
20+
describe Elasticsearch::Transport::Transport::Sniffer do
21+
22+
let(:transport) do
23+
double('transport').tap do |t|
24+
allow(t).to receive(:perform_request).and_return(response)
25+
allow(t).to receive(:options).and_return(sniffer_timeout: 2)
26+
end
27+
end
28+
29+
let(:sniffer) do
30+
described_class.new(transport)
31+
end
32+
33+
let(:response) do
34+
double('response').tap do |r|
35+
allow(r).to receive(:body).and_return(raw_response)
36+
end
37+
end
38+
39+
let(:raw_response) do
40+
{ 'nodes' => { 'n1' => { 'http' => { 'publish_address' => publish_address } } } }
41+
end
42+
43+
let(:publish_address) do
44+
'127.0.0.1:9250'
45+
end
46+
47+
describe '#initialize' do
48+
49+
it 'has a transport instance' do
50+
expect(sniffer.transport).to be(transport)
51+
end
52+
53+
it 'inherits the sniffer timeout from the transport object' do
54+
expect(sniffer.timeout).to eq(2)
55+
end
56+
end
57+
58+
describe '#timeout' do
59+
60+
let(:sniffer) do
61+
described_class.new(double('transport', options: {}))
62+
end
63+
64+
before do
65+
sniffer.timeout = 3
66+
end
67+
68+
it 'allows the timeout to be configured' do
69+
expect(sniffer.timeout).to eq(3)
70+
end
71+
end
72+
73+
describe '#hosts' do
74+
75+
let(:hosts) do
76+
sniffer.hosts
77+
end
78+
79+
context 'when the entire response is parsed' do
80+
81+
let(:raw_response) do
82+
{
83+
"cluster_name" => "elasticsearch_test",
84+
"nodes" => {
85+
"N1" => {
86+
"name" => "Node 1",
87+
"transport_address" => "127.0.0.1:9300",
88+
"host" => "testhost1",
89+
"ip" => "127.0.0.1",
90+
"version" => "7.0.0",
91+
"roles" => [
92+
"master",
93+
"data",
94+
"ingest"
95+
],
96+
"attributes" => {
97+
"testattr" => "test"
98+
},
99+
"http" => {
100+
"bound_address" => [
101+
"[fe80::1]:9250",
102+
"[::1]:9250",
103+
"127.0.0.1:9250"
104+
],
105+
"publish_address" => "127.0.0.1:9250",
106+
"max_content_length_in_bytes" => 104857600
107+
}
108+
}
109+
}
110+
}
111+
end
112+
113+
it 'parses the id' do
114+
expect(sniffer.hosts[0][:id]).to eq('N1')
115+
end
116+
117+
it 'parses the name' do
118+
expect(sniffer.hosts[0][:name]).to eq('Node 1')
119+
end
120+
121+
it 'parses the version' do
122+
expect(sniffer.hosts[0][:version]).to eq('7.0.0')
123+
end
124+
125+
it 'parses the host' do
126+
expect(sniffer.hosts[0][:host]).to eq('127.0.0.1')
127+
end
128+
129+
it 'parses the port' do
130+
expect(sniffer.hosts[0][:port]).to eq('9250')
131+
end
132+
133+
it 'parses the roles' do
134+
expect(sniffer.hosts[0][:roles]).to eq(['master',
135+
'data',
136+
'ingest'])
137+
end
138+
139+
it 'parses the attributes' do
140+
expect(sniffer.hosts[0][:attributes]).to eq('testattr' => 'test')
141+
end
142+
end
143+
144+
context 'when the transport protocol does not match' do
145+
146+
let(:raw_response) do
147+
{ 'nodes' => { 'n1' => { 'foo' => { 'publish_address' => '127.0.0.1:9250' } } } }
148+
end
149+
150+
it 'does not parse the addresses' do
151+
expect(hosts).to eq([])
152+
end
153+
end
154+
155+
context 'when a list of nodes is returned' do
156+
157+
let(:raw_response) do
158+
{ 'nodes' => { 'n1' => { 'http' => { 'publish_address' => '127.0.0.1:9250' } },
159+
'n2' => { 'http' => { 'publish_address' => '127.0.0.1:9251' } } } }
160+
end
161+
162+
it 'parses the response' do
163+
expect(hosts.size).to eq(2)
164+
end
165+
166+
it 'correctly parses the hosts' do
167+
expect(hosts[0][:host]).to eq('127.0.0.1')
168+
expect(hosts[1][:host]).to eq('127.0.0.1')
169+
end
170+
171+
it 'correctly parses the ports' do
172+
expect(hosts[0][:port]).to eq('9250')
173+
expect(hosts[1][:port]).to eq('9251')
174+
end
175+
end
176+
177+
context 'when the host and port are an ip address and port' do
178+
179+
it 'parses the response' do
180+
expect(hosts.size).to eq(1)
181+
end
182+
183+
it 'correctly parses the host' do
184+
expect(hosts[0][:host]).to eq('127.0.0.1')
185+
end
186+
187+
it 'correctly parses the port' do
188+
expect(hosts[0][:port]).to eq('9250')
189+
end
190+
end
191+
192+
context 'when the host and port are a hostname and port' do
193+
194+
let(:publish_address) do
195+
'testhost1.com:9250'
196+
end
197+
198+
let(:hosts) do
199+
sniffer.hosts
200+
end
201+
202+
it 'parses the response' do
203+
expect(hosts.size).to eq(1)
204+
end
205+
206+
it 'correctly parses the host' do
207+
expect(hosts[0][:host]).to eq('testhost1.com')
208+
end
209+
210+
it 'correctly parses the port' do
211+
expect(hosts[0][:port]).to eq('9250')
212+
end
213+
end
214+
215+
context 'when the host and port are in the format: hostname/ip:port' do
216+
217+
let(:publish_address) do
218+
'example.com/127.0.0.1:9250'
219+
end
220+
221+
it 'parses the response' do
222+
expect(hosts.size).to eq(1)
223+
end
224+
225+
it 'uses the hostname' do
226+
expect(hosts[0][:host]).to eq('example.com')
227+
end
228+
229+
it 'correctly parses the port' do
230+
expect(hosts[0][:port]).to eq('9250')
231+
end
232+
end
233+
234+
context 'when the address is IPv6' do
235+
236+
let(:publish_address) do
237+
'[::1]:9250'
238+
end
239+
240+
it 'parses the response' do
241+
expect(hosts.size).to eq(1)
242+
end
243+
244+
it 'correctly parses the host' do
245+
expect(hosts[0][:host]).to eq('::1')
246+
end
247+
248+
it 'correctly parses the port' do
249+
expect(hosts[0][:port]).to eq('9250')
250+
end
251+
end
252+
253+
context 'when the transport has :randomize_hosts option' do
254+
255+
let(:raw_response) do
256+
{ 'nodes' => { 'n1' => { 'http' => { 'publish_address' => '127.0.0.1:9250' } },
257+
'n2' => { 'http' => { 'publish_address' => '127.0.0.1:9251' } } } }
258+
end
259+
260+
before do
261+
allow(transport).to receive(:options).and_return(randomize_hosts: true)
262+
end
263+
264+
it 'shuffles the list' do
265+
expect(hosts.size).to eq(2)
266+
end
267+
end
268+
end
269+
end

0 commit comments

Comments
 (0)