Support for publish_address as hostname/ip:port (#804)

This commit is contained in:
Tomas Della Vedova
2019-04-08 17:13:44 +02:00
committed by GitHub
parent 5794ad54e4
commit 5af9ec1040
6 changed files with 159 additions and 37 deletions

View File

@ -127,7 +127,7 @@ export default class ConnectionPool {
* @param {object} nodes
* @returns {array} hosts
*/
nodesToHost(nodes: any): any[];
nodesToHost(nodes: any, protocol: string): any[];
/**
* Transforms an url string to a host object
*

View File

@ -332,18 +332,33 @@ class ConnectionPool {
* @param {object} nodes
* @returns {array} hosts
*/
nodesToHost (nodes) {
nodesToHost (nodes, protocol) {
const ids = Object.keys(nodes)
const hosts = []
for (var i = 0, len = ids.length; i < len; i++) {
const node = nodes[ids[i]]
// If there is no protocol in
// the `publish_address` new URL wil throw
// the `publish_address` new URL will throw
// the publish_address can have two forms:
// - ip:port
// - hostname/ip:port
// if we encounter the second case, we should
// use the hostname instead of the ip
var address = node.http.publish_address
const hostAndIpRegex = /^[a-z0-9_.-]*\/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/gi
const match = address.match(hostAndIpRegex)
if (match !== null) {
const ipRegex = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/
const ip = address.match(ipRegex)[0]
// extract the hostname, the -1 at the end removes the final /
const hostname = address.slice(0, address.indexOf(ip) - 1)
const port = address.split(':')[1]
address = `${hostname}:${port}`
}
address = address.slice(0, 4) === 'http'
? address
: 'http://' + address
: `${protocol}//${address}`
const roles = node.roles.reduce((acc, role) => {
acc[role] = true
return acc

View File

@ -353,7 +353,8 @@ class Transport {
}
debug('Sniffing ended successfully', result.body)
const hosts = this.connectionPool.nodesToHost(result.body.nodes)
const protocol = result.meta.connection.url.protocol || 'http:'
const hosts = this.connectionPool.nodesToHost(result.body.nodes, protocol)
this.connectionPool.update(hosts)
result.meta.sniff = { hosts, reason }

View File

@ -93,6 +93,39 @@ test('Should update the connection pool', t => {
})
})
test('Should handle hostnames in publish_address', t => {
t.plan(10)
buildCluster({ hostPublishAddress: true }, ({ nodes, shutdown }) => {
const client = new Client({
node: nodes[Object.keys(nodes)[0]].url
})
t.strictEqual(client.connectionPool.connections.size, 1)
client.on(events.SNIFF, (err, request) => {
t.error(err)
t.strictEqual(
request.meta.sniff.reason,
Transport.sniffReasons.DEFAULT
)
})
// run the sniffer
client.transport.sniff((err, hosts) => {
t.error(err)
t.strictEqual(hosts.length, 4)
for (var i = 0; i < hosts.length; i++) {
// the first node will be an update of the existing one
t.strictEqual(hosts[i].url.hostname, 'localhost')
}
t.strictEqual(client.connectionPool.connections.size, 4)
})
t.teardown(shutdown)
})
})
test('Sniff interval', t => {
t.plan(10)

View File

@ -282,41 +282,112 @@ test('API', t => {
})
t.test('nodesToHost', t => {
const pool = new ConnectionPool({ Connection })
const nodes = {
a1: {
http: {
publish_address: '127.0.0.1:9200'
t.test('publish_address as ip address', t => {
const pool = new ConnectionPool({ Connection })
const nodes = {
a1: {
http: {
publish_address: '127.0.0.1:9200'
},
roles: ['master', 'data', 'ingest']
},
roles: ['master', 'data', 'ingest']
},
a2: {
http: {
publish_address: '127.0.0.1:9202'
},
roles: ['master', 'data', 'ingest']
a2: {
http: {
publish_address: '127.0.0.1:9201'
},
roles: ['master', 'data', 'ingest']
}
}
}
t.deepEqual(pool.nodesToHost(nodes), [{
url: new URL('http://127.0.0.1:9200'),
id: 'a1',
roles: {
master: true,
data: true,
ingest: true,
ml: false
t.deepEqual(pool.nodesToHost(nodes, 'http:'), [{
url: new URL('http://127.0.0.1:9200'),
id: 'a1',
roles: {
master: true,
data: true,
ingest: true,
ml: false
}
}, {
url: new URL('http://127.0.0.1:9201'),
id: 'a2',
roles: {
master: true,
data: true,
ingest: true,
ml: false
}
}])
t.strictEqual(pool.nodesToHost(nodes, 'http:')[0].url.host, '127.0.0.1:9200')
t.strictEqual(pool.nodesToHost(nodes, 'http:')[1].url.host, '127.0.0.1:9201')
t.end()
})
t.test('publish_address as host/ip', t => {
const pool = new ConnectionPool({ Connection })
const nodes = {
a1: {
http: {
publish_address: 'example.com/127.0.0.1:9200'
},
roles: ['master', 'data', 'ingest']
},
a2: {
http: {
publish_address: 'example.com/127.0.0.1:9201'
},
roles: ['master', 'data', 'ingest']
}
}
}, {
url: new URL('http://127.0.0.1:9201'),
id: 'a2',
roles: {
master: true,
data: true,
ingest: true,
ml: false
t.deepEqual(pool.nodesToHost(nodes, 'http:'), [{
url: new URL('http://example.com:9200'),
id: 'a1',
roles: {
master: true,
data: true,
ingest: true,
ml: false
}
}, {
url: new URL('http://example.com:9201'),
id: 'a2',
roles: {
master: true,
data: true,
ingest: true,
ml: false
}
}])
t.strictEqual(pool.nodesToHost(nodes, 'http:')[0].url.host, 'example.com:9200')
t.strictEqual(pool.nodesToHost(nodes, 'http:')[1].url.host, 'example.com:9201')
t.end()
})
t.test('Should use the configure protocol', t => {
const pool = new ConnectionPool({ Connection })
const nodes = {
a1: {
http: {
publish_address: 'example.com/127.0.0.1:9200'
},
roles: ['master', 'data', 'ingest']
},
a2: {
http: {
publish_address: 'example.com/127.0.0.1:9201'
},
roles: ['master', 'data', 'ingest']
}
}
}])
t.strictEqual(pool.nodesToHost(nodes, 'https:')[0].url.protocol, 'https:')
t.strictEqual(pool.nodesToHost(nodes, 'http:')[1].url.protocol, 'http:')
t.end()
})
t.end()
})

View File

@ -53,12 +53,14 @@ function buildCluster (options, callback) {
buildServer(options.handler || handler, ({ port }, server) => {
nodes[opts.id] = {
url: `http://localhost:${port}`,
url: `http://127.0.0.1:${port}`,
server
}
sniffResult.nodes[opts.id] = {
http: {
publish_address: `http://localhost:${port}`
publish_address: options.hostPublishAddress
? `localhost/127.0.0.1:${port}`
: `127.0.0.1:${port}`
},
roles: ['master', 'data', 'ingest']
}