mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[APM] Make UI indices space aware (support for spaces) (#126176)
* new apm indices saved object * adding some comments * fixing typo * addressing PR comments * fixing tests * addressing PR comments * fixing tests * fixing test * showing callout with space name * addressing PR changes
This commit is contained in:
parent
43a2622b97
commit
4e238ecbe5
11 changed files with 397 additions and 68 deletions
|
@ -8,9 +8,9 @@
|
|||
// the types have to match the names of the saved object mappings
|
||||
// in /x-pack/plugins/apm/mappings.json
|
||||
|
||||
// APM indices
|
||||
export const APM_INDICES_SAVED_OBJECT_TYPE = 'apm-indices';
|
||||
export const APM_INDICES_SAVED_OBJECT_ID = 'apm-indices';
|
||||
// APM index settings
|
||||
export const APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE = 'apm-indices';
|
||||
export const APM_INDEX_SETTINGS_SAVED_OBJECT_ID = 'apm-indices';
|
||||
|
||||
// APM telemetry
|
||||
export const APM_TELEMETRY_SAVED_OBJECT_TYPE = 'apm-telemetry';
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { ApmIndices } from '.';
|
||||
import * as hooks from '../../../../hooks/use_fetcher';
|
||||
import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context';
|
||||
|
||||
describe('ApmIndices', () => {
|
||||
it('should not get stuck in infinite loop', () => {
|
||||
const spy = jest.spyOn(hooks, 'useFetcher').mockReturnValue({
|
||||
data: undefined,
|
||||
status: hooks.FETCH_STATUS.LOADING,
|
||||
refetch: jest.fn(),
|
||||
});
|
||||
const { getByText } = render(
|
||||
<MockApmPluginContextWrapper>
|
||||
<ApmIndices />
|
||||
</MockApmPluginContextWrapper>
|
||||
);
|
||||
|
||||
expect(getByText('Indices')).toMatchInlineSnapshot(`
|
||||
<h2
|
||||
class="euiTitle euiTitle--small"
|
||||
>
|
||||
Indices
|
||||
</h2>
|
||||
`);
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
|
@ -8,6 +8,7 @@
|
|||
import {
|
||||
EuiButton,
|
||||
EuiButtonEmpty,
|
||||
EuiCallOut,
|
||||
EuiFieldText,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
|
@ -19,9 +20,12 @@ import {
|
|||
EuiToolTip,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
|
||||
import { useFetcher } from '../../../../hooks/use_fetcher';
|
||||
import { ApmPluginStartDeps } from '../../../../plugin';
|
||||
import { clearCache } from '../../../../services/rest/call_api';
|
||||
import {
|
||||
APIReturnType,
|
||||
|
@ -93,6 +97,8 @@ const INITIAL_STATE: ApiResponse = { apmIndexSettings: [] };
|
|||
|
||||
export function ApmIndices() {
|
||||
const { core } = useApmPluginContext();
|
||||
const { services } = useKibana<ApmPluginStartDeps>();
|
||||
|
||||
const { notifications, application } = core;
|
||||
const canSave = application.capabilities.apm.save;
|
||||
|
||||
|
@ -108,6 +114,10 @@ export function ApmIndices() {
|
|||
[canSave]
|
||||
);
|
||||
|
||||
const { data: space } = useFetcher(() => {
|
||||
return services.spaces?.getActiveSpace();
|
||||
}, [services.spaces]);
|
||||
|
||||
useEffect(() => {
|
||||
setApmIndices(
|
||||
data.apmIndexSettings.reduce(
|
||||
|
@ -191,6 +201,31 @@ export function ApmIndices() {
|
|||
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
{space?.name && (
|
||||
<>
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiCallOut
|
||||
color="primary"
|
||||
iconType="spacesApp"
|
||||
title={
|
||||
<EuiText size="s">
|
||||
<FormattedMessage
|
||||
id="xpack.apm.settings.apmIndices.spaceDescription"
|
||||
defaultMessage="The index settings apply to the {spaceName} space."
|
||||
values={{
|
||||
spaceName: <strong>{space?.name}</strong>,
|
||||
}}
|
||||
/>
|
||||
</EuiText>
|
||||
}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size="m" />
|
||||
</>
|
||||
)}
|
||||
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiForm>
|
||||
|
|
|
@ -53,6 +53,7 @@ import { getLazyAPMPolicyCreateExtension } from './components/fleet_integration/
|
|||
import { getLazyAPMPolicyEditExtension } from './components/fleet_integration/lazy_apm_policy_edit_extension';
|
||||
import { featureCatalogueEntry } from './feature_catalogue_entry';
|
||||
import type { SecurityPluginStart } from '../../security/public';
|
||||
import { SpacesPluginStart } from '../../spaces/public';
|
||||
|
||||
export type ApmPluginSetup = ReturnType<ApmPlugin['setup']>;
|
||||
|
||||
|
@ -82,6 +83,7 @@ export interface ApmPluginStartDeps {
|
|||
observability: ObservabilityPublicStart;
|
||||
fleet?: FleetStart;
|
||||
security?: SecurityPluginStart;
|
||||
spaces?: SpacesPluginStart;
|
||||
}
|
||||
|
||||
const servicesTitle = i18n.translate('xpack.apm.navigation.servicesTitle', {
|
||||
|
|
|
@ -48,6 +48,7 @@ import {
|
|||
TRANSACTION_TYPE,
|
||||
} from '../common/elasticsearch_fieldnames';
|
||||
import { tutorialProvider } from './tutorial';
|
||||
import { migrateLegacyAPMIndicesToSpaceAware } from './saved_objects/migrations/migrate_legacy_apm_indices_to_space_aware';
|
||||
|
||||
export class APMPlugin
|
||||
implements
|
||||
|
@ -247,6 +248,11 @@ export class APMPlugin
|
|||
config: this.currentConfig,
|
||||
logger: this.logger,
|
||||
});
|
||||
|
||||
migrateLegacyAPMIndicesToSpaceAware({
|
||||
coreStart: core,
|
||||
logger: this.logger,
|
||||
});
|
||||
}
|
||||
|
||||
public stop() {}
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
|
||||
import { SavedObjectsClient } from 'src/core/server';
|
||||
import {
|
||||
APM_INDICES_SAVED_OBJECT_TYPE,
|
||||
APM_INDICES_SAVED_OBJECT_ID,
|
||||
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
|
||||
APM_INDEX_SETTINGS_SAVED_OBJECT_ID,
|
||||
} from '../../../../common/apm_saved_object_constants';
|
||||
import { APMConfig } from '../../..';
|
||||
import { APMRouteHandlerResources } from '../../typings';
|
||||
import { withApmSpan } from '../../../utils/with_apm_span';
|
||||
import { ApmIndicesConfig } from '../../../../../observability/common/typings';
|
||||
import { APMIndices } from '../../../saved_objects/apm_indices';
|
||||
|
||||
export type { ApmIndicesConfig };
|
||||
|
||||
|
@ -22,13 +23,15 @@ type ISavedObjectsClient = Pick<SavedObjectsClient, 'get'>;
|
|||
async function getApmIndicesSavedObject(
|
||||
savedObjectsClient: ISavedObjectsClient
|
||||
) {
|
||||
const apmIndices = await withApmSpan('get_apm_indices_saved_object', () =>
|
||||
savedObjectsClient.get<Partial<ApmIndicesConfig>>(
|
||||
APM_INDICES_SAVED_OBJECT_TYPE,
|
||||
APM_INDICES_SAVED_OBJECT_ID
|
||||
)
|
||||
const apmIndicesSavedObject = await withApmSpan(
|
||||
'get_apm_indices_saved_object',
|
||||
() =>
|
||||
savedObjectsClient.get<Partial<APMIndices>>(
|
||||
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
|
||||
APM_INDEX_SETTINGS_SAVED_OBJECT_ID
|
||||
)
|
||||
);
|
||||
return apmIndices.attributes;
|
||||
return apmIndicesSavedObject.attributes.apmIndices;
|
||||
}
|
||||
|
||||
export function getApmIndicesConfig(config: APMConfig): ApmIndicesConfig {
|
||||
|
@ -90,6 +93,6 @@ export async function getApmIndexSettings({
|
|||
return apmIndices.map((configurationName) => ({
|
||||
configurationName,
|
||||
defaultValue: apmIndicesConfig[configurationName], // value defined in kibana[.dev].yml
|
||||
savedValue: apmIndicesSavedObject[configurationName], // value saved via Saved Objects service
|
||||
savedValue: apmIndicesSavedObject?.[configurationName], // value saved via Saved Objects service
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -26,7 +26,10 @@ describe('saveApmIndices', () => {
|
|||
await saveApmIndices(savedObjectsClient, apmIndices);
|
||||
expect(savedObjectsClient.create).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
{ settingA: 'aa', settingF: 'ff', settingG: 'gg' },
|
||||
{
|
||||
apmIndices: { settingA: 'aa', settingF: 'ff', settingG: 'gg' },
|
||||
isSpaceAware: true,
|
||||
},
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
|
||||
import { SavedObjectsClientContract } from '../../../../../../../src/core/server';
|
||||
import {
|
||||
APM_INDICES_SAVED_OBJECT_TYPE,
|
||||
APM_INDICES_SAVED_OBJECT_ID,
|
||||
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
|
||||
APM_INDEX_SETTINGS_SAVED_OBJECT_ID,
|
||||
} from '../../../../common/apm_saved_object_constants';
|
||||
import { APMIndices } from '../../../saved_objects/apm_indices';
|
||||
import { withApmSpan } from '../../../utils/with_apm_span';
|
||||
import { ApmIndicesConfig } from './get_apm_indices';
|
||||
|
||||
|
@ -18,13 +19,10 @@ export function saveApmIndices(
|
|||
apmIndices: Partial<ApmIndicesConfig>
|
||||
) {
|
||||
return withApmSpan('save_apm_indices', () =>
|
||||
savedObjectsClient.create(
|
||||
APM_INDICES_SAVED_OBJECT_TYPE,
|
||||
removeEmpty(apmIndices),
|
||||
{
|
||||
id: APM_INDICES_SAVED_OBJECT_ID,
|
||||
overwrite: true,
|
||||
}
|
||||
savedObjectsClient.create<APMIndices>(
|
||||
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
|
||||
{ apmIndices: removeEmpty(apmIndices), isSpaceAware: true },
|
||||
{ id: APM_INDEX_SETTINGS_SAVED_OBJECT_ID, overwrite: true }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,20 +10,43 @@ import { i18n } from '@kbn/i18n';
|
|||
import { updateApmOssIndexPaths } from './migrations/update_apm_oss_index_paths';
|
||||
import { ApmIndicesConfigName } from '..';
|
||||
|
||||
const properties: { [Property in ApmIndicesConfigName]: { type: 'keyword' } } =
|
||||
{
|
||||
sourcemap: { type: 'keyword' },
|
||||
error: { type: 'keyword' },
|
||||
onboarding: { type: 'keyword' },
|
||||
span: { type: 'keyword' },
|
||||
transaction: { type: 'keyword' },
|
||||
metric: { type: 'keyword' },
|
||||
export interface APMIndices {
|
||||
apmIndices?: {
|
||||
sourcemap?: string;
|
||||
error?: string;
|
||||
onboarding?: string;
|
||||
span?: string;
|
||||
transaction?: string;
|
||||
metric?: string;
|
||||
};
|
||||
isSpaceAware?: boolean;
|
||||
}
|
||||
|
||||
const properties: {
|
||||
apmIndices: {
|
||||
properties: {
|
||||
[Property in ApmIndicesConfigName]: { type: 'keyword' };
|
||||
};
|
||||
};
|
||||
isSpaceAware: { type: 'boolean' };
|
||||
} = {
|
||||
apmIndices: {
|
||||
properties: {
|
||||
sourcemap: { type: 'keyword' },
|
||||
error: { type: 'keyword' },
|
||||
onboarding: { type: 'keyword' },
|
||||
span: { type: 'keyword' },
|
||||
transaction: { type: 'keyword' },
|
||||
metric: { type: 'keyword' },
|
||||
},
|
||||
},
|
||||
isSpaceAware: { type: 'boolean' },
|
||||
};
|
||||
|
||||
export const apmIndices: SavedObjectsType = {
|
||||
name: 'apm-indices',
|
||||
hidden: false,
|
||||
namespaceType: 'agnostic',
|
||||
namespaceType: 'single',
|
||||
mappings: { properties },
|
||||
management: {
|
||||
importableAndExportable: true,
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import type { CoreStart, Logger } from 'src/core/server';
|
||||
import {
|
||||
APM_INDEX_SETTINGS_SAVED_OBJECT_ID,
|
||||
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
|
||||
} from '../../../common/apm_saved_object_constants';
|
||||
import { migrateLegacyAPMIndicesToSpaceAware } from './migrate_legacy_apm_indices_to_space_aware';
|
||||
|
||||
const loggerMock = {
|
||||
debug: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
error: jest.fn(),
|
||||
} as unknown as Logger;
|
||||
|
||||
describe('migrateLegacyAPMIndicesToSpaceAware', () => {
|
||||
describe('when legacy APM indices is not found', () => {
|
||||
const mockBulkCreate = jest.fn();
|
||||
const mockCreate = jest.fn();
|
||||
const mockFind = jest.fn();
|
||||
const core = {
|
||||
savedObjects: {
|
||||
createInternalRepository: jest.fn().mockReturnValue({
|
||||
get: () => {
|
||||
throw new Error('BOOM');
|
||||
},
|
||||
find: mockFind,
|
||||
bulkCreate: mockBulkCreate,
|
||||
create: mockCreate,
|
||||
}),
|
||||
},
|
||||
} as unknown as CoreStart;
|
||||
|
||||
it('does not save any new saved object', () => {
|
||||
migrateLegacyAPMIndicesToSpaceAware({
|
||||
coreStart: core,
|
||||
logger: loggerMock,
|
||||
});
|
||||
expect(mockFind).not.toHaveBeenCalled();
|
||||
expect(mockBulkCreate).not.toHaveBeenCalled();
|
||||
expect(mockCreate).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when only default space is available', () => {
|
||||
const mockBulkCreate = jest.fn();
|
||||
const mockCreate = jest.fn();
|
||||
const mockSpaceFind = jest.fn().mockReturnValue({
|
||||
page: 1,
|
||||
per_page: 10000,
|
||||
total: 3,
|
||||
saved_objects: [
|
||||
{
|
||||
type: 'space',
|
||||
id: 'default',
|
||||
attributes: {
|
||||
name: 'Default',
|
||||
},
|
||||
references: [],
|
||||
migrationVersion: {
|
||||
space: '6.6.0',
|
||||
},
|
||||
coreMigrationVersion: '8.2.0',
|
||||
updated_at: '2022-02-22T14:13:28.839Z',
|
||||
version: 'WzI4OSwxXQ==',
|
||||
score: 0,
|
||||
},
|
||||
],
|
||||
});
|
||||
const core = {
|
||||
savedObjects: {
|
||||
createInternalRepository: jest.fn().mockReturnValue({
|
||||
get: jest.fn().mockReturnValue({
|
||||
id: 'apm-indices',
|
||||
type: 'apm-indices',
|
||||
namespaces: [],
|
||||
updated_at: '2022-02-22T14:17:10.584Z',
|
||||
version: 'WzE1OSwxXQ==',
|
||||
attributes: {
|
||||
transaction: 'default-apm-*',
|
||||
span: 'default-apm-*',
|
||||
error: 'default-apm-*',
|
||||
metric: 'default-apm-*',
|
||||
sourcemap: 'default-apm-*',
|
||||
onboarding: 'default-apm-*',
|
||||
},
|
||||
references: [],
|
||||
migrationVersion: {
|
||||
'apm-indices': '7.16.0',
|
||||
},
|
||||
coreMigrationVersion: '8.2.0',
|
||||
}),
|
||||
find: mockSpaceFind,
|
||||
bulkCreate: mockBulkCreate,
|
||||
create: mockCreate,
|
||||
}),
|
||||
},
|
||||
} as unknown as CoreStart;
|
||||
it('creates new default saved object with space awareness and delete legacy', async () => {
|
||||
await migrateLegacyAPMIndicesToSpaceAware({
|
||||
coreStart: core,
|
||||
logger: loggerMock,
|
||||
});
|
||||
expect(mockCreate).toBeCalledWith(
|
||||
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
|
||||
{
|
||||
apmIndices: {
|
||||
transaction: 'default-apm-*',
|
||||
span: 'default-apm-*',
|
||||
error: 'default-apm-*',
|
||||
metric: 'default-apm-*',
|
||||
sourcemap: 'default-apm-*',
|
||||
onboarding: 'default-apm-*',
|
||||
},
|
||||
isSpaceAware: true,
|
||||
},
|
||||
{
|
||||
id: APM_INDEX_SETTINGS_SAVED_OBJECT_ID,
|
||||
overwrite: true,
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when multiple spaces are found', () => {
|
||||
const mockBulkCreate = jest.fn();
|
||||
const mockCreate = jest.fn();
|
||||
|
||||
const savedObjects = [
|
||||
{ id: 'default', name: 'Default' },
|
||||
{ id: 'space-a', name: 'Space A' },
|
||||
{ id: 'space-b', name: 'Space B' },
|
||||
];
|
||||
const mockSpaceFind = jest.fn().mockReturnValue({
|
||||
page: 1,
|
||||
per_page: 10000,
|
||||
total: 3,
|
||||
saved_objects: savedObjects.map(({ id, name }) => {
|
||||
return {
|
||||
type: 'space',
|
||||
id,
|
||||
attributes: { name },
|
||||
references: [],
|
||||
migrationVersion: { space: '6.6.0' },
|
||||
coreMigrationVersion: '8.2.0',
|
||||
updated_at: '2022-02-22T14:13:28.839Z',
|
||||
version: 'WzI4OSwxXQ==',
|
||||
score: 0,
|
||||
};
|
||||
}),
|
||||
});
|
||||
const attributes = {
|
||||
transaction: 'space-apm-*',
|
||||
span: 'space-apm-*',
|
||||
error: 'space-apm-*',
|
||||
metric: 'space-apm-*',
|
||||
sourcemap: 'space-apm-*',
|
||||
onboarding: 'space-apm-*',
|
||||
};
|
||||
const core = {
|
||||
savedObjects: {
|
||||
createInternalRepository: jest.fn().mockReturnValue({
|
||||
get: jest.fn().mockReturnValue({
|
||||
id: 'apm-indices',
|
||||
type: 'apm-indices',
|
||||
namespaces: [],
|
||||
updated_at: '2022-02-22T14:17:10.584Z',
|
||||
version: 'WzE1OSwxXQ==',
|
||||
attributes,
|
||||
references: [],
|
||||
migrationVersion: {
|
||||
'apm-indices': '7.16.0',
|
||||
},
|
||||
coreMigrationVersion: '8.2.0',
|
||||
}),
|
||||
find: mockSpaceFind,
|
||||
bulkCreate: mockBulkCreate,
|
||||
create: mockCreate,
|
||||
}),
|
||||
},
|
||||
} as unknown as CoreStart;
|
||||
it('creates multiple saved objects with space awareness and delete legacies', async () => {
|
||||
await migrateLegacyAPMIndicesToSpaceAware({
|
||||
coreStart: core,
|
||||
logger: loggerMock,
|
||||
});
|
||||
expect(mockCreate).toBeCalled();
|
||||
expect(mockBulkCreate).toBeCalledWith(
|
||||
savedObjects
|
||||
.filter(({ id }) => id !== 'default')
|
||||
.map(({ id }) => {
|
||||
return {
|
||||
type: APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
|
||||
id: APM_INDEX_SETTINGS_SAVED_OBJECT_ID,
|
||||
initialNamespaces: [id],
|
||||
attributes: { apmIndices: attributes, isSpaceAware: true },
|
||||
};
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import type {
|
||||
CoreStart,
|
||||
Logger,
|
||||
ISavedObjectsRepository,
|
||||
} from 'src/core/server';
|
||||
import { SavedObjectsErrorHelpers } from '../../../../../../src/core/server';
|
||||
import {
|
||||
APM_INDEX_SETTINGS_SAVED_OBJECT_ID,
|
||||
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
|
||||
} from '../../../common/apm_saved_object_constants';
|
||||
import { ApmIndicesConfig } from '../../routes/settings/apm_indices/get_apm_indices';
|
||||
import { APMIndices } from '../apm_indices';
|
||||
|
||||
async function fetchLegacyAPMIndices(repository: ISavedObjectsRepository) {
|
||||
try {
|
||||
const apmIndices = await repository.get<
|
||||
Partial<ApmIndicesConfig & { isSpaceAware: boolean }>
|
||||
>(APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE, APM_INDEX_SETTINGS_SAVED_OBJECT_ID);
|
||||
if (apmIndices.attributes.isSpaceAware) {
|
||||
// This has already been migrated to become space-aware
|
||||
return null;
|
||||
}
|
||||
return apmIndices;
|
||||
} catch (err) {
|
||||
if (SavedObjectsErrorHelpers.isNotFoundError(err)) {
|
||||
// This can happen if APM is not being used
|
||||
return null;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export async function migrateLegacyAPMIndicesToSpaceAware({
|
||||
coreStart,
|
||||
logger,
|
||||
}: {
|
||||
coreStart: CoreStart;
|
||||
logger: Logger;
|
||||
}) {
|
||||
const repository = coreStart.savedObjects.createInternalRepository(['space']);
|
||||
try {
|
||||
// Fetch legacy APM indices
|
||||
const legacyAPMIndices = await fetchLegacyAPMIndices(repository);
|
||||
|
||||
if (legacyAPMIndices === null) {
|
||||
return;
|
||||
}
|
||||
// Fetch spaces available
|
||||
const spaces = await repository.find({
|
||||
type: 'space',
|
||||
page: 1,
|
||||
perPage: 10_000, // max number of spaces as of 8.2
|
||||
fields: ['name'], // to avoid fetching *all* fields
|
||||
});
|
||||
|
||||
const savedObjectAttributes: APMIndices = {
|
||||
apmIndices: legacyAPMIndices.attributes,
|
||||
isSpaceAware: true,
|
||||
};
|
||||
|
||||
// Calls create first to update the default space setting isSpaceAware to true
|
||||
await repository.create<
|
||||
Partial<ApmIndicesConfig & { isSpaceAware: boolean }>
|
||||
>(APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE, savedObjectAttributes, {
|
||||
id: APM_INDEX_SETTINGS_SAVED_OBJECT_ID,
|
||||
overwrite: true,
|
||||
});
|
||||
|
||||
// Create new APM indices space aware for all spaces available
|
||||
await repository.bulkCreate<Partial<APMIndices>>(
|
||||
spaces.saved_objects
|
||||
// Skip default space since it was already updated
|
||||
.filter(({ id: spaceId }) => spaceId !== 'default')
|
||||
.map(({ id: spaceId }) => ({
|
||||
id: APM_INDEX_SETTINGS_SAVED_OBJECT_ID,
|
||||
type: APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
|
||||
initialNamespaces: [spaceId],
|
||||
attributes: savedObjectAttributes,
|
||||
}))
|
||||
);
|
||||
} catch (e) {
|
||||
logger.error('Failed to migrate legacy APM indices object: ' + e.message);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue