[SearchProfiler] Handle scenario when user has no indices (#128066)

This commit is contained in:
Alison Goryachev 2022-03-23 11:46:42 -04:00 committed by GitHub
parent c55bb917fa
commit d253355234
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 14 deletions

View file

@ -21,6 +21,16 @@ interface ReturnValue {
error?: string;
}
interface ProfileResponse {
profile?: { shards: ShardSerialized[] };
_shards: {
failed: number;
skipped: number;
total: number;
successful: number;
};
}
const extractProfilerErrorMessage = (e: any): string | undefined => {
if (e.body?.attributes?.error?.reason) {
const { reason, line, col } = e.body.attributes.error;
@ -67,8 +77,7 @@ export const useRequestProfile = () => {
try {
const resp = await http.post<
| { ok: true; resp: { profile: { shards: ShardSerialized[] } } }
| { ok: false; err: { msg: string } }
{ ok: true; resp: ProfileResponse } | { ok: false; err: { msg: string } }
>('../api/searchprofiler/profile', {
body: JSON.stringify(payload),
headers: { 'Content-Type': 'application/json' },
@ -78,7 +87,23 @@ export const useRequestProfile = () => {
return { data: null, error: resp.err.msg };
}
return { data: resp.resp.profile.shards };
// If a user attempts to run Search Profiler without any indices,
// _shards=0 and a "profile" output will not be returned
if (resp.resp._shards.total === 0) {
notifications.addDanger({
'data-test-subj': 'noShardsNotification',
title: i18n.translate('xpack.searchProfiler.errorNoShardsTitle', {
defaultMessage: 'Unable to profile',
}),
text: i18n.translate('xpack.searchProfiler.errorNoShardsDescription', {
defaultMessage: 'Verify your index input matches a valid index',
}),
});
return { data: null };
}
return { data: resp.resp.profile!.shards };
} catch (e) {
const profilerErrorMessage = extractProfilerErrorMessage(e);
if (profilerErrorMessage) {

View file

@ -6,6 +6,7 @@
*/
import expect from '@kbn/expect';
import { asyncForEach } from '@kbn/std';
import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ getPageObjects, getService }: FtrProviderContext) {
@ -14,6 +15,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
const aceEditor = getService('aceEditor');
const retry = getService('retry');
const security = getService('security');
const es = getService('es');
const log = getService('log');
const editorTestSubjectSelector = 'searchProfilerEditor';
@ -34,23 +37,23 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
const okInput = [
`{
"query": {
"match_all": {}`,
"query": {
"match_all": {}`,
`{
"query": {
"match_all": {
"test": """{ "more": "json" }"""`,
"query": {
"match_all": {
"test": """{ "more": "json" }"""`,
];
const notOkInput = [
`{
"query": {
"match_all": {
"test": """{ "more": "json" }""`,
"query": {
"match_all": {
"test": """{ "more": "json" }""`,
`{
"query": {
"match_all": {
"test": """{ "more": "json" }""'`,
"query": {
"match_all": {
"test": """{ "more": "json" }""'`,
];
const expectHasParseErrorsToBe = (expectation: boolean) => async (inputs: string[]) => {
@ -70,5 +73,44 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await expectHasParseErrorsToBe(false)(okInput);
await expectHasParseErrorsToBe(true)(notOkInput);
});
describe('No indices', () => {
before(async () => {
// Delete any existing indices that were not properly cleaned up
try {
const indices = await es.indices.get({
index: '*',
});
const indexNames = Object.keys(indices);
if (indexNames.length > 0) {
await asyncForEach(indexNames, async (indexName) => {
await es.indices.delete({ index: indexName });
});
}
} catch (e) {
log.debug('[Setup error] Error deleting existing indices');
throw e;
}
});
it('returns error if profile is executed with no valid indices', async () => {
const input = {
query: {
match_all: {},
},
};
await aceEditor.setValue(editorTestSubjectSelector, JSON.stringify(input));
await testSubjects.click('profileButton');
await retry.waitFor('notification renders', async () => {
const notification = await testSubjects.find('noShardsNotification');
const notificationText = await notification.getVisibleText();
return notificationText.includes('Unable to profile');
});
});
});
});
}

View file

@ -425,6 +425,14 @@ export default async function ({ readConfigFile }) {
},
global_devtools_read: {
elasticsearch: {
indices: [
{
names: ['*'],
privileges: ['read', 'all'],
},
],
},
kibana: [
{
feature: {