Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verify connection to Elasticsearch #1487

Merged
merged 14 commits into from Jul 19, 2021
Merged

Verify connection to Elasticsearch #1487

merged 14 commits into from Jul 19, 2021

Conversation

delvedor
Copy link
Member

Follows this logic for verifying a connection to Elasticsearch:

Before the first API request:

  1. Make an API request to /, inspect the response:
  2. If call to / fails with 401 or 403 pass the check and show a warning (message will be linked later). This happens if the monitor permission missing for user. The subsequent checks must be ignored.
  3. If there's no version field or if the version field value is <6.0.0 raise an error.
  4. If there is a version field and it's >= 6.0.0 and <7.0.0:
    • If there is no tagline field or if the tagline field value isn't You know, for Search raise an error.
  5. If there is a version field and it's >=7.0.0 and <7.14.0:
    • If there is no tagline field or if the tagline field value isn't You know, for Search raise an error.
    • If there is no build_flavor field or if the build_flavor field value isn't default raise an error.
  6. If there is a version field and it's >=7.14.0:
    • If there is no X-Elastic-Product HTTP header in the response or if the X-Elastic-Product HTTP header value isn't Elasticsearch raise an error.

@mshustov
Copy link
Contributor

Kibana implements a periodical version check as well https://github.com/elastic/kibana/blob/ef6b84dfa544a4677e1a33e911ef484979b5af17/src/core/server/elasticsearch/version_check/ensure_es_version.ts#L142 but both checks complement each other.

Before the first API request:

I guess we need to handle the incompatibility error in a special way to stop the Kibana instance. It might require additional work on the Kibana side to trigger @elastic/elasticsearch version check. Are you going to ship the check in v8.0 or v7.x?

lib/Transport.js Outdated Show resolved Hide resolved
@delvedor
Copy link
Member Author

@mshustov the check will be shipped in v7.

@mshustov
Copy link
Contributor

@delvedor in which version? I will fill out an ER for the Kibana.

index.js Outdated
Comment on lines 258 to 260
// sync product check
const tSymbols = Object.getOwnPropertySymbols(this.transport)
client.transport[tSymbols[0]] = this.transport[tSymbols[0]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems a bit fragile IMO to rely on the order of when the symbols were assigned outside the Transport class. Would it make sense to add a function like this.transport.sync(client.transport) so that the order of the symbols does not need to be relied on?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call out, I'll see what I can do.

if (err) {
if (err.statusCode === 401 || err.statusCode === 403) {
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.')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think this wording would be more clear

Suggested change
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 an authentication error with the server. Some functionality may not be compatible if the server is running an unsupported product.')

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like your suggestion, but this message cannot be changed as it has already been approved by product :)

@@ -494,6 +536,51 @@ class Transport {
callback(null, hosts)
})
}

productCheck () {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add any debug logging to this check so that we can easily find problems with it if it's not working as intended? Specifically, it'd be helpful to be able to inspect the response from Elasticsearch and know which branch failed the check.

productCheckEmitter.emit('product-check', false)
}
} else {
if (result.body.version == null || typeof result.body.version.number !== 'string') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO I'd rather not rely on loose equality between undefined and null and would add an explicit check here. If nothing else, this makes it clear that this case should be tested.

Suggested change
if (result.body.version == null || typeof result.body.version.number !== 'string') {
if (result.body.version === null || result.body.version === undefined || typeof result.body.version.number !== 'string') {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, when you are checking for both null and undefined, doing == null does the job pretty well, as it's testing for both.

cluster_name: 'docker-cluster',
cluster_uuid: 'cQ5pAMvRRTyEzObH4L5mTA',
version: {
number: '8.0.0-SNAPSHOT',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Should we be using SNAPSHOT in the test data? (applies to all of these tests)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that we are only looking for the first two numbers it's fine :)

Comment on lines +171 to +173
lucene_version: '8.9.0',
minimum_wire_compatibility_version: '7.15.0',
minimum_index_compatibility_version: '7.0.0'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I don't think these are correct for any of the 7.x/6.x/5.x/4.x tests. They're not being used by the check right now, but it seems worth making sure this tests data is close to being accurate in case we do use these fields in the future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I only changed the fields that we need to validate.
Given that from 7.14 we'll only test the response headers there is no need to make this too much future proof. I'll revisit if needed :)

const MockConnection = buildMockConnection({
onRequest (params) {
return {
statusCode: 401,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add test for 403 case for full coverage

@delvedor delvedor merged commit 17c744e into master Jul 19, 2021
@delvedor delvedor deleted the product-check branch July 19, 2021 14:42
github-actions bot pushed a commit that referenced this pull request Jul 19, 2021
delvedor added a commit that referenced this pull request Jul 19, 2021
Co-authored-by: Tomas Della Vedova <delvedor@users.noreply.github.com>
delvedor added a commit that referenced this pull request Jul 19, 2021
return productCheckEmitter.emit('product-check', false)
}
} else if (major === 7 && minor < 14) {
if (tagline !== 'You Know, for Search' || result.body.version.build_flavor !== 'default') {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI this breaks support for the oss docker images <= 7.10.1.
The build_flavor in there s oss.

{
  "name" : "elasticsearch-production-2",
  "cluster_name" : "elasticsearch-bmg-prd",
  "cluster_uuid" : "41tljEp7T66B-13N2zaE4A",
  "version" : {
    "number" : "7.10.1",
    "build_flavor" : "oss",
    "build_type" : "docker",
    "build_hash" : "1c34507e66d7db1211f66f3513706fdf548736aa",
    "build_date" : "2020-12-05T01:00:33.671820Z",
    "build_snapshot" : false,
    "lucene_version" : "8.7.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

While an upgrade to a newer image fixes the incompatibility, you might want to adopt the check in here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello! Please see #1519.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Thomas, that's then on purpose as I've assumed. There's just no mention in this PR, which could have the change a bit more transparent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants