From 8b0d5f54dd701f0f5a9b36d2a8a1a27cffbdb6e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Mon, 23 Dec 2019 16:44:57 +0100 Subject: [PATCH] [APM] Fix missing apm indicies (#53541) * [APM] Fix missing apm indicies * Fix infinite loop in ui indices * Add test for empty settings --- .../app/Settings/ApmIndices/index.test.tsx | 35 ++++++++++++++++++ .../app/Settings/ApmIndices/index.tsx | 5 ++- .../apm_indices/save_apm_indices.test.ts | 37 +++++++++++++++++++ .../settings/apm_indices/save_apm_indices.ts | 13 ++++++- 4 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.test.tsx create mode 100644 x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.test.ts diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.test.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.test.tsx new file mode 100644 index 00000000000000..fd71bf9709ce93 --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.test.tsx @@ -0,0 +1,35 @@ +/* + * 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 { render, wait } from '@testing-library/react'; +import React from 'react'; +import { ApmIndices } from '.'; +import { MockApmPluginContextWrapper } from '../../../../utils/testHelpers'; +import * as hooks from '../../../../hooks/useFetcher'; + +describe('ApmIndices', () => { + it('should not get stuck in infinite loop', async () => { + spyOn(hooks, 'useFetcher').and.returnValue({ + data: undefined, + status: 'loading' + }); + const { getByText } = render( + + + + ); + + expect(getByText('Indices')).toMatchInlineSnapshot(` +

+ Indices +

+ `); + + await wait(); + }); +}); diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx index ba68e1726d2b41..14670fe1885f64 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx @@ -85,6 +85,9 @@ async function saveApmIndices({ clearCache(); } +// avoid infinite loop by initializing the state outside the component +const INITIAL_STATE = [] as []; + export function ApmIndices() { const { toasts } = useApmPluginContext().core.notifications; @@ -93,7 +96,7 @@ export function ApmIndices() { const callApmApiFromHook = useCallApmApi(); - const { data = [], status, refetch } = useFetcher( + const { data = INITIAL_STATE, status, refetch } = useFetcher( callApmApi => callApmApi({ pathname: `/api/apm/settings/apm-index-settings` }), [] diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.test.ts b/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.test.ts new file mode 100644 index 00000000000000..6567736996502d --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.test.ts @@ -0,0 +1,37 @@ +/* + * 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 { saveApmIndices } from './save_apm_indices'; + +describe('saveApmIndices', () => { + it('should trim and strip empty settings', async () => { + const context = { + core: { + savedObjects: { + client: { + create: jest.fn() + } + } + } + } as any; + + const apmIndices = { + settingA: 'aa', + settingB: '', + settingC: undefined, + settingD: null, + settingE: ' ', + settingF: 'ff', + settingG: ' gg ' + } as any; + await saveApmIndices(context, apmIndices); + expect(context.core.savedObjects.client.create).toHaveBeenCalledWith( + expect.any(String), + { settingA: 'aa', settingF: 'ff', settingG: 'gg' }, + expect.any(Object) + ); + }); +}); diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.ts b/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.ts index 2fdfd79ce933b4..4b68b248d80319 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.ts @@ -13,14 +13,23 @@ import { APMRequestHandlerContext } from '../../../routes/typings'; export async function saveApmIndices( context: APMRequestHandlerContext, - apmIndicesSavedObject: Partial + apmIndices: Partial ) { return await context.core.savedObjects.client.create( APM_INDICES_SAVED_OBJECT_TYPE, - apmIndicesSavedObject, + removeEmpty(apmIndices), { id: APM_INDICES_SAVED_OBJECT_ID, overwrite: true } ); } + +// remove empty/undefined values +function removeEmpty(apmIndices: Partial) { + return Object.fromEntries( + Object.entries(apmIndices) + .map(([key, value]) => [key, value?.trim()]) + .filter(([key, value]) => !!value) + ); +}