Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Logs] Provide help for migrating Logs UI settings #189646

Merged
merged 13 commits into from
Aug 14, 2024
Merged
1 change: 1 addition & 0 deletions .buildkite/ftr_oblt_stateful_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ defaultQueue: 'n2-4-spot'
enabled:
- x-pack/test/alerting_api_integration/observability/config.ts
- x-pack/test/api_integration/apis/logs_ui/config.ts
- x-pack/test/api_integration/apis/logs_shared/config.ts
- x-pack/test/api_integration/apis/metrics_ui/config.ts
- x-pack/test/api_integration/apis/osquery/config.ts
- x-pack/test/api_integration/apis/synthetics/config.ts
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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.
*/

export const MIGRATE_LOG_VIEW_SETTINGS_URL =
'/api/logs_shared/deprecations/migrate_log_view_settings';
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 { LogsSharedPluginCoreSetup } from '../types';
import { getLogSourcesSettingDeprecationInfo } from './log_sources_setting';

export const registerDeprecations = ({ core }: { core: LogsSharedPluginCoreSetup }) => {
core.deprecations.registerDeprecations({
getDeprecations: async (context) => {
return [
...(await getLogSourcesSettingDeprecationInfo({
context,
getStartServices: core.getStartServices,
})),
];
},
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* 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 { DeprecationsDetails } from '@kbn/core-deprecations-common';
import { GetDeprecationsContext } from '@kbn/core-deprecations-server';
import { i18n } from '@kbn/i18n';
import { defaultLogViewId } from '../../common/log_views';
import { MIGRATE_LOG_VIEW_SETTINGS_URL } from '../../common/http_api/deprecations';
import { logSourcesKibanaAdvancedSettingRT } from '../../common';
import { LogsSharedPluginStartServicesAccessor } from '../types';

export const getLogSourcesSettingDeprecationInfo = async ({
getStartServices,
context,
}: {
context: GetDeprecationsContext;
getStartServices: LogsSharedPluginStartServicesAccessor;
}): Promise<DeprecationsDetails[]> => {
const [_, pluginStartDeps, pluginStart] = await getStartServices();
const logSourcesService =
pluginStartDeps.logsDataAccess.services.logSourcesServiceFactory.getLogSourcesService(
context.savedObjectsClient
);
const logViewsClient = pluginStart.logViews.getClient(
context.savedObjectsClient,
context.esClient.asCurrentUser,
logSourcesService
);

const logView = await logViewsClient.getLogView(defaultLogViewId);

if (logView && !logSourcesKibanaAdvancedSettingRT.is(logView.attributes.logIndices)) {
return [
{
title: i18n.translate(
'xpack.logsShared.deprecations.migrateLogViewSettingsToLogSourcesSetting.title',
{
defaultMessage: 'Log sources setting',
}
),
level: 'warning',
deprecationType: 'feature',
message: i18n.translate(
'xpack.logsShared.deprecations.migrateLogViewSettingsToLogSourcesSetting.message',
{
defaultMessage:
'Indices and Data view options previously provided via the Logs UI settings page are now deprecated. Please migrate to using the Kibana log sources advanced setting.',
}
),
correctiveActions: {
manualSteps: [
i18n.translate(
'xpack.logsShared.deprecations.migrateLogViewSettingsToLogSourcesSetting.message.manualStepMessage',
{
defaultMessage:
'Update the Log sources Kibana advanced setting (via Management > Advanced Settings) to match the setting previously provided via the Logs UI settings page. Then via the Logs UI settings page use the Kibana log sources advanced setting option.',
}
),
],
api: {
method: 'PUT',
path: MIGRATE_LOG_VIEW_SETTINGS_URL,
},
},
},
];
} else {
return [];
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import {
initLogEntriesSummaryRoute,
} from './routes/log_entries';
import { initLogViewRoutes } from './routes/log_views';
import { initMigrateLogViewSettingsRoute } from './routes/deprecations';

export const initLogsSharedServer = (libs: LogsSharedBackendLibs) => {
initLogEntriesHighlightsRoute(libs);
initLogEntriesSummaryRoute(libs);
initLogEntriesSummaryHighlightsRoute(libs);
initLogViewRoutes(libs);
initMigrateLogViewSettingsRoute(libs);
};
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import { LogsSharedLogEntriesDomain } from './lib/domains/log_entries_domain';
import { LogsSharedKibanaLogEntriesAdapter } from './lib/adapters/log_entries/kibana_log_entries_adapter';
import { LogEntriesService } from './services/log_entries';
import { LogsSharedConfig } from '../common/plugin_config';
import { registerDeprecations } from './deprecations';
import { defaultLogViewId } from '../common/log_views';

export class LogsSharedPlugin
implements
Expand Down Expand Up @@ -58,7 +60,7 @@ export class LogsSharedPlugin
core.savedObjects.registerType(logViewSavedObjectType);
} else {
// Register a static internal view to use as a fallback when the log view SO is not registered
logViews.defineInternalLogView('default', {});
logViews.defineInternalLogView(defaultLogViewId, {});
}

const domainLibs: LogsSharedDomainLibs = {
Expand All @@ -84,6 +86,8 @@ export class LogsSharedPlugin
const logEntriesService = new LogEntriesService();
logEntriesService.setup(core, plugins);

registerDeprecations({ core });

return {
...domainLibs,
logViews,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/

export * from './migrate_log_view_settings';
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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 { defaultLogViewId } from '../../../common/log_views';
import { MIGRATE_LOG_VIEW_SETTINGS_URL } from '../../../common/http_api/deprecations';
import { logSourcesKibanaAdvancedSettingRT } from '../../../common';
import { LogsSharedBackendLibs } from '../../lib/logs_shared_types';

// This route facilitates automated one-click handling of updating log view's to use the
// Kibana advanced setting as part of the upgrade assistant.
// First, it will gather the indices currently set on the log view.
// Secondly, it will update the advanced setting to use these indices.
// Lastly, it will update the log view to use the kibana advanced setting.
export const initMigrateLogViewSettingsRoute = ({
framework,
getStartServices,
}: LogsSharedBackendLibs) => {
framework.router.put(
{ path: MIGRATE_LOG_VIEW_SETTINGS_URL, validate: false },
async (context, request, response) => {
try {
const [_, pluginStartDeps, pluginStart] = await getStartServices();

const logSourcesService =
await pluginStartDeps.logsDataAccess.services.logSourcesServiceFactory.getScopedLogSourcesService(
request
);
const logViewsClient = pluginStart.logViews.getScopedClient(request);

const logView = await logViewsClient.getLogView(defaultLogViewId);

if (!logView || logSourcesKibanaAdvancedSettingRT.is(logView.attributes.logIndices)) {
return response.customError({
body: new Error(
"Unable to migrate log view settings. A log view either doesn't exist or is already using the Kibana advanced setting."
),
statusCode: 400,
});
}

const indices = (
await logViewsClient.getResolvedLogView({
type: 'log-view-reference',
logViewId: defaultLogViewId,
})
).indices;

await logSourcesService.setLogSources([{ indexPattern: indices }]);
await logViewsClient.putLogView(defaultLogViewId, {
logIndices: { type: 'kibana_advanced_setting' },
});
Kerry350 marked this conversation as resolved.
Show resolved Hide resolved
return response.ok();
} catch (error) {
throw error;
}
}
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,7 @@
"@kbn/test-jest-helpers",
"@kbn/router-utils",
"@kbn/logs-data-access-plugin",
"@kbn/core-deprecations-common",
"@kbn/core-deprecations-server",
]
}
17 changes: 17 additions & 0 deletions x-pack/test/api_integration/apis/logs_shared/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* 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 { FtrConfigProviderContext } from '@kbn/test';

export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts'));

return {
...baseIntegrationTestsConfig.getAll(),
testFiles: [require.resolve('.')],
};
}
14 changes: 14 additions & 0 deletions x-pack/test/api_integration/apis/logs_shared/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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 { FtrProviderContext } from '../../ftr_provider_context';

export default function ({ loadTestFile }: FtrProviderContext) {
describe('Logs shared routes', () => {
loadTestFile(require.resolve('./migrate_log_view_settings'));
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* 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 expect from '@kbn/expect';
import { LogViewAttributes } from '@kbn/logs-shared-plugin/common/log_views';
import { infraSourceConfigurationSavedObjectName } from '@kbn/infra-plugin/server/lib/sources';
import { logViewSavedObjectName } from '@kbn/logs-shared-plugin/server';
import { defaultLogViewId } from '@kbn/logs-shared-plugin/common/log_views';
import { MIGRATE_LOG_VIEW_SETTINGS_URL } from '@kbn/logs-shared-plugin/common/http_api/deprecations';
import { OBSERVABILITY_LOGS_DATA_ACCESS_LOG_SOURCES_ID } from '@kbn/management-settings-ids';
import { FtrProviderContext } from '../../ftr_provider_context';

export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const logViewsService = getService('infraLogViews');
const kibanaServer = getService('kibanaServer');
const retry = getService('retry');

const INDICES = 'logs-*,something-else-*,test-*';

describe('Log view settings migration', () => {
describe('Migration API', () => {
before(async () => {
await kibanaServer.savedObjects.clean({
types: [infraSourceConfigurationSavedObjectName, logViewSavedObjectName],
});
});

afterEach(async () => {
await kibanaServer.savedObjects.clean({
types: [infraSourceConfigurationSavedObjectName, logViewSavedObjectName],
});
});

it('performs a migration when the log view is not using the Kibana advanced setting', async () => {
const logViewAttributes: Partial<LogViewAttributes> = {
name: 'Test Log View 1',
description: 'Test Description 1',
logIndices: { type: 'index_name', indexName: INDICES },
logColumns: [],
};

await logViewsService.putLogView(defaultLogViewId, {
attributes: logViewAttributes,
});

await supertest
.put(MIGRATE_LOG_VIEW_SETTINGS_URL)
.set({
'kbn-xsrf': 'some-xsrf-token',
})
.send()
.expect(200);

await retry.try(async () => {
const migratedLogView = await logViewsService.getLogView(defaultLogViewId);
expect(migratedLogView.data.attributes.logIndices.type).to.eql('kibana_advanced_setting');
const uiSetting = await kibanaServer.uiSettings.get(
OBSERVABILITY_LOGS_DATA_ACCESS_LOG_SOURCES_ID
);
expect(uiSetting).to.eql([INDICES]);
});
});

it('should error when the log view is already using the Kibana advanced setting', async () => {
const logViewAttributes: Partial<LogViewAttributes> = {
name: 'Test Log View 1',
description: 'Test Description 1',
logIndices: { type: 'kibana_advanced_setting' },
logColumns: [],
};

await logViewsService.putLogView(defaultLogViewId, {
attributes: logViewAttributes,
});

const response = await supertest
.put(MIGRATE_LOG_VIEW_SETTINGS_URL)
.set({
'kbn-xsrf': 'some-xsrf-token',
})
.send()
.expect(400);

expect(response.body.message).to.eql(
"Unable to migrate log view settings. A log view either doesn't exist or is already using the Kibana advanced setting."
);
});
});
});
}
1 change: 1 addition & 0 deletions x-pack/test/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@
"@kbn/entities-schema",
"@kbn/actions-simulators-plugin",
"@kbn/cases-api-integration-test-plugin",
"@kbn/management-settings-ids",
"@kbn/mock-idp-utils"
]
}