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

[KP] use new ES client in SO service #72289

Merged
merged 44 commits into from
Jul 25, 2020
Merged

Conversation

mshustov
Copy link
Contributor

@mshustov mshustov commented Jul 17, 2020

Summary

  • Refactors SO service to use https://github.com/elastic/elasticsearch-js under the hood.
    It should not affect public API since we return only the response body from SO API methods.
    However, this change might affect plugins reading response status field from SO error bubbled to the Solutions code since ES error doesn't provide status field anymore (statusCode is still provided).
  • Adjusts several plugins to check SO errors with SavedObjectsErrorHelpers. Plugins must use it because we are going to stop wrapping errors in the Boom object Do not wrap SO errors in Boom #72441
Comments on client integration problems @delvedor:

Comments on client integration problems @delvedor:

  • lack of response types. I had to added DeleteDocumentResponse, GetResponse and SearchResponse manually from the legacy client interface.
  • update, bulk methods interface incompatible. before: refresh: boolean | 'wait_for'. after: refresh: 'true' | 'false' | 'wait_for'
    // @ts-expect-error refresh?: 'true' | 'false' | 'wait_for' in Client
    refresh,

    It's possible to cast to String type, but it's rather clumsy in TS.
function toRefresh(refresh?: MutatingOperationRefreshSetting) {
  if (refresh === undefined) return;
  if (refresh === true) return 'true';
  if (refresh === false) return 'false';
  return refresh;
}
  • updateByQuery. accepts refresh?: boolean; is it expected? shouldn't it have a compatible interface with refresh: 'true' | 'false' | 'wait_for'?
  • there are no _seq_no, _primary_term fields in ES document returned from update, get methods https://www.elastic.co/guide/en/elasticsearch/reference/master/optimistic-concurrency-control.html
  • Several times I had runtime exceptions because all request params extends Generic type containing ignore?: number | number[];, however, it had been failing argument validation until I moved ignore: [404] to the transport options.
// no TS error. runtime exception
await client.mget({body: ..., ignore: [404] });
// no TS error. no runtime exception
await client.mget({body: ... }, { ignore: [404] });
  • TransportRequestPromise usage makes wrapping in an async function incompatible
async function logError(fn: () => Promise<T>): Promise<T> {
  try{
    return await fn();
  } catch(e){
    console.log(e);
    throw e;
  }
}

Checklist

For maintainers

@mshustov mshustov added chore Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc release_note:skip Skip the PR/issue when compiling release notes v7.10.0 labels Jul 17, 2020
@delvedor
Copy link
Member

lack of response types. I had to added DeleteDocumentResponse, GetResponse and SearchResponse manually from the legacy client interface.

We are aware of this, unfortunately, the rest-api-spec is not complete in that regard. We are working for improving the situation, I'll keep you posted.

update, bulk methods interface incompatible. before: refresh: boolean | 'wait_for'. after: refresh: 'true' | 'false' | 'wait_for'

We are using the rest-api-spec for generating the types, and as you can see they are listed as strings. I agree that it should be boolean | 'wait_for, as the serialization is an implementation detail. I'll update the code generation to address this.

updateByQuery. accepts refresh?: boolean; is it expected? shouldn't it have a compatible interface with refresh: 'true' | 'false' | 'wait_for'?

This is how it's defined in the rest-api-spec, I'll ping the ES team for understanding if it's correct or is missing an option.

there are no _seq_no, _primary_term fields in ES document returned from update, get methods https://www.elastic.co/guide/en/elasticsearch/reference/master/optimistic-concurrency-control.html

The client is not doing anything with the Elasticsearch response, so if a field is missing, it means that ES is not sending it out.

Several times I had runtime exceptions because all request params extends Generic type containing ignore?: number | number[];, however, it had been failing argument validation until I moved ignore: [404] to the transport options.

This is a bug in the types, I'll fix it :)

TransportRequestPromise usage makes wrapping in an async function incompatible

This is "correct", as TransportRequestPromise contains an abort method as well.

import { ApiResponse } from './'
import { TransportRequestPromise } from './lib/Transport'

async function logError (fn: () => TransportRequestPromise<ApiResponse>): Promise<ApiResponse> {
  try{
    return await fn()
  } catch(e){
    console.log(e)
    throw e
  }
}

all camelCase request params renamed to snake_case. It's not mentioned in https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/breaking-changes.html

This is a fun one :P
The JavaScript code allows both (and I regret this decision), while the TypeScript one allows snake:case only. The reason is because if TypeScript would allows both styles, it would not be possible defining which parameters are required and which not. I've decided to force people to use snake_case for two reasons, the first is because inside the body you are forced to use snake_case anyhow, the second is because transforming every parameter from camelCase to snake_case at runtime is expensive, and it's better to just use snake_case.

@mshustov mshustov requested a review from a team July 21, 2020 12:35
@mshustov mshustov requested review from a team as code owners July 21, 2020 12:35
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-platform (Team:Platform)

@botelastic botelastic bot added Team:APM All issues that need APM UI Team support Team:Fleet Team label for Observability Data Collection Fleet team labels Jul 21, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/apm-ui (Team:apm)

@elasticmachine
Copy link
Contributor

Pinging @elastic/ingest-management (Team:Ingest Management)

Copy link
Member

@sorenlouv sorenlouv left a comment

Choose a reason for hiding this comment

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

APM changes lgtm

Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

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

Some nits and comments, overall LGTM

src/core/server/elasticsearch/client/mocks.ts Outdated Show resolved Hide resolved
src/core/server/elasticsearch/client/mocks.ts Outdated Show resolved Hide resolved
src/core/server/elasticsearch/client/configure_client.ts Outdated Show resolved Hide resolved
@@ -109,6 +109,7 @@ export {
LegacyAPICaller,
FakeRequest,
ScopeableRequest,
ElasticsearchClient,
Copy link
Contributor

Choose a reason for hiding this comment

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

NIT: Why exposing it now? Should we wait until we officially exposes the API to plugins?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I used it in the integration tests.

const esClient = getService('es');

I don't want to expose raw Client there. Also, exposing a type doesn't hurt us a lot.

src/core/server/saved_objects/service/lib/repository.ts Outdated Show resolved Hide resolved
const deleteDocNotFound = deleteResponse.result === 'not_found';
const deleteIndexNotFound =
deleteResponse.error && deleteResponse.error.type === 'index_not_found_exception';
const deleteDocNotFound = body.result === 'not_found';
Copy link
Contributor

Choose a reason for hiding this comment

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

It was already like that, but wouldn't check on statusCode be better?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't want to take a risk to change this code without talking to an author. From the source code, it seems that there could be different reasons for Not found response https://github.com/elastic/elasticsearch/blob/b7062391452dbe82c552fa2bb2d5a31f64667b1d/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java

Copy link
Contributor

@cjcenizal cjcenizal left a comment

Choose a reason for hiding this comment

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

Upgrade Assistant changes LGTM, didn't test locally.

Copy link
Contributor

@jen-huang jen-huang left a comment

Choose a reason for hiding this comment

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

Ingest Manager changes LGTM

@@ -56,7 +56,7 @@ export const createEndpointList = async ({
);
return transformSavedObjectToExceptionList({ savedObject });
} catch (err) {
if (err.status === 409) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TODO: to make sure it's listed in the migration guide

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Build metrics

✅ unchanged

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@mshustov mshustov merged commit 2a82ff9 into elastic:master Jul 25, 2020
@mshustov mshustov deleted the pr/71412 branch July 25, 2020 10:00
mshustov added a commit to mshustov/kibana that referenced this pull request Jul 25, 2020
* adapt retryCallCluster for new ES client

* review comments

* retry on 408 ResponseError

* remove legacy retry functions

* use Migrator Es client in SO migration

* update migration tests

* improve ES typings and mocks

* migrate decorate ES errors

* add repository es client

* use new es client in so repository

* update repository tests

* fix migrator integration tests

* declare _seq_no & _primary_term on get response. _source expect to be a string

* make _sourceIncludes and refresh compatible with the client

* add test for repository_es_client

* move ApiResponse to es client mocks

* TEMP: handle wait_for as true for deleteByNamespace

* add tests for migration_es_client

* TEMP: skip test for deleteByNamespace refresh

* pass ignore as transport option in mget

* log both es client and response errors

* fix update method test failures

* update deleteByNamespace refresh settings

es doesn't support 'refresh: wait_for' for `updateByQuery` endpoint

* update repository tests. we do not allow customising wait_for

* do not delegate retry logic to es client

* fix type errors after master merged

* fix repository tests

* fix security solutions code

SO doesn't throw Error with status code anymore. Always use SO error helpers

* switch error conditions to use SO error helpers

* cleanup

* address comments about mocks

* use isResponseError helper

* address comments

* fix type errors

Co-authored-by: pgayvallet <[email protected]>
mshustov added a commit that referenced this pull request Jul 25, 2020
* adapt retryCallCluster for new ES client

* review comments

* retry on 408 ResponseError

* remove legacy retry functions

* use Migrator Es client in SO migration

* update migration tests

* improve ES typings and mocks

* migrate decorate ES errors

* add repository es client

* use new es client in so repository

* update repository tests

* fix migrator integration tests

* declare _seq_no & _primary_term on get response. _source expect to be a string

* make _sourceIncludes and refresh compatible with the client

* add test for repository_es_client

* move ApiResponse to es client mocks

* TEMP: handle wait_for as true for deleteByNamespace

* add tests for migration_es_client

* TEMP: skip test for deleteByNamespace refresh

* pass ignore as transport option in mget

* log both es client and response errors

* fix update method test failures

* update deleteByNamespace refresh settings

es doesn't support 'refresh: wait_for' for `updateByQuery` endpoint

* update repository tests. we do not allow customising wait_for

* do not delegate retry logic to es client

* fix type errors after master merged

* fix repository tests

* fix security solutions code

SO doesn't throw Error with status code anymore. Always use SO error helpers

* switch error conditions to use SO error helpers

* cleanup

* address comments about mocks

* use isResponseError helper

* address comments

* fix type errors

Co-authored-by: pgayvallet <[email protected]>

Co-authored-by: pgayvallet <[email protected]>
gmmorris added a commit to gmmorris/kibana that referenced this pull request Jul 27, 2020
* master: (111 commits)
  Remove flaky note from gauge tests (elastic#73240)
  Convert functional vega tests to ts and unskip tests (elastic#72238)
  [Graph] Unskip graph tests (elastic#72291)
  Add default Elasticsearch credentials to docs (elastic#72617)
  [APM] Read body from indicesStats in upload-telemetry-data (elastic#72732)
  The directory in the command was missing the /generated directory and would cause all definitions to be regenerated in the wrong place. (elastic#72766)
  [KP] use new ES client in SO service (elastic#72289)
  [Security Solution][Exceptions] Prevents value list entries from co-existing with non value list entries (elastic#72995)
  Return EUI CSS to Shareable Runtime (elastic#72990)
  Removed useless karma test (elastic#73190)
  [INGEST_MANAGER] Make package config name blank for endpoint on Package Config create (elastic#73082)
  [Ingest Manager] Support DEGRADED state in fleet agent event (elastic#73104)
  [Security Solution][Detections] Change detections breadcrumb title (elastic#73059)
  [ML] Fixing unnecessary deleting job polling (elastic#73087)
  [ML] Fixing recognizer wizard create job button (elastic#73025)
  [Composable template] Preview composite template (elastic#72598)
  [Uptime] Use manual intervals for ping histogram (elastic#72928)
  [Security Solution][Endpoint] Task/policy save modal text change, remove duplicate policy details text (elastic#73130)
  [Maps] fix tile layer attibution text and attribution link validation errors (elastic#73160)
  skip ingest pipeline api tests
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backported chore release_note:plugin_api_changes Contains a Plugin API changes section for the breaking plugin API changes section. Team:APM All issues that need APM UI Team support Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc Team:Fleet Team label for Observability Data Collection Fleet team v7.10.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants