Skip to content

Commit

Permalink
[index pattern management] Restore cross cluster search functionality (
Browse files Browse the repository at this point in the history
…#108756) (#108977)

* restore cross cluster search functionality
# Conflicts:
#	src/plugins/index_pattern_editor/public/lib/get_indices.test.ts
  • Loading branch information
mattkime authored Aug 17, 2021
1 parent 80ab1dc commit 743d720
Show file tree
Hide file tree
Showing 8 changed files with 328 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const EmptyPrompts: FC<Props> = ({
loadSources,
}) => {
const {
services: { docLinks, application, http },
services: { docLinks, application, http, searchClient },
} = useKibana<IndexPatternEditorContext>();

const [remoteClustersExist, setRemoteClustersExist] = useState<boolean>(false);
Expand All @@ -47,15 +47,21 @@ export const EmptyPrompts: FC<Props> = ({
useCallback(() => {
let isMounted = true;
if (!hasDataIndices)
getIndices(http, () => false, '*:*', false).then((dataSources) => {
getIndices({
http,
isRollupIndex: () => false,
pattern: '*:*',
showAllIndices: false,
searchClient,
}).then((dataSources) => {
if (isMounted) {
setRemoteClustersExist(!!dataSources.filter(removeAliases).length);
}
});
return () => {
isMounted = false;
};
}, [http, hasDataIndices]);
}, [http, hasDataIndices, searchClient]);

if (!hasExistingIndexPatterns && !goToForm) {
if (!hasDataIndices && !remoteClustersExist) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const IndexPatternEditorFlyoutContentComponent = ({
}: Props) => {
const isMounted = useRef<boolean>(false);
const {
services: { http, indexPatternService, uiSettings },
services: { http, indexPatternService, uiSettings, searchClient },
} = useKibana<IndexPatternEditorContext>();

const { form } = useForm<IndexPatternConfig, FormInternal>({
Expand Down Expand Up @@ -128,13 +128,19 @@ const IndexPatternEditorFlyoutContentComponent = ({

// load all data sources and set initial matchedIndices
const loadSources = useCallback(() => {
getIndices(http, () => false, '*', allowHidden).then((dataSources) => {
getIndices({
http,
isRollupIndex: () => false,
pattern: '*',
showAllIndices: allowHidden,
searchClient,
}).then((dataSources) => {
setAllSources(dataSources);
const matchedSet = getMatchedIndices(dataSources, [], [], allowHidden);
setMatchedIndices(matchedSet);
setIsLoadingSources(false);
});
}, [http, allowHidden]);
}, [http, allowHidden, searchClient]);

// loading list of index patterns
useEffect(() => {
Expand Down Expand Up @@ -223,13 +229,31 @@ const IndexPatternEditorFlyoutContentComponent = ({
const indexRequests = [];

if (query?.endsWith('*')) {
const exactMatchedQuery = getIndices(http, isRollupIndex, query, allowHidden);
const exactMatchedQuery = getIndices({
http,
isRollupIndex,
pattern: query,
showAllIndices: allowHidden,
searchClient,
});
indexRequests.push(exactMatchedQuery);
// provide default value when not making a request for the partialMatchQuery
indexRequests.push(Promise.resolve([]));
} else {
const exactMatchQuery = getIndices(http, isRollupIndex, query, allowHidden);
const partialMatchQuery = getIndices(http, isRollupIndex, `${query}*`, allowHidden);
const exactMatchQuery = getIndices({
http,
isRollupIndex,
pattern: query,
showAllIndices: allowHidden,
searchClient,
});
const partialMatchQuery = getIndices({
http,
isRollupIndex,
pattern: `${query}*`,
showAllIndices: allowHidden,
searchClient,
});

indexRequests.push(exactMatchQuery);
indexRequests.push(partialMatchQuery);
Expand Down Expand Up @@ -264,7 +288,7 @@ const IndexPatternEditorFlyoutContentComponent = ({

return fetchIndices(newTitle);
},
[http, allowHidden, allSources, type, rollupIndicesCapabilities]
[http, allowHidden, allSources, type, rollupIndicesCapabilities, searchClient]
);

useEffect(() => {
Expand Down
7 changes: 7 additions & 0 deletions src/plugins/index_pattern_editor/public/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,10 @@
export const pluginName = 'index_pattern_editor';
export const MAX_NUMBER_OF_MATCHING_INDICES = 100;
export const CONFIG_ROLLUPS = 'rollups:enableIndexPatterns';

// This isn't ideal. We want to avoid searching for 20 indices
// then filtering out the majority of them because they are system indices.
// We'd like to filter system indices out in the query
// so if we can accomplish that in the future, this logic can go away
export const ESTIMATED_NUMBER_OF_SYSTEM_INDICES = 100;
export const MAX_SEARCH_SIZE = MAX_NUMBER_OF_MATCHING_INDICES + ESTIMATED_NUMBER_OF_SYSTEM_INDICES;
136 changes: 113 additions & 23 deletions src/plugins/index_pattern_editor/public/lib/get_indices.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@
* Side Public License, v 1.
*/

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { getIndices, responseToItemArray } from './get_indices';
import {
getIndices,
getIndicesViaSearch,
responseToItemArray,
dedupeMatchedItems,
} from './get_indices';
import { httpServiceMock } from '../../../../core/public/mocks';
import { ResolveIndexResponseItemIndexAttrs } from '../types';
import { ResolveIndexResponseItemIndexAttrs, MatchedItem } from '../types';
import { Observable } from 'rxjs';

export const successfulResponse = {
export const successfulResolveResponse = {
indices: [
{
name: 'remoteCluster1:bar-01',
Expand All @@ -40,28 +38,99 @@ export const successfulResponse = {
],
};

const mockGetTags = () => [];
const mockIsRollupIndex = () => false;
const successfulSearchResponse = {
isPartial: false,
isRunning: false,
rawResponse: {
aggregations: {
indices: {
buckets: [{ key: 'kibana_sample_data_ecommerce' }, { key: '.kibana_1' }],
},
},
},
};

const partialSearchResponse = {
isPartial: true,
isRunning: true,
rawResponse: {
hits: {
total: 2,
hits: [],
},
},
};

const errorSearchResponse = {
isPartial: true,
isRunning: false,
};

const isRollupIndex = () => false;
const getTags = () => [];
const searchClient = () =>
new Observable((observer) => {
observer.next(successfulSearchResponse);
observer.complete();
}) as any;

const http = httpServiceMock.createStartContract();
http.get.mockResolvedValue(successfulResponse);
http.get.mockResolvedValue(successfulResolveResponse);

describe('getIndices', () => {
it('should work in a basic case', async () => {
const result = await getIndices(http, mockIsRollupIndex, 'kibana', false);
const uncalledSearchClient = jest.fn();
const result = await getIndices({
http,
pattern: 'kibana',
searchClient: uncalledSearchClient,
isRollupIndex,
});
expect(http.get).toHaveBeenCalled();
expect(uncalledSearchClient).not.toHaveBeenCalled();
expect(result.length).toBe(3);
expect(result[0].name).toBe('f-alias');
expect(result[1].name).toBe('foo');
});

it('should make two calls in cross cluser case', async () => {
http.get.mockResolvedValue(successfulResolveResponse);
const result = await getIndices({ http, pattern: '*:kibana', searchClient, isRollupIndex });

expect(http.get).toHaveBeenCalled();
expect(result.length).toBe(4);
expect(result[0].name).toBe('f-alias');
expect(result[1].name).toBe('foo');
expect(result[2].name).toBe('kibana_sample_data_ecommerce');
expect(result[3].name).toBe('remoteCluster1:bar-01');
});

it('should ignore ccs query-all', async () => {
expect((await getIndices(http, mockIsRollupIndex, '*:', false)).length).toBe(0);
expect((await getIndices({ http, pattern: '*:', searchClient, isRollupIndex })).length).toBe(0);
});

it('should ignore a single comma', async () => {
expect((await getIndices(http, mockIsRollupIndex, ',', false)).length).toBe(0);
expect((await getIndices(http, mockIsRollupIndex, ',*', false)).length).toBe(0);
expect((await getIndices(http, mockIsRollupIndex, ',foobar', false)).length).toBe(0);
expect((await getIndices({ http, pattern: ',', searchClient, isRollupIndex })).length).toBe(0);
expect((await getIndices({ http, pattern: ',*', searchClient, isRollupIndex })).length).toBe(0);
expect(
(await getIndices({ http, pattern: ',foobar', searchClient, isRollupIndex })).length
).toBe(0);
});

it('should work with partial responses', async () => {
const searchClientPartialResponse = () =>
new Observable((observer) => {
observer.next(partialSearchResponse);
observer.next(successfulSearchResponse);
observer.complete();
}) as any;
const result = await getIndices({
http,
pattern: '*:kibana',
searchClient: searchClientPartialResponse,
isRollupIndex,
});
expect(result.length).toBe(4);
});

it('response object to item array', () => {
Expand Down Expand Up @@ -89,16 +158,37 @@ describe('getIndices', () => {
},
],
};
expect(responseToItemArray(result, mockGetTags)).toMatchSnapshot();
expect(responseToItemArray({}, mockGetTags)).toEqual([]);
expect(responseToItemArray(result, getTags)).toMatchSnapshot();
expect(responseToItemArray({}, getTags)).toEqual([]);
});

it('matched items are deduped', () => {
const setA = [{ name: 'a' }, { name: 'b' }] as MatchedItem[];
const setB = [{ name: 'b' }, { name: 'c' }] as MatchedItem[];
expect(dedupeMatchedItems(setA, setB)).toHaveLength(3);
});

describe('errors', () => {
it('should handle errors gracefully', async () => {
it('should handle thrown errors gracefully', async () => {
http.get.mockImplementationOnce(() => {
throw new Error('Test error');
});
const result = await getIndices(http, mockIsRollupIndex, 'kibana', false);
const result = await getIndices({ http, pattern: 'kibana', searchClient, isRollupIndex });
expect(result.length).toBe(0);
});

it('getIndicesViaSearch should handle error responses gracefully', async () => {
const searchClientErrorResponse = () =>
new Observable((observer) => {
observer.next(errorSearchResponse);
observer.complete();
}) as any;
const result = await getIndicesViaSearch({
pattern: '*:kibana',
searchClient: searchClientErrorResponse,
showAllIndices: false,
isRollupIndex,
});
expect(result.length).toBe(0);
});
});
Expand Down
Loading

0 comments on commit 743d720

Please sign in to comment.