Better message in case of unsupported build flavor (#1498)
This commit is contained in:
committed by
GitHub
parent
28e57dd2e4
commit
6686316433
@ -54,7 +54,9 @@ of `^7.10.0`).
|
|||||||
|
|
||||||
### Compatibility
|
### Compatibility
|
||||||
|
|
||||||
The library is compatible with all Elasticsearch versions since 5.x, and you should use the same major version of the Elasticsearch instance that you are using.
|
Elastic language clients are guaranteed to be able to communicate with Elasticsearch or Elastic solutions running on the same major version and greater or equal minor version.
|
||||||
|
|
||||||
|
Language clients are forward compatible; meaning that clients support communicating with greater minor versions of Elasticsearch. Elastic language clients are not guaranteed to be backwards compatible.
|
||||||
|
|
||||||
| Elasticsearch Version | Client Version |
|
| Elasticsearch Version | Client Version |
|
||||||
| --------------------- |----------------|
|
| --------------------- |----------------|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ To install a specific major version of the client, run the following command:
|
|||||||
npm install @elastic/elasticsearch@<major>
|
npm install @elastic/elasticsearch@<major>
|
||||||
----
|
----
|
||||||
|
|
||||||
To learn more about the supported major versions, please refer to the
|
To learn more about the supported major versions, please refer to the
|
||||||
<<js-compatibility-matrix>>.
|
<<js-compatibility-matrix>>.
|
||||||
|
|
||||||
[discrete]
|
[discrete]
|
||||||
@ -37,7 +37,7 @@ to support that version for at least another minor release. If you are using the
|
|||||||
with a version of Node.js that will be unsupported soon, you will see a warning
|
with a version of Node.js that will be unsupported soon, you will see a warning
|
||||||
in your logs (the client will start logging the warning with two minors in advance).
|
in your logs (the client will start logging the warning with two minors in advance).
|
||||||
|
|
||||||
Unless you are *always* using a supported version of Node.js,
|
Unless you are *always* using a supported version of Node.js,
|
||||||
we recommend defining the client dependency in your
|
we recommend defining the client dependency in your
|
||||||
`package.json` with the `~` instead of `^`. In this way, you will lock the
|
`package.json` with the `~` instead of `^`. In this way, you will lock the
|
||||||
dependency on the minor release and not the major. (for example, `~7.10.0` instead
|
dependency on the minor release and not the major. (for example, `~7.10.0` instead
|
||||||
@ -62,9 +62,12 @@ of `^7.10.0`).
|
|||||||
[[js-compatibility-matrix]]
|
[[js-compatibility-matrix]]
|
||||||
=== Compatibility matrix
|
=== Compatibility matrix
|
||||||
|
|
||||||
The library is compatible with all {es} versions since 5.x. We recommend you to
|
Elastic language clients are guaranteed to be able to communicate with Elasticsearch
|
||||||
use the same major version of the client as the {es} instance that you are
|
or Elastic solutions running on the same major version and greater or equal minor version.
|
||||||
using.
|
|
||||||
|
Language clients are forward compatible; meaning that clients support communicating
|
||||||
|
with greater minor versions of Elasticsearch. Elastic language clients are not
|
||||||
|
guaranteed to be backwards compatible.
|
||||||
|
|
||||||
[%header,cols=2*]
|
[%header,cols=2*]
|
||||||
|===
|
|===
|
||||||
@ -91,4 +94,4 @@ using.
|
|||||||
WARNING: There is no official support for the browser environment. It exposes
|
WARNING: There is no official support for the browser environment. It exposes
|
||||||
your {es} instance to everyone, which could lead to security issues. We
|
your {es} instance to everyone, which could lead to security issues. We
|
||||||
recommend you to write a lightweight proxy that uses this client instead,
|
recommend you to write a lightweight proxy that uses this client instead,
|
||||||
you can see a proxy example https://github.com/elastic/elasticsearch-js/tree/master/docs/examples/proxy[here].
|
you can see a proxy example https://github.com/elastic/elasticsearch-js/tree/master/docs/examples/proxy[here].
|
||||||
|
|||||||
@ -69,7 +69,7 @@ class Transport {
|
|||||||
this.generateRequestId = opts.generateRequestId || generateRequestId()
|
this.generateRequestId = opts.generateRequestId || generateRequestId()
|
||||||
this.name = opts.name
|
this.name = opts.name
|
||||||
this.opaqueIdPrefix = opts.opaqueIdPrefix
|
this.opaqueIdPrefix = opts.opaqueIdPrefix
|
||||||
this[kProductCheck] = 0 // 0 = to be checked, 1 = checking, 2 = checked-ok, 3 checked-notok
|
this[kProductCheck] = 0 // 0 = to be checked, 1 = checking, 2 = checked-ok, 3 checked-notok, 4 checked-nodefault
|
||||||
this[kApiVersioning] = process.env.ELASTIC_CLIENT_APIVERSIONING === 'true'
|
this[kApiVersioning] = process.env.ELASTIC_CLIENT_APIVERSIONING === 'true'
|
||||||
|
|
||||||
this.nodeFilter = opts.nodeFilter || defaultNodeFilter
|
this.nodeFilter = opts.nodeFilter || defaultNodeFilter
|
||||||
@ -455,9 +455,12 @@ class Transport {
|
|||||||
prepareRequest()
|
prepareRequest()
|
||||||
} else {
|
} else {
|
||||||
// wait for product check to finish
|
// wait for product check to finish
|
||||||
productCheckEmitter.once('product-check', status => {
|
productCheckEmitter.once('product-check', (error, status) => {
|
||||||
if (status === false) {
|
if (status === false) {
|
||||||
const err = new ProductNotSupportedError(result)
|
const err = error || new ProductNotSupportedError(result)
|
||||||
|
if (this[kProductCheck] === 4) {
|
||||||
|
err.message = 'The client noticed that the server is not a supported distribution of Elasticsearch'
|
||||||
|
}
|
||||||
this.emit('request', err, result)
|
this.emit('request', err, result)
|
||||||
process.nextTick(callback, err, result)
|
process.nextTick(callback, err, result)
|
||||||
} else {
|
} else {
|
||||||
@ -470,8 +473,11 @@ class Transport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// the product check is finished and it's not Elasticsearch
|
// the product check is finished and it's not Elasticsearch
|
||||||
} else if (this[kProductCheck] === 3) {
|
} else if (this[kProductCheck] === 3 || this[kProductCheck] === 4) {
|
||||||
const err = new ProductNotSupportedError(result)
|
const err = new ProductNotSupportedError(result)
|
||||||
|
if (this[kProductCheck] === 4) {
|
||||||
|
err.message = 'The client noticed that the server is not a supported distribution of Elasticsearch'
|
||||||
|
}
|
||||||
this.emit('request', err, result)
|
this.emit('request', err, result)
|
||||||
process.nextTick(callback, err, result)
|
process.nextTick(callback, err, result)
|
||||||
// the product check finished and it's Elasticsearch
|
// the product check finished and it's Elasticsearch
|
||||||
@ -550,42 +556,48 @@ class Transport {
|
|||||||
if (err.statusCode === 401 || err.statusCode === 403) {
|
if (err.statusCode === 401 || err.statusCode === 403) {
|
||||||
this[kProductCheck] = 2
|
this[kProductCheck] = 2
|
||||||
process.emitWarning('The client is unable to verify that the server is Elasticsearch due to security privileges on the server side. Some functionality may not be compatible if the server is running an unsupported product.')
|
process.emitWarning('The client is unable to verify that the server is Elasticsearch due to security privileges on the server side. Some functionality may not be compatible if the server is running an unsupported product.')
|
||||||
productCheckEmitter.emit('product-check', true)
|
productCheckEmitter.emit('product-check', null, true)
|
||||||
} else {
|
} else {
|
||||||
this[kProductCheck] = 0
|
this[kProductCheck] = 0
|
||||||
productCheckEmitter.emit('product-check', false)
|
productCheckEmitter.emit('product-check', err, false)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug('Checking elasticsearch version', result.body, result.headers)
|
debug('Checking elasticsearch version', result.body, result.headers)
|
||||||
if (result.body.version == null || typeof result.body.version.number !== 'string') {
|
if (result.body.version == null || typeof result.body.version.number !== 'string') {
|
||||||
debug('Can\'t access Elasticsearch version')
|
debug('Can\'t access Elasticsearch version')
|
||||||
return productCheckEmitter.emit('product-check', false)
|
return productCheckEmitter.emit('product-check', null, false)
|
||||||
}
|
}
|
||||||
const tagline = result.body.tagline
|
const tagline = result.body.tagline
|
||||||
const version = result.body.version.number.split('.')
|
const version = result.body.version.number.split('.')
|
||||||
const major = Number(version[0])
|
const major = Number(version[0])
|
||||||
const minor = Number(version[1])
|
const minor = Number(version[1])
|
||||||
if (major < 6) {
|
if (major < 6) {
|
||||||
return productCheckEmitter.emit('product-check', false)
|
return productCheckEmitter.emit('product-check', null, false)
|
||||||
} else if (major >= 6 && major < 7) {
|
} else if (major >= 6 && major < 7) {
|
||||||
if (tagline !== 'You Know, for Search') {
|
if (tagline !== 'You Know, for Search') {
|
||||||
debug('Bad tagline')
|
debug('Bad tagline')
|
||||||
return productCheckEmitter.emit('product-check', false)
|
return productCheckEmitter.emit('product-check', null, false)
|
||||||
}
|
}
|
||||||
} else if (major === 7 && minor < 14) {
|
} else if (major === 7 && minor < 14) {
|
||||||
if (tagline !== 'You Know, for Search' || result.body.version.build_flavor !== 'default') {
|
if (tagline !== 'You Know, for Search') {
|
||||||
debug('Bad tagline or build_flavor')
|
debug('Bad tagline')
|
||||||
return productCheckEmitter.emit('product-check', false)
|
return productCheckEmitter.emit('product-check', null, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.body.version.build_flavor !== 'default') {
|
||||||
|
debug('Bad build_flavor')
|
||||||
|
this[kProductCheck] = 4
|
||||||
|
return productCheckEmitter.emit('product-check', null, false)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (result.headers['x-elastic-product'] !== 'Elasticsearch') {
|
if (result.headers['x-elastic-product'] !== 'Elasticsearch') {
|
||||||
debug('x-elastic-product not recognized')
|
debug('x-elastic-product not recognized')
|
||||||
return productCheckEmitter.emit('product-check', false)
|
return productCheckEmitter.emit('product-check', null, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug('Valid Elasticsearch distribution')
|
debug('Valid Elasticsearch distribution')
|
||||||
this[kProductCheck] = 2
|
this[kProductCheck] = 2
|
||||||
productCheckEmitter.emit('product-check', true)
|
productCheckEmitter.emit('product-check', null, true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,7 @@ const { Client } = require('../../')
|
|||||||
const {
|
const {
|
||||||
connection: {
|
connection: {
|
||||||
MockConnectionTimeout,
|
MockConnectionTimeout,
|
||||||
|
MockConnectionError,
|
||||||
buildMockConnection
|
buildMockConnection
|
||||||
}
|
}
|
||||||
} = require('../utils')
|
} = require('../utils')
|
||||||
@ -210,7 +211,7 @@ test('No errors ≤v7.13', t => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Errors ≤v7.13', t => {
|
test('Errors ≤v7.13 (tagline)', t => {
|
||||||
t.plan(3)
|
t.plan(3)
|
||||||
const MockConnection = buildMockConnection({
|
const MockConnection = buildMockConnection({
|
||||||
onRequest (params) {
|
onRequest (params) {
|
||||||
@ -222,7 +223,7 @@ test('Errors ≤v7.13', t => {
|
|||||||
cluster_uuid: 'cQ5pAMvRRTyEzObH4L5mTA',
|
cluster_uuid: 'cQ5pAMvRRTyEzObH4L5mTA',
|
||||||
version: {
|
version: {
|
||||||
number: '7.13.0-SNAPSHOT',
|
number: '7.13.0-SNAPSHOT',
|
||||||
build_flavor: 'other',
|
build_flavor: 'default',
|
||||||
build_type: 'docker',
|
build_type: 'docker',
|
||||||
build_hash: '5fb4c050958a6b0b6a70a6fb3e616d0e390eaac3',
|
build_hash: '5fb4c050958a6b0b6a70a6fb3e616d0e390eaac3',
|
||||||
build_date: '2021-07-10T01:45:02.136546168Z',
|
build_date: '2021-07-10T01:45:02.136546168Z',
|
||||||
@ -271,6 +272,83 @@ test('Errors ≤v7.13', t => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Errors ≤v7.13 (build flavor)', t => {
|
||||||
|
t.plan(5)
|
||||||
|
const MockConnection = buildMockConnection({
|
||||||
|
onRequest (params) {
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
body: {
|
||||||
|
name: '1ef419078577',
|
||||||
|
cluster_name: 'docker-cluster',
|
||||||
|
cluster_uuid: 'cQ5pAMvRRTyEzObH4L5mTA',
|
||||||
|
version: {
|
||||||
|
number: '7.13.0-SNAPSHOT',
|
||||||
|
build_flavor: 'other',
|
||||||
|
build_type: 'docker',
|
||||||
|
build_hash: '5fb4c050958a6b0b6a70a6fb3e616d0e390eaac3',
|
||||||
|
build_date: '2021-07-10T01:45:02.136546168Z',
|
||||||
|
build_snapshot: true,
|
||||||
|
lucene_version: '8.9.0',
|
||||||
|
minimum_wire_compatibility_version: '7.15.0',
|
||||||
|
minimum_index_compatibility_version: '7.0.0'
|
||||||
|
},
|
||||||
|
tagline: 'You Know, for Search'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const requests = [{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/'
|
||||||
|
}, {
|
||||||
|
method: 'POST',
|
||||||
|
path: '/foo/_search'
|
||||||
|
}, {
|
||||||
|
method: 'POST',
|
||||||
|
path: '/foo/_search'
|
||||||
|
}]
|
||||||
|
|
||||||
|
const client = new Client({
|
||||||
|
node: 'http://localhost:9200',
|
||||||
|
Connection: MockConnection
|
||||||
|
})
|
||||||
|
|
||||||
|
client.on('request', (err, event) => {
|
||||||
|
const req = requests.shift()
|
||||||
|
if (req.method === 'GET') {
|
||||||
|
t.error(err)
|
||||||
|
} else {
|
||||||
|
t.equal(err.message, 'The client noticed that the server is not a supported distribution of Elasticsearch')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
client.search({
|
||||||
|
index: 'foo',
|
||||||
|
body: {
|
||||||
|
query: {
|
||||||
|
match_all: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, (err, result) => {
|
||||||
|
t.equal(err.message, 'The client noticed that the server is not a supported distribution of Elasticsearch')
|
||||||
|
})
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
client.search({
|
||||||
|
index: 'foo',
|
||||||
|
body: {
|
||||||
|
query: {
|
||||||
|
match_all: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, (err, result) => {
|
||||||
|
t.equal(err.message, 'The client noticed that the server is not a supported distribution of Elasticsearch')
|
||||||
|
})
|
||||||
|
}, 100)
|
||||||
|
})
|
||||||
|
|
||||||
test('No errors v6', t => {
|
test('No errors v6', t => {
|
||||||
t.plan(7)
|
t.plan(7)
|
||||||
const MockConnection = buildMockConnection({
|
const MockConnection = buildMockConnection({
|
||||||
@ -571,7 +649,7 @@ test('500 error', t => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, (err, result) => {
|
}, (err, result) => {
|
||||||
t.equal(err.message, 'The client noticed that the server is not Elasticsearch and we do not support this unknown product.')
|
t.equal(err.message, 'Response Error')
|
||||||
|
|
||||||
client.search({
|
client.search({
|
||||||
index: 'foo',
|
index: 'foo',
|
||||||
@ -608,7 +686,7 @@ test('TimeoutError', t => {
|
|||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
t.error(err)
|
t.error(err)
|
||||||
} else {
|
} else {
|
||||||
t.equal(err.message, 'The client noticed that the server is not Elasticsearch and we do not support this unknown product.')
|
t.equal(err.message, 'Request timed out')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -620,7 +698,45 @@ test('TimeoutError', t => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, (err, result) => {
|
}, (err, result) => {
|
||||||
t.equal(err.message, 'The client noticed that the server is not Elasticsearch and we do not support this unknown product.')
|
t.equal(err.message, 'Request timed out')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('ConnectionError', t => {
|
||||||
|
t.plan(3)
|
||||||
|
|
||||||
|
const requests = [{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/'
|
||||||
|
}, {
|
||||||
|
method: 'POST',
|
||||||
|
path: '/foo/_search'
|
||||||
|
}]
|
||||||
|
|
||||||
|
const client = new Client({
|
||||||
|
node: 'http://localhost:9200',
|
||||||
|
Connection: MockConnectionError,
|
||||||
|
maxRetries: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
client.on('request', (err, event) => {
|
||||||
|
const req = requests.shift()
|
||||||
|
if (req.method === 'GET') {
|
||||||
|
t.error(err)
|
||||||
|
} else {
|
||||||
|
t.equal(err.message, 'Kaboom')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
client.search({
|
||||||
|
index: 'foo',
|
||||||
|
body: {
|
||||||
|
query: {
|
||||||
|
match_all: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, (err, result) => {
|
||||||
|
t.equal(err.message, 'Kaboom')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user