From 41b5f5337dbe92a176578375d0f99f7daf40616d Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Fri, 15 Jan 2021 11:33:44 -0500 Subject: [PATCH] update painless_lab to use new es-js client --- .../errors/handle_es_error.ts | 12 ++++- .../painless_lab/server/routes/api/execute.ts | 23 ++++----- .../painless_lab/server/shared_imports.ts | 2 +- x-pack/test/api_integration/apis/index.ts | 1 + .../apis/painless_lab/index.ts | 13 +++++ .../apis/painless_lab/painless_lab.ts | 49 +++++++++++++++++++ 6 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 x-pack/test/api_integration/apis/painless_lab/index.ts create mode 100644 x-pack/test/api_integration/apis/painless_lab/painless_lab.ts diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts index 1c3643898dd1d9..752fe864aca2d1 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts @@ -24,14 +24,24 @@ import { IKibanaResponse, KibanaResponseFactory } from 'kibana/server'; interface EsErrorHandlerParams { error: ApiError; response: KibanaResponseFactory; + handleCustomError?: () => IKibanaResponse; } /* * For errors returned by the new elasticsearch js client. */ -export const handleEsError = ({ error, response }: EsErrorHandlerParams): IKibanaResponse => { +export const handleEsError = ({ + error, + response, + handleCustomError, +}: EsErrorHandlerParams): IKibanaResponse => { // error.name is slightly better in terms of performance, since all errors now have name property if (error.name === 'ResponseError') { + // The consumer may sometimes want to provide a custom response + if (typeof handleCustomError === 'function') { + return handleCustomError(); + } + const { statusCode, body } = error as ResponseError; return response.customError({ statusCode, diff --git a/x-pack/plugins/painless_lab/server/routes/api/execute.ts b/x-pack/plugins/painless_lab/server/routes/api/execute.ts index 7bb2d9f93c6fcf..44529d7bacbd4c 100644 --- a/x-pack/plugins/painless_lab/server/routes/api/execute.ts +++ b/x-pack/plugins/painless_lab/server/routes/api/execute.ts @@ -7,7 +7,7 @@ import { schema } from '@kbn/config-schema'; import { API_BASE_PATH } from '../../../common/constants'; import { RouteDependencies } from '../../types'; -import { isEsError } from '../../shared_imports'; +import { handleEsError } from '../../shared_imports'; const bodySchema = schema.string(); @@ -23,23 +23,24 @@ export function registerExecuteRoute({ router, license }: RouteDependencies) { const body = req.body; try { - const callAsCurrentUser = ctx.core.elasticsearch.legacy.client.callAsCurrentUser; - const response = await callAsCurrentUser('scriptsPainlessExecute', { + const client = ctx.core.elasticsearch.client.asCurrentUser; + const response = await client.scriptsPainlessExecute({ body, }); return res.ok({ - body: response, + body: response.body, }); - } catch (e) { - if (isEsError(e)) { - // Assume invalid painless script was submitted - // Return 200 with error object + } catch (error) { + // Assume invalid painless script was submitted + // Return 200 with error object + const handleCustomError = () => { return res.ok({ - body: e.body, + body: error.body, }); - } - return res.internalError({ body: e }); + }; + + return handleEsError({ error, response: res, handleCustomError }); } }) ); diff --git a/x-pack/plugins/painless_lab/server/shared_imports.ts b/x-pack/plugins/painless_lab/server/shared_imports.ts index 454beda5394c71..068cddcee4c86a 100644 --- a/x-pack/plugins/painless_lab/server/shared_imports.ts +++ b/x-pack/plugins/painless_lab/server/shared_imports.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { isEsError } from '../../../../src/plugins/es_ui_shared/server'; +export { handleEsError } from '../../../../src/plugins/es_ui_shared/server'; diff --git a/x-pack/test/api_integration/apis/index.ts b/x-pack/test/api_integration/apis/index.ts index 6b6326df017aaa..6c9c34b5598aee 100644 --- a/x-pack/test/api_integration/apis/index.ts +++ b/x-pack/test/api_integration/apis/index.ts @@ -33,5 +33,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./transform')); loadTestFile(require.resolve('./lists')); loadTestFile(require.resolve('./upgrade_assistant')); + loadTestFile(require.resolve('./painless_lab')); }); } diff --git a/x-pack/test/api_integration/apis/painless_lab/index.ts b/x-pack/test/api_integration/apis/painless_lab/index.ts new file mode 100644 index 00000000000000..7ccd7c5691e565 --- /dev/null +++ b/x-pack/test/api_integration/apis/painless_lab/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('Painless Lab', () => { + loadTestFile(require.resolve('./painless_lab')); + }); +} diff --git a/x-pack/test/api_integration/apis/painless_lab/painless_lab.ts b/x-pack/test/api_integration/apis/painless_lab/painless_lab.ts new file mode 100644 index 00000000000000..c78ceaaa814379 --- /dev/null +++ b/x-pack/test/api_integration/apis/painless_lab/painless_lab.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +const API_BASE_PATH = '/api/painless_lab'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('Painless Lab', function () { + describe('Execute', () => { + it('should execute a valid painless script', async () => { + const script = + '"{\\n \\"script\\": {\\n \\"source\\": \\"return true;\\",\\n \\"params\\": {\\n \\"string_parameter\\": \\"string value\\",\\n \\"number_parameter\\": 1.5,\\n \\"boolean_parameter\\": true\\n}\\n }\\n}"'; + + const { body } = await supertest + .post(`${API_BASE_PATH}/execute`) + .set('kbn-xsrf', 'xxx') + .set('Content-Type', 'application/json;charset=UTF-8') + .send(script) + .expect(200); + + expect(body).to.eql({ + result: 'true', + }); + }); + + it('should return error response for invalid painless script', async () => { + const invalidScript = + '"{\\n \\"script\\": {\\n \\"source\\": \\"foobar\\",\\n \\"params\\": {\\n \\"string_parameter\\": \\"string value\\",\\n \\"number_parameter\\": 1.5,\\n \\"boolean_parameter\\": true\\n}\\n }\\n}"'; + + const { body } = await supertest + .post(`${API_BASE_PATH}/execute`) + .set('kbn-xsrf', 'xxx') + .set('Content-Type', 'application/json;charset=UTF-8') + .send(invalidScript) + .expect(200); + + expect(body.error).to.not.be(undefined); + expect(body.error.reason).to.eql('compile error'); + }); + }); + }); +}