Show aliases in index details (#24048) (#26912)

* Adds aliases to details for indicies.

* Lists aliases when there is more than one.

Fixes reload call using duplicate code atm.
Removes unintentional formatting change.

* Silly line ending removed by accident.

* Simplifies fetching aliases to single method/file.

* Adds superfluous logs statement.

* Uses the correct i18n translation variable for the header.

* Sets the translation variable to the correctly spelled variable.

* Simplifies building an array of aliases.

* Does not export fetchAliases as default.

* Makes the code more readable by destructing results.

* Adds test for expected results and no results.
This commit is contained in:
Bill McConaghy 2018-12-10 15:06:09 -05:00 committed by GitHub
parent 1d3fcaac0a
commit ec145129b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 9 deletions

View file

@ -38,6 +38,9 @@ const HEADERS = {
}),
primary_size: i18n.translate('xpack.idxMgmt.summary.headers.primaryStorageSizeHeader', {
defaultMessage: 'Primary Storage Size',
}),
aliases: i18n.translate('xpack.idxMgmt.summary.headers.aliases', {
defaultMessage: 'Aliases'
})
};
@ -46,10 +49,13 @@ export class Summary extends React.PureComponent {
const { index } = this.props;
return Object.keys(HEADERS).map(fieldName => {
const value = index[fieldName];
const content =
fieldName === "health" ? (
<EuiHealth color={healthToColor(value)}>{value}</EuiHealth>
) : value;
let content = value;
if(fieldName === 'health') {
content = <EuiHealth color={healthToColor(value)}>{value}</EuiHealth>;
}
if(Array.isArray(content)) {
content = content.join(', ');
}
return [
<EuiDescriptionListTitle key={fieldName}>
<strong>{HEADERS[fieldName]}:</strong>

View file

@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export async function fetchAliases(callWithRequest) {
const results = await callWithRequest('cat.aliases', { format: 'json' });
return results.reduce((hash, { index, alias }) => {
(hash[index] = hash[index] || []).push(alias);
return hash;
}, {});
}

View file

@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import sinon from 'sinon';
import { fetchAliases } from './fetch_aliases';
describe('fetching aliases', () => {
const fetchFn = fetchAliases;
test('should return map of aliases for indices', async () => {
const retVal = [
{ index: 'test1Index', alias: 'test1Alias' },
{ index: 'test2Index', alias: 'test1Alias' },
{ index: 'test3Index', alias: 'test2Alias' },
{ index: 'test3Index', alias: 'test3Alias' },
];
const mockCallWithRequest = sinon.spy(() => {return retVal;});
const results = await fetchFn(mockCallWithRequest);
expect(mockCallWithRequest.called);
expect(results).toBeDefined();
expect(results).toMatchObject({
test1Index: ['test1Alias'],
test2Index: ['test1Alias'],
test3Index: ['test2Alias', 'test3Alias'],
});
});
test('should return an empty object if no aliases exist', async () => {
const mockCallWithRequest = sinon.spy(() => {return [];});
const results = await fetchFn(mockCallWithRequest);
expect(mockCallWithRequest.called);
expect(results).toBeDefined();
expect(results).toMatchObject({});
});
});

View file

@ -8,8 +8,9 @@ import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
import { isEsErrorFactory } from '../../../lib/is_es_error_factory';
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory';
import { fetchAliases } from './fetch_aliases';
function formatHits(hits) {
function formatHits(hits, aliases) {
return hits.map(hit => {
return {
health: hit.health,
@ -22,6 +23,7 @@ function formatHits(hits) {
documents_deleted: hit["docs.deleted"],
size: hit["store.size"],
primary_size: hit["pri.store.size"],
aliases: aliases.hasOwnProperty(hit.index) ? aliases[hit.index] : 'none',
};
});
}
@ -45,8 +47,9 @@ export function registerListRoute(server) {
const callWithRequest = callWithRequestFactory(server, request);
try {
const aliases = await fetchAliases(callWithRequest);
const hits = await fetchIndices(callWithRequest);
const response = formatHits(hits);
const response = formatHits(hits, aliases);
return response;
} catch (err) {
if (isEsError(err)) {

View file

@ -8,12 +8,13 @@ import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
import { isEsErrorFactory } from '../../../lib/is_es_error_factory';
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory';
import { fetchAliases } from './fetch_aliases';
function getIndexNamesFromPayload(payload) {
return payload.indexNames || [];
}
function formatHits(hits) {
function formatHits(hits, aliases) {
return hits.map(hit => {
return {
health: hit.health,
@ -26,6 +27,7 @@ function formatHits(hits) {
documents_deleted: hit["docs.deleted"],
size: hit["store.size"],
primary_size: hit["pri.store.size"],
aliases: aliases.hasOwnProperty(hit.index) ? aliases[hit.index] : 'none',
};
});
}
@ -51,8 +53,9 @@ export function registerReloadRoute(server) {
const indexNames = getIndexNamesFromPayload(request.payload);
try {
const hits = await fetchIndices(callWithRequest, indexNames);
const response = formatHits(hits);
const indices = await fetchIndices(callWithRequest, indexNames);
const aliases = await fetchAliases(callWithRequest);
const response = formatHits(indices, aliases);
return response;
} catch (err) {
if (isEsError(err)) {