[data views] data_views REST API (#112916)

* initial stab at changing endpoints to data_view while keeping existing endpoints

* partial progress

* partial progress

* partial progress on multiple fields returned

* partial progress on multiple fields returned

* partial progress on multiple fields returned

* correct response - index_pattern => data_view

* fix legacy key

* update runtime field responses to return array of fields instead of since field value

* complete tests for data views api

* fix export

* more tests

* fix types for data view create

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Matthew Kime 2022-01-06 07:15:05 -06:00 committed by GitHub
parent 00d1ad30f4
commit e62768a9c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 2955 additions and 2478 deletions

View file

@ -0,0 +1,27 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export const SERVICE_PATH = '/api/data_views';
export const SERVICE_PATH_LEGACY = '/api/index_patterns';
export const DATA_VIEW_PATH = `${SERVICE_PATH}/data_view`;
export const DATA_VIEW_PATH_LEGACY = `${SERVICE_PATH_LEGACY}/index_pattern`;
export const SPECIFIC_DATA_VIEW_PATH = `${DATA_VIEW_PATH}/{id}`;
export const SPECIFIC_DATA_VIEW_PATH_LEGACY = `${DATA_VIEW_PATH_LEGACY}/{id}`;
export const RUNTIME_FIELD_PATH = `${SPECIFIC_DATA_VIEW_PATH}/runtime_field`;
export const RUNTIME_FIELD_PATH_LEGACY = `${SPECIFIC_DATA_VIEW_PATH_LEGACY}/runtime_field`;
export const SPECIFIC_RUNTIME_FIELD_PATH = `${RUNTIME_FIELD_PATH}/{name}`;
export const SPECIFIC_RUNTIME_FIELD_PATH_LEGACY = `${RUNTIME_FIELD_PATH_LEGACY}/{name}`;
export const SCRIPTED_FIELD_PATH = `${SPECIFIC_DATA_VIEW_PATH}/scripted_field`;
export const SCRIPTED_FIELD_PATH_LEGACY = `${SPECIFIC_DATA_VIEW_PATH_LEGACY}/scripted_field`;
export const SPECIFIC_SCRIPTED_FIELD_PATH = `${SCRIPTED_FIELD_PATH}/{name}`;
export const SPECIFIC_SCRIPTED_FIELD_PATH_LEGACY = `${SCRIPTED_FIELD_PATH_LEGACY}/{name}`;
export const SERVICE_KEY = 'data_view';
export const SERVICE_KEY_LEGACY = 'index_pattern';
export type SERVICE_KEY_TYPE = typeof SERVICE_KEY | typeof SERVICE_KEY_LEGACY;

View file

@ -35,3 +35,24 @@ export type {
DataViewsServerPluginStart as PluginStart,
};
export { DataViewsServerPlugin as Plugin };
export {
SERVICE_PATH,
SERVICE_PATH_LEGACY,
DATA_VIEW_PATH,
DATA_VIEW_PATH_LEGACY,
SPECIFIC_DATA_VIEW_PATH,
SPECIFIC_DATA_VIEW_PATH_LEGACY,
RUNTIME_FIELD_PATH,
RUNTIME_FIELD_PATH_LEGACY,
SPECIFIC_RUNTIME_FIELD_PATH,
SPECIFIC_RUNTIME_FIELD_PATH_LEGACY,
SCRIPTED_FIELD_PATH,
SCRIPTED_FIELD_PATH_LEGACY,
SPECIFIC_SCRIPTED_FIELD_PATH,
SPECIFIC_SCRIPTED_FIELD_PATH_LEGACY,
SERVICE_KEY,
SERVICE_KEY_LEGACY,
} from './constants';
export type { SERVICE_KEY_TYPE } from './constants';

View file

@ -9,24 +9,62 @@
import { schema } from '@kbn/config-schema';
import { HttpServiceSetup, StartServicesAccessor } from 'kibana/server';
import { IndexPatternsFetcher } from './fetcher';
import { registerCreateIndexPatternRoute } from './routes/create_index_pattern';
import { registerGetIndexPatternRoute } from './routes/get_index_pattern';
import { registerDeleteIndexPatternRoute } from './routes/delete_index_pattern';
import { registerUpdateIndexPatternRoute } from './routes/update_index_pattern';
import { registerUpdateFieldsRoute } from './routes/fields/update_fields';
import {
registerCreateDataViewRoute,
registerCreateDataViewRouteLegacy,
} from './routes/create_index_pattern';
import {
registerGetDataViewRoute,
registerGetDataViewRouteLegacy,
} from './routes/get_index_pattern';
import {
registerDeleteDataViewRoute,
registerDeleteDataViewRouteLegacy,
} from './routes/delete_index_pattern';
import {
registerUpdateDataViewRoute,
registerUpdateDataViewRouteLegacy,
} from './routes/update_index_pattern';
import {
registerUpdateFieldsRoute,
registerUpdateFieldsRouteLegacy,
} from './routes/fields/update_fields';
import { registerCreateScriptedFieldRoute } from './routes/scripted_fields/create_scripted_field';
import { registerPutScriptedFieldRoute } from './routes/scripted_fields/put_scripted_field';
import { registerGetScriptedFieldRoute } from './routes/scripted_fields/get_scripted_field';
import { registerDeleteScriptedFieldRoute } from './routes/scripted_fields/delete_scripted_field';
import { registerUpdateScriptedFieldRoute } from './routes/scripted_fields/update_scripted_field';
import {
registerManageDefaultDataViewRoute,
registerManageDefaultDataViewRouteLegacy,
} from './routes/default_index_pattern';
import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from './types';
import { registerManageDefaultIndexPatternRoutes } from './routes/default_index_pattern';
import { registerCreateRuntimeFieldRoute } from './routes/runtime_fields/create_runtime_field';
import { registerGetRuntimeFieldRoute } from './routes/runtime_fields/get_runtime_field';
import { registerDeleteRuntimeFieldRoute } from './routes/runtime_fields/delete_runtime_field';
import { registerPutRuntimeFieldRoute } from './routes/runtime_fields/put_runtime_field';
import { registerUpdateRuntimeFieldRoute } from './routes/runtime_fields/update_runtime_field';
import { registerHasUserIndexPatternRoute } from './routes/has_user_index_pattern';
import {
registerCreateRuntimeFieldRoute,
registerCreateRuntimeFieldRouteLegacy,
} from './routes/runtime_fields/create_runtime_field';
import {
registerGetRuntimeFieldRoute,
registerGetRuntimeFieldRouteLegacy,
} from './routes/runtime_fields/get_runtime_field';
import {
registerDeleteRuntimeFieldRoute,
registerDeleteRuntimeFieldRouteLegacy,
} from './routes/runtime_fields/delete_runtime_field';
import {
registerPutRuntimeFieldRoute,
registerPutRuntimeFieldRouteLegacy,
} from './routes/runtime_fields/put_runtime_field';
import {
registerUpdateRuntimeFieldRoute,
registerUpdateRuntimeFieldRouteLegacy,
} from './routes/runtime_fields/update_runtime_field';
import {
registerHasUserDataViewRoute,
registerHasUserDataViewRouteLegacy,
} from './routes/has_user_index_pattern';
import { registerFieldForWildcard } from './fields_for';
export function registerRoutes(
@ -48,17 +86,37 @@ export function registerRoutes(
const router = http.createRouter();
// Index Patterns API
registerCreateIndexPatternRoute(router, getStartServices);
registerGetIndexPatternRoute(router, getStartServices);
registerDeleteIndexPatternRoute(router, getStartServices);
registerUpdateIndexPatternRoute(router, getStartServices);
registerManageDefaultIndexPatternRoutes(router, getStartServices);
registerHasUserIndexPatternRoute(router, getStartServices);
// Data Views API
registerCreateDataViewRoute(router, getStartServices);
registerGetDataViewRoute(router, getStartServices);
registerDeleteDataViewRoute(router, getStartServices);
registerUpdateDataViewRoute(router, getStartServices);
registerManageDefaultDataViewRoute(router, getStartServices);
registerHasUserDataViewRoute(router, getStartServices);
// Fields API
registerUpdateFieldsRoute(router, getStartServices);
// Runtime Fields API
registerCreateRuntimeFieldRoute(router, getStartServices);
registerGetRuntimeFieldRoute(router, getStartServices);
registerDeleteRuntimeFieldRoute(router, getStartServices);
registerPutRuntimeFieldRoute(router, getStartServices);
registerUpdateRuntimeFieldRoute(router, getStartServices);
// ###
// Legacy Index Pattern API
// ###
registerCreateDataViewRouteLegacy(router, getStartServices);
registerGetDataViewRouteLegacy(router, getStartServices);
registerDeleteDataViewRouteLegacy(router, getStartServices);
registerUpdateDataViewRouteLegacy(router, getStartServices);
registerManageDefaultDataViewRouteLegacy(router, getStartServices);
registerHasUserDataViewRouteLegacy(router, getStartServices);
// Fields API
registerUpdateFieldsRouteLegacy(router, getStartServices);
// Scripted Field API
registerCreateScriptedFieldRoute(router, getStartServices);
registerPutScriptedFieldRoute(router, getStartServices);
@ -67,11 +125,12 @@ export function registerRoutes(
registerUpdateScriptedFieldRoute(router, getStartServices);
// Runtime Fields API
registerCreateRuntimeFieldRoute(router, getStartServices);
registerGetRuntimeFieldRoute(router, getStartServices);
registerDeleteRuntimeFieldRoute(router, getStartServices);
registerPutRuntimeFieldRoute(router, getStartServices);
registerUpdateRuntimeFieldRoute(router, getStartServices);
registerCreateRuntimeFieldRouteLegacy(router, getStartServices);
registerGetRuntimeFieldRouteLegacy(router, getStartServices);
registerDeleteRuntimeFieldRouteLegacy(router, getStartServices);
registerPutRuntimeFieldRouteLegacy(router, getStartServices);
registerUpdateRuntimeFieldRouteLegacy(router, getStartServices);
// ###
registerFieldForWildcard(router, getStartServices);

View file

@ -7,7 +7,7 @@
*/
import { schema } from '@kbn/config-schema';
import { IndexPatternSpec } from 'src/plugins/data_views/common';
import { DataViewSpec } from 'src/plugins/data_views/common';
import { handleErrors } from './util/handle_errors';
import {
fieldSpecSchema,
@ -15,7 +15,13 @@ import {
serializedFieldFormatSchema,
} from './util/schemas';
import { IRouter, StartServicesAccessor } from '../../../../core/server';
import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types';
import type { DataViewsServerPluginStartDependencies, DataViewsServerPluginStart } from '../types';
import {
DATA_VIEW_PATH,
DATA_VIEW_PATH_LEGACY,
SERVICE_KEY,
SERVICE_KEY_LEGACY,
} from '../constants';
const indexPatternSpecSchema = schema.object({
title: schema.string(),
@ -46,51 +52,67 @@ const indexPatternSpecSchema = schema.object({
runtimeFieldMap: schema.maybe(schema.recordOf(schema.string(), runtimeFieldSpecSchema)),
});
export const registerCreateIndexPatternRoute = (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.post(
{
path: '/api/index_patterns/index_pattern',
validate: {
body: schema.object({
override: schema.maybe(schema.boolean({ defaultValue: false })),
refresh_fields: schema.maybe(schema.boolean({ defaultValue: false })),
index_pattern: indexPatternSpecSchema,
}),
},
},
router.handleLegacyErrors(
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const body = req.body;
const indexPattern = await indexPatternsService.createAndSave(
body.index_pattern as IndexPatternSpec,
body.override,
!body.refresh_fields
);
return res.ok({
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
index_pattern: indexPattern.toSpec(),
const registerCreateDataViewRouteFactory =
(path: string, serviceKey: string) =>
(
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.post(
{
path,
validate: {
body: schema.object({
override: schema.maybe(schema.boolean({ defaultValue: false })),
refresh_fields: schema.maybe(schema.boolean({ defaultValue: false })),
data_view: serviceKey === SERVICE_KEY ? indexPatternSpecSchema : schema.never(),
index_pattern:
serviceKey === SERVICE_KEY_LEGACY ? indexPatternSpecSchema : schema.never(),
}),
});
})
)
);
};
},
},
router.handleLegacyErrors(
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { dataViewsServiceFactory }] = await getStartServices();
const indexPatternsService = await dataViewsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const body = req.body;
const spec = serviceKey === SERVICE_KEY ? body.data_view : body.index_pattern;
const indexPattern = await indexPatternsService.createAndSave(
spec as DataViewSpec,
body.override,
!body.refresh_fields
);
return res.ok({
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
[serviceKey]: indexPattern.toSpec(),
}),
});
})
)
);
};
export const registerCreateDataViewRoute = registerCreateDataViewRouteFactory(
DATA_VIEW_PATH,
SERVICE_KEY
);
export const registerCreateDataViewRouteLegacy = registerCreateDataViewRouteFactory(
DATA_VIEW_PATH_LEGACY,
SERVICE_KEY_LEGACY
);

View file

@ -8,76 +8,89 @@
import { schema } from '@kbn/config-schema';
import { IRouter, StartServicesAccessor } from '../../../../core/server';
import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types';
import type { DataViewsServerPluginStartDependencies, DataViewsServerPluginStart } from '../types';
import { handleErrors } from './util/handle_errors';
import { SERVICE_PATH, SERVICE_PATH_LEGACY, SERVICE_KEY, SERVICE_KEY_LEGACY } from '../constants';
export const registerManageDefaultIndexPatternRoutes = (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.get(
{
path: '/api/index_patterns/default',
validate: {},
},
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const defaultIndexPatternId = await indexPatternsService.getDefaultId();
return res.ok({
body: {
index_pattern_id: defaultIndexPatternId,
},
});
})
);
router.post(
{
path: '/api/index_patterns/default',
validate: {
body: schema.object({
index_pattern_id: schema.nullable(
schema.string({
minLength: 1,
maxLength: 1_000,
})
),
force: schema.boolean({ defaultValue: false }),
}),
const manageDefaultIndexPatternRoutesFactory =
(path: string, serviceKey: string) =>
(
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.get(
{
path,
validate: {},
},
},
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { dataViewsServiceFactory }] = await getStartServices();
const indexPatternsService = await dataViewsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const newDefaultId = req.body.index_pattern_id;
const force = req.body.force;
const defaultIndexPatternId = await indexPatternsService.getDefaultId();
await indexPatternsService.setDefault(newDefaultId, force);
return res.ok({
body: {
[`${serviceKey}_id`]: defaultIndexPatternId,
},
});
})
);
return res.ok({
body: {
acknowledged: true,
router.post(
{
path,
validate: {
body: schema.object({
[`${serviceKey}_id`]: schema.nullable(
schema.string({
minLength: 1,
maxLength: 1_000,
})
),
force: schema.boolean({ defaultValue: false }),
}),
},
});
})
);
};
},
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { dataViewsServiceFactory }] = await getStartServices();
const indexPatternsService = await dataViewsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const newDefaultId = req.body[`${serviceKey}_id`] as string;
const force = req.body.force as boolean;
await indexPatternsService.setDefault(newDefaultId, force);
return res.ok({
body: {
acknowledged: true,
},
});
})
);
};
export const registerManageDefaultDataViewRoute = manageDefaultIndexPatternRoutesFactory(
`${SERVICE_PATH}/default`,
SERVICE_KEY
);
export const registerManageDefaultDataViewRouteLegacy = manageDefaultIndexPatternRoutesFactory(
`${SERVICE_PATH_LEGACY}/default`,
SERVICE_KEY_LEGACY
);

View file

@ -9,50 +9,59 @@
import { schema } from '@kbn/config-schema';
import { handleErrors } from './util/handle_errors';
import { IRouter, StartServicesAccessor } from '../../../../core/server';
import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types';
import type { DataViewsServerPluginStartDependencies, DataViewsServerPluginStart } from '../types';
import { SPECIFIC_DATA_VIEW_PATH, SPECIFIC_DATA_VIEW_PATH_LEGACY } from '../constants';
export const registerDeleteIndexPatternRoute = (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.delete(
{
path: '/api/index_patterns/index_pattern/{id}',
validate: {
params: schema.object(
{
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
},
{ unknowns: 'allow' }
),
const deleteIndexPatternRouteFactory =
(path: string) =>
(
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.delete(
{
path,
validate: {
params: schema.object(
{
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
},
{ unknowns: 'allow' }
),
},
},
},
router.handleLegacyErrors(
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
router.handleLegacyErrors(
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { dataViewsServiceFactory }] = await getStartServices();
const indexPatternsService = await dataViewsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
await indexPatternsService.delete(id);
await indexPatternsService.delete(id);
return res.ok({
headers: {
'content-type': 'application/json',
},
});
})
)
);
};
return res.ok({
headers: {
'content-type': 'application/json',
},
});
})
)
);
};
export const registerDeleteDataViewRoute = deleteIndexPatternRouteFactory(SPECIFIC_DATA_VIEW_PATH);
export const registerDeleteDataViewRouteLegacy = deleteIndexPatternRouteFactory(
SPECIFIC_DATA_VIEW_PATH_LEGACY
);

View file

@ -11,111 +11,129 @@ import { handleErrors } from '../util/handle_errors';
import { serializedFieldFormatSchema } from '../util/schemas';
import { IRouter, StartServicesAccessor } from '../../../../../core/server';
import type {
DataViewsServerPluginStart,
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart,
} from '../../types';
import {
SPECIFIC_DATA_VIEW_PATH,
SPECIFIC_DATA_VIEW_PATH_LEGACY,
SERVICE_KEY,
SERVICE_KEY_LEGACY,
} from '../../constants';
export const registerUpdateFieldsRoute = (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.post(
{
path: '/api/index_patterns/index_pattern/{id}/fields',
validate: {
params: schema.object(
{
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
},
{ unknowns: 'allow' }
),
body: schema.object({
fields: schema.recordOf(
schema.string({
minLength: 1,
maxLength: 1_000,
}),
schema.object({
customLabel: schema.maybe(
schema.nullable(
schema.string({
minLength: 1,
maxLength: 1_000,
})
)
),
count: schema.maybe(schema.nullable(schema.number())),
format: schema.maybe(schema.nullable(serializedFieldFormatSchema)),
})
const updateFieldsActionRouteFactory = (path: string, serviceKey: string) => {
return (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.post(
{
path,
validate: {
params: schema.object(
{
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
},
{ unknowns: 'allow' }
),
}),
body: schema.object({
fields: schema.recordOf(
schema.string({
minLength: 1,
maxLength: 1_000,
}),
schema.object({
customLabel: schema.maybe(
schema.nullable(
schema.string({
minLength: 1,
maxLength: 1_000,
})
)
),
count: schema.maybe(schema.nullable(schema.number())),
format: schema.maybe(schema.nullable(serializedFieldFormatSchema)),
})
),
}),
},
},
},
router.handleLegacyErrors(
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const { fields } = req.body;
const fieldNames = Object.keys(fields);
router.handleLegacyErrors(
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { dataViewsServiceFactory }] = await getStartServices();
const indexPatternsService = await dataViewsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const { fields } = req.body;
const fieldNames = Object.keys(fields);
if (fieldNames.length < 1) {
throw new Error('No fields provided.');
}
const indexPattern = await indexPatternsService.get(id);
let changeCount = 0;
for (const fieldName of fieldNames) {
const field = fields[fieldName];
if (field.customLabel !== undefined) {
changeCount++;
indexPattern.setFieldCustomLabel(fieldName, field.customLabel);
if (fieldNames.length < 1) {
throw new Error('No fields provided.');
}
if (field.count !== undefined) {
changeCount++;
indexPattern.setFieldCount(fieldName, field.count);
}
const indexPattern = await indexPatternsService.get(id);
if (field.format !== undefined) {
changeCount++;
if (field.format) {
indexPattern.setFieldFormat(fieldName, field.format);
} else {
indexPattern.deleteFieldFormat(fieldName);
let changeCount = 0;
for (const fieldName of fieldNames) {
const field = fields[fieldName];
if (field.customLabel !== undefined) {
changeCount++;
indexPattern.setFieldCustomLabel(fieldName, field.customLabel);
}
if (field.count !== undefined) {
changeCount++;
indexPattern.setFieldCount(fieldName, field.count);
}
if (field.format !== undefined) {
changeCount++;
if (field.format) {
indexPattern.setFieldFormat(fieldName, field.format);
} else {
indexPattern.deleteFieldFormat(fieldName);
}
}
}
}
if (changeCount < 1) {
throw new Error('Change set is empty.');
}
if (changeCount < 1) {
throw new Error('Change set is empty.');
}
await indexPatternsService.updateSavedObject(indexPattern);
await indexPatternsService.updateSavedObject(indexPattern);
return res.ok({
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
index_pattern: indexPattern.toSpec(),
}),
});
})
)
);
return res.ok({
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
[serviceKey]: indexPattern.toSpec(),
}),
});
})
)
);
};
};
export const registerUpdateFieldsRouteLegacy = updateFieldsActionRouteFactory(
`${SPECIFIC_DATA_VIEW_PATH}/fields`,
SERVICE_KEY
);
export const registerUpdateFieldsRoute = updateFieldsActionRouteFactory(
`${SPECIFIC_DATA_VIEW_PATH_LEGACY}/fields`,
SERVICE_KEY_LEGACY
);

View file

@ -9,52 +9,70 @@
import { schema } from '@kbn/config-schema';
import { handleErrors } from './util/handle_errors';
import { IRouter, StartServicesAccessor } from '../../../../core/server';
import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types';
import type { DataViewsServerPluginStartDependencies, DataViewsServerPluginStart } from '../types';
import {
SPECIFIC_DATA_VIEW_PATH,
SPECIFIC_DATA_VIEW_PATH_LEGACY,
SERVICE_KEY,
SERVICE_KEY_LEGACY,
} from '../constants';
export const registerGetIndexPatternRoute = (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.get(
{
path: '/api/index_patterns/index_pattern/{id}',
validate: {
params: schema.object(
{
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
},
{ unknowns: 'allow' }
),
const getDataViewRouteFactory =
(path: string, serviceKey: string) =>
(
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.get(
{
path,
validate: {
params: schema.object(
{
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
},
{ unknowns: 'allow' }
),
},
},
},
router.handleLegacyErrors(
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const indexPattern = await indexPatternsService.get(id);
router.handleLegacyErrors(
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { dataViewsServiceFactory }] = await getStartServices();
const indexPatternsService = await dataViewsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const indexPattern = await indexPatternsService.get(id);
return res.ok({
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
index_pattern: indexPattern.toSpec(),
}),
});
})
)
);
};
return res.ok({
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
[serviceKey]: indexPattern.toSpec(),
}),
});
})
)
);
};
export const registerGetDataViewRoute = getDataViewRouteFactory(
SPECIFIC_DATA_VIEW_PATH,
SERVICE_KEY
);
export const registerGetDataViewRouteLegacy = getDataViewRouteFactory(
SPECIFIC_DATA_VIEW_PATH_LEGACY,
SERVICE_KEY_LEGACY
);

View file

@ -8,37 +8,48 @@
import { handleErrors } from './util/handle_errors';
import { IRouter, StartServicesAccessor } from '../../../../core/server';
import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types';
import type { DataViewsServerPluginStartDependencies, DataViewsServerPluginStart } from '../types';
import { SERVICE_PATH, SERVICE_PATH_LEGACY } from '../constants';
export const registerHasUserIndexPatternRoute = (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.get(
{
path: '/api/index_patterns/has_user_index_pattern',
validate: {},
},
router.handleLegacyErrors(
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const hasUserDataViewRouteFactory =
(path: string) =>
(
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.get(
{
path,
validate: {},
},
router.handleLegacyErrors(
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { dataViewsServiceFactory }] = await getStartServices();
const indexPatternsService = await dataViewsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
return res.ok({
body: {
result: await indexPatternsService.hasUserDataView(),
},
});
})
)
);
};
return res.ok({
body: {
result: await indexPatternsService.hasUserDataView(),
},
});
})
)
);
};
export const registerHasUserDataViewRoute = hasUserDataViewRouteFactory(
`${SERVICE_PATH}/has_user_data_view`
);
export const registerHasUserDataViewRouteLegacy = hasUserDataViewRouteFactory(
`${SERVICE_PATH_LEGACY}/has_user_index_pattern`
);

View file

@ -14,68 +14,95 @@ import type {
DataViewsServerPluginStart,
DataViewsServerPluginStartDependencies,
} from '../../types';
import {
RUNTIME_FIELD_PATH,
RUNTIME_FIELD_PATH_LEGACY,
SERVICE_KEY,
SERVICE_KEY_LEGACY,
SERVICE_KEY_TYPE,
} from '../../constants';
export const registerCreateRuntimeFieldRoute = (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.post(
{
path: '/api/index_patterns/index_pattern/{id}/runtime_field',
validate: {
params: schema.object({
id: schema.string({
minLength: 1,
maxLength: 1_000,
const runtimeCreateFieldRouteFactory =
(path: string, serviceKey: SERVICE_KEY_TYPE) =>
(
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.post(
{
path,
validate: {
params: schema.object({
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
}),
}),
body: schema.object({
name: schema.string({
minLength: 1,
maxLength: 1_000,
body: schema.object({
name: schema.string({
minLength: 1,
maxLength: 1_000,
}),
runtimeField: runtimeFieldSpecSchema,
}),
runtimeField: runtimeFieldSpecSchema,
}),
},
},
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const { name, runtimeField } = req.body;
const indexPattern = await indexPatternsService.get(id);
if (indexPattern.fields.getByName(name)) {
throw new Error(`Field [name = ${name}] already exists.`);
}
indexPattern.addRuntimeField(name, runtimeField);
const addedField = indexPattern.fields.getByName(name);
if (!addedField) throw new Error(`Could not create a field [name = ${name}].`);
await indexPatternsService.updateSavedObject(indexPattern);
const savedField = indexPattern.fields.getByName(name);
if (!savedField) throw new Error(`Could not create a field [name = ${name}].`);
return res.ok({
body: {
field: savedField.toSpec(),
index_pattern: indexPattern.toSpec(),
},
});
})
);
};
},
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const { name, runtimeField } = req.body;
const indexPattern = await indexPatternsService.get(id);
if (indexPattern.fields.getByName(name)) {
throw new Error(`Field [name = ${name}] already exists.`);
}
indexPattern.addRuntimeField(name, runtimeField);
const addedField = indexPattern.fields.getByName(name);
if (!addedField) throw new Error(`Could not create a field [name = ${name}].`);
await indexPatternsService.updateSavedObject(indexPattern);
const savedField = indexPattern.fields.getByName(name);
if (!savedField) throw new Error(`Could not create a field [name = ${name}].`);
const response = {
body: {
fields: [savedField.toSpec()],
[serviceKey]: indexPattern.toSpec(),
},
};
const legacyResponse = {
body: {
[serviceKey]: indexPattern.toSpec(),
field: savedField.toSpec(),
},
};
return res.ok(serviceKey === SERVICE_KEY_LEGACY ? legacyResponse : response);
})
);
};
export const registerCreateRuntimeFieldRoute = runtimeCreateFieldRouteFactory(
RUNTIME_FIELD_PATH,
SERVICE_KEY
);
export const registerCreateRuntimeFieldRouteLegacy = runtimeCreateFieldRouteFactory(
RUNTIME_FIELD_PATH_LEGACY,
SERVICE_KEY_LEGACY
);

View file

@ -14,58 +14,69 @@ import type {
DataViewsServerPluginStart,
DataViewsServerPluginStartDependencies,
} from '../../types';
import { SPECIFIC_RUNTIME_FIELD_PATH, SPECIFIC_RUNTIME_FIELD_PATH_LEGACY } from '../../constants';
export const registerDeleteRuntimeFieldRoute = (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.delete(
{
path: '/api/index_patterns/index_pattern/{id}/runtime_field/{name}',
validate: {
params: schema.object({
id: schema.string({
minLength: 1,
maxLength: 1_000,
const deleteRuntimeFieldRouteFactory =
(path: string) =>
(
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.delete(
{
path,
validate: {
params: schema.object({
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
name: schema.string({
minLength: 1,
maxLength: 1_000,
}),
}),
name: schema.string({
minLength: 1,
maxLength: 1_000,
}),
}),
},
},
},
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const name = req.params.name;
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const name = req.params.name;
const indexPattern = await indexPatternsService.get(id);
const field = indexPattern.fields.getByName(name);
const indexPattern = await indexPatternsService.get(id);
const field = indexPattern.fields.getByName(name);
if (!field) {
throw new ErrorIndexPatternFieldNotFound(id, name);
}
if (!field) {
throw new ErrorIndexPatternFieldNotFound(id, name);
}
if (!field.runtimeField) {
throw new Error('Only runtime fields can be deleted.');
}
if (!field.runtimeField) {
throw new Error('Only runtime fields can be deleted.');
}
indexPattern.removeRuntimeField(name);
indexPattern.removeRuntimeField(name);
await indexPatternsService.updateSavedObject(indexPattern);
await indexPatternsService.updateSavedObject(indexPattern);
return res.ok();
})
);
};
return res.ok();
})
);
};
export const registerDeleteRuntimeFieldRoute = deleteRuntimeFieldRouteFactory(
SPECIFIC_RUNTIME_FIELD_PATH
);
export const registerDeleteRuntimeFieldRouteLegacy = deleteRuntimeFieldRouteFactory(
SPECIFIC_RUNTIME_FIELD_PATH_LEGACY
);

View file

@ -14,61 +14,89 @@ import type {
DataViewsServerPluginStart,
DataViewsServerPluginStartDependencies,
} from '../../types';
import {
SPECIFIC_RUNTIME_FIELD_PATH,
SPECIFIC_RUNTIME_FIELD_PATH_LEGACY,
SERVICE_KEY,
SERVICE_KEY_LEGACY,
SERVICE_KEY_TYPE,
} from '../../constants';
export const registerGetRuntimeFieldRoute = (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.get(
{
path: '/api/index_patterns/index_pattern/{id}/runtime_field/{name}',
validate: {
params: schema.object({
id: schema.string({
minLength: 1,
maxLength: 1_000,
const getRuntimeFieldRouteFactory =
(path: string, serviceKey: SERVICE_KEY_TYPE) =>
(
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.get(
{
path,
validate: {
params: schema.object({
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
name: schema.string({
minLength: 1,
maxLength: 1_000,
}),
}),
name: schema.string({
minLength: 1,
maxLength: 1_000,
}),
}),
},
},
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const name = req.params.name;
const indexPattern = await indexPatternsService.get(id);
const field = indexPattern.fields.getByName(name);
if (!field) {
throw new ErrorIndexPatternFieldNotFound(id, name);
}
if (!field.runtimeField) {
throw new Error('Only runtime fields can be retrieved.');
}
return res.ok({
body: {
field: field.toSpec(),
runtimeField: indexPattern.getRuntimeField(name),
},
});
})
);
};
},
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const name = req.params.name;
const indexPattern = await indexPatternsService.get(id);
const field = indexPattern.fields.getByName(name);
if (!field) {
throw new ErrorIndexPatternFieldNotFound(id, name);
}
if (!field.runtimeField) {
throw new Error('Only runtime fields can be retrieved.');
}
const legacyResponse = {
body: {
field: field.toSpec(),
runtimeField: indexPattern.getRuntimeField(name),
},
};
const response = {
body: {
fields: [field.toSpec()],
runtimeField: indexPattern.getRuntimeField(name),
},
};
return res.ok(serviceKey === SERVICE_KEY_LEGACY ? legacyResponse : response);
})
);
};
export const registerGetRuntimeFieldRoute = getRuntimeFieldRouteFactory(
SPECIFIC_RUNTIME_FIELD_PATH,
SERVICE_KEY
);
export const registerGetRuntimeFieldRouteLegacy = getRuntimeFieldRouteFactory(
SPECIFIC_RUNTIME_FIELD_PATH_LEGACY,
SERVICE_KEY_LEGACY
);

View file

@ -14,70 +14,97 @@ import type {
DataViewsServerPluginStart,
DataViewsServerPluginStartDependencies,
} from '../../types';
import {
RUNTIME_FIELD_PATH,
RUNTIME_FIELD_PATH_LEGACY,
SERVICE_KEY,
SERVICE_KEY_LEGACY,
} from '../../constants';
export const registerPutRuntimeFieldRoute = (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.put(
{
path: '/api/index_patterns/index_pattern/{id}/runtime_field',
validate: {
params: schema.object({
id: schema.string({
minLength: 1,
maxLength: 1_000,
const putRuntimeFieldRouteFactory =
(path: string, serviceKey: string) =>
(
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.put(
{
path,
validate: {
params: schema.object({
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
}),
}),
body: schema.object({
name: schema.string({
minLength: 1,
maxLength: 1_000,
body: schema.object({
name: schema.string({
minLength: 1,
maxLength: 1_000,
}),
runtimeField: runtimeFieldSpecSchema,
}),
runtimeField: runtimeFieldSpecSchema,
}),
},
},
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const { name, runtimeField } = req.body;
const indexPattern = await indexPatternsService.get(id);
const oldFieldObject = indexPattern.fields.getByName(name);
if (oldFieldObject && !oldFieldObject.runtimeField) {
throw new Error('Only runtime fields can be updated');
}
if (oldFieldObject) {
indexPattern.removeRuntimeField(name);
}
indexPattern.addRuntimeField(name, runtimeField);
await indexPatternsService.updateSavedObject(indexPattern);
const fieldObject = indexPattern.fields.getByName(name);
if (!fieldObject) throw new Error(`Could not create a field [name = ${name}].`);
return res.ok({
body: {
field: fieldObject.toSpec(),
index_pattern: indexPattern.toSpec(),
},
});
})
);
};
},
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const { name, runtimeField } = req.body;
const indexPattern = await indexPatternsService.get(id);
const oldFieldObject = indexPattern.fields.getByName(name);
if (oldFieldObject && !oldFieldObject.runtimeField) {
throw new Error('Only runtime fields can be updated');
}
if (oldFieldObject) {
indexPattern.removeRuntimeField(name);
}
indexPattern.addRuntimeField(name, runtimeField);
await indexPatternsService.updateSavedObject(indexPattern);
const fieldObject = indexPattern.fields.getByName(name);
if (!fieldObject) throw new Error(`Could not create a field [name = ${name}].`);
const legacyResponse = {
body: {
field: fieldObject.toSpec(),
[serviceKey]: indexPattern.toSpec(),
},
};
const response = {
body: {
fields: [fieldObject.toSpec()],
[serviceKey]: indexPattern.toSpec(),
},
};
return res.ok(serviceKey === SERVICE_KEY_LEGACY ? legacyResponse : response);
})
);
};
export const registerPutRuntimeFieldRoute = putRuntimeFieldRouteFactory(
RUNTIME_FIELD_PATH,
SERVICE_KEY
);
export const registerPutRuntimeFieldRouteLegacy = putRuntimeFieldRouteFactory(
RUNTIME_FIELD_PATH_LEGACY,
SERVICE_KEY_LEGACY
);

View file

@ -16,76 +16,104 @@ import type {
DataViewsServerPluginStart,
DataViewsServerPluginStartDependencies,
} from '../../types';
import {
SPECIFIC_RUNTIME_FIELD_PATH,
SPECIFIC_RUNTIME_FIELD_PATH_LEGACY,
SERVICE_KEY,
SERVICE_KEY_LEGACY,
SERVICE_KEY_TYPE,
} from '../../constants';
export const registerUpdateRuntimeFieldRoute = (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.post(
{
path: '/api/index_patterns/index_pattern/{id}/runtime_field/{name}',
validate: {
params: schema.object({
id: schema.string({
minLength: 1,
maxLength: 1_000,
const updateRuntimeFieldRouteFactory =
(path: string, serviceKey: SERVICE_KEY_TYPE) =>
(
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.post(
{
path,
validate: {
params: schema.object({
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
name: schema.string({
minLength: 1,
maxLength: 1_000,
}),
}),
name: schema.string({
minLength: 1,
maxLength: 1_000,
body: schema.object({
name: schema.never(),
runtimeField: schema.object({
...runtimeFieldSpec,
// We need to overwrite the below fields on top of `runtimeFieldSpec`,
// because some fields would be optional
type: schema.maybe(runtimeFieldSpecTypeSchema),
}),
}),
}),
body: schema.object({
name: schema.never(),
runtimeField: schema.object({
...runtimeFieldSpec,
// We need to overwrite the below fields on top of `runtimeFieldSpec`,
// because some fields would be optional
type: schema.maybe(runtimeFieldSpecTypeSchema),
}),
}),
},
},
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const name = req.params.name;
const runtimeField = req.body.runtimeField as Partial<RuntimeField>;
const indexPattern = await indexPatternsService.get(id);
const existingRuntimeField = indexPattern.getRuntimeField(name);
if (!existingRuntimeField) {
throw new ErrorIndexPatternFieldNotFound(id, name);
}
indexPattern.removeRuntimeField(name);
indexPattern.addRuntimeField(name, {
...existingRuntimeField,
...runtimeField,
});
await indexPatternsService.updateSavedObject(indexPattern);
const fieldObject = indexPattern.fields.getByName(name);
if (!fieldObject) throw new Error(`Could not create a field [name = ${name}].`);
return res.ok({
body: {
field: fieldObject.toSpec(),
index_pattern: indexPattern.toSpec(),
},
});
})
);
};
},
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const name = req.params.name;
const runtimeField = req.body.runtimeField as Partial<RuntimeField>;
const indexPattern = await indexPatternsService.get(id);
const existingRuntimeField = indexPattern.getRuntimeField(name);
if (!existingRuntimeField) {
throw new ErrorIndexPatternFieldNotFound(id, name);
}
indexPattern.removeRuntimeField(name);
indexPattern.addRuntimeField(name, {
...existingRuntimeField,
...runtimeField,
});
await indexPatternsService.updateSavedObject(indexPattern);
const fieldObject = indexPattern.fields.getByName(name);
if (!fieldObject) throw new Error(`Could not create a field [name = ${name}].`);
const legacyResponse = {
body: {
field: fieldObject.toSpec(),
[serviceKey]: indexPattern.toSpec(),
},
};
const response = {
body: {
fields: [fieldObject.toSpec()],
[serviceKey]: indexPattern.toSpec(),
},
};
return res.ok(serviceKey === SERVICE_KEY_LEGACY ? legacyResponse : response);
})
);
};
export const registerUpdateRuntimeFieldRoute = updateRuntimeFieldRouteFactory(
SPECIFIC_RUNTIME_FIELD_PATH,
SERVICE_KEY
);
export const registerUpdateRuntimeFieldRouteLegacy = updateRuntimeFieldRouteFactory(
SPECIFIC_RUNTIME_FIELD_PATH_LEGACY,
SERVICE_KEY_LEGACY
);

View file

@ -7,6 +7,7 @@
*/
import { schema } from '@kbn/config-schema';
import { DataViewSpec } from 'src/plugins/data_views/common';
import { handleErrors } from './util/handle_errors';
import {
fieldSpecSchema,
@ -14,7 +15,13 @@ import {
serializedFieldFormatSchema,
} from './util/schemas';
import { IRouter, StartServicesAccessor } from '../../../../core/server';
import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types';
import type { DataViewsServerPluginStartDependencies, DataViewsServerPluginStart } from '../types';
import {
SPECIFIC_DATA_VIEW_PATH,
SPECIFIC_DATA_VIEW_PATH_LEGACY,
SERVICE_KEY,
SERVICE_KEY_LEGACY,
} from '../constants';
const indexPatternUpdateSchema = schema.object({
title: schema.maybe(schema.string()),
@ -34,50 +41,55 @@ const indexPatternUpdateSchema = schema.object({
runtimeFieldMap: schema.maybe(schema.recordOf(schema.string(), runtimeFieldSpecSchema)),
});
export const registerUpdateIndexPatternRoute = (
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.post(
{
path: '/api/index_patterns/index_pattern/{id}',
validate: {
params: schema.object(
{
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
},
{ unknowns: 'allow' }
),
body: schema.object({
refresh_fields: schema.maybe(schema.boolean({ defaultValue: false })),
index_pattern: indexPatternUpdateSchema,
}),
const updateDataViewRouteFactory =
(path: string, serviceKey: string) =>
(
router: IRouter,
getStartServices: StartServicesAccessor<
DataViewsServerPluginStartDependencies,
DataViewsServerPluginStart
>
) => {
router.post(
{
path,
validate: {
params: schema.object(
{
id: schema.string({
minLength: 1,
maxLength: 1_000,
}),
},
{ unknowns: 'allow' }
),
body: schema.object({
refresh_fields: schema.maybe(schema.boolean({ defaultValue: false })),
[serviceKey]: indexPatternUpdateSchema,
}),
},
},
},
router.handleLegacyErrors(
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { indexPatternsServiceFactory }] = await getStartServices();
const indexPatternsService = await indexPatternsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
router.handleLegacyErrors(
handleErrors(async (ctx, req, res) => {
const savedObjectsClient = ctx.core.savedObjects.client;
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
const [, , { dataViewsServiceFactory }] = await getStartServices();
const indexPatternsService = await dataViewsServiceFactory(
savedObjectsClient,
elasticsearchClient,
req
);
const id = req.params.id;
const indexPattern = await indexPatternsService.get(id);
const indexPattern = await indexPatternsService.get(id);
const {
// eslint-disable-next-line @typescript-eslint/naming-convention
refresh_fields = true,
index_pattern: {
const {
// eslint-disable-next-line @typescript-eslint/naming-convention
refresh_fields = true,
} = req.body;
const indexPatternSpec = req.body[serviceKey] as DataViewSpec;
const {
title,
timeFieldName,
sourceFilters,
@ -86,78 +98,87 @@ export const registerUpdateIndexPatternRoute = (
typeMeta,
fields,
runtimeFieldMap,
},
} = req.body;
} = indexPatternSpec;
let changeCount = 0;
let doRefreshFields = false;
let changeCount = 0;
let doRefreshFields = false;
if (title !== undefined && title !== indexPattern.title) {
changeCount++;
indexPattern.title = title;
}
if (title !== undefined && title !== indexPattern.title) {
changeCount++;
indexPattern.title = title;
}
if (timeFieldName !== undefined && timeFieldName !== indexPattern.timeFieldName) {
changeCount++;
indexPattern.timeFieldName = timeFieldName;
}
if (timeFieldName !== undefined && timeFieldName !== indexPattern.timeFieldName) {
changeCount++;
indexPattern.timeFieldName = timeFieldName;
}
if (sourceFilters !== undefined) {
changeCount++;
indexPattern.sourceFilters = sourceFilters;
}
if (sourceFilters !== undefined) {
changeCount++;
indexPattern.sourceFilters = sourceFilters;
}
if (fieldFormats !== undefined) {
changeCount++;
indexPattern.fieldFormatMap = fieldFormats;
}
if (fieldFormats !== undefined) {
changeCount++;
indexPattern.fieldFormatMap = fieldFormats;
}
if (type !== undefined) {
changeCount++;
indexPattern.type = type;
}
if (type !== undefined) {
changeCount++;
indexPattern.type = type;
}
if (typeMeta !== undefined) {
changeCount++;
indexPattern.typeMeta = typeMeta;
}
if (typeMeta !== undefined) {
changeCount++;
indexPattern.typeMeta = typeMeta;
}
if (fields !== undefined) {
changeCount++;
doRefreshFields = true;
indexPattern.fields.replaceAll(
Object.values(fields || {}).map((field) => ({
...field,
aggregatable: true,
searchable: true,
}))
);
}
if (fields !== undefined) {
changeCount++;
doRefreshFields = true;
indexPattern.fields.replaceAll(
Object.values(fields || {}).map((field) => ({
...field,
aggregatable: true,
searchable: true,
}))
);
}
if (runtimeFieldMap !== undefined) {
changeCount++;
indexPattern.replaceAllRuntimeFields(runtimeFieldMap);
}
if (runtimeFieldMap !== undefined) {
changeCount++;
indexPattern.replaceAllRuntimeFields(runtimeFieldMap);
}
if (changeCount < 1) {
throw new Error('Index pattern change set is empty.');
}
if (changeCount < 1) {
throw new Error('Index pattern change set is empty.');
}
await indexPatternsService.updateSavedObject(indexPattern);
await indexPatternsService.updateSavedObject(indexPattern);
if (doRefreshFields && refresh_fields) {
await indexPatternsService.refreshFields(indexPattern);
}
if (doRefreshFields && refresh_fields) {
await indexPatternsService.refreshFields(indexPattern);
}
return res.ok({
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
index_pattern: indexPattern.toSpec(),
}),
});
})
)
);
};
return res.ok({
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
[serviceKey]: indexPattern.toSpec(),
}),
});
})
)
);
};
export const registerUpdateDataViewRoute = updateDataViewRouteFactory(
SPECIFIC_DATA_VIEW_PATH,
SERVICE_KEY
);
export const registerUpdateDataViewRouteLegacy = updateDataViewRouteFactory(
SPECIFIC_DATA_VIEW_PATH_LEGACY,
SERVICE_KEY_LEGACY
);

View file

@ -0,0 +1,32 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import {
DATA_VIEW_PATH_LEGACY,
SERVICE_KEY_LEGACY,
DATA_VIEW_PATH,
SERVICE_KEY,
SERVICE_PATH,
SERVICE_PATH_LEGACY,
} from '../../../../src/plugins/data_views/server';
const legacyConfig = {
name: 'legacy index pattern api',
path: DATA_VIEW_PATH_LEGACY,
basePath: SERVICE_PATH_LEGACY,
serviceKey: SERVICE_KEY_LEGACY,
};
const dataViewConfig = {
name: 'data view api',
path: DATA_VIEW_PATH,
basePath: SERVICE_PATH,
serviceKey: SERVICE_KEY,
};
export const configArray = [legacyConfig, dataViewConfig];

View file

@ -8,42 +8,49 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { configArray } from '../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
describe('default index pattern api', () => {
const newId = () => `default-id-${Date.now()}-${Math.random()}`;
it('can set default index pattern', async () => {
const defaultId = newId();
const response1 = await supertest.post('/api/index_patterns/default').send({
index_pattern_id: defaultId,
force: true,
configArray.forEach((config) => {
describe(config.name, () => {
const newId = () => `default-id-${Date.now()}-${Math.random()}`;
it('can set default index pattern', async () => {
const defaultId = newId();
const defaultPath = `${config.basePath}/default`;
const serviceKeyId = `${config.serviceKey}_id`;
const response1 = await supertest.post(defaultPath).send({
[serviceKeyId]: defaultId,
force: true,
});
expect(response1.status).to.be(200);
expect(response1.body.acknowledged).to.be(true);
const response2 = await supertest.get(defaultPath);
expect(response2.status).to.be(200);
expect(response2.body[serviceKeyId]).to.be(defaultId);
const response3 = await supertest.post(defaultPath).send({
[serviceKeyId]: newId(),
// no force this time, so this new default shouldn't be set
});
expect(response3.status).to.be(200);
const response4 = await supertest.get(defaultPath);
expect(response4.body[serviceKeyId]).to.be(defaultId); // original default id is used
const response5 = await supertest.post(defaultPath).send({
[serviceKeyId]: null,
force: true,
});
expect(response5.status).to.be(200);
const response6 = await supertest.get(defaultPath);
expect(response6.body[serviceKeyId]).to.be(null);
});
});
expect(response1.status).to.be(200);
expect(response1.body.acknowledged).to.be(true);
const response2 = await supertest.get('/api/index_patterns/default');
expect(response2.status).to.be(200);
expect(response2.body.index_pattern_id).to.be(defaultId);
const response3 = await supertest.post('/api/index_patterns/default').send({
index_pattern_id: newId(),
// no force this time, so this new default shouldn't be set
});
expect(response3.status).to.be(200);
const response4 = await supertest.get('/api/index_patterns/default');
expect(response4.body.index_pattern_id).to.be(defaultId); // original default id is used
const response5 = await supertest.post('/api/index_patterns/default').send({
index_pattern_id: null,
force: true,
});
expect(response5.status).to.be(200);
const response6 = await supertest.get('/api/index_patterns/default');
expect(response6.body.index_pattern_id).to.be(null);
});
});
}

View file

@ -8,63 +8,68 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
describe('errors', () => {
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.post(`/api/index_patterns/index_pattern/${id}/fields`).send({
fields: {
foo: {},
},
});
configArray.forEach((config) => {
describe(config.name, () => {
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.post(`${config.path}/${id}/fields`).send({
fields: {
foo: {},
},
});
expect(response.status).to.be(404);
});
it('returns error when "fields" payload attribute is invalid', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
});
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/fields`)
.send({
fields: 123,
expect(response.status).to.be(404);
});
expect(response2.status).to.be(400);
expect(response2.body.statusCode).to.be(400);
expect(response2.body.message).to.be(
'[request body.fields]: expected value of type [object] but got [number]'
);
});
it('returns error when "fields" payload attribute is invalid', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
});
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/fields`)
.send({
fields: 123,
});
it('returns error if not changes are specified', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
});
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/fields`)
.send({
fields: {
foo: {},
bar: {},
baz: {},
},
expect(response2.status).to.be(400);
expect(response2.body.statusCode).to.be(400);
expect(response2.body.message).to.be(
'[request body.fields]: expected value of type [object] but got [number]'
);
});
expect(response2.status).to.be(400);
expect(response2.body.statusCode).to.be(400);
expect(response2.body.message).to.be('Change set is empty.');
it('returns error if not changes are specified', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
});
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/fields`)
.send({
fields: {
foo: {},
bar: {},
baz: {},
},
});
expect(response2.status).to.be(400);
expect(response2.body.statusCode).to.be(400);
expect(response2.body.message).to.be('Change set is empty.');
});
});
});
});
}

View file

@ -8,6 +8,7 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
@ -17,474 +18,476 @@ export default function ({ getService }: FtrProviderContext) {
const basicIndex = 'ba*ic_index';
let indexPattern: any;
before(async () => {
await esArchiver.load('test/api_integration/fixtures/es_archiver/index_patterns/basic_index');
configArray.forEach((config) => {
describe(config.name, () => {
before(async () => {
await esArchiver.load(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
indexPattern = (
await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title: basicIndex,
},
})
).body.index_pattern;
});
after(async () => {
await esArchiver.unload(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
if (indexPattern) {
await supertest.delete('/api/index_patterns/index_pattern/' + indexPattern.id);
}
});
it('can update multiple fields', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
});
expect(response1.status).to.be(200);
expect(response1.body.index_pattern.fieldAttrs.foo).to.be(undefined);
expect(response1.body.index_pattern.fieldAttrs.bar).to.be(undefined);
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/fields`)
.send({
fields: {
foo: {
count: 123,
customLabel: 'test',
},
bar: {
count: 456,
},
},
});
expect(response2.status).to.be(200);
expect(response2.body.index_pattern.fieldAttrs.foo.count).to.be(123);
expect(response2.body.index_pattern.fieldAttrs.foo.customLabel).to.be('test');
expect(response2.body.index_pattern.fieldAttrs.bar.count).to.be(456);
const response3 = await supertest.get(
`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}`
);
expect(response3.status).to.be(200);
expect(response3.body.index_pattern.fieldAttrs.foo.count).to.be(123);
expect(response3.body.index_pattern.fieldAttrs.foo.customLabel).to.be('test');
expect(response3.body.index_pattern.fieldAttrs.bar.count).to.be(456);
});
describe('count', () => {
it('can set field "count" attribute on non-existing field', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
});
expect(response1.status).to.be(200);
expect(response1.body.index_pattern.fieldAttrs.foo).to.be(undefined);
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/fields`)
.send({
fields: {
foo: {
count: 123,
indexPattern = (
await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title: basicIndex,
},
})
).body[config.serviceKey];
});
after(async () => {
await esArchiver.unload(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
if (indexPattern) {
await supertest.delete(`${config.path}/${indexPattern.id}`);
}
});
it('can update multiple fields', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
});
expect(response2.status).to.be(200);
expect(response2.body.index_pattern.fieldAttrs.foo.count).to.be(123);
expect(response1.status).to.be(200);
expect(response1.body[config.serviceKey].fieldAttrs.foo).to.be(undefined);
expect(response1.body[config.serviceKey].fieldAttrs.bar).to.be(undefined);
const response3 = await supertest.get(
`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}`
);
expect(response3.status).to.be(200);
expect(response3.body.index_pattern.fieldAttrs.foo.count).to.be(123);
});
it('can update "count" attribute in index_pattern attribute map', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
fieldAttrs: {
foo: {
count: 1,
},
},
},
});
expect(response1.status).to.be(200);
expect(response1.body.index_pattern.fieldAttrs.foo.count).to.be(1);
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/fields`)
.send({
fields: {
foo: {
count: 2,
},
},
});
expect(response2.status).to.be(200);
expect(response2.body.index_pattern.fieldAttrs.foo.count).to.be(2);
const response3 = await supertest.get(
`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}`
);
expect(response3.status).to.be(200);
expect(response3.body.index_pattern.fieldAttrs.foo.count).to.be(2);
});
it('can delete "count" attribute from index_pattern attribute map', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
fieldAttrs: {
foo: {
count: 1,
},
},
},
});
expect(response1.status).to.be(200);
expect(response1.body.index_pattern.fieldAttrs.foo.count).to.be(1);
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/fields`)
.send({
fields: {
foo: {
count: null,
},
},
});
expect(response2.status).to.be(200);
expect(response2.body.index_pattern.fieldAttrs.foo.count).to.be(undefined);
const response3 = await supertest.get(
`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}`
);
expect(response3.status).to.be(200);
expect(response3.body.index_pattern.fieldAttrs.foo.count).to.be(undefined);
});
});
describe('customLabel', () => {
it('can set field "customLabel" attribute on non-existing field', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
});
expect(response1.status).to.be(200);
expect(response1.body.index_pattern.fieldAttrs.foo).to.be(undefined);
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/fields`)
.send({
fields: {
foo: {
customLabel: 'foo',
},
},
});
expect(response2.status).to.be(200);
expect(response2.body.index_pattern.fieldAttrs.foo.customLabel).to.be('foo');
const response3 = await supertest.get(
`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}`
);
expect(response3.status).to.be(200);
expect(response3.body.index_pattern.fieldAttrs.foo.customLabel).to.be('foo');
});
it('can update "customLabel" attribute in index_pattern attribute map', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
fieldAttrs: {
foo: {
customLabel: 'foo',
},
},
},
});
expect(response1.status).to.be(200);
expect(response1.body.index_pattern.fieldAttrs.foo.customLabel).to.be('foo');
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/fields`)
.send({
fields: {
foo: {
customLabel: 'bar',
},
},
});
expect(response2.status).to.be(200);
expect(response2.body.index_pattern.fieldAttrs.foo.customLabel).to.be('bar');
const response3 = await supertest.get(
`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}`
);
expect(response3.status).to.be(200);
expect(response3.body.index_pattern.fieldAttrs.foo.customLabel).to.be('bar');
});
it('can delete "customLabel" attribute from index_pattern attribute map', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
fieldAttrs: {
foo: {
customLabel: 'foo',
},
},
},
});
expect(response1.status).to.be(200);
expect(response1.body.index_pattern.fieldAttrs.foo.customLabel).to.be('foo');
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/fields`)
.send({
fields: {
foo: {
customLabel: null,
},
},
});
expect(response2.status).to.be(200);
expect(response2.body.index_pattern.fieldAttrs.foo.customLabel).to.be(undefined);
const response3 = await supertest.get(
`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}`
);
expect(response3.status).to.be(200);
expect(response3.body.index_pattern.fieldAttrs.foo.customLabel).to.be(undefined);
});
it('can set field "customLabel" attribute on an existing field', async () => {
await supertest.post(`/api/index_patterns/index_pattern/${indexPattern.id}/fields`).send({
fields: {
foo: {
customLabel: 'baz',
},
},
});
const response1 = await supertest.get(
`/api/index_patterns/index_pattern/${indexPattern.id}`
);
expect(response1.status).to.be(200);
expect(response1.body.index_pattern.fields.foo.customLabel).to.be('baz');
});
});
describe('format', () => {
it('can set field "format" attribute on non-existing field', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
});
expect(response1.status).to.be(200);
expect(response1.body.index_pattern.fieldFormats.foo).to.be(undefined);
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/fields`)
.send({
fields: {
foo: {
format: {
id: 'bar',
params: { baz: 'qux' },
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/fields`)
.send({
fields: {
foo: {
count: 123,
customLabel: 'test',
},
bar: {
count: 456,
},
},
},
});
expect(response2.status).to.be(200);
expect(response2.body[config.serviceKey].fieldAttrs.foo.count).to.be(123);
expect(response2.body[config.serviceKey].fieldAttrs.foo.customLabel).to.be('test');
expect(response2.body[config.serviceKey].fieldAttrs.bar.count).to.be(456);
const response3 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response3.status).to.be(200);
expect(response3.body[config.serviceKey].fieldAttrs.foo.count).to.be(123);
expect(response3.body[config.serviceKey].fieldAttrs.foo.customLabel).to.be('test');
expect(response3.body[config.serviceKey].fieldAttrs.bar.count).to.be(456);
});
describe('count', () => {
it('can set field "count" attribute on non-existing field', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
});
expect(response1.status).to.be(200);
expect(response1.body[config.serviceKey].fieldAttrs.foo).to.be(undefined);
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/fields`)
.send({
fields: {
foo: {
count: 123,
},
},
});
expect(response2.status).to.be(200);
expect(response2.body[config.serviceKey].fieldAttrs.foo.count).to.be(123);
const response3 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response3.status).to.be(200);
expect(response3.body[config.serviceKey].fieldAttrs.foo.count).to.be(123);
});
expect(response2.status).to.be(200);
expect(response2.body.index_pattern.fieldFormats.foo).to.eql({
id: 'bar',
params: { baz: 'qux' },
});
const response3 = await supertest.get(
`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}`
);
expect(response3.status).to.be(200);
expect(response3.body.index_pattern.fieldFormats.foo).to.eql({
id: 'bar',
params: { baz: 'qux' },
});
});
it('can update "format" attribute in index_pattern format map', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
fieldFormats: {
foo: {
id: 'bar',
params: {
baz: 'qux',
it('can update "count" attribute in index_pattern attribute map', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
fieldAttrs: {
foo: {
count: 1,
},
},
},
},
},
});
});
expect(response1.status).to.be(200);
expect(response1.body.index_pattern.fieldFormats.foo).to.eql({
id: 'bar',
params: {
baz: 'qux',
},
});
expect(response1.status).to.be(200);
expect(response1.body[config.serviceKey].fieldAttrs.foo.count).to.be(1);
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/fields`)
.send({
fields: {
foo: {
format: {
id: 'bar-2',
params: { baz: 'qux-2' },
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/fields`)
.send({
fields: {
foo: {
count: 2,
},
},
});
expect(response2.status).to.be(200);
expect(response2.body[config.serviceKey].fieldAttrs.foo.count).to.be(2);
const response3 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response3.status).to.be(200);
expect(response3.body[config.serviceKey].fieldAttrs.foo.count).to.be(2);
});
it('can delete "count" attribute from index_pattern attribute map', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
fieldAttrs: {
foo: {
count: 1,
},
},
},
},
});
expect(response1.status).to.be(200);
expect(response1.body[config.serviceKey].fieldAttrs.foo.count).to.be(1);
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/fields`)
.send({
fields: {
foo: {
count: null,
},
},
});
expect(response2.status).to.be(200);
expect(response2.body[config.serviceKey].fieldAttrs.foo.count).to.be(undefined);
const response3 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response3.status).to.be(200);
expect(response3.body[config.serviceKey].fieldAttrs.foo.count).to.be(undefined);
});
expect(response2.status).to.be(200);
expect(response2.body.index_pattern.fieldFormats.foo).to.eql({
id: 'bar-2',
params: { baz: 'qux-2' },
});
const response3 = await supertest.get(
`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}`
);
expect(response3.status).to.be(200);
expect(response3.body.index_pattern.fieldFormats.foo).to.eql({
id: 'bar-2',
params: { baz: 'qux-2' },
});
});
it('can remove "format" attribute from index_pattern format map', async () => {
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${indexPattern.id}/fields`)
.send({
fields: {
foo: {
format: null,
describe('customLabel', () => {
it('can set field "customLabel" attribute on non-existing field', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
},
});
expect(response1.status).to.be(200);
expect(response1.body[config.serviceKey].fieldAttrs.foo).to.be(undefined);
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/fields`)
.send({
fields: {
foo: {
customLabel: 'foo',
},
},
});
expect(response2.status).to.be(200);
expect(response2.body[config.serviceKey].fieldAttrs.foo.customLabel).to.be('foo');
const response3 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response3.status).to.be(200);
expect(response3.body[config.serviceKey].fieldAttrs.foo.customLabel).to.be('foo');
});
expect(response2.status).to.be(200);
expect(response2.body.index_pattern.fieldFormats.foo).to.be(undefined);
const response3 = await supertest.get(
`/api/index_patterns/index_pattern/${indexPattern.id}`
);
expect(response3.status).to.be(200);
expect(response3.body.index_pattern.fieldFormats.foo).to.be(undefined);
});
it('can set field "format" on an existing field', async () => {
const title = indexPattern.title;
await supertest.delete(`/api/index_patterns/index_pattern/${indexPattern.id}`);
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
fields: {
foo: {
name: 'foo',
type: 'string',
scripted: true,
format: {
id: 'string',
it('can update "customLabel" attribute in index_pattern attribute map', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
fieldAttrs: {
foo: {
customLabel: 'foo',
},
},
},
},
},
});
});
expect(response1.status).to.be(200);
expect(response1.body.index_pattern.fieldFormats.foo).to.be(undefined);
expect(response1.body.index_pattern.fields.foo.format).to.eql({
id: 'string',
});
expect(response1.status).to.be(200);
expect(response1.body[config.serviceKey].fieldAttrs.foo.customLabel).to.be('foo');
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/fields`)
.send({
fields: {
foo: {
format: { id: 'number' },
},
},
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/fields`)
.send({
fields: {
foo: {
customLabel: 'bar',
},
},
});
expect(response2.status).to.be(200);
expect(response2.body[config.serviceKey].fieldAttrs.foo.customLabel).to.be('bar');
const response3 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response3.status).to.be(200);
expect(response3.body[config.serviceKey].fieldAttrs.foo.customLabel).to.be('bar');
});
expect(response2.status).to.be(200);
expect(response2.body.index_pattern.fieldFormats.foo).to.eql({
id: 'number',
});
expect(response2.body.index_pattern.fields.foo.format).to.eql({
id: 'number',
it('can delete "customLabel" attribute from index_pattern attribute map', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
fieldAttrs: {
foo: {
customLabel: 'foo',
},
},
},
});
expect(response1.status).to.be(200);
expect(response1.body[config.serviceKey].fieldAttrs.foo.customLabel).to.be('foo');
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/fields`)
.send({
fields: {
foo: {
customLabel: null,
},
},
});
expect(response2.status).to.be(200);
expect(response2.body[config.serviceKey].fieldAttrs.foo.customLabel).to.be(undefined);
const response3 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response3.status).to.be(200);
expect(response3.body[config.serviceKey].fieldAttrs.foo.customLabel).to.be(undefined);
});
it('can set field "customLabel" attribute on an existing field', async () => {
await supertest.post(`${config.path}/${indexPattern.id}/fields`).send({
fields: {
foo: {
customLabel: 'baz',
},
},
});
const response1 = await supertest.get(`${config.path}/${indexPattern.id}`);
expect(response1.status).to.be(200);
expect(response1.body[config.serviceKey].fields.foo.customLabel).to.be('baz');
});
});
const response3 = await supertest.get(
`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}`
);
describe('format', () => {
it('can set field "format" attribute on non-existing field', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
});
expect(response3.status).to.be(200);
expect(response3.body.index_pattern.fieldFormats.foo).to.eql({
id: 'number',
});
expect(response3.body.index_pattern.fields.foo.format).to.eql({
id: 'number',
expect(response1.status).to.be(200);
expect(response1.body[config.serviceKey].fieldFormats.foo).to.be(undefined);
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/fields`)
.send({
fields: {
foo: {
format: {
id: 'bar',
params: { baz: 'qux' },
},
},
},
});
expect(response2.status).to.be(200);
expect(response2.body[config.serviceKey].fieldFormats.foo).to.eql({
id: 'bar',
params: { baz: 'qux' },
});
const response3 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response3.status).to.be(200);
expect(response3.body[config.serviceKey].fieldFormats.foo).to.eql({
id: 'bar',
params: { baz: 'qux' },
});
});
it('can update "format" attribute in index_pattern format map', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
fieldFormats: {
foo: {
id: 'bar',
params: {
baz: 'qux',
},
},
},
},
});
expect(response1.status).to.be(200);
expect(response1.body[config.serviceKey].fieldFormats.foo).to.eql({
id: 'bar',
params: {
baz: 'qux',
},
});
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/fields`)
.send({
fields: {
foo: {
format: {
id: 'bar-2',
params: { baz: 'qux-2' },
},
},
},
});
expect(response2.status).to.be(200);
expect(response2.body[config.serviceKey].fieldFormats.foo).to.eql({
id: 'bar-2',
params: { baz: 'qux-2' },
});
const response3 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response3.status).to.be(200);
expect(response3.body[config.serviceKey].fieldFormats.foo).to.eql({
id: 'bar-2',
params: { baz: 'qux-2' },
});
});
it('can remove "format" attribute from index_pattern format map', async () => {
const response2 = await supertest
.post(`${config.path}/${indexPattern.id}/fields`)
.send({
fields: {
foo: {
format: null,
},
},
});
expect(response2.status).to.be(200);
expect(response2.body[config.serviceKey].fieldFormats.foo).to.be(undefined);
const response3 = await supertest.get(`${config.path}/${indexPattern.id}`);
expect(response3.status).to.be(200);
expect(response3.body[config.serviceKey].fieldFormats.foo).to.be(undefined);
});
it('can set field "format" on an existing field', async () => {
const title = indexPattern.title;
await supertest.delete(`${config.path}/${indexPattern.id}`);
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
fields: {
foo: {
name: 'foo',
type: 'string',
scripted: true,
format: {
id: 'string',
},
},
},
},
});
expect(response1.status).to.be(200);
expect(response1.body[config.serviceKey].fieldFormats.foo).to.be(undefined);
expect(response1.body[config.serviceKey].fields.foo.format).to.eql({
id: 'string',
});
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/fields`)
.send({
fields: {
foo: {
format: { id: 'number' },
},
},
});
expect(response2.status).to.be(200);
expect(response2.body[config.serviceKey].fieldFormats.foo).to.eql({
id: 'number',
});
expect(response2.body[config.serviceKey].fields.foo.format).to.eql({
id: 'number',
});
const response3 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response3.status).to.be(200);
expect(response3.body[config.serviceKey].fieldFormats.foo).to.eql({
id: 'number',
});
expect(response3.body[config.serviceKey].fields.foo.format).to.eql({
id: 'number',
});
});
});
});
});

View file

@ -8,6 +8,7 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { configArray } from '../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
@ -15,125 +16,133 @@ export default function ({ getService }: FtrProviderContext) {
const es = getService('es');
describe('has user index pattern API', () => {
beforeEach(async () => {
await esArchiver.emptyKibanaIndex();
if (await es.indices.exists({ index: 'metrics-test' })) {
await es.indices.delete({ index: 'metrics-test' });
}
configArray.forEach((config) => {
describe(config.name, () => {
beforeEach(async () => {
await esArchiver.emptyKibanaIndex();
if (await es.indices.exists({ index: 'metrics-test' })) {
await es.indices.delete({ index: 'metrics-test' });
}
if (await es.indices.exists({ index: 'logs-test' })) {
await es.indices.delete({ index: 'logs-test' });
}
});
if (await es.indices.exists({ index: 'logs-test' })) {
await es.indices.delete({ index: 'logs-test' });
}
});
it('should return false if no index patterns', async () => {
const response = await supertest.get('/api/index_patterns/has_user_index_pattern');
expect(response.status).to.be(200);
expect(response.body.result).to.be(false);
});
const servicePath = `${config.basePath}/has_user_${config.serviceKey}`;
it('should return true if has index pattern with user data', async () => {
await esArchiver.load('test/api_integration/fixtures/es_archiver/index_patterns/basic_index');
await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title: 'basic_index',
},
it('should return false if no index patterns', async () => {
const response = await supertest.get(servicePath);
expect(response.status).to.be(200);
expect(response.body.result).to.be(false);
});
it('should return true if has index pattern with user data', async () => {
await esArchiver.load(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title: 'basic_index',
},
});
const response = await supertest.get(servicePath);
expect(response.status).to.be(200);
expect(response.body.result).to.be(true);
await esArchiver.unload(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
});
it('should return true if has user index pattern without data', async () => {
await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title: 'basic_index',
allowNoIndex: true,
},
});
const response = await supertest.get(servicePath);
expect(response.status).to.be(200);
expect(response.body.result).to.be(true);
});
it('should return false if only metric-* index pattern without data', async () => {
await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title: 'metrics-*',
allowNoIndex: true,
},
});
const response = await supertest.get(servicePath);
expect(response.status).to.be(200);
expect(response.body.result).to.be(false);
});
it('should return true if metric-* index pattern with user data', async () => {
await es.index({
index: 'metrics-test',
body: {
foo: 'bar',
},
});
await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title: 'metrics-*',
},
});
const response = await supertest.get(servicePath);
expect(response.status).to.be(200);
expect(response.body.result).to.be(true);
});
it('should return false if only logs-* index pattern without data', async () => {
await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title: 'logs-*',
},
});
const response = await supertest.get(servicePath);
expect(response.status).to.be(200);
expect(response.body.result).to.be(false);
});
it('should return true if logs-* index pattern with user data', async () => {
await es.index({
index: 'logs-test',
body: {
foo: 'bar',
},
});
await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title: 'logs-*',
},
});
const response = await supertest.get(servicePath);
expect(response.status).to.be(200);
expect(response.body.result).to.be(true);
});
// TODO: should setup fleet first similar to x-pack/test/fleet_functional/apps/home/welcome.ts
// but it is skipped due to flakiness https://github.com/elastic/kibana/issues/109017
it('should return false if logs-* with .ds-logs-elastic_agent only');
it('should return false if metrics-* with .ds-metrics-elastic_agent only');
});
const response = await supertest.get('/api/index_patterns/has_user_index_pattern');
expect(response.status).to.be(200);
expect(response.body.result).to.be(true);
await esArchiver.unload(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
});
it('should return true if has user index pattern without data', async () => {
await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title: 'basic_index',
allowNoIndex: true,
},
});
const response = await supertest.get('/api/index_patterns/has_user_index_pattern');
expect(response.status).to.be(200);
expect(response.body.result).to.be(true);
});
it('should return false if only metric-* index pattern without data', async () => {
await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title: 'metrics-*',
allowNoIndex: true,
},
});
const response = await supertest.get('/api/index_patterns/has_user_index_pattern');
expect(response.status).to.be(200);
expect(response.body.result).to.be(false);
});
it('should return true if metric-* index pattern with user data', async () => {
await es.index({
index: 'metrics-test',
body: {
foo: 'bar',
},
});
await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title: 'metrics-*',
},
});
const response = await supertest.get('/api/index_patterns/has_user_index_pattern');
expect(response.status).to.be(200);
expect(response.body.result).to.be(true);
});
it('should return false if only logs-* index pattern without data', async () => {
await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title: 'logs-*',
},
});
const response = await supertest.get('/api/index_patterns/has_user_index_pattern');
expect(response.status).to.be(200);
expect(response.body.result).to.be(false);
});
it('should return true if logs-* index pattern with user data', async () => {
await es.index({
index: 'logs-test',
body: {
foo: 'bar',
},
});
await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title: 'logs-*',
},
});
const response = await supertest.get('/api/index_patterns/has_user_index_pattern');
expect(response.status).to.be(200);
expect(response.body.result).to.be(true);
});
// TODO: should setup fleet first similar to x-pack/test/fleet_functional/apps/home/welcome.ts
// but it is skipped due to flakiness https://github.com/elastic/kibana/issues/109017
it('should return false if logs-* with .ds-logs-elastic_agent only');
it('should return false if metrics-* with .ds-metrics-elastic_agent only');
});
}

View file

@ -8,276 +8,286 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
describe('main', () => {
it('can create an index_pattern with just a title', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
});
expect(response.status).to.be(200);
});
it('returns back the created index_pattern object', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
});
expect(typeof response.body.index_pattern).to.be('object');
expect(response.body.index_pattern.title).to.be(title);
expect(typeof response.body.index_pattern.id).to.be('string');
expect(response.body.index_pattern.id.length > 0).to.be(true);
});
it('can specify primitive optional attributes when creating an index pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const id = `test-id-${Date.now()}-${Math.random()}*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
id,
type: 'test-type',
timeFieldName: 'test-timeFieldName',
},
});
expect(response.status).to.be(200);
expect(response.body.index_pattern.title).to.be(title);
expect(response.body.index_pattern.id).to.be(id);
expect(response.body.index_pattern.type).to.be('test-type');
expect(response.body.index_pattern.timeFieldName).to.be('test-timeFieldName');
});
it('can specify optional sourceFilters attribute when creating an index pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
sourceFilters: [
{
value: 'foo',
configArray.forEach((config) => {
describe(config.name, () => {
it('can create an index_pattern with just a title', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
],
},
});
});
expect(response.status).to.be(200);
expect(response.body.index_pattern.title).to.be(title);
expect(response.body.index_pattern.sourceFilters[0].value).to.be('foo');
});
describe('creating fields', () => {
before(async () => {
await esArchiver.load(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
});
after(async () => {
await esArchiver.unload(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
});
it('can specify optional fields attribute when creating an index pattern', async () => {
const title = `basic_index*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
fields: {
foo: {
name: 'foo',
type: 'string',
scripted: true,
script: "doc['field_name'].value",
},
},
},
expect(response.status).to.be(200);
});
expect(response.status).to.be(200);
expect(response.body.index_pattern.title).to.be(title);
expect(response.body.index_pattern.fields.foo.name).to.be('foo');
expect(response.body.index_pattern.fields.foo.type).to.be('string');
expect(response.body.index_pattern.fields.foo.scripted).to.be(true);
expect(response.body.index_pattern.fields.foo.script).to.be("doc['field_name'].value");
expect(response.body.index_pattern.fields.bar.name).to.be('bar'); // created from es index
expect(response.body.index_pattern.fields.bar.type).to.be('boolean');
});
it('can add scripted fields, other fields created from es index', async () => {
const title = `basic_index*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
fields: {
foo: {
name: 'foo',
type: 'string',
},
fake: {
name: 'fake',
type: 'string',
},
bar: {
name: 'bar',
type: 'number',
count: 123,
script: '',
esTypes: ['test-type'],
scripted: true,
},
it('returns back the created index_pattern object', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
},
});
expect(typeof response.body[config.serviceKey]).to.be('object');
expect(response.body[config.serviceKey].title).to.be(title);
expect(typeof response.body[config.serviceKey].id).to.be('string');
expect(response.body[config.serviceKey].id.length > 0).to.be(true);
});
expect(response.status).to.be(200);
expect(response.body.index_pattern.title).to.be(title);
it('can specify primitive optional attributes when creating an index pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const id = `test-id-${Date.now()}-${Math.random()}*`;
const response = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
id,
type: 'test-type',
timeFieldName: 'test-timeFieldName',
},
});
expect(response.body.index_pattern.fields.foo.name).to.be('foo');
expect(response.body.index_pattern.fields.foo.type).to.be('number'); // picked up from index
expect(response.status).to.be(200);
expect(response.body[config.serviceKey].title).to.be(title);
expect(response.body[config.serviceKey].id).to.be(id);
expect(response.body[config.serviceKey].type).to.be('test-type');
expect(response.body[config.serviceKey].timeFieldName).to.be('test-timeFieldName');
});
expect(response.body.index_pattern.fields.fake).to.be(undefined); // not in index, so not created
it('can specify optional sourceFilters attribute when creating an index pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
sourceFilters: [
{
value: 'foo',
},
],
},
});
expect(response.body.index_pattern.fields.bar.name).to.be('bar');
expect(response.body.index_pattern.fields.bar.type).to.be('number');
expect(response.body.index_pattern.fields.bar.count).to.be(123);
expect(response.body.index_pattern.fields.bar.script).to.be('');
expect(response.body.index_pattern.fields.bar.esTypes[0]).to.be('test-type');
expect(response.body.index_pattern.fields.bar.scripted).to.be(true);
});
expect(response.status).to.be(200);
expect(response.body[config.serviceKey].title).to.be(title);
expect(response.body[config.serviceKey].sourceFilters[0].value).to.be('foo');
});
it('can add runtime fields', async () => {
const title = `basic_index*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'keyword',
script: {
source: 'emit(doc["foo"].value)',
describe('creating fields', () => {
before(async () => {
await esArchiver.load(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
});
after(async () => {
await esArchiver.unload(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
});
it('can specify optional fields attribute when creating an index pattern', async () => {
const title = `basic_index*`;
const response = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
fields: {
foo: {
name: 'foo',
type: 'string',
scripted: true,
script: "doc['field_name'].value",
},
},
},
});
expect(response.status).to.be(200);
expect(response.body[config.serviceKey].title).to.be(title);
expect(response.body[config.serviceKey].fields.foo.name).to.be('foo');
expect(response.body[config.serviceKey].fields.foo.type).to.be('string');
expect(response.body[config.serviceKey].fields.foo.scripted).to.be(true);
expect(response.body[config.serviceKey].fields.foo.script).to.be(
"doc['field_name'].value"
);
expect(response.body[config.serviceKey].fields.bar.name).to.be('bar'); // created from es index
expect(response.body[config.serviceKey].fields.bar.type).to.be('boolean');
});
it('can add scripted fields, other fields created from es index', async () => {
const title = `basic_index*`;
const response = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
fields: {
foo: {
name: 'foo',
type: 'string',
},
fake: {
name: 'fake',
type: 'string',
},
bar: {
name: 'bar',
type: 'number',
count: 123,
script: '',
esTypes: ['test-type'],
scripted: true,
},
},
},
});
expect(response.status).to.be(200);
expect(response.body[config.serviceKey].title).to.be(title);
expect(response.body[config.serviceKey].fields.foo.name).to.be('foo');
expect(response.body[config.serviceKey].fields.foo.type).to.be('number'); // picked up from index
expect(response.body[config.serviceKey].fields.fake).to.be(undefined); // not in index, so not created
expect(response.body[config.serviceKey].fields.bar.name).to.be('bar');
expect(response.body[config.serviceKey].fields.bar.type).to.be('number');
expect(response.body[config.serviceKey].fields.bar.count).to.be(123);
expect(response.body[config.serviceKey].fields.bar.script).to.be('');
expect(response.body[config.serviceKey].fields.bar.esTypes[0]).to.be('test-type');
expect(response.body[config.serviceKey].fields.bar.scripted).to.be(true);
});
it('can add runtime fields', async () => {
const title = `basic_index*`;
const response = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'keyword',
script: {
source: 'emit(doc["foo"].value)',
},
},
},
},
});
expect(response.status).to.be(200);
expect(response.body[config.serviceKey].title).to.be(title);
expect(response.body[config.serviceKey].runtimeFieldMap.runtimeFoo.type).to.be(
'keyword'
);
expect(response.body[config.serviceKey].runtimeFieldMap.runtimeFoo.script.source).to.be(
'emit(doc["foo"].value)'
);
});
});
it('can specify optional typeMeta attribute when creating an index pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
typeMeta: {},
},
});
expect(response.status).to.be(200);
});
it('can specify optional fieldFormats attribute when creating an index pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
fieldFormats: {
foo: {
id: 'test-id',
params: {},
},
},
},
},
});
expect(response.status).to.be(200);
expect(response.body[config.serviceKey].fieldFormats.foo.id).to.be('test-id');
expect(response.body[config.serviceKey].fieldFormats.foo.params).to.eql({});
});
expect(response.status).to.be(200);
expect(response.body.index_pattern.title).to.be(title);
expect(response.body.index_pattern.runtimeFieldMap.runtimeFoo.type).to.be('keyword');
expect(response.body.index_pattern.runtimeFieldMap.runtimeFoo.script.source).to.be(
'emit(doc["foo"].value)'
);
});
});
it('can specify optional typeMeta attribute when creating an index pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
typeMeta: {},
},
});
expect(response.status).to.be(200);
});
it('can specify optional fieldFormats attribute when creating an index pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
fieldFormats: {
foo: {
id: 'test-id',
params: {},
it('can specify optional fieldFormats attribute when creating an index pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
fieldAttrs: {
foo: {
count: 123,
customLabel: 'test',
},
},
},
},
},
});
});
expect(response.status).to.be(200);
expect(response.body.index_pattern.fieldFormats.foo.id).to.be('test-id');
expect(response.body.index_pattern.fieldFormats.foo.params).to.eql({});
});
it('can specify optional fieldFormats attribute when creating an index pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
fieldAttrs: {
foo: {
count: 123,
customLabel: 'test',
},
},
},
});
expect(response.status).to.be(200);
expect(response.body.index_pattern.fieldAttrs.foo.count).to.be(123);
expect(response.body.index_pattern.fieldAttrs.foo.customLabel).to.be('test');
});
describe('when creating index pattern with existing title', () => {
it('returns error, by default', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
});
const response2 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
expect(response.status).to.be(200);
expect(response.body[config.serviceKey].fieldAttrs.foo.count).to.be(123);
expect(response.body[config.serviceKey].fieldAttrs.foo.customLabel).to.be('test');
});
expect(response1.status).to.be(200);
expect(response2.status).to.be(400);
});
describe('when creating index pattern with existing title', () => {
it('returns error, by default', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
});
const response2 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
});
it('succeeds, override flag is set', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
timeFieldName: 'foo',
},
expect(response1.status).to.be(200);
expect(response2.status).to.be(400);
});
it('succeeds, override flag is set', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
timeFieldName: 'foo',
},
});
const response2 = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
timeFieldName: 'bar',
},
});
expect(response1.status).to.be(200);
expect(response2.status).to.be(200);
expect(response1.body[config.serviceKey].timeFieldName).to.be('foo');
expect(response2.body[config.serviceKey].timeFieldName).to.be('bar');
expect(response1.body[config.serviceKey].id).to.be(
response1.body[config.serviceKey].id
);
});
});
const response2 = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
timeFieldName: 'bar',
},
});
expect(response1.status).to.be(200);
expect(response2.status).to.be(200);
expect(response1.body.index_pattern.timeFieldName).to.be('foo');
expect(response2.body.index_pattern.timeFieldName).to.be('bar');
expect(response1.body.index_pattern.id).to.be(response1.body.index_pattern.id);
});
});
});

View file

@ -8,81 +8,86 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
describe('validation', () => {
it('returns error when index_pattern object is not provided', async () => {
const response = await supertest.post('/api/index_patterns/index_pattern');
configArray.forEach((config) => {
describe(config.name, () => {
it('returns error when index_pattern object is not provided', async () => {
const response = await supertest.post(config.path);
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
'[request body]: expected a plain object value, but found [null] instead.'
);
});
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
'[request body]: expected a plain object value, but found [null] instead.'
);
});
it('returns error on empty index_pattern object', async () => {
const response = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {},
});
it('returns error on empty index_pattern object', async () => {
const response = await supertest.post(config.path).send({
[config.serviceKey]: {},
});
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
'[request body.index_pattern.title]: expected value of type [string] but got [undefined]'
);
});
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
`[request body.${config.serviceKey}.title]: expected value of type [string] but got [undefined]`
);
});
it('returns error when "override" parameter is not a boolean', async () => {
const response = await supertest.post('/api/index_patterns/index_pattern').send({
override: 123,
index_pattern: {
title: 'foo',
},
});
it('returns error when "override" parameter is not a boolean', async () => {
const response = await supertest.post(config.path).send({
override: 123,
[config.serviceKey]: {
title: 'foo',
},
});
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
'[request body.override]: expected value of type [boolean] but got [number]'
);
});
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
'[request body.override]: expected value of type [boolean] but got [number]'
);
});
it('returns error when "refresh_fields" parameter is not a boolean', async () => {
const response = await supertest.post('/api/index_patterns/index_pattern').send({
refresh_fields: 123,
index_pattern: {
title: 'foo',
},
});
it('returns error when "refresh_fields" parameter is not a boolean', async () => {
const response = await supertest.post(config.path).send({
refresh_fields: 123,
[config.serviceKey]: {
title: 'foo',
},
});
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
'[request body.refresh_fields]: expected value of type [boolean] but got [number]'
);
});
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
'[request body.refresh_fields]: expected value of type [boolean] but got [number]'
);
});
it('returns an error when unknown runtime field type', async () => {
const title = `basic_index*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'wrong-type',
script: {
source: 'emit(doc["foo"].value)',
it('returns an error when unknown runtime field type', async () => {
const title = `basic_index*`;
const response = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'wrong-type',
script: {
source: 'emit(doc["foo"].value)',
},
},
},
},
},
},
});
});
expect(response.status).to.be(400);
expect(response.status).to.be(400);
});
});
});
});
}

View file

@ -8,26 +8,31 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
describe('errors', () => {
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.delete(`/api/index_patterns/index_pattern/${id}`);
configArray.forEach((config) => {
describe(config.name, () => {
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.delete(`${config.path}/${id}`);
expect(response.status).to.be(404);
});
expect(response.status).to.be(404);
});
it('returns error when ID is too long', async () => {
const id = `xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx`;
const response = await supertest.delete(`/api/index_patterns/index_pattern/${id}`);
it('returns error when ID is too long', async () => {
const id = `xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx`;
const response = await supertest.delete(`${config.path}/${id}`);
expect(response.status).to.be(400);
expect(response.body.message).to.be(
'[request params.id]: value has length [1759] but it must have a maximum length of [1000].'
);
expect(response.status).to.be(400);
expect(response.body.message).to.be(
'[request params.id]: value has length [1759] but it must have a maximum length of [1000].'
);
});
});
});
});
}

View file

@ -8,50 +8,55 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
describe('main', () => {
it('deletes an index_pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
configArray.forEach((config) => {
describe(config.name, () => {
it('deletes an index_pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
});
const response2 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response2.status).to.be(200);
const response3 = await supertest.delete(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response3.status).to.be(200);
const response4 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response4.status).to.be(404);
});
it('returns nothing', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
});
await supertest.get(`${config.path}/${response1.body[config.serviceKey].id}`);
const response2 = await supertest.delete(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(!!response2.body).to.be(false);
});
});
const response2 = await supertest.get(
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
expect(response2.status).to.be(200);
const response3 = await supertest.delete(
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
expect(response3.status).to.be(200);
const response4 = await supertest.get(
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
expect(response4.status).to.be(404);
});
it('returns nothing', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
});
await supertest.get('/api/index_patterns/index_pattern/' + response1.body.index_pattern.id);
const response2 = await supertest.delete(
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
expect(!!response2.body).to.be(false);
});
});
}

View file

@ -8,26 +8,31 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
describe('errors', () => {
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.get(`/api/index_patterns/index_pattern/${id}`);
configArray.forEach((config) => {
describe(config.name, () => {
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.get(`${config.path}/${id}`);
expect(response.status).to.be(404);
});
expect(response.status).to.be(404);
});
it('returns error when ID is too long', async () => {
const id = `xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx`;
const response = await supertest.get(`/api/index_patterns/index_pattern/${id}`);
it('returns error when ID is too long', async () => {
const id = `xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx`;
const response = await supertest.get(`${config.path}/${id}`);
expect(response.status).to.be(400);
expect(response.body.message).to.be(
'[request params.id]: value has length [1759] but it must have a maximum length of [1000].'
);
expect(response.status).to.be(400);
expect(response.body.message).to.be(
'[request params.id]: value has length [1759] but it must have a maximum length of [1000].'
);
});
});
});
});
}

View file

@ -8,23 +8,28 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
describe('main', () => {
it('can retrieve an index_pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
});
const response2 = await supertest.get(
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
configArray.forEach((config) => {
describe(config.name, () => {
it('can retrieve an index_pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
});
const response2 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response2.body.index_pattern.title).to.be(title);
expect(response2.body[config.serviceKey].title).to.be(title);
});
});
});
});
}

View file

@ -8,65 +8,68 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
describe('errors', () => {
it('returns error when index_pattern object is not provided', async () => {
const response = await supertest.post('/api/index_patterns/index_pattern/foo');
configArray.forEach((config) => {
describe(config.name, () => {
it('returns error when index_pattern object is not provided', async () => {
const response = await supertest.post(`${config.path}/foo`);
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
'[request body]: expected a plain object value, but found [null] instead.'
);
});
it('returns error on non-existing index_pattern', async () => {
const response = await supertest
.post('/api/index_patterns/index_pattern/non-existing-index-pattern')
.send({
index_pattern: {},
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
'[request body]: expected a plain object value, but found [null] instead.'
);
});
expect(response.status).to.be(404);
expect(response.body.statusCode).to.be(404);
expect(response.body.message).to.be(
'Saved object [index-pattern/non-existing-index-pattern] not found'
);
});
it('returns error on non-existing index_pattern', async () => {
const response = await supertest.post(`${config.path}/non-existing-index-pattern`).send({
[config.serviceKey]: {},
});
it('returns error when "refresh_fields" parameter is not a boolean', async () => {
const response = await supertest.post('/api/index_patterns/index_pattern/foo`').send({
refresh_fields: 123,
index_pattern: {
title: 'foo',
},
expect(response.status).to.be(404);
expect(response.body.statusCode).to.be(404);
expect(response.body.message).to.be(
'Saved object [index-pattern/non-existing-index-pattern] not found'
);
});
it('returns error when "refresh_fields" parameter is not a boolean', async () => {
const response = await supertest.post(`${config.path}/foo`).send({
refresh_fields: 123,
[config.serviceKey]: {
title: 'foo',
},
});
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
'[request body.refresh_fields]: expected value of type [boolean] but got [number]'
);
});
it('returns error when update patch is empty', async () => {
const title1 = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post(config.path).send({
[config.serviceKey]: {
title: title1,
},
});
const id = response.body[config.serviceKey].id;
const response2 = await supertest.post(`${config.path}/${id}`).send({
[config.serviceKey]: {},
});
expect(response2.status).to.be(400);
expect(response2.body.statusCode).to.be(400);
expect(response2.body.message).to.be('Index pattern change set is empty.');
});
});
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
'[request body.refresh_fields]: expected value of type [boolean] but got [number]'
);
});
it('returns error when update patch is empty', async () => {
const title1 = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title: title1,
},
});
const id = response.body.index_pattern.id;
const response2 = await supertest.post('/api/index_patterns/index_pattern/' + id).send({
index_pattern: {},
});
expect(response2.status).to.be(400);
expect(response2.body.statusCode).to.be(400);
expect(response2.body.message).to.be('Index pattern change set is empty.');
});
});
}

View file

@ -8,301 +8,312 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
describe('main', () => {
it('can update index_pattern title', async () => {
const title1 = `foo-${Date.now()}-${Math.random()}*`;
const title2 = `bar-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title: title1,
},
});
configArray.forEach((config) => {
describe(config.name, () => {
it('can update index_pattern title', async () => {
const title1 = `foo-${Date.now()}-${Math.random()}*`;
const title2 = `bar-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title: title1,
},
});
expect(response1.body.index_pattern.title).to.be(title1);
expect(response1.body[config.serviceKey].title).to.be(title1);
const id = response1.body.index_pattern.id;
const response2 = await supertest.post('/api/index_patterns/index_pattern/' + id).send({
index_pattern: {
title: title2,
},
});
const id = response1.body[config.serviceKey].id;
const response2 = await supertest.post(`${config.path}/${id}`).send({
[config.serviceKey]: {
title: title2,
},
});
expect(response2.body.index_pattern.title).to.be(title2);
expect(response2.body[config.serviceKey].title).to.be(title2);
const response3 = await supertest.get('/api/index_patterns/index_pattern/' + id);
const response3 = await supertest.get(`${config.path}/${id}`);
expect(response3.body.index_pattern.title).to.be(title2);
});
expect(response3.body[config.serviceKey].title).to.be(title2);
});
it('can update index_pattern timeFieldName', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
timeFieldName: 'timeFieldName1',
},
});
it('can update index_pattern timeFieldName', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
timeFieldName: 'timeFieldName1',
},
});
expect(response1.body.index_pattern.timeFieldName).to.be('timeFieldName1');
expect(response1.body[config.serviceKey].timeFieldName).to.be('timeFieldName1');
const id = response1.body.index_pattern.id;
const response2 = await supertest.post('/api/index_patterns/index_pattern/' + id).send({
index_pattern: {
timeFieldName: 'timeFieldName2',
},
});
const id = response1.body[config.serviceKey].id;
const response2 = await supertest.post(`${config.path}/${id}`).send({
[config.serviceKey]: {
timeFieldName: 'timeFieldName2',
},
});
expect(response2.body.index_pattern.timeFieldName).to.be('timeFieldName2');
expect(response2.body[config.serviceKey].timeFieldName).to.be('timeFieldName2');
const response3 = await supertest.get('/api/index_patterns/index_pattern/' + id);
const response3 = await supertest.get(`${config.path}/${id}`);
expect(response3.body.index_pattern.timeFieldName).to.be('timeFieldName2');
});
expect(response3.body[config.serviceKey].timeFieldName).to.be('timeFieldName2');
});
it('can update index_pattern sourceFilters', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
sourceFilters: [
it('can update index_pattern sourceFilters', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
sourceFilters: [
{
value: 'foo',
},
],
},
});
expect(response1.body[config.serviceKey].sourceFilters).to.eql([
{
value: 'foo',
},
],
},
});
]);
expect(response1.body.index_pattern.sourceFilters).to.eql([
{
value: 'foo',
},
]);
const id = response1.body[config.serviceKey].id;
const response2 = await supertest.post(`${config.path}/${id}`).send({
[config.serviceKey]: {
sourceFilters: [
{
value: 'bar',
},
{
value: 'baz',
},
],
},
});
const id = response1.body.index_pattern.id;
const response2 = await supertest.post('/api/index_patterns/index_pattern/' + id).send({
index_pattern: {
sourceFilters: [
expect(response2.body[config.serviceKey].sourceFilters).to.eql([
{
value: 'bar',
},
{
value: 'baz',
},
],
},
});
]);
expect(response2.body.index_pattern.sourceFilters).to.eql([
{
value: 'bar',
},
{
value: 'baz',
},
]);
const response3 = await supertest.get(`${config.path}/${id}`);
const response3 = await supertest.get('/api/index_patterns/index_pattern/' + id);
expect(response3.body[config.serviceKey].sourceFilters).to.eql([
{
value: 'bar',
},
{
value: 'baz',
},
]);
});
expect(response3.body.index_pattern.sourceFilters).to.eql([
{
value: 'bar',
},
{
value: 'baz',
},
]);
});
it('can update index_pattern fieldFormats', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
fieldFormats: {
foo: {
id: 'foo',
params: {
bar: 'baz',
},
},
},
},
});
it('can update index_pattern fieldFormats', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
fieldFormats: {
expect(response1.body[config.serviceKey].fieldFormats).to.eql({
foo: {
id: 'foo',
params: {
bar: 'baz',
},
},
},
},
});
});
expect(response1.body.index_pattern.fieldFormats).to.eql({
foo: {
id: 'foo',
params: {
bar: 'baz',
},
},
});
const id = response1.body[config.serviceKey].id;
const response2 = await supertest.post(`${config.path}/${id}`).send({
[config.serviceKey]: {
fieldFormats: {
a: {
id: 'a',
params: {
b: 'v',
},
},
},
},
});
const id = response1.body.index_pattern.id;
const response2 = await supertest.post('/api/index_patterns/index_pattern/' + id).send({
index_pattern: {
fieldFormats: {
expect(response2.body[config.serviceKey].fieldFormats).to.eql({
a: {
id: 'a',
params: {
b: 'v',
},
},
},
},
});
});
expect(response2.body.index_pattern.fieldFormats).to.eql({
a: {
id: 'a',
params: {
b: 'v',
},
},
});
const response3 = await supertest.get(`${config.path}/${id}`);
const response3 = await supertest.get('/api/index_patterns/index_pattern/' + id);
expect(response3.body.index_pattern.fieldFormats).to.eql({
a: {
id: 'a',
params: {
b: 'v',
},
},
});
});
it('can update index_pattern type', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
type: 'foo',
},
});
expect(response1.body.index_pattern.type).to.be('foo');
const id = response1.body.index_pattern.id;
const response2 = await supertest.post('/api/index_patterns/index_pattern/' + id).send({
index_pattern: {
type: 'bar',
},
});
expect(response2.body.index_pattern.type).to.be('bar');
const response3 = await supertest.get('/api/index_patterns/index_pattern/' + id);
expect(response3.body.index_pattern.type).to.be('bar');
});
it('can update index_pattern typeMeta', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
typeMeta: { foo: 'bar' },
},
});
expect(response1.body.index_pattern.typeMeta).to.eql({ foo: 'bar' });
const id = response1.body.index_pattern.id;
const response2 = await supertest.post('/api/index_patterns/index_pattern/' + id).send({
index_pattern: {
typeMeta: { foo: 'baz' },
},
});
expect(response2.body.index_pattern.typeMeta).to.eql({ foo: 'baz' });
const response3 = await supertest.get('/api/index_patterns/index_pattern/' + id);
expect(response3.body.index_pattern.typeMeta).to.eql({ foo: 'baz' });
});
it('can update multiple index pattern fields at once', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
timeFieldName: 'timeFieldName1',
typeMeta: { foo: 'bar' },
},
});
expect(response1.body.index_pattern.timeFieldName).to.be('timeFieldName1');
expect(response1.body.index_pattern.typeMeta.foo).to.be('bar');
const id = response1.body.index_pattern.id;
const response2 = await supertest.post('/api/index_patterns/index_pattern/' + id).send({
index_pattern: {
timeFieldName: 'timeFieldName2',
typeMeta: { baz: 'qux' },
},
});
expect(response2.body.index_pattern.timeFieldName).to.be('timeFieldName2');
expect(response2.body.index_pattern.typeMeta.baz).to.be('qux');
const response3 = await supertest.get('/api/index_patterns/index_pattern/' + id);
expect(response3.body.index_pattern.timeFieldName).to.be('timeFieldName2');
expect(response3.body.index_pattern.typeMeta.baz).to.be('qux');
});
it('can update runtime fields', async () => {
const title = `basic_index*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'keyword',
script: {
source: 'emit(doc["foo"].value)',
expect(response3.body[config.serviceKey].fieldFormats).to.eql({
a: {
id: 'a',
params: {
b: 'v',
},
},
},
},
});
});
});
expect(response1.status).to.be(200);
expect(response1.body.index_pattern.title).to.be(title);
it('can update index_pattern type', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
type: 'foo',
},
});
expect(response1.body.index_pattern.runtimeFieldMap.runtimeFoo.type).to.be('keyword');
expect(response1.body.index_pattern.runtimeFieldMap.runtimeFoo.script.source).to.be(
'emit(doc["foo"].value)'
);
expect(response1.body[config.serviceKey].type).to.be('foo');
const id = response1.body.index_pattern.id;
const response2 = await supertest.post('/api/index_patterns/index_pattern/' + id).send({
index_pattern: {
runtimeFieldMap: {
runtimeBar: {
type: 'keyword',
script: {
source: 'emit(doc["foo"].value)',
const id = response1.body[config.serviceKey].id;
const response2 = await supertest.post(`${config.path}/${id}`).send({
[config.serviceKey]: {
type: 'bar',
},
});
expect(response2.body[config.serviceKey].type).to.be('bar');
const response3 = await supertest.get(`${config.path}/${id}`);
expect(response3.body[config.serviceKey].type).to.be('bar');
});
it('can update index_pattern typeMeta', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
typeMeta: { foo: 'bar' },
},
});
expect(response1.body[config.serviceKey].typeMeta).to.eql({ foo: 'bar' });
const id = response1.body[config.serviceKey].id;
const response2 = await supertest.post(`${config.path}/${id}`).send({
[config.serviceKey]: {
typeMeta: { foo: 'baz' },
},
});
expect(response2.body[config.serviceKey].typeMeta).to.eql({ foo: 'baz' });
const response3 = await supertest.get(`${config.path}/${id}`);
expect(response3.body[config.serviceKey].typeMeta).to.eql({ foo: 'baz' });
});
it('can update multiple index pattern fields at once', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
timeFieldName: 'timeFieldName1',
typeMeta: { foo: 'bar' },
},
});
expect(response1.body[config.serviceKey].timeFieldName).to.be('timeFieldName1');
expect(response1.body[config.serviceKey].typeMeta.foo).to.be('bar');
const id = response1.body[config.serviceKey].id;
const response2 = await supertest.post(`${config.path}/${id}`).send({
[config.serviceKey]: {
timeFieldName: 'timeFieldName2',
typeMeta: { baz: 'qux' },
},
});
expect(response2.body[config.serviceKey].timeFieldName).to.be('timeFieldName2');
expect(response2.body[config.serviceKey].typeMeta.baz).to.be('qux');
const response3 = await supertest.get(`${config.path}/${id}`);
expect(response3.body[config.serviceKey].timeFieldName).to.be('timeFieldName2');
expect(response3.body[config.serviceKey].typeMeta.baz).to.be('qux');
});
it('can update runtime fields', async () => {
const title = `basic_index*`;
const response1 = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'keyword',
script: {
source: 'emit(doc["foo"].value)',
},
},
},
},
},
},
});
expect(response1.status).to.be(200);
expect(response1.body[config.serviceKey].title).to.be(title);
expect(response1.body[config.serviceKey].runtimeFieldMap.runtimeFoo.type).to.be(
'keyword'
);
expect(response1.body[config.serviceKey].runtimeFieldMap.runtimeFoo.script.source).to.be(
'emit(doc["foo"].value)'
);
const id = response1.body[config.serviceKey].id;
const response2 = await supertest.post(`${config.path}/${id}`).send({
[config.serviceKey]: {
runtimeFieldMap: {
runtimeBar: {
type: 'keyword',
script: {
source: 'emit(doc["foo"].value)',
},
},
},
},
});
expect(response2.body[config.serviceKey].runtimeFieldMap.runtimeBar.type).to.be(
'keyword'
);
expect(response2.body[config.serviceKey].runtimeFieldMap.runtimeFoo).to.be(undefined);
const response3 = await supertest.get(`${config.path}/${id}`);
expect(response3.body[config.serviceKey].runtimeFieldMap.runtimeBar.type).to.be(
'keyword'
);
expect(response3.body[config.serviceKey].runtimeFieldMap.runtimeFoo).to.be(undefined);
});
});
expect(response2.body.index_pattern.runtimeFieldMap.runtimeBar.type).to.be('keyword');
expect(response2.body.index_pattern.runtimeFieldMap.runtimeFoo).to.be(undefined);
const response3 = await supertest.get('/api/index_patterns/index_pattern/' + id);
expect(response3.body.index_pattern.runtimeFieldMap.runtimeBar.type).to.be('keyword');
expect(response3.body.index_pattern.runtimeFieldMap.runtimeFoo).to.be(undefined);
});
});
}

View file

@ -8,28 +8,31 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
describe('errors', () => {
it('returns an error field object is not provided', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
},
});
const id = response1.body.index_pattern.id;
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${id}/runtime_field`)
.send({});
configArray.forEach((config) => {
describe(config.name, () => {
it('returns an error field object is not provided', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post(config.path).send({
[config.serviceKey]: {
title,
},
});
const id = response1.body[config.serviceKey].id;
const response2 = await supertest.post(`${config.path}/${id}/runtime_field`).send({});
expect(response2.status).to.be(400);
expect(response2.body.statusCode).to.be(400);
expect(response2.body.message).to.be(
'[request body.name]: expected value of type [string] but got [undefined]'
);
expect(response2.status).to.be(400);
expect(response2.body.statusCode).to.be(400);
expect(response2.body.message).to.be(
'[request body.name]: expected value of type [string] but got [undefined]'
);
});
});
});
});
}

View file

@ -8,6 +8,7 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
@ -24,72 +25,73 @@ export default function ({ getService }: FtrProviderContext) {
);
});
it('can create a new runtime field', async () => {
const title = `basic_index*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
},
});
const id = response1.body.index_pattern.id;
const response2 = await supertest
.post(`/api/index_patterns/index_pattern/${id}/runtime_field`)
.send({
name: 'runtimeBar',
runtimeField: {
type: 'long',
script: {
source: "emit(doc['field_name'].value)",
configArray.forEach((config) => {
describe(config.name, () => {
it('can create a new runtime field', async () => {
const title = `basic_index*`;
const response1 = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
},
},
});
const id = response1.body[config.serviceKey].id;
const response2 = await supertest.post(`${config.path}/${id}/runtime_field`).send({
name: 'runtimeBar',
runtimeField: {
type: 'long',
script: {
source: "emit(doc['field_name'].value)",
},
},
});
expect(response2.status).to.be(200);
const field =
config.serviceKey === 'index_pattern' ? response2.body.field : response2.body.fields[0];
expect(field.name).to.be('runtimeBar');
expect(field.runtimeField.type).to.be('long');
expect(field.runtimeField.script.source).to.be("emit(doc['field_name'].value)");
expect(field.scripted).to.be(false);
});
expect(response2.status).to.be(200);
expect(response2.body.field.name).to.be('runtimeBar');
expect(response2.body.field.runtimeField.type).to.be('long');
expect(response2.body.field.runtimeField.script.source).to.be(
"emit(doc['field_name'].value)"
);
expect(response2.body.field.scripted).to.be(false);
});
it('newly created runtime field is available in the index_pattern object', async () => {
const title = `basic_index`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
},
});
await supertest
.post(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/runtime_field`)
.send({
name: 'runtimeBar',
runtimeField: {
type: 'long',
script: {
source: "emit(doc['field_name'].value)",
it('newly created runtime field is available in the index_pattern object', async () => {
const title = `basic_index`;
const response1 = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
},
},
});
await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/runtime_field`)
.send({
name: 'runtimeBar',
runtimeField: {
type: 'long',
script: {
source: "emit(doc['field_name'].value)",
},
},
});
const response2 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(response2.status).to.be(200);
const field = response2.body[config.serviceKey].fields.runtimeBar;
expect(field.name).to.be('runtimeBar');
expect(field.runtimeField.type).to.be('long');
expect(field.runtimeField.script.source).to.be("emit(doc['field_name'].value)");
expect(field.scripted).to.be(false);
await supertest.delete(`${config.path}/${response1.body[config.serviceKey].id}`);
});
const response2 = await supertest.get(
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
expect(response2.status).to.be(200);
const field = response2.body.index_pattern.fields.runtimeBar;
expect(field.name).to.be('runtimeBar');
expect(field.runtimeField.type).to.be('long');
expect(field.runtimeField.script.source).to.be("emit(doc['field_name'].value)");
expect(field.scripted).to.be(false);
await supertest.delete(
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
});
});
});
}

View file

@ -8,6 +8,7 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
@ -17,65 +18,67 @@ export default function ({ getService }: FtrProviderContext) {
const basicIndex = 'b*sic_index';
let indexPattern: any;
before(async () => {
await esArchiver.load('test/api_integration/fixtures/es_archiver/index_patterns/basic_index');
configArray.forEach((config) => {
describe(config.name, () => {
before(async () => {
await esArchiver.load(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
indexPattern = (
await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title: basicIndex,
},
})
).body.index_pattern;
});
indexPattern = (
await supertest.post(config.path).send({
[config.serviceKey]: {
title: basicIndex,
},
})
).body[config.serviceKey];
});
after(async () => {
await esArchiver.unload(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
after(async () => {
await esArchiver.unload(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
if (indexPattern) {
await supertest.delete('/api/index_patterns/index_pattern/' + indexPattern.id);
}
});
if (indexPattern) {
await supertest.delete(`${config.path}/${indexPattern.id}`);
}
});
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.delete(
`/api/index_patterns/index_pattern/${id}/runtime_field/foo`
);
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.delete(`${config.path}/${id}/runtime_field/foo`);
expect(response.status).to.be(404);
});
expect(response.status).to.be(404);
});
it('returns 404 error on non-existing runtime field', async () => {
const response1 = await supertest.delete(
`/api/index_patterns/index_pattern/${indexPattern.id}/runtime_field/test`
);
it('returns 404 error on non-existing runtime field', async () => {
const response1 = await supertest.delete(
`${config.path}/${indexPattern.id}/runtime_field/test`
);
expect(response1.status).to.be(404);
});
expect(response1.status).to.be(404);
});
it('returns error when attempting to delete a field which is not a runtime field', async () => {
const response2 = await supertest.delete(
`/api/index_patterns/index_pattern/${indexPattern.id}/runtime_field/foo`
);
it('returns error when attempting to delete a field which is not a runtime field', async () => {
const response2 = await supertest.delete(
`${config.path}/${indexPattern.id}/runtime_field/foo`
);
expect(response2.status).to.be(400);
expect(response2.body.statusCode).to.be(400);
expect(response2.body.message).to.be('Only runtime fields can be deleted.');
});
expect(response2.status).to.be(400);
expect(response2.body.statusCode).to.be(400);
expect(response2.body.message).to.be('Only runtime fields can be deleted.');
});
it('returns error when ID is too long', async () => {
const id = `xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx`;
const response = await supertest.delete(
`/api/index_patterns/index_pattern/${id}/runtime_field/foo`
);
it('returns error when ID is too long', async () => {
const id = `xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx`;
const response = await supertest.delete(`${config.path}/${id}/runtime_field/foo`);
expect(response.status).to.be(400);
expect(response.body.message).to.be(
'[request params.id]: value has length [1759] but it must have a maximum length of [1000].'
);
expect(response.status).to.be(400);
expect(response.body.message).to.be(
'[request params.id]: value has length [1759] but it must have a maximum length of [1000].'
);
});
});
});
});
}

View file

@ -8,6 +8,7 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
@ -24,43 +25,45 @@ export default function ({ getService }: FtrProviderContext) {
);
});
it('can delete a runtime field', async () => {
const title = `basic_index*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
runtimeFieldMap: {
runtimeBar: {
type: 'long',
script: {
source: "emit(doc['field_name'].value)",
configArray.forEach((config) => {
describe(config.name, () => {
it('can delete a runtime field', async () => {
const title = `basic_index*`;
const response1 = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
runtimeFieldMap: {
runtimeBar: {
type: 'long',
script: {
source: "emit(doc['field_name'].value)",
},
},
},
},
},
},
});
const response2 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(typeof response2.body[config.serviceKey].fields.runtimeBar).to.be('object');
const response3 = await supertest.delete(
`${config.path}/${response1.body[config.serviceKey].id}/runtime_field/runtimeBar`
);
expect(response3.status).to.be(200);
const response4 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}`
);
expect(typeof response4.body[config.serviceKey].fields.runtimeBar).to.be('undefined');
await supertest.delete(`${config.path}/${response1.body[config.serviceKey].id}`);
});
});
const response2 = await supertest.get(
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
expect(typeof response2.body.index_pattern.fields.runtimeBar).to.be('object');
const response3 = await supertest.delete(
`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/runtime_field/runtimeBar`
);
expect(response3.status).to.be(200);
const response4 = await supertest.get(
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
expect(typeof response4.body.index_pattern.fields.runtimeBar).to.be('undefined');
await supertest.delete(
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
});
});
}

View file

@ -8,6 +8,7 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
@ -17,65 +18,67 @@ export default function ({ getService }: FtrProviderContext) {
const basicIndex = '*asic_index';
let indexPattern: any;
before(async () => {
await esArchiver.load('test/api_integration/fixtures/es_archiver/index_patterns/basic_index');
configArray.forEach((config) => {
describe(config.name, () => {
before(async () => {
await esArchiver.load(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
indexPattern = (
await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title: basicIndex,
},
})
).body.index_pattern;
});
indexPattern = (
await supertest.post(config.path).send({
[config.serviceKey]: {
title: basicIndex,
},
})
).body[config.serviceKey];
});
after(async () => {
await esArchiver.unload(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
after(async () => {
await esArchiver.unload(
'test/api_integration/fixtures/es_archiver/index_patterns/basic_index'
);
if (indexPattern) {
await supertest.delete('/api/index_patterns/index_pattern/' + indexPattern.id);
}
});
if (indexPattern) {
await supertest.delete(`${config.path}/${indexPattern.id}`);
}
});
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.get(
`/api/index_patterns/index_pattern/${id}/runtime_field/foo`
);
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.get(`${config.path}/${id}/runtime_field/foo`);
expect(response.status).to.be(404);
});
expect(response.status).to.be(404);
});
it('returns 404 error on non-existing runtime field', async () => {
const response1 = await supertest.get(
`/api/index_patterns/index_pattern/${indexPattern.id}/runtime_field/sf`
);
it('returns 404 error on non-existing runtime field', async () => {
const response1 = await supertest.get(
`${config.path}/${indexPattern.id}/runtime_field/sf`
);
expect(response1.status).to.be(404);
});
expect(response1.status).to.be(404);
});
it('returns error when ID is too long', async () => {
const id = `xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx`;
const response = await supertest.get(
`/api/index_patterns/index_pattern/${id}/runtime_field/foo`
);
it('returns error when ID is too long', async () => {
const id = `xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx`;
const response = await supertest.get(`${config.path}/${id}/runtime_field/foo`);
expect(response.status).to.be(400);
expect(response.body.message).to.be(
'[request params.id]: value has length [1759] but it must have a maximum length of [1000].'
);
});
expect(response.status).to.be(400);
expect(response.body.message).to.be(
'[request params.id]: value has length [1759] but it must have a maximum length of [1000].'
);
});
it('returns error when attempting to fetch a field which is not a runtime field', async () => {
const response2 = await supertest.get(
`/api/index_patterns/index_pattern/${indexPattern.id}/runtime_field/foo`
);
it('returns error when attempting to fetch a field which is not a runtime field', async () => {
const response2 = await supertest.get(
`${config.path}/${indexPattern.id}/runtime_field/foo`
);
expect(response2.status).to.be(400);
expect(response2.body.statusCode).to.be(400);
expect(response2.body.message).to.be('Only runtime fields can be retrieved.');
expect(response2.status).to.be(400);
expect(response2.body.statusCode).to.be(400);
expect(response2.body.message).to.be('Only runtime fields can be retrieved.');
});
});
});
});
}

View file

@ -8,6 +8,7 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
@ -24,48 +25,49 @@ export default function ({ getService }: FtrProviderContext) {
);
});
it('can fetch a runtime field', async () => {
const title = `basic_index*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'keyword',
script: {
source: "emit(doc['field_name'].value)",
configArray.forEach((config) => {
describe(config.name, () => {
it('can fetch a runtime field', async () => {
const title = `basic_index*`;
const response1 = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'keyword',
script: {
source: "emit(doc['field_name'].value)",
},
},
runtimeBar: {
type: 'keyword',
script: {
source: "emit(doc['field_name'].value)",
},
},
},
},
runtimeBar: {
type: 'keyword',
script: {
source: "emit(doc['field_name'].value)",
},
},
},
},
});
expect(response1.status).to.be(200);
const response2 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}/runtime_field/runtimeFoo`
);
const field =
config.serviceKey === 'index_pattern' ? response2.body.field : response2.body.fields[0];
expect(response2.status).to.be(200);
expect(typeof field).to.be('object');
expect(field.name).to.be('runtimeFoo');
expect(field.type).to.be('string');
expect(field.scripted).to.be(false);
expect(field.runtimeField.script.source).to.be("emit(doc['field_name'].value)");
await supertest.delete(`${config.path}/${response1.body[config.serviceKey].id}`);
});
});
expect(response1.status).to.be(200);
const response2 = await supertest.get(
'/api/index_patterns/index_pattern/' +
response1.body.index_pattern.id +
'/runtime_field/runtimeFoo'
);
expect(response2.status).to.be(200);
expect(typeof response2.body.field).to.be('object');
expect(response2.body.field.name).to.be('runtimeFoo');
expect(response2.body.field.type).to.be('string');
expect(response2.body.field.scripted).to.be(false);
expect(response2.body.field.runtimeField.script.source).to.be(
"emit(doc['field_name'].value)"
);
await supertest.delete(
'/api/index_patterns/index_pattern/' + response1.body.index_pattern.id
);
});
});
}

View file

@ -8,6 +8,7 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
@ -24,46 +25,48 @@ export default function ({ getService }: FtrProviderContext) {
);
});
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest
.put(`/api/index_patterns/index_pattern/${id}/runtime_field`)
.send({
name: 'runtimeBar',
runtimeField: {
type: 'long',
script: {
source: "emit(doc['field_name'].value)",
configArray.forEach((config) => {
describe(config.name, () => {
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.put(`${config.path}/${id}/runtime_field`).send({
name: 'runtimeBar',
runtimeField: {
type: 'long',
script: {
source: "emit(doc['field_name'].value)",
},
},
},
});
expect(response.status).to.be(404);
});
expect(response.status).to.be(404);
});
it('returns error on non-runtime field update attempt', async () => {
const title = `basic_index`;
const response1 = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
},
});
it('returns error on non-runtime field update attempt', async () => {
const title = `basic_index`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
},
const response2 = await supertest
.put(`${config.path}/${response1.body[config.serviceKey].id}/runtime_field`)
.send({
name: 'bar',
runtimeField: {
type: 'long',
script: {
source: "emit(doc['field_name'].value)",
},
},
});
expect(response2.status).to.be(400);
expect(response2.body.message).to.be('Only runtime fields can be updated');
});
});
const response2 = await supertest
.put(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/runtime_field`)
.send({
name: 'bar',
runtimeField: {
type: 'long',
script: {
source: "emit(doc['field_name'].value)",
},
},
});
expect(response2.status).to.be(400);
expect(response2.body.message).to.be('Only runtime fields can be updated');
});
});
}

View file

@ -8,6 +8,7 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
@ -24,99 +25,106 @@ export default function ({ getService }: FtrProviderContext) {
);
});
it('can overwrite an existing field', async () => {
const title = `basic_index`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'keyword',
script: {
source: "doc['field_name'].value",
configArray.forEach((config) => {
describe(config.name, () => {
it('can overwrite an existing field', async () => {
const title = `basic_index`;
const response1 = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'keyword',
script: {
source: "doc['field_name'].value",
},
},
runtimeBar: {
type: 'keyword',
script: {
source: "doc['field_name'].value",
},
},
},
},
runtimeBar: {
type: 'keyword',
script: {
source: "doc['field_name'].value",
},
},
},
},
});
});
const response2 = await supertest
.put(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/runtime_field`)
.send({
name: 'runtimeFoo',
runtimeField: {
type: 'long',
script: {
source: "doc['field_name'].value",
},
},
const response2 = await supertest
.put(`${config.path}/${response1.body[config.serviceKey].id}/runtime_field`)
.send({
name: 'runtimeFoo',
runtimeField: {
type: 'long',
script: {
source: "doc['field_name'].value",
},
},
});
expect(response2.status).to.be(200);
const response3 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}/runtime_field/runtimeFoo`
);
const field3 =
config.serviceKey === 'index_pattern' ? response3.body.field : response3.body.fields[0];
expect(response3.status).to.be(200);
expect(field3.type).to.be('number');
const response4 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}/runtime_field/runtimeBar`
);
const field4 =
config.serviceKey === 'index_pattern' ? response4.body.field : response4.body.fields[0];
expect(response4.status).to.be(200);
expect(field4.type).to.be('string');
});
expect(response2.status).to.be(200);
const response3 = await supertest.get(
'/api/index_patterns/index_pattern/' +
response1.body.index_pattern.id +
'/runtime_field/runtimeFoo'
);
expect(response3.status).to.be(200);
expect(response3.body.field.type).to.be('number');
const response4 = await supertest.get(
'/api/index_patterns/index_pattern/' +
response1.body.index_pattern.id +
'/runtime_field/runtimeBar'
);
expect(response4.status).to.be(200);
expect(response4.body.field.type).to.be('string');
});
it('can add a new runtime field', async () => {
const title = `basic_index`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'keyword',
script: {
source: "doc['field_name'].value",
it('can add a new runtime field', async () => {
const title = `basic_index`;
const response1 = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'keyword',
script: {
source: "doc['field_name'].value",
},
},
},
},
},
},
});
});
await supertest
.put(`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/runtime_field`)
.send({
name: 'runtimeBar',
runtimeField: {
type: 'long',
script: {
source: "doc['field_name'].value",
},
},
await supertest
.put(`${config.path}/${response1.body[config.serviceKey].id}/runtime_field`)
.send({
name: 'runtimeBar',
runtimeField: {
type: 'long',
script: {
source: "doc['field_name'].value",
},
},
});
const response2 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}/runtime_field/runtimeBar`
);
const field =
config.serviceKey === 'index_pattern' ? response2.body.field : response2.body.fields[0];
expect(response2.status).to.be(200);
expect(typeof field.runtimeField).to.be('object');
});
const response2 = await supertest.get(
'/api/index_patterns/index_pattern/' +
response1.body.index_pattern.id +
'/runtime_field/runtimeBar'
);
expect(response2.status).to.be(200);
expect(typeof response2.body.field.runtimeField).to.be('object');
});
});
});
}

View file

@ -8,44 +8,45 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
describe('errors', () => {
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest
.post(`/api/index_patterns/index_pattern/${id}/runtime_field/foo`)
.send({
runtimeField: {
script: {
source: "doc['something_new'].value",
configArray.forEach((config) => {
describe(config.name, () => {
it('returns 404 error on non-existing index_pattern', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.post(`${config.path}/${id}/runtime_field/foo`).send({
runtimeField: {
script: {
source: "doc['something_new'].value",
},
},
},
});
expect(response.status).to.be(404);
});
expect(response.status).to.be(404);
});
it('returns error when field name is specified', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest
.post(`/api/index_patterns/index_pattern/${id}/runtime_field/foo`)
.send({
name: 'foo',
runtimeField: {
script: {
source: "doc['something_new'].value",
it('returns error when field name is specified', async () => {
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`;
const response = await supertest.post(`${config.path}/${id}/runtime_field/foo`).send({
name: 'foo',
runtimeField: {
script: {
source: "doc['something_new'].value",
},
},
},
});
});
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
"[request body.name]: a value wasn't expected to be present"
);
expect(response.status).to.be(400);
expect(response.body.statusCode).to.be(400);
expect(response.body.message).to.be(
"[request body.name]: a value wasn't expected to be present"
);
});
});
});
});
}

View file

@ -8,6 +8,7 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { configArray } from '../../constants';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
@ -24,53 +25,56 @@ export default function ({ getService }: FtrProviderContext) {
);
});
it('can update an existing field', async () => {
const title = `basic_index`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'keyword',
script: {
source: "doc['field_name'].value",
configArray.forEach((config) => {
describe(config.name, () => {
it('can update an existing field', async () => {
const title = `basic_index`;
const response1 = await supertest.post(config.path).send({
override: true,
[config.serviceKey]: {
title,
runtimeFieldMap: {
runtimeFoo: {
type: 'keyword',
script: {
source: "doc['field_name'].value",
},
},
runtimeBar: {
type: 'keyword',
script: {
source: "doc['field_name'].value",
},
},
},
},
runtimeBar: {
type: 'keyword',
script: {
source: "doc['field_name'].value",
},
},
},
},
});
});
const response2 = await supertest
.post(
`/api/index_patterns/index_pattern/${response1.body.index_pattern.id}/runtime_field/runtimeFoo`
)
.send({
runtimeField: {
script: {
source: "doc['something_new'].value",
},
},
const response2 = await supertest
.post(`${config.path}/${response1.body[config.serviceKey].id}/runtime_field/runtimeFoo`)
.send({
runtimeField: {
script: {
source: "doc['something_new'].value",
},
},
});
expect(response2.status).to.be(200);
const response3 = await supertest.get(
`${config.path}/${response1.body[config.serviceKey].id}/runtime_field/runtimeFoo`
);
const field =
config.serviceKey === 'index_pattern' ? response3.body.field : response3.body.fields[0];
expect(response3.status).to.be(200);
expect(field.type).to.be('string');
expect(field.runtimeField.type).to.be('keyword');
expect(field.runtimeField.script.source).to.be("doc['something_new'].value");
});
expect(response2.status).to.be(200);
const response3 = await supertest.get(
'/api/index_patterns/index_pattern/' +
response1.body.index_pattern.id +
'/runtime_field/runtimeFoo'
);
expect(response3.status).to.be(200);
expect(response3.body.field.type).to.be('string');
expect(response3.body.field.runtimeField.type).to.be('keyword');
expect(response3.body.field.runtimeField.script.source).to.be("doc['something_new'].value");
});
});
});
}