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

[data views] Create runtime field - use execute api #134713

Merged
merged 11 commits into from
Jun 27, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,7 @@ describe('Field editor Preview panel', () => {
subTitle: 'First doc - subTitle',
title: 'First doc - title',
},
documentId: '001',
index: 'testIndexPattern',
index: 'testIndex',
script: {
source: 'echo("hello")',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,10 @@ export const FieldPreviewProvider: FunctionComponent = ({ children }) => {
const currentApiCall = ++previewCount.current;

const response = await getFieldPreview({
index: dataView.title,
index: currentDocIndex,
document: document!,
context: `${type!}_field` as PainlessExecuteContext,
script: script!,
documentId: currentDocId,
});

if (currentApiCall !== previewCount.current) {
Expand Down Expand Up @@ -391,7 +390,7 @@ export const FieldPreviewProvider: FunctionComponent = ({ children }) => {
allParamsDefined,
scriptEditorValidation,
hasSomeParamsChanged,
dataView.title,
currentDocIndex,
]);

const goToNextDoc = useCallback(() => {
Expand Down
3 changes: 0 additions & 3 deletions src/plugins/data_view_field_editor/public/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@ export const initApi = (httpClient: HttpSetup) => {
context,
script,
document,
documentId,
}: {
index: string;
context: PainlessExecuteContext;
script: { source: string } | null;
document: Record<string, any>;
documentId: string;
}) => {
return sendRequest<FieldPreviewResponse>(httpClient, {
path: `${API_BASE_PATH}/field_preview`,
Expand All @@ -32,7 +30,6 @@ export const initApi = (httpClient: HttpSetup) => {
context,
script,
document,
documentId,
},
});
};
Expand Down
45 changes: 12 additions & 33 deletions src/plugins/data_view_field_editor/server/routes/field_preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* Side Public License, v 1.
*/

import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { schema } from '@kbn/config-schema';
import { HttpResponsePayload } from '@kbn/core/server';

import { API_BASE_PATH } from '../../common/constants';
import { RouteDependencies } from '../types';
Expand All @@ -26,7 +26,6 @@ const bodySchema = schema.object({
schema.literal('long_field'),
]),
document: schema.object({}, { unknowns: 'allow' }),
documentId: schema.string(),
});

export const registerFieldPreviewRoute = ({ router }: RouteDependencies): void => {
Expand All @@ -40,48 +39,28 @@ export const registerFieldPreviewRoute = ({ router }: RouteDependencies): void =
async (ctx, req, res) => {
const { client } = (await ctx.core).elasticsearch;

const type = req.body.context.split('_field')[0] as estypes.MappingRuntimeFieldType;
const body = {
runtime_mappings: {
my_runtime_field: {
type,
script: req.body.script,
},
},
size: 1,
query: {
term: {
_id: req.body.documentId,
},
script: req.body.script,
context: req.body.context,
context_setup: {
document: req.body.document,
index: req.body.index,
},
fields: ['my_runtime_field'],
};

try {
// Ideally we want to use the Painless _execute API to get the runtime field preview.
// There is a current ES limitation that requires a user to have too many privileges
// to execute the script. (issue: https://github.com/elastic/elasticsearch/issues/48856)
// Until we find a way to execute a script without advanced privileges we are going to
// use the Search API to get the field value (and possible errors).
// Note: here is the PR were we changed from using Painless _execute to _search and should be
// reverted when the ES issue is fixed: https://github.com/elastic/kibana/pull/115070
const response = await client.asCurrentUser.search({
index: req.body.index,
body,
});

const fieldValue = response.hits.hits[0]?.fields?.my_runtime_field ?? '';
// client types need to be update to support this request format
// @ts-expect-error
const { result } = await client.asCurrentUser.scriptsPainlessExecute(body);
const fieldValue = result as HttpResponsePayload;

return res.ok({ body: { values: fieldValue } });
} catch (error: any) {
} catch (error) {
// Assume invalid painless script was submitted
// Return 200 with error object
const handleCustomError = () => {
return res.ok({
body: {
values: [],
error: error.body.error.failed_shards[0]?.reason ?? {},
},
body: { values: [], ...error.body },
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { FtrProviderContext } from '../../ftr_provider_context';
import { API_BASE_PATH } from './constants';

const INDEX_NAME = 'api-integration-test-field-preview';
const DOC_ID = '1';

export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
Expand All @@ -39,26 +38,14 @@ export default function ({ getService }: FtrProviderContext) {
});
};

const addDoc = async () => {
await es.index({
index: INDEX_NAME,
id: DOC_ID,
body: document,
refresh: 'wait_for',
});
};

const deleteIndex = async () => {
await es.indices.delete({
index: INDEX_NAME,
});
};

describe('Field preview', function () {
before(async () => {
await createIndex();
await addDoc();
});
before(async () => await createIndex());
after(async () => await deleteIndex());

describe('should return the script value', () => {
Expand Down Expand Up @@ -91,7 +78,6 @@ export default function ({ getService }: FtrProviderContext) {
const payload = {
script: test.script,
document,
documentId: DOC_ID,
context: test.context,
index: INDEX_NAME,
};
Expand Down Expand Up @@ -153,7 +139,6 @@ export default function ({ getService }: FtrProviderContext) {
script: { source: 'emit(123)' }, // We send a long but the type is "keyword"
context: 'keyword_field',
index: INDEX_NAME,
documentId: DOC_ID,
})
.set('kbn-xsrf', 'xxx');

Expand Down