Support for Elasticsearch 7.3 (#928)
This commit is contained in:
committed by
GitHub
parent
823c209c32
commit
8c78f47ac3
@ -1,21 +1,6 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
|
||||
@ -1,21 +1,6 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
@ -38,7 +23,6 @@ test('Basic (callback)', t => {
|
||||
|
||||
client.search({
|
||||
index: 'test',
|
||||
type: 'doc',
|
||||
q: 'foo:bar'
|
||||
}, (err, { body }) => {
|
||||
t.error(err)
|
||||
@ -64,7 +48,6 @@ test('Basic (promises)', t => {
|
||||
client
|
||||
.search({
|
||||
index: 'test',
|
||||
type: 'doc',
|
||||
q: 'foo:bar'
|
||||
})
|
||||
.then(({ body }) => {
|
||||
@ -91,7 +74,6 @@ test('Error (callback)', t => {
|
||||
|
||||
client.search({
|
||||
index: 'test',
|
||||
type: 'doc',
|
||||
q: 'foo:bar'
|
||||
}, (err, { body }) => {
|
||||
t.ok(err)
|
||||
@ -117,7 +99,6 @@ test('Error (promises)', t => {
|
||||
client
|
||||
.search({
|
||||
index: 'test',
|
||||
type: 'doc',
|
||||
q: 'foo:bar'
|
||||
})
|
||||
.then(t.fail)
|
||||
@ -143,7 +124,6 @@ test('Abort method (callback)', t => {
|
||||
|
||||
const request = client.search({
|
||||
index: 'test',
|
||||
type: 'doc',
|
||||
q: 'foo:bar'
|
||||
}, (err, { body }) => {
|
||||
t.error(err)
|
||||
@ -170,7 +150,6 @@ test('Abort is not supported in promises', t => {
|
||||
|
||||
const request = client.search({
|
||||
index: 'test',
|
||||
type: 'doc',
|
||||
q: 'foo:bar'
|
||||
})
|
||||
|
||||
@ -200,7 +179,6 @@ test('Basic (options and callback)', t => {
|
||||
|
||||
client.search({
|
||||
index: 'test',
|
||||
type: 'doc',
|
||||
q: 'foo:bar'
|
||||
}, {
|
||||
requestTimeout: 10000
|
||||
@ -228,7 +206,6 @@ test('Basic (options and promises)', t => {
|
||||
client
|
||||
.search({
|
||||
index: 'test',
|
||||
type: 'doc',
|
||||
q: 'foo:bar'
|
||||
}, {
|
||||
requestTimeout: 10000
|
||||
@ -245,7 +222,7 @@ test('Pass unknown parameters as query parameters (and get a warning)', t => {
|
||||
t.plan(4)
|
||||
|
||||
function handler (req, res) {
|
||||
t.strictEqual(req.url, '/test/doc/_search?q=foo%3Abar&winter=is%20coming')
|
||||
t.strictEqual(req.url, '/test/_search?q=foo%3Abar&winter=is%20coming')
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
@ -257,7 +234,6 @@ test('Pass unknown parameters as query parameters (and get a warning)', t => {
|
||||
|
||||
client.search({
|
||||
index: 'test',
|
||||
type: 'doc',
|
||||
q: 'foo:bar',
|
||||
winter: 'is coming'
|
||||
}, (err, { body, warnings }) => {
|
||||
@ -273,7 +249,7 @@ test('If the API uses the same key for both url and query parameter, the url sho
|
||||
t.plan(2)
|
||||
|
||||
function handler (req, res) {
|
||||
t.strictEqual(req.url, '/index/type/_bulk')
|
||||
t.strictEqual(req.url, '/index/_bulk')
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
@ -286,7 +262,6 @@ test('If the API uses the same key for both url and query parameter, the url sho
|
||||
// bulk has two `type` parameters
|
||||
client.bulk({
|
||||
index: 'index',
|
||||
type: 'type',
|
||||
body: []
|
||||
}, (err, { body, warnings }) => {
|
||||
t.error(err)
|
||||
|
||||
490
test/unit/base-connection-pool.test.js
Normal file
490
test/unit/base-connection-pool.test.js
Normal file
@ -0,0 +1,490 @@
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const { URL } = require('url')
|
||||
const BaseConnectionPool = require('../../lib/pool/BaseConnectionPool')
|
||||
const Connection = require('../../lib/Connection')
|
||||
|
||||
test('API', t => {
|
||||
t.test('addConnection', t => {
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
const href = 'http://localhost:9200/'
|
||||
pool.addConnection(href)
|
||||
t.ok(pool.connections.find(c => c.id === href) instanceof Connection)
|
||||
t.strictEqual(pool.connections.find(c => c.id === href).status, Connection.statuses.ALIVE)
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('addConnection should throw with two connections with the same id', t => {
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
const href = 'http://localhost:9200/'
|
||||
pool.addConnection(href)
|
||||
try {
|
||||
pool.addConnection(href)
|
||||
t.fail('Should throw')
|
||||
} catch (err) {
|
||||
t.is(err.message, `Connection with id '${href}' is already present`)
|
||||
}
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('addConnection should handle not-friendly url parameters for user and password', t => {
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
const href = 'http://us"er:p@assword@localhost:9200/'
|
||||
pool.addConnection(href)
|
||||
const conn = pool.connections[0]
|
||||
t.strictEqual(conn.url.username, 'us%22er')
|
||||
t.strictEqual(conn.url.password, 'p%40assword')
|
||||
t.match(conn.headers, {
|
||||
authorization: 'Basic ' + Buffer.from('us"er:p@assword').toString('base64')
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('markDead', t => {
|
||||
const pool = new BaseConnectionPool({ Connection, sniffEnabled: true })
|
||||
const href = 'http://localhost:9200/'
|
||||
var connection = pool.addConnection(href)
|
||||
t.same(pool.markDead(connection), pool)
|
||||
connection = pool.connections.find(c => c.id === href)
|
||||
t.strictEqual(connection.status, Connection.statuses.ALIVE)
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('markAlive', t => {
|
||||
const pool = new BaseConnectionPool({ Connection, sniffEnabled: true })
|
||||
const href = 'http://localhost:9200/'
|
||||
var connection = pool.addConnection(href)
|
||||
t.same(pool.markAlive(connection), pool)
|
||||
connection = pool.connections.find(c => c.id === href)
|
||||
t.strictEqual(connection.status, Connection.statuses.ALIVE)
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('getConnection should throw', t => {
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
const href = 'http://localhost:9200/'
|
||||
pool.addConnection(href)
|
||||
try {
|
||||
pool.getConnection()
|
||||
t.fail('Should fail')
|
||||
} catch (err) {
|
||||
t.is(err.message, 'getConnection must be implemented')
|
||||
}
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('removeConnection', t => {
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
const href = 'http://localhost:9200/'
|
||||
var connection = pool.addConnection(href)
|
||||
pool.removeConnection(connection)
|
||||
t.strictEqual(pool.size, 0)
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('empty', t => {
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
pool.addConnection('http://localhost:9200/')
|
||||
pool.addConnection('http://localhost:9201/')
|
||||
pool.empty(() => {
|
||||
t.strictEqual(pool.size, 0)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.test('urlToHost', t => {
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
const url = 'http://localhost:9200'
|
||||
t.deepEqual(
|
||||
pool.urlToHost(url),
|
||||
{ url: new URL(url) }
|
||||
)
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('nodesToHost', t => {
|
||||
t.test('publish_address as ip address (IPv4)', t => {
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
const nodes = {
|
||||
a1: {
|
||||
http: {
|
||||
publish_address: '127.0.0.1:9200'
|
||||
},
|
||||
roles: ['master', 'data', 'ingest']
|
||||
},
|
||||
a2: {
|
||||
http: {
|
||||
publish_address: '127.0.0.1:9201'
|
||||
},
|
||||
roles: ['master', 'data', 'ingest']
|
||||
}
|
||||
}
|
||||
|
||||
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 ip address (IPv6)', t => {
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
const nodes = {
|
||||
a1: {
|
||||
http: {
|
||||
publish_address: '[::1]:9200'
|
||||
},
|
||||
roles: ['master', 'data', 'ingest']
|
||||
},
|
||||
a2: {
|
||||
http: {
|
||||
publish_address: '[::1]:9201'
|
||||
},
|
||||
roles: ['master', 'data', 'ingest']
|
||||
}
|
||||
}
|
||||
|
||||
t.deepEqual(pool.nodesToHost(nodes, 'http:'), [{
|
||||
url: new URL('http://[::1]:9200'),
|
||||
id: 'a1',
|
||||
roles: {
|
||||
master: true,
|
||||
data: true,
|
||||
ingest: true,
|
||||
ml: false
|
||||
}
|
||||
}, {
|
||||
url: new URL('http://[::1]:9201'),
|
||||
id: 'a2',
|
||||
roles: {
|
||||
master: true,
|
||||
data: true,
|
||||
ingest: true,
|
||||
ml: false
|
||||
}
|
||||
}])
|
||||
|
||||
t.strictEqual(pool.nodesToHost(nodes, 'http:')[0].url.host, '[::1]:9200')
|
||||
t.strictEqual(pool.nodesToHost(nodes, 'http:')[1].url.host, '[::1]:9201')
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('publish_address as host/ip (IPv4)', t => {
|
||||
const pool = new BaseConnectionPool({ 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.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('publish_address as host/ip (IPv6)', t => {
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
const nodes = {
|
||||
a1: {
|
||||
http: {
|
||||
publish_address: 'example.com/[::1]:9200'
|
||||
},
|
||||
roles: ['master', 'data', 'ingest']
|
||||
},
|
||||
a2: {
|
||||
http: {
|
||||
publish_address: 'example.com/[::1]:9201'
|
||||
},
|
||||
roles: ['master', 'data', 'ingest']
|
||||
}
|
||||
}
|
||||
|
||||
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 BaseConnectionPool({ 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()
|
||||
})
|
||||
|
||||
t.test('update', t => {
|
||||
t.test('Should not update existing connections', t => {
|
||||
t.plan(2)
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
pool.addConnection([{
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'a1',
|
||||
roles: {
|
||||
master: true,
|
||||
data: true,
|
||||
ingest: true
|
||||
}
|
||||
}, {
|
||||
url: new URL('http://127.0.0.1:9201'),
|
||||
id: 'a2',
|
||||
roles: {
|
||||
master: true,
|
||||
data: true,
|
||||
ingest: true
|
||||
}
|
||||
}])
|
||||
|
||||
pool.update([{
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'a1',
|
||||
roles: null
|
||||
}, {
|
||||
url: new URL('http://127.0.0.1:9201'),
|
||||
id: 'a2',
|
||||
roles: null
|
||||
}])
|
||||
|
||||
t.ok(pool.connections.find(c => c.id === 'a1').roles !== null)
|
||||
t.ok(pool.connections.find(c => c.id === 'a2').roles !== null)
|
||||
})
|
||||
|
||||
t.test('Should not update existing connections (mark alive)', t => {
|
||||
t.plan(5)
|
||||
class CustomBaseConnectionPool extends BaseConnectionPool {
|
||||
markAlive (connection) {
|
||||
t.ok('called')
|
||||
super.markAlive(connection)
|
||||
}
|
||||
}
|
||||
const pool = new CustomBaseConnectionPool({ Connection })
|
||||
const conn1 = pool.addConnection({
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'a1',
|
||||
roles: {
|
||||
master: true,
|
||||
data: true,
|
||||
ingest: true
|
||||
}
|
||||
})
|
||||
|
||||
const conn2 = pool.addConnection({
|
||||
url: new URL('http://127.0.0.1:9201'),
|
||||
id: 'a2',
|
||||
roles: {
|
||||
master: true,
|
||||
data: true,
|
||||
ingest: true
|
||||
}
|
||||
})
|
||||
|
||||
pool.markDead(conn1)
|
||||
pool.markDead(conn2)
|
||||
|
||||
pool.update([{
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'a1',
|
||||
roles: null
|
||||
}, {
|
||||
url: new URL('http://127.0.0.1:9201'),
|
||||
id: 'a2',
|
||||
roles: null
|
||||
}])
|
||||
|
||||
t.ok(pool.connections.find(c => c.id === 'a1').roles !== null)
|
||||
t.ok(pool.connections.find(c => c.id === 'a2').roles !== null)
|
||||
})
|
||||
|
||||
t.test('Should not update existing connections (same url, different id)', t => {
|
||||
t.plan(3)
|
||||
class CustomBaseConnectionPool extends BaseConnectionPool {
|
||||
markAlive (connection) {
|
||||
t.ok('called')
|
||||
super.markAlive(connection)
|
||||
}
|
||||
}
|
||||
const pool = new CustomBaseConnectionPool({ Connection })
|
||||
pool.addConnection([{
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'http://127.0.0.1:9200/',
|
||||
roles: {
|
||||
master: true,
|
||||
data: true,
|
||||
ingest: true
|
||||
}
|
||||
}])
|
||||
|
||||
pool.update([{
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'a1',
|
||||
roles: true
|
||||
}])
|
||||
|
||||
// roles will never be updated, we only use it to do
|
||||
// a dummy check to see if the connection has been updated
|
||||
t.deepEqual(pool.connections.find(c => c.id === 'a1').roles, {
|
||||
master: true,
|
||||
data: true,
|
||||
ingest: true,
|
||||
ml: false
|
||||
})
|
||||
t.strictEqual(pool.connections.find(c => c.id === 'http://127.0.0.1:9200/'), undefined)
|
||||
})
|
||||
|
||||
t.test('Add a new connection', t => {
|
||||
t.plan(2)
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
pool.addConnection({
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'a1',
|
||||
roles: {
|
||||
master: true,
|
||||
data: true,
|
||||
ingest: true
|
||||
}
|
||||
})
|
||||
|
||||
pool.update([{
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'a1',
|
||||
roles: null
|
||||
}, {
|
||||
url: new URL('http://127.0.0.1:9201'),
|
||||
id: 'a2',
|
||||
roles: null
|
||||
}])
|
||||
|
||||
t.ok(pool.connections.find(c => c.id === 'a1').roles !== null)
|
||||
t.ok(pool.connections.find(c => c.id === 'a2'))
|
||||
})
|
||||
|
||||
t.test('Remove old connections', t => {
|
||||
t.plan(3)
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
pool.addConnection({
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'a1',
|
||||
roles: null
|
||||
})
|
||||
|
||||
pool.update([{
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'a2',
|
||||
roles: null
|
||||
}, {
|
||||
url: new URL('http://127.0.0.1:9201'),
|
||||
id: 'a3',
|
||||
roles: null
|
||||
}])
|
||||
|
||||
t.false(pool.connections.find(c => c.id === 'a1'))
|
||||
t.true(pool.connections.find(c => c.id === 'a2'))
|
||||
t.true(pool.connections.find(c => c.id === 'a3'))
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('CreateConnection', t => {
|
||||
t.plan(1)
|
||||
const pool = new BaseConnectionPool({ Connection })
|
||||
const conn = pool.createConnection('http://localhost:9200')
|
||||
pool.connections.push(conn)
|
||||
try {
|
||||
pool.createConnection('http://localhost:9200')
|
||||
t.fail('Should throw')
|
||||
} catch (err) {
|
||||
t.is(err.message, 'Connection with id \'http://localhost:9200/\' is already present')
|
||||
}
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
@ -1,21 +1,6 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
|
||||
@ -1,27 +1,13 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const { URL } = require('url')
|
||||
const { Client, ConnectionPool, Transport } = require('../../index')
|
||||
const { CloudConnectionPool } = require('../../lib/pool')
|
||||
const { buildServer } = require('../utils')
|
||||
|
||||
test('Configure host', t => {
|
||||
@ -30,7 +16,7 @@ test('Configure host', t => {
|
||||
node: 'http://localhost:9200'
|
||||
})
|
||||
const pool = client.connectionPool
|
||||
t.match(pool.connections.get('http://localhost:9200/'), {
|
||||
t.match(pool.connections.find(c => c.id === 'http://localhost:9200/'), {
|
||||
url: new URL('http://localhost:9200'),
|
||||
id: 'http://localhost:9200/',
|
||||
ssl: null,
|
||||
@ -51,7 +37,7 @@ test('Configure host', t => {
|
||||
nodes: ['http://localhost:9200', 'http://localhost:9201']
|
||||
})
|
||||
const pool = client.connectionPool
|
||||
t.match(pool.connections.get('http://localhost:9200/'), {
|
||||
t.match(pool.connections.find(c => c.id === 'http://localhost:9200/'), {
|
||||
url: new URL('http://localhost:9200'),
|
||||
id: 'http://localhost:9200/',
|
||||
ssl: null,
|
||||
@ -64,7 +50,7 @@ test('Configure host', t => {
|
||||
ml: false
|
||||
}
|
||||
})
|
||||
t.match(pool.connections.get('http://localhost:9201/'), {
|
||||
t.match(pool.connections.find(c => c.id === 'http://localhost:9201/'), {
|
||||
url: new URL('http://localhost:9201'),
|
||||
id: 'http://localhost:9201/',
|
||||
ssl: null,
|
||||
@ -95,7 +81,7 @@ test('Configure host', t => {
|
||||
}
|
||||
})
|
||||
const pool = client.connectionPool
|
||||
t.match(pool.connections.get('node'), {
|
||||
t.match(pool.connections.find(c => c.id === 'node'), {
|
||||
url: new URL('http://localhost:9200'),
|
||||
id: 'node',
|
||||
ssl: 'ssl',
|
||||
@ -103,7 +89,7 @@ test('Configure host', t => {
|
||||
resurrectTimeout: 0
|
||||
})
|
||||
|
||||
t.deepEqual(pool.connections.get('node').roles, {
|
||||
t.deepEqual(pool.connections.find(c => c.id === 'node').roles, {
|
||||
master: true,
|
||||
data: false,
|
||||
ingest: false,
|
||||
@ -136,7 +122,7 @@ test('Configure host', t => {
|
||||
}]
|
||||
})
|
||||
const pool = client.connectionPool
|
||||
t.match(pool.connections.get('node1'), {
|
||||
t.match(pool.connections.find(c => c.id === 'node1'), {
|
||||
url: new URL('http://localhost:9200'),
|
||||
id: 'node1',
|
||||
ssl: 'ssl',
|
||||
@ -144,14 +130,14 @@ test('Configure host', t => {
|
||||
resurrectTimeout: 0
|
||||
})
|
||||
|
||||
t.deepEqual(pool.connections.get('node1').roles, {
|
||||
t.deepEqual(pool.connections.find(c => c.id === 'node1').roles, {
|
||||
master: true,
|
||||
data: false,
|
||||
ingest: false,
|
||||
ml: false
|
||||
})
|
||||
|
||||
t.match(pool.connections.get('node2'), {
|
||||
t.match(pool.connections.find(c => c.id === 'node2'), {
|
||||
url: new URL('http://localhost:9200'),
|
||||
id: 'node2',
|
||||
ssl: 'ssl',
|
||||
@ -159,7 +145,7 @@ test('Configure host', t => {
|
||||
resurrectTimeout: 0
|
||||
})
|
||||
|
||||
t.deepEqual(pool.connections.get('node2').roles, {
|
||||
t.deepEqual(pool.connections.find(c => c.id === 'node2').roles, {
|
||||
master: false,
|
||||
data: true,
|
||||
ingest: false,
|
||||
@ -178,7 +164,7 @@ test('Configure host', t => {
|
||||
}
|
||||
})
|
||||
const pool = client.connectionPool
|
||||
t.match(pool.connections.get('node'), {
|
||||
t.match(pool.connections.find(c => c.id === 'node'), {
|
||||
url: new URL('http://localhost:9200'),
|
||||
headers: { 'x-foo': 'bar' }
|
||||
})
|
||||
@ -198,63 +184,293 @@ test('Configure host', t => {
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('Node with auth data in the url', t => {
|
||||
t.plan(3)
|
||||
test('Authentication', t => {
|
||||
t.test('Basic', t => {
|
||||
t.test('Node with basic auth data in the url', t => {
|
||||
t.plan(3)
|
||||
|
||||
function handler (req, res) {
|
||||
t.match(req.headers, {
|
||||
authorization: 'Basic Zm9vOmJhcg=='
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const client = new Client({
|
||||
node: `http://foo:bar@localhost:${port}`
|
||||
})
|
||||
|
||||
client.info((err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
server.stop()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test('Custom authentication per request', t => {
|
||||
t.plan(6)
|
||||
|
||||
var first = true
|
||||
function handler (req, res) {
|
||||
t.match(req.headers, {
|
||||
authorization: first ? 'hello' : 'Basic Zm9vOmJhcg=='
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const client = new Client({
|
||||
node: `http://foo:bar@localhost:${port}`
|
||||
})
|
||||
|
||||
client.info({}, {
|
||||
headers: {
|
||||
authorization: 'hello'
|
||||
function handler (req, res) {
|
||||
t.match(req.headers, {
|
||||
authorization: 'Basic Zm9vOmJhcg=='
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
}, (err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
first = false
|
||||
|
||||
client.info((err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
server.stop()
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const client = new Client({
|
||||
node: `http://foo:bar@localhost:${port}`
|
||||
})
|
||||
|
||||
client.info((err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
server.stop()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.test('Node with basic auth data in the url (array of nodes)', t => {
|
||||
t.plan(3)
|
||||
|
||||
function handler (req, res) {
|
||||
t.match(req.headers, {
|
||||
authorization: 'Basic Zm9vOmJhcg=='
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const client = new Client({
|
||||
nodes: [`http://foo:bar@localhost:${port}`]
|
||||
})
|
||||
|
||||
client.info((err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
server.stop()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.test('Node with basic auth data in the options', t => {
|
||||
t.plan(3)
|
||||
|
||||
function handler (req, res) {
|
||||
t.match(req.headers, {
|
||||
authorization: 'Basic Zm9vOmJhcg=='
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const client = new Client({
|
||||
node: `http://localhost:${port}`,
|
||||
auth: {
|
||||
username: 'foo',
|
||||
password: 'bar'
|
||||
}
|
||||
})
|
||||
|
||||
client.info((err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
server.stop()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.test('Custom basic authentication per request', t => {
|
||||
t.plan(6)
|
||||
|
||||
var first = true
|
||||
function handler (req, res) {
|
||||
t.match(req.headers, {
|
||||
authorization: first ? 'hello' : 'Basic Zm9vOmJhcg=='
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const client = new Client({
|
||||
node: `http://foo:bar@localhost:${port}`
|
||||
})
|
||||
|
||||
client.info({}, {
|
||||
headers: {
|
||||
authorization: 'hello'
|
||||
}
|
||||
}, (err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
first = false
|
||||
|
||||
client.info((err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
server.stop()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.test('Override default basic authentication per request', t => {
|
||||
t.plan(6)
|
||||
|
||||
var first = true
|
||||
function handler (req, res) {
|
||||
t.match(req.headers, {
|
||||
authorization: first ? 'hello' : 'Basic Zm9vOmJhcg=='
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const client = new Client({
|
||||
node: `http://localhost:${port}`,
|
||||
auth: {
|
||||
username: 'foo',
|
||||
password: 'bar'
|
||||
}
|
||||
})
|
||||
|
||||
client.info({}, {
|
||||
headers: {
|
||||
authorization: 'hello'
|
||||
}
|
||||
}, (err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
first = false
|
||||
|
||||
client.info((err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
server.stop()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('ApiKey', t => {
|
||||
t.test('Node with ApiKey auth data in the options as string', t => {
|
||||
t.plan(3)
|
||||
|
||||
function handler (req, res) {
|
||||
t.match(req.headers, {
|
||||
authorization: 'ApiKey Zm9vOmJhcg=='
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const client = new Client({
|
||||
node: `http://localhost:${port}`,
|
||||
auth: {
|
||||
apiKey: 'Zm9vOmJhcg=='
|
||||
}
|
||||
})
|
||||
|
||||
client.info((err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
server.stop()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.test('Node with ApiKey auth data in the options as object', t => {
|
||||
t.plan(3)
|
||||
|
||||
function handler (req, res) {
|
||||
t.match(req.headers, {
|
||||
authorization: 'ApiKey Zm9vOmJhcg=='
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const client = new Client({
|
||||
node: `http://localhost:${port}`,
|
||||
auth: {
|
||||
apiKey: { id: 'foo', api_key: 'bar' }
|
||||
}
|
||||
})
|
||||
|
||||
client.info((err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
server.stop()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.test('Custom ApiKey authentication per request', t => {
|
||||
t.plan(6)
|
||||
|
||||
var first = true
|
||||
function handler (req, res) {
|
||||
t.match(req.headers, {
|
||||
authorization: first ? 'ApiKey Zm9vOmJhcg==' : 'Basic Zm9vOmJhcg=='
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const client = new Client({
|
||||
node: `http://foo:bar@localhost:${port}`
|
||||
})
|
||||
|
||||
client.info({}, {
|
||||
headers: {
|
||||
authorization: 'ApiKey Zm9vOmJhcg=='
|
||||
}
|
||||
}, (err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
first = false
|
||||
|
||||
client.info((err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
server.stop()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.test('Override default ApiKey authentication per request', t => {
|
||||
t.plan(6)
|
||||
|
||||
var first = true
|
||||
function handler (req, res) {
|
||||
t.match(req.headers, {
|
||||
authorization: first ? 'hello' : 'ApiKey Zm9vOmJhcg=='
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const client = new Client({
|
||||
node: `http://localhost:${port}`,
|
||||
auth: {
|
||||
apiKey: 'Zm9vOmJhcg=='
|
||||
}
|
||||
})
|
||||
|
||||
client.info({}, {
|
||||
headers: {
|
||||
authorization: 'hello'
|
||||
}
|
||||
}, (err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
first = false
|
||||
|
||||
client.info((err, { body }) => {
|
||||
t.error(err)
|
||||
t.deepEqual(body, { hello: 'world' })
|
||||
server.stop()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('Custom headers per request', t => {
|
||||
@ -540,7 +756,7 @@ test('Extend client APIs', t => {
|
||||
|
||||
test('Elastic cloud config', t => {
|
||||
t.test('Basic', t => {
|
||||
t.plan(4)
|
||||
t.plan(5)
|
||||
const client = new Client({
|
||||
cloud: {
|
||||
// 'localhost$abcd$efgh'
|
||||
@ -551,9 +767,50 @@ test('Elastic cloud config', t => {
|
||||
})
|
||||
|
||||
const pool = client.connectionPool
|
||||
t.match(pool.connections.get('https://abcd.localhost/'), {
|
||||
t.ok(pool instanceof CloudConnectionPool)
|
||||
t.match(pool.connections.find(c => c.id === 'https://abcd.localhost/'), {
|
||||
url: new URL('https://elastic:changeme@abcd.localhost'),
|
||||
id: 'https://abcd.localhost/',
|
||||
headers: {
|
||||
authorization: 'Basic ' + Buffer.from('elastic:changeme').toString('base64')
|
||||
},
|
||||
ssl: { secureProtocol: 'TLSv1_2_method' },
|
||||
deadCount: 0,
|
||||
resurrectTimeout: 0,
|
||||
roles: {
|
||||
master: true,
|
||||
data: true,
|
||||
ingest: true,
|
||||
ml: false
|
||||
}
|
||||
})
|
||||
|
||||
t.strictEqual(client.transport.compression, 'gzip')
|
||||
t.strictEqual(client.transport.suggestCompression, true)
|
||||
t.deepEqual(pool._ssl, { secureProtocol: 'TLSv1_2_method' })
|
||||
})
|
||||
|
||||
t.test('Auth as separate option', t => {
|
||||
t.plan(5)
|
||||
const client = new Client({
|
||||
cloud: {
|
||||
// 'localhost$abcd$efgh'
|
||||
id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA=='
|
||||
},
|
||||
auth: {
|
||||
username: 'elastic',
|
||||
password: 'changeme'
|
||||
}
|
||||
})
|
||||
|
||||
const pool = client.connectionPool
|
||||
t.ok(pool instanceof CloudConnectionPool)
|
||||
t.match(pool.connections.find(c => c.id === 'https://abcd.localhost/'), {
|
||||
url: new URL('https://elastic:changeme@abcd.localhost'),
|
||||
id: 'https://abcd.localhost/',
|
||||
headers: {
|
||||
authorization: 'Basic ' + Buffer.from('elastic:changeme').toString('base64')
|
||||
},
|
||||
ssl: { secureProtocol: 'TLSv1_2_method' },
|
||||
deadCount: 0,
|
||||
resurrectTimeout: 0,
|
||||
@ -571,7 +828,7 @@ test('Elastic cloud config', t => {
|
||||
})
|
||||
|
||||
t.test('Override default options', t => {
|
||||
t.plan(3)
|
||||
t.plan(4)
|
||||
const client = new Client({
|
||||
cloud: {
|
||||
// 'localhost$abcd$efgh'
|
||||
@ -586,6 +843,7 @@ test('Elastic cloud config', t => {
|
||||
}
|
||||
})
|
||||
|
||||
t.ok(client.connectionPool instanceof CloudConnectionPool)
|
||||
t.strictEqual(client.transport.compression, false)
|
||||
t.strictEqual(client.transport.suggestCompression, false)
|
||||
t.deepEqual(client.connectionPool._ssl, { secureProtocol: 'TLSv1_1_method' })
|
||||
|
||||
33
test/unit/cloud-connection-pool.test.js
Normal file
33
test/unit/cloud-connection-pool.test.js
Normal file
@ -0,0 +1,33 @@
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const { CloudConnectionPool } = require('../../lib/pool')
|
||||
const Connection = require('../../lib/Connection')
|
||||
|
||||
test('Should expose a cloudConnection property', t => {
|
||||
const pool = new CloudConnectionPool({ Connection })
|
||||
pool.addConnection('http://localhost:9200/')
|
||||
t.ok(pool.cloudConnection instanceof Connection)
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('Get connection should always return cloudConnection', t => {
|
||||
const pool = new CloudConnectionPool({ Connection })
|
||||
const conn = pool.addConnection('http://localhost:9200/')
|
||||
t.deepEqual(pool.getConnection(), conn)
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('pool.empty should reset cloudConnection', t => {
|
||||
const pool = new CloudConnectionPool({ Connection })
|
||||
pool.addConnection('http://localhost:9200/')
|
||||
t.ok(pool.cloudConnection instanceof Connection)
|
||||
pool.empty(() => {
|
||||
t.strictEqual(pool.cloudConnection, null)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
@ -1,27 +1,12 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const { URL } = require('url')
|
||||
const ConnectionPool = require('../../lib/ConnectionPool')
|
||||
const ConnectionPool = require('../../lib/pool/ConnectionPool')
|
||||
const Connection = require('../../lib/Connection')
|
||||
const { defaultNodeFilter, roundRobinSelector } = require('../../lib/Transport').internals
|
||||
const { connection: { MockConnection, MockConnectionTimeout } } = require('../utils')
|
||||
@ -31,8 +16,8 @@ test('API', t => {
|
||||
const pool = new ConnectionPool({ Connection })
|
||||
const href = 'http://localhost:9200/'
|
||||
pool.addConnection(href)
|
||||
t.ok(pool.connections.get(href) instanceof Connection)
|
||||
t.strictEqual(pool.connections.get(href).status, Connection.statuses.ALIVE)
|
||||
t.ok(pool.connections.find(c => c.id === href) instanceof Connection)
|
||||
t.strictEqual(pool.connections.find(c => c.id === href).status, Connection.statuses.ALIVE)
|
||||
t.deepEqual(pool.dead, [])
|
||||
t.end()
|
||||
})
|
||||
@ -50,25 +35,6 @@ test('API', t => {
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('addConnection (should store the auth data)', t => {
|
||||
const pool = new ConnectionPool({ Connection })
|
||||
const href = 'http://localhost:9200/'
|
||||
pool.addConnection('http://foo:bar@localhost:9200')
|
||||
|
||||
t.ok(pool.connections.get(href) instanceof Connection)
|
||||
t.strictEqual(pool.connections.get(href).status, Connection.statuses.ALIVE)
|
||||
t.deepEqual(pool.dead, [])
|
||||
t.deepEqual(pool._auth, { username: 'foo', password: 'bar' })
|
||||
|
||||
pool.addConnection('http://localhost:9201')
|
||||
const conn = pool.connections.get('http://localhost:9201/')
|
||||
t.strictEqual(conn.url.username, 'foo')
|
||||
t.strictEqual(conn.url.password, 'bar')
|
||||
t.strictEqual(conn.auth.username, 'foo')
|
||||
t.strictEqual(conn.auth.password, 'bar')
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('addConnection should handle not-friendly url parameters for user and password', t => {
|
||||
const pool = new ConnectionPool({ Connection })
|
||||
const href = 'http://us"er:p@assword@localhost:9200/'
|
||||
@ -76,8 +42,9 @@ test('API', t => {
|
||||
const conn = pool.getConnection()
|
||||
t.strictEqual(conn.url.username, 'us%22er')
|
||||
t.strictEqual(conn.url.password, 'p%40assword')
|
||||
t.strictEqual(conn.auth.username, 'us"er')
|
||||
t.strictEqual(conn.auth.password, 'p@assword')
|
||||
t.match(conn.headers, {
|
||||
authorization: 'Basic ' + Buffer.from('us"er:p@assword').toString('base64')
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
|
||||
@ -86,7 +53,7 @@ test('API', t => {
|
||||
const href = 'http://localhost:9200/'
|
||||
var connection = pool.addConnection(href)
|
||||
pool.markDead(connection)
|
||||
connection = pool.connections.get(href)
|
||||
connection = pool.connections.find(c => c.id === href)
|
||||
t.strictEqual(connection.deadCount, 1)
|
||||
t.true(connection.resurrectTimeout > 0)
|
||||
t.deepEqual(pool.dead, [href])
|
||||
@ -113,7 +80,7 @@ test('API', t => {
|
||||
var connection = pool.addConnection(href)
|
||||
pool.markDead(connection)
|
||||
pool.markAlive(connection)
|
||||
connection = pool.connections.get(href)
|
||||
connection = pool.connections.find(c => c.id === href)
|
||||
t.strictEqual(connection.deadCount, 0)
|
||||
t.strictEqual(connection.resurrectTimeout, 0)
|
||||
t.strictEqual(connection.status, Connection.statuses.ALIVE)
|
||||
@ -140,7 +107,7 @@ test('API', t => {
|
||||
}
|
||||
pool.resurrect(opts, (isAlive, connection) => {
|
||||
t.true(isAlive)
|
||||
connection = pool.connections.get(connection.id)
|
||||
connection = pool.connections.find(c => c.id === connection.id)
|
||||
t.strictEqual(connection.deadCount, 0)
|
||||
t.strictEqual(connection.resurrectTimeout, 0)
|
||||
t.strictEqual(connection.status, Connection.statuses.ALIVE)
|
||||
@ -166,7 +133,7 @@ test('API', t => {
|
||||
}
|
||||
pool.resurrect(opts, (isAlive, connection) => {
|
||||
t.false(isAlive)
|
||||
connection = pool.connections.get(connection.id)
|
||||
connection = pool.connections.find(c => c.id === connection.id)
|
||||
t.strictEqual(connection.deadCount, 2)
|
||||
t.true(connection.resurrectTimeout > 0)
|
||||
t.strictEqual(connection.status, Connection.statuses.DEAD)
|
||||
@ -194,7 +161,7 @@ test('API', t => {
|
||||
}
|
||||
pool.resurrect(opts, (isAlive, connection) => {
|
||||
t.true(isAlive)
|
||||
connection = pool.connections.get(connection.id)
|
||||
connection = pool.connections.find(c => c.id === connection.id)
|
||||
t.strictEqual(connection.deadCount, 1)
|
||||
t.true(connection.resurrectTimeout > 0)
|
||||
t.strictEqual(connection.status, Connection.statuses.ALIVE)
|
||||
@ -220,7 +187,7 @@ test('API', t => {
|
||||
pool.resurrect(opts, (isAlive, connection) => {
|
||||
t.ok(isAlive === null)
|
||||
t.ok(connection === null)
|
||||
connection = pool.connections.get(href)
|
||||
connection = pool.connections.find(c => c.id === href)
|
||||
t.strictEqual(connection.deadCount, 1)
|
||||
t.true(connection.resurrectTimeout > 0)
|
||||
t.strictEqual(connection.status, Connection.statuses.DEAD)
|
||||
@ -300,7 +267,7 @@ test('API', t => {
|
||||
pool.addConnection('http://localhost:9200/')
|
||||
pool.addConnection('http://localhost:9201/')
|
||||
pool.empty(() => {
|
||||
t.strictEqual(pool.connections.size, 0)
|
||||
t.strictEqual(pool.size, 0)
|
||||
t.deepEqual(pool.dead, [])
|
||||
t.end()
|
||||
})
|
||||
@ -513,12 +480,7 @@ test('API', t => {
|
||||
t.test('update', t => {
|
||||
t.test('Should not update existing connections', t => {
|
||||
t.plan(2)
|
||||
class CustomConnectionPool extends ConnectionPool {
|
||||
markAlive () {
|
||||
t.fail('Should not be called')
|
||||
}
|
||||
}
|
||||
const pool = new CustomConnectionPool({ Connection })
|
||||
const pool = new ConnectionPool({ Connection })
|
||||
pool.addConnection([{
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'a1',
|
||||
@ -547,12 +509,12 @@ test('API', t => {
|
||||
roles: null
|
||||
}])
|
||||
|
||||
t.ok(pool.connections.get('a1').roles !== null)
|
||||
t.ok(pool.connections.get('a2').roles !== null)
|
||||
t.ok(pool.connections.find(c => c.id === 'a1').roles !== null)
|
||||
t.ok(pool.connections.find(c => c.id === 'a2').roles !== null)
|
||||
})
|
||||
|
||||
t.test('Should not update existing connections (mark alive)', t => {
|
||||
t.plan(4)
|
||||
t.plan(5)
|
||||
class CustomConnectionPool extends ConnectionPool {
|
||||
markAlive (connection) {
|
||||
t.ok('called')
|
||||
@ -593,15 +555,16 @@ test('API', t => {
|
||||
roles: null
|
||||
}])
|
||||
|
||||
t.ok(pool.connections.get('a1').roles !== null)
|
||||
t.ok(pool.connections.get('a2').roles !== null)
|
||||
t.ok(pool.connections.find(c => c.id === 'a1').roles !== null)
|
||||
t.ok(pool.connections.find(c => c.id === 'a2').roles !== null)
|
||||
})
|
||||
|
||||
t.test('Should not update existing connections (same url, different id)', t => {
|
||||
t.plan(2)
|
||||
t.plan(3)
|
||||
class CustomConnectionPool extends ConnectionPool {
|
||||
markAlive () {
|
||||
t.fail('Should not be called')
|
||||
markAlive (connection) {
|
||||
t.ok('called')
|
||||
super.markAlive(connection)
|
||||
}
|
||||
}
|
||||
const pool = new CustomConnectionPool({ Connection })
|
||||
@ -623,13 +586,13 @@ test('API', t => {
|
||||
|
||||
// roles will never be updated, we only use it to do
|
||||
// a dummy check to see if the connection has been updated
|
||||
t.deepEqual(pool.connections.get('a1').roles, {
|
||||
t.deepEqual(pool.connections.find(c => c.id === 'a1').roles, {
|
||||
master: true,
|
||||
data: true,
|
||||
ingest: true,
|
||||
ml: false
|
||||
})
|
||||
t.strictEqual(pool.connections.get('http://127.0.0.1:9200/'), undefined)
|
||||
t.strictEqual(pool.connections.find(c => c.id === 'http://127.0.0.1:9200/'), undefined)
|
||||
})
|
||||
|
||||
t.test('Add a new connection', t => {
|
||||
@ -655,8 +618,8 @@ test('API', t => {
|
||||
roles: null
|
||||
}])
|
||||
|
||||
t.ok(pool.connections.get('a1').roles !== null)
|
||||
t.true(pool.connections.has('a2'))
|
||||
t.ok(pool.connections.find(c => c.id === 'a1').roles !== null)
|
||||
t.ok(pool.connections.find(c => c.id === 'a2'))
|
||||
})
|
||||
|
||||
t.test('Remove old connections', t => {
|
||||
@ -678,9 +641,37 @@ test('API', t => {
|
||||
roles: null
|
||||
}])
|
||||
|
||||
t.false(pool.connections.has('a1'))
|
||||
t.true(pool.connections.has('a2'))
|
||||
t.true(pool.connections.has('a3'))
|
||||
t.false(pool.connections.find(c => c.id === 'a1'))
|
||||
t.true(pool.connections.find(c => c.id === 'a2'))
|
||||
t.true(pool.connections.find(c => c.id === 'a3'))
|
||||
})
|
||||
|
||||
t.test('Remove old connections (markDead)', t => {
|
||||
t.plan(5)
|
||||
const pool = new ConnectionPool({ Connection, sniffEnabled: true })
|
||||
const conn = pool.addConnection({
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'a1',
|
||||
roles: null
|
||||
})
|
||||
|
||||
pool.markDead(conn)
|
||||
t.deepEqual(pool.dead, ['a1'])
|
||||
|
||||
pool.update([{
|
||||
url: new URL('http://127.0.0.1:9200'),
|
||||
id: 'a2',
|
||||
roles: null
|
||||
}, {
|
||||
url: new URL('http://127.0.0.1:9201'),
|
||||
id: 'a3',
|
||||
roles: null
|
||||
}])
|
||||
|
||||
t.deepEqual(pool.dead, [])
|
||||
t.false(pool.connections.find(c => c.id === 'a1'))
|
||||
t.true(pool.connections.find(c => c.id === 'a2'))
|
||||
t.true(pool.connections.find(c => c.id === 'a3'))
|
||||
})
|
||||
|
||||
t.end()
|
||||
@ -735,22 +726,22 @@ test('Node filter', t => {
|
||||
|
||||
test('Single node behavior', t => {
|
||||
t.test('sniffing disabled (markDead and markAlive should be noop)', t => {
|
||||
t.plan(2)
|
||||
t.plan(4)
|
||||
const pool = new ConnectionPool({ Connection, sniffEnabled: false })
|
||||
const conn = pool.addConnection('http://localhost:9200/')
|
||||
pool.markDead(conn)
|
||||
t.true(pool.markDead(conn) instanceof ConnectionPool)
|
||||
t.strictEqual(pool.dead.length, 0)
|
||||
pool.markAlive(conn)
|
||||
t.true(pool.markAlive(conn) instanceof ConnectionPool)
|
||||
t.strictEqual(pool.dead.length, 0)
|
||||
})
|
||||
|
||||
t.test('sniffing enabled (markDead and markAlive should work)', t => {
|
||||
t.plan(2)
|
||||
t.plan(4)
|
||||
const pool = new ConnectionPool({ Connection, sniffEnabled: true })
|
||||
const conn = pool.addConnection('http://localhost:9200/')
|
||||
pool.markDead(conn)
|
||||
t.true(pool.markDead(conn) instanceof ConnectionPool)
|
||||
t.strictEqual(pool.dead.length, 1)
|
||||
pool.markAlive(conn)
|
||||
t.true(pool.markAlive(conn) instanceof ConnectionPool)
|
||||
t.strictEqual(pool.dead.length, 0)
|
||||
})
|
||||
|
||||
|
||||
@ -1,21 +1,6 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
@ -748,7 +733,7 @@ test('Util.inspect Connection class should hide agent, ssl and auth', t => {
|
||||
resurrectTimeout: 0,
|
||||
_openRequests: 0,
|
||||
status: 'alive',
|
||||
roles: { master: true, data: true, ingest: true, ml: false } }`)
|
||||
roles: { master: true, data: true, ingest: true, ml: false }}`)
|
||||
)
|
||||
})
|
||||
|
||||
@ -811,6 +796,53 @@ test('Port handling', t => {
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('Authorization header', t => {
|
||||
t.test('None', t => {
|
||||
const connection = new Connection({
|
||||
url: new URL('http://localhost:9200')
|
||||
})
|
||||
|
||||
t.deepEqual(connection.headers, {})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('Basic', t => {
|
||||
const connection = new Connection({
|
||||
url: new URL('http://localhost:9200'),
|
||||
auth: { username: 'foo', password: 'bar' }
|
||||
})
|
||||
|
||||
t.deepEqual(connection.headers, { authorization: 'Basic Zm9vOmJhcg==' })
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('ApiKey (string)', t => {
|
||||
const connection = new Connection({
|
||||
url: new URL('http://localhost:9200'),
|
||||
auth: { apiKey: 'Zm9vOmJhcg==' }
|
||||
})
|
||||
|
||||
t.deepEqual(connection.headers, { authorization: 'ApiKey Zm9vOmJhcg==' })
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('ApiKey (object)', t => {
|
||||
const connection = new Connection({
|
||||
url: new URL('http://localhost:9200'),
|
||||
auth: { apiKey: { id: 'foo', api_key: 'bar' } }
|
||||
})
|
||||
|
||||
t.deepEqual(connection.headers, { authorization: 'ApiKey Zm9vOmJhcg==' })
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('Should not add agent and ssl to the serialized connection', t => {
|
||||
const connection = new Connection({
|
||||
url: new URL('http://localhost:9200')
|
||||
@ -818,7 +850,7 @@ test('Should not add agent and ssl to the serialized connection', t => {
|
||||
|
||||
t.strictEqual(
|
||||
JSON.stringify(connection),
|
||||
'{"url":"http://localhost:9200/","id":"http://localhost:9200/","headers":null,"deadCount":0,"resurrectTimeout":0,"_openRequests":0,"status":"alive","roles":{"master":true,"data":true,"ingest":true,"ml":false}}'
|
||||
'{"url":"http://localhost:9200/","id":"http://localhost:9200/","headers":{},"deadCount":0,"resurrectTimeout":0,"_openRequests":0,"status":"alive","roles":{"master":true,"data":true,"ingest":true,"ml":false}}'
|
||||
)
|
||||
|
||||
t.end()
|
||||
|
||||
@ -1,21 +1,6 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
|
||||
@ -1,21 +1,6 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
@ -45,7 +30,7 @@ test('Should emit a request event when a request is performed', t => {
|
||||
request: {
|
||||
params: {
|
||||
method: 'GET',
|
||||
path: '/test/doc/_search',
|
||||
path: '/test/_search',
|
||||
body: '',
|
||||
querystring: 'q=foo%3Abar',
|
||||
headers: {
|
||||
@ -67,7 +52,6 @@ test('Should emit a request event when a request is performed', t => {
|
||||
|
||||
client.search({
|
||||
index: 'test',
|
||||
type: 'doc',
|
||||
q: 'foo:bar'
|
||||
}, (err, result) => {
|
||||
t.error(err)
|
||||
@ -98,7 +82,7 @@ test('Should emit a response event in case of a successful response', t => {
|
||||
request: {
|
||||
params: {
|
||||
method: 'GET',
|
||||
path: '/test/doc/_search',
|
||||
path: '/test/_search',
|
||||
body: '',
|
||||
querystring: 'q=foo%3Abar',
|
||||
headers: {
|
||||
@ -120,7 +104,6 @@ test('Should emit a response event in case of a successful response', t => {
|
||||
|
||||
client.search({
|
||||
index: 'test',
|
||||
type: 'doc',
|
||||
q: 'foo:bar'
|
||||
}, (err, result) => {
|
||||
t.error(err)
|
||||
@ -149,7 +132,7 @@ test('Should emit a response event with the error set', t => {
|
||||
request: {
|
||||
params: {
|
||||
method: 'GET',
|
||||
path: '/test/doc/_search',
|
||||
path: '/test/_search',
|
||||
body: '',
|
||||
querystring: 'q=foo%3Abar',
|
||||
headers: {
|
||||
@ -173,7 +156,6 @@ test('Should emit a response event with the error set', t => {
|
||||
|
||||
client.search({
|
||||
index: 'test',
|
||||
type: 'doc',
|
||||
q: 'foo:bar'
|
||||
}, {
|
||||
requestTimeout: 500
|
||||
|
||||
@ -1,21 +1,6 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
|
||||
@ -1,21 +1,6 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
|
||||
@ -1,26 +1,12 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// Licensed to Elasticsearch B.V under one or more agreements.
|
||||
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information
|
||||
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const { URL } = require('url')
|
||||
const lolex = require('lolex')
|
||||
const { createGunzip } = require('zlib')
|
||||
const os = require('os')
|
||||
const intoStream = require('into-stream')
|
||||
@ -38,7 +24,7 @@ const {
|
||||
ConfigurationError
|
||||
} = require('../../lib/errors')
|
||||
|
||||
const ConnectionPool = require('../../lib/ConnectionPool')
|
||||
const ConnectionPool = require('../../lib/pool/ConnectionPool')
|
||||
const Connection = require('../../lib/Connection')
|
||||
const Serializer = require('../../lib/Serializer')
|
||||
const Transport = require('../../lib/Transport')
|
||||
@ -893,148 +879,95 @@ test('Override requestTimeout', t => {
|
||||
|
||||
test('sniff', t => {
|
||||
t.test('sniffOnStart', t => {
|
||||
t.plan(3)
|
||||
t.plan(1)
|
||||
|
||||
class CustomConnectionPool extends ConnectionPool {
|
||||
update () {
|
||||
t.ok('called')
|
||||
return this
|
||||
}
|
||||
|
||||
nodesToHost (nodes) {
|
||||
t.ok('called')
|
||||
return []
|
||||
class MyTransport extends Transport {
|
||||
sniff (opts) {
|
||||
t.strictEqual(opts.reason, Transport.sniffReasons.SNIFF_ON_START)
|
||||
}
|
||||
}
|
||||
|
||||
function handler (req, res) {
|
||||
t.strictEqual(req.url, '/sniff')
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
const pool = new ConnectionPool({ Connection })
|
||||
pool.addConnection('http://localhost:9200')
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const pool = new CustomConnectionPool({ Connection })
|
||||
pool.addConnection(`http://localhost:${port}`)
|
||||
|
||||
// eslint-disable-next-line
|
||||
new Transport({
|
||||
emit: () => {},
|
||||
connectionPool: pool,
|
||||
serializer: new Serializer(),
|
||||
maxRetries: 3,
|
||||
requestTimeout: 30000,
|
||||
sniffInterval: false,
|
||||
sniffOnStart: true,
|
||||
sniffEndpoint: '/sniff'
|
||||
})
|
||||
|
||||
setTimeout(() => server.stop(), 100)
|
||||
// eslint-disable-next-line
|
||||
new MyTransport({
|
||||
emit: () => {},
|
||||
connectionPool: pool,
|
||||
serializer: new Serializer(),
|
||||
maxRetries: 3,
|
||||
requestTimeout: 30000,
|
||||
sniffInterval: false,
|
||||
sniffOnStart: true,
|
||||
sniffEndpoint: '/sniff'
|
||||
})
|
||||
})
|
||||
|
||||
t.test('sniffOnConnectionFault', t => {
|
||||
t.plan(3)
|
||||
t.plan(2)
|
||||
|
||||
class CustomConnectionPool extends ConnectionPool {
|
||||
update () {
|
||||
t.ok('called')
|
||||
return this
|
||||
}
|
||||
|
||||
nodesToHost (nodes) {
|
||||
t.ok('called')
|
||||
return []
|
||||
class MyTransport extends Transport {
|
||||
sniff (opts) {
|
||||
t.strictEqual(opts.reason, Transport.sniffReasons.SNIFF_ON_CONNECTION_FAULT)
|
||||
}
|
||||
}
|
||||
|
||||
function handler (req, res) {
|
||||
if (req.url === '/other/sniff') {
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
} else {
|
||||
setTimeout(() => res.end(), 1000)
|
||||
}
|
||||
}
|
||||
const pool = new ConnectionPool({ Connection: MockConnectionTimeout })
|
||||
pool.addConnection('http://localhost:9200')
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const pool = new CustomConnectionPool({ Connection })
|
||||
pool.addConnection(`http://localhost:${port}`)
|
||||
pool.addConnection(`http://localhost:${port}/other`)
|
||||
const transport = new MyTransport({
|
||||
emit: () => {},
|
||||
connectionPool: pool,
|
||||
serializer: new Serializer(),
|
||||
maxRetries: 0,
|
||||
requestTimeout: 500,
|
||||
sniffInterval: false,
|
||||
sniffOnConnectionFault: true,
|
||||
sniffEndpoint: '/sniff'
|
||||
})
|
||||
|
||||
const transport = new Transport({
|
||||
emit: () => {},
|
||||
connectionPool: pool,
|
||||
serializer: new Serializer(),
|
||||
maxRetries: 0,
|
||||
requestTimeout: 500,
|
||||
sniffInterval: false,
|
||||
sniffOnConnectionFault: true,
|
||||
sniffEndpoint: '/sniff'
|
||||
})
|
||||
|
||||
transport.request({
|
||||
method: 'GET',
|
||||
path: '/'
|
||||
}, (err, { body }) => {
|
||||
t.ok(err instanceof TimeoutError)
|
||||
})
|
||||
|
||||
setTimeout(() => server.stop(), 1100)
|
||||
transport.request({
|
||||
method: 'GET',
|
||||
path: '/'
|
||||
}, (err, { body }) => {
|
||||
t.ok(err instanceof TimeoutError)
|
||||
})
|
||||
})
|
||||
|
||||
t.test('sniffInterval', t => {
|
||||
t.plan(9)
|
||||
t.plan(6)
|
||||
|
||||
class CustomConnectionPool extends ConnectionPool {
|
||||
update () {
|
||||
return this
|
||||
}
|
||||
const clock = lolex.install({ toFake: ['Date'] })
|
||||
t.teardown(() => clock.uninstall())
|
||||
|
||||
nodesToHost (nodes) {
|
||||
return []
|
||||
class MyTransport extends Transport {
|
||||
sniff (opts) {
|
||||
t.strictEqual(opts.reason, Transport.sniffReasons.SNIFF_INTERVAL)
|
||||
}
|
||||
}
|
||||
|
||||
function handler (req, res) {
|
||||
// this should be called 6 times
|
||||
t.ok('called')
|
||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||
res.end(JSON.stringify({ hello: 'world' }))
|
||||
}
|
||||
const pool = new ConnectionPool({ Connection: MockConnection })
|
||||
pool.addConnection('http://localhost:9200')
|
||||
|
||||
buildServer(handler, ({ port }, server) => {
|
||||
const pool = new CustomConnectionPool({ Connection })
|
||||
pool.addConnection(`http://localhost:${port}`)
|
||||
|
||||
const transport = new Transport({
|
||||
emit: () => {},
|
||||
connectionPool: pool,
|
||||
serializer: new Serializer(),
|
||||
maxRetries: 3,
|
||||
requestTimeout: 3000,
|
||||
sniffInterval: 1,
|
||||
sniffEndpoint: '/sniff'
|
||||
})
|
||||
|
||||
const params = { method: 'GET', path: '/' }
|
||||
setTimeout(() => {
|
||||
transport.request(params, t.error)
|
||||
}, 100)
|
||||
|
||||
setTimeout(() => {
|
||||
transport.request(params, t.error)
|
||||
}, 200)
|
||||
|
||||
setTimeout(() => {
|
||||
transport.request(params, t.error)
|
||||
}, 300)
|
||||
|
||||
setTimeout(() => {
|
||||
server.stop()
|
||||
}, 400)
|
||||
const transport = new MyTransport({
|
||||
emit: () => {},
|
||||
connectionPool: pool,
|
||||
serializer: new Serializer(),
|
||||
maxRetries: 3,
|
||||
requestTimeout: 3000,
|
||||
sniffInterval: 1,
|
||||
sniffEndpoint: '/sniff'
|
||||
})
|
||||
|
||||
const params = { method: 'GET', path: '/' }
|
||||
clock.tick(100)
|
||||
transport.request(params, t.error)
|
||||
|
||||
clock.tick(200)
|
||||
transport.request(params, t.error)
|
||||
|
||||
clock.tick(300)
|
||||
transport.request(params, t.error)
|
||||
})
|
||||
|
||||
t.test('errored', t => {
|
||||
|
||||
Reference in New Issue
Block a user