mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Data views, getExistingIndices
method to server side (#168522)
This commit is contained in:
parent
b61f570979
commit
91435a573f
23 changed files with 547 additions and 88 deletions
|
@ -57,3 +57,9 @@ export const PLUGIN_NAME = 'DataViews';
|
|||
* @public
|
||||
*/
|
||||
export const FIELDS_FOR_WILDCARD_PATH = '/internal/data_views/_fields_for_wildcard';
|
||||
|
||||
/**
|
||||
* Existing indices path
|
||||
* @public
|
||||
*/
|
||||
export const EXISTING_INDICES_PATH = '/internal/data_views/_existing_indices';
|
||||
|
|
|
@ -662,36 +662,4 @@ describe('IndexPatterns', () => {
|
|||
expect(apiClient.getFieldsForWildcard.mock.calls[0][0].allowNoIndex).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getExistingIndices', () => {
|
||||
test('getExistingIndices returns the valid matched indices', async () => {
|
||||
apiClient.getFieldsForWildcard = jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce({ fields: ['length'] })
|
||||
.mockResolvedValue({ fields: [] });
|
||||
const patternList = await indexPatterns.getExistingIndices(['packetbeat-*', 'filebeat-*']);
|
||||
expect(apiClient.getFieldsForWildcard).toBeCalledTimes(2);
|
||||
expect(patternList.length).toBe(1);
|
||||
});
|
||||
|
||||
test('getExistingIndices checks the positive pattern if provided with a negative pattern', async () => {
|
||||
const mockFn = jest.fn().mockResolvedValue({ fields: ['length'] });
|
||||
apiClient.getFieldsForWildcard = mockFn;
|
||||
const patternList = await indexPatterns.getExistingIndices(['-filebeat-*', 'filebeat-*']);
|
||||
expect(mockFn.mock.calls[0][0].pattern).toEqual('filebeat-*');
|
||||
expect(mockFn.mock.calls[1][0].pattern).toEqual('filebeat-*');
|
||||
expect(patternList).toEqual(['-filebeat-*', 'filebeat-*']);
|
||||
});
|
||||
|
||||
test('getExistingIndices handles an error', async () => {
|
||||
apiClient.getFieldsForWildcard = jest
|
||||
.fn()
|
||||
.mockImplementationOnce(async () => {
|
||||
throw new DataViewMissingIndices('Catch me if you can!');
|
||||
})
|
||||
.mockImplementation(() => Promise.resolve({ fields: ['length'] }));
|
||||
const patternList = await indexPatterns.getExistingIndices(['packetbeat-*', 'filebeat-*']);
|
||||
expect(patternList).toEqual(['filebeat-*']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,12 +7,10 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { defer, from } from 'rxjs';
|
||||
import type { PublicMethodsOf } from '@kbn/utility-types';
|
||||
import { castEsToKbnFieldTypeName } from '@kbn/field-types';
|
||||
import { FieldFormatsStartCommon, FORMATS_UI_SETTINGS } from '@kbn/field-formats-plugin/common';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { rateLimitingForkJoin } from './utils';
|
||||
import { PersistenceAPI } from '../types';
|
||||
|
||||
import { createDataViewCache } from '.';
|
||||
|
@ -240,12 +238,6 @@ export interface DataViewsServicePublicMethods {
|
|||
* @param options - options for getting fields
|
||||
*/
|
||||
getFieldsForWildcard: (options: GetFieldsOptions) => Promise<FieldSpec[]>;
|
||||
/**
|
||||
* Get existing index pattern list by providing string array index pattern list.
|
||||
* @param indices - index pattern list
|
||||
* @returns index pattern list of index patterns that match indices
|
||||
*/
|
||||
getExistingIndices: (indices: string[]) => Promise<string[]>;
|
||||
/**
|
||||
* Get list of data view ids.
|
||||
* @param refresh - clear cache and fetch from server
|
||||
|
@ -524,41 +516,6 @@ export class DataViewsService {
|
|||
return fields;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get existing index pattern list by providing string array index pattern list.
|
||||
* @param indices index pattern list
|
||||
* @returns index pattern list
|
||||
*/
|
||||
getExistingIndices = async (indices: string[]): Promise<string[]> => {
|
||||
const indicesObs = indices.map((pattern) => {
|
||||
// when checking a negative pattern, check if the positive pattern exists
|
||||
const indexToQuery = pattern.trim().startsWith('-')
|
||||
? pattern.trim().substring(1)
|
||||
: pattern.trim();
|
||||
return defer(() =>
|
||||
from(
|
||||
this.getFieldsForWildcard({
|
||||
// check one field to keep request fast/small
|
||||
fields: ['_id'],
|
||||
// true so no errors thrown in browser
|
||||
allowNoIndex: true,
|
||||
pattern: indexToQuery,
|
||||
})
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return new Promise<boolean[]>((resolve) => {
|
||||
rateLimitingForkJoin(indicesObs, 3, []).subscribe((value) => {
|
||||
resolve(value.map((v) => v.length > 0));
|
||||
});
|
||||
})
|
||||
.then((allPatterns: boolean[]) =>
|
||||
indices.filter((pattern, i, self) => self.indexOf(pattern) === i && allPatterns[i])
|
||||
)
|
||||
.catch(() => indices);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get field list by providing an index patttern (or spec).
|
||||
* @param options options for getting field list
|
||||
|
|
|
@ -319,6 +319,11 @@ export interface FieldsForWildcardResponse {
|
|||
indices: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Existing Indices response
|
||||
*/
|
||||
export type ExistingIndicesResponse = string[];
|
||||
|
||||
export interface IDataViewsApiClient {
|
||||
getFieldsForWildcard: (options: GetFieldsOptions) => Promise<FieldsForWildcardResponse>;
|
||||
hasUserDataView: () => Promise<boolean>;
|
||||
|
|
|
@ -6,11 +6,15 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { HttpStart } from '@kbn/core/public';
|
||||
import { DataViewsService, MatchedItem } from '.';
|
||||
|
||||
import { DataViewsServiceDeps } from '../common/data_views/data_views';
|
||||
import { HasDataService } from '../common';
|
||||
|
||||
import { ExistingIndicesResponse } from '../common/types';
|
||||
import { EXISTING_INDICES_PATH } from '../common/constants';
|
||||
|
||||
/**
|
||||
* Data Views public service dependencies
|
||||
* @public
|
||||
|
@ -32,6 +36,7 @@ export interface DataViewsServicePublicDeps extends DataViewsServiceDeps {
|
|||
|
||||
getRollupsEnabled: () => boolean;
|
||||
scriptedFieldsEnabled: boolean;
|
||||
http: HttpStart;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,6 +53,7 @@ export class DataViewsServicePublic extends DataViewsService {
|
|||
}) => Promise<MatchedItem[]>;
|
||||
public hasData: HasDataService;
|
||||
private rollupsEnabled: boolean = false;
|
||||
private readonly http: HttpStart;
|
||||
public readonly scriptedFieldsEnabled: boolean;
|
||||
|
||||
/**
|
||||
|
@ -62,9 +68,22 @@ export class DataViewsServicePublic extends DataViewsService {
|
|||
this.getIndices = deps.getIndices;
|
||||
this.rollupsEnabled = deps.getRollupsEnabled();
|
||||
this.scriptedFieldsEnabled = deps.scriptedFieldsEnabled;
|
||||
this.http = deps.http;
|
||||
}
|
||||
|
||||
getRollupsEnabled() {
|
||||
return this.rollupsEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get existing index pattern list by providing string array index pattern list.
|
||||
* @param indices - index pattern list
|
||||
* @returns index pattern list of index patterns that match indices
|
||||
*/
|
||||
async getExistingIndices(indices: string[]): Promise<ExistingIndicesResponse> {
|
||||
return this.http.get<ExistingIndicesResponse>(EXISTING_INDICES_PATH, {
|
||||
query: { indices },
|
||||
version: '1',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,6 +88,7 @@ export class DataViewsPublicPlugin
|
|||
savedObjectsClient: new ContentMagementWrapper(contentManagement.client),
|
||||
apiClient: new DataViewsApiClient(http),
|
||||
fieldFormats,
|
||||
http,
|
||||
onNotification: (toastInputFields, key) => {
|
||||
onNotifDebounced(key)(toastInputFields);
|
||||
},
|
||||
|
|
|
@ -123,6 +123,12 @@ export interface DataViewsServicePublic extends DataViewsServicePublicMethods {
|
|||
}) => Promise<MatchedItem[]>;
|
||||
getRollupsEnabled: () => boolean;
|
||||
scriptedFieldsEnabled: boolean;
|
||||
/**
|
||||
* Get existing index pattern list by providing string array index pattern list.
|
||||
* @param indices - index pattern list
|
||||
* @returns index pattern list of index patterns that match indices
|
||||
*/
|
||||
getExistingIndices: (indices: string[]) => Promise<string[]>;
|
||||
}
|
||||
|
||||
export type DataViewsContract = DataViewsServicePublic;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { IndexPatternsFetcher } from '.';
|
||||
import { elasticsearchServiceMock } from '@kbn/core/server/mocks';
|
||||
import { DataViewMissingIndices } from '../../common';
|
||||
|
||||
const rollupResponse = {
|
||||
foo: {
|
||||
|
@ -34,17 +35,16 @@ describe('Index Pattern Fetcher - server', () => {
|
|||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
esClient = elasticsearchServiceMock.createElasticsearchClient();
|
||||
esClient.fieldCaps.mockResponse(response as unknown as estypes.FieldCapsResponse);
|
||||
indexPatterns = new IndexPatternsFetcher(esClient, false, true);
|
||||
});
|
||||
it('calls fieldcaps once', async () => {
|
||||
esClient.fieldCaps.mockResponse(response as unknown as estypes.FieldCapsResponse);
|
||||
indexPatterns = new IndexPatternsFetcher(esClient, true, true);
|
||||
await indexPatterns.getFieldsForWildcard({ pattern: patternList });
|
||||
expect(esClient.fieldCaps).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('calls rollup api when given rollup data view', async () => {
|
||||
esClient.fieldCaps.mockResponse(response as unknown as estypes.FieldCapsResponse);
|
||||
esClient.rollup.getRollupIndexCaps.mockResponse(
|
||||
rollupResponse as unknown as estypes.RollupGetRollupIndexCapsResponse
|
||||
);
|
||||
|
@ -58,7 +58,6 @@ describe('Index Pattern Fetcher - server', () => {
|
|||
});
|
||||
|
||||
it("doesn't call rollup api when given rollup data view and rollups are disabled", async () => {
|
||||
esClient.fieldCaps.mockResponse(response as unknown as estypes.FieldCapsResponse);
|
||||
esClient.rollup.getRollupIndexCaps.mockResponse(
|
||||
rollupResponse as unknown as estypes.RollupGetRollupIndexCapsResponse
|
||||
);
|
||||
|
@ -70,4 +69,39 @@ describe('Index Pattern Fetcher - server', () => {
|
|||
});
|
||||
expect(esClient.rollup.getRollupIndexCaps).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
describe('getExistingIndices', () => {
|
||||
test('getExistingIndices returns the valid matched indices', async () => {
|
||||
indexPatterns = new IndexPatternsFetcher(esClient, true, true);
|
||||
indexPatterns.getFieldsForWildcard = jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce({ indices: ['length'] })
|
||||
.mockResolvedValue({ indices: [] });
|
||||
const result = await indexPatterns.getExistingIndices(['packetbeat-*', 'filebeat-*']);
|
||||
expect(indexPatterns.getFieldsForWildcard).toBeCalledTimes(2);
|
||||
expect(result.length).toBe(1);
|
||||
});
|
||||
|
||||
test('getExistingIndices checks the positive pattern if provided with a negative pattern', async () => {
|
||||
indexPatterns = new IndexPatternsFetcher(esClient, true, true);
|
||||
const mockFn = jest.fn().mockResolvedValue({ indices: ['length'] });
|
||||
indexPatterns.getFieldsForWildcard = mockFn;
|
||||
const result = await indexPatterns.getExistingIndices(['-filebeat-*', 'filebeat-*']);
|
||||
expect(mockFn.mock.calls[0][0].pattern).toEqual('filebeat-*');
|
||||
expect(mockFn.mock.calls[1][0].pattern).toEqual('filebeat-*');
|
||||
expect(result).toEqual(['-filebeat-*', 'filebeat-*']);
|
||||
});
|
||||
|
||||
test('getExistingIndices handles an error', async () => {
|
||||
indexPatterns = new IndexPatternsFetcher(esClient, true, true);
|
||||
indexPatterns.getFieldsForWildcard = jest
|
||||
.fn()
|
||||
.mockImplementationOnce(async () => {
|
||||
throw new DataViewMissingIndices('Catch me if you can!');
|
||||
})
|
||||
.mockImplementation(() => Promise.resolve({ indices: ['length'] }));
|
||||
const result = await indexPatterns.getExistingIndices(['packetbeat-*', 'filebeat-*']);
|
||||
expect(result).toEqual(['filebeat-*']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { ElasticsearchClient } from '@kbn/core/server';
|
||||
import { keyBy } from 'lodash';
|
||||
import { defer, from } from 'rxjs';
|
||||
import { rateLimitingForkJoin } from '../../common/data_views/utils';
|
||||
import type { QueryDslQueryContainer } from '../../common/types';
|
||||
|
||||
import {
|
||||
|
@ -117,4 +119,37 @@ export class IndexPatternsFetcher {
|
|||
}
|
||||
return fieldCapsResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get existing index pattern list by providing string array index pattern list.
|
||||
* @param indices - index pattern list
|
||||
* @returns index pattern list of index patterns that match indices
|
||||
*/
|
||||
async getExistingIndices(indices: string[]): Promise<string[]> {
|
||||
const indicesObs = indices.map((pattern) => {
|
||||
// when checking a negative pattern, check if the positive pattern exists
|
||||
const indexToQuery = pattern.trim().startsWith('-')
|
||||
? pattern.trim().substring(1)
|
||||
: pattern.trim();
|
||||
return defer(() =>
|
||||
from(
|
||||
this.getFieldsForWildcard({
|
||||
// check one field to keep request fast/small
|
||||
fields: ['_id'],
|
||||
pattern: indexToQuery,
|
||||
})
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return new Promise<boolean[]>((resolve) => {
|
||||
rateLimitingForkJoin(indicesObs, 3, { fields: [], indices: [] }).subscribe((value) => {
|
||||
resolve(value.map((v) => v.indices.length > 0));
|
||||
});
|
||||
})
|
||||
.then((allPatterns: boolean[]) =>
|
||||
indices.filter((pattern, i, self) => self.indexOf(pattern) === i && allPatterns[i])
|
||||
)
|
||||
.catch(() => indices);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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 { parseIndices } from './existing_indices';
|
||||
|
||||
describe('parseIndices', () => {
|
||||
it('should return an array of indices when given an array of indices', () => {
|
||||
const indices = ['index1', 'index2', 'index3'];
|
||||
const result = parseIndices(indices);
|
||||
expect(result).toEqual(indices);
|
||||
});
|
||||
|
||||
it('should return an array of indices when given a JSON-stringified array of indices', () => {
|
||||
const indices = '["index1", "index2", "index3"]';
|
||||
const result = parseIndices(indices);
|
||||
expect(result).toEqual(['index1', 'index2', 'index3']);
|
||||
});
|
||||
|
||||
it('should return an array with a single index when given a single index name', () => {
|
||||
const index = 'index1';
|
||||
const result = parseIndices(index);
|
||||
expect(result).toEqual(['index1']);
|
||||
});
|
||||
|
||||
it('should throw an error when given an invalid JSON-stringified array', () => {
|
||||
const indices = '["index1", "index2"';
|
||||
expect(() => {
|
||||
parseIndices(indices);
|
||||
}).toThrowError(
|
||||
'indices should be an array of index aliases, a JSON-stringified array of index aliases, or a single index alias'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error when given a string with a comma but not JSON-stringified', () => {
|
||||
const indices = 'index1,index2';
|
||||
expect(() => {
|
||||
parseIndices(indices);
|
||||
}).toThrowError(
|
||||
'indices should be an array of index aliases, a JSON-stringified array of index aliases, or a single index alias'
|
||||
);
|
||||
});
|
||||
|
||||
it('should return an empty array when given an empty array', () => {
|
||||
const indices: string[] = [];
|
||||
const result = parseIndices(indices);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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 { IRouter, RequestHandler } from '@kbn/core/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { INITIAL_REST_VERSION_INTERNAL as version } from '../../constants';
|
||||
import { IndexPatternsFetcher } from '../..';
|
||||
import { EXISTING_INDICES_PATH } from '../../../common/constants';
|
||||
|
||||
/**
|
||||
* Accepts one of the following:
|
||||
* 1. An array of field names
|
||||
* 2. A JSON-stringified array of field names
|
||||
* 3. A single field name (not comma-separated)
|
||||
* @returns an array of indices
|
||||
* @param indices
|
||||
*/
|
||||
export const parseIndices = (indices: string | string[]): string[] => {
|
||||
if (Array.isArray(indices)) return indices;
|
||||
try {
|
||||
return JSON.parse(indices);
|
||||
} catch (e) {
|
||||
if (!indices.includes(',')) return [indices];
|
||||
throw new Error(
|
||||
'indices should be an array of index aliases, a JSON-stringified array of index aliases, or a single index alias'
|
||||
);
|
||||
}
|
||||
};
|
||||
export const handler: RequestHandler<{}, { indices: string | string[] }, string[]> = async (
|
||||
ctx,
|
||||
req,
|
||||
res
|
||||
) => {
|
||||
const { indices } = req.query;
|
||||
try {
|
||||
const indexArray = parseIndices(indices);
|
||||
const core = await ctx.core;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const indexPatterns = new IndexPatternsFetcher(elasticsearchClient, true);
|
||||
|
||||
const response: string[] = await indexPatterns.getExistingIndices(indexArray);
|
||||
return res.ok({ body: response });
|
||||
} catch (error) {
|
||||
return res.badRequest();
|
||||
}
|
||||
};
|
||||
|
||||
export const registerExistingIndicesPath = (router: IRouter): void => {
|
||||
router.versioned
|
||||
.get({
|
||||
path: EXISTING_INDICES_PATH,
|
||||
access: 'internal',
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
version,
|
||||
validate: {
|
||||
request: {
|
||||
query: schema.object({
|
||||
indices: schema.oneOf([schema.string(), schema.arrayOf(schema.string())]),
|
||||
}),
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
body: schema.arrayOf(schema.string()),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
handler
|
||||
);
|
||||
};
|
|
@ -11,6 +11,7 @@ import { UsageCounter } from '@kbn/usage-collection-plugin/server';
|
|||
import { routes } from './rest_api_routes/public';
|
||||
import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from './types';
|
||||
|
||||
import { registerExistingIndicesPath } from './rest_api_routes/internal/existing_indices';
|
||||
import { registerFieldForWildcard } from './rest_api_routes/internal/fields_for';
|
||||
import { registerHasDataViewsRoute } from './rest_api_routes/internal/has_data_views';
|
||||
|
||||
|
@ -27,6 +28,7 @@ export function registerRoutes(
|
|||
|
||||
routes.forEach((route) => route(router, getStartServices, dataViewRestCounter));
|
||||
|
||||
registerExistingIndicesPath(router);
|
||||
registerFieldForWildcard(router, getStartServices, isRollupsEnabled);
|
||||
registerHasDataViewsRoute(router);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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 { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||
describe('index_patterns/_existing_indices route', () => {
|
||||
loadTestFile(require.resolve('./params'));
|
||||
loadTestFile(require.resolve('./response'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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 { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common';
|
||||
import { INITIAL_REST_VERSION_INTERNAL } from '@kbn/data-views-plugin/server/constants';
|
||||
import { EXISTING_INDICES_PATH } from '@kbn/data-views-plugin/common/constants';
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default function ({ getService }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const supertest = getService('supertest');
|
||||
const randomness = getService('randomness');
|
||||
|
||||
describe('_existing_indices params', () => {
|
||||
before(() =>
|
||||
esArchiver.load('test/api_integration/fixtures/es_archiver/index_patterns/basic_index')
|
||||
);
|
||||
after(() =>
|
||||
esArchiver.unload('test/api_integration/fixtures/es_archiver/index_patterns/basic_index')
|
||||
);
|
||||
|
||||
it('requires a query param', () =>
|
||||
supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
.query({})
|
||||
.expect(400));
|
||||
|
||||
it('accepts indices param as single index string', () =>
|
||||
supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
.query({
|
||||
indices: 'filebeat-*',
|
||||
})
|
||||
.expect(200));
|
||||
|
||||
it('accepts indices param as single index array', () =>
|
||||
supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
.query({
|
||||
indices: ['filebeat-*'],
|
||||
})
|
||||
.expect(200));
|
||||
|
||||
it('accepts indices param', () =>
|
||||
supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
.query({
|
||||
indices: ['filebeat-*', 'packetbeat-*'],
|
||||
})
|
||||
.expect(200));
|
||||
|
||||
it('rejects unexpected query params', () =>
|
||||
supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
.query({
|
||||
[randomness.word()]: randomness.word(),
|
||||
})
|
||||
.expect(400));
|
||||
|
||||
it('rejects a comma-separated list of indices', () =>
|
||||
supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
.query({
|
||||
indices: 'filebeat-*,packetbeat-*',
|
||||
})
|
||||
.expect(400));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common';
|
||||
import { INITIAL_REST_VERSION_INTERNAL } from '@kbn/data-views-plugin/server/constants';
|
||||
import { EXISTING_INDICES_PATH } from '@kbn/data-views-plugin/common/constants';
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default function ({ getService }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const supertest = getService('supertest');
|
||||
|
||||
describe('_existing_indices response', () => {
|
||||
before(() =>
|
||||
esArchiver.load('test/api_integration/fixtures/es_archiver/index_patterns/basic_index')
|
||||
);
|
||||
after(() =>
|
||||
esArchiver.unload('test/api_integration/fixtures/es_archiver/index_patterns/basic_index')
|
||||
);
|
||||
|
||||
it('returns an array of existing indices', async () => {
|
||||
await supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
.query({
|
||||
indices: ['basic_index', 'bad_index'],
|
||||
})
|
||||
.expect(200, ['basic_index']);
|
||||
});
|
||||
|
||||
it('returns an empty array when no indices exist', async () => {
|
||||
await supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
.query({
|
||||
indices: ['bad_index'],
|
||||
})
|
||||
.expect(200, []);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -11,6 +11,7 @@ import { FtrProviderContext } from '../../ftr_provider_context';
|
|||
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||
describe('index_patterns', () => {
|
||||
loadTestFile(require.resolve('./es_errors'));
|
||||
loadTestFile(require.resolve('./existing_indices_route'));
|
||||
loadTestFile(require.resolve('./fields_for_wildcard_route'));
|
||||
loadTestFile(require.resolve('./data_views_crud'));
|
||||
loadTestFile(require.resolve('./scripted_fields_crud'));
|
||||
|
|
|
@ -5,11 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type {
|
||||
DataViewListItem,
|
||||
DataViewsContract,
|
||||
DataView as DataViewType,
|
||||
} from '@kbn/data-views-plugin/common';
|
||||
import type { DataViewListItem, DataView as DataViewType } from '@kbn/data-views-plugin/common';
|
||||
import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public/types';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { ensurePatternFormat } from '../../../../common/utils/sourcerer';
|
||||
import type { KibanaDataView } from '../../store/sourcerer/model';
|
||||
|
@ -21,7 +18,7 @@ export interface GetSourcererDataView {
|
|||
body: {
|
||||
patternList: string[];
|
||||
};
|
||||
dataViewService: DataViewsContract;
|
||||
dataViewService: DataViewsServicePublic;
|
||||
dataViewId: string | null;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { getSourcererDataView } from './get_sourcerer_data_view';
|
||||
import type { DataViewsService } from '@kbn/data-views-plugin/common';
|
||||
import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public/types';
|
||||
|
||||
const dataViewId = 'test-id';
|
||||
const dataViewsService = {
|
||||
|
@ -20,7 +20,7 @@ const dataViewsService = {
|
|||
fields: {},
|
||||
}),
|
||||
getExistingIndices: jest.fn().mockResolvedValue(['test-pattern']),
|
||||
} as unknown as jest.Mocked<DataViewsService>;
|
||||
} as unknown as jest.Mocked<DataViewsServicePublic>;
|
||||
describe('getSourcererDataView', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { DataViewsContract } from '@kbn/data-views-plugin/common';
|
||||
import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public/types';
|
||||
import { ensurePatternFormat } from '../../../../common/utils/sourcerer';
|
||||
import type { SourcererDataView, RunTimeMappings } from '../../store/sourcerer/model';
|
||||
import { getDataViewStateFromIndexFields } from '../source/use_data_view';
|
||||
|
||||
export const getSourcererDataView = async (
|
||||
dataViewId: string,
|
||||
dataViewsService: DataViewsContract,
|
||||
dataViewsService: DataViewsServicePublic,
|
||||
refreshFields = false
|
||||
): Promise<SourcererDataView> => {
|
||||
const dataView = await dataViewsService.get(dataViewId, true, refreshFields);
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { FtrProviderContext } from '../../../../ftr_provider_context';
|
||||
|
||||
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||
describe('index_patterns/_existing_indices route', () => {
|
||||
loadTestFile(require.resolve('./params'));
|
||||
loadTestFile(require.resolve('./response'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common';
|
||||
import { INITIAL_REST_VERSION_INTERNAL } from '@kbn/data-views-plugin/server/constants';
|
||||
import { EXISTING_INDICES_PATH } from '@kbn/data-views-plugin/common/constants';
|
||||
import type { FtrProviderContext } from '../../../../ftr_provider_context';
|
||||
|
||||
export default function ({ getService }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const supertest = getService('supertest');
|
||||
const randomness = getService('randomness');
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
|
||||
describe('_existing_indices params', () => {
|
||||
before(() =>
|
||||
esArchiver.load('test/api_integration/fixtures/es_archiver/index_patterns/basic_index')
|
||||
);
|
||||
after(() =>
|
||||
esArchiver.unload('test/api_integration/fixtures/es_archiver/index_patterns/basic_index')
|
||||
);
|
||||
|
||||
it('requires a query param', () =>
|
||||
supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
// TODO: API requests in Serverless require internal request headers
|
||||
.set(svlCommonApi.getInternalRequestHeader())
|
||||
.query({})
|
||||
.expect(400));
|
||||
|
||||
it('accepts indices param as single index string', () =>
|
||||
supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
// TODO: API requests in Serverless require internal request headers
|
||||
.set(svlCommonApi.getInternalRequestHeader())
|
||||
.query({
|
||||
indices: 'filebeat-*',
|
||||
})
|
||||
.expect(200));
|
||||
|
||||
it('accepts indices param as single index array', () =>
|
||||
supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
// TODO: API requests in Serverless require internal request headers
|
||||
.set(svlCommonApi.getInternalRequestHeader())
|
||||
.query({
|
||||
indices: ['filebeat-*'],
|
||||
})
|
||||
.expect(200));
|
||||
|
||||
it('accepts indices param', () =>
|
||||
supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
// TODO: API requests in Serverless require internal request headers
|
||||
.set(svlCommonApi.getInternalRequestHeader())
|
||||
.query({
|
||||
indices: ['filebeat-*', 'packetbeat-*'],
|
||||
})
|
||||
.expect(200));
|
||||
|
||||
it('rejects unexpected query params', () =>
|
||||
supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
// TODO: API requests in Serverless require internal request headers
|
||||
.set(svlCommonApi.getInternalRequestHeader())
|
||||
.query({
|
||||
[randomness.word()]: randomness.word(),
|
||||
})
|
||||
.expect(400));
|
||||
|
||||
it('rejects a comma-separated list of indices', () =>
|
||||
supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
// TODO: API requests in Serverless require internal request headers
|
||||
.set(svlCommonApi.getInternalRequestHeader())
|
||||
.query({
|
||||
indices: 'filebeat-*,packetbeat-*',
|
||||
})
|
||||
.expect(400));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common';
|
||||
import { INITIAL_REST_VERSION_INTERNAL } from '@kbn/data-views-plugin/server/constants';
|
||||
import { EXISTING_INDICES_PATH } from '@kbn/data-views-plugin/common/constants';
|
||||
import type { FtrProviderContext } from '../../../../ftr_provider_context';
|
||||
|
||||
export default function ({ getService }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const supertest = getService('supertest');
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
|
||||
describe('_existing_indices response', () => {
|
||||
before(() =>
|
||||
esArchiver.load('test/api_integration/fixtures/es_archiver/index_patterns/basic_index')
|
||||
);
|
||||
after(() =>
|
||||
esArchiver.unload('test/api_integration/fixtures/es_archiver/index_patterns/basic_index')
|
||||
);
|
||||
|
||||
it('returns an array of existing indices', async () => {
|
||||
await supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
// TODO: API requests in Serverless require internal request headers
|
||||
.set(svlCommonApi.getInternalRequestHeader())
|
||||
.query({
|
||||
indices: ['basic_index', 'bad_index'],
|
||||
})
|
||||
.expect(200, ['basic_index']);
|
||||
});
|
||||
|
||||
it('returns an empty array when no indices exist', async () => {
|
||||
await supertest
|
||||
.get(EXISTING_INDICES_PATH)
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL)
|
||||
// TODO: API requests in Serverless require internal request headers
|
||||
.set(svlCommonApi.getInternalRequestHeader())
|
||||
.query({
|
||||
indices: ['bad_index'],
|
||||
})
|
||||
.expect(200, []);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -12,6 +12,7 @@ export default function ({ loadTestFile }: FtrProviderContext) {
|
|||
this.tags(['esGate']);
|
||||
|
||||
loadTestFile(require.resolve('./es_errors'));
|
||||
loadTestFile(require.resolve('./existing_indices_route'));
|
||||
loadTestFile(require.resolve('./fields_for_wildcard_route'));
|
||||
loadTestFile(require.resolve('./data_views_crud'));
|
||||
// TODO: Removed `scripted_fields_crud` since
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue