* TypeScriptify errors.js * Fixed type errors in errors.ts * Prettierize resolve_time_pattern.test.js * Prettierize resolve_time_pattern.js * TypeScriptify resolve_time_pattern.js * Prettierize mixin.js * Fixed errors.ts payload error. * TypeScriptify and Prettierize mixin.ts * Prettierize query_params.js * TypeScriptified routes and used core.http features and fixed related tests. * Fixed type errors. * Removed anys * Prettierize params.js * Prettierize response.js * Accepts string array as query param. * Returns 404 when there's no matching pattern for fields_for_wildcard. * Simplified schema. * Fixed types.
This commit is contained in:
parent
90bf444703
commit
817877dc8b
24
src/legacy/server/index_patterns/mixin.d.ts
vendored
24
src/legacy/server/index_patterns/mixin.d.ts
vendored
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { IndexPatternsService } from './service';
|
||||
|
||||
export type IndexPatternsServiceFactory = (args: {
|
||||
callCluster: (endpoint: string, clientParams: any, options: any) => Promise<any>;
|
||||
}) => IndexPatternsService;
|
|
@ -18,26 +18,12 @@
|
|||
*/
|
||||
|
||||
import { IndexPatternsService } from './service';
|
||||
import KbnServer from '../kbn_server';
|
||||
import { APICaller } from '../../../core/server';
|
||||
import { Legacy } from '../../../../kibana';
|
||||
import { registerRoutes } from './routes';
|
||||
|
||||
import {
|
||||
createFieldsForWildcardRoute,
|
||||
createFieldsForTimePatternRoute,
|
||||
} from './routes';
|
||||
|
||||
export function indexPatternsMixin(kbnServer, server) {
|
||||
const pre = {
|
||||
/**
|
||||
* Create an instance of the `indexPatterns` service
|
||||
* @type {Hapi.Pre}
|
||||
*/
|
||||
getIndexPatternsService: {
|
||||
assign: 'indexPatterns',
|
||||
method(request) {
|
||||
return request.getIndexPatternsService();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export function indexPatternsMixin(kbnServer: KbnServer, server: Legacy.Server) {
|
||||
/**
|
||||
* Create an instance of the IndexPatternsService
|
||||
*
|
||||
|
@ -55,12 +41,16 @@ export function indexPatternsMixin(kbnServer, server) {
|
|||
* @method request.getIndexPatternsService
|
||||
* @type {IndexPatternsService}
|
||||
*/
|
||||
server.addMemoizedFactoryToRequest('getIndexPatternsService', request => {
|
||||
server.addMemoizedFactoryToRequest('getIndexPatternsService', (request: Legacy.Request) => {
|
||||
const { callWithRequest } = request.server.plugins.elasticsearch.getCluster('data');
|
||||
const callCluster = (...args) => callWithRequest(request, ...args);
|
||||
const callCluster: APICaller = (endpoint, params, options) =>
|
||||
callWithRequest(request, endpoint, params, options);
|
||||
return server.indexPatternsServiceFactory({ callCluster });
|
||||
});
|
||||
|
||||
server.route(createFieldsForWildcardRoute(pre));
|
||||
server.route(createFieldsForTimePatternRoute(pre));
|
||||
registerRoutes(kbnServer.newPlatform.setup.core);
|
||||
}
|
||||
|
||||
export type IndexPatternsServiceFactory = (args: {
|
||||
callCluster: (endpoint: string, clientParams: any, options: any) => Promise<any>;
|
||||
}) => IndexPatternsService;
|
134
src/legacy/server/index_patterns/routes.ts
Normal file
134
src/legacy/server/index_patterns/routes.ts
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { first } from 'rxjs/operators';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import {
|
||||
InternalCoreSetup,
|
||||
KibanaRequest,
|
||||
RequestHandlerContext,
|
||||
APICaller,
|
||||
} from '../../../core/server';
|
||||
import { IndexPatternsService } from './service';
|
||||
|
||||
export function registerRoutes(core: InternalCoreSetup) {
|
||||
const getIndexPatternsService = async (request: KibanaRequest): Promise<IndexPatternsService> => {
|
||||
const client = await core.elasticsearch.dataClient$.pipe(first()).toPromise();
|
||||
const callCluster: APICaller = (endpoint, params, options) =>
|
||||
client.asScoped(request).callAsCurrentUser(endpoint, params, options);
|
||||
return new Promise(resolve => resolve(new IndexPatternsService(callCluster)));
|
||||
};
|
||||
|
||||
const parseMetaFields = (metaFields: string | string[]) => {
|
||||
let parsedFields: string[] = [];
|
||||
if (typeof metaFields === 'string') {
|
||||
parsedFields = JSON.parse(metaFields);
|
||||
} else {
|
||||
parsedFields = metaFields;
|
||||
}
|
||||
return parsedFields;
|
||||
};
|
||||
|
||||
const router = core.http.createRouter('/api/index_patterns');
|
||||
router.get(
|
||||
{
|
||||
path: '/_fields_for_wildcard',
|
||||
validate: {
|
||||
query: schema.object({
|
||||
pattern: schema.string(),
|
||||
meta_fields: schema.oneOf([schema.string(), schema.arrayOf(schema.string())], {
|
||||
defaultValue: [],
|
||||
}),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async (context: RequestHandlerContext, request: any, response: any) => {
|
||||
const indexPatterns = await getIndexPatternsService(request);
|
||||
const { pattern, meta_fields: metaFields } = request.query;
|
||||
|
||||
let parsedFields: string[] = [];
|
||||
try {
|
||||
parsedFields = parseMetaFields(metaFields);
|
||||
} catch (error) {
|
||||
return response.badRequest();
|
||||
}
|
||||
|
||||
try {
|
||||
const fields = await indexPatterns.getFieldsForWildcard({
|
||||
pattern,
|
||||
metaFields: parsedFields,
|
||||
});
|
||||
|
||||
return response.ok({
|
||||
body: { fields },
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
return response.notFound();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
router.get(
|
||||
{
|
||||
path: '/_fields_for_time_pattern',
|
||||
validate: {
|
||||
query: schema.object({
|
||||
pattern: schema.string(),
|
||||
interval: schema.maybe(schema.string()),
|
||||
look_back: schema.number({ min: 1 }),
|
||||
meta_fields: schema.oneOf([schema.string(), schema.arrayOf(schema.string())], {
|
||||
defaultValue: [],
|
||||
}),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async (context: RequestHandlerContext, request: any, response: any) => {
|
||||
const indexPatterns = await getIndexPatternsService(request);
|
||||
const { pattern, interval, look_back: lookBack, meta_fields: metaFields } = request.query;
|
||||
|
||||
let parsedFields: string[] = [];
|
||||
try {
|
||||
parsedFields = parseMetaFields(metaFields);
|
||||
} catch (error) {
|
||||
return response.badRequest();
|
||||
}
|
||||
|
||||
try {
|
||||
const fields = await indexPatterns.getFieldsForTimePattern({
|
||||
pattern,
|
||||
interval: interval ? interval : '',
|
||||
lookBack,
|
||||
metaFields: parsedFields,
|
||||
});
|
||||
|
||||
return response.ok({
|
||||
body: { fields },
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
return response.notFound();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import Joi from 'joi';
|
||||
|
||||
export const createFieldsForTimePatternRoute = pre => ({
|
||||
path: '/api/index_patterns/_fields_for_time_pattern',
|
||||
method: 'GET',
|
||||
config: {
|
||||
pre: [pre.getIndexPatternsService],
|
||||
validate: {
|
||||
query: Joi.object().keys({
|
||||
pattern: Joi.string().required(),
|
||||
look_back: Joi.number().min(1).required(),
|
||||
meta_fields: Joi.array().items(Joi.string()).default([]),
|
||||
}).default()
|
||||
},
|
||||
async handler(req) {
|
||||
const { indexPatterns } = req.pre;
|
||||
const {
|
||||
pattern,
|
||||
interval,
|
||||
look_back: lookBack,
|
||||
meta_fields: metaFields,
|
||||
} = req.query;
|
||||
|
||||
const fields = await indexPatterns.getFieldsForTimePattern({
|
||||
pattern,
|
||||
interval,
|
||||
lookBack,
|
||||
metaFields
|
||||
});
|
||||
|
||||
return { fields };
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import Joi from 'joi';
|
||||
|
||||
export const createFieldsForWildcardRoute = pre => ({
|
||||
path: '/api/index_patterns/_fields_for_wildcard',
|
||||
method: 'GET',
|
||||
config: {
|
||||
pre: [pre.getIndexPatternsService],
|
||||
validate: {
|
||||
query: Joi.object().keys({
|
||||
pattern: Joi.string().required(),
|
||||
meta_fields: Joi.array().items(Joi.string()).default([]),
|
||||
}).default()
|
||||
},
|
||||
async handler(req) {
|
||||
const { indexPatterns } = req.pre;
|
||||
const {
|
||||
pattern,
|
||||
meta_fields: metaFields,
|
||||
} = req.query;
|
||||
|
||||
const fields = await indexPatterns.getFieldsForWildcard({
|
||||
pattern,
|
||||
metaFields
|
||||
});
|
||||
|
||||
return { fields };
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { createFieldsForWildcardRoute } from './fields_for_wildcard_route';
|
||||
export { createFieldsForTimePatternRoute } from './fields_for_time_pattern_route';
|
|
@ -29,7 +29,7 @@ const ERR_NO_MATCHING_INDICES = 'no_matching_indices';
|
|||
* @param {Any} err
|
||||
* @return {Boolean}
|
||||
*/
|
||||
export function isEsIndexNotFoundError(err) {
|
||||
export function isEsIndexNotFoundError(err: any) {
|
||||
return get(err, ['body', 'error', 'type']) === ERR_ES_INDEX_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
@ -39,9 +39,9 @@ export function isEsIndexNotFoundError(err) {
|
|||
* @param {String} pattern the pattern which indexes were supposed to match
|
||||
* @return {Boom}
|
||||
*/
|
||||
export function createNoMatchingIndicesError(pattern) {
|
||||
export function createNoMatchingIndicesError(pattern: string[] | string) {
|
||||
const err = Boom.notFound(`No indices match pattern "${pattern}"`);
|
||||
err.output.payload.code = ERR_NO_MATCHING_INDICES;
|
||||
(err.output.payload as any).code = ERR_NO_MATCHING_INDICES;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -51,17 +51,17 @@ export function createNoMatchingIndicesError(pattern) {
|
|||
* @param {Any} err
|
||||
* @return {Boolean}
|
||||
*/
|
||||
export function isNoMatchingIndicesError(err) {
|
||||
export function isNoMatchingIndicesError(err: any) {
|
||||
return get(err, ['output', 'payload', 'code']) === ERR_NO_MATCHING_INDICES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap "index_not_found_exception" errors in custom Boom errors
|
||||
* automatically
|
||||
* @param {[type]} indices [description]
|
||||
* @return {[type]} [description]
|
||||
* @param {Array<String>|String} indices
|
||||
* @return {Boom}
|
||||
*/
|
||||
export function convertEsError(indices, error) {
|
||||
export function convertEsError(indices: string[] | string, error: any) {
|
||||
if (isEsIndexNotFoundError(error)) {
|
||||
return createNoMatchingIndicesError(indices);
|
||||
}
|
|
@ -22,6 +22,16 @@ import { APICaller } from 'src/core/server';
|
|||
import { convertEsError } from './errors';
|
||||
import { FieldCapsResponse } from './field_capabilities';
|
||||
|
||||
export interface IndicesAliasResponse {
|
||||
[index: string]: IndexAliasResponse;
|
||||
}
|
||||
|
||||
export interface IndexAliasResponse {
|
||||
aliases: {
|
||||
[aliasName: string]: Record<string, any>;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the index.getAlias API for a list of indices.
|
||||
*
|
||||
|
@ -36,13 +46,16 @@ import { FieldCapsResponse } from './field_capabilities';
|
|||
* @param {Array<String>|String} indices
|
||||
* @return {Promise<IndexAliasResponse>}
|
||||
*/
|
||||
export async function callIndexAliasApi(callCluster: APICaller, indices: string[] | string) {
|
||||
export async function callIndexAliasApi(
|
||||
callCluster: APICaller,
|
||||
indices: string[] | string
|
||||
): Promise<IndicesAliasResponse> {
|
||||
try {
|
||||
return await callCluster('indices.getAlias', {
|
||||
return (await callCluster('indices.getAlias', {
|
||||
index: indices,
|
||||
ignoreUnavailable: true,
|
||||
allowNoIndices: false,
|
||||
});
|
||||
})) as Promise<IndicesAliasResponse>;
|
||||
} catch (error) {
|
||||
throw convertEsError(indices, error);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ const TIME_PATTERN = '[logs-]dddd-YYYY.w';
|
|||
|
||||
describe('server/index_patterns/service/lib/resolve_time_pattern', () => {
|
||||
let sandbox;
|
||||
beforeEach(() => sandbox = sinon.createSandbox());
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()));
|
||||
afterEach(() => sandbox.restore());
|
||||
|
||||
describe('resolveTimePattern()', () => {
|
||||
|
@ -47,8 +47,7 @@ describe('server/index_patterns/service/lib/resolve_time_pattern', () => {
|
|||
const timePattern = {};
|
||||
const wildcard = {};
|
||||
|
||||
sandbox.stub(timePatternToWildcardNS, 'timePatternToWildcard')
|
||||
.returns(wildcard);
|
||||
sandbox.stub(timePatternToWildcardNS, 'timePatternToWildcard').returns(wildcard);
|
||||
|
||||
await resolveTimePattern(noop, timePattern);
|
||||
sinon.assert.calledOnce(timePatternToWildcard);
|
||||
|
@ -60,8 +59,7 @@ describe('server/index_patterns/service/lib/resolve_time_pattern', () => {
|
|||
const wildcard = {};
|
||||
|
||||
sandbox.stub(callIndexAliasApiNS, 'callIndexAliasApi').returns({});
|
||||
sandbox.stub(timePatternToWildcardNS, 'timePatternToWildcard')
|
||||
.returns(wildcard);
|
||||
sandbox.stub(timePatternToWildcardNS, 'timePatternToWildcard').returns(wildcard);
|
||||
|
||||
await resolveTimePattern(noop, timePattern);
|
||||
sinon.assert.calledOnce(callIndexAliasApi);
|
||||
|
@ -110,7 +108,7 @@ describe('server/index_patterns/service/lib/resolve_time_pattern', () => {
|
|||
expect(resp.matches).toEqual([
|
||||
'logs-Saturday-2017.1',
|
||||
'logs-Friday-2017.1',
|
||||
'logs-Sunday-2017.1'
|
||||
'logs-Sunday-2017.1',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,8 +20,10 @@
|
|||
import { chain } from 'lodash';
|
||||
import moment from 'moment';
|
||||
|
||||
import { APICaller } from 'src/core/server';
|
||||
|
||||
import { timePatternToWildcard } from './time_pattern_to_wildcard';
|
||||
import { callIndexAliasApi } from './es_api';
|
||||
import { callIndexAliasApi, IndicesAliasResponse } from './es_api';
|
||||
|
||||
/**
|
||||
* Convert a time pattern into a list of indexes it could
|
||||
|
@ -34,15 +36,16 @@ import { callIndexAliasApi } from './es_api';
|
|||
* and the indices that actually match the time
|
||||
* pattern (matches);
|
||||
*/
|
||||
export async function resolveTimePattern(callCluster, timePattern) {
|
||||
export async function resolveTimePattern(callCluster: APICaller, timePattern: string) {
|
||||
const aliases = await callIndexAliasApi(callCluster, timePatternToWildcard(timePattern));
|
||||
|
||||
const allIndexDetails = chain(aliases)
|
||||
.reduce((acc, index, indexName) => acc.concat(
|
||||
indexName,
|
||||
Object.keys(index.aliases || {})
|
||||
), [])
|
||||
.sort()
|
||||
const allIndexDetails = chain<IndicesAliasResponse>(aliases)
|
||||
.reduce(
|
||||
(acc: string[], index: any, indexName: string) =>
|
||||
acc.concat(indexName, Object.keys(index.aliases || {})),
|
||||
[]
|
||||
)
|
||||
.sortBy((indexName: string) => indexName)
|
||||
.uniq(true)
|
||||
.map(indexName => {
|
||||
const parsed = moment(indexName, timePattern, true);
|
||||
|
@ -51,7 +54,7 @@ export async function resolveTimePattern(callCluster, timePattern) {
|
|||
valid: false,
|
||||
indexName,
|
||||
order: indexName,
|
||||
isMatch: false
|
||||
isMatch: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -59,18 +62,15 @@ export async function resolveTimePattern(callCluster, timePattern) {
|
|||
valid: true,
|
||||
indexName,
|
||||
order: parsed,
|
||||
isMatch: indexName === parsed.format(timePattern)
|
||||
isMatch: indexName === parsed.format(timePattern),
|
||||
};
|
||||
})
|
||||
.sortByOrder(['valid', 'order'], ['desc', 'desc'])
|
||||
.value();
|
||||
|
||||
return {
|
||||
all: allIndexDetails
|
||||
.map(details => details.indexName),
|
||||
all: allIndexDetails.map(details => details.indexName),
|
||||
|
||||
matches: allIndexDetails
|
||||
.filter(details => details.isMatch)
|
||||
.map(details => details.indexName),
|
||||
matches: allIndexDetails.filter(details => details.isMatch).map(details => details.indexName),
|
||||
};
|
||||
}
|
4
src/legacy/server/kbn_server.d.ts
vendored
4
src/legacy/server/kbn_server.d.ts
vendored
|
@ -73,6 +73,10 @@ declare module 'hapi' {
|
|||
savedObjectsManagement(): SavedObjectsManagement;
|
||||
getInjectedUiAppVars: (pluginName: string) => { [key: string]: any };
|
||||
getUiNavLinks(): Array<{ _id: string }>;
|
||||
addMemoizedFactoryToRequest: (
|
||||
name: string,
|
||||
factoryFn: (request: Request) => Record<string, any>
|
||||
) => void;
|
||||
}
|
||||
|
||||
interface Request {
|
||||
|
|
|
@ -27,34 +27,49 @@ export default function ({ getService }) {
|
|||
before(() => esArchiver.load('index_patterns/daily_index'));
|
||||
after(() => esArchiver.unload('index_patterns/daily_index'));
|
||||
|
||||
it('requires `pattern` and `look_back` query params', () => (
|
||||
it('requires `pattern` query param', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_time_pattern')
|
||||
.query({ pattern: null })
|
||||
.query({ look_back: 1 })
|
||||
.expect(400)
|
||||
.then(resp => {
|
||||
expect(resp.body.validation).to.eql({
|
||||
keys: [
|
||||
'pattern',
|
||||
'look_back'
|
||||
],
|
||||
source: 'query'
|
||||
});
|
||||
})
|
||||
));
|
||||
expect(resp.body.message).to.contain(
|
||||
'[request query.pattern]: expected value of type [string] but got [undefined]'
|
||||
);
|
||||
}));
|
||||
|
||||
it('supports `meta_fields` query param', () => (
|
||||
it('requires `look_back` query param', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_time_pattern')
|
||||
.query({ pattern: 'pattern-*' })
|
||||
.expect(400)
|
||||
.then(resp => {
|
||||
expect(resp.body.message).to.contain(
|
||||
'[request query.look_back]: expected value of type [number] but got [undefined]'
|
||||
);
|
||||
}));
|
||||
|
||||
it('supports `meta_fields` query param in JSON format', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_time_pattern')
|
||||
.query({
|
||||
pattern: '[logs-]YYYY.MM.DD',
|
||||
look_back: 1,
|
||||
meta_fields: JSON.stringify(['a'])
|
||||
meta_fields: JSON.stringify(['a']),
|
||||
})
|
||||
.expect(200)
|
||||
));
|
||||
.expect(200));
|
||||
|
||||
it('requires `look_back` to be a number', () => (
|
||||
it('supports `meta_fields` query param in string array format', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_time_pattern')
|
||||
.query({
|
||||
pattern: '[logs-]YYYY.MM.DD',
|
||||
look_back: 1,
|
||||
meta_fields: ['a', 'b'],
|
||||
})
|
||||
.expect(200));
|
||||
|
||||
it('requires `look_back` to be a number', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_time_pattern')
|
||||
.query({
|
||||
|
@ -63,11 +78,12 @@ export default function ({ getService }) {
|
|||
})
|
||||
.expect(400)
|
||||
.then(resp => {
|
||||
expect(resp.body.message).to.contain('"look_back" must be a number');
|
||||
})
|
||||
));
|
||||
expect(resp.body.message).to.contain(
|
||||
'[request query.look_back]: expected value of type [number] but got [string]'
|
||||
);
|
||||
}));
|
||||
|
||||
it('requires `look_back` to be greater than one', () => (
|
||||
it('requires `look_back` to be greater than one', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_time_pattern')
|
||||
.query({
|
||||
|
@ -76,8 +92,9 @@ export default function ({ getService }) {
|
|||
})
|
||||
.expect(400)
|
||||
.then(resp => {
|
||||
expect(resp.body.message).to.contain('"look_back" must be larger than or equal to 1');
|
||||
})
|
||||
));
|
||||
expect(resp.body.message).to.contain(
|
||||
'[request query.look_back]: Value is [0] but it must be equal to or greater than [1].'
|
||||
);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -26,41 +26,46 @@ export default function ({ getService }) {
|
|||
before(() => esArchiver.load('index_patterns/basic_index'));
|
||||
after(() => esArchiver.unload('index_patterns/basic_index'));
|
||||
|
||||
it('requires a pattern query param', () => (
|
||||
it('requires a pattern query param', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_wildcard')
|
||||
.query({})
|
||||
.expect(400)
|
||||
));
|
||||
.expect(400));
|
||||
|
||||
it('accepts a JSON formatted meta_fields query param', () => (
|
||||
it('accepts a JSON formatted meta_fields query param', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_wildcard')
|
||||
.query({
|
||||
pattern: '*',
|
||||
meta_fields: JSON.stringify(['meta'])
|
||||
meta_fields: JSON.stringify(['meta']),
|
||||
})
|
||||
.expect(200)
|
||||
));
|
||||
.expect(200));
|
||||
|
||||
it('rejects a comma-separated list of meta_fields', () => (
|
||||
it('accepts meta_fields query param in string array', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_wildcard')
|
||||
.query({
|
||||
pattern: '*',
|
||||
meta_fields: 'foo,bar'
|
||||
meta_fields: ['_id', 'meta'],
|
||||
})
|
||||
.expect(400)
|
||||
));
|
||||
.expect(200));
|
||||
|
||||
it('rejects unexpected query params', () => (
|
||||
it('rejects a comma-separated list of meta_fields', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_wildcard')
|
||||
.query({
|
||||
pattern: '*',
|
||||
meta_fields: 'foo,bar',
|
||||
})
|
||||
.expect(400));
|
||||
|
||||
it('rejects unexpected query params', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_wildcard')
|
||||
.query({
|
||||
pattern: chance.word(),
|
||||
[chance.word()]: chance.word(),
|
||||
})
|
||||
.expect(400)
|
||||
));
|
||||
.expect(400));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -25,8 +25,7 @@ export default function ({ getService }) {
|
|||
const supertest = getService('supertest');
|
||||
|
||||
const ensureFieldsAreSorted = resp => {
|
||||
expect(resp.body.fields)
|
||||
.to.eql(sortBy(resp.body.fields, 'name'));
|
||||
expect(resp.body.fields).to.eql(sortBy(resp.body.fields, 'name'));
|
||||
};
|
||||
|
||||
describe('response', () => {
|
||||
|
@ -45,7 +44,7 @@ export default function ({ getService }) {
|
|||
searchable: true,
|
||||
aggregatable: true,
|
||||
name: 'bar',
|
||||
readFromDocValues: true
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
|
@ -53,7 +52,7 @@ export default function ({ getService }) {
|
|||
searchable: true,
|
||||
aggregatable: false,
|
||||
name: 'baz',
|
||||
readFromDocValues: false
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
|
@ -71,23 +70,18 @@ export default function ({ getService }) {
|
|||
searchable: true,
|
||||
aggregatable: true,
|
||||
name: 'foo',
|
||||
readFromDocValues: true
|
||||
}
|
||||
]
|
||||
readFromDocValues: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(ensureFieldsAreSorted)
|
||||
);
|
||||
.then(ensureFieldsAreSorted));
|
||||
|
||||
it('always returns a field for all passed meta fields', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_wildcard')
|
||||
.query({
|
||||
pattern: 'basic_index',
|
||||
meta_fields: JSON.stringify([
|
||||
'_id',
|
||||
'_source',
|
||||
'crazy_meta_field'
|
||||
])
|
||||
meta_fields: JSON.stringify(['_id', '_source', 'crazy_meta_field']),
|
||||
})
|
||||
.expect(200, {
|
||||
fields: [
|
||||
|
@ -113,7 +107,7 @@ export default function ({ getService }) {
|
|||
searchable: true,
|
||||
aggregatable: true,
|
||||
name: 'bar',
|
||||
readFromDocValues: true
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
aggregatable: false,
|
||||
|
@ -146,11 +140,18 @@ export default function ({ getService }) {
|
|||
searchable: true,
|
||||
aggregatable: true,
|
||||
name: 'foo',
|
||||
readFromDocValues: true
|
||||
}
|
||||
]
|
||||
readFromDocValues: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(ensureFieldsAreSorted)
|
||||
);
|
||||
.then(ensureFieldsAreSorted));
|
||||
|
||||
it('returns 404 when the pattern does not exist', () =>
|
||||
supertest
|
||||
.get('/api/index_patterns/_fields_for_wildcard')
|
||||
.query({
|
||||
pattern: '[non-existing-pattern]its-invalid-*',
|
||||
})
|
||||
.expect(404));
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue