[Deprecations service] add deprecationType and use it in configs deprecations (#100983) (#101039)

Co-authored-by: Ahmad Bamieh <ahmadbamieh@gmail.com>
This commit is contained in:
Kibana Machine 2021-06-01 09:05:09 -04:00 committed by GitHub
parent 1faae80762
commit 3295128346
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 204 additions and 10 deletions

View file

@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) &gt; [deprecationType](./kibana-plugin-core-server.deprecationsdetails.deprecationtype.md)
## DeprecationsDetails.deprecationType property
(optional) Used to identify between different deprecation types. Example use case: in Upgrade Assistant, we may want to allow the user to sort by deprecation type or show each type in a separate tab.
Feel free to add new types if necessary. Predefined types are necessary to reduce having similar definitions with different keywords across kibana deprecations.
<b>Signature:</b>
```typescript
deprecationType?: 'config' | 'feature';
```

View file

@ -15,6 +15,7 @@ export interface DeprecationsDetails
| Property | Type | Description |
| --- | --- | --- |
| [correctiveActions](./kibana-plugin-core-server.deprecationsdetails.correctiveactions.md) | <code>{</code><br/><code> api?: {</code><br/><code> path: string;</code><br/><code> method: 'POST' &#124; 'PUT';</code><br/><code> body?: {</code><br/><code> [key: string]: any;</code><br/><code> };</code><br/><code> };</code><br/><code> manualSteps?: string[];</code><br/><code> }</code> | |
| [deprecationType](./kibana-plugin-core-server.deprecationsdetails.deprecationtype.md) | <code>'config' &#124; 'feature'</code> | (optional) Used to identify between different deprecation types. Example use case: in Upgrade Assistant, we may want to allow the user to sort by deprecation type or show each type in a separate tab.<!-- -->Feel free to add new types if necessary. Predefined types are necessary to reduce having similar definitions with different keywords across kibana deprecations. |
| [documentationUrl](./kibana-plugin-core-server.deprecationsdetails.documentationurl.md) | <code>string</code> | |
| [level](./kibana-plugin-core-server.deprecationsdetails.level.md) | <code>'warning' &#124; 'critical' &#124; 'fetch_error'</code> | levels: - warning: will not break deployment upon upgrade - critical: needs to be addressed before upgrade. - fetch\_error: Deprecations service failed to grab the deprecation details for the domain. |
| [message](./kibana-plugin-core-server.deprecationsdetails.message.md) | <code>string</code> | |

View file

@ -0,0 +1,27 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { PublicMethodsOf } from '@kbn/utility-types';
import type { DeprecationsFactory } from './deprecations_factory';
type DeprecationsFactoryContract = PublicMethodsOf<DeprecationsFactory>;
const createDeprecationsFactoryMock = () => {
const mocked: jest.Mocked<DeprecationsFactoryContract> = {
getRegistry: jest.fn(),
getDeprecations: jest.fn(),
getAllDeprecations: jest.fn(),
};
mocked.getDeprecations.mockResolvedValue([]);
mocked.getAllDeprecations.mockResolvedValue([]);
return mocked as jest.Mocked<DeprecationsFactory>;
};
export const mockDeprecationsFactory = {
create: createDeprecationsFactoryMock,
};

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { GetDeprecationsContext } from './types';
import type { GetDeprecationsContext } from './types';
import { DeprecationsFactory } from './deprecations_factory';
import { loggerMock } from '../logging/logger.mock';

View file

@ -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
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { PublicMethodsOf } from '@kbn/utility-types';
import type { DeprecationsRegistry } from './deprecations_registry';
import type { GetDeprecationsContext } from './types';
import { elasticsearchClientMock } from '../elasticsearch/client/mocks';
import { savedObjectsClientMock } from '../saved_objects/service/saved_objects_client.mock';
type DeprecationsRegistryContract = PublicMethodsOf<DeprecationsRegistry>;
const createDeprecationsRegistryMock = () => {
const mocked: jest.Mocked<DeprecationsRegistryContract> = {
registerDeprecations: jest.fn(),
getDeprecations: jest.fn(),
};
return mocked as jest.Mocked<DeprecationsRegistry>;
};
const createGetDeprecationsContextMock = () => {
const mocked: jest.Mocked<GetDeprecationsContext> = {
esClient: elasticsearchClientMock.createScopedClusterClient(),
savedObjectsClient: savedObjectsClientMock.create(),
};
return mocked;
};
export const mockDeprecationsRegistry = {
create: createDeprecationsRegistryMock,
createGetDeprecationsContext: createGetDeprecationsContextMock,
};

View file

@ -7,7 +7,7 @@
*/
/* eslint-disable dot-notation */
import { RegisterDeprecationsConfig, GetDeprecationsContext } from './types';
import type { RegisterDeprecationsConfig, GetDeprecationsContext } from './types';
import { DeprecationsRegistry } from './deprecations_registry';
describe('DeprecationsRegistry', () => {

View file

@ -6,7 +6,11 @@
* Side Public License, v 1.
*/
import { DeprecationsDetails, RegisterDeprecationsConfig, GetDeprecationsContext } from './types';
import type {
DeprecationsDetails,
RegisterDeprecationsConfig,
GetDeprecationsContext,
} from './types';
export class DeprecationsRegistry {
private readonly deprecationContexts: RegisterDeprecationsConfig[] = [];

View file

@ -0,0 +1,99 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
/* eslint-disable dot-notation */
import { DeprecationsService } from './deprecations_service';
import { httpServiceMock } from '../http/http_service.mock';
import { mockRouter } from '../http/router/router.mock';
import { mockCoreContext } from '../core_context.mock';
import { mockDeprecationsFactory } from './deprecations_factory.mock';
import { mockDeprecationsRegistry } from './deprecations_registry.mock';
describe('DeprecationsService', () => {
const coreContext = mockCoreContext.create();
beforeEach(() => jest.clearAllMocks());
describe('#setup', () => {
const http = httpServiceMock.createInternalSetupContract();
const router = mockRouter.create();
http.createRouter.mockReturnValue(router);
const deprecationsCoreSetupDeps = { http };
it('registers routes', () => {
const deprecationsService = new DeprecationsService(coreContext);
deprecationsService.setup(deprecationsCoreSetupDeps);
// Registers correct base api path
expect(http.createRouter).toBeCalledWith('/api/deprecations');
// registers get route '/'
expect(router.get).toHaveBeenCalledTimes(1);
expect(router.get).toHaveBeenCalledWith({ path: '/', validate: false }, expect.any(Function));
});
it('calls registerConfigDeprecationsInfo', () => {
const deprecationsService = new DeprecationsService(coreContext);
const mockRegisterConfigDeprecationsInfo = jest.fn();
deprecationsService['registerConfigDeprecationsInfo'] = mockRegisterConfigDeprecationsInfo;
deprecationsService.setup(deprecationsCoreSetupDeps);
expect(mockRegisterConfigDeprecationsInfo).toBeCalledTimes(1);
});
});
describe('#registerConfigDeprecationsInfo', () => {
const deprecationsFactory = mockDeprecationsFactory.create();
const deprecationsRegistry = mockDeprecationsRegistry.create();
const getDeprecationsContext = mockDeprecationsRegistry.createGetDeprecationsContext();
it('registers config deprecations', () => {
const deprecationsService = new DeprecationsService(coreContext);
coreContext.configService.getHandledDeprecatedConfigs.mockReturnValue([
[
'testDomain',
[
{
message: 'testMessage',
documentationUrl: 'testDocUrl',
correctiveActions: {
manualSteps: [
'Using Kibana user management, change all users using the kibana_user role to the kibana_admin role.',
'Using Kibana role-mapping management, change all role-mappings which assing the kibana_user role to the kibana_admin role.',
],
},
},
],
],
]);
deprecationsFactory.getRegistry.mockReturnValue(deprecationsRegistry);
deprecationsService['registerConfigDeprecationsInfo'](deprecationsFactory);
expect(coreContext.configService.getHandledDeprecatedConfigs).toBeCalledTimes(1);
expect(deprecationsFactory.getRegistry).toBeCalledTimes(1);
expect(deprecationsFactory.getRegistry).toBeCalledWith('testDomain');
expect(deprecationsRegistry.registerDeprecations).toBeCalledTimes(1);
const configDeprecations = deprecationsRegistry.registerDeprecations.mock.calls[0][0].getDeprecations(
getDeprecationsContext
);
expect(configDeprecations).toMatchInlineSnapshot(`
Array [
Object {
"correctiveActions": Object {
"manualSteps": Array [
"Using Kibana user management, change all users using the kibana_user role to the kibana_admin role.",
"Using Kibana role-mapping management, change all role-mappings which assing the kibana_user role to the kibana_admin role.",
],
},
"deprecationType": "config",
"documentationUrl": "testDocUrl",
"level": "critical",
"message": "testMessage",
},
]
`);
});
});
});

View file

@ -11,8 +11,6 @@ import { RegisterDeprecationsConfig } from './types';
import { registerRoutes } from './routes';
import { CoreContext } from '../core_context';
import { CoreUsageDataSetup } from '../core_usage_data';
import { InternalElasticsearchServiceSetup } from '../elasticsearch';
import { CoreService } from '../../types';
import { InternalHttpServiceSetup } from '../http';
import { Logger } from '../logging';
@ -112,8 +110,6 @@ export interface InternalDeprecationsServiceSetup {
/** @internal */
export interface DeprecationsSetupDeps {
http: InternalHttpServiceSetup;
elasticsearch: InternalElasticsearchServiceSetup;
coreUsageData: CoreUsageDataSetup;
}
/** @internal */
@ -156,6 +152,7 @@ export class DeprecationsService implements CoreService<InternalDeprecationsServ
return deprecationsContexts.map(({ message, correctiveActions, documentationUrl }) => {
return {
level: 'critical',
deprecationType: 'config',
message,
correctiveActions: correctiveActions ?? {},
documentationUrl,

View file

@ -25,6 +25,16 @@ export interface DeprecationsDetails {
* - fetch_error: Deprecations service failed to grab the deprecation details for the domain.
*/
level: 'warning' | 'critical' | 'fetch_error';
/**
* (optional) Used to identify between different deprecation types.
* Example use case: in Upgrade Assistant, we may want to allow the user to sort by
* deprecation type or show each type in a separate tab.
*
* Feel free to add new types if necessary.
* Predefined types are necessary to reduce having similar definitions with different keywords
* across kibana deprecations.
*/
deprecationType?: 'config' | 'feature';
/* (optional) link to the documentation for more details on the deprecation. */
documentationUrl?: string;
/* corrective action needed to fix this deprecation. */

View file

@ -874,6 +874,7 @@ export interface DeprecationsDetails {
};
manualSteps?: string[];
};
deprecationType?: 'config' | 'feature';
// (undocumented)
documentationUrl?: string;
level: 'warning' | 'critical' | 'fetch_error';

View file

@ -193,8 +193,6 @@ export class Server {
const deprecationsSetup = this.deprecations.setup({
http: httpSetup,
elasticsearch: elasticsearchServiceSetup,
coreUsageData: coreUsageDataSetup,
});
const coreSetup: InternalCoreSetup = {

View file

@ -18,6 +18,7 @@ async function getDeprecations({
message: `CorePluginDeprecationsPlugin is a deprecated feature for testing.`,
documentationUrl: 'test-url',
level: 'warning',
deprecationType: 'feature',
correctiveActions: {
manualSteps: ['Step a', 'Step b'],
},

View file

@ -17,7 +17,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
const PageObjects = getPageObjects(['common']);
const browser = getService('browser');
const CorePluginDeprecationsPluginDeprecations = [
const CorePluginDeprecationsPluginDeprecations: DomainDeprecationDetails[] = [
{
level: 'critical',
message:
@ -27,6 +27,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
'Replace "corePluginDeprecations.oldProperty" with "corePluginDeprecations.newProperty" in the Kibana config file, CLI flag, or environment variable (in Docker only).',
],
},
deprecationType: 'config',
domainId: 'corePluginDeprecations',
},
{
@ -37,6 +38,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
'Remove "corePluginDeprecations.noLongerUsed" from the Kibana config file, CLI flag, or environment variable (in Docker only)',
],
},
deprecationType: 'config',
domainId: 'corePluginDeprecations',
},
{
@ -45,6 +47,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
'Kibana plugin functional tests will no longer allow corePluginDeprecations.secret config to be set to anything except 42.',
correctiveActions: {},
documentationUrl: 'config-secret-doc-url',
deprecationType: 'config',
domainId: 'corePluginDeprecations',
},
{
@ -54,6 +57,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
correctiveActions: {
manualSteps: ['Step a', 'Step b'],
},
deprecationType: 'feature',
domainId: 'corePluginDeprecations',
},
{