mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
* Phase 1 of search services * First review feedback * Start on tests * Add functional tests for search explorer * Add unload and fix ts error * Add index.test.ts files for coverage completeness * Adding unit tests * use internal route terminology. No reason this should be a public route, at least not yet. * Move search service into data plugin * App mount search context needs to be optional * Add more unit tests for server stuff * wip types fix * fix types for new context container stuff * put back all jest test coverage paths * address review comments * delete the two test files that just tested the instantiation of the search service * expose search fn on StartContract... tested locally only * update mocks to account for new startcontract
This commit is contained in:
parent
02240b27ef
commit
0419844ee3
83 changed files with 3721 additions and 4 deletions
|
@ -39,6 +39,8 @@ export default {
|
|||
'<rootDir>/test/functional/services/remote',
|
||||
],
|
||||
collectCoverageFrom: [
|
||||
'src/plugins/**/*.{ts,tsx}',
|
||||
'!src/plugins/**/*.d.ts',
|
||||
'packages/kbn-ui-framework/src/components/**/*.js',
|
||||
'!packages/kbn-ui-framework/src/components/index.js',
|
||||
'!packages/kbn-ui-framework/src/components/**/*/index.js',
|
||||
|
|
20
src/plugins/data/common/search/es_search/index.ts
Normal file
20
src/plugins/data/common/search/es_search/index.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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 { IEsSearchRequest, IEsSearchResponse, ES_SEARCH_STRATEGY } from './types';
|
30
src/plugins/data/common/search/es_search/types.ts
Normal file
30
src/plugins/data/common/search/es_search/types.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 { SearchParams, SearchResponse } from 'elasticsearch';
|
||||
import { IKibanaSearchRequest, IKibanaSearchResponse } from '../types';
|
||||
|
||||
export const ES_SEARCH_STRATEGY = 'es';
|
||||
|
||||
export interface IEsSearchRequest extends IKibanaSearchRequest {
|
||||
params: SearchParams;
|
||||
}
|
||||
|
||||
export interface IEsSearchResponse<Hits = unknown> extends IKibanaSearchResponse {
|
||||
rawResponse: SearchResponse<Hits>;
|
||||
}
|
26
src/plugins/data/common/search/index.ts
Normal file
26
src/plugins/data/common/search/index.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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 { ES_SEARCH_STRATEGY } from './es_search';
|
||||
|
||||
export { IKibanaSearchResponse, IKibanaSearchRequest } from './types';
|
||||
|
||||
export const DEFAULT_SEARCH_STRATEGY = ES_SEARCH_STRATEGY;
|
||||
|
||||
export { IEsSearchRequest, IEsSearchResponse, ES_SEARCH_STRATEGY } from './es_search';
|
55
src/plugins/data/common/search/types.ts
Normal file
55
src/plugins/data/common/search/types.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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 interface IKibanaSearchResponse {
|
||||
/**
|
||||
* Some responses may contain a unique id to identify the request this response came from.
|
||||
*/
|
||||
id?: string;
|
||||
|
||||
/**
|
||||
* If relevant to the search strategy, return a percentage
|
||||
* that represents how progress is indicated.
|
||||
*/
|
||||
percentComplete?: number;
|
||||
|
||||
/**
|
||||
* If relevant to the search strategy, return a total number
|
||||
* that represents how progress is indicated.
|
||||
*/
|
||||
total?: number;
|
||||
|
||||
/**
|
||||
* If relevant to the search strategy, return a loaded number
|
||||
* that represents how progress is indicated.
|
||||
*/
|
||||
loaded?: number;
|
||||
}
|
||||
|
||||
export interface IKibanaSearchRequest {
|
||||
/**
|
||||
* An id can be used to uniquely identify this request.
|
||||
*/
|
||||
id?: string;
|
||||
|
||||
/**
|
||||
* Optionally tell search strategies to output debug information.
|
||||
*/
|
||||
debug?: boolean;
|
||||
}
|
|
@ -31,3 +31,6 @@ export * from '../common';
|
|||
export * from './autocomplete_provider';
|
||||
|
||||
export * from './types';
|
||||
|
||||
export { IRequestTypesMap, IResponseTypesMap } from './search';
|
||||
export * from './search';
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
import { Plugin } from '.';
|
||||
import { searchSetupMock } from './search/mocks';
|
||||
|
||||
export type Setup = jest.Mocked<ReturnType<Plugin['setup']>>;
|
||||
export type Start = jest.Mocked<ReturnType<Plugin['start']>>;
|
||||
|
@ -30,6 +31,7 @@ const autocompleteMock: any = {
|
|||
const createSetupContract = (): Setup => {
|
||||
const setupContract: Setup = {
|
||||
autocomplete: autocompleteMock as Setup['autocomplete'],
|
||||
search: searchSetupMock,
|
||||
};
|
||||
|
||||
return setupContract;
|
||||
|
@ -39,6 +41,7 @@ const createStartContract = (): Start => {
|
|||
const startContract: Start = {
|
||||
autocomplete: autocompleteMock as Start['autocomplete'],
|
||||
getSuggestions: jest.fn(),
|
||||
search: { search: jest.fn() },
|
||||
};
|
||||
return startContract;
|
||||
};
|
||||
|
|
|
@ -20,16 +20,21 @@
|
|||
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public';
|
||||
import { AutocompleteProviderRegister } from './autocomplete_provider';
|
||||
import { DataPublicPluginSetup, DataPublicPluginStart } from './types';
|
||||
import { SearchService } from './search/search_service';
|
||||
import { getSuggestionsProvider } from './suggestions_provider';
|
||||
|
||||
export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPublicPluginStart> {
|
||||
private readonly autocomplete = new AutocompleteProviderRegister();
|
||||
private readonly searchService: SearchService;
|
||||
|
||||
constructor(initializerContext: PluginInitializerContext) {}
|
||||
constructor(initializerContext: PluginInitializerContext) {
|
||||
this.searchService = new SearchService(initializerContext);
|
||||
}
|
||||
|
||||
public setup(core: CoreSetup): DataPublicPluginSetup {
|
||||
return {
|
||||
autocomplete: this.autocomplete,
|
||||
search: this.searchService.setup(core),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -37,6 +42,7 @@ export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPubli
|
|||
return {
|
||||
autocomplete: this.autocomplete,
|
||||
getSuggestions: getSuggestionsProvider(core.uiSettings, core.http),
|
||||
search: this.searchService.start(core),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
13
src/plugins/data/public/search/README.md
Normal file
13
src/plugins/data/public/search/README.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# search
|
||||
|
||||
The `search` plugin provides the ability to register search strategies that take in a request
|
||||
object, and return a response object, of a given shape.
|
||||
|
||||
Both client side search strategies can be registered, as well as server side search strategies.
|
||||
|
||||
The `search` plugin includes two one concrete client side implementations -
|
||||
`SYNC_SEARCH_STRATEGY` and `ES_SEARCH_STRATEGY` which uses `SYNC_SEARCH_STRATEGY`. There is also one
|
||||
default server side search strategy, `ES_SEARCH_STRATEGY`.
|
||||
|
||||
Includes the `esSearch` plugin in order to search for data from Elasticsearch using Elasticsearch
|
||||
DSL.
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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 { createAppMountSearchContext } from './create_app_mount_context_search';
|
||||
import { from } from 'rxjs';
|
||||
|
||||
describe('Create app mount search context', () => {
|
||||
it('Returns search fn when there are no strategies', () => {
|
||||
const context = createAppMountSearchContext({});
|
||||
expect(context.search).toBeDefined();
|
||||
});
|
||||
|
||||
it(`Search throws an error when the strategy doesn't exist`, () => {
|
||||
const context = createAppMountSearchContext({});
|
||||
expect(() => context.search({}, {}, 'noexist').toPromise()).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Strategy with name noexist does not exist"`
|
||||
);
|
||||
});
|
||||
|
||||
it(`Search fn is called on appropriate strategy name`, done => {
|
||||
const context = createAppMountSearchContext({
|
||||
mysearch: search =>
|
||||
Promise.resolve({
|
||||
search: () => from(Promise.resolve({ percentComplete: 98 })),
|
||||
}),
|
||||
anothersearch: search =>
|
||||
Promise.resolve({
|
||||
search: () => from(Promise.resolve({ percentComplete: 0 })),
|
||||
}),
|
||||
});
|
||||
|
||||
context.search({}, {}, 'mysearch').subscribe(response => {
|
||||
expect(response).toEqual({ percentComplete: 98 });
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it(`Search fn is called with the passed in request object`, done => {
|
||||
const context = createAppMountSearchContext({
|
||||
mysearch: search => {
|
||||
return Promise.resolve({
|
||||
search: request => {
|
||||
expect(request).toEqual({ greeting: 'hi' });
|
||||
return from(Promise.resolve({}));
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
context
|
||||
.search({ greeting: 'hi' } as any, {}, 'mysearch')
|
||||
.subscribe(response => {}, () => {}, done);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 { mergeMap } from 'rxjs/operators';
|
||||
import { from } from 'rxjs';
|
||||
import { ISearchAppMountContext } from './i_search_app_mount_context';
|
||||
import { ISearchGeneric } from './i_search';
|
||||
import {
|
||||
TSearchStrategiesMap,
|
||||
ISearchStrategy,
|
||||
TSearchStrategyProviderEnhanced,
|
||||
} from './i_search_strategy';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
import { DEFAULT_SEARCH_STRATEGY } from '../../common/search';
|
||||
|
||||
export const createAppMountSearchContext = (
|
||||
searchStrategies: TSearchStrategiesMap
|
||||
): ISearchAppMountContext => {
|
||||
const getSearchStrategy = <K extends TStrategyTypes = typeof DEFAULT_SEARCH_STRATEGY>(
|
||||
strategyName?: K
|
||||
): Promise<ISearchStrategy<K>> => {
|
||||
const strategyProvider = searchStrategies[
|
||||
strategyName ? strategyName : DEFAULT_SEARCH_STRATEGY
|
||||
] as TSearchStrategyProviderEnhanced<K> | undefined;
|
||||
if (!strategyProvider) {
|
||||
throw new Error(`Strategy with name ${strategyName} does not exist`);
|
||||
}
|
||||
return strategyProvider(search);
|
||||
};
|
||||
|
||||
const search: ISearchGeneric = (request, options, strategyName) => {
|
||||
const strategyPromise = getSearchStrategy(strategyName);
|
||||
return from(strategyPromise).pipe(
|
||||
mergeMap(strategy => {
|
||||
return strategy.search(request, options);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return { search };
|
||||
};
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 { coreMock } from '../../../../../core/public/mocks';
|
||||
import { EsSearchService } from './es_search_service';
|
||||
import { CoreSetup } from '../../../../../core/public';
|
||||
import { searchSetupMock } from '../mocks';
|
||||
|
||||
describe('ES search strategy service', () => {
|
||||
let service: EsSearchService;
|
||||
let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
const opaqueId = Symbol();
|
||||
|
||||
beforeEach(() => {
|
||||
service = new EsSearchService({ opaqueId });
|
||||
mockCoreSetup = coreMock.createSetup();
|
||||
});
|
||||
|
||||
describe('setup()', () => {
|
||||
it('registers the ES search strategy', async () => {
|
||||
service.setup(mockCoreSetup, {
|
||||
search: searchSetupMock,
|
||||
});
|
||||
expect(searchSetupMock.registerSearchStrategyProvider).toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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 { Plugin, CoreSetup, PluginInitializerContext } from '../../../../../core/public';
|
||||
import { ES_SEARCH_STRATEGY } from '../../../common/search/es_search';
|
||||
import { esSearchStrategyProvider } from './es_search_strategy';
|
||||
import { ISearchSetup } from '../i_search_setup';
|
||||
|
||||
export interface IEsSearchSetupDependencies {
|
||||
search: ISearchSetup;
|
||||
}
|
||||
|
||||
export class EsSearchService implements Plugin {
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
public setup(core: CoreSetup, deps: IEsSearchSetupDependencies) {
|
||||
deps.search.registerSearchStrategyProvider(
|
||||
this.initializerContext.opaqueId,
|
||||
ES_SEARCH_STRATEGY,
|
||||
esSearchStrategyProvider
|
||||
);
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public stop() {}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 { coreMock } from '../../../../../core/public/mocks';
|
||||
import { esSearchStrategyProvider } from './es_search_strategy';
|
||||
import { CoreSetup } from 'kibana/public';
|
||||
import { ES_SEARCH_STRATEGY } from '../../../common/search/es_search';
|
||||
|
||||
describe('ES search strategy', () => {
|
||||
let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
const mockSearch = jest.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
mockCoreSetup = coreMock.createSetup();
|
||||
mockSearch.mockClear();
|
||||
});
|
||||
|
||||
it('returns a strategy with `search` that calls the sync search `search`', () => {
|
||||
const request = { params: {} };
|
||||
const options = {};
|
||||
|
||||
const esSearch = esSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
},
|
||||
mockSearch
|
||||
);
|
||||
esSearch.search(request, options);
|
||||
|
||||
expect(mockSearch.mock.calls[0][0]).toEqual({
|
||||
...request,
|
||||
serverStrategy: ES_SEARCH_STRATEGY,
|
||||
});
|
||||
expect(mockSearch.mock.calls[0][1]).toBe(options);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 { Observable } from 'rxjs';
|
||||
import { ES_SEARCH_STRATEGY, IEsSearchResponse } from '../../../common/search';
|
||||
import { SYNC_SEARCH_STRATEGY } from '../sync_search_strategy';
|
||||
import { TSearchStrategyProvider, ISearchStrategy, ISearchGeneric, ISearchContext } from '..';
|
||||
|
||||
export const esSearchStrategyProvider: TSearchStrategyProvider<typeof ES_SEARCH_STRATEGY> = (
|
||||
context: ISearchContext,
|
||||
search: ISearchGeneric
|
||||
): ISearchStrategy<typeof ES_SEARCH_STRATEGY> => {
|
||||
return {
|
||||
search: (request, options) =>
|
||||
search(
|
||||
{ ...request, serverStrategy: ES_SEARCH_STRATEGY },
|
||||
options,
|
||||
SYNC_SEARCH_STRATEGY
|
||||
) as Observable<IEsSearchResponse>,
|
||||
};
|
||||
};
|
25
src/plugins/data/public/search/es_search/index.test.ts
Normal file
25
src/plugins/data/public/search/es_search/index.test.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 { esSearchService } from '.';
|
||||
|
||||
it('es search service is instantiated', () => {
|
||||
const esSearch = esSearchService({ opaqueId: Symbol() });
|
||||
expect(esSearch).toBeDefined();
|
||||
});
|
25
src/plugins/data/public/search/es_search/index.ts
Normal file
25
src/plugins/data/public/search/es_search/index.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 { PluginInitializer, PluginInitializerContext } from 'kibana/public';
|
||||
import { EsSearchService } from './es_search_service';
|
||||
|
||||
export const esSearchService: PluginInitializer<void, void> = (
|
||||
initializerContext: PluginInitializerContext
|
||||
) => new EsSearchService(initializerContext);
|
59
src/plugins/data/public/search/i_search.ts
Normal file
59
src/plugins/data/public/search/i_search.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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 { Observable } from 'rxjs';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
import {
|
||||
DEFAULT_SEARCH_STRATEGY,
|
||||
IKibanaSearchRequest,
|
||||
IKibanaSearchResponse,
|
||||
} from '../../common/search';
|
||||
import { SYNC_SEARCH_STRATEGY, ISyncSearchRequest } from './sync_search_strategy';
|
||||
import {
|
||||
ES_SEARCH_STRATEGY,
|
||||
IEsSearchRequest,
|
||||
IEsSearchResponse,
|
||||
} from '../../common/search/es_search';
|
||||
|
||||
export interface ISearchOptions {
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
export interface IRequestTypesMap {
|
||||
[SYNC_SEARCH_STRATEGY]: ISyncSearchRequest;
|
||||
[ES_SEARCH_STRATEGY]: IEsSearchRequest;
|
||||
[key: string]: IKibanaSearchRequest;
|
||||
}
|
||||
|
||||
export interface IResponseTypesMap {
|
||||
[SYNC_SEARCH_STRATEGY]: IKibanaSearchResponse;
|
||||
[ES_SEARCH_STRATEGY]: IEsSearchResponse;
|
||||
[key: string]: IKibanaSearchResponse;
|
||||
}
|
||||
|
||||
export type ISearchGeneric = <T extends TStrategyTypes = typeof DEFAULT_SEARCH_STRATEGY>(
|
||||
request: IRequestTypesMap[T],
|
||||
options: ISearchOptions,
|
||||
strategy?: T
|
||||
) => Observable<IResponseTypesMap[T]>;
|
||||
|
||||
export type ISearch<T extends TStrategyTypes = typeof DEFAULT_SEARCH_STRATEGY> = (
|
||||
request: IRequestTypesMap[T],
|
||||
options: ISearchOptions
|
||||
) => Observable<IResponseTypesMap[T]>;
|
24
src/plugins/data/public/search/i_search_app_mount_context.ts
Normal file
24
src/plugins/data/public/search/i_search_app_mount_context.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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 { ISearchGeneric } from './i_search';
|
||||
|
||||
export interface ISearchAppMountContext {
|
||||
search: ISearchGeneric;
|
||||
}
|
23
src/plugins/data/public/search/i_search_context.ts
Normal file
23
src/plugins/data/public/search/i_search_context.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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 { CoreSetup } from '../../../../core/public';
|
||||
|
||||
export interface ISearchContext {
|
||||
core: CoreSetup;
|
||||
}
|
40
src/plugins/data/public/search/i_search_setup.ts
Normal file
40
src/plugins/data/public/search/i_search_setup.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 { IContextProvider } from 'kibana/public';
|
||||
import { ISearchContext } from './i_search_context';
|
||||
import { TRegisterSearchStrategyProvider, TSearchStrategyProvider } from './i_search_strategy';
|
||||
|
||||
/**
|
||||
* The setup contract exposed by the Search plugin exposes the search strategy extension
|
||||
* point.
|
||||
*/
|
||||
export interface ISearchSetup {
|
||||
registerSearchStrategyContext: <TContextName extends keyof ISearchContext>(
|
||||
pluginId: symbol,
|
||||
contextName: TContextName,
|
||||
provider: IContextProvider<TSearchStrategyProvider<any>, TContextName>
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* Extension point exposed for other plugins to register their own search
|
||||
* strategies.
|
||||
*/
|
||||
registerSearchStrategyProvider: TRegisterSearchStrategyProvider;
|
||||
}
|
63
src/plugins/data/public/search/i_search_strategy.ts
Normal file
63
src/plugins/data/public/search/i_search_strategy.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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 { ISearch, ISearchGeneric } from './i_search';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
import { ISearchContext } from './i_search_context';
|
||||
|
||||
/**
|
||||
* Search strategy interface contains a search method that takes in
|
||||
* a request and returns a promise that resolves to a response.
|
||||
*/
|
||||
export interface ISearchStrategy<T extends TStrategyTypes> {
|
||||
search: ISearch<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search strategy provider creates an instance of a search strategy with the request
|
||||
* handler context bound to it. This way every search strategy can use
|
||||
* whatever information they require from the request context.
|
||||
*/
|
||||
export type TSearchStrategyProviderEnhanced<T extends TStrategyTypes> = (
|
||||
search: ISearchGeneric
|
||||
) => Promise<ISearchStrategy<T>>;
|
||||
|
||||
/**
|
||||
* Search strategy provider creates an instance of a search strategy with the request
|
||||
* handler context bound to it. This way every search strategy can use
|
||||
* whatever information they require from the request context.
|
||||
*/
|
||||
export type TSearchStrategyProvider<T extends TStrategyTypes> = (
|
||||
context: ISearchContext,
|
||||
search: ISearchGeneric
|
||||
) => ISearchStrategy<T>;
|
||||
|
||||
/**
|
||||
* Extension point exposed for other plugins to register their own search
|
||||
* strategies.
|
||||
*/
|
||||
export type TRegisterSearchStrategyProvider = <T extends TStrategyTypes>(
|
||||
opaqueId: symbol,
|
||||
name: T,
|
||||
searchStrategyProvider: TSearchStrategyProvider<T>
|
||||
) => void;
|
||||
|
||||
export type TSearchStrategiesMap = {
|
||||
[K in TStrategyTypes]?: TSearchStrategyProviderEnhanced<K>;
|
||||
};
|
42
src/plugins/data/public/search/index.ts
Normal file
42
src/plugins/data/public/search/index.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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 { ISearchAppMountContext } from './i_search_app_mount_context';
|
||||
|
||||
export { ISearchSetup } from './i_search_setup';
|
||||
|
||||
export { ISearchContext } from './i_search_context';
|
||||
|
||||
export {
|
||||
ISearch,
|
||||
ISearchOptions,
|
||||
IRequestTypesMap,
|
||||
IResponseTypesMap,
|
||||
ISearchGeneric,
|
||||
} from './i_search';
|
||||
|
||||
export { TSearchStrategyProvider, ISearchStrategy } from './i_search_strategy';
|
||||
|
||||
export { IEsSearchResponse, IEsSearchRequest, ES_SEARCH_STRATEGY } from '../../common/search';
|
||||
|
||||
export { SYNC_SEARCH_STRATEGY } from './sync_search_strategy';
|
||||
|
||||
export { IKibanaSearchResponse, IKibanaSearchRequest } from '../../common/search';
|
||||
|
||||
export { ISearchStart } from './search_service';
|
23
src/plugins/data/public/search/mocks.ts
Normal file
23
src/plugins/data/public/search/mocks.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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 const searchSetupMock = {
|
||||
registerSearchStrategyContext: jest.fn(),
|
||||
registerSearchStrategyProvider: jest.fn(),
|
||||
};
|
41
src/plugins/data/public/search/search_service.test.ts
Normal file
41
src/plugins/data/public/search/search_service.test.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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 { coreMock } from '../../../../core/public/mocks';
|
||||
|
||||
import { SearchService } from './search_service';
|
||||
import { CoreSetup } from '../../../../core/public';
|
||||
|
||||
describe('Search service', () => {
|
||||
let searchService: SearchService;
|
||||
let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
const opaqueId = Symbol();
|
||||
beforeEach(() => {
|
||||
searchService = new SearchService({ opaqueId });
|
||||
mockCoreSetup = coreMock.createSetup();
|
||||
});
|
||||
|
||||
describe('setup()', () => {
|
||||
it('exposes proper contract', async () => {
|
||||
const setup = searchService.setup(mockCoreSetup);
|
||||
expect(setup).toHaveProperty('registerSearchStrategyContext');
|
||||
expect(setup).toHaveProperty('registerSearchStrategyProvider');
|
||||
});
|
||||
});
|
||||
});
|
126
src/plugins/data/public/search/search_service.ts
Normal file
126
src/plugins/data/public/search/search_service.ts
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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 {
|
||||
Plugin,
|
||||
CoreSetup,
|
||||
PluginInitializerContext,
|
||||
CoreStart,
|
||||
IContextContainer,
|
||||
PluginOpaqueId,
|
||||
} from '../../../../core/public';
|
||||
|
||||
import { ISearchAppMountContext } from './i_search_app_mount_context';
|
||||
import { ISearchSetup } from './i_search_setup';
|
||||
import { createAppMountSearchContext } from './create_app_mount_context_search';
|
||||
import { SYNC_SEARCH_STRATEGY, syncSearchStrategyProvider } from './sync_search_strategy';
|
||||
import {
|
||||
TSearchStrategyProvider,
|
||||
TRegisterSearchStrategyProvider,
|
||||
TSearchStrategiesMap,
|
||||
} from './i_search_strategy';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
import { esSearchService } from './es_search';
|
||||
import { ISearchGeneric } from './i_search';
|
||||
|
||||
/**
|
||||
* Extends the AppMountContext so other plugins have access
|
||||
* to search functionality in their applications.
|
||||
*/
|
||||
declare module 'kibana/public' {
|
||||
interface AppMountContext {
|
||||
search?: ISearchAppMountContext;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ISearchStart {
|
||||
search: ISearchGeneric;
|
||||
}
|
||||
|
||||
/**
|
||||
* The search plugin exposes two registration methods for other plugins:
|
||||
* - registerSearchStrategyProvider for plugins to add their own custom
|
||||
* search strategies
|
||||
* - registerSearchStrategyContext for plugins to expose information
|
||||
* and/or functionality for other search strategies to use
|
||||
*
|
||||
* It also comes with two search strategy implementations - SYNC_SEARCH_STRATEGY and ES_SEARCH_STRATEGY.
|
||||
*/
|
||||
export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
||||
/**
|
||||
* A mapping of search strategies keyed by a unique identifier. Plugins can use this unique identifier
|
||||
* to override certain strategy implementations.
|
||||
*/
|
||||
private searchStrategies: TSearchStrategiesMap = {};
|
||||
|
||||
/**
|
||||
* Exposes context to the search strategies.
|
||||
*/
|
||||
private contextContainer?: IContextContainer<TSearchStrategyProvider<any>>;
|
||||
|
||||
private search?: ISearchGeneric;
|
||||
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
|
||||
public setup(core: CoreSetup): ISearchSetup {
|
||||
const search = (this.search = createAppMountSearchContext(this.searchStrategies).search);
|
||||
core.application.registerMountContext<'search'>('search', () => {
|
||||
return { search };
|
||||
});
|
||||
|
||||
this.contextContainer = core.context.createContextContainer();
|
||||
|
||||
const registerSearchStrategyProvider: TRegisterSearchStrategyProvider = <
|
||||
T extends TStrategyTypes
|
||||
>(
|
||||
plugin: PluginOpaqueId,
|
||||
name: T,
|
||||
strategyProvider: TSearchStrategyProvider<T>
|
||||
) => {
|
||||
this.searchStrategies[name] = this.contextContainer!.createHandler(plugin, strategyProvider);
|
||||
};
|
||||
|
||||
const api = {
|
||||
registerSearchStrategyContext: this.contextContainer!.registerContext,
|
||||
registerSearchStrategyProvider,
|
||||
};
|
||||
|
||||
api.registerSearchStrategyContext(this.initializerContext.opaqueId, 'core', () => core);
|
||||
api.registerSearchStrategyProvider(
|
||||
this.initializerContext.opaqueId,
|
||||
SYNC_SEARCH_STRATEGY,
|
||||
syncSearchStrategyProvider
|
||||
);
|
||||
|
||||
// ES search capabilities are written in a way that it could easily be a separate plugin,
|
||||
// however these two plugins are tightly coupled due to the default search strategy using
|
||||
// es search types.
|
||||
esSearchService(this.initializerContext).setup(core, { search: api });
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
public start(core: CoreStart) {
|
||||
if (!this.search) {
|
||||
throw new Error('Search should always be defined');
|
||||
}
|
||||
return { search: this.search };
|
||||
}
|
||||
|
||||
public stop() {}
|
||||
}
|
40
src/plugins/data/public/search/strategy_types.ts
Normal file
40
src/plugins/data/public/search/strategy_types.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 { ES_SEARCH_STRATEGY } from '../../common/search/es_search';
|
||||
import { SYNC_SEARCH_STRATEGY } from './sync_search_strategy';
|
||||
|
||||
/**
|
||||
* Contains all known strategy type identifiers that will be used to map to
|
||||
* request and response shapes. Plugins that wish to add their own custom search
|
||||
* strategies should extend this type via:
|
||||
*
|
||||
* const MY_STRATEGY = 'MY_STRATEGY';
|
||||
*
|
||||
* declare module 'src/plugins/data/public' {
|
||||
* export interface IRequestTypesMap {
|
||||
* [MY_STRATEGY]: IMySearchRequest;
|
||||
* }
|
||||
*
|
||||
* export interface IResponseTypesMap {
|
||||
* [MY_STRATEGY]: IMySearchResponse
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export type TStrategyTypes = typeof SYNC_SEARCH_STRATEGY | typeof ES_SEARCH_STRATEGY | string;
|
58
src/plugins/data/public/search/sync_search_strategy.test.ts
Normal file
58
src/plugins/data/public/search/sync_search_strategy.test.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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 { coreMock } from '../../../../core/public/mocks';
|
||||
import { SYNC_SEARCH_STRATEGY, syncSearchStrategyProvider } from './sync_search_strategy';
|
||||
import { CoreSetup } from '../../../../core/public';
|
||||
|
||||
describe('Sync search strategy', () => {
|
||||
let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
const mockSearch = jest.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
mockCoreSetup = coreMock.createSetup();
|
||||
});
|
||||
|
||||
it('returns a strategy with `search` that calls the backend API', () => {
|
||||
mockCoreSetup.http.fetch.mockImplementationOnce(() => Promise.resolve());
|
||||
|
||||
const syncSearch = syncSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
},
|
||||
mockSearch
|
||||
);
|
||||
syncSearch.search(
|
||||
{
|
||||
serverStrategy: SYNC_SEARCH_STRATEGY,
|
||||
},
|
||||
{}
|
||||
);
|
||||
expect(mockCoreSetup.http.fetch.mock.calls[0][0]).toBe(
|
||||
`/internal/search/${SYNC_SEARCH_STRATEGY}`
|
||||
);
|
||||
expect(mockCoreSetup.http.fetch.mock.calls[0][1]).toEqual({
|
||||
body: JSON.stringify({
|
||||
serverStrategy: 'SYNC_SEARCH_STRATEGY',
|
||||
}),
|
||||
method: 'POST',
|
||||
signal: undefined,
|
||||
});
|
||||
});
|
||||
});
|
56
src/plugins/data/public/search/sync_search_strategy.ts
Normal file
56
src/plugins/data/public/search/sync_search_strategy.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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 { from } from 'rxjs';
|
||||
import { IKibanaSearchRequest, IKibanaSearchResponse } from '../../common/search';
|
||||
import { ISearchContext } from './i_search_context';
|
||||
import { ISearch, ISearchOptions } from './i_search';
|
||||
import { TSearchStrategyProvider, ISearchStrategy } from './i_search_strategy';
|
||||
|
||||
export const SYNC_SEARCH_STRATEGY = 'SYNC_SEARCH_STRATEGY';
|
||||
|
||||
export interface ISyncSearchRequest extends IKibanaSearchRequest {
|
||||
serverStrategy: string;
|
||||
}
|
||||
|
||||
export const syncSearchStrategyProvider: TSearchStrategyProvider<typeof SYNC_SEARCH_STRATEGY> = (
|
||||
context: ISearchContext
|
||||
) => {
|
||||
const search: ISearch<typeof SYNC_SEARCH_STRATEGY> = (
|
||||
request: ISyncSearchRequest,
|
||||
options: ISearchOptions
|
||||
) => {
|
||||
const response: Promise<IKibanaSearchResponse> = context.core.http.fetch(
|
||||
`/internal/search/${request.serverStrategy}`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(request),
|
||||
signal: options.signal,
|
||||
}
|
||||
);
|
||||
|
||||
return from(response);
|
||||
};
|
||||
|
||||
const strategy: ISearchStrategy<typeof SYNC_SEARCH_STRATEGY> = {
|
||||
search,
|
||||
};
|
||||
|
||||
return strategy;
|
||||
};
|
|
@ -20,14 +20,17 @@
|
|||
export * from './autocomplete_provider/types';
|
||||
|
||||
import { AutocompletePublicPluginSetup, AutocompletePublicPluginStart } from '.';
|
||||
import { ISearchSetup, ISearchStart } from './search';
|
||||
import { IGetSuggestions } from './suggestions_provider/types';
|
||||
export interface DataPublicPluginSetup {
|
||||
autocomplete: AutocompletePublicPluginSetup;
|
||||
search: ISearchSetup;
|
||||
}
|
||||
|
||||
export interface DataPublicPluginStart {
|
||||
autocomplete: AutocompletePublicPluginStart;
|
||||
getSuggestions: IGetSuggestions;
|
||||
search: ISearchStart;
|
||||
}
|
||||
|
||||
export { IGetSuggestions } from './suggestions_provider/types';
|
||||
|
|
|
@ -25,3 +25,7 @@ export function plugin(initializerContext: PluginInitializerContext) {
|
|||
}
|
||||
|
||||
export { DataServerPlugin as Plugin };
|
||||
|
||||
export * from './search';
|
||||
|
||||
export { IRequestTypesMap, IResponseTypesMap } from './search';
|
||||
|
|
|
@ -18,10 +18,23 @@
|
|||
*/
|
||||
|
||||
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/server';
|
||||
import { ISearchSetup } from './search';
|
||||
import { SearchService } from './search/search_service';
|
||||
|
||||
export class DataServerPlugin implements Plugin {
|
||||
constructor(initializerContext: PluginInitializerContext) {}
|
||||
public setup(core: CoreSetup) {}
|
||||
export interface DataPluginSetup {
|
||||
search: ISearchSetup;
|
||||
}
|
||||
|
||||
export class DataServerPlugin implements Plugin<DataPluginSetup> {
|
||||
private readonly searchService: SearchService;
|
||||
constructor(initializerContext: PluginInitializerContext) {
|
||||
this.searchService = new SearchService(initializerContext);
|
||||
}
|
||||
public setup(core: CoreSetup) {
|
||||
return {
|
||||
search: this.searchService.setup(core),
|
||||
};
|
||||
}
|
||||
public start(core: CoreStart) {}
|
||||
public stop() {}
|
||||
}
|
||||
|
|
13
src/plugins/data/server/search/README.md
Normal file
13
src/plugins/data/server/search/README.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# search
|
||||
|
||||
The `search` plugin provides the ability to register search strategies that take in a request
|
||||
object, and return a response object, of a given shape.
|
||||
|
||||
Both client side search strategies can be registered, as well as server side search strategies.
|
||||
|
||||
The `search` plugin includes two one concrete client side implementations -
|
||||
`SYNC_SEARCH_STRATEGY` and `ES_SEARCH_STRATEGY` which uses `SYNC_SEARCH_STRATEGY`. There is also one
|
||||
default server side search strategy, `ES_SEARCH_STRATEGY`.
|
||||
|
||||
Includes the `esSearch` plugin in order to search for data from Elasticsearch using Elasticsearch
|
||||
DSL.
|
62
src/plugins/data/server/search/create_api.test.ts
Normal file
62
src/plugins/data/server/search/create_api.test.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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 { createApi } from './create_api';
|
||||
|
||||
import { TSearchStrategiesMap } from './i_search_strategy';
|
||||
import { IRouteHandlerSearchContext } from './i_route_handler_search_context';
|
||||
import { DEFAULT_SEARCH_STRATEGY } from '../../common/search';
|
||||
|
||||
// let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
|
||||
const mockDefaultSearch = jest.fn(() => Promise.resolve({ percentComplete: 0 }));
|
||||
const mockDefaultSearchStrategyProvider = jest.fn(() =>
|
||||
Promise.resolve({
|
||||
search: mockDefaultSearch,
|
||||
})
|
||||
);
|
||||
const mockStrategies: TSearchStrategiesMap = {
|
||||
[DEFAULT_SEARCH_STRATEGY]: mockDefaultSearchStrategyProvider,
|
||||
};
|
||||
|
||||
describe('createApi', () => {
|
||||
let api: IRouteHandlerSearchContext;
|
||||
|
||||
beforeEach(() => {
|
||||
api = createApi({
|
||||
caller: jest.fn(),
|
||||
searchStrategies: mockStrategies,
|
||||
});
|
||||
mockDefaultSearchStrategyProvider.mockClear();
|
||||
});
|
||||
|
||||
it('should default to DEFAULT_SEARCH_STRATEGY if none is provided', async () => {
|
||||
await api.search({
|
||||
params: {},
|
||||
});
|
||||
expect(mockDefaultSearchStrategyProvider).toBeCalled();
|
||||
expect(mockDefaultSearch).toBeCalled();
|
||||
});
|
||||
|
||||
it('should throw if no provider is found for the given name', () => {
|
||||
expect(api.search({}, 'noneByThisName')).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"No strategy found for noneByThisName"`
|
||||
);
|
||||
});
|
||||
});
|
45
src/plugins/data/server/search/create_api.ts
Normal file
45
src/plugins/data/server/search/create_api.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 { APICaller } from 'kibana/server';
|
||||
import { IRouteHandlerSearchContext } from './i_route_handler_search_context';
|
||||
import { DEFAULT_SEARCH_STRATEGY } from '../../common/search';
|
||||
import { TSearchStrategiesMap } from './i_search_strategy';
|
||||
|
||||
export function createApi({
|
||||
caller,
|
||||
searchStrategies,
|
||||
}: {
|
||||
searchStrategies: TSearchStrategiesMap;
|
||||
caller: APICaller;
|
||||
}) {
|
||||
const api: IRouteHandlerSearchContext = {
|
||||
search: async (request, strategyName) => {
|
||||
const name = strategyName ? strategyName : DEFAULT_SEARCH_STRATEGY;
|
||||
const strategyProvider = searchStrategies[name];
|
||||
if (!strategyProvider) {
|
||||
throw new Error(`No strategy found for ${strategyName}`);
|
||||
}
|
||||
// Give providers access to other search strategies by injecting this function
|
||||
const strategy = await strategyProvider(caller, api.search);
|
||||
return strategy.search(request);
|
||||
},
|
||||
};
|
||||
return api;
|
||||
}
|
34
src/plugins/data/server/search/es_search/elasticsearch.ts
Normal file
34
src/plugins/data/server/search/es_search/elasticsearch.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 interface StringMap<T = unknown> {
|
||||
[key: string]: T;
|
||||
}
|
||||
|
||||
export type IndexAsString<Map> = {
|
||||
[k: string]: Map[keyof Map];
|
||||
} & Map;
|
||||
|
||||
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
||||
|
||||
export interface BoolQuery {
|
||||
must_not: Array<Record<string, any>>;
|
||||
should: Array<Record<string, any>>;
|
||||
filter: Array<Record<string, any>>;
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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 { coreMock } from '../../../../../core/server/mocks';
|
||||
import { EsSearchService } from './es_search_service';
|
||||
import { PluginInitializerContext } from '../../../../../core/server';
|
||||
import { searchSetupMock } from '../mocks';
|
||||
|
||||
describe('ES search strategy service', () => {
|
||||
let service: EsSearchService;
|
||||
|
||||
const mockCoreSetup = coreMock.createSetup();
|
||||
const opaqueId = Symbol();
|
||||
const context: PluginInitializerContext = {
|
||||
opaqueId,
|
||||
config: {
|
||||
createIfExists: jest.fn(),
|
||||
create: jest.fn(),
|
||||
},
|
||||
env: {
|
||||
mode: {
|
||||
dev: false,
|
||||
name: 'development',
|
||||
prod: false,
|
||||
},
|
||||
},
|
||||
logger: {
|
||||
get: jest.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
service = new EsSearchService(context);
|
||||
});
|
||||
|
||||
describe('setup()', () => {
|
||||
it('registers the ES search strategy', async () => {
|
||||
service.setup(mockCoreSetup, {
|
||||
search: searchSetupMock,
|
||||
});
|
||||
expect(searchSetupMock.registerSearchStrategyProvider).toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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 { ISearchSetup } from '../i_search_setup';
|
||||
import { PluginInitializerContext, CoreSetup, Plugin } from '../../../../../core/server';
|
||||
import { esSearchStrategyProvider } from './es_search_strategy';
|
||||
import { ES_SEARCH_STRATEGY } from '../../../common/search';
|
||||
|
||||
interface IEsSearchDependencies {
|
||||
search: ISearchSetup;
|
||||
}
|
||||
|
||||
export class EsSearchService implements Plugin<void, void, IEsSearchDependencies> {
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
|
||||
public setup(core: CoreSetup, deps: IEsSearchDependencies) {
|
||||
deps.search.registerSearchStrategyProvider(
|
||||
this.initializerContext.opaqueId,
|
||||
ES_SEARCH_STRATEGY,
|
||||
esSearchStrategyProvider
|
||||
);
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public stop() {}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* 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 { coreMock } from '../../../../../core/server/mocks';
|
||||
import { esSearchStrategyProvider } from './es_search_strategy';
|
||||
|
||||
describe('ES search strategy', () => {
|
||||
const mockCoreSetup = coreMock.createSetup();
|
||||
const mockApiCaller = jest.fn().mockResolvedValue({
|
||||
_shards: {
|
||||
total: 10,
|
||||
failed: 1,
|
||||
skipped: 2,
|
||||
successful: 7,
|
||||
},
|
||||
});
|
||||
const mockSearch = jest.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
mockApiCaller.mockClear();
|
||||
mockSearch.mockClear();
|
||||
});
|
||||
|
||||
it('returns a strategy with `search`', () => {
|
||||
const esSearch = esSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
|
||||
expect(typeof esSearch.search).toBe('function');
|
||||
});
|
||||
|
||||
it('logs the response if `debug` is set to `true`', () => {
|
||||
const spy = jest.spyOn(console, 'log');
|
||||
const esSearch = esSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
|
||||
expect(spy).not.toBeCalled();
|
||||
|
||||
esSearch.search({ params: {}, debug: true });
|
||||
|
||||
expect(spy).toBeCalled();
|
||||
});
|
||||
|
||||
it('calls the API caller with the params', () => {
|
||||
const params = { index: 'logstash-*' };
|
||||
const esSearch = esSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
|
||||
esSearch.search({ params });
|
||||
|
||||
expect(mockApiCaller).toBeCalled();
|
||||
expect(mockApiCaller.mock.calls[0][0]).toBe('search');
|
||||
expect(mockApiCaller.mock.calls[0][1]).toEqual(params);
|
||||
});
|
||||
|
||||
it('returns total, loaded, and raw response', async () => {
|
||||
const params = { index: 'logstash-*' };
|
||||
const esSearch = esSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
|
||||
const response = await esSearch.search({ params });
|
||||
|
||||
expect(response).toHaveProperty('total');
|
||||
expect(response).toHaveProperty('loaded');
|
||||
expect(response).toHaveProperty('rawResponse');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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 { APICaller } from 'kibana/server';
|
||||
import { SearchResponse } from 'elasticsearch';
|
||||
import { IEsSearchRequest, ES_SEARCH_STRATEGY } from '../../../common/search';
|
||||
import { ISearchStrategy, TSearchStrategyProvider } from '../i_search_strategy';
|
||||
import { ISearchContext } from '..';
|
||||
|
||||
export const esSearchStrategyProvider: TSearchStrategyProvider<typeof ES_SEARCH_STRATEGY> = (
|
||||
context: ISearchContext,
|
||||
caller: APICaller
|
||||
): ISearchStrategy<typeof ES_SEARCH_STRATEGY> => {
|
||||
return {
|
||||
search: async (request: IEsSearchRequest) => {
|
||||
if (request.debug) {
|
||||
// eslint-disable-next-line
|
||||
console.log(JSON.stringify(request, null, 2));
|
||||
}
|
||||
const esSearchResponse = (await caller('search', {
|
||||
...request.params,
|
||||
// TODO: could do something like this here?
|
||||
// ...getCurrentSearchParams(context),
|
||||
})) as SearchResponse<any>;
|
||||
|
||||
// The above query will either complete or timeout and throw an error.
|
||||
// There is no progress indication on this api.
|
||||
return {
|
||||
total: esSearchResponse._shards.total,
|
||||
loaded:
|
||||
esSearchResponse._shards.failed +
|
||||
esSearchResponse._shards.skipped +
|
||||
esSearchResponse._shards.successful,
|
||||
rawResponse: esSearchResponse,
|
||||
};
|
||||
},
|
||||
};
|
||||
};
|
27
src/plugins/data/server/search/es_search/index.ts
Normal file
27
src/plugins/data/server/search/es_search/index.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 { PluginInitializerContext } from '../../../../../core/server';
|
||||
import { EsSearchService } from './es_search_service';
|
||||
|
||||
export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common/search';
|
||||
|
||||
export function esSearchService(initializerContext: PluginInitializerContext) {
|
||||
return new EsSearchService(initializerContext);
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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 { ISearchGeneric } from './i_search';
|
||||
|
||||
export interface IRouteHandlerSearchContext {
|
||||
search: ISearchGeneric;
|
||||
}
|
42
src/plugins/data/server/search/i_search.ts
Normal file
42
src/plugins/data/server/search/i_search.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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 { IKibanaSearchResponse, IKibanaSearchRequest } from '../../common/search';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
import { ES_SEARCH_STRATEGY, IEsSearchResponse } from '../../common/search/es_search';
|
||||
import { IEsSearchRequest } from './es_search';
|
||||
|
||||
export interface IRequestTypesMap {
|
||||
[ES_SEARCH_STRATEGY]: IEsSearchRequest;
|
||||
[key: string]: IKibanaSearchRequest;
|
||||
}
|
||||
|
||||
export interface IResponseTypesMap {
|
||||
[ES_SEARCH_STRATEGY]: IEsSearchResponse;
|
||||
[key: string]: IKibanaSearchResponse;
|
||||
}
|
||||
|
||||
export type ISearchGeneric = <T extends TStrategyTypes = typeof ES_SEARCH_STRATEGY>(
|
||||
request: IRequestTypesMap[T],
|
||||
strategy?: T
|
||||
) => Promise<IResponseTypesMap[T]>;
|
||||
|
||||
export type ISearch<T extends TStrategyTypes> = (
|
||||
request: IRequestTypesMap[T]
|
||||
) => Promise<IResponseTypesMap[T]>;
|
23
src/plugins/data/server/search/i_search_context.ts
Normal file
23
src/plugins/data/server/search/i_search_context.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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 { CoreSetup } from '../../../../core/server';
|
||||
|
||||
export interface ISearchContext {
|
||||
core: CoreSetup;
|
||||
}
|
51
src/plugins/data/server/search/i_search_setup.ts
Normal file
51
src/plugins/data/server/search/i_search_setup.ts
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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 { IContextProvider, APICaller } from 'kibana/server';
|
||||
import { ISearchContext } from './i_search_context';
|
||||
import { IResponseTypesMap, IRequestTypesMap } from './i_search';
|
||||
import { TRegisterSearchStrategyProvider, TSearchStrategyProvider } from './i_search_strategy';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
import { DEFAULT_SEARCH_STRATEGY } from '../../common/search';
|
||||
|
||||
/**
|
||||
* The setup contract exposed by the Search plugin exposes the search strategy extension
|
||||
* point.
|
||||
*/
|
||||
export interface ISearchSetup {
|
||||
registerSearchStrategyContext: <TContextName extends keyof ISearchContext>(
|
||||
pluginId: symbol,
|
||||
strategyName: TContextName,
|
||||
provider: IContextProvider<TSearchStrategyProvider<any>, TContextName>
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* Extension point exposed for other plugins to register their own search
|
||||
* strategies.
|
||||
*/
|
||||
registerSearchStrategyProvider: TRegisterSearchStrategyProvider;
|
||||
|
||||
__LEGACY: {
|
||||
search: <T extends TStrategyTypes = typeof DEFAULT_SEARCH_STRATEGY>(
|
||||
caller: APICaller,
|
||||
request: IRequestTypesMap[T],
|
||||
strategyName?: T
|
||||
) => Promise<IResponseTypesMap[T]>;
|
||||
};
|
||||
}
|
66
src/plugins/data/server/search/i_search_strategy.ts
Normal file
66
src/plugins/data/server/search/i_search_strategy.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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 { APICaller } from 'kibana/server';
|
||||
import { ISearch, ISearchGeneric } from './i_search';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
import { ISearchContext } from './i_search_context';
|
||||
|
||||
/**
|
||||
* Search strategy interface contains a search method that takes in
|
||||
* a request and returns a promise that resolves to a response.
|
||||
*/
|
||||
export interface ISearchStrategy<T extends TStrategyTypes> {
|
||||
search: ISearch<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search strategy provider creates an instance of a search strategy with the request
|
||||
* handler context bound to it. This way every search strategy can use
|
||||
* whatever information they require from the request context.
|
||||
*/
|
||||
export type TSearchStrategyProviderEnhanced<T extends TStrategyTypes> = (
|
||||
caller: APICaller,
|
||||
search: ISearchGeneric
|
||||
) => Promise<ISearchStrategy<T>>;
|
||||
|
||||
/**
|
||||
* Search strategy provider creates an instance of a search strategy with the request
|
||||
* handler context bound to it. This way every search strategy can use
|
||||
* whatever information they require from the request context.
|
||||
*/
|
||||
export type TSearchStrategyProvider<T extends TStrategyTypes> = (
|
||||
context: ISearchContext,
|
||||
caller: APICaller,
|
||||
search: ISearchGeneric
|
||||
) => ISearchStrategy<T>;
|
||||
|
||||
/**
|
||||
* Extension point exposed for other plugins to register their own search
|
||||
* strategies.
|
||||
*/
|
||||
export type TRegisterSearchStrategyProvider = <T extends TStrategyTypes>(
|
||||
opaqueId: symbol,
|
||||
name: T,
|
||||
searchStrategyProvider: TSearchStrategyProvider<T>
|
||||
) => void;
|
||||
|
||||
export type TSearchStrategiesMap = {
|
||||
[K in TStrategyTypes]?: TSearchStrategyProviderEnhanced<K>;
|
||||
};
|
29
src/plugins/data/server/search/index.ts
Normal file
29
src/plugins/data/server/search/index.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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 { ISearchSetup } from './i_search_setup';
|
||||
export * from '../../common';
|
||||
|
||||
export { ISearchContext } from './i_search_context';
|
||||
|
||||
export { IRequestTypesMap, IResponseTypesMap } from './i_search';
|
||||
|
||||
export { TStrategyTypes } from './strategy_types';
|
||||
|
||||
export { TSearchStrategyProvider } from './i_search_strategy';
|
26
src/plugins/data/server/search/mocks.ts
Normal file
26
src/plugins/data/server/search/mocks.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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 const searchSetupMock = {
|
||||
registerSearchStrategyContext: jest.fn(),
|
||||
registerSearchStrategyProvider: jest.fn(),
|
||||
__LEGACY: {
|
||||
search: jest.fn(),
|
||||
},
|
||||
};
|
99
src/plugins/data/server/search/routes.test.ts
Normal file
99
src/plugins/data/server/search/routes.test.ts
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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 { httpServiceMock, httpServerMock } from '../../../../../src/core/server/mocks';
|
||||
import { registerSearchRoute } from './routes';
|
||||
import { IRouter, ScopedClusterClient } from 'kibana/server';
|
||||
|
||||
describe('Search service', () => {
|
||||
let routerMock: jest.Mocked<IRouter>;
|
||||
|
||||
beforeEach(() => {
|
||||
routerMock = httpServiceMock.createRouter();
|
||||
});
|
||||
|
||||
it('registers a post route', async () => {
|
||||
registerSearchRoute(routerMock);
|
||||
expect(routerMock.post).toBeCalled();
|
||||
});
|
||||
|
||||
it('handler calls context.search.search with the given request and strategy', async () => {
|
||||
const mockSearch = jest.fn().mockResolvedValue('yay');
|
||||
const mockContext = {
|
||||
core: {
|
||||
elasticsearch: {
|
||||
dataClient: {} as ScopedClusterClient,
|
||||
adminClient: {} as ScopedClusterClient,
|
||||
},
|
||||
},
|
||||
search: {
|
||||
search: mockSearch,
|
||||
},
|
||||
};
|
||||
const mockBody = { params: {} };
|
||||
const mockParams = { strategy: 'foo' };
|
||||
const mockRequest = httpServerMock.createKibanaRequest({
|
||||
body: mockBody,
|
||||
params: mockParams,
|
||||
});
|
||||
const mockResponse = httpServerMock.createResponseFactory();
|
||||
|
||||
registerSearchRoute(routerMock);
|
||||
const handler = routerMock.post.mock.calls[0][1];
|
||||
await handler(mockContext, mockRequest, mockResponse);
|
||||
|
||||
expect(mockSearch).toBeCalled();
|
||||
expect(mockSearch.mock.calls[0][0]).toStrictEqual(mockBody);
|
||||
expect(mockSearch.mock.calls[0][1]).toBe(mockParams.strategy);
|
||||
expect(mockResponse.ok).toBeCalled();
|
||||
expect(mockResponse.ok.mock.calls[0][0]).toEqual({ body: 'yay' });
|
||||
});
|
||||
|
||||
it('handler throws internal error if the search throws an error', async () => {
|
||||
const mockSearch = jest.fn().mockRejectedValue('oh no');
|
||||
const mockContext = {
|
||||
core: {
|
||||
elasticsearch: {
|
||||
dataClient: {} as ScopedClusterClient,
|
||||
adminClient: {} as ScopedClusterClient,
|
||||
},
|
||||
},
|
||||
search: {
|
||||
search: mockSearch,
|
||||
},
|
||||
};
|
||||
const mockBody = { params: {} };
|
||||
const mockParams = { strategy: 'foo' };
|
||||
const mockRequest = httpServerMock.createKibanaRequest({
|
||||
body: mockBody,
|
||||
params: mockParams,
|
||||
});
|
||||
const mockResponse = httpServerMock.createResponseFactory();
|
||||
|
||||
registerSearchRoute(routerMock);
|
||||
const handler = routerMock.post.mock.calls[0][1];
|
||||
await handler(mockContext, mockRequest, mockResponse);
|
||||
|
||||
expect(mockSearch).toBeCalled();
|
||||
expect(mockSearch.mock.calls[0][0]).toStrictEqual(mockBody);
|
||||
expect(mockSearch.mock.calls[0][1]).toBe(mockParams.strategy);
|
||||
expect(mockResponse.internalError).toBeCalled();
|
||||
expect(mockResponse.internalError.mock.calls[0][0]).toEqual({ body: 'oh no' });
|
||||
});
|
||||
});
|
46
src/plugins/data/server/search/routes.ts
Normal file
46
src/plugins/data/server/search/routes.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
import { IRouter } from '../../../../core/server';
|
||||
|
||||
export function registerSearchRoute(router: IRouter): void {
|
||||
router.post(
|
||||
{
|
||||
path: '/internal/search/{strategy}',
|
||||
validate: {
|
||||
params: schema.object({ strategy: schema.string() }),
|
||||
|
||||
query: schema.object({}, { allowUnknowns: true }),
|
||||
|
||||
body: schema.object({}, { allowUnknowns: true }),
|
||||
},
|
||||
},
|
||||
async (context, request, res) => {
|
||||
const searchRequest = request.body;
|
||||
const strategy = request.params.strategy;
|
||||
try {
|
||||
const response = await context.search!.search(searchRequest, strategy);
|
||||
return res.ok({ body: response });
|
||||
} catch (err) {
|
||||
return res.internalError({ body: err });
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
56
src/plugins/data/server/search/search_service.test.ts
Normal file
56
src/plugins/data/server/search/search_service.test.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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 { coreMock } from '../../../../core/server/mocks';
|
||||
|
||||
import { SearchService } from './search_service';
|
||||
import { CoreSetup } from '../../../../core/server';
|
||||
|
||||
const mockSearchApi = { search: jest.fn() };
|
||||
jest.mock('./create_api', () => ({
|
||||
createApi: () => mockSearchApi,
|
||||
}));
|
||||
|
||||
describe('Search service', () => {
|
||||
let plugin: SearchService;
|
||||
let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
|
||||
beforeEach(() => {
|
||||
plugin = new SearchService(coreMock.createPluginInitializerContext({}));
|
||||
mockCoreSetup = coreMock.createSetup();
|
||||
mockSearchApi.search.mockClear();
|
||||
});
|
||||
|
||||
describe('setup()', () => {
|
||||
it('exposes proper contract', async () => {
|
||||
const setup = plugin.setup(mockCoreSetup);
|
||||
expect(setup).toHaveProperty('registerSearchStrategyContext');
|
||||
expect(setup).toHaveProperty('registerSearchStrategyProvider');
|
||||
expect(setup).toHaveProperty('__LEGACY');
|
||||
});
|
||||
});
|
||||
|
||||
describe('__LEGACY', () => {
|
||||
it('calls searchAPI.search', async () => {
|
||||
const setup = plugin.setup(mockCoreSetup);
|
||||
setup.__LEGACY.search(jest.fn(), {}, 'foo');
|
||||
expect(mockSearchApi.search).toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
97
src/plugins/data/server/search/search_service.ts
Normal file
97
src/plugins/data/server/search/search_service.ts
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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 {
|
||||
PluginInitializerContext,
|
||||
Plugin,
|
||||
CoreSetup,
|
||||
IContextContainer,
|
||||
} from '../../../../core/server';
|
||||
import { registerSearchRoute } from './routes';
|
||||
import { ISearchSetup } from './i_search_setup';
|
||||
import { createApi } from './create_api';
|
||||
import {
|
||||
TSearchStrategiesMap,
|
||||
TSearchStrategyProvider,
|
||||
TRegisterSearchStrategyProvider,
|
||||
} from './i_search_strategy';
|
||||
import { IRouteHandlerSearchContext } from './i_route_handler_search_context';
|
||||
import { esSearchService } from './es_search';
|
||||
|
||||
declare module 'kibana/server' {
|
||||
interface RequestHandlerContext {
|
||||
search?: IRouteHandlerSearchContext;
|
||||
}
|
||||
}
|
||||
|
||||
export class SearchService implements Plugin<ISearchSetup, void> {
|
||||
private searchStrategies: TSearchStrategiesMap = {};
|
||||
|
||||
private contextContainer?: IContextContainer<TSearchStrategyProvider<any>>;
|
||||
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
|
||||
public setup(core: CoreSetup): ISearchSetup {
|
||||
const router = core.http.createRouter();
|
||||
registerSearchRoute(router);
|
||||
|
||||
this.contextContainer = core.context.createContextContainer();
|
||||
|
||||
core.http.registerRouteHandlerContext<'search'>('search', context => {
|
||||
return createApi({
|
||||
caller: context.core!.elasticsearch.dataClient.callAsCurrentUser,
|
||||
searchStrategies: this.searchStrategies,
|
||||
});
|
||||
});
|
||||
|
||||
const registerSearchStrategyProvider: TRegisterSearchStrategyProvider = (
|
||||
plugin,
|
||||
name,
|
||||
strategyProvider
|
||||
) => {
|
||||
this.searchStrategies[name] = this.contextContainer!.createHandler(plugin, strategyProvider);
|
||||
};
|
||||
|
||||
const api: ISearchSetup = {
|
||||
registerSearchStrategyContext: this.contextContainer!.registerContext,
|
||||
registerSearchStrategyProvider,
|
||||
__LEGACY: {
|
||||
search: (caller, request, strategyName) => {
|
||||
const searchAPI = createApi({
|
||||
caller,
|
||||
searchStrategies: this.searchStrategies,
|
||||
});
|
||||
return searchAPI.search(request, strategyName);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
api.registerSearchStrategyContext(this.initializerContext.opaqueId, 'core', () => core);
|
||||
|
||||
// ES search capabilities are written in a way that it could easily be a separate plugin,
|
||||
// however these two plugins are tightly coupled due to the default search strategy using
|
||||
// es search types.
|
||||
esSearchService(this.initializerContext).setup(core, { search: api });
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public stop() {}
|
||||
}
|
39
src/plugins/data/server/search/strategy_types.ts
Normal file
39
src/plugins/data/server/search/strategy_types.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 { ES_SEARCH_STRATEGY } from '../../common/search/es_search';
|
||||
|
||||
/**
|
||||
* Contains all known strategy type identifiers that will be used to map to
|
||||
* request and response shapes. Plugins that wish to add their own custom search
|
||||
* strategies should extend this type via:
|
||||
*
|
||||
* const MY_STRATEGY = 'MY_STRATEGY';
|
||||
*
|
||||
* declare module 'src/plugins/search/server' {
|
||||
* export interface IRequestTypesMap {
|
||||
* [MY_STRATEGY]: IMySearchRequest;
|
||||
* }
|
||||
*
|
||||
* export interface IResponseTypesMap {
|
||||
* [MY_STRATEGY]: IMySearchResponse
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export type TStrategyTypes = typeof ES_SEARCH_STRATEGY | string;
|
|
@ -213,6 +213,17 @@ export async function FindProvider({ getService }: FtrProviderContext) {
|
|||
return await this.filterElementIsDisplayed(allElements);
|
||||
}
|
||||
|
||||
public async allDescendantDisplayedByTagName(
|
||||
tagName: string,
|
||||
parentElement: WebElementWrapper
|
||||
): Promise<WebElementWrapper[]> {
|
||||
log.debug(`Find.allDescendantDisplayedByTagName('${tagName}')`);
|
||||
const allElements = await wrapAll(
|
||||
await parentElement._webElement.findElements(By.tagName(tagName))
|
||||
);
|
||||
return await this.filterElementIsDisplayed(allElements);
|
||||
}
|
||||
|
||||
public async displayedByLinkText(
|
||||
linkText: string,
|
||||
timeout: number = defaultFindTimeout
|
||||
|
|
|
@ -72,6 +72,27 @@ export function TestSubjectsProvider({ getService }: FtrProviderContext) {
|
|||
: find.waitForDeletedByCssSelector(testSubjSelector(selector), timeout));
|
||||
}
|
||||
|
||||
async stringExistsInCodeBlockOrFail(codeBlockSelector: string, stringToFind: string) {
|
||||
await retry.try(async () => {
|
||||
const responseCodeBlock = await this.find(codeBlockSelector);
|
||||
const spans = await find.allDescendantDisplayedByTagName('span', responseCodeBlock);
|
||||
const foundInSpans = await Promise.all(
|
||||
spans.map(async span => {
|
||||
const text = await span.getVisibleText();
|
||||
if (text === stringToFind) {
|
||||
log.debug(`"${text}" matched "${stringToFind}"!`);
|
||||
return true;
|
||||
} else {
|
||||
log.debug(`"${text}" did not match "${stringToFind}"`);
|
||||
}
|
||||
})
|
||||
);
|
||||
if (!foundInSpans.find(foundInSpan => foundInSpan)) {
|
||||
throw new Error(`"${stringToFind}" was not found. Trying again...`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async append(selector: string, text: string): Promise<void> {
|
||||
return await retry.try(async () => {
|
||||
log.debug(`TestSubjects.append(${selector}, ${text})`);
|
||||
|
|
|
@ -33,6 +33,7 @@ export default async function ({ readConfigFile }) {
|
|||
require.resolve('./test_suites/custom_visualizations'),
|
||||
require.resolve('./test_suites/embedding_visualizations'),
|
||||
require.resolve('./test_suites/panel_actions'),
|
||||
require.resolve('./test_suites/search'),
|
||||
|
||||
/**
|
||||
* @todo Work on re-enabling this test suite after this is merged. These tests pass
|
||||
|
|
34
test/plugin_functional/plugins/demo_search/common/index.ts
Normal file
34
test/plugin_functional/plugins/demo_search/common/index.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 {
|
||||
IKibanaSearchRequest,
|
||||
IKibanaSearchResponse,
|
||||
} from '../../../../../src/plugins/data/common/search';
|
||||
|
||||
export const DEMO_SEARCH_STRATEGY = 'DEMO_SEARCH_STRATEGY';
|
||||
|
||||
export interface IDemoRequest extends IKibanaSearchRequest {
|
||||
mood: string | 'sad' | 'happy';
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface IDemoResponse extends IKibanaSearchResponse {
|
||||
greeting: string;
|
||||
}
|
10
test/plugin_functional/plugins/demo_search/kibana.json
Normal file
10
test/plugin_functional/plugins/demo_search/kibana.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "demoSearch",
|
||||
"version": "0.0.1",
|
||||
"kibanaVersion": "kibana",
|
||||
"configPath": ["demo_search"],
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["data"],
|
||||
"optionalPlugins": []
|
||||
}
|
17
test/plugin_functional/plugins/demo_search/package.json
Normal file
17
test/plugin_functional/plugins/demo_search/package.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "demo_data_search",
|
||||
"version": "1.0.0",
|
||||
"main": "target/test/plugin_functional/plugins/demo_data_search",
|
||||
"kibana": {
|
||||
"version": "kibana",
|
||||
"templateVersion": "1.0.0"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"kbn": "node ../../../../scripts/kbn.js",
|
||||
"build": "rm -rf './target' && tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "3.5.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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 { Observable } from 'rxjs';
|
||||
import {
|
||||
ISearchContext,
|
||||
SYNC_SEARCH_STRATEGY,
|
||||
ISearchGeneric,
|
||||
} from '../../../../../src/plugins/data/public';
|
||||
import { TSearchStrategyProvider, ISearchStrategy } from '../../../../../src/plugins/data/public';
|
||||
|
||||
import { DEMO_SEARCH_STRATEGY, IDemoResponse } from '../common';
|
||||
|
||||
/**
|
||||
* This demo search strategy provider simply provides a shortcut for calling the DEMO_SEARCH_STRATEGY
|
||||
* on the server side, without users having to pass it in explicitly, and it takes advantage of the
|
||||
* already registered SYNC_SEARCH_STRATEGY that exists on the client.
|
||||
*
|
||||
* so instead of callers having to do:
|
||||
*
|
||||
* ```
|
||||
* context.search(
|
||||
* { ...request, serverStrategy: DEMO_SEARCH_STRATEGY },
|
||||
* options,
|
||||
* SYNC_SEARCH_STRATEGY
|
||||
* ) as Observable<IDemoResponse>,
|
||||
*```
|
||||
|
||||
* They can instead just do
|
||||
*
|
||||
* ```
|
||||
* context.search(request, options, DEMO_SEARCH_STRATEGY);
|
||||
* ```
|
||||
*
|
||||
* and are ensured type safety in regard to the request and response objects.
|
||||
*
|
||||
* @param context - context supplied by other plugins.
|
||||
* @param search - a search function to access other strategies that have already been registered.
|
||||
*/
|
||||
export const demoClientSearchStrategyProvider: TSearchStrategyProvider<
|
||||
typeof DEMO_SEARCH_STRATEGY
|
||||
> = (
|
||||
context: ISearchContext,
|
||||
search: ISearchGeneric
|
||||
): ISearchStrategy<typeof DEMO_SEARCH_STRATEGY> => {
|
||||
return {
|
||||
search: (request, options) =>
|
||||
search(
|
||||
{ ...request, serverStrategy: DEMO_SEARCH_STRATEGY },
|
||||
options,
|
||||
SYNC_SEARCH_STRATEGY
|
||||
) as Observable<IDemoResponse>,
|
||||
};
|
||||
};
|
28
test/plugin_functional/plugins/demo_search/public/index.ts
Normal file
28
test/plugin_functional/plugins/demo_search/public/index.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 { PluginInitializer, PluginInitializerContext } from 'kibana/public';
|
||||
|
||||
import { DemoDataPlugin } from './plugin';
|
||||
|
||||
export { DEMO_SEARCH_STRATEGY } from '../common';
|
||||
|
||||
export const plugin: PluginInitializer<void, void> = (
|
||||
initializerContext: PluginInitializerContext
|
||||
) => new DemoDataPlugin(initializerContext);
|
61
test/plugin_functional/plugins/demo_search/public/plugin.ts
Normal file
61
test/plugin_functional/plugins/demo_search/public/plugin.ts
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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 { DataPublicPluginSetup } from '../../../../../src/plugins/data/public';
|
||||
import { Plugin, CoreSetup, PluginInitializerContext } from '../../../../../src/core/public';
|
||||
import { DEMO_SEARCH_STRATEGY } from '../common';
|
||||
import { demoClientSearchStrategyProvider } from './demo_search_strategy';
|
||||
import { IDemoRequest, IDemoResponse } from '../common';
|
||||
|
||||
interface DemoDataSearchSetupDependencies {
|
||||
data: DataPublicPluginSetup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the typescript mappings for our search strategy to the request and
|
||||
* response types. This allows typescript to require the right shapes if
|
||||
* making the call:
|
||||
* const response = context.search.search(request, {}, DEMO_SEARCH_STRATEGY);
|
||||
*
|
||||
* If the caller does not pass in the right `request` shape, typescript will
|
||||
* complain. The caller will also get a typed response.
|
||||
*/
|
||||
declare module '../../../../../src/plugins/data/public' {
|
||||
export interface IRequestTypesMap {
|
||||
[DEMO_SEARCH_STRATEGY]: IDemoRequest;
|
||||
}
|
||||
|
||||
export interface IResponseTypesMap {
|
||||
[DEMO_SEARCH_STRATEGY]: IDemoResponse;
|
||||
}
|
||||
}
|
||||
|
||||
export class DemoDataPlugin implements Plugin {
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
public setup(core: CoreSetup, deps: DemoDataSearchSetupDependencies) {
|
||||
deps.data.search.registerSearchStrategyProvider(
|
||||
this.initializerContext.opaqueId,
|
||||
DEMO_SEARCH_STRATEGY,
|
||||
demoClientSearchStrategyProvider
|
||||
);
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public stop() {}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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 const FAKE_PROGRESS_STRATEGY = 'FAKE_PROGRESS_STRATEGY';
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 { TSearchStrategyProvider } from 'src/plugins/data/server';
|
||||
import { DEMO_SEARCH_STRATEGY } from '../common';
|
||||
|
||||
export const demoSearchStrategyProvider: TSearchStrategyProvider<
|
||||
typeof DEMO_SEARCH_STRATEGY
|
||||
> = () => {
|
||||
return {
|
||||
search: request => {
|
||||
return Promise.resolve({
|
||||
greeting:
|
||||
request.mood === 'happy'
|
||||
? `Lovely to meet you, ${request.name}`
|
||||
: `Hope you feel better, ${request.name}`,
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
25
test/plugin_functional/plugins/demo_search/server/index.ts
Normal file
25
test/plugin_functional/plugins/demo_search/server/index.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 { PluginInitializerContext, PluginInitializer } from 'kibana/server';
|
||||
import { DemoDataPlugin } from './plugin';
|
||||
|
||||
export const plugin: PluginInitializer<void, void> = (
|
||||
initializerContext: PluginInitializerContext
|
||||
) => new DemoDataPlugin(initializerContext);
|
61
test/plugin_functional/plugins/demo_search/server/plugin.ts
Normal file
61
test/plugin_functional/plugins/demo_search/server/plugin.ts
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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 { Plugin, CoreSetup, PluginInitializerContext } from 'kibana/server';
|
||||
import { DataPluginSetup } from 'src/plugins/data/server/plugin';
|
||||
import { demoSearchStrategyProvider } from './demo_search_strategy';
|
||||
import { DEMO_SEARCH_STRATEGY, IDemoRequest, IDemoResponse } from '../common';
|
||||
|
||||
interface IDemoSearchExplorerDeps {
|
||||
data: DataPluginSetup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the typescript mappings for our search strategy to the request and
|
||||
* response types. This allows typescript to require the right shapes if
|
||||
* making the call:
|
||||
* const response = context.search.search(request, DEMO_SEARCH_STRATEGY);
|
||||
*
|
||||
* If the caller does not pass in the right `request` shape, typescript will
|
||||
* complain. The caller will also get a typed response.
|
||||
*/
|
||||
declare module '../../../../../src/plugins/data/server' {
|
||||
export interface IRequestTypesMap {
|
||||
[DEMO_SEARCH_STRATEGY]: IDemoRequest;
|
||||
}
|
||||
|
||||
export interface IResponseTypesMap {
|
||||
[DEMO_SEARCH_STRATEGY]: IDemoResponse;
|
||||
}
|
||||
}
|
||||
|
||||
export class DemoDataPlugin implements Plugin<void, void, IDemoSearchExplorerDeps> {
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
|
||||
public setup(core: CoreSetup, deps: IDemoSearchExplorerDeps) {
|
||||
deps.data.search.registerSearchStrategyProvider(
|
||||
this.initializerContext.opaqueId,
|
||||
DEMO_SEARCH_STRATEGY,
|
||||
demoSearchStrategyProvider
|
||||
);
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public stop() {}
|
||||
}
|
16
test/plugin_functional/plugins/demo_search/tsconfig.json
Normal file
16
test/plugin_functional/plugins/demo_search/tsconfig.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"extends": "../../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./target",
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"index.ts",
|
||||
"common/**/*.ts",
|
||||
"public/**/*.ts",
|
||||
"public/**/*.tsx",
|
||||
"server/**/*.ts",
|
||||
"../../../../typings/**/*"
|
||||
],
|
||||
"exclude": []
|
||||
}
|
10
test/plugin_functional/plugins/search_explorer/kibana.json
Normal file
10
test/plugin_functional/plugins/search_explorer/kibana.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "search_explorer",
|
||||
"version": "0.0.1",
|
||||
"kibanaVersion": "kibana",
|
||||
"configPath": ["search_explorer"],
|
||||
"server": false,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["data", "demoSearch"],
|
||||
"optionalPlugins": []
|
||||
}
|
17
test/plugin_functional/plugins/search_explorer/package.json
Normal file
17
test/plugin_functional/plugins/search_explorer/package.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "search_explorer",
|
||||
"version": "1.0.0",
|
||||
"main": "target/test/plugin_functional/plugins/search_explorer",
|
||||
"kibana": {
|
||||
"version": "kibana",
|
||||
"templateVersion": "1.0.0"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"kbn": "node ../../../../scripts/kbn.js",
|
||||
"build": "rm -rf './target' && tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "3.5.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter as Router, Route, withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
EuiPage,
|
||||
EuiPageSideBar,
|
||||
// @ts-ignore
|
||||
EuiSideNav,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { AppMountContext, AppMountParameters } from '../../../../../src/core/public';
|
||||
import { EsSearchTest } from './es_strategy';
|
||||
import { Page } from './page';
|
||||
import { DemoStrategy } from './demo_strategy';
|
||||
import { DocumentationPage } from './documentation';
|
||||
import { SearchApiPage } from './search_api';
|
||||
|
||||
const Home = () => <DocumentationPage />;
|
||||
|
||||
interface PageDef {
|
||||
title: string;
|
||||
id: string;
|
||||
component: React.ReactNode;
|
||||
}
|
||||
|
||||
type NavProps = RouteComponentProps & {
|
||||
navigateToApp: AppMountContext['core']['application']['navigateToApp'];
|
||||
pages: PageDef[];
|
||||
};
|
||||
|
||||
const Nav = withRouter(({ history, navigateToApp, pages }: NavProps) => {
|
||||
const navItems = pages.map(page => ({
|
||||
id: page.id,
|
||||
name: page.title,
|
||||
onClick: () => history.push(`/${page.id}`),
|
||||
'data-test-subj': page.id,
|
||||
}));
|
||||
|
||||
return (
|
||||
<EuiSideNav
|
||||
items={[
|
||||
{
|
||||
name: 'Search explorer',
|
||||
id: 'home',
|
||||
items: [...navItems],
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const buildPage = (page: PageDef) => <Page title={page.title}>{page.component}</Page>;
|
||||
|
||||
const SearchApp = ({ basename, context }: { basename: string; context: AppMountContext }) => {
|
||||
const pages: PageDef[] = [
|
||||
{
|
||||
id: 'home',
|
||||
title: 'Home',
|
||||
component: <Home />,
|
||||
},
|
||||
{
|
||||
title: 'Search API',
|
||||
id: 'searchAPI',
|
||||
component: <SearchApiPage />,
|
||||
},
|
||||
{
|
||||
title: 'ES search strategy',
|
||||
id: 'esSearch',
|
||||
component: <EsSearchTest search={context.search!.search} />,
|
||||
},
|
||||
{
|
||||
title: 'Demo search strategy',
|
||||
id: 'demoSearch',
|
||||
component: <DemoStrategy search={context.search!.search} />,
|
||||
},
|
||||
];
|
||||
|
||||
const routes = pages.map((page, i) => (
|
||||
<Route key={i} path={`/${page.id}`} render={props => buildPage(page)} />
|
||||
));
|
||||
|
||||
return (
|
||||
<Router basename={basename}>
|
||||
<EuiPage>
|
||||
<EuiPageSideBar>
|
||||
<Nav navigateToApp={context.core.application.navigateToApp} pages={pages} />
|
||||
</EuiPageSideBar>
|
||||
<Route path="/" exact component={Home} />
|
||||
{routes}
|
||||
</EuiPage>
|
||||
</Router>
|
||||
);
|
||||
};
|
||||
|
||||
export const renderApp = (
|
||||
context: AppMountContext,
|
||||
{ appBasePath, element }: AppMountParameters
|
||||
) => {
|
||||
ReactDOM.render(<SearchApp basename={appBasePath} context={context} />, element);
|
||||
|
||||
return () => ReactDOM.unmountComponentAtNode(element);
|
||||
};
|
|
@ -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 React from 'react';
|
||||
import {
|
||||
EuiPageContentBody,
|
||||
EuiFormRow,
|
||||
EuiFlexItem,
|
||||
EuiFlexGroup,
|
||||
EuiFieldText,
|
||||
} from '@elastic/eui';
|
||||
import { ISearchGeneric } from '../../../../../src/plugins/data/public';
|
||||
import { DoSearch } from './do_search';
|
||||
import { GuideSection } from './guide_section';
|
||||
|
||||
import { DEMO_SEARCH_STRATEGY } from '../../demo_search/public';
|
||||
|
||||
import { IDemoResponse, IDemoRequest } from '../../demo_search/common';
|
||||
|
||||
// @ts-ignore
|
||||
import doSearch from '!!raw-loader!./do_search.tsx';
|
||||
// @ts-ignore
|
||||
import demoStrategyServerProvider from '!!raw-loader!./../../demo_search/server/demo_search_strategy';
|
||||
// @ts-ignore
|
||||
import demoStrategyPublicProvider from '!!raw-loader!./../../demo_search/public/demo_search_strategy';
|
||||
// @ts-ignore
|
||||
import demoStrategyServerPlugin from '!!raw-loader!./../../demo_search/server/plugin';
|
||||
// @ts-ignore
|
||||
import demoStrategyPublicPlugin from '!!raw-loader!./../../demo_search/public/plugin';
|
||||
|
||||
interface Props {
|
||||
search: ISearchGeneric;
|
||||
}
|
||||
|
||||
interface State {
|
||||
results?: IDemoResponse;
|
||||
searching: boolean;
|
||||
name: string;
|
||||
mood: string;
|
||||
changes: boolean;
|
||||
error?: any;
|
||||
}
|
||||
|
||||
export class DemoStrategy extends React.Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
searching: false,
|
||||
changes: false,
|
||||
name: 'Molly',
|
||||
mood: 'happy',
|
||||
};
|
||||
}
|
||||
|
||||
renderDemo = () => {
|
||||
const request: IDemoRequest = {
|
||||
name: this.state.name,
|
||||
mood: this.state.mood,
|
||||
};
|
||||
return (
|
||||
<React.Fragment>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow label="What is your name?">
|
||||
<EuiFieldText
|
||||
value={this.state.name}
|
||||
onChange={e => this.setState({ name: e.target.value })}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow label="How are you feeling today?">
|
||||
<EuiFieldText
|
||||
value={this.state.mood}
|
||||
onChange={e => this.setState({ mood: e.target.value })}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<DoSearch
|
||||
request={request}
|
||||
strategy={DEMO_SEARCH_STRATEGY}
|
||||
search={(signal: AbortSignal) =>
|
||||
this.props.search(request, { signal }, DEMO_SEARCH_STRATEGY)
|
||||
}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EuiPageContentBody>
|
||||
<GuideSection
|
||||
codeSections={[
|
||||
{
|
||||
title: 'Public',
|
||||
code: [
|
||||
{ description: 'plugin.ts', snippet: demoStrategyPublicPlugin },
|
||||
{ description: 'demo_search_strategy.ts', snippet: demoStrategyPublicProvider },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Server',
|
||||
code: [
|
||||
{ description: 'plugin.ts', snippet: demoStrategyServerPlugin },
|
||||
{ description: 'demo_search_strategy.ts', snippet: demoStrategyServerProvider },
|
||||
],
|
||||
},
|
||||
]}
|
||||
demo={this.renderDemo()}
|
||||
></GuideSection>
|
||||
</EuiPageContentBody>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { EuiButton, EuiCodeBlock, EuiFlexItem, EuiFlexGroup, EuiText } from '@elastic/eui';
|
||||
import { EuiProgress } from '@elastic/eui';
|
||||
import { Observable } from 'rxjs';
|
||||
import {
|
||||
IKibanaSearchResponse,
|
||||
IKibanaSearchRequest,
|
||||
} from '../../../../../src/plugins/data/public';
|
||||
|
||||
interface Props {
|
||||
request: IKibanaSearchRequest;
|
||||
strategy?: string;
|
||||
search: (signal: AbortSignal) => Observable<IKibanaSearchResponse>;
|
||||
}
|
||||
|
||||
interface State {
|
||||
searching: boolean;
|
||||
response?: IKibanaSearchResponse;
|
||||
error?: any;
|
||||
}
|
||||
|
||||
export class DoSearch extends React.Component<Props, State> {
|
||||
private abortController?: AbortController;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
searching: false,
|
||||
response: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
search = async () => {
|
||||
if (this.state.searching && this.abortController) {
|
||||
this.abortController.abort();
|
||||
}
|
||||
|
||||
this.setState({
|
||||
searching: true,
|
||||
response: undefined,
|
||||
error: undefined,
|
||||
});
|
||||
|
||||
this.abortController = new AbortController();
|
||||
|
||||
this.props.search(this.abortController.signal).subscribe(
|
||||
response => {
|
||||
this.setState({ response, error: undefined });
|
||||
},
|
||||
error => {
|
||||
this.setState({ error, searching: false, response: undefined });
|
||||
},
|
||||
() => {
|
||||
this.setState({ searching: false, error: undefined });
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
cancel = () => {
|
||||
if (this.abortController) {
|
||||
this.abortController.abort();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
let responseStr = this.state.error
|
||||
? JSON.stringify(this.state.error, null, 2)
|
||||
: JSON.stringify(this.state.response, null, 2);
|
||||
responseStr = responseStr ? responseStr.substring(0, 2000) : '';
|
||||
const requestStr = JSON.stringify(this.props.request, null, 2);
|
||||
return (
|
||||
<React.Fragment>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton data-test-subj="doSearch" onClick={this.search}>
|
||||
Search
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton disabled={!this.state.searching} onClick={this.cancel}>
|
||||
Cancel
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiText>Request:</EuiText>
|
||||
<EuiCodeBlock language="json" fontSize="m" paddingSize="m" color="dark">
|
||||
{this.props.strategy
|
||||
? `data.search
|
||||
(
|
||||
${requestStr},
|
||||
"${this.props.strategy}"
|
||||
)`
|
||||
: `data.search
|
||||
(
|
||||
${requestStr}
|
||||
)`}
|
||||
</EuiCodeBlock>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiText>Response:</EuiText>
|
||||
<EuiProgress
|
||||
value={(this.state.response && this.state.response.percentComplete) || 0}
|
||||
max={100}
|
||||
/>
|
||||
<EuiCodeBlock
|
||||
language="json"
|
||||
fontSize="m"
|
||||
paddingSize="m"
|
||||
color="dark"
|
||||
data-test-subj="response"
|
||||
>
|
||||
{responseStr}
|
||||
</EuiCodeBlock>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
import {
|
||||
EuiText,
|
||||
EuiPageBody,
|
||||
EuiPageContent,
|
||||
EuiPageContentBody,
|
||||
EuiPageContentHeader,
|
||||
EuiPageContentHeaderSection,
|
||||
EuiPageHeader,
|
||||
EuiPageHeaderSection,
|
||||
EuiTitle,
|
||||
EuiListGroup,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export const DocumentationPage = () => (
|
||||
<EuiPageBody data-test-subj="dataPluginExplorerHome">
|
||||
<EuiPageHeader>
|
||||
<EuiPageHeaderSection>
|
||||
<EuiTitle size="l">
|
||||
<h1>Welcome to the data plugin portal!</h1>
|
||||
</EuiTitle>
|
||||
</EuiPageHeaderSection>
|
||||
</EuiPageHeader>
|
||||
<EuiPageContent>
|
||||
<EuiPageContentHeader>
|
||||
<EuiPageContentHeaderSection>
|
||||
<EuiTitle>
|
||||
<h2>Documentation links</h2>
|
||||
</EuiTitle>
|
||||
</EuiPageContentHeaderSection>
|
||||
</EuiPageContentHeader>
|
||||
<EuiPageContentBody>
|
||||
<EuiText>
|
||||
<h2>Search Services</h2>
|
||||
<ul>
|
||||
<li>Provide an abstraction on top of advanced query settings</li>
|
||||
|
||||
<li>
|
||||
Providing an abstraction layer for query cancellation semantics allows us to avoid
|
||||
wide-spread code changes when ES API changes, allows us to provide a minimum set of
|
||||
useful functionality first, and allows us to continue adding more advanced features
|
||||
down the road
|
||||
</li>
|
||||
|
||||
<li>Provide a clean separation of OSS and commercial search strategies.</li>
|
||||
</ul>
|
||||
<h2>Extensibility</h2>
|
||||
<p>
|
||||
Plugins can register or use different client side, and server side{' '}
|
||||
<i>search strategies</i>. Search strategies can take advantage of other search stratgies
|
||||
already registered. For example, the `DEMO_SEARCH_STRATEGY` uses the
|
||||
`ASYNC_SEARCH_STRATEGY` which uses the `SYNC_SEARCH_STRATEGY`
|
||||
</p>
|
||||
|
||||
<h2>References</h2>
|
||||
<EuiListGroup
|
||||
listItems={[
|
||||
{
|
||||
label: 'Design document',
|
||||
href:
|
||||
'https://docs.google.com/document/d/1ROLq29V1TeLux4ASQIJNllRGkv-xa5XIE72gTU6u16Q/edit#heading=h.3aa9ppqzkvdd',
|
||||
iconType: 'document',
|
||||
size: 's',
|
||||
},
|
||||
{
|
||||
label: 'Roadmap',
|
||||
href: 'https://github.com/elastic/kibana/issues/44661',
|
||||
iconType: 'logoGithub',
|
||||
size: 's',
|
||||
},
|
||||
{
|
||||
label: 'Data access API issue',
|
||||
href: 'https://github.com/elastic/kibana/issues/43371',
|
||||
iconType: 'logoGithub',
|
||||
size: 's',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</EuiText>
|
||||
</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
</EuiPageBody>
|
||||
);
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import {
|
||||
EuiPageContentBody,
|
||||
EuiFieldText,
|
||||
EuiFormRow,
|
||||
EuiFlexItem,
|
||||
EuiFlexGroup,
|
||||
} from '@elastic/eui';
|
||||
import {
|
||||
ISearchGeneric,
|
||||
IEsSearchResponse,
|
||||
IEsSearchRequest,
|
||||
} from '../../../../../src/plugins/data/public';
|
||||
import { DoSearch } from './do_search';
|
||||
import { GuideSection } from './guide_section';
|
||||
|
||||
// @ts-ignore
|
||||
import serverPlugin from '!!raw-loader!./../../../../../src/plugins/data/server/search/es_search/es_search_service';
|
||||
// @ts-ignore
|
||||
import serverStrategy from '!!raw-loader!./../../../../../src/plugins/data/server/search/es_search/es_search_strategy';
|
||||
|
||||
// @ts-ignore
|
||||
import publicPlugin from '!!raw-loader!./../../../../../src/plugins/data/public/search/es_search/es_search_service';
|
||||
// @ts-ignore
|
||||
import publicStrategy from '!!raw-loader!./../../../../../src/plugins/data/public/search/es_search/es_search_strategy';
|
||||
|
||||
interface Props {
|
||||
search: ISearchGeneric;
|
||||
}
|
||||
|
||||
interface State {
|
||||
query: string;
|
||||
results?: IEsSearchResponse;
|
||||
index: string;
|
||||
searching: boolean;
|
||||
request: IEsSearchRequest;
|
||||
strategy?: string;
|
||||
changes: boolean;
|
||||
error?: any;
|
||||
}
|
||||
|
||||
export class EsSearchTest extends React.Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
query: '*',
|
||||
index: '*',
|
||||
searching: false,
|
||||
request: this.getRequest({ index: '*', query: '*' }),
|
||||
changes: false,
|
||||
};
|
||||
}
|
||||
|
||||
getRequest({ index, query }: { index: string; query: string }): IEsSearchRequest {
|
||||
return {
|
||||
debug: true,
|
||||
params: {
|
||||
index,
|
||||
body: {
|
||||
query: {
|
||||
query_string: {
|
||||
query,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
renderDemo() {
|
||||
const request: IEsSearchRequest = this.getRequest(this.state);
|
||||
return (
|
||||
<React.Fragment>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow label="Index pattern">
|
||||
<EuiFieldText
|
||||
value={this.state.index}
|
||||
onChange={e => this.setState({ index: e.target.value, changes: true })}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow label="Query string query">
|
||||
<EuiFieldText
|
||||
value={this.state.query}
|
||||
onChange={e => this.setState({ query: e.target.value, changes: true })}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<DoSearch
|
||||
request={request}
|
||||
search={(signal: AbortSignal) => this.props.search(request, { signal })}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EuiPageContentBody>
|
||||
<GuideSection
|
||||
codeSections={[
|
||||
{
|
||||
title: 'Public',
|
||||
code: [
|
||||
{ description: 'es_search_service.ts', snippet: publicPlugin },
|
||||
{ description: 'es_search_strategy.ts', snippet: publicStrategy },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Server',
|
||||
code: [
|
||||
{ description: 'es_search_service.ts', snippet: serverPlugin },
|
||||
{ description: 'es_search_strategy.ts', snippet: serverStrategy },
|
||||
],
|
||||
},
|
||||
]}
|
||||
demo={this.renderDemo()}
|
||||
></GuideSection>
|
||||
</EuiPageContentBody>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
import { EuiTab, EuiTabs, EuiCodeBlock } from '@elastic/eui';
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
import { EuiHorizontalRule } from '@elastic/eui';
|
||||
|
||||
export interface CodeSection {
|
||||
title: string;
|
||||
code: Array<{ description?: string; snippet: string }> | string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
demo?: React.ReactNode;
|
||||
codeSections?: CodeSection[];
|
||||
}
|
||||
|
||||
interface State {
|
||||
selectedTab: string;
|
||||
}
|
||||
|
||||
export class GuideSection extends React.Component<Props, State> {
|
||||
private tabs: Array<{ name: string; displayName: string }>;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
if (!props.demo && !props.codeSections) {
|
||||
throw new Error('Must supply either demo or code sections');
|
||||
}
|
||||
|
||||
if (props.demo) {
|
||||
this.tabs = [
|
||||
{
|
||||
name: 'demo',
|
||||
displayName: 'Demo',
|
||||
},
|
||||
];
|
||||
} else {
|
||||
this.tabs = [];
|
||||
}
|
||||
|
||||
if (props.codeSections) {
|
||||
props.codeSections.forEach(section => {
|
||||
this.tabs.push({
|
||||
name: section.title,
|
||||
displayName: section.title,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this.state = {
|
||||
selectedTab: this.tabs[0].name,
|
||||
};
|
||||
}
|
||||
|
||||
onSelectedTabChanged = (selectedTab: string) => {
|
||||
this.setState({
|
||||
selectedTab,
|
||||
});
|
||||
};
|
||||
|
||||
renderTabs() {
|
||||
return this.tabs.map(tab => (
|
||||
<EuiTab
|
||||
onClick={() => this.onSelectedTabChanged(tab.name)}
|
||||
isSelected={tab.name === this.state.selectedTab}
|
||||
key={tab.name}
|
||||
>
|
||||
{tab.displayName}
|
||||
</EuiTab>
|
||||
));
|
||||
}
|
||||
|
||||
removeLicenseBlock(code: string) {
|
||||
return code.replace(/\/\*[\w\'\s\r\n\*\.\,\(\)\"\;\:\/\-]*\s*\//m, '');
|
||||
}
|
||||
|
||||
renderCodeBlocks() {
|
||||
if (!this.props.codeSections) {
|
||||
return undefined;
|
||||
}
|
||||
const section = this.props.codeSections.find(s => s.title === this.state.selectedTab);
|
||||
|
||||
if (!section) {
|
||||
throw new Error('No section named ' + this.state.selectedTab);
|
||||
}
|
||||
const code = section.code;
|
||||
if (typeof code === 'string') {
|
||||
return <EuiCodeBlock language="ts">{this.removeLicenseBlock(code)}</EuiCodeBlock>;
|
||||
}
|
||||
|
||||
return code.map((codeBlock, i) => (
|
||||
<React.Fragment key={i}>
|
||||
<EuiSpacer></EuiSpacer>
|
||||
<h3>{codeBlock.description}</h3>
|
||||
<EuiCodeBlock language="ts">{this.removeLicenseBlock(codeBlock.snippet)}</EuiCodeBlock>
|
||||
<EuiHorizontalRule />
|
||||
</React.Fragment>
|
||||
));
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
if (this.state.selectedTab === 'demo') {
|
||||
return this.props.demo;
|
||||
} else if (this.props.codeSections) {
|
||||
return this.renderCodeBlocks();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<EuiTabs>{this.renderTabs()}</EuiTabs>
|
||||
{this.renderContent()}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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 { SearchExplorerPlugin } from './plugin';
|
||||
|
||||
export const plugin = () => new SearchExplorerPlugin();
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
import {
|
||||
EuiPageBody,
|
||||
EuiPageContent,
|
||||
EuiPageContentBody,
|
||||
EuiPageHeader,
|
||||
EuiPageHeaderSection,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
|
||||
interface PageProps {
|
||||
title: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function Page({ title, children }: PageProps) {
|
||||
return (
|
||||
<EuiPageBody data-test-subj="searchTestPage">
|
||||
<EuiPageHeader>
|
||||
<EuiPageHeaderSection>
|
||||
<EuiTitle size="l">
|
||||
<h1>{title}</h1>
|
||||
</EuiTitle>
|
||||
</EuiPageHeaderSection>
|
||||
</EuiPageHeader>
|
||||
<EuiPageContent>
|
||||
<EuiPageContentBody>{children}</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
</EuiPageBody>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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 { Plugin, CoreSetup } from 'kibana/public';
|
||||
import { ISearchAppMountContext } from '../../../../../src/plugins/data/public';
|
||||
|
||||
declare module 'kibana/public' {
|
||||
interface AppMountContext {
|
||||
search?: ISearchAppMountContext;
|
||||
}
|
||||
}
|
||||
export class SearchExplorerPlugin implements Plugin {
|
||||
public setup(core: CoreSetup) {
|
||||
core.application.register({
|
||||
id: 'searchExplorer',
|
||||
title: 'Search Explorer',
|
||||
async mount(context, params) {
|
||||
const { renderApp } = await import('./application');
|
||||
return renderApp(context, params);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public stop() {}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { GuideSection } from './guide_section';
|
||||
|
||||
// @ts-ignore
|
||||
import publicSetupContract from '!!raw-loader!./../../../../../src/plugins/data/public/search/i_search_setup';
|
||||
// @ts-ignore
|
||||
import publicSearchStrategy from '!!raw-loader!./../../../../../src/plugins/data/public/search/i_search_strategy';
|
||||
// @ts-ignore
|
||||
import publicSearch from '!!raw-loader!./../../../../../src/plugins/data/public/search/i_search';
|
||||
// @ts-ignore
|
||||
import publicPlugin from '!!raw-loader!./../../../../../src/plugins/data/public/search/search_service';
|
||||
|
||||
// @ts-ignore
|
||||
import serverSetupContract from '!!raw-loader!./../../../../../src/plugins/data/server/search/i_search_setup';
|
||||
// @ts-ignore
|
||||
import serverSearchStrategy from '!!raw-loader!./../../../../../src/plugins/data/server/search/i_search_strategy';
|
||||
// @ts-ignore
|
||||
import serverSearch from '!!raw-loader!./../../../../../src/plugins/data/server/search/i_search';
|
||||
// @ts-ignore
|
||||
import serverPlugin from '!!raw-loader!./../../../../../src/plugins/data/server/search/search_service';
|
||||
|
||||
export const SearchApiPage = () => (
|
||||
<GuideSection
|
||||
codeSections={[
|
||||
{
|
||||
title: 'Public',
|
||||
code: [
|
||||
{
|
||||
description: 'search_service.ts',
|
||||
snippet: publicPlugin,
|
||||
},
|
||||
{
|
||||
description: `i_search_setup.ts`,
|
||||
snippet: publicSetupContract,
|
||||
},
|
||||
{
|
||||
description: 'i_search',
|
||||
snippet: publicSearch,
|
||||
},
|
||||
{
|
||||
description: 'i_search_strategy',
|
||||
snippet: publicSearchStrategy,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Server',
|
||||
code: [
|
||||
{
|
||||
description: 'search_service.ts',
|
||||
snippet: serverPlugin,
|
||||
},
|
||||
{
|
||||
description: `i_search_setup.ts`,
|
||||
snippet: serverSetupContract,
|
||||
},
|
||||
{
|
||||
description: 'i_search',
|
||||
snippet: serverSearch,
|
||||
},
|
||||
{
|
||||
description: 'i_search_strategy',
|
||||
snippet: serverSearchStrategy,
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
></GuideSection>
|
||||
);
|
15
test/plugin_functional/plugins/search_explorer/tsconfig.json
Normal file
15
test/plugin_functional/plugins/search_explorer/tsconfig.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"extends": "../../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./target",
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"index.ts",
|
||||
"public/**/*.ts",
|
||||
"public/**/*.tsx",
|
||||
"server/**/*.ts",
|
||||
"../../../../typings/**/*",
|
||||
],
|
||||
"exclude": []
|
||||
}
|
36
test/plugin_functional/test_suites/search/demo_data.ts
Normal file
36
test/plugin_functional/test_suites/search/demo_data.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 { FtrProviderContext } from 'test/functional/ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function({ getService }: FtrProviderContext) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
describe('demo search strategy', () => {
|
||||
before(async () => {
|
||||
await testSubjects.click('demoSearch');
|
||||
});
|
||||
|
||||
it('data is returned', async () => {
|
||||
await testSubjects.click('doSearch');
|
||||
await testSubjects.stringExistsInCodeBlockOrFail('response', '"Lovely to meet you, Molly"');
|
||||
});
|
||||
});
|
||||
}
|
35
test/plugin_functional/test_suites/search/es_search.ts
Normal file
35
test/plugin_functional/test_suites/search/es_search.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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 { FtrProviderContext } from 'test/functional/ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function({ getService }: FtrProviderContext) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
describe('es search strategy', () => {
|
||||
before(async () => {
|
||||
await testSubjects.click('esSearch');
|
||||
});
|
||||
|
||||
it('data is returned', async () => {
|
||||
await testSubjects.click('doSearch');
|
||||
await testSubjects.stringExistsInCodeBlockOrFail('response', '"animal weights"');
|
||||
});
|
||||
});
|
||||
}
|
51
test/plugin_functional/test_suites/search/index.ts
Normal file
51
test/plugin_functional/test_suites/search/index.ts
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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 { FtrProviderContext } from 'test/functional/ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function({ getService, getPageObjects, loadTestFile }: FtrProviderContext) {
|
||||
const browser = getService('browser');
|
||||
const appsMenu = getService('appsMenu');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const PageObjects = getPageObjects(['common', 'header']);
|
||||
|
||||
describe('search services', function() {
|
||||
before(async () => {
|
||||
await esArchiver.loadIfNeeded('../functional/fixtures/es_archiver/dashboard/current/data');
|
||||
await esArchiver.load('../functional/fixtures/es_archiver/dashboard/current/kibana');
|
||||
await kibanaServer.uiSettings.replace({
|
||||
'dateFormat:tz': 'Australia/North',
|
||||
defaultIndex: 'logstash-*',
|
||||
});
|
||||
await browser.setWindowSize(1300, 900);
|
||||
await PageObjects.common.navigateToApp('settings');
|
||||
await appsMenu.clickLink('Search Explorer');
|
||||
});
|
||||
|
||||
after(async function() {
|
||||
await esArchiver.unload('../functional/fixtures/es_archiver/dashboard/current/data');
|
||||
await esArchiver.unload('../functional/fixtures/es_archiver/dashboard/current/kibana');
|
||||
});
|
||||
|
||||
loadTestFile(require.resolve('./demo_data'));
|
||||
loadTestFile(require.resolve('./es_search'));
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue