mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[data view mgmt] only use resolve api for getting index list (#127085)
* only use resolve api for getting index list Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
719ccb6d87
commit
9739c5fa15
4 changed files with 13 additions and 192 deletions
|
@ -143,14 +143,13 @@ const IndexPatternEditorFlyoutContentComponent = ({
|
|||
isRollupIndex: () => false,
|
||||
pattern: '*',
|
||||
showAllIndices: allowHidden,
|
||||
searchClient,
|
||||
}).then((dataSources) => {
|
||||
setAllSources(dataSources);
|
||||
const matchedSet = getMatchedIndices(dataSources, [], [], allowHidden);
|
||||
setMatchedIndices(matchedSet);
|
||||
setIsLoadingSources(false);
|
||||
});
|
||||
}, [http, allowHidden, searchClient]);
|
||||
}, [http, allowHidden]);
|
||||
|
||||
// loading list of index patterns
|
||||
useEffect(() => {
|
||||
|
@ -407,7 +406,6 @@ const loadMatchedIndices = memoizeOne(
|
|||
isRollupIndex,
|
||||
pattern: query,
|
||||
showAllIndices: allowHidden,
|
||||
searchClient,
|
||||
});
|
||||
indexRequests.push(exactMatchedQuery);
|
||||
// provide default value when not making a request for the partialMatchQuery
|
||||
|
@ -418,14 +416,12 @@ const loadMatchedIndices = memoizeOne(
|
|||
isRollupIndex,
|
||||
pattern: query,
|
||||
showAllIndices: allowHidden,
|
||||
searchClient,
|
||||
});
|
||||
const partialMatchQuery = getIndices({
|
||||
http,
|
||||
isRollupIndex,
|
||||
pattern: `${query}*`,
|
||||
showAllIndices: allowHidden,
|
||||
searchClient,
|
||||
});
|
||||
|
||||
indexRequests.push(exactMatchQuery);
|
||||
|
|
|
@ -66,7 +66,6 @@ export const EmptyPrompts: FC<Props> = ({ allSources, onCancel, children, loadSo
|
|||
isRollupIndex: () => false,
|
||||
pattern: '*:*',
|
||||
showAllIndices: false,
|
||||
searchClient,
|
||||
}).then((dataSources) => {
|
||||
setRemoteClustersExist(!!dataSources.filter(removeAliases).length);
|
||||
});
|
||||
|
|
|
@ -6,15 +6,9 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
getIndices,
|
||||
getIndicesViaSearch,
|
||||
responseToItemArray,
|
||||
dedupeMatchedItems,
|
||||
} from './get_indices';
|
||||
import { getIndices, responseToItemArray } from './get_indices';
|
||||
import { httpServiceMock } from '../../../../core/public/mocks';
|
||||
import { ResolveIndexResponseItemIndexAttrs, MatchedItem } from '../types';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ResolveIndexResponseItemIndexAttrs } from '../types';
|
||||
|
||||
export const successfulResolveResponse = {
|
||||
indices: [
|
||||
|
@ -38,41 +32,8 @@ export const successfulResolveResponse = {
|
|||
],
|
||||
};
|
||||
|
||||
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(successfulResolveResponse);
|
||||
|
@ -83,7 +44,6 @@ describe('getIndices', () => {
|
|||
const result = await getIndices({
|
||||
http,
|
||||
pattern: 'kibana',
|
||||
searchClient: uncalledSearchClient,
|
||||
isRollupIndex,
|
||||
});
|
||||
expect(http.get).toHaveBeenCalled();
|
||||
|
@ -95,42 +55,23 @@ describe('getIndices', () => {
|
|||
|
||||
it('should make two calls in cross cluser case', async () => {
|
||||
http.get.mockResolvedValue(successfulResolveResponse);
|
||||
const result = await getIndices({ http, pattern: '*:kibana', searchClient, isRollupIndex });
|
||||
const result = await getIndices({ http, pattern: '*:kibana', isRollupIndex });
|
||||
|
||||
expect(http.get).toHaveBeenCalled();
|
||||
expect(result.length).toBe(4);
|
||||
expect(result.length).toBe(3);
|
||||
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');
|
||||
expect(result[2].name).toBe('remoteCluster1:bar-01');
|
||||
});
|
||||
|
||||
it('should ignore ccs query-all', async () => {
|
||||
expect((await getIndices({ http, pattern: '*:', searchClient, isRollupIndex })).length).toBe(0);
|
||||
expect((await getIndices({ http, pattern: '*:', isRollupIndex })).length).toBe(0);
|
||||
});
|
||||
|
||||
it('should ignore a single comma', async () => {
|
||||
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);
|
||||
expect((await getIndices({ http, pattern: ',', isRollupIndex })).length).toBe(0);
|
||||
expect((await getIndices({ http, pattern: ',*', isRollupIndex })).length).toBe(0);
|
||||
expect((await getIndices({ http, pattern: ',foobar', isRollupIndex })).length).toBe(0);
|
||||
});
|
||||
|
||||
it('response object to item array', () => {
|
||||
|
@ -162,33 +103,12 @@ describe('getIndices', () => {
|
|||
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 thrown errors gracefully', async () => {
|
||||
http.get.mockImplementationOnce(() => {
|
||||
throw new Error('Test error');
|
||||
});
|
||||
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,
|
||||
});
|
||||
const result = await getIndices({ http, pattern: 'kibana', isRollupIndex });
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,18 +8,11 @@
|
|||
|
||||
import { sortBy } from 'lodash';
|
||||
import { HttpStart } from 'kibana/public';
|
||||
import { map, filter } from 'rxjs/operators';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { Tag, INDEX_PATTERN_TYPE } from '../types';
|
||||
import { MatchedItem, ResolveIndexResponse, ResolveIndexResponseItemIndexAttrs } from '../types';
|
||||
import { MAX_SEARCH_SIZE } from '../constants';
|
||||
|
||||
import {
|
||||
DataPublicPluginStart,
|
||||
IEsSearchResponse,
|
||||
isErrorResponse,
|
||||
isCompleteResponse,
|
||||
} from '../../../data/public';
|
||||
import { IEsSearchResponse } from '../../../data/public';
|
||||
|
||||
const aliasLabel = i18n.translate('indexPatternEditor.aliasLabel', { defaultMessage: 'Alias' });
|
||||
const dataStreamLabel = i18n.translate('indexPatternEditor.dataStreamLabel', {
|
||||
|
@ -78,42 +71,6 @@ export const searchResponseToArray =
|
|||
}
|
||||
};
|
||||
|
||||
export const getIndicesViaSearch = async ({
|
||||
pattern,
|
||||
searchClient,
|
||||
showAllIndices,
|
||||
isRollupIndex,
|
||||
}: {
|
||||
pattern: string;
|
||||
searchClient: DataPublicPluginStart['search']['search'];
|
||||
showAllIndices: boolean;
|
||||
isRollupIndex: (indexName: string) => boolean;
|
||||
}): Promise<MatchedItem[]> =>
|
||||
searchClient({
|
||||
params: {
|
||||
ignoreUnavailable: true,
|
||||
expand_wildcards: showAllIndices ? 'all' : 'open',
|
||||
index: pattern,
|
||||
body: {
|
||||
size: 0, // no hits
|
||||
aggs: {
|
||||
indices: {
|
||||
terms: {
|
||||
field: '_index',
|
||||
size: MAX_SEARCH_SIZE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
.pipe(
|
||||
filter((resp) => isCompleteResponse(resp) || isErrorResponse(resp)),
|
||||
map(searchResponseToArray(getIndexTags(isRollupIndex), showAllIndices))
|
||||
)
|
||||
.toPromise()
|
||||
.catch(() => []);
|
||||
|
||||
export const getIndicesViaResolve = async ({
|
||||
http,
|
||||
pattern,
|
||||
|
@ -137,48 +94,18 @@ export const getIndicesViaResolve = async ({
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Takes two MatchedItem[]s and returns a merged set, with the second set prrioritized over the first based on name
|
||||
*
|
||||
* @param matchedA
|
||||
* @param matchedB
|
||||
*/
|
||||
|
||||
export const dedupeMatchedItems = (matchedA: MatchedItem[], matchedB: MatchedItem[]) => {
|
||||
const mergedMatchedItems = matchedA.reduce((col, item) => {
|
||||
col[item.name] = item;
|
||||
return col;
|
||||
}, {} as Record<string, MatchedItem>);
|
||||
|
||||
matchedB.reduce((col, item) => {
|
||||
col[item.name] = item;
|
||||
return col;
|
||||
}, mergedMatchedItems);
|
||||
|
||||
return Object.values(mergedMatchedItems).sort((a, b) => {
|
||||
if (a.name > b.name) return 1;
|
||||
if (b.name > a.name) return -1;
|
||||
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
|
||||
export async function getIndices({
|
||||
http,
|
||||
pattern: rawPattern = '',
|
||||
showAllIndices = false,
|
||||
searchClient,
|
||||
isRollupIndex,
|
||||
}: {
|
||||
http: HttpStart;
|
||||
pattern: string;
|
||||
showAllIndices?: boolean;
|
||||
searchClient: DataPublicPluginStart['search']['search'];
|
||||
isRollupIndex: (indexName: string) => boolean;
|
||||
}): Promise<MatchedItem[]> {
|
||||
const pattern = rawPattern.trim();
|
||||
const isCCS = pattern.indexOf(':') !== -1;
|
||||
const requests: Array<Promise<MatchedItem[]>> = [];
|
||||
|
||||
// Searching for `*:` fails for CCS environments. The search request
|
||||
// is worthless anyways as the we should only send a request
|
||||
|
@ -198,33 +125,12 @@ export async function getIndices({
|
|||
return [];
|
||||
}
|
||||
|
||||
const promiseResolve = getIndicesViaResolve({
|
||||
return getIndicesViaResolve({
|
||||
http,
|
||||
pattern,
|
||||
showAllIndices,
|
||||
isRollupIndex,
|
||||
}).catch(() => []);
|
||||
requests.push(promiseResolve);
|
||||
|
||||
if (isCCS) {
|
||||
// CCS supports ±1 major version. We won't be able to expect resolve endpoint to exist until v9
|
||||
const promiseSearch = getIndicesViaSearch({
|
||||
pattern,
|
||||
searchClient,
|
||||
showAllIndices,
|
||||
isRollupIndex,
|
||||
}).catch(() => []);
|
||||
requests.push(promiseSearch);
|
||||
}
|
||||
|
||||
const responses = await Promise.all(requests);
|
||||
|
||||
if (responses.length === 2) {
|
||||
const [resolveResponse, searchResponse] = responses;
|
||||
return dedupeMatchedItems(searchResponse, resolveResponse);
|
||||
} else {
|
||||
return responses[0];
|
||||
}
|
||||
}
|
||||
|
||||
export const responseToItemArray = (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue