From 9b1e73427cdc9ac43386ba2bc8be18c38936333b Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 17 Mar 2021 20:08:44 +0200 Subject: [PATCH 01/23] core.deprecations service --- .../kbn-config/src/config_service.mock.ts | 3 + packages/kbn-config/src/config_service.ts | 19 +- .../deprecation/apply_deprecations.test.ts | 8 +- .../src/deprecation/apply_deprecations.ts | 13 +- .../deprecation/deprecation_factory.test.ts | 4 +- .../src/deprecation/deprecation_factory.ts | 64 +++-- packages/kbn-config/src/deprecation/index.ts | 5 +- packages/kbn-config/src/deprecation/types.ts | 21 +- packages/kbn-config/src/index.ts | 2 +- .../config/deprecation/core_deprecations.ts | 107 +++++--- src/core/server/config/index.ts | 2 +- .../deprecations/deprecations_factory.test.ts | 244 ++++++++++++++++++ .../deprecations/deprecations_factory.ts | 112 ++++++++ .../deprecations_registry.test.ts | 72 ++++++ .../deprecations/deprecations_registry.ts | 31 +++ .../deprecations/deprecations_service.mock.ts | 49 ++++ .../deprecations/deprecations_service.ts | 118 +++++++++ src/core/server/deprecations/index.ts | 16 ++ src/core/server/deprecations/routes/get.ts | 37 +++ src/core/server/deprecations/routes/index.ts | 22 ++ src/core/server/deprecations/types.ts | 42 +++ src/core/server/index.ts | 13 +- src/core/server/internal_types.ts | 2 + src/core/server/plugins/plugin_context.ts | 1 + src/core/server/server.ts | 11 + src/plugins/kibana_legacy/server/index.ts | 21 +- src/plugins/timelion/server/deprecations.ts | 70 +++++ src/plugins/timelion/server/plugin.ts | 27 +- .../plugins/monitoring/server/deprecations.ts | 36 +-- x-pack/plugins/spaces/server/config.ts | 8 +- 30 files changed, 1044 insertions(+), 136 deletions(-) create mode 100644 src/core/server/deprecations/deprecations_factory.test.ts create mode 100644 src/core/server/deprecations/deprecations_factory.ts create mode 100644 src/core/server/deprecations/deprecations_registry.test.ts create mode 100644 src/core/server/deprecations/deprecations_registry.ts create mode 100644 src/core/server/deprecations/deprecations_service.mock.ts create mode 100644 src/core/server/deprecations/deprecations_service.ts create mode 100644 src/core/server/deprecations/index.ts create mode 100644 src/core/server/deprecations/routes/get.ts create mode 100644 src/core/server/deprecations/routes/index.ts create mode 100644 src/core/server/deprecations/types.ts create mode 100644 src/plugins/timelion/server/deprecations.ts diff --git a/packages/kbn-config/src/config_service.mock.ts b/packages/kbn-config/src/config_service.mock.ts index 638627caf1e5..5019d97b3e20 100644 --- a/packages/kbn-config/src/config_service.mock.ts +++ b/packages/kbn-config/src/config_service.mock.ts @@ -25,13 +25,16 @@ const createConfigServiceMock = ({ setSchema: jest.fn(), addDeprecationProvider: jest.fn(), validate: jest.fn(), + getHandledDeprecatedConfigs: jest.fn(), }; + mocked.atPath.mockReturnValue(new BehaviorSubject(atPath)); mocked.atPathSync.mockReturnValue(atPath); mocked.getConfig$.mockReturnValue(new BehaviorSubject(new ObjectToConfigAdapter(getConfig$))); mocked.getUsedPaths.mockResolvedValue([]); mocked.getUnusedPaths.mockResolvedValue([]); mocked.isEnabledAtPath.mockResolvedValue(true); + mocked.getHandledDeprecatedConfigs.mockReturnValue(new Map()); return mocked; }; diff --git a/packages/kbn-config/src/config_service.ts b/packages/kbn-config/src/config_service.ts index d71327350d21..678cb05421db 100644 --- a/packages/kbn-config/src/config_service.ts +++ b/packages/kbn-config/src/config_service.ts @@ -21,6 +21,7 @@ import { ConfigDeprecationWithContext, ConfigDeprecationProvider, configDeprecationFactory, + DeprecatedConfigContext, } from './deprecation'; import { LegacyObjectToConfigAdapter } from './legacy'; @@ -43,6 +44,7 @@ export class ConfigService { private readonly handledPaths: Set = new Set(); private readonly schemas = new Map>(); private readonly deprecations = new BehaviorSubject([]); + private readonly handledDeprecatedConfigs = new Map(); constructor( private readonly rawConfigProvider: RawConfigurationProvider, @@ -91,6 +93,13 @@ export class ConfigService { ]); } + /** + * returns all handled deprecated configs + */ + public getHandledDeprecatedConfigs() { + return [...this.handledDeprecatedConfigs.entries()]; + } + /** * Validate the whole configuration and log the deprecation warnings. * @@ -186,8 +195,14 @@ export class ConfigService { const rawConfig = await this.rawConfigProvider.getConfig$().pipe(take(1)).toPromise(); const deprecations = await this.deprecations.pipe(take(1)).toPromise(); const deprecationMessages: string[] = []; - const logger = (msg: string) => deprecationMessages.push(msg); - applyDeprecations(rawConfig, deprecations, logger); + const onHandleDeprecationHook = (pluginId: string) => (context: DeprecatedConfigContext) => { + deprecationMessages.push(context.message); + const handledDeprecatedConfig = this.handledDeprecatedConfigs.get(pluginId) || []; + handledDeprecatedConfig.push(context); + this.handledDeprecatedConfigs.set(pluginId, handledDeprecatedConfig); + }; + + applyDeprecations(rawConfig, deprecations, onHandleDeprecationHook); deprecationMessages.forEach((msg) => { this.deprecationLog.warn(msg); }); diff --git a/packages/kbn-config/src/deprecation/apply_deprecations.test.ts b/packages/kbn-config/src/deprecation/apply_deprecations.test.ts index 9e058faf6805..78ffea1a185f 100644 --- a/packages/kbn-config/src/deprecation/apply_deprecations.test.ts +++ b/packages/kbn-config/src/deprecation/apply_deprecations.test.ts @@ -33,7 +33,7 @@ describe('applyDeprecations', () => { }); it('calls handlers with correct arguments', () => { - const logger = () => undefined; + const configDeprecationHook = () => undefined; const initialConfig = { foo: 'bar', deprecated: 'deprecated' }; const alteredConfig = { foo: 'bar' }; @@ -43,11 +43,11 @@ describe('applyDeprecations', () => { applyDeprecations( initialConfig, [wrapHandler(handlerA, 'pathA'), wrapHandler(handlerB, 'pathB')], - logger + () => configDeprecationHook ); - expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', logger); - expect(handlerB).toHaveBeenCalledWith(alteredConfig, 'pathB', logger); + expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', configDeprecationHook); + expect(handlerB).toHaveBeenCalledWith(alteredConfig, 'pathB', configDeprecationHook); }); it('returns the migrated config', () => { diff --git a/packages/kbn-config/src/deprecation/apply_deprecations.ts b/packages/kbn-config/src/deprecation/apply_deprecations.ts index 0813440adb57..7e2941cb2a75 100644 --- a/packages/kbn-config/src/deprecation/apply_deprecations.ts +++ b/packages/kbn-config/src/deprecation/apply_deprecations.ts @@ -7,23 +7,24 @@ */ import { cloneDeep } from 'lodash'; -import { ConfigDeprecationWithContext, ConfigDeprecationLogger } from './types'; - -const noopLogger = (msg: string) => undefined; +import { ConfigDeprecationWithContext, ConfigDeprecationHook } from './types'; +const noopConfigDeprecationHook: () => ConfigDeprecationHook = () => () => undefined; /** - * Applies deprecations on given configuration and logs any deprecation warning using provided logger. + * Applies deprecations on given configuration and passes handled deprecation configDeprecationHook + * This hook is used for logging any deprecation warning using provided logger. + * This hook is used for exposing deprecated configs that must be handled by the user before upgrading to next major. * * @internal */ export const applyDeprecations = ( config: Record, deprecations: ConfigDeprecationWithContext[], - logger: ConfigDeprecationLogger = noopLogger + configDeprecationHook: (pluginId: string) => ConfigDeprecationHook = noopConfigDeprecationHook ) => { let processed = cloneDeep(config); deprecations.forEach(({ deprecation, path }) => { - processed = deprecation(processed, path, logger); + processed = deprecation(processed, path, configDeprecationHook(path)); }); return processed; }; diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts index ba8a0cbf7ca5..d76e3ea7536f 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts @@ -6,14 +6,14 @@ * Side Public License, v 1. */ -import { ConfigDeprecationLogger } from './types'; +import { ConfigDeprecationHook } from './types'; import { configDeprecationFactory } from './deprecation_factory'; describe('DeprecationFactory', () => { const { rename, unused, renameFromRoot, unusedFromRoot } = configDeprecationFactory; let deprecationMessages: string[]; - const logger: ConfigDeprecationLogger = (msg) => deprecationMessages.push(msg); + const logger: ConfigDeprecationHook = ({ message }) => deprecationMessages.push(message); beforeEach(() => { deprecationMessages = []; diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.ts b/packages/kbn-config/src/deprecation/deprecation_factory.ts index 73196dc897a5..5e0ad9b978e6 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.ts @@ -9,12 +9,12 @@ import { get } from 'lodash'; import { set } from '@elastic/safer-lodash-set'; import { unset } from '@kbn/std'; -import { ConfigDeprecation, ConfigDeprecationLogger, ConfigDeprecationFactory } from './types'; +import { ConfigDeprecation, ConfigDeprecationHook, ConfigDeprecationFactory } from './types'; const _rename = ( config: Record, rootPath: string, - log: ConfigDeprecationLogger, + configDeprecationHook: ConfigDeprecationHook, oldKey: string, newKey: string, silent?: boolean @@ -32,23 +32,33 @@ const _rename = ( if (newValue === undefined) { set(config, fullNewPath, oldValue); - if (!silent) { - log(`"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}"`); - } + configDeprecationHook({ + silent, + message: `"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}"`, + correctionActions: { + manualSteps: [`Replace "${fullOldPath}" in the kibana.yml file with "${fullNewPath}"`], + }, + }); } else { - if (!silent) { - log( - `"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}". However both key are present, ignoring "${fullOldPath}"` - ); - } + configDeprecationHook({ + silent, + message: `"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}". However both key are present, ignoring "${fullOldPath}"`, + correctionActions: { + manualSteps: [ + `Make sure "${fullNewPath}" contains the correct value in the kibana.yml file."`, + `Remove "${fullOldPath}" from the kibana.yml file."`, + ], + }, + }); } + return config; }; const _unused = ( config: Record, rootPath: string, - log: ConfigDeprecationLogger, + configDeprecationHook: ConfigDeprecationHook, unusedKey: string ) => { const fullPath = getPath(rootPath, unusedKey); @@ -56,24 +66,38 @@ const _unused = ( return config; } unset(config, fullPath); - log(`${fullPath} is deprecated and is no longer used`); + configDeprecationHook({ + message: `${fullPath} is deprecated and is no longer used`, + correctionActions: { + manualSteps: [`Remove "${fullPath}" from the kibana.yml file."`], + }, + }); return config; }; -const rename = (oldKey: string, newKey: string): ConfigDeprecation => (config, rootPath, log) => - _rename(config, rootPath, log, oldKey, newKey); +const rename = (oldKey: string, newKey: string): ConfigDeprecation => ( + config, + rootPath, + configDeprecationHook +) => _rename(config, rootPath, configDeprecationHook, oldKey, newKey); const renameFromRoot = (oldKey: string, newKey: string, silent?: boolean): ConfigDeprecation => ( config, rootPath, - log -) => _rename(config, '', log, oldKey, newKey, silent); + configDeprecationHook +) => _rename(config, '', configDeprecationHook, oldKey, newKey, silent); -const unused = (unusedKey: string): ConfigDeprecation => (config, rootPath, log) => - _unused(config, rootPath, log, unusedKey); +const unused = (unusedKey: string): ConfigDeprecation => ( + config, + rootPath, + configDeprecationHook +) => _unused(config, rootPath, configDeprecationHook, unusedKey); -const unusedFromRoot = (unusedKey: string): ConfigDeprecation => (config, rootPath, log) => - _unused(config, '', log, unusedKey); +const unusedFromRoot = (unusedKey: string): ConfigDeprecation => ( + config, + rootPath, + configDeprecationHook +) => _unused(config, '', configDeprecationHook, unusedKey); const getPath = (rootPath: string, subPath: string) => rootPath !== '' ? `${rootPath}.${subPath}` : subPath; diff --git a/packages/kbn-config/src/deprecation/index.ts b/packages/kbn-config/src/deprecation/index.ts index 6fe1a53efecb..a1acc6997632 100644 --- a/packages/kbn-config/src/deprecation/index.ts +++ b/packages/kbn-config/src/deprecation/index.ts @@ -6,12 +6,13 @@ * Side Public License, v 1. */ -export { +export type { ConfigDeprecation, ConfigDeprecationWithContext, - ConfigDeprecationLogger, ConfigDeprecationFactory, + ConfigDeprecationHook, ConfigDeprecationProvider, + DeprecatedConfigContext, } from './types'; export { configDeprecationFactory } from './deprecation_factory'; export { applyDeprecations } from './apply_deprecations'; diff --git a/packages/kbn-config/src/deprecation/types.ts b/packages/kbn-config/src/deprecation/types.ts index 6e1816867abc..972ac924ec8d 100644 --- a/packages/kbn-config/src/deprecation/types.ts +++ b/packages/kbn-config/src/deprecation/types.ts @@ -11,7 +11,23 @@ * * @public */ -export type ConfigDeprecationLogger = (message: string) => void; +export type ConfigDeprecationHook = (context: DeprecatedConfigContext) => void; + +export interface DeprecatedConfigContext { + message: string; + silent?: boolean; + documentationUrl?: string; + correctionActions?: { + api?: { + path: string; + method: 'POST' | 'PUT'; + body?: { + [key: string]: any; + }; + }; + manualSteps?: string[]; + }; +} /** * Configuration deprecation returned from {@link ConfigDeprecationProvider} that handles a single deprecation from the configuration. @@ -25,7 +41,7 @@ export type ConfigDeprecationLogger = (message: string) => void; export type ConfigDeprecation = ( config: Record, fromPath: string, - logger: ConfigDeprecationLogger + onDeprecationHook: ConfigDeprecationHook ) => Record; /** @@ -62,6 +78,7 @@ export type ConfigDeprecationProvider = (factory: ConfigDeprecationFactory) => C * * @public */ + export interface ConfigDeprecationFactory { /** * Rename a configuration property from inside a plugin's configuration path. diff --git a/packages/kbn-config/src/index.ts b/packages/kbn-config/src/index.ts index 24f271c979f3..be5225d1fdd3 100644 --- a/packages/kbn-config/src/index.ts +++ b/packages/kbn-config/src/index.ts @@ -11,7 +11,7 @@ export { ConfigDeprecation, ConfigDeprecationFactory, configDeprecationFactory, - ConfigDeprecationLogger, + ConfigDeprecationHook, ConfigDeprecationProvider, ConfigDeprecationWithContext, } from './deprecation'; diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts index fbdbaeb14fd5..33183cf2eee9 100644 --- a/src/core/server/config/deprecation/core_deprecations.ts +++ b/src/core/server/config/deprecation/core_deprecations.ts @@ -9,40 +9,47 @@ import { has, get } from 'lodash'; import { ConfigDeprecationProvider, ConfigDeprecation } from '@kbn/config'; -const configPathDeprecation: ConfigDeprecation = (settings, fromPath, log) => { +const configPathDeprecation: ConfigDeprecation = (settings, fromPath, configDeprecationHook) => { if (has(process.env, 'CONFIG_PATH')) { - log( - `Environment variable CONFIG_PATH is deprecated. It has been replaced with KBN_PATH_CONF pointing to a config folder` - ); + configDeprecationHook({ + message: `Environment variable CONFIG_PATH is deprecated. It has been replaced with KBN_PATH_CONF pointing to a config folder`, + }); } return settings; }; -const dataPathDeprecation: ConfigDeprecation = (settings, fromPath, log) => { +const dataPathDeprecation: ConfigDeprecation = (settings, fromPath, configDeprecationHook) => { if (has(process.env, 'DATA_PATH')) { - log( - `Environment variable "DATA_PATH" will be removed. It has been replaced with kibana.yml setting "path.data"` - ); + configDeprecationHook({ + message: `Environment variable "DATA_PATH" will be removed. It has been replaced with kibana.yml setting "path.data"`, + }); } return settings; }; -const rewriteBasePathDeprecation: ConfigDeprecation = (settings, fromPath, log) => { +const rewriteBasePathDeprecation: ConfigDeprecation = ( + settings, + fromPath, + configDeprecationHook +) => { if (has(settings, 'server.basePath') && !has(settings, 'server.rewriteBasePath')) { - log( - 'You should set server.basePath along with server.rewriteBasePath. Starting in 7.0, Kibana ' + + configDeprecationHook({ + message: + 'You should set server.basePath along with server.rewriteBasePath. Starting in 7.0, Kibana ' + 'will expect that all requests start with server.basePath rather than expecting you to rewrite ' + 'the requests in your reverse proxy. Set server.rewriteBasePath to false to preserve the ' + - 'current behavior and silence this warning.' - ); + 'current behavior and silence this warning.', + }); } return settings; }; -const rewriteCorsSettings: ConfigDeprecation = (settings, fromPath, log) => { +const rewriteCorsSettings: ConfigDeprecation = (settings, fromPath, configDeprecationHook) => { const corsSettings = get(settings, 'server.cors'); if (typeof get(settings, 'server.cors') === 'boolean') { - log('"server.cors" is deprecated and has been replaced by "server.cors.enabled"'); + configDeprecationHook({ + message: '"server.cors" is deprecated and has been replaced by "server.cors.enabled"', + }); settings.server.cors = { enabled: corsSettings, }; @@ -50,7 +57,7 @@ const rewriteCorsSettings: ConfigDeprecation = (settings, fromPath, log) => { return settings; }; -const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, log) => { +const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, configDeprecationHook) => { const NONCE_STRING = `{nonce}`; // Policies that should include the 'self' source const SELF_POLICIES = Object.freeze(['script-src', 'style-src']); @@ -67,7 +74,9 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, log) => { settings.csp.rules = [...parsed].map(([policy, sourceList]) => { if (sourceList.find((source) => source.includes(NONCE_STRING))) { - log(`csp.rules no longer supports the {nonce} syntax. Replacing with 'self' in ${policy}`); + configDeprecationHook({ + message: `csp.rules no longer supports the {nonce} syntax. Replacing with 'self' in ${policy}`, + }); sourceList = sourceList.filter((source) => !source.includes(NONCE_STRING)); // Add 'self' if not present @@ -80,7 +89,9 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, log) => { SELF_POLICIES.includes(policy) && !sourceList.find((source) => source.includes(SELF_STRING)) ) { - log(`csp.rules must contain the 'self' source. Automatically adding to ${policy}.`); + configDeprecationHook({ + message: `csp.rules must contain the 'self' source. Automatically adding to ${policy}.`, + }); sourceList.push(SELF_STRING); } @@ -91,50 +102,70 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, log) => { return settings; }; -const mapManifestServiceUrlDeprecation: ConfigDeprecation = (settings, fromPath, log) => { +const mapManifestServiceUrlDeprecation: ConfigDeprecation = ( + settings, + fromPath, + configDeprecationHook +) => { if (has(settings, 'map.manifestServiceUrl')) { - log( - 'You should no longer use the map.manifestServiceUrl setting in kibana.yml to configure the location ' + + configDeprecationHook({ + message: + 'You should no longer use the map.manifestServiceUrl setting in kibana.yml to configure the location ' + 'of the Elastic Maps Service settings. These settings have moved to the "map.emsTileApiUrl" and ' + '"map.emsFileApiUrl" settings instead. These settings are for development use only and should not be ' + - 'modified for use in production environments.' - ); + 'modified for use in production environments.', + }); } return settings; }; -const opsLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, log) => { +const opsLoggingEventDeprecation: ConfigDeprecation = ( + settings, + fromPath, + configDeprecationHook +) => { if (has(settings, 'logging.events.ops')) { - log( - '"logging.events.ops" has been deprecated and will be removed ' + + configDeprecationHook({ + message: + '"logging.events.ops" has been deprecated and will be removed ' + 'in 8.0. To access ops data moving forward, please enable debug logs for the ' + '"metrics.ops" context in your logging configuration. For more details, see ' + - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.md' - ); + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.md', + }); } return settings; }; -const requestLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, log) => { +const requestLoggingEventDeprecation: ConfigDeprecation = ( + settings, + fromPath, + configDeprecationHook +) => { if (has(settings, 'logging.events.request') || has(settings, 'logging.events.response')) { - log( - '"logging.events.request" and "logging.events.response" have been deprecated and will be removed ' + + configDeprecationHook({ + message: + '"logging.events.request" and "logging.events.response" have been deprecated and will be removed ' + 'in 8.0. To access request and/or response data moving forward, please enable debug logs for the ' + '"http.server.response" context in your logging configuration. For more details, see ' + - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.md' - ); + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.md', + }); } return settings; }; -const timezoneLoggingDeprecation: ConfigDeprecation = (settings, fromPath, log) => { +const timezoneLoggingDeprecation: ConfigDeprecation = ( + settings, + fromPath, + configDeprecationHook +) => { if (has(settings, 'logging.timezone')) { - log( - '"logging.timezone" has been deprecated and will be removed ' + + configDeprecationHook({ + message: + '"logging.timezone" has been deprecated and will be removed ' + 'in 8.0. To set the timezone moving forward, please add a timezone date modifier to the log pattern ' + 'in your logging configuration. For more details, see ' + - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.md' - ); + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.md', + }); } return settings; }; diff --git a/src/core/server/config/index.ts b/src/core/server/config/index.ts index bf2ce16e869b..c16133176037 100644 --- a/src/core/server/config/index.ts +++ b/src/core/server/config/index.ts @@ -24,7 +24,7 @@ export type { ConfigPath, CliArgs, ConfigDeprecation, - ConfigDeprecationLogger, + ConfigDeprecationHook, ConfigDeprecationProvider, ConfigDeprecationFactory, EnvironmentMode, diff --git a/src/core/server/deprecations/deprecations_factory.test.ts b/src/core/server/deprecations/deprecations_factory.test.ts new file mode 100644 index 000000000000..7ff297aca519 --- /dev/null +++ b/src/core/server/deprecations/deprecations_factory.test.ts @@ -0,0 +1,244 @@ +/* + * 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 { DeprecationDependencies } from './types'; +import { DeprecationsFactory } from './deprecations_factory'; +import { loggerMock } from '../logging/logger.mock'; + +describe('DeprecationsFactory', () => { + const logger = loggerMock.create(); + beforeEach(() => { + loggerMock.clear(logger); + }); + + describe('createRegistry', () => { + it('creates a registry for a pluginId', async () => { + const deprecationsFactory = new DeprecationsFactory({ logger }); + const pluginId = 'test-plugin'; + const registry = deprecationsFactory.createRegistry(pluginId); + + expect(registry).toHaveProperty('registerDeprecations'); + expect(registry).toHaveProperty('getDeprecations'); + }); + + it('creates one registry for a pluginId', async () => { + const deprecationsFactory = new DeprecationsFactory({ logger }); + const pluginId = 'test-plugin'; + const registry = deprecationsFactory.createRegistry(pluginId); + const sameRegistry = deprecationsFactory.createRegistry(pluginId); + + expect(registry).toStrictEqual(sameRegistry); + }); + }); + + describe('getRegistry', () => { + const pluginId = 'test-plugin'; + const deprecationsFactory = new DeprecationsFactory({ logger }); + it('returns a registered registry', () => { + const registry = deprecationsFactory.createRegistry(pluginId); + expect(deprecationsFactory.getRegistry(pluginId)).toStrictEqual(registry); + }); + it('returns undefined if no registry is defined', () => { + expect(deprecationsFactory.getRegistry('never-registered-plugin')).toBe(undefined); + }); + }); + + describe('getAllDeprecations', () => { + const mockDependencies = ({ + esClient: jest.fn(), + savedObjectsClient: jest.fn(), + } as unknown) as DeprecationDependencies; + + it('returns a flattened array of deprecations', async () => { + const deprecationsFactory = new DeprecationsFactory({ logger }); + const mockPluginDeprecationsInfo = [ + { + message: 'mockPlugin message', + level: 'critical', + correctionActions: { + manualSteps: ['mockPlugin step 1', 'mockPlugin step 2'], + }, + }, + { + message: 'hello there!', + level: 'warning', + correctionActions: { + manualSteps: ['mockPlugin step a', 'mockPlugin step b'], + }, + }, + ]; + const anotherMockPluginDeprecationsInfo = [ + { + message: 'anotherMockPlugin message', + level: 'critical', + correctionActions: { + manualSteps: ['anotherMockPlugin step 1', 'anotherMockPlugin step 2'], + }, + }, + ]; + + const mockPluginRegistry = deprecationsFactory.createRegistry('mockPlugin'); + const anotherMockPluginRegistry = deprecationsFactory.createRegistry('anotherMockPlugin'); + mockPluginRegistry.registerDeprecations({ + getDeprecations: jest.fn().mockResolvedValue(mockPluginDeprecationsInfo), + }); + anotherMockPluginRegistry.registerDeprecations({ + getDeprecations: jest.fn().mockResolvedValue(anotherMockPluginDeprecationsInfo), + }); + + const derpecationsInfo = await deprecationsFactory.getAllDeprecations(mockDependencies); + expect(derpecationsInfo).toStrictEqual( + [ + mockPluginDeprecationsInfo.map((info) => ({ ...info, pluginId: 'mockPlugin' })), + anotherMockPluginDeprecationsInfo.map((info) => ({ + ...info, + pluginId: 'anotherMockPlugin', + })), + ].flat() + ); + }); + + it(`returns a failure message for failed getDeprecations functions`, async () => { + const deprecationsFactory = new DeprecationsFactory({ logger }); + const pluginId = 'mockPlugin'; + const mockError = new Error(); + + const deprecationsRegistry = deprecationsFactory.createRegistry(pluginId); + deprecationsRegistry.registerDeprecations({ + getDeprecations: jest.fn().mockRejectedValue(mockError), + }); + const derpecationsInfo = await deprecationsFactory.getAllDeprecations(mockDependencies); + expect(logger.warn).toBeCalledTimes(1); + expect(logger.warn).toBeCalledWith( + `Failed to get deprecations info for plugin "${pluginId}".`, + mockError + ); + expect(derpecationsInfo).toStrictEqual([ + { + pluginId, + message: `Failed to get deprecations info for plugin "${pluginId}".`, + level: 'warning', + correctionActions: { + manualSteps: ['Check Kibana server logs for error message.'], + }, + }, + ]); + }); + + it(`returns successful results even when some getDeprecations fail`, async () => { + const deprecationsFactory = new DeprecationsFactory({ logger }); + const mockPluginRegistry = deprecationsFactory.createRegistry('mockPlugin'); + const anotherMockPluginRegistry = deprecationsFactory.createRegistry('anotherMockPlugin'); + const mockError = new Error(); + const mockPluginDeprecationsInfo = [ + { + message: 'mockPlugin message', + level: 'critical', + correctionActions: { + manualSteps: ['mockPlugin step 1', 'mockPlugin step 2'], + }, + }, + ]; + mockPluginRegistry.registerDeprecations({ + getDeprecations: jest.fn().mockResolvedValue(mockPluginDeprecationsInfo), + }); + anotherMockPluginRegistry.registerDeprecations({ + getDeprecations: jest.fn().mockRejectedValue(mockError), + }); + const derpecationsInfo = await deprecationsFactory.getAllDeprecations(mockDependencies); + + expect(logger.warn).toBeCalledTimes(1); + expect(logger.warn).toBeCalledWith( + `Failed to get deprecations info for plugin "anotherMockPlugin".`, + mockError + ); + expect(derpecationsInfo).toStrictEqual([ + ...mockPluginDeprecationsInfo.map((info) => ({ ...info, pluginId: 'mockPlugin' })), + { + pluginId: 'anotherMockPlugin', + message: `Failed to get deprecations info for plugin "anotherMockPlugin".`, + level: 'warning', + correctionActions: { + manualSteps: ['Check Kibana server logs for error message.'], + }, + }, + ]); + }); + }); + + describe('getDeprecations', () => { + const mockDependencies = ({ + esClient: jest.fn(), + savedObjectsClient: jest.fn(), + } as unknown) as DeprecationDependencies; + + it('returns a flattened array of DeprecationInfo', async () => { + const deprecationsFactory = new DeprecationsFactory({ logger }); + const deprecationsRegistry = deprecationsFactory.createRegistry('mockPlugin'); + const deprecationsInfoBody = [ + { + message: 'mockPlugin message', + level: 'critical', + correctionActions: { + manualSteps: ['mockPlugin step 1', 'mockPlugin step 2'], + }, + }, + [ + { + message: 'hello there!', + level: 'warning', + correctionActions: { + manualSteps: ['mockPlugin step a', 'mockPlugin step b'], + }, + }, + ], + ]; + + deprecationsRegistry.registerDeprecations({ + getDeprecations: jest.fn().mockResolvedValue(deprecationsInfoBody), + }); + + const derpecationsInfo = await deprecationsFactory.getDeprecations( + 'mockPlugin', + mockDependencies + ); + expect(derpecationsInfo).toStrictEqual( + deprecationsInfoBody.flat().map((body) => ({ ...body, pluginId: 'mockPlugin' })) + ); + }); + + it('removes empty entries from the returned array', async () => { + const deprecationsFactory = new DeprecationsFactory({ logger }); + const deprecationsRegistry = deprecationsFactory.createRegistry('mockPlugin'); + const deprecationsInfoBody = [ + { + message: 'mockPlugin message', + level: 'critical', + correctionActions: { + manualSteps: ['mockPlugin step 1', 'mockPlugin step 2'], + }, + }, + [undefined], + undefined, + ]; + + deprecationsRegistry.registerDeprecations({ + getDeprecations: jest.fn().mockResolvedValue(deprecationsInfoBody), + }); + + const derpecationsInfo = await deprecationsFactory.getDeprecations( + 'mockPlugin', + mockDependencies + ); + expect(derpecationsInfo).toHaveLength(1); + expect(derpecationsInfo).toStrictEqual([ + { ...deprecationsInfoBody[0], pluginId: 'mockPlugin' }, + ]); + }); + }); +}); diff --git a/src/core/server/deprecations/deprecations_factory.ts b/src/core/server/deprecations/deprecations_factory.ts new file mode 100644 index 000000000000..d212241e1c6a --- /dev/null +++ b/src/core/server/deprecations/deprecations_factory.ts @@ -0,0 +1,112 @@ +/* + * 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 { DeprecationsRegistry } from './deprecations_registry'; +import type { Logger } from '../logging'; +import type { + PluginDeprecationDetails, + DeprecationsDetails, + DeprecationDependencies, +} from './types'; + +export interface DeprecationsFactoryDeps { + logger: Logger; +} + +export class DeprecationsFactory { + private readonly registries: Map = new Map(); + private readonly logger: Logger; + constructor({ logger }: DeprecationsFactoryDeps) { + this.logger = logger; + } + + public createRegistry = (pluginId: string): DeprecationsRegistry => { + const exsiting = this.registries.get(pluginId); + if (exsiting) { + return exsiting; + } + const registry = new DeprecationsRegistry(); + this.registries.set(pluginId, registry); + return registry; + }; + + public getRegistry = (pluginId: string): DeprecationsRegistry | undefined => { + return this.registries.get(pluginId); + }; + + public getDeprecations = async ( + pluginId: string, + dependencies: DeprecationDependencies + ): Promise => { + const infoBody = await this.getDeprecationsBody(pluginId, dependencies); + return this.createDeprecationInfo(pluginId, infoBody).flat(); + }; + + public getAllDeprecations = async ( + dependencies: DeprecationDependencies + ): Promise => { + const pluginIds = [...this.registries.keys()]; + + const deprecationsInfo = await Promise.all( + pluginIds.map(async (pluginId) => { + const infoBody = await this.getDeprecationsBody(pluginId, dependencies); + return this.createDeprecationInfo(pluginId, infoBody); + }) + ); + + return deprecationsInfo.flat(); + }; + + private createDeprecationInfo = ( + pluginId: string, + deprecationInfoBody: DeprecationsDetails[] + ): PluginDeprecationDetails[] => { + return deprecationInfoBody + .flat() + .filter(Boolean) + .map((pluginDeprecation) => ({ + ...pluginDeprecation, + pluginId, + })); + }; + + private getDeprecationsBody = async ( + pluginId: string, + dependencies: DeprecationDependencies + ): Promise => { + const deprecationsRegistry = this.registries.get(pluginId); + if (!deprecationsRegistry) { + return []; + } + try { + const settledResults = await deprecationsRegistry.getDeprecations(dependencies); + return settledResults.flatMap((settledResult) => { + if (settledResult.status === 'rejected') { + this.logger.warn( + `Failed to get deprecations info for plugin "${pluginId}".`, + settledResult.reason + ); + return [ + { + message: `Failed to get deprecations info for plugin "${pluginId}".`, + level: 'warning', + correctionActions: { + manualSteps: ['Check Kibana server logs for error message.'], + }, + }, + ]; + } + + return settledResult.value; + }); + } catch (err) { + this.logger.warn(`Failed to get deprecations info for plugin "${pluginId}".`, err); + return []; + } + }; +} diff --git a/src/core/server/deprecations/deprecations_registry.test.ts b/src/core/server/deprecations/deprecations_registry.test.ts new file mode 100644 index 000000000000..6391c093ba8b --- /dev/null +++ b/src/core/server/deprecations/deprecations_registry.test.ts @@ -0,0 +1,72 @@ +/* + * 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 { DeprecationsContext, DeprecationDependencies } from './types'; +import { DeprecationsRegistry } from './deprecations_registry'; + +describe('DeprecationsRegistry', () => { + describe('registerDeprecations', () => { + it('throws if getDeprecations is not a function', async () => { + const deprecationsRegistry = new DeprecationsRegistry(); + const context = ({ getDeprecations: null } as unknown) as DeprecationsContext; + expect(() => deprecationsRegistry.registerDeprecations(context)).toThrowError( + /getDeprecations must be a function/ + ); + }); + + it('registers deprecation context', () => { + const deprecationsRegistry = new DeprecationsRegistry(); + const getDeprecations = jest.fn(); + const context = { getDeprecations }; + deprecationsRegistry.registerDeprecations(context); + expect(deprecationsRegistry.deprecationContexts).toStrictEqual([context]); + }); + + it('allows registering multiple contexts', async () => { + const deprecationsRegistry = new DeprecationsRegistry(); + const contextA = { getDeprecations: jest.fn() }; + const contextB = { getDeprecations: jest.fn() }; + deprecationsRegistry.registerDeprecations(contextA); + deprecationsRegistry.registerDeprecations(contextB); + expect(deprecationsRegistry.deprecationContexts).toStrictEqual([contextA, contextB]); + }); + }); + + describe('getDeprecations', () => { + it('returns all settled deprecations', async () => { + const deprecationsRegistry = new DeprecationsRegistry(); + const mockDependencies = ({} as unknown) as DeprecationDependencies; + const mockError = new Error(); + const contextA = { getDeprecations: jest.fn().mockResolvedValue('hi') }; + const contextB = { getDeprecations: jest.fn().mockRejectedValue(mockError) }; + deprecationsRegistry.registerDeprecations(contextA); + deprecationsRegistry.registerDeprecations(contextB); + const deprecations = await deprecationsRegistry.getDeprecations(mockDependencies); + expect(deprecations).toStrictEqual([ + { + status: 'fulfilled', + value: 'hi', + }, + { + status: 'rejected', + reason: mockError, + }, + ]); + }); + + it('passes dependencies to registered getDeprecations function', async () => { + const deprecationsRegistry = new DeprecationsRegistry(); + const mockDependencies = ({} as unknown) as DeprecationDependencies; + const context = { getDeprecations: jest.fn().mockResolvedValue('hi') }; + deprecationsRegistry.registerDeprecations(context); + const deprecations = await deprecationsRegistry.getDeprecations(mockDependencies); + expect(deprecations).toHaveLength(1); + expect(context.getDeprecations).toBeCalledWith(mockDependencies); + }); + }); +}); diff --git a/src/core/server/deprecations/deprecations_registry.ts b/src/core/server/deprecations/deprecations_registry.ts new file mode 100644 index 000000000000..a005a9394bcc --- /dev/null +++ b/src/core/server/deprecations/deprecations_registry.ts @@ -0,0 +1,31 @@ +/* + * 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 { DeprecationsDetails, DeprecationsContext, DeprecationDependencies } from './types'; + +export class DeprecationsRegistry { + private readonly deprecationContexts: DeprecationsContext[] = []; + + public registerDeprecations = (deprecationContext: DeprecationsContext) => { + if (typeof deprecationContext.getDeprecations !== 'function') { + throw new Error(`getDeprecations must be a function in registerDeprecations(context)`); + } + + this.deprecationContexts.push(deprecationContext); + }; + + public getDeprecations = async ( + dependencies: DeprecationDependencies + ): Promise>> => { + return await Promise.allSettled( + this.deprecationContexts.map( + async (deprecationContext) => await deprecationContext.getDeprecations(dependencies) + ) + ); + }; +} diff --git a/src/core/server/deprecations/deprecations_service.mock.ts b/src/core/server/deprecations/deprecations_service.mock.ts new file mode 100644 index 000000000000..13f7dbd196c3 --- /dev/null +++ b/src/core/server/deprecations/deprecations_service.mock.ts @@ -0,0 +1,49 @@ +/* + * 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 { + DeprecationsService, + InternalDeprecationsServiceSetup, + DeprecationsServiceSetup, +} from './deprecations_service'; +type DeprecationsServiceContract = PublicMethodsOf; + +const createSetupContractMock = () => { + const setupContract: jest.Mocked = { + registerDeprecations: jest.fn(), + }; + + return setupContract; +}; + +const createInternalSetupContractMock = () => { + const internalSetupContract: jest.Mocked = { + createRegistry: jest.fn(), + }; + + internalSetupContract.createRegistry.mockReturnValue(createSetupContractMock()); + return internalSetupContract; +}; + +const createDeprecationsServiceMock = () => { + const mocked: jest.Mocked = { + setup: jest.fn(), + start: jest.fn(), + stop: jest.fn(), + }; + + mocked.setup.mockReturnValue(createInternalSetupContractMock()); + return mocked; +}; + +export const savedObjectsServiceMock = { + create: createDeprecationsServiceMock, + createInternalSetupContract: createInternalSetupContractMock, + createSetupContract: createSetupContractMock, +}; diff --git a/src/core/server/deprecations/deprecations_service.ts b/src/core/server/deprecations/deprecations_service.ts new file mode 100644 index 000000000000..1f55f02f7d96 --- /dev/null +++ b/src/core/server/deprecations/deprecations_service.ts @@ -0,0 +1,118 @@ +/* + * 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 { CoreService } from '../../types'; +import { DeprecationsFactory } from './deprecations_factory'; +import { DeprecationsRegistry } from './deprecations_registry'; + +import { CoreContext } from '../core_context'; +import { CoreUsageDataSetup } from '../core_usage_data'; +import { InternalElasticsearchServiceSetup } from '../elasticsearch'; +import { InternalHttpServiceSetup } from '../http'; +import { Logger } from '../logging'; +import { registerRoutes } from './routes'; + +/** + * Deprecations Service is a mechanism to allow plugins to communiicate deprecated features. + * + * @example + * ```ts + * import { DeprecationsContext, CoreSetup } from 'src/core/server'; + * + * const getDeprecations: DeprecationsContext['getDeprecations'] = async ({ esClient, savedObjectsClient }) => { + * return [ + * { + * message: string; + * level: 'warning' | 'critical'; + * documentationUrl?: string; + * correctionActions: { + * api?: { + * path: string; + * method: 'POST' | 'PUT'; + * body?: { [key: string]: any }, + * }, + * manualSteps?: string[]; + * } + * } + * ] + * } + * + * export class Plugin() { + * setup: (core: CoreSetup) => { + * core.deprecations.registerDeprecations({ getDeprecations }); + * } + * } + * ``` + * + * @public + */ +export interface DeprecationsServiceSetup { + registerDeprecations: DeprecationsRegistry['registerDeprecations']; +} + +/** @internal */ +export interface InternalDeprecationsServiceSetup { + createRegistry: (pluginId: string) => DeprecationsServiceSetup; +} + +/** @internal */ +export interface DeprecationsSetupDeps { + http: InternalHttpServiceSetup; + elasticsearch: InternalElasticsearchServiceSetup; + coreUsageData: CoreUsageDataSetup; +} + +export class DeprecationsService implements CoreService { + private readonly logger: Logger; + + constructor(private readonly coreContext: CoreContext) { + this.logger = coreContext.logger.get('deprecations'); + } + + public setup({ http }: DeprecationsSetupDeps): InternalDeprecationsServiceSetup { + this.logger.debug('Setting up Deprecations service'); + const deprecationsFactory = new DeprecationsFactory({ + logger: this.logger, + }); + + registerRoutes({ http, deprecationsFactory }); + this.registerConfigDeprecationsInfo(deprecationsFactory); + + return { + createRegistry: (pluginId: string): DeprecationsServiceSetup => { + const registry = deprecationsFactory.createRegistry(pluginId); + return { + registerDeprecations: registry.registerDeprecations, + }; + }, + }; + } + + public start() {} + public stop() {} + + private registerConfigDeprecationsInfo(deprecationsFactory: DeprecationsFactory) { + const handledDeprecatedConfigs = this.coreContext.configService.getHandledDeprecatedConfigs(); + + for (const [pluginId, deprecationsContexts] of handledDeprecatedConfigs) { + const deprecationsRegistry = deprecationsFactory.createRegistry(pluginId); + deprecationsRegistry.registerDeprecations({ + getDeprecations: () => { + return deprecationsContexts.map(({ message, correctionActions, documentationUrl }) => { + return { + level: 'critical', + message, + correctionActions: correctionActions ?? {}, + documentationUrl, + }; + }); + }, + }); + } + } +} diff --git a/src/core/server/deprecations/index.ts b/src/core/server/deprecations/index.ts new file mode 100644 index 000000000000..84fe7ad4221b --- /dev/null +++ b/src/core/server/deprecations/index.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ + +export type { DeprecationsDetails, DeprecationsContext } from './types'; + +export type { + DeprecationsServiceSetup, + InternalDeprecationsServiceSetup, +} from './deprecations_service'; + +export { DeprecationsService } from './deprecations_service'; diff --git a/src/core/server/deprecations/routes/get.ts b/src/core/server/deprecations/routes/get.ts new file mode 100644 index 000000000000..3813dfebe801 --- /dev/null +++ b/src/core/server/deprecations/routes/get.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 + * 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 { IRouter } from '../../http'; +import { DeprecationDependencies } from '../types'; +import { DeprecationsFactory } from '../deprecations_factory'; + +interface RouteDependencies { + deprecationsFactory: DeprecationsFactory; +} + +export const registerGetRoute = (router: IRouter, { deprecationsFactory }: RouteDependencies) => { + router.get( + { + path: '/', + validate: false, + }, + async (context, req, res) => { + const dependencies: DeprecationDependencies = { + esClient: context.core.elasticsearch.client, + savedObjectsClient: context.core.savedObjects.client, + }; + + const deprecationsInfo = await deprecationsFactory.getAllDeprecations(dependencies); + + return res.ok({ + body: { + deprecationsInfo, + }, + }); + } + ); +}; diff --git a/src/core/server/deprecations/routes/index.ts b/src/core/server/deprecations/routes/index.ts new file mode 100644 index 000000000000..db58bec29f7b --- /dev/null +++ b/src/core/server/deprecations/routes/index.ts @@ -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 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 { InternalHttpServiceSetup } from '../../http'; +import { registerGetRoute } from './get'; +import { DeprecationsFactory } from '../deprecations_factory'; + +export function registerRoutes({ + http, + deprecationsFactory, +}: { + http: InternalHttpServiceSetup; + deprecationsFactory: DeprecationsFactory; +}) { + const router = http.createRouter('/api/deprecations'); + registerGetRoute(router, { deprecationsFactory }); +} diff --git a/src/core/server/deprecations/types.ts b/src/core/server/deprecations/types.ts new file mode 100644 index 000000000000..33b9b54c805f --- /dev/null +++ b/src/core/server/deprecations/types.ts @@ -0,0 +1,42 @@ +/* + * 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 { IScopedClusterClient, SavedObjectsClientContract } from '../../server'; + +export interface PluginDeprecationDetails extends DeprecationsDetails { + pluginId: string; +} + +export interface DeprecationsDetails { + message: string; + level: 'warning' | 'critical'; + documentationUrl?: string; + correctionActions: { + api?: { + path: string; + method: 'POST' | 'PUT'; + body?: { + [key: string]: any; + }; + }; + manualSteps?: string[]; + }; +} + +export interface DeprecationsContext { + getDeprecations: ( + dependencies: GetDeprecationsDependencies + ) => MaybePromise; +} + +interface GetDeprecationsDependencies { + esClient: IScopedClusterClient; + savedObjectsClient: SavedObjectsClientContract; +} + +type MaybePromise = T | Promise; diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 3e336dceb83d..36e5cd3c83a1 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -57,7 +57,7 @@ import { StatusServiceSetup } from './status'; import { AppenderConfigType, appendersSchema, LoggingServiceSetup } from './logging'; import { CoreUsageDataStart } from './core_usage_data'; import { I18nServiceSetup } from './i18n'; - +import { DeprecationsServiceSetup, DeprecationsServiceStart } from './deprecations'; // Because of #79265 we need to explicity import, then export these types for // scripts/telemetry_check.js to work as expected import { @@ -88,8 +88,8 @@ export type { ConfigService, ConfigDeprecation, ConfigDeprecationProvider, - ConfigDeprecationLogger, ConfigDeprecationFactory, + ConfigDeprecationHook, EnvironmentMode, PackageInfo, } from './config'; @@ -378,6 +378,11 @@ export type { } from './metrics'; export type { I18nServiceSetup } from './i18n'; +export type { + DeprecationsDetails, + DeprecationsContext, + DeprecationsServiceSetup, +} from './deprecations'; export type { AppCategory } from '../types'; export { DEFAULT_APP_CATEGORIES } from '../utils'; @@ -480,6 +485,8 @@ export interface CoreSetup; + /** {@link DeprecationsServiceSetup} */ + deprecations: DeprecationsServiceSetup; } /** @@ -515,6 +522,8 @@ export interface CoreStart { uiSettings: UiSettingsServiceStart; /** @internal {@link CoreUsageDataStart} */ coreUsageData: CoreUsageDataStart; + /** @internal {@link CoreUsageDataStart} */ + deprecations: DeprecationsServiceStart; } export type { diff --git a/src/core/server/internal_types.ts b/src/core/server/internal_types.ts index 28194a7d0dc3..34193f8d0c35 100644 --- a/src/core/server/internal_types.ts +++ b/src/core/server/internal_types.ts @@ -29,6 +29,7 @@ import { InternalStatusServiceSetup } from './status'; import { InternalLoggingServiceSetup } from './logging'; import { CoreUsageDataStart } from './core_usage_data'; import { I18nServiceSetup } from './i18n'; +import { InternalDeprecationsServiceSetup } from './deprecations'; /** @internal */ export interface InternalCoreSetup { @@ -45,6 +46,7 @@ export interface InternalCoreSetup { httpResources: InternalHttpResourcesSetup; logging: InternalLoggingServiceSetup; metrics: InternalMetricsServiceSetup; + deprecations: InternalDeprecationsServiceSetup; } /** diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index 74451f38b893..2253cfc9b9ff 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -165,6 +165,7 @@ export function createPluginSetupContext( register: deps.uiSettings.register, }, getStartServices: () => plugin.startDependencies, + deprecations: deps.deprecations.createRegistry(plugin.name), }; } diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 337dfa882430..ba96607048b5 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -41,6 +41,7 @@ import { ContextService } from './context'; import { RequestHandlerContext } from '.'; import { InternalCoreSetup, InternalCoreStart, ServiceConfigDescriptor } from './internal_types'; import { CoreUsageDataService } from './core_usage_data'; +import { DeprecationsService } from './deprecations'; import { CoreRouteHandlerContext } from './core_route_handler_context'; import { config as externalUrlConfig } from './external_url'; @@ -67,6 +68,7 @@ export class Server { private readonly coreApp: CoreApp; private readonly coreUsageData: CoreUsageDataService; private readonly i18n: I18nService; + private readonly deprecations: DeprecationsService; private readonly savedObjectsStartPromise: Promise; private resolveSavedObjectsStartPromise?: (value: SavedObjectsServiceStart) => void; @@ -102,6 +104,7 @@ export class Server { this.logging = new LoggingService(core); this.coreUsageData = new CoreUsageDataService(core); this.i18n = new I18nService(core); + this.deprecations = new DeprecationsService(core); this.savedObjectsStartPromise = new Promise((resolve) => { this.resolveSavedObjectsStartPromise = resolve; @@ -195,6 +198,12 @@ export class Server { loggingSystem: this.loggingSystem, }); + const deprecationsSetup = this.deprecations.setup({ + http: httpSetup, + elasticsearch: elasticsearchServiceSetup, + coreUsageData: coreUsageDataSetup, + }); + const coreSetup: InternalCoreSetup = { capabilities: capabilitiesSetup, context: contextServiceSetup, @@ -209,6 +218,7 @@ export class Server { httpResources: httpResourcesSetup, logging: loggingSetup, metrics: metricsSetup, + deprecations: deprecationsSetup, }; const pluginsSetup = await this.plugins.setup(coreSetup); @@ -288,6 +298,7 @@ export class Server { await this.metrics.stop(); await this.status.stop(); await this.logging.stop(); + this.deprecations.stop(); } private registerCoreContext(coreSetup: InternalCoreSetup) { diff --git a/src/plugins/kibana_legacy/server/index.ts b/src/plugins/kibana_legacy/server/index.ts index 15511e1e9f7f..da0bee68a297 100644 --- a/src/plugins/kibana_legacy/server/index.ts +++ b/src/plugins/kibana_legacy/server/index.ts @@ -6,12 +6,7 @@ * Side Public License, v 1. */ -import { - ConfigDeprecationLogger, - CoreSetup, - CoreStart, - PluginConfigDescriptor, -} from 'kibana/server'; +import { ConfigDeprecationHook, CoreSetup, CoreStart, PluginConfigDescriptor } from 'kibana/server'; import { get } from 'lodash'; import { configSchema, ConfigSchema } from '../config'; @@ -24,16 +19,22 @@ export const config: PluginConfigDescriptor = { deprecations: ({ renameFromRoot }) => [ // TODO: Remove deprecation once defaultAppId is deleted renameFromRoot('kibana.defaultAppId', 'kibana_legacy.defaultAppId', true), - (completeConfig: Record, rootPath: string, log: ConfigDeprecationLogger) => { + ( + completeConfig: Record, + rootPath: string, + configDeprecationHook: ConfigDeprecationHook + ) => { if ( get(completeConfig, 'kibana.defaultAppId') === undefined && get(completeConfig, 'kibana_legacy.defaultAppId') === undefined ) { return completeConfig; } - log( - `kibana.defaultAppId is deprecated and will be removed in 8.0. Please use the \`defaultRoute\` advanced setting instead` - ); + configDeprecationHook({ + type: 'unused', + oldConfigFullPath: 'kibana.defaultAppId', + logMsg: `kibana.defaultAppId is deprecated and will be removed in 8.0. Please use the \`defaultRoute\` advanced setting instead`, + }); return completeConfig; }, ], diff --git a/src/plugins/timelion/server/deprecations.ts b/src/plugins/timelion/server/deprecations.ts new file mode 100644 index 000000000000..f20b9b6c134d --- /dev/null +++ b/src/plugins/timelion/server/deprecations.ts @@ -0,0 +1,70 @@ +/* + * 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 { + CoreStart, + SavedObjectsClient, + Logger, + DeprecationsContext, + DeprecationsDetails, +} from 'src/core/server'; + +export const getTimelionSheetsCount = async ( + savedObjectsClient: Pick +) => { + const { total } = await savedObjectsClient.find({ type: 'timelion-sheet', perPage: 1 }); + return total; +}; + +export const showWarningMessageIfTimelionSheetWasFound = async ( + core: CoreStart, + logger: Logger +) => { + const { savedObjects } = core; + const savedObjectsClient = savedObjects.createInternalRepository(); + const count = await getTimelionSheetsCount(savedObjectsClient); + if (count > 0) { + logger.warn( + 'Deprecated since 7.0, the Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard. See https://www.elastic.co/guide/en/kibana/current/create-panels-with-timelion.html.' + ); + } +}; + +/** + * Deprecated since 7.0, the Timelion app will be removed in 8.0. + * To continue using your Timelion worksheets, migrate them to a dashboard. + * + * @link https://www.elastic.co/guide/en/kibana/master/timelion.html#timelion-deprecation + **/ +export const getDeprecations: DeprecationsContext['getDeprecations'] = async ({ + savedObjectsClient, +}) => { + const deprecations: DeprecationsDetails[] = []; + const count = await getTimelionSheetsCount(savedObjectsClient); + + if (count > 0) { + deprecations.push({ + message: `You have ${count} Timelion worksheets. The Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard.`, + documentationUrl: + 'https://www.elastic.co/guide/en/kibana/master/dashboard.html#timelion-deprecation', + level: 'warning', + correctionActions: { + manualSteps: [ + 'Navigate to the Kibana Dashboard and click "Create dashboard".', + 'Select Timelion from the "New Visualization" window.', + 'Open a new tab, open the Timelion app, select the chart you want to copy, then copy the chart expression.', + 'Go to Timelion, paste the chart expression in the Timelion expression field, then click Update.', + 'In the toolbar, click Save.', + 'On the Save visualization window, enter the visualization Title, then click Save and return.', + ], + }, + }); + } + + return deprecations; +}; diff --git a/src/plugins/timelion/server/plugin.ts b/src/plugins/timelion/server/plugin.ts index 66348c572117..d647d9f05912 100644 --- a/src/plugins/timelion/server/plugin.ts +++ b/src/plugins/timelion/server/plugin.ts @@ -11,30 +11,7 @@ import { i18n } from '@kbn/i18n'; import { schema } from '@kbn/config-schema'; import { TimelionConfigType } from './config'; import { timelionSheetSavedObjectType } from './saved_objects'; - -/** - * Deprecated since 7.0, the Timelion app will be removed in 8.0. - * To continue using your Timelion worksheets, migrate them to a dashboard. - * - * @link https://www.elastic.co/guide/en/kibana/master/timelion.html#timelion-deprecation - **/ -const showWarningMessageIfTimelionSheetWasFound = (core: CoreStart, logger: Logger) => { - const { savedObjects } = core; - const savedObjectsClient = savedObjects.createInternalRepository(); - - savedObjectsClient - .find({ - type: 'timelion-sheet', - perPage: 1, - }) - .then( - ({ total }) => - total && - logger.warn( - 'Deprecated since 7.0, the Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard. See https://www.elastic.co/guide/en/kibana/current/create-panels-with-timelion.html.' - ) - ); -}; +import { getDeprecations, showWarningMessageIfTimelionSheetWasFound } from './deprecations'; export class TimelionPlugin implements Plugin { private logger: Logger; @@ -86,6 +63,8 @@ export class TimelionPlugin implements Plugin { schema: schema.number(), }, }); + + core.deprecations.registerDeprecations({ getDeprecations }); } start(core: CoreStart) { showWarningMessageIfTimelionSheetWasFound(core, this.logger); diff --git a/x-pack/plugins/monitoring/server/deprecations.ts b/x-pack/plugins/monitoring/server/deprecations.ts index 47a01385c630..e9de116fea66 100644 --- a/x-pack/plugins/monitoring/server/deprecations.ts +++ b/x-pack/plugins/monitoring/server/deprecations.ts @@ -44,43 +44,43 @@ export const deprecations = ({ 'monitoring.ui.elasticsearch.logFetchCount' ), renameFromRoot('xpack.monitoring', 'monitoring'), - (config, fromPath, logger) => { + (config, fromPath, configDeprecationHook) => { const clusterAlertsEnabled = get(config, 'cluster_alerts.enabled'); const emailNotificationsEnabled = clusterAlertsEnabled && get(config, 'cluster_alerts.email_notifications.enabled'); if (emailNotificationsEnabled && !get(config, CLUSTER_ALERTS_ADDRESS_CONFIG_KEY)) { - logger( - `Config key [${fromPath}.${CLUSTER_ALERTS_ADDRESS_CONFIG_KEY}] will be required for email notifications to work in 7.0."` - ); + configDeprecationHook({ + message: `Config key [${fromPath}.${CLUSTER_ALERTS_ADDRESS_CONFIG_KEY}] will be required for email notifications to work in 7.0."`, + }); } return config; }, - (config, fromPath, logger) => { + (config, fromPath, configDeprecationHook) => { const es: Record = get(config, 'elasticsearch'); if (es) { if (es.username === 'elastic') { - logger( - `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.` - ); + configDeprecationHook({ + message: `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.`, + }); } else if (es.username === 'kibana') { - logger( - `Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.` - ); + configDeprecationHook({ + message: `Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.`, + }); } } return config; }, - (config, fromPath, logger) => { + (config, fromPath, configDeprecationHook) => { const ssl: Record = get(config, 'elasticsearch.ssl'); if (ssl) { if (ssl.key !== undefined && ssl.certificate === undefined) { - logger( - `Setting [${fromPath}.key] without [${fromPath}.certificate] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.` - ); + configDeprecationHook({ + message: `Setting [${fromPath}.key] without [${fromPath}.certificate] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`, + }); } else if (ssl.certificate !== undefined && ssl.key === undefined) { - logger( - `Setting [${fromPath}.certificate] without [${fromPath}.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.` - ); + configDeprecationHook({ + message: `Setting [${fromPath}.certificate] without [${fromPath}.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`, + }); } } return config; diff --git a/x-pack/plugins/spaces/server/config.ts b/x-pack/plugins/spaces/server/config.ts index bc53f43c3e8c..46b102a88797 100644 --- a/x-pack/plugins/spaces/server/config.ts +++ b/x-pack/plugins/spaces/server/config.ts @@ -24,11 +24,11 @@ export function createConfig$(context: PluginInitializerContext) { return context.config.create>(); } -const disabledDeprecation: ConfigDeprecation = (config, fromPath, log) => { +const disabledDeprecation: ConfigDeprecation = (config, fromPath, configDeprecationHook) => { if (config.xpack?.spaces?.enabled === false) { - log( - `Disabling the spaces plugin (xpack.spaces.enabled) will not be supported in the next major version (8.0)` - ); + configDeprecationHook({ + message: `Disabling the spaces plugin (xpack.spaces.enabled) will not be supported in the next major version (8.0)`, + }); } return config; }; From d1ea48b82c1be51e53d46d757610316bb4c737ad Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 18 Mar 2021 13:55:22 +0200 Subject: [PATCH 02/23] update docs and names --- ...ugin-core-server.coresetup.deprecations.md | 13 ++++ .../kibana-plugin-core-server.coresetup.md | 1 + ...r.deprecationsdetails.correctionactions.md | 20 +++++ ...er.deprecationsdetails.documentationurl.md | 11 +++ ...n-core-server.deprecationsdetails.level.md | 11 +++ ...-plugin-core-server.deprecationsdetails.md | 21 ++++++ ...core-server.deprecationsdetails.message.md | 11 +++ ...in-core-server.deprecationsservicesetup.md | 52 +++++++++++++ ...ationsservicesetup.registerdeprecations.md | 11 +++ .../core/server/kibana-plugin-core-server.md | 5 +- ...isterdeprecationsconfig.getdeprecations.md | 11 +++ ...-core-server.registerdeprecationsconfig.md | 18 +++++ ...-core-server.savedobjectsclientcontract.md | 2 +- .../kbn-config/src/config_service.mock.ts | 2 +- packages/kbn-config/src/config_service.ts | 6 +- .../deprecation/apply_deprecations.test.ts | 8 +- .../src/deprecation/apply_deprecations.ts | 6 +- .../deprecation/deprecation_factory.test.ts | 36 +++++---- .../src/deprecation/deprecation_factory.ts | 75 +++++++++++-------- packages/kbn-config/src/deprecation/index.ts | 2 +- packages/kbn-config/src/deprecation/types.ts | 31 +++++--- .../config/deprecation/core_deprecations.ts | 60 +++++++-------- .../deprecations/deprecations_factory.test.ts | 18 ++--- .../deprecations/deprecations_factory.ts | 10 +-- .../deprecations_registry.test.ts | 4 +- .../deprecations/deprecations_registry.ts | 8 +- .../deprecations/deprecations_service.ts | 16 ++-- src/core/server/deprecations/index.ts | 2 +- src/core/server/deprecations/routes/get.ts | 4 +- src/core/server/deprecations/types.ts | 14 ++-- .../elasticsearch/elasticsearch_config.ts | 32 ++++---- src/core/server/index.ts | 6 +- src/core/server/kibana_config.ts | 9 ++- src/core/server/server.api.md | 48 +++++++++++- src/plugins/kibana_legacy/server/index.ts | 17 +++-- src/plugins/timelion/server/deprecations.ts | 6 +- src/plugins/vis_type_timelion/server/index.ts | 2 +- .../vis_type_timeseries/server/index.ts | 10 ++- .../plugins/monitoring/server/deprecations.ts | 16 ++-- x-pack/plugins/spaces/server/config.ts | 4 +- 40 files changed, 448 insertions(+), 191 deletions(-) create mode 100644 docs/development/core/server/kibana-plugin-core-server.coresetup.deprecations.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.correctionactions.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.documentationurl.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.level.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.message.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.md diff --git a/docs/development/core/server/kibana-plugin-core-server.coresetup.deprecations.md b/docs/development/core/server/kibana-plugin-core-server.coresetup.deprecations.md new file mode 100644 index 000000000000..436cc29b6e34 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.coresetup.deprecations.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CoreSetup](./kibana-plugin-core-server.coresetup.md) > [deprecations](./kibana-plugin-core-server.coresetup.deprecations.md) + +## CoreSetup.deprecations property + +[DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) + +Signature: + +```typescript +deprecations: DeprecationsServiceSetup; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.coresetup.md b/docs/development/core/server/kibana-plugin-core-server.coresetup.md index 1171dbad570c..b37ac80db87d 100644 --- a/docs/development/core/server/kibana-plugin-core-server.coresetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.coresetup.md @@ -18,6 +18,7 @@ export interface CoreSetupCapabilitiesSetup | [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) | | [context](./kibana-plugin-core-server.coresetup.context.md) | ContextSetup | [ContextSetup](./kibana-plugin-core-server.contextsetup.md) | +| [deprecations](./kibana-plugin-core-server.coresetup.deprecations.md) | DeprecationsServiceSetup | [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) | | [elasticsearch](./kibana-plugin-core-server.coresetup.elasticsearch.md) | ElasticsearchServiceSetup | [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) | | [getStartServices](./kibana-plugin-core-server.coresetup.getstartservices.md) | StartServicesAccessor<TPluginsStart, TStart> | [StartServicesAccessor](./kibana-plugin-core-server.startservicesaccessor.md) | | [http](./kibana-plugin-core-server.coresetup.http.md) | HttpServiceSetup & {
resources: HttpResources;
} | [HttpServiceSetup](./kibana-plugin-core-server.httpservicesetup.md) | diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.correctionactions.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.correctionactions.md new file mode 100644 index 000000000000..071396c81c58 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.correctionactions.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) > [correctiveActions](./kibana-plugin-core-server.deprecationsdetails.correctionactions.md) + +## DeprecationsDetails.correctiveActions property + +Signature: + +```typescript +correctiveActions: { + api?: { + path: string; + method: 'POST' | 'PUT'; + body?: { + [key: string]: any; + }; + }; + manualSteps?: string[]; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.documentationurl.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.documentationurl.md new file mode 100644 index 000000000000..467d6d76cf84 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.documentationurl.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) > [documentationUrl](./kibana-plugin-core-server.deprecationsdetails.documentationurl.md) + +## DeprecationsDetails.documentationUrl property + +Signature: + +```typescript +documentationUrl?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.level.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.level.md new file mode 100644 index 000000000000..5f0dbe8d8c4b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.level.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) > [level](./kibana-plugin-core-server.deprecationsdetails.level.md) + +## DeprecationsDetails.level property + +Signature: + +```typescript +level: 'warning' | 'critical'; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.md new file mode 100644 index 000000000000..00488070f3c2 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) + +## DeprecationsDetails interface + +Signature: + +```typescript +export interface DeprecationsDetails +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [correctiveActions](./kibana-plugin-core-server.deprecationsdetails.correctionactions.md) | {
api?: {
path: string;
method: 'POST' | 'PUT';
body?: {
[key: string]: any;
};
};
manualSteps?: string[];
} | | +| [documentationUrl](./kibana-plugin-core-server.deprecationsdetails.documentationurl.md) | string | | +| [level](./kibana-plugin-core-server.deprecationsdetails.level.md) | 'warning' | 'critical' | | +| [message](./kibana-plugin-core-server.deprecationsdetails.message.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.message.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.message.md new file mode 100644 index 000000000000..d79a4c9bd799 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.message.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) > [message](./kibana-plugin-core-server.deprecationsdetails.message.md) + +## DeprecationsDetails.message property + +Signature: + +```typescript +message: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md new file mode 100644 index 000000000000..9f65568bb87f --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md @@ -0,0 +1,52 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) + +## DeprecationsServiceSetup interface + +Deprecations Service is a mechanism to allow plugins to communiicate deprecated features. + +Signature: + +```typescript +export interface DeprecationsServiceSetup +``` + +## Example + + +```ts +import { DeprecationsDetails, GetDeprecationsContext, CoreSetup } from 'src/core/server'; + +const getDeprecations = async ({ esClient, savedObjectsClient }: GetDeprecationsContext): DeprecationsDetails[] => { + return [ + { + message: string; + level: 'warning' | 'critical'; + documentationUrl?: string; + correctiveActions: { + api?: { + path: string; + method: 'POST' | 'PUT'; + body?: { [key: string]: any }, + }, + manualSteps?: string[]; + } + } + ] +} + +export class Plugin() { + setup: (core: CoreSetup) => { + core.deprecations.registerDeprecations({ getDeprecations }); + } +} + +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [registerDeprecations](./kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md) | DeprecationsRegistry['registerDeprecations'] | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md new file mode 100644 index 000000000000..f79e8875238b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) > [registerDeprecations](./kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md) + +## DeprecationsServiceSetup.registerDeprecations property + +Signature: + +```typescript +registerDeprecations: DeprecationsRegistry['registerDeprecations']; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index b4faa4299a92..c0f535e2e859 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -69,7 +69,9 @@ The plugin integrates with the core system via lifecycle events: `setup` | [DeprecationAPIClientParams](./kibana-plugin-core-server.deprecationapiclientparams.md) | | | [DeprecationAPIResponse](./kibana-plugin-core-server.deprecationapiresponse.md) | | | [DeprecationInfo](./kibana-plugin-core-server.deprecationinfo.md) | | +| [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) | | | [DeprecationSettings](./kibana-plugin-core-server.deprecationsettings.md) | UiSettings deprecation field options. | +| [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) | Deprecations Service is a mechanism to allow plugins to communiicate deprecated features. | | [DiscoveredPlugin](./kibana-plugin-core-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. | | [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) | | | [ElasticsearchServiceStart](./kibana-plugin-core-server.elasticsearchservicestart.md) | | @@ -127,6 +129,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [PluginConfigDescriptor](./kibana-plugin-core-server.pluginconfigdescriptor.md) | Describes a plugin configuration properties. | | [PluginInitializerContext](./kibana-plugin-core-server.plugininitializercontext.md) | Context that's available to plugins during initialization stage. | | [PluginManifest](./kibana-plugin-core-server.pluginmanifest.md) | Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. | +| [RegisterDeprecationsConfig](./kibana-plugin-core-server.registerdeprecationsconfig.md) | | | [RequestHandlerContext](./kibana-plugin-core-server.requesthandlercontext.md) | Plugin specific context passed to a route handler.Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.client](./kibana-plugin-core-server.iscopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [elasticsearch.legacy.client](./kibana-plugin-core-server.legacyscopedclusterclient.md) - The legacy Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request | | [ResolveCapabilitiesOptions](./kibana-plugin-core-server.resolvecapabilitiesoptions.md) | Defines a set of additional options for the resolveCapabilities method of [CapabilitiesStart](./kibana-plugin-core-server.capabilitiesstart.md). | | [RouteConfig](./kibana-plugin-core-server.routeconfig.md) | Route specific configuration. | @@ -300,7 +303,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectAttributeSingle](./kibana-plugin-core-server.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-core-server.savedobjectattribute.md) | | [SavedObjectMigrationFn](./kibana-plugin-core-server.savedobjectmigrationfn.md) | A migration function for a [saved object type](./kibana-plugin-core-server.savedobjectstype.md) used to migrate it to a given version | | [SavedObjectSanitizedDoc](./kibana-plugin-core-server.savedobjectsanitizeddoc.md) | Describes Saved Object documents that have passed through the migration framework and are guaranteed to have a references root property. | -| [SavedObjectsClientContract](./kibana-plugin-core-server.savedobjectsclientcontract.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state.\#\# SavedObjectsClient errorsSince the SavedObjectsClient has its hands in everything we are a little paranoid about the way we present errors back to application code. Ideally, all errors will be either:1. Caused by bad implementation (ie. undefined is not a function) and as such unpredictable 2. An error that has been classified and decorated appropriately by the decorators in [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md)Type 1 errors are inevitable, but since all expected/handle-able errors should be Type 2 the isXYZError() helpers exposed at SavedObjectsErrorHelpers should be used to understand and manage error responses from the SavedObjectsClient.Type 2 errors are decorated versions of the source error, so if the elasticsearch client threw an error it will be decorated based on its type. That means that rather than looking for error.body.error.type or doing substring checks on error.body.error.reason, just use the helpers to understand the meaning of the error:\`\`\`js if (SavedObjectsErrorHelpers.isNotFoundError(error)) { // handle 404 }if (SavedObjectsErrorHelpers.isNotAuthorizedError(error)) { // 401 handling should be automatic, but in case you wanted to know }// always rethrow the error unless you handle it throw error; \`\`\`\#\#\# 404s from missing indexFrom the perspective of application code and APIs the SavedObjectsClient is a black box that persists objects. One of the internal details that users have no control over is that we use an elasticsearch index for persistance and that index might be missing.At the time of writing we are in the process of transitioning away from the operating assumption that the SavedObjects index is always available. Part of this transition is handling errors resulting from an index missing. These used to trigger a 500 error in most cases, and in others cause 404s with different error messages.From my (Spencer) perspective, a 404 from the SavedObjectsApi is a 404; The object the request/call was targeting could not be found. This is why \#14141 takes special care to ensure that 404 errors are generic and don't distinguish between index missing or document missing.See [SavedObjectsClient](./kibana-plugin-core-server.savedobjectsclient.md) See [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) | +| [SavedObjectsClientContract](./kibana-plugin-core-server.savedobjectsclientcontract.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state.\#\# SavedObjectsClient errorsSince the SavedObjectsClient has its hands in everything we are a little paranoid about the way we present errors back to to application code. Ideally, all errors will be either:1. Caused by bad implementation (ie. undefined is not a function) and as such unpredictable 2. An error that has been classified and decorated appropriately by the decorators in [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md)Type 1 errors are inevitable, but since all expected/handle-able errors should be Type 2 the isXYZError() helpers exposed at SavedObjectsErrorHelpers should be used to understand and manage error responses from the SavedObjectsClient.Type 2 errors are decorated versions of the source error, so if the elasticsearch client threw an error it will be decorated based on its type. That means that rather than looking for error.body.error.type or doing substring checks on error.body.error.reason, just use the helpers to understand the meaning of the error:\`\`\`js if (SavedObjectsErrorHelpers.isNotFoundError(error)) { // handle 404 }if (SavedObjectsErrorHelpers.isNotAuthorizedError(error)) { // 401 handling should be automatic, but in case you wanted to know }// always rethrow the error unless you handle it throw error; \`\`\`\#\#\# 404s from missing indexFrom the perspective of application code and APIs the SavedObjectsClient is a black box that persists objects. One of the internal details that users have no control over is that we use an elasticsearch index for persistance and that index might be missing.At the time of writing we are in the process of transitioning away from the operating assumption that the SavedObjects index is always available. Part of this transition is handling errors resulting from an index missing. These used to trigger a 500 error in most cases, and in others cause 404s with different error messages.From my (Spencer) perspective, a 404 from the SavedObjectsApi is a 404; The object the request/call was targeting could not be found. This is why \#14141 takes special care to ensure that 404 errors are generic and don't distinguish between index missing or document missing.See [SavedObjectsClient](./kibana-plugin-core-server.savedobjectsclient.md) See [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) | | [SavedObjectsClientFactory](./kibana-plugin-core-server.savedobjectsclientfactory.md) | Describes the factory used to create instances of the Saved Objects Client. | | [SavedObjectsClientFactoryProvider](./kibana-plugin-core-server.savedobjectsclientfactoryprovider.md) | Provider to invoke to retrieve a [SavedObjectsClientFactory](./kibana-plugin-core-server.savedobjectsclientfactory.md). | | [SavedObjectsClientWrapperFactory](./kibana-plugin-core-server.savedobjectsclientwrapperfactory.md) | Describes the factory used to create instances of Saved Objects Client Wrappers. | diff --git a/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md b/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md new file mode 100644 index 000000000000..16b416363e4f --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [RegisterDeprecationsConfig](./kibana-plugin-core-server.registerdeprecationsconfig.md) > [getDeprecations](./kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md) + +## RegisterDeprecationsConfig.getDeprecations property + +Signature: + +```typescript +getDeprecations: (dependencies: GetDeprecationsContext) => MaybePromise; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.md b/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.md new file mode 100644 index 000000000000..7edc5e3cf2b6 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [RegisterDeprecationsConfig](./kibana-plugin-core-server.registerdeprecationsconfig.md) + +## RegisterDeprecationsConfig interface + +Signature: + +```typescript +export interface RegisterDeprecationsConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [getDeprecations](./kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md) | (dependencies: GetDeprecationsContext) => MaybePromise<DeprecationsDetails[]> | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientcontract.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientcontract.md index 537cfbc17567..610356a73312 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientcontract.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientcontract.md @@ -8,7 +8,7 @@ Saved Objects is Kibana's data persisentence mechanism allowing plugins to use E \#\# SavedObjectsClient errors -Since the SavedObjectsClient has its hands in everything we are a little paranoid about the way we present errors back to application code. Ideally, all errors will be either: +Since the SavedObjectsClient has its hands in everything we are a little paranoid about the way we present errors back to to application code. Ideally, all errors will be either: 1. Caused by bad implementation (ie. undefined is not a function) and as such unpredictable 2. An error that has been classified and decorated appropriately by the decorators in [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) diff --git a/packages/kbn-config/src/config_service.mock.ts b/packages/kbn-config/src/config_service.mock.ts index 5019d97b3e20..83fbf20b5c0b 100644 --- a/packages/kbn-config/src/config_service.mock.ts +++ b/packages/kbn-config/src/config_service.mock.ts @@ -34,7 +34,7 @@ const createConfigServiceMock = ({ mocked.getUsedPaths.mockResolvedValue([]); mocked.getUnusedPaths.mockResolvedValue([]); mocked.isEnabledAtPath.mockResolvedValue(true); - mocked.getHandledDeprecatedConfigs.mockReturnValue(new Map()); + mocked.getHandledDeprecatedConfigs.mockReturnValue([]); return mocked; }; diff --git a/packages/kbn-config/src/config_service.ts b/packages/kbn-config/src/config_service.ts index 678cb05421db..59f5ae054e25 100644 --- a/packages/kbn-config/src/config_service.ts +++ b/packages/kbn-config/src/config_service.ts @@ -21,7 +21,7 @@ import { ConfigDeprecationWithContext, ConfigDeprecationProvider, configDeprecationFactory, - DeprecatedConfigContext, + DeprecatedConfigDetails, } from './deprecation'; import { LegacyObjectToConfigAdapter } from './legacy'; @@ -44,7 +44,7 @@ export class ConfigService { private readonly handledPaths: Set = new Set(); private readonly schemas = new Map>(); private readonly deprecations = new BehaviorSubject([]); - private readonly handledDeprecatedConfigs = new Map(); + private readonly handledDeprecatedConfigs = new Map(); constructor( private readonly rawConfigProvider: RawConfigurationProvider, @@ -195,7 +195,7 @@ export class ConfigService { const rawConfig = await this.rawConfigProvider.getConfig$().pipe(take(1)).toPromise(); const deprecations = await this.deprecations.pipe(take(1)).toPromise(); const deprecationMessages: string[] = []; - const onHandleDeprecationHook = (pluginId: string) => (context: DeprecatedConfigContext) => { + const onHandleDeprecationHook = (pluginId: string) => (context: DeprecatedConfigDetails) => { deprecationMessages.push(context.message); const handledDeprecatedConfig = this.handledDeprecatedConfigs.get(pluginId) || []; handledDeprecatedConfig.push(context); diff --git a/packages/kbn-config/src/deprecation/apply_deprecations.test.ts b/packages/kbn-config/src/deprecation/apply_deprecations.test.ts index 78ffea1a185f..62970613db42 100644 --- a/packages/kbn-config/src/deprecation/apply_deprecations.test.ts +++ b/packages/kbn-config/src/deprecation/apply_deprecations.test.ts @@ -33,7 +33,7 @@ describe('applyDeprecations', () => { }); it('calls handlers with correct arguments', () => { - const configDeprecationHook = () => undefined; + const deprecationHook = () => undefined; const initialConfig = { foo: 'bar', deprecated: 'deprecated' }; const alteredConfig = { foo: 'bar' }; @@ -43,11 +43,11 @@ describe('applyDeprecations', () => { applyDeprecations( initialConfig, [wrapHandler(handlerA, 'pathA'), wrapHandler(handlerB, 'pathB')], - () => configDeprecationHook + () => deprecationHook ); - expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', configDeprecationHook); - expect(handlerB).toHaveBeenCalledWith(alteredConfig, 'pathB', configDeprecationHook); + expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', deprecationHook); + expect(handlerB).toHaveBeenCalledWith(alteredConfig, 'pathB', deprecationHook); }); it('returns the migrated config', () => { diff --git a/packages/kbn-config/src/deprecation/apply_deprecations.ts b/packages/kbn-config/src/deprecation/apply_deprecations.ts index 7e2941cb2a75..62306683b993 100644 --- a/packages/kbn-config/src/deprecation/apply_deprecations.ts +++ b/packages/kbn-config/src/deprecation/apply_deprecations.ts @@ -11,7 +11,7 @@ import { ConfigDeprecationWithContext, ConfigDeprecationHook } from './types'; const noopConfigDeprecationHook: () => ConfigDeprecationHook = () => () => undefined; /** - * Applies deprecations on given configuration and passes handled deprecation configDeprecationHook + * Applies deprecations on given configuration and passes handled deprecation deprecationHook * This hook is used for logging any deprecation warning using provided logger. * This hook is used for exposing deprecated configs that must be handled by the user before upgrading to next major. * @@ -20,11 +20,11 @@ const noopConfigDeprecationHook: () => ConfigDeprecationHook = () => () => undef export const applyDeprecations = ( config: Record, deprecations: ConfigDeprecationWithContext[], - configDeprecationHook: (pluginId: string) => ConfigDeprecationHook = noopConfigDeprecationHook + deprecationHook: (pluginId: string) => ConfigDeprecationHook = noopConfigDeprecationHook ) => { let processed = cloneDeep(config); deprecations.forEach(({ deprecation, path }) => { - processed = deprecation(processed, path, configDeprecationHook(path)); + processed = deprecation(processed, path, deprecationHook(path)); }); return processed; }; diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts index d76e3ea7536f..b3c4e94c700e 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts @@ -13,7 +13,7 @@ describe('DeprecationFactory', () => { const { rename, unused, renameFromRoot, unusedFromRoot } = configDeprecationFactory; let deprecationMessages: string[]; - const logger: ConfigDeprecationHook = ({ message }) => deprecationMessages.push(message); + const deprecationHook: ConfigDeprecationHook = ({ message }) => deprecationMessages.push(message); beforeEach(() => { deprecationMessages = []; @@ -30,7 +30,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }; - const processed = rename('deprecated', 'renamed')(rawConfig, 'myplugin', logger); + const processed = rename('deprecated', 'renamed')(rawConfig, 'myplugin', deprecationHook); expect(processed).toEqual({ myplugin: { renamed: 'toberenamed', @@ -56,7 +56,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }; - const processed = rename('deprecated', 'new')(rawConfig, 'myplugin', logger); + const processed = rename('deprecated', 'new')(rawConfig, 'myplugin', deprecationHook); expect(processed).toEqual({ myplugin: { new: 'new', @@ -83,7 +83,7 @@ describe('DeprecationFactory', () => { const processed = rename('oldsection.deprecated', 'newsection.renamed')( rawConfig, 'myplugin', - logger + deprecationHook ); expect(processed).toEqual({ myplugin: { @@ -110,7 +110,7 @@ describe('DeprecationFactory', () => { renamed: 'renamed', }, }; - const processed = rename('deprecated', 'renamed')(rawConfig, 'myplugin', logger); + const processed = rename('deprecated', 'renamed')(rawConfig, 'myplugin', deprecationHook); expect(processed).toEqual({ myplugin: { renamed: 'renamed', @@ -138,7 +138,7 @@ describe('DeprecationFactory', () => { const processed = renameFromRoot('myplugin.deprecated', 'myplugin.renamed')( rawConfig, 'does-not-matter', - logger + deprecationHook ); expect(processed).toEqual({ myplugin: { @@ -169,7 +169,7 @@ describe('DeprecationFactory', () => { const processed = renameFromRoot('oldplugin.deprecated', 'newplugin.renamed')( rawConfig, 'does-not-matter', - logger + deprecationHook ); expect(processed).toEqual({ oldplugin: { @@ -200,7 +200,7 @@ describe('DeprecationFactory', () => { const processed = renameFromRoot('myplugin.deprecated', 'myplugin.new')( rawConfig, 'does-not-matter', - logger + deprecationHook ); expect(processed).toEqual({ myplugin: { @@ -224,7 +224,7 @@ describe('DeprecationFactory', () => { const processed = renameFromRoot('myplugin.deprecated', 'myplugin.renamed')( rawConfig, 'does-not-matter', - logger + deprecationHook ); expect(processed).toEqual({ myplugin: { @@ -250,7 +250,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }; - const processed = unused('deprecated')(rawConfig, 'myplugin', logger); + const processed = unused('deprecated')(rawConfig, 'myplugin', deprecationHook); expect(processed).toEqual({ myplugin: { valid: 'valid', @@ -278,7 +278,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }; - const processed = unused('section.deprecated')(rawConfig, 'myplugin', logger); + const processed = unused('section.deprecated')(rawConfig, 'myplugin', deprecationHook); expect(processed).toEqual({ myplugin: { valid: 'valid', @@ -304,7 +304,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }; - const processed = unused('deprecated')(rawConfig, 'myplugin', logger); + const processed = unused('deprecated')(rawConfig, 'myplugin', deprecationHook); expect(processed).toEqual({ myplugin: { valid: 'valid', @@ -328,7 +328,11 @@ describe('DeprecationFactory', () => { property: 'value', }, }; - const processed = unusedFromRoot('myplugin.deprecated')(rawConfig, 'does-not-matter', logger); + const processed = unusedFromRoot('myplugin.deprecated')( + rawConfig, + 'does-not-matter', + deprecationHook + ); expect(processed).toEqual({ myplugin: { valid: 'valid', @@ -353,7 +357,11 @@ describe('DeprecationFactory', () => { property: 'value', }, }; - const processed = unusedFromRoot('myplugin.deprecated')(rawConfig, 'does-not-matter', logger); + const processed = unusedFromRoot('myplugin.deprecated')( + rawConfig, + 'does-not-matter', + deprecationHook + ); expect(processed).toEqual({ myplugin: { valid: 'valid', diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.ts b/packages/kbn-config/src/deprecation/deprecation_factory.ts index 5e0ad9b978e6..836bb338109d 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.ts @@ -9,15 +9,20 @@ import { get } from 'lodash'; import { set } from '@elastic/safer-lodash-set'; import { unset } from '@kbn/std'; -import { ConfigDeprecation, ConfigDeprecationHook, ConfigDeprecationFactory } from './types'; +import { + ConfigDeprecation, + ConfigDeprecationHook, + ConfigDeprecationFactory, + DeprecatedConfigDetails, +} from './types'; const _rename = ( config: Record, rootPath: string, - configDeprecationHook: ConfigDeprecationHook, + deprecationHook: ConfigDeprecationHook, oldKey: string, newKey: string, - silent?: boolean + details?: Partial ) => { const fullOldPath = getPath(rootPath, oldKey); const oldValue = get(config, fullOldPath); @@ -32,23 +37,23 @@ const _rename = ( if (newValue === undefined) { set(config, fullNewPath, oldValue); - configDeprecationHook({ - silent, + deprecationHook({ message: `"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}"`, - correctionActions: { + correctiveActions: { manualSteps: [`Replace "${fullOldPath}" in the kibana.yml file with "${fullNewPath}"`], }, + ...details, }); } else { - configDeprecationHook({ - silent, + deprecationHook({ message: `"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}". However both key are present, ignoring "${fullOldPath}"`, - correctionActions: { + correctiveActions: { manualSteps: [ `Make sure "${fullNewPath}" contains the correct value in the kibana.yml file."`, `Remove "${fullOldPath}" from the kibana.yml file."`, ], }, + ...details, }); } @@ -58,46 +63,50 @@ const _rename = ( const _unused = ( config: Record, rootPath: string, - configDeprecationHook: ConfigDeprecationHook, - unusedKey: string + deprecationHook: ConfigDeprecationHook, + unusedKey: string, + details?: Partial ) => { const fullPath = getPath(rootPath, unusedKey); if (get(config, fullPath) === undefined) { return config; } unset(config, fullPath); - configDeprecationHook({ + deprecationHook({ message: `${fullPath} is deprecated and is no longer used`, - correctionActions: { + correctiveActions: { manualSteps: [`Remove "${fullPath}" from the kibana.yml file."`], }, + ...details, }); return config; }; -const rename = (oldKey: string, newKey: string): ConfigDeprecation => ( - config, - rootPath, - configDeprecationHook -) => _rename(config, rootPath, configDeprecationHook, oldKey, newKey); +const rename = ( + oldKey: string, + newKey: string, + details?: Partial +): ConfigDeprecation => (config, rootPath, deprecationHook) => + _rename(config, rootPath, deprecationHook, oldKey, newKey, details); -const renameFromRoot = (oldKey: string, newKey: string, silent?: boolean): ConfigDeprecation => ( - config, - rootPath, - configDeprecationHook -) => _rename(config, '', configDeprecationHook, oldKey, newKey, silent); +const renameFromRoot = ( + oldKey: string, + newKey: string, + details?: Partial +): ConfigDeprecation => (config, rootPath, deprecationHook) => + _rename(config, '', deprecationHook, oldKey, newKey, details); -const unused = (unusedKey: string): ConfigDeprecation => ( - config, - rootPath, - configDeprecationHook -) => _unused(config, rootPath, configDeprecationHook, unusedKey); +const unused = ( + unusedKey: string, + details?: Partial +): ConfigDeprecation => (config, rootPath, deprecationHook) => + _unused(config, rootPath, deprecationHook, unusedKey, details); -const unusedFromRoot = (unusedKey: string): ConfigDeprecation => ( - config, - rootPath, - configDeprecationHook -) => _unused(config, '', configDeprecationHook, unusedKey); +const unusedFromRoot = ( + unusedKey: string, + details?: Partial +): ConfigDeprecation => (config, rootPath, deprecationHook) => + _unused(config, '', deprecationHook, unusedKey, details); const getPath = (rootPath: string, subPath: string) => rootPath !== '' ? `${rootPath}.${subPath}` : subPath; diff --git a/packages/kbn-config/src/deprecation/index.ts b/packages/kbn-config/src/deprecation/index.ts index a1acc6997632..2552396de809 100644 --- a/packages/kbn-config/src/deprecation/index.ts +++ b/packages/kbn-config/src/deprecation/index.ts @@ -12,7 +12,7 @@ export type { ConfigDeprecationFactory, ConfigDeprecationHook, ConfigDeprecationProvider, - DeprecatedConfigContext, + DeprecatedConfigDetails, } from './types'; export { configDeprecationFactory } from './deprecation_factory'; export { applyDeprecations } from './apply_deprecations'; diff --git a/packages/kbn-config/src/deprecation/types.ts b/packages/kbn-config/src/deprecation/types.ts index 972ac924ec8d..96efe6eaa33f 100644 --- a/packages/kbn-config/src/deprecation/types.ts +++ b/packages/kbn-config/src/deprecation/types.ts @@ -7,17 +7,22 @@ */ /** - * Logger interface used when invoking a {@link ConfigDeprecation} + * Config deprecation hook used when invoking a {@link ConfigDeprecation} * * @public */ -export type ConfigDeprecationHook = (context: DeprecatedConfigContext) => void; +export type ConfigDeprecationHook = (details: DeprecatedConfigDetails) => void; -export interface DeprecatedConfigContext { +/** + * Deprecated Config Details + * + * @public + */ +export interface DeprecatedConfigDetails { message: string; silent?: boolean; documentationUrl?: string; - correctionActions?: { + correctiveActions?: { api?: { path: string; method: 'POST' | 'PUT'; @@ -41,7 +46,7 @@ export interface DeprecatedConfigContext { export type ConfigDeprecation = ( config: Record, fromPath: string, - onDeprecationHook: ConfigDeprecationHook + deprecationHook: ConfigDeprecationHook ) => Record; /** @@ -92,7 +97,11 @@ export interface ConfigDeprecationFactory { * ] * ``` */ - rename(oldKey: string, newKey: string): ConfigDeprecation; + rename( + oldKey: string, + newKey: string, + details?: Partial + ): ConfigDeprecation; /** * Rename a configuration property from the root configuration. * Will log a deprecation warning if the oldKey was found and deprecation applied. @@ -108,7 +117,11 @@ export interface ConfigDeprecationFactory { * ] * ``` */ - renameFromRoot(oldKey: string, newKey: string, silent?: boolean): ConfigDeprecation; + renameFromRoot( + oldKey: string, + newKey: string, + details?: Partial + ): ConfigDeprecation; /** * Remove a configuration property from inside a plugin's configuration path. * Will log a deprecation warning if the unused key was found and deprecation applied. @@ -121,7 +134,7 @@ export interface ConfigDeprecationFactory { * ] * ``` */ - unused(unusedKey: string): ConfigDeprecation; + unused(unusedKey: string, details?: Partial): ConfigDeprecation; /** * Remove a configuration property from the root configuration. * Will log a deprecation warning if the unused key was found and deprecation applied. @@ -137,7 +150,7 @@ export interface ConfigDeprecationFactory { * ] * ``` */ - unusedFromRoot(unusedKey: string): ConfigDeprecation; + unusedFromRoot(unusedKey: string, details?: Partial): ConfigDeprecation; } /** @internal */ diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts index 33183cf2eee9..e28b419e7ff8 100644 --- a/src/core/server/config/deprecation/core_deprecations.ts +++ b/src/core/server/config/deprecation/core_deprecations.ts @@ -9,31 +9,27 @@ import { has, get } from 'lodash'; import { ConfigDeprecationProvider, ConfigDeprecation } from '@kbn/config'; -const configPathDeprecation: ConfigDeprecation = (settings, fromPath, configDeprecationHook) => { +const configPathDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { if (has(process.env, 'CONFIG_PATH')) { - configDeprecationHook({ + deprecationHook({ message: `Environment variable CONFIG_PATH is deprecated. It has been replaced with KBN_PATH_CONF pointing to a config folder`, }); } return settings; }; -const dataPathDeprecation: ConfigDeprecation = (settings, fromPath, configDeprecationHook) => { +const dataPathDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { if (has(process.env, 'DATA_PATH')) { - configDeprecationHook({ + deprecationHook({ message: `Environment variable "DATA_PATH" will be removed. It has been replaced with kibana.yml setting "path.data"`, }); } return settings; }; -const rewriteBasePathDeprecation: ConfigDeprecation = ( - settings, - fromPath, - configDeprecationHook -) => { +const rewriteBasePathDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { if (has(settings, 'server.basePath') && !has(settings, 'server.rewriteBasePath')) { - configDeprecationHook({ + deprecationHook({ message: 'You should set server.basePath along with server.rewriteBasePath. Starting in 7.0, Kibana ' + 'will expect that all requests start with server.basePath rather than expecting you to rewrite ' + @@ -44,10 +40,10 @@ const rewriteBasePathDeprecation: ConfigDeprecation = ( return settings; }; -const rewriteCorsSettings: ConfigDeprecation = (settings, fromPath, configDeprecationHook) => { +const rewriteCorsSettings: ConfigDeprecation = (settings, fromPath, deprecationHook) => { const corsSettings = get(settings, 'server.cors'); if (typeof get(settings, 'server.cors') === 'boolean') { - configDeprecationHook({ + deprecationHook({ message: '"server.cors" is deprecated and has been replaced by "server.cors.enabled"', }); settings.server.cors = { @@ -57,7 +53,7 @@ const rewriteCorsSettings: ConfigDeprecation = (settings, fromPath, configDeprec return settings; }; -const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, configDeprecationHook) => { +const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { const NONCE_STRING = `{nonce}`; // Policies that should include the 'self' source const SELF_POLICIES = Object.freeze(['script-src', 'style-src']); @@ -74,7 +70,7 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, configDeprec settings.csp.rules = [...parsed].map(([policy, sourceList]) => { if (sourceList.find((source) => source.includes(NONCE_STRING))) { - configDeprecationHook({ + deprecationHook({ message: `csp.rules no longer supports the {nonce} syntax. Replacing with 'self' in ${policy}`, }); sourceList = sourceList.filter((source) => !source.includes(NONCE_STRING)); @@ -89,7 +85,7 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, configDeprec SELF_POLICIES.includes(policy) && !sourceList.find((source) => source.includes(SELF_STRING)) ) { - configDeprecationHook({ + deprecationHook({ message: `csp.rules must contain the 'self' source. Automatically adding to ${policy}.`, }); sourceList.push(SELF_STRING); @@ -105,10 +101,10 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, configDeprec const mapManifestServiceUrlDeprecation: ConfigDeprecation = ( settings, fromPath, - configDeprecationHook + deprecationHook ) => { if (has(settings, 'map.manifestServiceUrl')) { - configDeprecationHook({ + deprecationHook({ message: 'You should no longer use the map.manifestServiceUrl setting in kibana.yml to configure the location ' + 'of the Elastic Maps Service settings. These settings have moved to the "map.emsTileApiUrl" and ' + @@ -119,13 +115,11 @@ const mapManifestServiceUrlDeprecation: ConfigDeprecation = ( return settings; }; -const opsLoggingEventDeprecation: ConfigDeprecation = ( - settings, - fromPath, - configDeprecationHook -) => { +const opsLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { if (has(settings, 'logging.events.ops')) { - configDeprecationHook({ + deprecationHook({ + documentationUrl: + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.md', message: '"logging.events.ops" has been deprecated and will be removed ' + 'in 8.0. To access ops data moving forward, please enable debug logs for the ' + @@ -136,13 +130,11 @@ const opsLoggingEventDeprecation: ConfigDeprecation = ( return settings; }; -const requestLoggingEventDeprecation: ConfigDeprecation = ( - settings, - fromPath, - configDeprecationHook -) => { +const requestLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { if (has(settings, 'logging.events.request') || has(settings, 'logging.events.response')) { - configDeprecationHook({ + deprecationHook({ + documentationUrl: + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.md', message: '"logging.events.request" and "logging.events.response" have been deprecated and will be removed ' + 'in 8.0. To access request and/or response data moving forward, please enable debug logs for the ' + @@ -153,13 +145,11 @@ const requestLoggingEventDeprecation: ConfigDeprecation = ( return settings; }; -const timezoneLoggingDeprecation: ConfigDeprecation = ( - settings, - fromPath, - configDeprecationHook -) => { +const timezoneLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { if (has(settings, 'logging.timezone')) { - configDeprecationHook({ + deprecationHook({ + documentationUrl: + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.md', message: '"logging.timezone" has been deprecated and will be removed ' + 'in 8.0. To set the timezone moving forward, please add a timezone date modifier to the log pattern ' + diff --git a/src/core/server/deprecations/deprecations_factory.test.ts b/src/core/server/deprecations/deprecations_factory.test.ts index 7ff297aca519..b0899e05eeb1 100644 --- a/src/core/server/deprecations/deprecations_factory.test.ts +++ b/src/core/server/deprecations/deprecations_factory.test.ts @@ -60,14 +60,14 @@ describe('DeprecationsFactory', () => { { message: 'mockPlugin message', level: 'critical', - correctionActions: { + correctiveActions: { manualSteps: ['mockPlugin step 1', 'mockPlugin step 2'], }, }, { message: 'hello there!', level: 'warning', - correctionActions: { + correctiveActions: { manualSteps: ['mockPlugin step a', 'mockPlugin step b'], }, }, @@ -76,7 +76,7 @@ describe('DeprecationsFactory', () => { { message: 'anotherMockPlugin message', level: 'critical', - correctionActions: { + correctiveActions: { manualSteps: ['anotherMockPlugin step 1', 'anotherMockPlugin step 2'], }, }, @@ -123,7 +123,7 @@ describe('DeprecationsFactory', () => { pluginId, message: `Failed to get deprecations info for plugin "${pluginId}".`, level: 'warning', - correctionActions: { + correctiveActions: { manualSteps: ['Check Kibana server logs for error message.'], }, }, @@ -139,7 +139,7 @@ describe('DeprecationsFactory', () => { { message: 'mockPlugin message', level: 'critical', - correctionActions: { + correctiveActions: { manualSteps: ['mockPlugin step 1', 'mockPlugin step 2'], }, }, @@ -163,7 +163,7 @@ describe('DeprecationsFactory', () => { pluginId: 'anotherMockPlugin', message: `Failed to get deprecations info for plugin "anotherMockPlugin".`, level: 'warning', - correctionActions: { + correctiveActions: { manualSteps: ['Check Kibana server logs for error message.'], }, }, @@ -184,7 +184,7 @@ describe('DeprecationsFactory', () => { { message: 'mockPlugin message', level: 'critical', - correctionActions: { + correctiveActions: { manualSteps: ['mockPlugin step 1', 'mockPlugin step 2'], }, }, @@ -192,7 +192,7 @@ describe('DeprecationsFactory', () => { { message: 'hello there!', level: 'warning', - correctionActions: { + correctiveActions: { manualSteps: ['mockPlugin step a', 'mockPlugin step b'], }, }, @@ -219,7 +219,7 @@ describe('DeprecationsFactory', () => { { message: 'mockPlugin message', level: 'critical', - correctionActions: { + correctiveActions: { manualSteps: ['mockPlugin step 1', 'mockPlugin step 2'], }, }, diff --git a/src/core/server/deprecations/deprecations_factory.ts b/src/core/server/deprecations/deprecations_factory.ts index d212241e1c6a..f41d4b86690b 100644 --- a/src/core/server/deprecations/deprecations_factory.ts +++ b/src/core/server/deprecations/deprecations_factory.ts @@ -11,7 +11,7 @@ import type { Logger } from '../logging'; import type { PluginDeprecationDetails, DeprecationsDetails, - DeprecationDependencies, + GetDeprecationsContext, } from './types'; export interface DeprecationsFactoryDeps { @@ -41,14 +41,14 @@ export class DeprecationsFactory { public getDeprecations = async ( pluginId: string, - dependencies: DeprecationDependencies + dependencies: GetDeprecationsContext ): Promise => { const infoBody = await this.getDeprecationsBody(pluginId, dependencies); return this.createDeprecationInfo(pluginId, infoBody).flat(); }; public getAllDeprecations = async ( - dependencies: DeprecationDependencies + dependencies: GetDeprecationsContext ): Promise => { const pluginIds = [...this.registries.keys()]; @@ -77,7 +77,7 @@ export class DeprecationsFactory { private getDeprecationsBody = async ( pluginId: string, - dependencies: DeprecationDependencies + dependencies: GetDeprecationsContext ): Promise => { const deprecationsRegistry = this.registries.get(pluginId); if (!deprecationsRegistry) { @@ -95,7 +95,7 @@ export class DeprecationsFactory { { message: `Failed to get deprecations info for plugin "${pluginId}".`, level: 'warning', - correctionActions: { + correctiveActions: { manualSteps: ['Check Kibana server logs for error message.'], }, }, diff --git a/src/core/server/deprecations/deprecations_registry.test.ts b/src/core/server/deprecations/deprecations_registry.test.ts index 6391c093ba8b..09dd77f74df8 100644 --- a/src/core/server/deprecations/deprecations_registry.test.ts +++ b/src/core/server/deprecations/deprecations_registry.test.ts @@ -6,14 +6,14 @@ * Side Public License, v 1. */ -import { DeprecationsContext, DeprecationDependencies } from './types'; +import { RegisterDeprecationsConfig, DeprecationDependencies } from './types'; import { DeprecationsRegistry } from './deprecations_registry'; describe('DeprecationsRegistry', () => { describe('registerDeprecations', () => { it('throws if getDeprecations is not a function', async () => { const deprecationsRegistry = new DeprecationsRegistry(); - const context = ({ getDeprecations: null } as unknown) as DeprecationsContext; + const context = ({ getDeprecations: null } as unknown) as RegisterDeprecationsConfig; expect(() => deprecationsRegistry.registerDeprecations(context)).toThrowError( /getDeprecations must be a function/ ); diff --git a/src/core/server/deprecations/deprecations_registry.ts b/src/core/server/deprecations/deprecations_registry.ts index a005a9394bcc..f92d807514b8 100644 --- a/src/core/server/deprecations/deprecations_registry.ts +++ b/src/core/server/deprecations/deprecations_registry.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ -import { DeprecationsDetails, DeprecationsContext, DeprecationDependencies } from './types'; +import { DeprecationsDetails, RegisterDeprecationsConfig, GetDeprecationsContext } from './types'; export class DeprecationsRegistry { - private readonly deprecationContexts: DeprecationsContext[] = []; + private readonly deprecationContexts: RegisterDeprecationsConfig[] = []; - public registerDeprecations = (deprecationContext: DeprecationsContext) => { + public registerDeprecations = (deprecationContext: RegisterDeprecationsConfig) => { if (typeof deprecationContext.getDeprecations !== 'function') { throw new Error(`getDeprecations must be a function in registerDeprecations(context)`); } @@ -20,7 +20,7 @@ export class DeprecationsRegistry { }; public getDeprecations = async ( - dependencies: DeprecationDependencies + dependencies: GetDeprecationsContext ): Promise>> => { return await Promise.allSettled( this.deprecationContexts.map( diff --git a/src/core/server/deprecations/deprecations_service.ts b/src/core/server/deprecations/deprecations_service.ts index 1f55f02f7d96..f8faa87a04d2 100644 --- a/src/core/server/deprecations/deprecations_service.ts +++ b/src/core/server/deprecations/deprecations_service.ts @@ -18,19 +18,22 @@ import { Logger } from '../logging'; import { registerRoutes } from './routes'; /** - * Deprecations Service is a mechanism to allow plugins to communiicate deprecated features. + * The deprecations service provides a way for the Kibana platform to communicate deprecated + * features and configs with its users. These deprecations are only communicated + * if the deployment is using these features. Allowing for a user tailored experience + * for upgrading the stack version. * * @example * ```ts - * import { DeprecationsContext, CoreSetup } from 'src/core/server'; + * import { DeprecationsDetails, GetDeprecationsContext, CoreSetup } from 'src/core/server'; * - * const getDeprecations: DeprecationsContext['getDeprecations'] = async ({ esClient, savedObjectsClient }) => { + * const getDeprecations = async ({ esClient, savedObjectsClient }: GetDeprecationsContext): DeprecationsDetails[] => { * return [ * { * message: string; * level: 'warning' | 'critical'; * documentationUrl?: string; - * correctionActions: { + * correctiveActions: { * api?: { * path: string; * method: 'POST' | 'PUT'; @@ -67,6 +70,7 @@ export interface DeprecationsSetupDeps { coreUsageData: CoreUsageDataSetup; } +/** @internal */ export class DeprecationsService implements CoreService { private readonly logger: Logger; @@ -103,11 +107,11 @@ export class DeprecationsService implements CoreService { - return deprecationsContexts.map(({ message, correctionActions, documentationUrl }) => { + return deprecationsContexts.map(({ message, correctiveActions, documentationUrl }) => { return { level: 'critical', message, - correctionActions: correctionActions ?? {}, + correctiveActions: correctiveActions ?? {}, documentationUrl, }; }); diff --git a/src/core/server/deprecations/index.ts b/src/core/server/deprecations/index.ts index 84fe7ad4221b..6704c0bdea95 100644 --- a/src/core/server/deprecations/index.ts +++ b/src/core/server/deprecations/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -export type { DeprecationsDetails, DeprecationsContext } from './types'; +export type { DeprecationsDetails, RegisterDeprecationsConfig } from './types'; export type { DeprecationsServiceSetup, diff --git a/src/core/server/deprecations/routes/get.ts b/src/core/server/deprecations/routes/get.ts index 3813dfebe801..7408c14e1f9d 100644 --- a/src/core/server/deprecations/routes/get.ts +++ b/src/core/server/deprecations/routes/get.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ import { IRouter } from '../../http'; -import { DeprecationDependencies } from '../types'; +import { GetDeprecationsContext } from '../types'; import { DeprecationsFactory } from '../deprecations_factory'; interface RouteDependencies { @@ -20,7 +20,7 @@ export const registerGetRoute = (router: IRouter, { deprecationsFactory }: Route validate: false, }, async (context, req, res) => { - const dependencies: DeprecationDependencies = { + const dependencies: GetDeprecationsContext = { esClient: context.core.elasticsearch.client, savedObjectsClient: context.core.savedObjects.client, }; diff --git a/src/core/server/deprecations/types.ts b/src/core/server/deprecations/types.ts index 33b9b54c805f..743462ae38e2 100644 --- a/src/core/server/deprecations/types.ts +++ b/src/core/server/deprecations/types.ts @@ -8,6 +8,8 @@ import type { IScopedClusterClient, SavedObjectsClientContract } from '../../server'; +type MaybePromise = T | Promise; + export interface PluginDeprecationDetails extends DeprecationsDetails { pluginId: string; } @@ -16,7 +18,7 @@ export interface DeprecationsDetails { message: string; level: 'warning' | 'critical'; documentationUrl?: string; - correctionActions: { + correctiveActions: { api?: { path: string; method: 'POST' | 'PUT'; @@ -28,15 +30,11 @@ export interface DeprecationsDetails { }; } -export interface DeprecationsContext { - getDeprecations: ( - dependencies: GetDeprecationsDependencies - ) => MaybePromise; +export interface RegisterDeprecationsConfig { + getDeprecations: (dependencies: GetDeprecationsContext) => MaybePromise; } -interface GetDeprecationsDependencies { +export interface GetDeprecationsContext { esClient: IScopedClusterClient; savedObjectsClient: SavedObjectsClientContract; } - -type MaybePromise = T | Promise; diff --git a/src/core/server/elasticsearch/elasticsearch_config.ts b/src/core/server/elasticsearch/elasticsearch_config.ts index 879002a6ece5..4dfea9451bb0 100644 --- a/src/core/server/elasticsearch/elasticsearch_config.ts +++ b/src/core/server/elasticsearch/elasticsearch_config.ts @@ -144,32 +144,32 @@ export const configSchema = schema.object({ }); const deprecations: ConfigDeprecationProvider = () => [ - (settings, fromPath, log) => { + (settings, fromPath, deprecationHook) => { const es = settings[fromPath]; if (!es) { return settings; } if (es.username === 'elastic') { - log( - `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.` - ); + deprecationHook({ + message: `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.`, + }); } else if (es.username === 'kibana') { - log( - `Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.` - ); + deprecationHook({ + message: `Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.`, + }); } if (es.ssl?.key !== undefined && es.ssl?.certificate === undefined) { - log( - `Setting [${fromPath}.ssl.key] without [${fromPath}.ssl.certificate] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.` - ); + deprecationHook({ + message: `Setting [${fromPath}.ssl.key] without [${fromPath}.ssl.certificate] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`, + }); } else if (es.ssl?.certificate !== undefined && es.ssl?.key === undefined) { - log( - `Setting [${fromPath}.ssl.certificate] without [${fromPath}.ssl.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.` - ); + deprecationHook({ + message: `Setting [${fromPath}.ssl.certificate] without [${fromPath}.ssl.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`, + }); } else if (es.logQueries === true) { - log( - `Setting [${fromPath}.logQueries] is deprecated and no longer used. You should set the log level to "debug" for the "elasticsearch.queries" context in "logging.loggers" or use "logging.verbose: true".` - ); + deprecationHook({ + message: `Setting [${fromPath}.logQueries] is deprecated and no longer used. You should set the log level to "debug" for the "elasticsearch.queries" context in "logging.loggers" or use "logging.verbose: true".`, + }); } return settings; }, diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 36e5cd3c83a1..8ab6e6ec69af 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -57,7 +57,7 @@ import { StatusServiceSetup } from './status'; import { AppenderConfigType, appendersSchema, LoggingServiceSetup } from './logging'; import { CoreUsageDataStart } from './core_usage_data'; import { I18nServiceSetup } from './i18n'; -import { DeprecationsServiceSetup, DeprecationsServiceStart } from './deprecations'; +import { DeprecationsServiceSetup } from './deprecations'; // Because of #79265 we need to explicity import, then export these types for // scripts/telemetry_check.js to work as expected import { @@ -380,7 +380,7 @@ export type { export type { I18nServiceSetup } from './i18n'; export type { DeprecationsDetails, - DeprecationsContext, + RegisterDeprecationsConfig, DeprecationsServiceSetup, } from './deprecations'; @@ -522,8 +522,6 @@ export interface CoreStart { uiSettings: UiSettingsServiceStart; /** @internal {@link CoreUsageDataStart} */ coreUsageData: CoreUsageDataStart; - /** @internal {@link CoreUsageDataStart} */ - deprecations: DeprecationsServiceStart; } export type { diff --git a/src/core/server/kibana_config.ts b/src/core/server/kibana_config.ts index d0ff18b38117..3c4bd0eab4b1 100644 --- a/src/core/server/kibana_config.ts +++ b/src/core/server/kibana_config.ts @@ -12,12 +12,13 @@ import { ConfigDeprecationProvider } from '@kbn/config'; export type KibanaConfigType = TypeOf; const deprecations: ConfigDeprecationProvider = () => [ - (settings, fromPath, log) => { + (settings, fromPath, deprecationHook) => { const kibana = settings[fromPath]; if (kibana?.index) { - log( - `"kibana.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details` - ); + deprecationHook({ + message: `"kibana.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details`, + documentationUrl: 'https://ela.st/kbn-remove-legacy-multitenancy', + }); } return settings; }, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index a1a774e8721c..dfaeb7469cf7 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -35,7 +35,7 @@ import { ClusterStateParams } from 'elasticsearch'; import { ClusterStatsParams } from 'elasticsearch'; import { ConfigDeprecation } from '@kbn/config'; import { ConfigDeprecationFactory } from '@kbn/config'; -import { ConfigDeprecationLogger } from '@kbn/config'; +import { ConfigDeprecationHook } from '@kbn/config'; import { ConfigDeprecationProvider } from '@kbn/config'; import { ConfigOptions } from 'elasticsearch'; import { ConfigPath } from '@kbn/config'; @@ -373,7 +373,7 @@ export { ConfigDeprecation } export { ConfigDeprecationFactory } -export { ConfigDeprecationLogger } +export { ConfigDeprecationHook } export { ConfigDeprecationProvider } @@ -490,6 +490,8 @@ export interface CoreSetup; @@ -829,12 +831,43 @@ export interface DeprecationInfo { url: string; } +// Warning: (ae-missing-release-tag) "DeprecationsDetails" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface DeprecationsDetails { + // (undocumented) + correctiveActions: { + api?: { + path: string; + method: 'POST' | 'PUT'; + body?: { + [key: string]: any; + }; + }; + manualSteps?: string[]; + }; + // (undocumented) + documentationUrl?: string; + // (undocumented) + level: 'warning' | 'critical'; + // (undocumented) + message: string; +} + // @public export interface DeprecationSettings { docLinksKey: string; message: string; } +// @public +export interface DeprecationsServiceSetup { + // Warning: (ae-forgotten-export) The symbol "DeprecationsRegistry" needs to be exported by the entry point index.d.ts + // + // (undocumented) + registerDeprecations: DeprecationsRegistry['registerDeprecations']; +} + // @public export type DestructiveRouteMethod = 'post' | 'put' | 'delete' | 'patch'; @@ -1905,6 +1938,17 @@ export type RedirectResponseOptions = HttpResponseOptions & { }; }; +// Warning: (ae-missing-release-tag) "RegisterDeprecationsConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface RegisterDeprecationsConfig { + // Warning: (ae-forgotten-export) The symbol "GetDeprecationsContext" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "MaybePromise" needs to be exported by the entry point index.d.ts + // + // (undocumented) + getDeprecations: (dependencies: GetDeprecationsContext) => MaybePromise; +} + // @public export type RequestHandler

= (context: Context, request: KibanaRequest, response: ResponseFactory) => IKibanaResponse | Promise>; diff --git a/src/plugins/kibana_legacy/server/index.ts b/src/plugins/kibana_legacy/server/index.ts index da0bee68a297..8899b0e9daa1 100644 --- a/src/plugins/kibana_legacy/server/index.ts +++ b/src/plugins/kibana_legacy/server/index.ts @@ -18,11 +18,11 @@ export const config: PluginConfigDescriptor = { schema: configSchema, deprecations: ({ renameFromRoot }) => [ // TODO: Remove deprecation once defaultAppId is deleted - renameFromRoot('kibana.defaultAppId', 'kibana_legacy.defaultAppId', true), + renameFromRoot('kibana.defaultAppId', 'kibana_legacy.defaultAppId', { silent: true }), ( completeConfig: Record, rootPath: string, - configDeprecationHook: ConfigDeprecationHook + deprecationHook: ConfigDeprecationHook ) => { if ( get(completeConfig, 'kibana.defaultAppId') === undefined && @@ -30,10 +30,15 @@ export const config: PluginConfigDescriptor = { ) { return completeConfig; } - configDeprecationHook({ - type: 'unused', - oldConfigFullPath: 'kibana.defaultAppId', - logMsg: `kibana.defaultAppId is deprecated and will be removed in 8.0. Please use the \`defaultRoute\` advanced setting instead`, + deprecationHook({ + message: `kibana.defaultAppId is deprecated and will be removed in 8.0. Please use the \`defaultRoute\` advanced setting instead`, + correctiveActions: { + manualSteps: [ + 'Go to Stack Management > Advanced Settings', + 'Update the "defaultRoute" setting under the General section', + 'Remove "kibana.defaultAppId" from the kibana.yml config file', + ], + }, }); return completeConfig; }, diff --git a/src/plugins/timelion/server/deprecations.ts b/src/plugins/timelion/server/deprecations.ts index f20b9b6c134d..997895c1e962 100644 --- a/src/plugins/timelion/server/deprecations.ts +++ b/src/plugins/timelion/server/deprecations.ts @@ -10,7 +10,7 @@ import { CoreStart, SavedObjectsClient, Logger, - DeprecationsContext, + RegisterDeprecationsConfig, DeprecationsDetails, } from 'src/core/server'; @@ -41,7 +41,7 @@ export const showWarningMessageIfTimelionSheetWasFound = async ( * * @link https://www.elastic.co/guide/en/kibana/master/timelion.html#timelion-deprecation **/ -export const getDeprecations: DeprecationsContext['getDeprecations'] = async ({ +export const getDeprecations: RegisterDeprecationsConfig['getDeprecations'] = async ({ savedObjectsClient, }) => { const deprecations: DeprecationsDetails[] = []; @@ -53,7 +53,7 @@ export const getDeprecations: DeprecationsContext['getDeprecations'] = async ({ documentationUrl: 'https://www.elastic.co/guide/en/kibana/master/dashboard.html#timelion-deprecation', level: 'warning', - correctionActions: { + correctiveActions: { manualSteps: [ 'Navigate to the Kibana Dashboard and click "Create dashboard".', 'Select Timelion from the "New Visualization" window.', diff --git a/src/plugins/vis_type_timelion/server/index.ts b/src/plugins/vis_type_timelion/server/index.ts index 1dcb7263c481..35f4182a50a8 100644 --- a/src/plugins/vis_type_timelion/server/index.ts +++ b/src/plugins/vis_type_timelion/server/index.ts @@ -21,7 +21,7 @@ export const config: PluginConfigDescriptor = { renameFromRoot('timelion_vis.enabled', 'vis_type_timelion.enabled'), renameFromRoot('timelion.enabled', 'vis_type_timelion.enabled'), renameFromRoot('timelion.graphiteUrls', 'vis_type_timelion.graphiteUrls'), - renameFromRoot('timelion.ui.enabled', 'vis_type_timelion.ui.enabled', true), + renameFromRoot('timelion.ui.enabled', 'vis_type_timelion.ui.enabled', { silent: true }), ], }; export const plugin = (initializerContext: PluginInitializerContext) => diff --git a/src/plugins/vis_type_timeseries/server/index.ts b/src/plugins/vis_type_timeseries/server/index.ts index 37eda1b1338d..3c27713c3750 100644 --- a/src/plugins/vis_type_timeseries/server/index.ts +++ b/src/plugins/vis_type_timeseries/server/index.ts @@ -15,9 +15,13 @@ export { VisTypeTimeseriesSetup } from './plugin'; export const config: PluginConfigDescriptor = { deprecations: ({ unused, renameFromRoot }) => [ // In Kibana v7.8 plugin id was renamed from 'metrics' to 'vis_type_timeseries': - renameFromRoot('metrics.enabled', 'vis_type_timeseries.enabled', true), - renameFromRoot('metrics.chartResolution', 'vis_type_timeseries.chartResolution', true), - renameFromRoot('metrics.minimumBucketSize', 'vis_type_timeseries.minimumBucketSize', true), + renameFromRoot('metrics.enabled', 'vis_type_timeseries.enabled', { silent: true }), + renameFromRoot('metrics.chartResolution', 'vis_type_timeseries.chartResolution', { + silent: true, + }), + renameFromRoot('metrics.minimumBucketSize', 'vis_type_timeseries.minimumBucketSize', { + silent: true, + }), // Unused properties which should be removed after releasing Kibana v8.0: unused('chartResolution'), diff --git a/x-pack/plugins/monitoring/server/deprecations.ts b/x-pack/plugins/monitoring/server/deprecations.ts index e9de116fea66..71e3891c3ad0 100644 --- a/x-pack/plugins/monitoring/server/deprecations.ts +++ b/x-pack/plugins/monitoring/server/deprecations.ts @@ -44,41 +44,41 @@ export const deprecations = ({ 'monitoring.ui.elasticsearch.logFetchCount' ), renameFromRoot('xpack.monitoring', 'monitoring'), - (config, fromPath, configDeprecationHook) => { + (config, fromPath, deprecationHook) => { const clusterAlertsEnabled = get(config, 'cluster_alerts.enabled'); const emailNotificationsEnabled = clusterAlertsEnabled && get(config, 'cluster_alerts.email_notifications.enabled'); if (emailNotificationsEnabled && !get(config, CLUSTER_ALERTS_ADDRESS_CONFIG_KEY)) { - configDeprecationHook({ + deprecationHook({ message: `Config key [${fromPath}.${CLUSTER_ALERTS_ADDRESS_CONFIG_KEY}] will be required for email notifications to work in 7.0."`, }); } return config; }, - (config, fromPath, configDeprecationHook) => { + (config, fromPath, deprecationHook) => { const es: Record = get(config, 'elasticsearch'); if (es) { if (es.username === 'elastic') { - configDeprecationHook({ + deprecationHook({ message: `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.`, }); } else if (es.username === 'kibana') { - configDeprecationHook({ + deprecationHook({ message: `Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.`, }); } } return config; }, - (config, fromPath, configDeprecationHook) => { + (config, fromPath, deprecationHook) => { const ssl: Record = get(config, 'elasticsearch.ssl'); if (ssl) { if (ssl.key !== undefined && ssl.certificate === undefined) { - configDeprecationHook({ + deprecationHook({ message: `Setting [${fromPath}.key] without [${fromPath}.certificate] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`, }); } else if (ssl.certificate !== undefined && ssl.key === undefined) { - configDeprecationHook({ + deprecationHook({ message: `Setting [${fromPath}.certificate] without [${fromPath}.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`, }); } diff --git a/x-pack/plugins/spaces/server/config.ts b/x-pack/plugins/spaces/server/config.ts index 46b102a88797..5ad13aa38815 100644 --- a/x-pack/plugins/spaces/server/config.ts +++ b/x-pack/plugins/spaces/server/config.ts @@ -24,9 +24,9 @@ export function createConfig$(context: PluginInitializerContext) { return context.config.create>(); } -const disabledDeprecation: ConfigDeprecation = (config, fromPath, configDeprecationHook) => { +const disabledDeprecation: ConfigDeprecation = (config, fromPath, deprecationHook) => { if (config.xpack?.spaces?.enabled === false) { - configDeprecationHook({ + deprecationHook({ message: `Disabling the spaces plugin (xpack.spaces.enabled) will not be supported in the next major version (8.0)`, }); } From 4c94eb100efd6237a7ba7114ebd339a3f72e7c1a Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 18 Mar 2021 14:31:54 +0200 Subject: [PATCH 03/23] fix core tests --- .../deprecation/core_deprecations.test.ts | 2 +- .../deprecations/deprecations_factory.test.ts | 6 +-- .../deprecations_registry.test.ts | 50 +++++++++++-------- .../deprecations/deprecations_service.mock.ts | 2 +- src/core/server/deprecations/types.ts | 2 +- .../elasticsearch_config.test.ts | 2 +- src/core/server/kibana_config.test.ts | 2 +- src/core/server/legacy/legacy_service.test.ts | 2 + src/core/server/legacy/legacy_service.ts | 5 ++ src/core/server/mocks.ts | 4 ++ 10 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/core/server/config/deprecation/core_deprecations.test.ts b/src/core/server/config/deprecation/core_deprecations.test.ts index 4d7dafd2162c..93a9177eabb2 100644 --- a/src/core/server/config/deprecation/core_deprecations.test.ts +++ b/src/core/server/config/deprecation/core_deprecations.test.ts @@ -20,7 +20,7 @@ const applyCoreDeprecations = (settings: Record = {}) => { deprecation, path: '', })), - (msg) => deprecationMessages.push(msg) + () => ({ message }) => deprecationMessages.push(message) ); return { messages: deprecationMessages, diff --git a/src/core/server/deprecations/deprecations_factory.test.ts b/src/core/server/deprecations/deprecations_factory.test.ts index b0899e05eeb1..b89b404dedda 100644 --- a/src/core/server/deprecations/deprecations_factory.test.ts +++ b/src/core/server/deprecations/deprecations_factory.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { DeprecationDependencies } from './types'; +import { GetDeprecationsContext } from './types'; import { DeprecationsFactory } from './deprecations_factory'; import { loggerMock } from '../logging/logger.mock'; @@ -52,7 +52,7 @@ describe('DeprecationsFactory', () => { const mockDependencies = ({ esClient: jest.fn(), savedObjectsClient: jest.fn(), - } as unknown) as DeprecationDependencies; + } as unknown) as GetDeprecationsContext; it('returns a flattened array of deprecations', async () => { const deprecationsFactory = new DeprecationsFactory({ logger }); @@ -175,7 +175,7 @@ describe('DeprecationsFactory', () => { const mockDependencies = ({ esClient: jest.fn(), savedObjectsClient: jest.fn(), - } as unknown) as DeprecationDependencies; + } as unknown) as GetDeprecationsContext; it('returns a flattened array of DeprecationInfo', async () => { const deprecationsFactory = new DeprecationsFactory({ logger }); diff --git a/src/core/server/deprecations/deprecations_registry.test.ts b/src/core/server/deprecations/deprecations_registry.test.ts index 09dd77f74df8..507677a53186 100644 --- a/src/core/server/deprecations/deprecations_registry.test.ts +++ b/src/core/server/deprecations/deprecations_registry.test.ts @@ -6,15 +6,18 @@ * Side Public License, v 1. */ -import { RegisterDeprecationsConfig, DeprecationDependencies } from './types'; +/* eslint-disable dot-notation */ +import { RegisterDeprecationsConfig, GetDeprecationsContext } from './types'; import { DeprecationsRegistry } from './deprecations_registry'; describe('DeprecationsRegistry', () => { describe('registerDeprecations', () => { it('throws if getDeprecations is not a function', async () => { const deprecationsRegistry = new DeprecationsRegistry(); - const context = ({ getDeprecations: null } as unknown) as RegisterDeprecationsConfig; - expect(() => deprecationsRegistry.registerDeprecations(context)).toThrowError( + const deprecationsConfig = ({ + getDeprecations: null, + } as unknown) as RegisterDeprecationsConfig; + expect(() => deprecationsRegistry.registerDeprecations(deprecationsConfig)).toThrowError( /getDeprecations must be a function/ ); }); @@ -22,31 +25,34 @@ describe('DeprecationsRegistry', () => { it('registers deprecation context', () => { const deprecationsRegistry = new DeprecationsRegistry(); const getDeprecations = jest.fn(); - const context = { getDeprecations }; - deprecationsRegistry.registerDeprecations(context); - expect(deprecationsRegistry.deprecationContexts).toStrictEqual([context]); + const deprecationsConfig = { getDeprecations }; + deprecationsRegistry.registerDeprecations(deprecationsConfig); + expect(deprecationsRegistry['deprecationContexts']).toStrictEqual([deprecationsConfig]); }); it('allows registering multiple contexts', async () => { const deprecationsRegistry = new DeprecationsRegistry(); - const contextA = { getDeprecations: jest.fn() }; - const contextB = { getDeprecations: jest.fn() }; - deprecationsRegistry.registerDeprecations(contextA); - deprecationsRegistry.registerDeprecations(contextB); - expect(deprecationsRegistry.deprecationContexts).toStrictEqual([contextA, contextB]); + const deprecationsConfigA = { getDeprecations: jest.fn() }; + const deprecationsConfigB = { getDeprecations: jest.fn() }; + deprecationsRegistry.registerDeprecations(deprecationsConfigA); + deprecationsRegistry.registerDeprecations(deprecationsConfigB); + expect(deprecationsRegistry['deprecationContexts']).toStrictEqual([ + deprecationsConfigA, + deprecationsConfigB, + ]); }); }); describe('getDeprecations', () => { it('returns all settled deprecations', async () => { const deprecationsRegistry = new DeprecationsRegistry(); - const mockDependencies = ({} as unknown) as DeprecationDependencies; + const mockContext = ({} as unknown) as GetDeprecationsContext; const mockError = new Error(); - const contextA = { getDeprecations: jest.fn().mockResolvedValue('hi') }; - const contextB = { getDeprecations: jest.fn().mockRejectedValue(mockError) }; - deprecationsRegistry.registerDeprecations(contextA); - deprecationsRegistry.registerDeprecations(contextB); - const deprecations = await deprecationsRegistry.getDeprecations(mockDependencies); + const deprecationsConfigA = { getDeprecations: jest.fn().mockResolvedValue('hi') }; + const deprecationsConfigB = { getDeprecations: jest.fn().mockRejectedValue(mockError) }; + deprecationsRegistry.registerDeprecations(deprecationsConfigA); + deprecationsRegistry.registerDeprecations(deprecationsConfigB); + const deprecations = await deprecationsRegistry.getDeprecations(mockContext); expect(deprecations).toStrictEqual([ { status: 'fulfilled', @@ -61,12 +67,12 @@ describe('DeprecationsRegistry', () => { it('passes dependencies to registered getDeprecations function', async () => { const deprecationsRegistry = new DeprecationsRegistry(); - const mockDependencies = ({} as unknown) as DeprecationDependencies; - const context = { getDeprecations: jest.fn().mockResolvedValue('hi') }; - deprecationsRegistry.registerDeprecations(context); - const deprecations = await deprecationsRegistry.getDeprecations(mockDependencies); + const mockContext = ({} as unknown) as GetDeprecationsContext; + const deprecationsConfig = { getDeprecations: jest.fn().mockResolvedValue('hi') }; + deprecationsRegistry.registerDeprecations(deprecationsConfig); + const deprecations = await deprecationsRegistry.getDeprecations(mockContext); expect(deprecations).toHaveLength(1); - expect(context.getDeprecations).toBeCalledWith(mockDependencies); + expect(deprecationsConfig.getDeprecations).toBeCalledWith(mockContext); }); }); }); diff --git a/src/core/server/deprecations/deprecations_service.mock.ts b/src/core/server/deprecations/deprecations_service.mock.ts index 13f7dbd196c3..f4e680c475dd 100644 --- a/src/core/server/deprecations/deprecations_service.mock.ts +++ b/src/core/server/deprecations/deprecations_service.mock.ts @@ -42,7 +42,7 @@ const createDeprecationsServiceMock = () => { return mocked; }; -export const savedObjectsServiceMock = { +export const deprecationsServiceMock = { create: createDeprecationsServiceMock, createInternalSetupContract: createInternalSetupContractMock, createSetupContract: createSetupContractMock, diff --git a/src/core/server/deprecations/types.ts b/src/core/server/deprecations/types.ts index 743462ae38e2..78bc03f0e135 100644 --- a/src/core/server/deprecations/types.ts +++ b/src/core/server/deprecations/types.ts @@ -31,7 +31,7 @@ export interface DeprecationsDetails { } export interface RegisterDeprecationsConfig { - getDeprecations: (dependencies: GetDeprecationsContext) => MaybePromise; + getDeprecations: (context: GetDeprecationsContext) => MaybePromise; } export interface GetDeprecationsContext { diff --git a/src/core/server/elasticsearch/elasticsearch_config.test.ts b/src/core/server/elasticsearch/elasticsearch_config.test.ts index d3f9693bab22..0c6cd70e60e1 100644 --- a/src/core/server/elasticsearch/elasticsearch_config.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_config.test.ts @@ -28,7 +28,7 @@ const applyElasticsearchDeprecations = (settings: Record = {}) => { deprecation, path: CONFIG_PATH, })), - (msg) => deprecationMessages.push(msg) + () => ({ message }) => deprecationMessages.push(message) ); return { messages: deprecationMessages, diff --git a/src/core/server/kibana_config.test.ts b/src/core/server/kibana_config.test.ts index 1c2b26815653..1acdff9dd78e 100644 --- a/src/core/server/kibana_config.test.ts +++ b/src/core/server/kibana_config.test.ts @@ -22,7 +22,7 @@ const applyKibanaDeprecations = (settings: Record = {}) => { deprecation, path: CONFIG_PATH, })), - (msg) => deprecationMessages.push(msg) + () => ({ message }) => deprecationMessages.push(message) ); return { messages: deprecationMessages, diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index da6b521bfde9..7dd200415501 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -36,6 +36,7 @@ import { statusServiceMock } from '../status/status_service.mock'; import { loggingServiceMock } from '../logging/logging_service.mock'; import { metricsServiceMock } from '../metrics/metrics_service.mock'; import { i18nServiceMock } from '../i18n/i18n_service.mock'; +import { deprecationsServiceMock } from '../deprecations/deprecations_service.mock'; const MockKbnServer: jest.Mock = KbnServer as any; @@ -84,6 +85,7 @@ beforeEach(() => { status: statusServiceMock.createInternalSetupContract(), logging: loggingServiceMock.createInternalSetupContract(), metrics: metricsServiceMock.createInternalSetupContract(), + deprecations: deprecationsServiceMock.createInternalSetupContract(), }, plugins: { 'plugin-id': 'plugin-value' }, uiPlugins: { diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index 63b84e2461e7..6b99e5fb593d 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -288,6 +288,11 @@ export class LegacyService implements CoreService { uiSettings: { register: setupDeps.core.uiSettings.register, }, + deprecations: { + registerDeprecations: () => { + throw new Error('core.setup.deprecations.registerDeprecations is unsupported in legacy'); + }, + }, getStartServices: () => Promise.resolve([coreStart, startDeps.plugins, {}]), }; diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index 19056ae1b9bc..cd0ce7005cc4 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -29,6 +29,7 @@ import { environmentServiceMock } from './environment/environment_service.mock'; import { statusServiceMock } from './status/status_service.mock'; import { coreUsageDataServiceMock } from './core_usage_data/core_usage_data_service.mock'; import { i18nServiceMock } from './i18n/i18n_service.mock'; +import { deprecationsServiceMock } from './deprecations/deprecations_service.mock'; export { configServiceMock } from './config/mocks'; export { httpServerMock } from './http/http_server.mocks'; @@ -49,6 +50,7 @@ export { contextServiceMock } from './context/context_service.mock'; export { capabilitiesServiceMock } from './capabilities/capabilities_service.mock'; export { coreUsageDataServiceMock } from './core_usage_data/core_usage_data_service.mock'; export { i18nServiceMock } from './i18n/i18n_service.mock'; +export { deprecationsServiceMock } from './deprecations/deprecations_service.mock'; export function pluginInitializerContextConfigMock(config: T) { const globalConfig: SharedGlobalConfig = { @@ -137,6 +139,7 @@ function createCoreSetupMock({ uiSettings: uiSettingsMock, logging: loggingServiceMock.createSetupContract(), metrics: metricsServiceMock.createSetupContract(), + deprecations: deprecationsServiceMock.createSetupContract(), getStartServices: jest .fn, object, any]>, []>() .mockResolvedValue([createCoreStartMock(), pluginStartDeps, pluginStartContract]), @@ -174,6 +177,7 @@ function createInternalCoreSetupMock() { uiSettings: uiSettingsServiceMock.createSetupContract(), logging: loggingServiceMock.createInternalSetupContract(), metrics: metricsServiceMock.createInternalSetupContract(), + deprecations: deprecationsServiceMock.createInternalSetupContract(), }; return setupDeps; } From b044c6a9f44cbe2736cc2e2ea167defde8d02bb3 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 18 Mar 2021 14:58:13 +0200 Subject: [PATCH 04/23] update docs --- ...plugin-core-server.deprecationsdetails.correctiveactions.md} | 2 +- .../server/kibana-plugin-core-server.deprecationsdetails.md | 2 +- .../kibana-plugin-core-server.deprecationsservicesetup.md | 2 +- docs/development/core/server/kibana-plugin-core-server.md | 2 +- ...in-core-server.registerdeprecationsconfig.getdeprecations.md | 2 +- .../kibana-plugin-core-server.registerdeprecationsconfig.md | 2 +- src/core/server/server.api.md | 2 +- x-pack/plugins/reporting/server/config/index.test.ts | 2 +- x-pack/plugins/security/server/config_deprecations.test.ts | 2 +- x-pack/plugins/spaces/server/config.test.ts | 2 +- x-pack/plugins/task_manager/server/index.test.ts | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) rename docs/development/core/server/{kibana-plugin-core-server.deprecationsdetails.correctionactions.md => kibana-plugin-core-server.deprecationsdetails.correctiveactions.md} (90%) diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.correctionactions.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.correctiveactions.md similarity index 90% rename from docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.correctionactions.md rename to docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.correctiveactions.md index 071396c81c58..e362bc4e0329 100644 --- a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.correctionactions.md +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.correctiveactions.md @@ -1,6 +1,6 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) > [correctiveActions](./kibana-plugin-core-server.deprecationsdetails.correctionactions.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) > [correctiveActions](./kibana-plugin-core-server.deprecationsdetails.correctiveactions.md) ## DeprecationsDetails.correctiveActions property diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.md index 00488070f3c2..affc52f1830d 100644 --- a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.md +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.md @@ -14,7 +14,7 @@ export interface DeprecationsDetails | Property | Type | Description | | --- | --- | --- | -| [correctiveActions](./kibana-plugin-core-server.deprecationsdetails.correctionactions.md) | {
api?: {
path: string;
method: 'POST' | 'PUT';
body?: {
[key: string]: any;
};
};
manualSteps?: string[];
} | | +| [correctiveActions](./kibana-plugin-core-server.deprecationsdetails.correctiveactions.md) | {
api?: {
path: string;
method: 'POST' | 'PUT';
body?: {
[key: string]: any;
};
};
manualSteps?: string[];
} | | | [documentationUrl](./kibana-plugin-core-server.deprecationsdetails.documentationurl.md) | string | | | [level](./kibana-plugin-core-server.deprecationsdetails.level.md) | 'warning' | 'critical' | | | [message](./kibana-plugin-core-server.deprecationsdetails.message.md) | string | | diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md index 9f65568bb87f..7d214927621a 100644 --- a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md @@ -4,7 +4,7 @@ ## DeprecationsServiceSetup interface -Deprecations Service is a mechanism to allow plugins to communiicate deprecated features. +The deprecations service provides a way for the Kibana platform to communicate deprecated features and configs with its users. These deprecations are only communicated if the deployment is using these features. Allowing for a user tailored experience for upgrading the stack version. Signature: diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index c0f535e2e859..d535a4e9484e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -71,7 +71,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [DeprecationInfo](./kibana-plugin-core-server.deprecationinfo.md) | | | [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) | | | [DeprecationSettings](./kibana-plugin-core-server.deprecationsettings.md) | UiSettings deprecation field options. | -| [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) | Deprecations Service is a mechanism to allow plugins to communiicate deprecated features. | +| [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) | The deprecations service provides a way for the Kibana platform to communicate deprecated features and configs with its users. These deprecations are only communicated if the deployment is using these features. Allowing for a user tailored experience for upgrading the stack version. | | [DiscoveredPlugin](./kibana-plugin-core-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. | | [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) | | | [ElasticsearchServiceStart](./kibana-plugin-core-server.elasticsearchservicestart.md) | | diff --git a/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md b/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md index 16b416363e4f..cf008725ff15 100644 --- a/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md +++ b/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md @@ -7,5 +7,5 @@ Signature: ```typescript -getDeprecations: (dependencies: GetDeprecationsContext) => MaybePromise; +getDeprecations: (context: GetDeprecationsContext) => MaybePromise; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.md b/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.md index 7edc5e3cf2b6..59e6d406f84b 100644 --- a/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.md +++ b/docs/development/core/server/kibana-plugin-core-server.registerdeprecationsconfig.md @@ -14,5 +14,5 @@ export interface RegisterDeprecationsConfig | Property | Type | Description | | --- | --- | --- | -| [getDeprecations](./kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md) | (dependencies: GetDeprecationsContext) => MaybePromise<DeprecationsDetails[]> | | +| [getDeprecations](./kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md) | (context: GetDeprecationsContext) => MaybePromise<DeprecationsDetails[]> | | diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index dfaeb7469cf7..a8454e1928db 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -1946,7 +1946,7 @@ export interface RegisterDeprecationsConfig { // Warning: (ae-forgotten-export) The symbol "MaybePromise" needs to be exported by the entry point index.d.ts // // (undocumented) - getDeprecations: (dependencies: GetDeprecationsContext) => MaybePromise; + getDeprecations: (context: GetDeprecationsContext) => MaybePromise; } // @public diff --git a/x-pack/plugins/reporting/server/config/index.test.ts b/x-pack/plugins/reporting/server/config/index.test.ts index d7c12937cda7..a395cd23288e 100644 --- a/x-pack/plugins/reporting/server/config/index.test.ts +++ b/x-pack/plugins/reporting/server/config/index.test.ts @@ -21,7 +21,7 @@ const applyReportingDeprecations = (settings: Record = {}) => { deprecation, path: CONFIG_PATH, })), - (msg) => deprecationMessages.push(msg) + () => ({ message }) => deprecationMessages.push(message) ); return { messages: deprecationMessages, diff --git a/x-pack/plugins/security/server/config_deprecations.test.ts b/x-pack/plugins/security/server/config_deprecations.test.ts index 2b6ad603e616..80173dd42a49 100644 --- a/x-pack/plugins/security/server/config_deprecations.test.ts +++ b/x-pack/plugins/security/server/config_deprecations.test.ts @@ -20,7 +20,7 @@ const applyConfigDeprecations = (settings: Record = {}) => { deprecation, path: 'xpack.security', })), - (msg) => deprecationMessages.push(msg) + () => ({ message }) => deprecationMessages.push(message) ); return { messages: deprecationMessages, diff --git a/x-pack/plugins/spaces/server/config.test.ts b/x-pack/plugins/spaces/server/config.test.ts index 41c4995b5bcf..1ce1be0698b1 100644 --- a/x-pack/plugins/spaces/server/config.test.ts +++ b/x-pack/plugins/spaces/server/config.test.ts @@ -19,7 +19,7 @@ const applyConfigDeprecations = (settings: Record = {}) => { deprecation, path: '', })), - (msg) => deprecationMessages.push(msg) + () => ({ message }) => deprecationMessages.push(message) ); return { messages: deprecationMessages, diff --git a/x-pack/plugins/task_manager/server/index.test.ts b/x-pack/plugins/task_manager/server/index.test.ts index 470b47b40f67..3fce5f7bdfdf 100644 --- a/x-pack/plugins/task_manager/server/index.test.ts +++ b/x-pack/plugins/task_manager/server/index.test.ts @@ -22,7 +22,7 @@ const applyTaskManagerDeprecations = (settings: Record = {}) => deprecation, path: CONFIG_PATH, })), - (msg) => deprecationMessages.push(msg) + () => ({ message }) => deprecationMessages.push(message) ); return { messages: deprecationMessages, From e5983fdc36e82540d98117a816805c8da2eab72a Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 18 Mar 2021 15:03:11 +0200 Subject: [PATCH 05/23] type_check --- x-pack/plugins/task_manager/server/index.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/task_manager/server/index.ts b/x-pack/plugins/task_manager/server/index.ts index 6d744010757f..02d114fda1d7 100644 --- a/x-pack/plugins/task_manager/server/index.ts +++ b/x-pack/plugins/task_manager/server/index.ts @@ -31,17 +31,18 @@ export { export const config: PluginConfigDescriptor = { schema: configSchema, deprecations: () => [ - (settings, fromPath, log) => { + (settings, fromPath, deprecationHook) => { const taskManager = get(settings, fromPath); if (taskManager?.index) { - log( - `"${fromPath}.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details` - ); + deprecationHook({ + documentationUrl: 'https://ela.st/kbn-remove-legacy-multitenancy', + message: `"${fromPath}.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details`, + }); } if (taskManager?.max_workers > MAX_WORKERS_LIMIT) { - log( - `setting "${fromPath}.max_workers" (${taskManager?.max_workers}) greater than ${MAX_WORKERS_LIMIT} is deprecated. Values greater than ${MAX_WORKERS_LIMIT} will not be supported starting in 8.0.` - ); + deprecationHook({ + message: `setting "${fromPath}.max_workers" (${taskManager?.max_workers}) greater than ${MAX_WORKERS_LIMIT} is deprecated. Values greater than ${MAX_WORKERS_LIMIT} will not be supported starting in 8.0.`, + }); } return settings; }, From 376ff368a73d8a199abda1b7625e84d7b1f3173a Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 18 Mar 2021 16:00:46 +0200 Subject: [PATCH 06/23] more type check fixes --- .../monitoring/server/deprecations.test.js | 74 +++++++++---------- .../plugins/reporting/server/config/index.ts | 8 +- .../security/server/config_deprecations.ts | 38 +++++----- 3 files changed, 62 insertions(+), 58 deletions(-) diff --git a/x-pack/plugins/monitoring/server/deprecations.test.js b/x-pack/plugins/monitoring/server/deprecations.test.js index 156fc76b6e07..7e9e3e1bcfbb 100644 --- a/x-pack/plugins/monitoring/server/deprecations.test.js +++ b/x-pack/plugins/monitoring/server/deprecations.test.js @@ -16,8 +16,8 @@ describe('monitoring plugin deprecations', function () { beforeAll(function () { const deprecations = deprecationsModule({ rename, renameFromRoot }); - transformDeprecations = (settings, fromPath, log = noop) => { - deprecations.forEach((deprecation) => deprecation(settings, fromPath, log)); + transformDeprecations = (settings, fromPath, deprecationHook = noop) => { + deprecations.forEach((deprecation) => deprecation(settings, fromPath, deprecationHook)); }; }); @@ -31,9 +31,9 @@ describe('monitoring plugin deprecations', function () { }, }; - const log = jest.fn(); - transformDeprecations(settings, fromPath, log); - expect(log).not.toHaveBeenCalled(); + const deprecationHook = jest.fn(); + transformDeprecations(settings, fromPath, deprecationHook); + expect(deprecationHook).not.toHaveBeenCalled(); }); it(`shouldn't log when cluster alerts are disabled`, function () { @@ -46,9 +46,9 @@ describe('monitoring plugin deprecations', function () { }, }; - const log = jest.fn(); - transformDeprecations(settings, fromPath, log); - expect(log).not.toHaveBeenCalled(); + const deprecationHook = jest.fn(); + transformDeprecations(settings, fromPath, deprecationHook); + expect(deprecationHook).not.toHaveBeenCalled(); }); it(`shouldn't log when email_address is specified`, function () { @@ -62,9 +62,9 @@ describe('monitoring plugin deprecations', function () { }, }; - const log = jest.fn(); - transformDeprecations(settings, fromPath, log); - expect(log).not.toHaveBeenCalled(); + const deprecationHook = jest.fn(); + transformDeprecations(settings, fromPath, deprecationHook); + expect(deprecationHook).not.toHaveBeenCalled(); }); it(`should log when email_address is missing, but alerts/notifications are both enabled`, function () { @@ -77,9 +77,9 @@ describe('monitoring plugin deprecations', function () { }, }; - const log = jest.fn(); - transformDeprecations(settings, fromPath, log); - expect(log).toHaveBeenCalled(); + const deprecationHook = jest.fn(); + transformDeprecations(settings, fromPath, deprecationHook); + expect(deprecationHook).toHaveBeenCalled(); }); }); @@ -87,65 +87,65 @@ describe('monitoring plugin deprecations', function () { it('logs a warning if elasticsearch.username is set to "elastic"', () => { const settings = { elasticsearch: { username: 'elastic' } }; - const log = jest.fn(); - transformDeprecations(settings, fromPath, log); - expect(log).toHaveBeenCalled(); + const deprecationHook = jest.fn(); + transformDeprecations(settings, fromPath, deprecationHook); + expect(deprecationHook).toHaveBeenCalled(); }); it('logs a warning if elasticsearch.username is set to "kibana"', () => { const settings = { elasticsearch: { username: 'kibana' } }; - const log = jest.fn(); - transformDeprecations(settings, fromPath, log); - expect(log).toHaveBeenCalled(); + const deprecationHook = jest.fn(); + transformDeprecations(settings, fromPath, deprecationHook); + expect(deprecationHook).toHaveBeenCalled(); }); it('does not log a warning if elasticsearch.username is set to something besides "elastic" or "kibana"', () => { const settings = { elasticsearch: { username: 'otheruser' } }; - const log = jest.fn(); - transformDeprecations(settings, fromPath, log); - expect(log).not.toHaveBeenCalled(); + const deprecationHook = jest.fn(); + transformDeprecations(settings, fromPath, deprecationHook); + expect(deprecationHook).not.toHaveBeenCalled(); }); it('does not log a warning if elasticsearch.username is unset', () => { const settings = { elasticsearch: { username: undefined } }; - const log = jest.fn(); - transformDeprecations(settings, fromPath, log); - expect(log).not.toHaveBeenCalled(); + const deprecationHook = jest.fn(); + transformDeprecations(settings, fromPath, deprecationHook); + expect(deprecationHook).not.toHaveBeenCalled(); }); it('logs a warning if ssl.key is set and ssl.certificate is not', () => { const settings = { elasticsearch: { ssl: { key: '' } } }; - const log = jest.fn(); - transformDeprecations(settings, fromPath, log); - expect(log).toHaveBeenCalled(); + const deprecationHook = jest.fn(); + transformDeprecations(settings, fromPath, deprecationHook); + expect(deprecationHook).toHaveBeenCalled(); }); it('logs a warning if ssl.certificate is set and ssl.key is not', () => { const settings = { elasticsearch: { ssl: { certificate: '' } } }; - const log = jest.fn(); - transformDeprecations(settings, fromPath, log); - expect(log).toHaveBeenCalled(); + const deprecationHook = jest.fn(); + transformDeprecations(settings, fromPath, deprecationHook); + expect(deprecationHook).toHaveBeenCalled(); }); it('does not log a warning if both ssl.key and ssl.certificate are set', () => { const settings = { elasticsearch: { ssl: { key: '', certificate: '' } } }; - const log = jest.fn(); - transformDeprecations(settings, fromPath, log); - expect(log).not.toHaveBeenCalled(); + const deprecationHook = jest.fn(); + transformDeprecations(settings, fromPath, deprecationHook); + expect(deprecationHook).not.toHaveBeenCalled(); }); }); describe('xpack_api_polling_frequency_millis', () => { it('should call rename for this renamed config key', () => { const settings = { xpack_api_polling_frequency_millis: 30000 }; - const log = jest.fn(); - transformDeprecations(settings, fromPath, log); + const deprecationHook = jest.fn(); + transformDeprecations(settings, fromPath, deprecationHook); expect(rename).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/reporting/server/config/index.ts b/x-pack/plugins/reporting/server/config/index.ts index 06975aa85f1e..c537e03e9fa0 100644 --- a/x-pack/plugins/reporting/server/config/index.ts +++ b/x-pack/plugins/reporting/server/config/index.ts @@ -24,12 +24,12 @@ export const config: PluginConfigDescriptor = { unused('poll.jobCompletionNotifier.intervalErrorMultiplier'), unused('poll.jobsRefresh.intervalErrorMultiplier'), unused('kibanaApp'), - (settings, fromPath, log) => { + (settings, fromPath, deprecationHook) => { const reporting = get(settings, fromPath); if (reporting?.index) { - log( - `"${fromPath}.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details` - ); + deprecationHook({ + message: `"${fromPath}.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details`, + }); } return settings; }, diff --git a/x-pack/plugins/security/server/config_deprecations.ts b/x-pack/plugins/security/server/config_deprecations.ts index a7bb5e09fb91..0005ec70906c 100644 --- a/x-pack/plugins/security/server/config_deprecations.ts +++ b/x-pack/plugins/security/server/config_deprecations.ts @@ -22,16 +22,17 @@ export const securityConfigDeprecationProvider: ConfigDeprecationProvider = ({ unused('authorization.legacyFallback.enabled'), unused('authc.saml.maxRedirectURLSize'), // Deprecation warning for the old array-based format of `xpack.security.authc.providers`. - (settings, fromPath, log) => { + (settings, fromPath, deprecationHook) => { if (Array.isArray(settings?.xpack?.security?.authc?.providers)) { - log( - 'Defining `xpack.security.authc.providers` as an array of provider types is deprecated. Use extended `object` format instead.' - ); + deprecationHook({ + message: + 'Defining `xpack.security.authc.providers` as an array of provider types is deprecated. Use extended `object` format instead.', + }); } return settings; }, - (settings, fromPath, log) => { + (settings, fromPath, deprecationHook) => { const hasProviderType = (providerType: string) => { const providers = settings?.xpack?.security?.authc?.providers; if (Array.isArray(providers)) { @@ -44,31 +45,34 @@ export const securityConfigDeprecationProvider: ConfigDeprecationProvider = ({ }; if (hasProviderType('basic') && hasProviderType('token')) { - log( - 'Enabling both `basic` and `token` authentication providers in `xpack.security.authc.providers` is deprecated. Login page will only use `token` provider.' - ); + deprecationHook({ + message: + 'Enabling both `basic` and `token` authentication providers in `xpack.security.authc.providers` is deprecated. Login page will only use `token` provider.', + }); } return settings; }, - (settings, fromPath, log) => { + (settings, fromPath, deprecationHook) => { const samlProviders = (settings?.xpack?.security?.authc?.providers?.saml ?? {}) as Record< string, any >; if (Object.values(samlProviders).find((provider) => !!provider.maxRedirectURLSize)) { - log( - '`xpack.security.authc.providers.saml..maxRedirectURLSize` is deprecated and is no longer used' - ); + deprecationHook({ + message: + '`xpack.security.authc.providers.saml..maxRedirectURLSize` is deprecated and is no longer used', + }); } return settings; }, - (settings, fromPath, log) => { + (settings, fromPath, deprecationHook) => { if (settings?.xpack?.security?.enabled === false) { - log( - 'Disabling the security plugin (`xpack.security.enabled`) will not be supported in the next major version (8.0). ' + - 'To turn off security features, disable them in Elasticsearch instead.' - ); + deprecationHook({ + message: + 'Disabling the security plugin (`xpack.security.enabled`) will not be supported in the next major version (8.0). ' + + 'To turn off security features, disable them in Elasticsearch instead.', + }); } return settings; }, From 87b0261a55e9cc39c24094a2b35b3dcfce8917b4 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Sun, 21 Mar 2021 13:24:08 +0200 Subject: [PATCH 07/23] update snapshots --- .../config/deprecation/core_deprecations.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/server/config/deprecation/core_deprecations.test.ts b/src/core/server/config/deprecation/core_deprecations.test.ts index 902569dafbfe..e3c236405a59 100644 --- a/src/core/server/config/deprecation/core_deprecations.test.ts +++ b/src/core/server/config/deprecation/core_deprecations.test.ts @@ -305,7 +305,7 @@ describe('core deprecations', () => { }); expect(messages).toMatchInlineSnapshot(` Array [ - "\\"logging.dest\\" has been deprecated and will be removed in 8.0. To set the destination moving forward, you can use the \\"console\\" appender in your logging configuration or define a custom one. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx.", + "\\"logging.dest\\" has been deprecated and will be removed in 8.0. To set the destination moving forward, you can use the \\"console\\" appender in your logging configuration or define a custom one. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx", ] `); }); @@ -315,7 +315,7 @@ describe('core deprecations', () => { }); expect(messages).toMatchInlineSnapshot(` Array [ - "\\"logging.dest\\" has been deprecated and will be removed in 8.0. To set the destination moving forward, you can use the \\"console\\" appender in your logging configuration or define a custom one. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx.", + "\\"logging.dest\\" has been deprecated and will be removed in 8.0. To set the destination moving forward, you can use the \\"console\\" appender in your logging configuration or define a custom one. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx", ] `); }); @@ -361,7 +361,7 @@ describe('core deprecations', () => { }); expect(messages).toMatchInlineSnapshot(` Array [ - "\\"logging.json\\" has been deprecated and will be removed in 8.0. To specify log message format moving forward, you can configure the \\"appender.layout\\" property for every custom appender in your logging configuration. There is currently no default layout for custom appenders and each one must be declared explicitly. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx.", + "\\"logging.json\\" has been deprecated and will be removed in 8.0. To specify log message format moving forward, you can configure the \\"appender.layout\\" property for every custom appender in your logging configuration. There is currently no default layout for custom appenders and each one must be declared explicitly. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx", ] `); }); @@ -446,7 +446,7 @@ describe('core deprecations', () => { }); expect(messages).toMatchInlineSnapshot(` Array [ - "\\"logging.filter\\" has been deprecated and will be removed in 8.0. ", + "\\"logging.filter\\" has been deprecated and will be removed in 8.0.", ] `); }); @@ -457,7 +457,7 @@ describe('core deprecations', () => { }); expect(messages).toMatchInlineSnapshot(` Array [ - "\\"logging.filter\\" has been deprecated and will be removed in 8.0. ", + "\\"logging.filter\\" has been deprecated and will be removed in 8.0.", ] `); }); From 39903d63fd02b9bae6529ce0d9a0fee900cbe13c Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Sun, 21 Mar 2021 15:07:33 +0200 Subject: [PATCH 08/23] update kbn-config tests --- .../src/config_service.test.mocks.ts | 8 +- .../kbn-config/src/config_service.test.ts | 80 +++++++++-- packages/kbn-config/src/config_service.ts | 8 +- .../deprecation/apply_deprecations.test.ts | 27 +++- .../src/deprecation/apply_deprecations.ts | 6 +- .../deprecation/deprecation_factory.test.ts | 135 +++++++++++------- 6 files changed, 189 insertions(+), 75 deletions(-) diff --git a/packages/kbn-config/src/config_service.test.mocks.ts b/packages/kbn-config/src/config_service.test.mocks.ts index 99539726c3e4..c5a31b6dd098 100644 --- a/packages/kbn-config/src/config_service.test.mocks.ts +++ b/packages/kbn-config/src/config_service.test.mocks.ts @@ -7,9 +7,15 @@ */ export const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); +import type { ConfigDeprecationWithContext, ConfigDeprecationHook } from './deprecation/types'; + jest.mock('../../../package.json', () => mockPackage); -export const mockApplyDeprecations = jest.fn((config, deprecations, log) => config); +export const mockApplyDeprecations = jest.fn< + Record, + [Record, ConfigDeprecationWithContext[], (pluginId: string) => ConfigDeprecationHook] +>((config, deprecations, deprecationFactory) => config); + jest.mock('./deprecation/apply_deprecations', () => ({ applyDeprecations: mockApplyDeprecations, })); diff --git a/packages/kbn-config/src/config_service.test.ts b/packages/kbn-config/src/config_service.test.ts index e38fff866df8..e65ba79abb3e 100644 --- a/packages/kbn-config/src/config_service.test.ts +++ b/packages/kbn-config/src/config_service.test.ts @@ -72,10 +72,10 @@ test('throws if config at path does not match schema', async () => { ); await expect(valuesReceived).toMatchInlineSnapshot(` - Array [ - [Error: [config validation of [key]]: expected value of type [string] but got [number]], - ] - `); + Array [ + [Error: [config validation of [key]]: expected value of type [string] but got [number]], + ] + `); }); test('re-validate config when updated', async () => { @@ -98,11 +98,11 @@ test('re-validate config when updated', async () => { rawConfig$.next({ key: 123 }); await expect(valuesReceived).toMatchInlineSnapshot(` - Array [ - "value", - [Error: [config validation of [key]]: expected value of type [string] but got [number]], - ] - `); + Array [ + "value", + [Error: [config validation of [key]]: expected value of type [string] but got [number]], + ] + `); }); test("does not push new configs when reloading if config at path hasn't changed", async () => { @@ -416,10 +416,10 @@ test('throws during validation is any schema is invalid', async () => { test('logs deprecation warning during validation', async () => { const rawConfig = getRawConfigProvider({}); const configService = new ConfigService(rawConfig, defaultEnv, logger); - - mockApplyDeprecations.mockImplementationOnce((config, deprecations, log) => { - log('some deprecation message'); - log('another deprecation message'); + mockApplyDeprecations.mockImplementationOnce((config, deprecations, deprecationFactory) => { + const deprecationHook = deprecationFactory(''); + deprecationHook({ message: 'some deprecation message' }); + deprecationHook({ message: 'another deprecation message' }); return config; }); @@ -437,6 +437,27 @@ test('logs deprecation warning during validation', async () => { `); }); +test('does not log warnings for silent deprecations during validation', async () => { + const rawConfig = getRawConfigProvider({}); + const configService = new ConfigService(rawConfig, defaultEnv, logger); + mockApplyDeprecations.mockImplementationOnce((config, deprecations, deprecationFactory) => { + const deprecationHook = deprecationFactory(''); + deprecationHook({ message: 'some deprecation message', silent: true }); + deprecationHook({ message: 'another deprecation message' }); + return config; + }); + + loggerMock.clear(logger); + await configService.validate(); + expect(loggerMock.collect(logger).warn).toMatchInlineSnapshot(` + Array [ + Array [ + "another deprecation message", + ], + ] + `); +}); + describe('atPathSync', () => { test('returns the value at path', async () => { const rawConfig = getRawConfigProvider({ key: 'foo' }); @@ -477,3 +498,36 @@ describe('atPathSync', () => { expect(configService.atPathSync('key')).toEqual('new-value'); }); }); + +describe('getHandledDeprecatedConfigs', () => { + it('returns all handled deprecated configs', async () => { + const rawConfig = getRawConfigProvider({ base: { unused: 'unusedConfig' } }); + const configService = new ConfigService(rawConfig, defaultEnv, logger); + + configService.addDeprecationProvider('base', ({ unused }) => [unused('unused')]); + + mockApplyDeprecations.mockImplementationOnce((config, deprecations, deprecationFactory) => { + deprecations.forEach((deprecation) => { + const deprecationHook = deprecationFactory(deprecation.path); + deprecationHook({ message: `some deprecation message`, documentationUrl: 'some-url' }); + }); + return config; + }); + + await configService.validate(); + + expect(configService.getHandledDeprecatedConfigs()).toMatchInlineSnapshot(` + Array [ + Array [ + "base", + Array [ + Object { + "documentationUrl": "some-url", + "message": "some deprecation message", + }, + ], + ], + ] + `); + }); +}); diff --git a/packages/kbn-config/src/config_service.ts b/packages/kbn-config/src/config_service.ts index 59f5ae054e25..3a5c95f27a19 100644 --- a/packages/kbn-config/src/config_service.ts +++ b/packages/kbn-config/src/config_service.ts @@ -195,14 +195,16 @@ export class ConfigService { const rawConfig = await this.rawConfigProvider.getConfig$().pipe(take(1)).toPromise(); const deprecations = await this.deprecations.pipe(take(1)).toPromise(); const deprecationMessages: string[] = []; - const onHandleDeprecationHook = (pluginId: string) => (context: DeprecatedConfigDetails) => { - deprecationMessages.push(context.message); + const deprecationHookFactory = (pluginId: string) => (context: DeprecatedConfigDetails) => { + if (!context.silent) { + deprecationMessages.push(context.message); + } const handledDeprecatedConfig = this.handledDeprecatedConfigs.get(pluginId) || []; handledDeprecatedConfig.push(context); this.handledDeprecatedConfigs.set(pluginId, handledDeprecatedConfig); }; - applyDeprecations(rawConfig, deprecations, onHandleDeprecationHook); + applyDeprecations(rawConfig, deprecations, deprecationHookFactory); deprecationMessages.forEach((msg) => { this.deprecationLog.warn(msg); }); diff --git a/packages/kbn-config/src/deprecation/apply_deprecations.test.ts b/packages/kbn-config/src/deprecation/apply_deprecations.test.ts index 62970613db42..99cab12ef5cf 100644 --- a/packages/kbn-config/src/deprecation/apply_deprecations.test.ts +++ b/packages/kbn-config/src/deprecation/apply_deprecations.test.ts @@ -32,8 +32,31 @@ describe('applyDeprecations', () => { expect(handlerC).toHaveBeenCalledTimes(1); }); + it('passes path to deprecationHook factory', () => { + const deprecationHook = jest.fn(); + const deprecationHookFactory = jest.fn().mockReturnValue(deprecationHook); + const initialConfig = { foo: 'bar', deprecated: 'deprecated' }; + const alteredConfig = { foo: 'bar' }; + + const handlerA = jest.fn().mockReturnValue(alteredConfig); + const handlerB = jest.fn().mockImplementation((conf) => conf); + + applyDeprecations( + initialConfig, + [wrapHandler(handlerA, 'pathA'), wrapHandler(handlerB, 'pathB')], + deprecationHookFactory + ); + + expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', deprecationHook); + expect(handlerB).toHaveBeenCalledWith(alteredConfig, 'pathB', deprecationHook); + expect(deprecationHookFactory).toBeCalledTimes(2); + expect(deprecationHookFactory).toHaveBeenNthCalledWith(1, 'pathA'); + expect(deprecationHookFactory).toHaveBeenNthCalledWith(2, 'pathB'); + }); + it('calls handlers with correct arguments', () => { - const deprecationHook = () => undefined; + const deprecationHook = jest.fn(); + const deprecationHookFactory = jest.fn().mockReturnValue(deprecationHook); const initialConfig = { foo: 'bar', deprecated: 'deprecated' }; const alteredConfig = { foo: 'bar' }; @@ -43,7 +66,7 @@ describe('applyDeprecations', () => { applyDeprecations( initialConfig, [wrapHandler(handlerA, 'pathA'), wrapHandler(handlerB, 'pathB')], - () => deprecationHook + deprecationHookFactory ); expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', deprecationHook); diff --git a/packages/kbn-config/src/deprecation/apply_deprecations.ts b/packages/kbn-config/src/deprecation/apply_deprecations.ts index 62306683b993..0eee001cddb4 100644 --- a/packages/kbn-config/src/deprecation/apply_deprecations.ts +++ b/packages/kbn-config/src/deprecation/apply_deprecations.ts @@ -9,7 +9,7 @@ import { cloneDeep } from 'lodash'; import { ConfigDeprecationWithContext, ConfigDeprecationHook } from './types'; -const noopConfigDeprecationHook: () => ConfigDeprecationHook = () => () => undefined; +const noopDeprecationHookFactory: () => ConfigDeprecationHook = () => () => undefined; /** * Applies deprecations on given configuration and passes handled deprecation deprecationHook * This hook is used for logging any deprecation warning using provided logger. @@ -20,11 +20,11 @@ const noopConfigDeprecationHook: () => ConfigDeprecationHook = () => () => undef export const applyDeprecations = ( config: Record, deprecations: ConfigDeprecationWithContext[], - deprecationHook: (pluginId: string) => ConfigDeprecationHook = noopConfigDeprecationHook + deprecationHookFactory: (pluginId: string) => ConfigDeprecationHook = noopDeprecationHookFactory ) => { let processed = cloneDeep(config); deprecations.forEach(({ deprecation, path }) => { - processed = deprecation(processed, path, deprecationHook(path)); + processed = deprecation(processed, path, deprecationHookFactory(path)); }); return processed; }; diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts index b3c4e94c700e..64ac51c4e230 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts @@ -6,17 +6,16 @@ * Side Public License, v 1. */ -import { ConfigDeprecationHook } from './types'; +import { DeprecatedConfigDetails } from './types'; import { configDeprecationFactory } from './deprecation_factory'; describe('DeprecationFactory', () => { const { rename, unused, renameFromRoot, unusedFromRoot } = configDeprecationFactory; - let deprecationMessages: string[]; - const deprecationHook: ConfigDeprecationHook = ({ message }) => deprecationMessages.push(message); + const deprecationHook = jest.fn(); beforeEach(() => { - deprecationMessages = []; + deprecationHook.mockClear(); }); describe('rename', () => { @@ -40,11 +39,14 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationMessages).toMatchInlineSnapshot(` - Array [ - "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\"", - ] - `); + expect(deprecationHook).toBeCalledWith({ + correctiveActions: { + manualSteps: [ + 'Replace "myplugin.deprecated" in the kibana.yml file with "myplugin.renamed"', + ], + }, + message: '"myplugin.deprecated" is deprecated and has been replaced by "myplugin.renamed"', + }); }); it('does not alter config and does not log if old property is not present', () => { const rawConfig = { @@ -66,7 +68,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationMessages.length).toEqual(0); + expect(deprecationHook).toHaveBeenCalledTimes(0); }); it('handles nested keys', () => { const rawConfig = { @@ -97,11 +99,15 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationMessages).toMatchInlineSnapshot(` - Array [ - "\\"myplugin.oldsection.deprecated\\" is deprecated and has been replaced by \\"myplugin.newsection.renamed\\"", - ] - `); + expect(deprecationHook).toBeCalledWith({ + correctiveActions: { + manualSteps: [ + 'Replace "myplugin.oldsection.deprecated" in the kibana.yml file with "myplugin.newsection.renamed"', + ], + }, + message: + '"myplugin.oldsection.deprecated" is deprecated and has been replaced by "myplugin.newsection.renamed"', + }); }); it('remove the old property but does not overrides the new one if they both exist, and logs a specific message', () => { const rawConfig = { @@ -116,11 +122,16 @@ describe('DeprecationFactory', () => { renamed: 'renamed', }, }); - expect(deprecationMessages).toMatchInlineSnapshot(` - Array [ - "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\". However both key are present, ignoring \\"myplugin.deprecated\\"", - ] - `); + expect(deprecationHook).toBeCalledWith({ + correctiveActions: { + manualSteps: [ + 'Make sure "myplugin.renamed" contains the correct value in the kibana.yml file."', + 'Remove "myplugin.deprecated" from the kibana.yml file."', + ], + }, + message: + '"myplugin.deprecated" is deprecated and has been replaced by "myplugin.renamed". However both key are present, ignoring "myplugin.deprecated"', + }); }); }); @@ -149,11 +160,14 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationMessages).toMatchInlineSnapshot(` - Array [ - "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\"", - ] - `); + expect(deprecationHook).toBeCalledWith({ + correctiveActions: { + manualSteps: [ + 'Replace "myplugin.deprecated" in the kibana.yml file with "myplugin.renamed"', + ], + }, + message: '"myplugin.deprecated" is deprecated and has been replaced by "myplugin.renamed"', + }); }); it('can move a property to a different namespace', () => { @@ -180,11 +194,15 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationMessages).toMatchInlineSnapshot(` - Array [ - "\\"oldplugin.deprecated\\" is deprecated and has been replaced by \\"newplugin.renamed\\"", - ] - `); + expect(deprecationHook).toBeCalledWith({ + correctiveActions: { + manualSteps: [ + 'Replace "oldplugin.deprecated" in the kibana.yml file with "newplugin.renamed"', + ], + }, + message: + '"oldplugin.deprecated" is deprecated and has been replaced by "newplugin.renamed"', + }); }); it('does not alter config and does not log if old property is not present', () => { @@ -211,7 +229,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationMessages.length).toEqual(0); + expect(deprecationHook).toBeCalledTimes(0); }); it('remove the old property but does not overrides the new one if they both exist, and logs a specific message', () => { @@ -231,11 +249,17 @@ describe('DeprecationFactory', () => { renamed: 'renamed', }, }); - expect(deprecationMessages).toMatchInlineSnapshot(` - Array [ - "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\". However both key are present, ignoring \\"myplugin.deprecated\\"", - ] - `); + + expect(deprecationHook).toBeCalledWith({ + correctiveActions: { + manualSteps: [ + 'Make sure "myplugin.renamed" contains the correct value in the kibana.yml file."', + 'Remove "myplugin.deprecated" from the kibana.yml file."', + ], + }, + message: + '"myplugin.deprecated" is deprecated and has been replaced by "myplugin.renamed". However both key are present, ignoring "myplugin.deprecated"', + }); }); }); @@ -259,11 +283,12 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationMessages).toMatchInlineSnapshot(` - Array [ - "myplugin.deprecated is deprecated and is no longer used", - ] - `); + expect(deprecationHook).toBeCalledWith({ + correctiveActions: { + manualSteps: ['Remove "myplugin.deprecated" from the kibana.yml file."'], + }, + message: 'myplugin.deprecated is deprecated and is no longer used', + }); }); it('handles deeply nested keys', () => { @@ -288,11 +313,13 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationMessages).toMatchInlineSnapshot(` - Array [ - "myplugin.section.deprecated is deprecated and is no longer used", - ] - `); + + expect(deprecationHook).toBeCalledWith({ + correctiveActions: { + manualSteps: ['Remove "myplugin.section.deprecated" from the kibana.yml file."'], + }, + message: 'myplugin.section.deprecated is deprecated and is no longer used', + }); }); it('does not alter config and does not log if unused property is not present', () => { @@ -313,7 +340,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationMessages.length).toEqual(0); + expect(deprecationHook).toBeCalledTimes(0); }); }); @@ -341,11 +368,13 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationMessages).toMatchInlineSnapshot(` - Array [ - "myplugin.deprecated is deprecated and is no longer used", - ] - `); + + expect(deprecationHook).toBeCalledWith({ + correctiveActions: { + manualSteps: ['Remove "myplugin.deprecated" from the kibana.yml file."'], + }, + message: 'myplugin.deprecated is deprecated and is no longer used', + }); }); it('does not alter config and does not log if unused property is not present', () => { @@ -370,7 +399,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationMessages.length).toEqual(0); + expect(deprecationHook).toBeCalledTimes(0); }); }); }); From 670c085becb11f96ee57e044be53fe7601194ce9 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Sun, 21 Mar 2021 19:01:49 +0200 Subject: [PATCH 09/23] add public client --- ...ugin-core-public.coresetup.deprecations.md | 13 ++ .../kibana-plugin-core-public.coresetup.md | 1 + ...ugin-core-public.corestart.deprecations.md | 13 ++ .../kibana-plugin-core-public.corestart.md | 1 + ...ecationsservicesetup.getalldeprecations.md | 13 ++ ...eprecationsservicesetup.getdeprecations.md | 13 ++ ...in-core-public.deprecationsservicesetup.md | 21 ++++ ...in-core-public.deprecationsservicestart.md | 13 ++ ...in-core-public.getalldeprecationsconfig.md | 12 ++ ...lugin-core-public.getdeprecationsconfig.md | 19 +++ ...-public.getdeprecationsconfig.skipcache.md | 13 ++ .../core/public/kibana-plugin-core-public.md | 4 + src/core/public/core_system.ts | 8 ++ .../deprecations/deprecations_client.test.ts | 116 ++++++++++++++++++ .../deprecations/deprecations_client.ts | 70 +++++++++++ .../deprecations/deprecations_service.mock.ts | 34 +++++ .../deprecations/deprecations_service.ts | 73 +++++++++++ src/core/public/deprecations/index.ts | 11 ++ src/core/public/index.ts | 12 ++ src/core/public/mocks.ts | 4 + src/core/public/plugins/plugin_context.ts | 2 + src/core/public/public.api.md | 25 +++- src/core/server/types.ts | 1 + src/plugins/data/public/public.api.md | 1 + src/plugins/embeddable/public/public.api.md | 1 + 25 files changed, 493 insertions(+), 1 deletion(-) create mode 100644 docs/development/core/public/kibana-plugin-core-public.coresetup.deprecations.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.corestart.deprecations.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getalldeprecations.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getdeprecations.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.getalldeprecationsconfig.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.skipcache.md create mode 100644 src/core/public/deprecations/deprecations_client.test.ts create mode 100644 src/core/public/deprecations/deprecations_client.ts create mode 100644 src/core/public/deprecations/deprecations_service.mock.ts create mode 100644 src/core/public/deprecations/deprecations_service.ts create mode 100644 src/core/public/deprecations/index.ts diff --git a/docs/development/core/public/kibana-plugin-core-public.coresetup.deprecations.md b/docs/development/core/public/kibana-plugin-core-public.coresetup.deprecations.md new file mode 100644 index 000000000000..ebb481b68ed2 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.coresetup.deprecations.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [CoreSetup](./kibana-plugin-core-public.coresetup.md) > [deprecations](./kibana-plugin-core-public.coresetup.deprecations.md) + +## CoreSetup.deprecations property + +[DeprecationsServiceSetup](./kibana-plugin-core-public.deprecationsservicesetup.md) + +Signature: + +```typescript +deprecations: DeprecationsServiceSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.coresetup.md b/docs/development/core/public/kibana-plugin-core-public.coresetup.md index 5d2288120da0..7a3255859a49 100644 --- a/docs/development/core/public/kibana-plugin-core-public.coresetup.md +++ b/docs/development/core/public/kibana-plugin-core-public.coresetup.md @@ -17,6 +17,7 @@ export interface CoreSetupApplicationSetup | [ApplicationSetup](./kibana-plugin-core-public.applicationsetup.md) | +| [deprecations](./kibana-plugin-core-public.coresetup.deprecations.md) | DeprecationsServiceSetup | [DeprecationsServiceSetup](./kibana-plugin-core-public.deprecationsservicesetup.md) | | [fatalErrors](./kibana-plugin-core-public.coresetup.fatalerrors.md) | FatalErrorsSetup | [FatalErrorsSetup](./kibana-plugin-core-public.fatalerrorssetup.md) | | [getStartServices](./kibana-plugin-core-public.coresetup.getstartservices.md) | StartServicesAccessor<TPluginsStart, TStart> | [StartServicesAccessor](./kibana-plugin-core-public.startservicesaccessor.md) | | [http](./kibana-plugin-core-public.coresetup.http.md) | HttpSetup | [HttpSetup](./kibana-plugin-core-public.httpsetup.md) | diff --git a/docs/development/core/public/kibana-plugin-core-public.corestart.deprecations.md b/docs/development/core/public/kibana-plugin-core-public.corestart.deprecations.md new file mode 100644 index 000000000000..624c4868d54a --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.corestart.deprecations.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [CoreStart](./kibana-plugin-core-public.corestart.md) > [deprecations](./kibana-plugin-core-public.corestart.deprecations.md) + +## CoreStart.deprecations property + +[DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) + +Signature: + +```typescript +deprecations: DeprecationsServiceStart; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.corestart.md b/docs/development/core/public/kibana-plugin-core-public.corestart.md index a7b45b318d2c..6ad9adca53ef 100644 --- a/docs/development/core/public/kibana-plugin-core-public.corestart.md +++ b/docs/development/core/public/kibana-plugin-core-public.corestart.md @@ -18,6 +18,7 @@ export interface CoreStart | --- | --- | --- | | [application](./kibana-plugin-core-public.corestart.application.md) | ApplicationStart | [ApplicationStart](./kibana-plugin-core-public.applicationstart.md) | | [chrome](./kibana-plugin-core-public.corestart.chrome.md) | ChromeStart | [ChromeStart](./kibana-plugin-core-public.chromestart.md) | +| [deprecations](./kibana-plugin-core-public.corestart.deprecations.md) | DeprecationsServiceStart | [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) | | [docLinks](./kibana-plugin-core-public.corestart.doclinks.md) | DocLinksStart | [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) | | [fatalErrors](./kibana-plugin-core-public.corestart.fatalerrors.md) | FatalErrorsStart | [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) | | [http](./kibana-plugin-core-public.corestart.http.md) | HttpStart | [HttpStart](./kibana-plugin-core-public.httpstart.md) | diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getalldeprecations.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getalldeprecations.md new file mode 100644 index 000000000000..ccdb69eef401 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getalldeprecations.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceSetup](./kibana-plugin-core-public.deprecationsservicesetup.md) > [getAllDeprecations](./kibana-plugin-core-public.deprecationsservicesetup.getalldeprecations.md) + +## DeprecationsServiceSetup.getAllDeprecations property + +Grabs deprecations for all plugins. + +Signature: + +```typescript +getAllDeprecations: DeprecationsClient['getAllDeprecations']; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getdeprecations.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getdeprecations.md new file mode 100644 index 000000000000..19178487801c --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getdeprecations.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceSetup](./kibana-plugin-core-public.deprecationsservicesetup.md) > [getDeprecations](./kibana-plugin-core-public.deprecationsservicesetup.getdeprecations.md) + +## DeprecationsServiceSetup.getDeprecations property + +Grabs deprecations for a specific plugin. + +Signature: + +```typescript +getDeprecations: DeprecationsClient['getDeprecations']; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.md new file mode 100644 index 000000000000..8d1b79efc63c --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceSetup](./kibana-plugin-core-public.deprecationsservicesetup.md) + +## DeprecationsServiceSetup interface + +DeprecationsService provides methods to fetch plugin deprecation details from the Kibana server. + +Signature: + +```typescript +export interface DeprecationsServiceSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [getAllDeprecations](./kibana-plugin-core-public.deprecationsservicesetup.getalldeprecations.md) | DeprecationsClient['getAllDeprecations'] | Grabs deprecations for all plugins. | +| [getDeprecations](./kibana-plugin-core-public.deprecationsservicesetup.getdeprecations.md) | DeprecationsClient['getDeprecations'] | Grabs deprecations for a specific plugin. | + diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md new file mode 100644 index 000000000000..8d43450c30db --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) + +## DeprecationsServiceStart type + +DeprecationsService provides methods to fetch plugin deprecation details from the Kibana server. + +Signature: + +```typescript +export declare type DeprecationsServiceStart = DeprecationsServiceSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.getalldeprecationsconfig.md b/docs/development/core/public/kibana-plugin-core-public.getalldeprecationsconfig.md new file mode 100644 index 000000000000..41757a348392 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.getalldeprecationsconfig.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [GetAllDeprecationsConfig](./kibana-plugin-core-public.getalldeprecationsconfig.md) + +## GetAllDeprecationsConfig type + + +Signature: + +```typescript +export declare type GetAllDeprecationsConfig = GetDeprecationsConfig; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.md b/docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.md new file mode 100644 index 000000000000..f6d38b29c8ca --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [GetDeprecationsConfig](./kibana-plugin-core-public.getdeprecationsconfig.md) + +## GetDeprecationsConfig interface + + +Signature: + +```typescript +export interface GetDeprecationsConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [skipCache](./kibana-plugin-core-public.getdeprecationsconfig.skipcache.md) | boolean | set true to fetch a fresh copy of the deprecations from the kibana server. | + diff --git a/docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.skipcache.md b/docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.skipcache.md new file mode 100644 index 000000000000..dc0a038625e6 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.skipcache.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [GetDeprecationsConfig](./kibana-plugin-core-public.getdeprecationsconfig.md) > [skipCache](./kibana-plugin-core-public.getdeprecationsconfig.skipcache.md) + +## GetDeprecationsConfig.skipCache property + +set true to fetch a fresh copy of the deprecations from the kibana server. + +Signature: + +```typescript +skipCache?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index e9d08dcd3bf4..ebfc5ded99e7 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -59,10 +59,12 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeUserBanner](./kibana-plugin-core-public.chromeuserbanner.md) | | | [CoreSetup](./kibana-plugin-core-public.coresetup.md) | Core services exposed to the Plugin setup lifecycle | | [CoreStart](./kibana-plugin-core-public.corestart.md) | Core services exposed to the Plugin start lifecycle | +| [DeprecationsServiceSetup](./kibana-plugin-core-public.deprecationsservicesetup.md) | DeprecationsService provides methods to fetch plugin deprecation details from the Kibana server. | | [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) | | | [ErrorToastOptions](./kibana-plugin-core-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) error APIs. | | [FatalErrorInfo](./kibana-plugin-core-public.fatalerrorinfo.md) | Represents the message and stack of a fatal Error | | [FatalErrorsSetup](./kibana-plugin-core-public.fatalerrorssetup.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | +| [GetDeprecationsConfig](./kibana-plugin-core-public.getdeprecationsconfig.md) | | | [HttpFetchOptions](./kibana-plugin-core-public.httpfetchoptions.md) | All options that may be used with a [HttpHandler](./kibana-plugin-core-public.httphandler.md). | | [HttpFetchOptionsWithPath](./kibana-plugin-core-public.httpfetchoptionswithpath.md) | Similar to [HttpFetchOptions](./kibana-plugin-core-public.httpfetchoptions.md) but with the URL path included. | | [HttpFetchQuery](./kibana-plugin-core-public.httpfetchquery.md) | | @@ -153,7 +155,9 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeHelpExtensionLinkBase](./kibana-plugin-core-public.chromehelpextensionlinkbase.md) | | | [ChromeHelpExtensionMenuLink](./kibana-plugin-core-public.chromehelpextensionmenulink.md) | | | [ChromeNavLinkUpdateableFields](./kibana-plugin-core-public.chromenavlinkupdateablefields.md) | | +| [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) | DeprecationsService provides methods to fetch plugin deprecation details from the Kibana server. | | [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | +| [GetAllDeprecationsConfig](./kibana-plugin-core-public.getalldeprecationsconfig.md) | | | [HttpStart](./kibana-plugin-core-public.httpstart.md) | See [HttpSetup](./kibana-plugin-core-public.httpsetup.md) | | [IToasts](./kibana-plugin-core-public.itoasts.md) | Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-core-public.toastsapi.md). | | [MountPoint](./kibana-plugin-core-public.mountpoint.md) | A function that should mount DOM content inside the provided container element and return a handler to unmount it. | diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 278bbe469e86..90d29ce076d6 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -28,6 +28,7 @@ import { DocLinksService } from './doc_links'; import { RenderingService } from './rendering'; import { SavedObjectsService } from './saved_objects'; import { IntegrationsService } from './integrations'; +import { DeprecationsService } from './deprecations'; import { CoreApp } from './core_app'; import type { InternalApplicationSetup, InternalApplicationStart } from './application/types'; @@ -82,6 +83,7 @@ export class CoreSystem { private readonly rendering: RenderingService; private readonly integrations: IntegrationsService; private readonly coreApp: CoreApp; + private readonly deprecations: DeprecationsService; private readonly rootDomElement: HTMLElement; private readonly coreContext: CoreContext; @@ -113,6 +115,7 @@ export class CoreSystem { this.rendering = new RenderingService(); this.application = new ApplicationService(); this.integrations = new IntegrationsService(); + this.deprecations = new DeprecationsService(); this.coreContext = { coreId: Symbol('core'), env: injectedMetadata.env }; this.plugins = new PluginsService(this.coreContext, injectedMetadata.uiPlugins); @@ -133,6 +136,7 @@ export class CoreSystem { const http = this.http.setup({ injectedMetadata, fatalErrors: this.fatalErrorsSetup }); const uiSettings = this.uiSettings.setup({ http, injectedMetadata }); const notifications = this.notifications.setup({ uiSettings }); + const deprecations = this.deprecations.setup({ http }); const application = this.application.setup({ http }); this.coreApp.setup({ application, http, injectedMetadata, notifications }); @@ -144,6 +148,7 @@ export class CoreSystem { injectedMetadata, notifications, uiSettings, + deprecations, }; // Services that do not expose contracts at setup @@ -195,6 +200,7 @@ export class CoreSystem { injectedMetadata, notifications, }); + const deprecations = this.deprecations.start(); this.coreApp.start({ application, http, notifications, uiSettings }); @@ -210,6 +216,7 @@ export class CoreSystem { overlays, uiSettings, fatalErrors, + deprecations, }; await this.plugins.start(core); @@ -252,6 +259,7 @@ export class CoreSystem { this.chrome.stop(); this.i18n.stop(); this.application.stop(); + this.deprecations.stop(); this.rootDomElement.textContent = ''; } } diff --git a/src/core/public/deprecations/deprecations_client.test.ts b/src/core/public/deprecations/deprecations_client.test.ts new file mode 100644 index 000000000000..70aea62f27f9 --- /dev/null +++ b/src/core/public/deprecations/deprecations_client.test.ts @@ -0,0 +1,116 @@ +/* + * 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 { httpServiceMock } from '../http/http_service.mock'; +import { DeprecationsClient } from './deprecations_client'; + +describe('DeprecationsClient', () => { + const http = httpServiceMock.createSetupContract(); + const mockDeprecationsInfo = [ + { pluginId: 'testPluginId-1' }, + { pluginId: 'testPluginId-1' }, + { pluginId: 'testPluginId-2' }, + ]; + + beforeEach(() => { + http.fetch.mockReset(); + http.fetch.mockResolvedValue({ deprecationsInfo: mockDeprecationsInfo }); + }); + + describe('getAllDeprecations', () => { + it('returns a list of deprecations', async () => { + const deprecationsClient = new DeprecationsClient({ http }); + const deprecations = await deprecationsClient.getAllDeprecations(); + expect(http.fetch).toBeCalledTimes(1); + expect(http.fetch).toBeCalledWith('/api/deprecations/', { + asSystemRequest: true, + }); + + expect(deprecations).toEqual(mockDeprecationsInfo); + }); + + it('caches the results', async () => { + const deprecationsClient = new DeprecationsClient({ http }); + const results = [ + await deprecationsClient.getAllDeprecations(), + await deprecationsClient.getAllDeprecations(), + ]; + + expect(http.fetch).toBeCalledTimes(1); + + expect(results).toEqual([mockDeprecationsInfo, mockDeprecationsInfo]); + }); + + it('calls the fetch api on skipCache: true', async () => { + const deprecationsClient = new DeprecationsClient({ http }); + http.fetch.mockResolvedValueOnce({ deprecationsInfo: ['test2'] }); + http.fetch.mockResolvedValueOnce({ deprecationsInfo: ['test3'] }); + const results = [ + await deprecationsClient.getAllDeprecations({ skipCache: true }), + await deprecationsClient.getAllDeprecations({ skipCache: true }), + ]; + + expect(http.fetch).toBeCalledTimes(2); + + expect(results).toEqual([['test2'], ['test3']]); + }); + }); + + describe('getDeprecations', () => { + it('returns deprecations for a single pluginId', async () => { + const deprecationsClient = new DeprecationsClient({ http }); + const deprecations = await deprecationsClient.getDeprecations('testPluginId-1'); + + expect(deprecations.length).toBe(2); + expect(deprecations).toEqual([ + { pluginId: 'testPluginId-1' }, + { pluginId: 'testPluginId-1' }, + ]); + }); + + it('returns [] if the pluginId does not have any deprecations', async () => { + const deprecationsClient = new DeprecationsClient({ http }); + const deprecations = await deprecationsClient.getDeprecations('testPluginId-4'); + + expect(deprecations).toEqual([]); + }); + + it('caches the results', async () => { + const deprecationsClient = new DeprecationsClient({ http }); + const results = [ + ...(await deprecationsClient.getDeprecations('testPluginId-1')), + ...(await deprecationsClient.getDeprecations('testPluginId-2')), + ]; + + expect(http.fetch).toBeCalledTimes(1); + expect(results).toEqual(mockDeprecationsInfo); + }); + + it('calls the fetch api on skipCache: true', async () => { + const deprecationsClient = new DeprecationsClient({ http }); + http.fetch.mockResolvedValueOnce({ + deprecationsInfo: [{ pluginId: 'testPluginId-1' }, { pluginId: 'testPluginId-1' }], + }); + http.fetch.mockResolvedValueOnce({ + deprecationsInfo: [{ pluginId: 'testPluginId-2' }, { pluginId: 'testPluginId-2' }], + }); + const results = [ + ...(await deprecationsClient.getDeprecations('testPluginId-1', { skipCache: true })), + ...(await deprecationsClient.getDeprecations('testPluginId-2', { skipCache: true })), + ]; + + expect(http.fetch).toBeCalledTimes(2); + expect(results).toEqual([ + { pluginId: 'testPluginId-1' }, + { pluginId: 'testPluginId-1' }, + { pluginId: 'testPluginId-2' }, + { pluginId: 'testPluginId-2' }, + ]); + }); + }); +}); diff --git a/src/core/public/deprecations/deprecations_client.ts b/src/core/public/deprecations/deprecations_client.ts new file mode 100644 index 000000000000..cbecd415b525 --- /dev/null +++ b/src/core/public/deprecations/deprecations_client.ts @@ -0,0 +1,70 @@ +/* + * 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 { HttpSetup } from 'src/core/public'; +import type { PluginDeprecationDetails } from '../../server/types'; + +/** + * @internal + */ +interface DeprecationsGetResponse { + deprecationsInfo: PluginDeprecationDetails[]; +} + +/** + * @internal + */ +export interface DeprecationsClientDeps { + http: Pick; +} + +/** @public */ +export interface GetDeprecationsConfig { + /** set true to fetch a fresh copy of the deprecations from the kibana server. */ + skipCache?: boolean; +} + +/** @public */ +export type GetAllDeprecationsConfig = GetDeprecationsConfig; + +export class DeprecationsClient { + private readonly http: Pick; + private deprecations?: PluginDeprecationDetails[]; + constructor({ http }: DeprecationsClientDeps) { + this.http = http; + } + + private fetchDeprecations = async (skipCache?: boolean): Promise => { + if (!skipCache && this.deprecations) { + return this.deprecations; + } + + const { deprecationsInfo } = await this.http.fetch( + '/api/deprecations/', + { + asSystemRequest: true, + } + ); + + this.deprecations = deprecationsInfo; + return deprecationsInfo; + }; + + public getAllDeprecations = async ({ skipCache }: GetAllDeprecationsConfig = {}) => { + return await this.fetchDeprecations(skipCache); + }; + + public getDeprecations = async (pluginId: string, { skipCache }: GetDeprecationsConfig = {}) => { + const deprecations = await this.fetchDeprecations(skipCache); + return deprecations.filter((deprecation) => deprecation.pluginId === pluginId); + }; + + public clearCache = () => { + this.deprecations = undefined; + }; +} diff --git a/src/core/public/deprecations/deprecations_service.mock.ts b/src/core/public/deprecations/deprecations_service.mock.ts new file mode 100644 index 000000000000..a11c4ff106ad --- /dev/null +++ b/src/core/public/deprecations/deprecations_service.mock.ts @@ -0,0 +1,34 @@ +/* + * 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 { DeprecationsService } from './deprecations_service'; +import type { DeprecationsServiceSetup, DeprecationsServiceStart } from './deprecations_service'; + +const createServiceMock = (): DeprecationsServiceSetup | DeprecationsServiceStart => ({ + getAllDeprecations: jest.fn().mockResolvedValue([]), + getDeprecations: jest.fn().mockResolvedValue([]), +}); + +const createMock = () => { + const mocked: jest.Mocked> = { + setup: jest.fn(), + start: jest.fn(), + stop: jest.fn(), + }; + + mocked.setup.mockReturnValue(createServiceMock()); + mocked.start.mockReturnValue(createServiceMock()); + return mocked; +}; + +export const deprecationsServiceMock = { + create: createMock, + createSetupContract: createServiceMock as () => DeprecationsServiceSetup, + createStartContract: createServiceMock as () => DeprecationsServiceStart, +}; diff --git a/src/core/public/deprecations/deprecations_service.ts b/src/core/public/deprecations/deprecations_service.ts new file mode 100644 index 000000000000..56459e823b70 --- /dev/null +++ b/src/core/public/deprecations/deprecations_service.ts @@ -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 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 { CoreService } from 'src/core/types'; +import { CoreSetup } from 'src/core/public'; +import { DeprecationsClient } from './deprecations_client'; + +/** + * DeprecationsService provides methods to fetch plugin deprecation details from + * the Kibana server. + * + * @public + */ +export interface DeprecationsServiceSetup { + /** + * Grabs deprecations for all plugins. + * + * @param {Object} configs { skipCache: boolean }; + * set skipCache: true to fetch a fresh copy of the deprecations from the kibana server. + */ + getAllDeprecations: DeprecationsClient['getAllDeprecations']; + /** + * Grabs deprecations for a specific plugin. + * + * @param {string} pluginId + * @param {Object} configs { skipCache: boolean }; + * set skipCache: true to fetch a fresh copy of the deprecations from the kibana server. + */ + getDeprecations: DeprecationsClient['getDeprecations']; +} + +/** + * DeprecationsService provides methods to fetch plugin deprecation details from + * the Kibana server. + * + * @public + */ +export type DeprecationsServiceStart = DeprecationsServiceSetup; + +export class DeprecationsService + implements CoreService { + private deprecationsClient?: DeprecationsClient; + + public setup({ http }: Pick): DeprecationsServiceSetup { + this.deprecationsClient = new DeprecationsClient({ http }); + return { + getAllDeprecations: this.deprecationsClient.getAllDeprecations, + getDeprecations: this.deprecationsClient.getDeprecations, + }; + } + + public start(): DeprecationsServiceStart { + if (!this.deprecationsClient) { + throw new Error('#setup must be called first.'); + } + + return { + getAllDeprecations: this.deprecationsClient.getAllDeprecations, + getDeprecations: this.deprecationsClient.getDeprecations, + }; + } + + public stop() { + if (this.deprecationsClient) { + this.deprecationsClient.clearCache(); + } + } +} diff --git a/src/core/public/deprecations/index.ts b/src/core/public/deprecations/index.ts new file mode 100644 index 000000000000..cf4ac4cff9d1 --- /dev/null +++ b/src/core/public/deprecations/index.ts @@ -0,0 +1,11 @@ +/* + * 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. + */ + +export { DeprecationsService } from './deprecations_service'; +export type { DeprecationsServiceSetup, DeprecationsServiceStart } from './deprecations_service'; +export type { GetDeprecationsConfig, GetAllDeprecationsConfig } from './deprecations_client'; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index c7b4c370eb6d..9506975ae8d2 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -65,6 +65,7 @@ import { UiSettingsState, IUiSettingsClient } from './ui_settings'; import { ApplicationSetup, Capabilities, ApplicationStart } from './application'; import { DocLinksStart } from './doc_links'; import { SavedObjectsStart } from './saved_objects'; +import { DeprecationsServiceSetup, DeprecationsServiceStart } from './deprecations'; export type { PackageInfo, EnvironmentMode, IExternalUrlPolicy } from '../server/types'; export type { CoreContext, CoreSystem } from './core_system'; @@ -184,6 +185,13 @@ export type { ErrorToastOptions, } from './notifications'; +export type { + DeprecationsServiceSetup, + DeprecationsServiceStart, + GetAllDeprecationsConfig, + GetDeprecationsConfig, +} from './deprecations'; + export type { MountPoint, UnmountCallback, PublicUiSettingsParams } from './types'; export { URL_MAX_LENGTH } from './core_app'; @@ -213,6 +221,8 @@ export interface CoreSetup; @@ -431,6 +434,8 @@ export interface CoreStart { // (undocumented) chrome: ChromeStart; // (undocumented) + deprecations: DeprecationsServiceStart; + // (undocumented) docLinks: DocLinksStart; // (undocumented) fatalErrors: FatalErrorsStart; @@ -471,6 +476,16 @@ export class CoreSystem { // @internal (undocumented) export const DEFAULT_APP_CATEGORIES: Record; +// @public +export interface DeprecationsServiceSetup { + // Warning: (ae-forgotten-export) The symbol "DeprecationsClient" needs to be exported by the entry point index.d.ts + getAllDeprecations: DeprecationsClient['getAllDeprecations']; + getDeprecations: DeprecationsClient['getDeprecations']; +} + +// @public +export type DeprecationsServiceStart = DeprecationsServiceSetup; + // @public (undocumented) export interface DocLinksStart { // (undocumented) @@ -664,6 +679,14 @@ export interface FatalErrorsSetup { // @public export type FatalErrorsStart = FatalErrorsSetup; +// @public (undocumented) +export type GetAllDeprecationsConfig = GetDeprecationsConfig; + +// @public (undocumented) +export interface GetDeprecationsConfig { + skipCache?: boolean; +} + // @internal (undocumented) export class HttpFetchError extends Error implements IHttpFetchError { constructor(message: string, name: string, request: Request, response?: Response | undefined, body?: any); @@ -1583,6 +1606,6 @@ export interface UserProvidedValues { // Warnings were encountered during analysis: // -// src/core/public/core_system.ts:164:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts +// src/core/public/core_system.ts:169:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts ``` diff --git a/src/core/server/types.ts b/src/core/server/types.ts index 6bd805d55af1..110b1ac09746 100644 --- a/src/core/server/types.ts +++ b/src/core/server/types.ts @@ -37,6 +37,7 @@ export type { SavedObjectsClientContract, SavedObjectsNamespaceType, } from './saved_objects/types'; +export type { PluginDeprecationDetails } from './deprecations/types'; export * from './ui_settings/types'; export * from './legacy/types'; export type { EnvironmentMode, PackageInfo } from '@kbn/config'; diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index a61b8f400d28..4a4461ece0fa 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -46,6 +46,7 @@ import { FormatFactory as FormatFactory_2 } from 'src/plugins/data/common/field_ import { History } from 'history'; import { Href } from 'history'; import { HttpSetup } from 'kibana/public'; +import { HttpSetup as HttpSetup_3 } from 'src/core/public'; import { IconType } from '@elastic/eui'; import { IncomingHttpHeaders } from 'http'; import { InjectedIntl } from '@kbn/i18n/react'; diff --git a/src/plugins/embeddable/public/public.api.md b/src/plugins/embeddable/public/public.api.md index 189f71b85206..5655e94c5017 100644 --- a/src/plugins/embeddable/public/public.api.md +++ b/src/plugins/embeddable/public/public.api.md @@ -24,6 +24,7 @@ import { EuiGlobalToastListToast } from '@elastic/eui'; import { EventEmitter } from 'events'; import { History } from 'history'; import { Href } from 'history'; +import { HttpSetup as HttpSetup_2 } from 'src/core/public'; import { I18nStart as I18nStart_2 } from 'src/core/public'; import { IconType } from '@elastic/eui'; import { IncomingHttpHeaders } from 'http'; From 330948e70dbcc2aa10cac31e619f4075b7614dd3 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Sun, 21 Mar 2021 22:34:12 +0200 Subject: [PATCH 10/23] type check --- src/core/public/deprecations/deprecations_service.mock.ts | 6 +++--- src/core/public/plugins/plugins_service.test.ts | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/core/public/deprecations/deprecations_service.mock.ts b/src/core/public/deprecations/deprecations_service.mock.ts index a11c4ff106ad..7cc4ef3e6aae 100644 --- a/src/core/public/deprecations/deprecations_service.mock.ts +++ b/src/core/public/deprecations/deprecations_service.mock.ts @@ -10,7 +10,7 @@ import type { PublicMethodsOf } from '@kbn/utility-types'; import { DeprecationsService } from './deprecations_service'; import type { DeprecationsServiceSetup, DeprecationsServiceStart } from './deprecations_service'; -const createServiceMock = (): DeprecationsServiceSetup | DeprecationsServiceStart => ({ +const createServiceMock = (): jest.Mocked => ({ getAllDeprecations: jest.fn().mockResolvedValue([]), getDeprecations: jest.fn().mockResolvedValue([]), }); @@ -29,6 +29,6 @@ const createMock = () => { export const deprecationsServiceMock = { create: createMock, - createSetupContract: createServiceMock as () => DeprecationsServiceSetup, - createStartContract: createServiceMock as () => DeprecationsServiceStart, + createSetupContract: createServiceMock as () => jest.Mocked, + createStartContract: createServiceMock as () => jest.Mocked, }; diff --git a/src/core/public/plugins/plugins_service.test.ts b/src/core/public/plugins/plugins_service.test.ts index e70b78f237d7..e9d974695303 100644 --- a/src/core/public/plugins/plugins_service.test.ts +++ b/src/core/public/plugins/plugins_service.test.ts @@ -34,6 +34,7 @@ import { httpServiceMock } from '../http/http_service.mock'; import { CoreSetup, CoreStart, PluginInitializerContext } from '..'; import { docLinksServiceMock } from '../doc_links/doc_links_service.mock'; import { savedObjectsServiceMock } from '../saved_objects/saved_objects_service.mock'; +import { deprecationsServiceMock } from '../deprecations/deprecations_service.mock'; export let mockPluginInitializers: Map; @@ -82,6 +83,7 @@ describe('PluginsService', () => { injectedMetadata: injectedMetadataServiceMock.createStartContract(), notifications: notificationServiceMock.createSetupContract(), uiSettings: uiSettingsServiceMock.createSetupContract(), + deprecations: deprecationsServiceMock.createSetupContract(), }; mockSetupContext = { ...mockSetupDeps, @@ -101,6 +103,7 @@ describe('PluginsService', () => { uiSettings: uiSettingsServiceMock.createStartContract(), savedObjects: savedObjectsServiceMock.createStartContract(), fatalErrors: fatalErrorsServiceMock.createStartContract(), + deprecations: deprecationsServiceMock.createStartContract(), }; mockStartContext = { ...mockStartDeps, From 9cc430aaf575369c4c742e87c8d8d2efdf3e3660 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Mon, 22 Mar 2021 17:06:18 +0200 Subject: [PATCH 11/23] update link --- src/plugins/timelion/server/deprecations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/timelion/server/deprecations.ts b/src/plugins/timelion/server/deprecations.ts index 997895c1e962..ea87442dcb1f 100644 --- a/src/plugins/timelion/server/deprecations.ts +++ b/src/plugins/timelion/server/deprecations.ts @@ -51,7 +51,7 @@ export const getDeprecations: RegisterDeprecationsConfig['getDeprecations'] = as deprecations.push({ message: `You have ${count} Timelion worksheets. The Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard.`, documentationUrl: - 'https://www.elastic.co/guide/en/kibana/master/dashboard.html#timelion-deprecation', + 'https://www.elastic.co/guide/en/kibana/current/create-panels-with-timelion.html', level: 'warning', correctiveActions: { manualSteps: [ From 0ea9e8196c32bc0d6ad25d3a15a9cb5ab9b14c83 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 23 Mar 2021 11:52:51 +0200 Subject: [PATCH 12/23] update logging deprecations documentationUrls --- .../config/deprecation/core_deprecations.ts | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts index 4d13e619d3ab..4f8fb24a6d81 100644 --- a/src/core/server/config/deprecation/core_deprecations.ts +++ b/src/core/server/config/deprecation/core_deprecations.ts @@ -119,7 +119,7 @@ const opsLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, depre if (has(settings, 'logging.events.ops')) { deprecationHook({ documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx', + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents', message: '"logging.events.ops" has been deprecated and will be removed ' + 'in 8.0. To access ops data moving forward, please enable debug logs for the ' + @@ -134,7 +134,7 @@ const requestLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, d if (has(settings, 'logging.events.request') || has(settings, 'logging.events.response')) { deprecationHook({ documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx', + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents', message: '"logging.events.request" and "logging.events.response" have been deprecated and will be removed ' + 'in 8.0. To access request and/or response data moving forward, please enable debug logs for the ' + @@ -149,7 +149,7 @@ const timezoneLoggingDeprecation: ConfigDeprecation = (settings, fromPath, depre if (has(settings, 'logging.timezone')) { deprecationHook({ documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx', + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingtimezone', message: '"logging.timezone" has been deprecated and will be removed ' + 'in 8.0. To set the timezone moving forward, please add a timezone date modifier to the log pattern ' + @@ -164,7 +164,7 @@ const destLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecati if (has(settings, 'logging.dest')) { deprecationHook({ documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx', + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingdest', message: '"logging.dest" has been deprecated and will be removed ' + 'in 8.0. To set the destination moving forward, you can use the "console" appender ' + @@ -178,6 +178,8 @@ const destLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecati const quietLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { if (has(settings, 'logging.quiet')) { deprecationHook({ + documentationUrl: + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingquiet', message: '"logging.quiet" has been deprecated and will be removed ' + 'in 8.0. Moving forward, you can use "logging.root.level:error" in your logging configuration. ', @@ -189,6 +191,8 @@ const quietLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecat const silentLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { if (has(settings, 'logging.silent')) { deprecationHook({ + documentationUrl: + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingsilent', message: '"logging.silent" has been deprecated and will be removed ' + 'in 8.0. Moving forward, you can use "logging.root.level:off" in your logging configuration. ', @@ -200,6 +204,8 @@ const silentLoggingDeprecation: ConfigDeprecation = (settings, fromPath, depreca const verboseLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { if (has(settings, 'logging.verbose')) { deprecationHook({ + documentationUrl: + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingverbose', message: '"logging.verbose" has been deprecated and will be removed ' + 'in 8.0. Moving forward, you can use "logging.root.level:all" in your logging configuration. ', @@ -247,6 +253,8 @@ const logRotateDeprecation: ConfigDeprecation = (settings, fromPath, deprecation const logEventsLogDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { if (has(settings, 'logging.events.log')) { deprecationHook({ + documentationUrl: + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents', message: '"logging.events.log" has been deprecated and will be removed ' + 'in 8.0. Moving forward, log levels can be customized on a per-logger basis using the new logging configuration. ', @@ -258,6 +266,8 @@ const logEventsLogDeprecation: ConfigDeprecation = (settings, fromPath, deprecat const logEventsErrorDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { if (has(settings, 'logging.events.error')) { deprecationHook({ + documentationUrl: + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents', message: '"logging.events.error" has been deprecated and will be removed ' + 'in 8.0. Moving forward, you can use "logging.root.level: error" in your logging configuration. ', @@ -269,6 +279,8 @@ const logEventsErrorDeprecation: ConfigDeprecation = (settings, fromPath, deprec const logFilterDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { if (has(settings, 'logging.filter')) { deprecationHook({ + documentationUrl: + 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingfilter', message: '"logging.filter" has been deprecated and will be removed in 8.0.', }); } From bacb636522e34ff2c1ccc3cabdb6776f521124a9 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 25 Mar 2021 15:03:36 +0200 Subject: [PATCH 13/23] code review changes --- ...ugin-core-public.coresetup.deprecations.md | 13 ---- .../kibana-plugin-core-public.coresetup.md | 1 - ...ecationsservicesetup.getalldeprecations.md | 13 ---- ...eprecationsservicesetup.getdeprecations.md | 13 ---- ...in-core-public.deprecationsservicesetup.md | 21 ------ ...ecationsservicestart.getalldeprecations.md | 13 ++++ ...eprecationsservicestart.getdeprecations.md | 13 ++++ ...in-core-public.deprecationsservicestart.md | 14 +++- ...in-core-public.getalldeprecationsconfig.md | 12 --- ...lugin-core-public.getdeprecationsconfig.md | 19 ----- ...-public.getdeprecationsconfig.skipcache.md | 13 ---- .../core/public/kibana-plugin-core-public.md | 5 +- ...n-core-server.deprecationsdetails.level.md | 4 +- ...-plugin-core-server.deprecationsdetails.md | 2 +- ...in-core-server.deprecationsservicesetup.md | 41 ++++++---- ...-server.getdeprecationscontext.esclient.md | 11 +++ ...ugin-core-server.getdeprecationscontext.md | 19 +++++ ...tdeprecationscontext.savedobjectsclient.md | 11 +++ .../core/server/kibana-plugin-core-server.md | 1 + ...plugins-data-public.searchsource.fetch_.md | 4 +- .../src/config_service.test.mocks.ts | 6 +- .../kbn-config/src/config_service.test.ts | 22 +++--- packages/kbn-config/src/config_service.ts | 4 +- .../deprecation/apply_deprecations.test.ts | 28 +++---- .../src/deprecation/apply_deprecations.ts | 10 +-- .../deprecation/deprecation_factory.test.ts | 56 +++++++------- .../src/deprecation/deprecation_factory.ts | 28 +++---- packages/kbn-config/src/deprecation/index.ts | 2 +- packages/kbn-config/src/deprecation/types.ts | 21 +++--- packages/kbn-config/src/index.ts | 10 +-- src/core/public/core_system.ts | 5 +- .../deprecations/deprecations_client.test.ts | 43 +---------- .../deprecations/deprecations_client.ts | 41 +++------- .../deprecations/deprecations_service.mock.ts | 10 +-- .../deprecations/deprecations_service.ts | 61 +++++---------- src/core/public/deprecations/index.ts | 3 +- src/core/public/index.ts | 11 +-- src/core/public/plugins/plugin_context.ts | 1 - .../public/plugins/plugins_service.test.ts | 1 - src/core/public/public.api.md | 24 ++---- .../config/deprecation/core_deprecations.ts | 74 +++++++++---------- src/core/server/config/index.ts | 2 +- .../deprecations/deprecations_factory.test.ts | 42 +++++------ .../deprecations/deprecations_factory.ts | 52 ++++++------- .../deprecations/deprecations_service.ts | 51 +++++++------ src/core/server/deprecations/index.ts | 6 +- src/core/server/deprecations/types.ts | 31 +++++++- .../elasticsearch/elasticsearch_config.ts | 12 +-- src/core/server/index.ts | 7 +- src/core/server/kibana_config.ts | 4 +- src/core/server/server.api.md | 20 +++-- src/core/server/types.ts | 2 +- src/plugins/data/public/public.api.md | 1 - src/plugins/embeddable/public/public.api.md | 1 - src/plugins/kibana_legacy/server/index.ts | 6 +- src/plugins/timelion/server/deprecations.ts | 8 +- .../monitoring/server/deprecations.test.js | 74 +++++++++---------- .../plugins/monitoring/server/deprecations.ts | 16 ++-- .../plugins/reporting/server/config/index.ts | 4 +- .../security/server/config_deprecations.ts | 16 ++-- x-pack/plugins/spaces/server/config.ts | 4 +- x-pack/plugins/task_manager/server/index.ts | 6 +- 62 files changed, 491 insertions(+), 578 deletions(-) delete mode 100644 docs/development/core/public/kibana-plugin-core-public.coresetup.deprecations.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getalldeprecations.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getdeprecations.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.getalldeprecations.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.getdeprecations.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.getalldeprecationsconfig.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.skipcache.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.getdeprecationscontext.esclient.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.getdeprecationscontext.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.getdeprecationscontext.savedobjectsclient.md diff --git a/docs/development/core/public/kibana-plugin-core-public.coresetup.deprecations.md b/docs/development/core/public/kibana-plugin-core-public.coresetup.deprecations.md deleted file mode 100644 index ebb481b68ed2..000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.coresetup.deprecations.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [CoreSetup](./kibana-plugin-core-public.coresetup.md) > [deprecations](./kibana-plugin-core-public.coresetup.deprecations.md) - -## CoreSetup.deprecations property - -[DeprecationsServiceSetup](./kibana-plugin-core-public.deprecationsservicesetup.md) - -Signature: - -```typescript -deprecations: DeprecationsServiceSetup; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.coresetup.md b/docs/development/core/public/kibana-plugin-core-public.coresetup.md index 7a3255859a49..5d2288120da0 100644 --- a/docs/development/core/public/kibana-plugin-core-public.coresetup.md +++ b/docs/development/core/public/kibana-plugin-core-public.coresetup.md @@ -17,7 +17,6 @@ export interface CoreSetupApplicationSetup | [ApplicationSetup](./kibana-plugin-core-public.applicationsetup.md) | -| [deprecations](./kibana-plugin-core-public.coresetup.deprecations.md) | DeprecationsServiceSetup | [DeprecationsServiceSetup](./kibana-plugin-core-public.deprecationsservicesetup.md) | | [fatalErrors](./kibana-plugin-core-public.coresetup.fatalerrors.md) | FatalErrorsSetup | [FatalErrorsSetup](./kibana-plugin-core-public.fatalerrorssetup.md) | | [getStartServices](./kibana-plugin-core-public.coresetup.getstartservices.md) | StartServicesAccessor<TPluginsStart, TStart> | [StartServicesAccessor](./kibana-plugin-core-public.startservicesaccessor.md) | | [http](./kibana-plugin-core-public.coresetup.http.md) | HttpSetup | [HttpSetup](./kibana-plugin-core-public.httpsetup.md) | diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getalldeprecations.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getalldeprecations.md deleted file mode 100644 index ccdb69eef401..000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getalldeprecations.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceSetup](./kibana-plugin-core-public.deprecationsservicesetup.md) > [getAllDeprecations](./kibana-plugin-core-public.deprecationsservicesetup.getalldeprecations.md) - -## DeprecationsServiceSetup.getAllDeprecations property - -Grabs deprecations for all plugins. - -Signature: - -```typescript -getAllDeprecations: DeprecationsClient['getAllDeprecations']; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getdeprecations.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getdeprecations.md deleted file mode 100644 index 19178487801c..000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.getdeprecations.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceSetup](./kibana-plugin-core-public.deprecationsservicesetup.md) > [getDeprecations](./kibana-plugin-core-public.deprecationsservicesetup.getdeprecations.md) - -## DeprecationsServiceSetup.getDeprecations property - -Grabs deprecations for a specific plugin. - -Signature: - -```typescript -getDeprecations: DeprecationsClient['getDeprecations']; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.md deleted file mode 100644 index 8d1b79efc63c..000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicesetup.md +++ /dev/null @@ -1,21 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceSetup](./kibana-plugin-core-public.deprecationsservicesetup.md) - -## DeprecationsServiceSetup interface - -DeprecationsService provides methods to fetch plugin deprecation details from the Kibana server. - -Signature: - -```typescript -export interface DeprecationsServiceSetup -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [getAllDeprecations](./kibana-plugin-core-public.deprecationsservicesetup.getalldeprecations.md) | DeprecationsClient['getAllDeprecations'] | Grabs deprecations for all plugins. | -| [getDeprecations](./kibana-plugin-core-public.deprecationsservicesetup.getdeprecations.md) | DeprecationsClient['getDeprecations'] | Grabs deprecations for a specific plugin. | - diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.getalldeprecations.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.getalldeprecations.md new file mode 100644 index 000000000000..8175da8a1893 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.getalldeprecations.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) > [getAllDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getalldeprecations.md) + +## DeprecationsServiceStart.getAllDeprecations property + +Grabs deprecations details for all domains. + +Signature: + +```typescript +getAllDeprecations: () => Promise; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.getdeprecations.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.getdeprecations.md new file mode 100644 index 000000000000..6e3472b7c3fe --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.getdeprecations.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) > [getDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getdeprecations.md) + +## DeprecationsServiceStart.getDeprecations property + +Grabs deprecations for a specific domain. + +Signature: + +```typescript +getDeprecations: (domainId: string) => Promise; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md index 8d43450c30db..60f0ccce42fd 100644 --- a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md @@ -2,12 +2,20 @@ [Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) -## DeprecationsServiceStart type +## DeprecationsServiceStart interface -DeprecationsService provides methods to fetch plugin deprecation details from the Kibana server. +DeprecationsService provides methods to fetch domain deprecation details from the Kibana server. Signature: ```typescript -export declare type DeprecationsServiceStart = DeprecationsServiceSetup; +export interface DeprecationsServiceStart ``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [getAllDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getalldeprecations.md) | () => Promise<DomainDeprecationDetails[]> | Grabs deprecations details for all domains. | +| [getDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getdeprecations.md) | (domainId: string) => Promise<DomainDeprecationDetails[]> | Grabs deprecations for a specific domain. | + diff --git a/docs/development/core/public/kibana-plugin-core-public.getalldeprecationsconfig.md b/docs/development/core/public/kibana-plugin-core-public.getalldeprecationsconfig.md deleted file mode 100644 index 41757a348392..000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.getalldeprecationsconfig.md +++ /dev/null @@ -1,12 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [GetAllDeprecationsConfig](./kibana-plugin-core-public.getalldeprecationsconfig.md) - -## GetAllDeprecationsConfig type - - -Signature: - -```typescript -export declare type GetAllDeprecationsConfig = GetDeprecationsConfig; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.md b/docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.md deleted file mode 100644 index f6d38b29c8ca..000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.md +++ /dev/null @@ -1,19 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [GetDeprecationsConfig](./kibana-plugin-core-public.getdeprecationsconfig.md) - -## GetDeprecationsConfig interface - - -Signature: - -```typescript -export interface GetDeprecationsConfig -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [skipCache](./kibana-plugin-core-public.getdeprecationsconfig.skipcache.md) | boolean | set true to fetch a fresh copy of the deprecations from the kibana server. | - diff --git a/docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.skipcache.md b/docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.skipcache.md deleted file mode 100644 index dc0a038625e6..000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.getdeprecationsconfig.skipcache.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [GetDeprecationsConfig](./kibana-plugin-core-public.getdeprecationsconfig.md) > [skipCache](./kibana-plugin-core-public.getdeprecationsconfig.skipcache.md) - -## GetDeprecationsConfig.skipCache property - -set true to fetch a fresh copy of the deprecations from the kibana server. - -Signature: - -```typescript -skipCache?: boolean; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index ebfc5ded99e7..695551802c1e 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -59,12 +59,11 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeUserBanner](./kibana-plugin-core-public.chromeuserbanner.md) | | | [CoreSetup](./kibana-plugin-core-public.coresetup.md) | Core services exposed to the Plugin setup lifecycle | | [CoreStart](./kibana-plugin-core-public.corestart.md) | Core services exposed to the Plugin start lifecycle | -| [DeprecationsServiceSetup](./kibana-plugin-core-public.deprecationsservicesetup.md) | DeprecationsService provides methods to fetch plugin deprecation details from the Kibana server. | +| [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) | DeprecationsService provides methods to fetch domain deprecation details from the Kibana server. | | [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) | | | [ErrorToastOptions](./kibana-plugin-core-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) error APIs. | | [FatalErrorInfo](./kibana-plugin-core-public.fatalerrorinfo.md) | Represents the message and stack of a fatal Error | | [FatalErrorsSetup](./kibana-plugin-core-public.fatalerrorssetup.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | -| [GetDeprecationsConfig](./kibana-plugin-core-public.getdeprecationsconfig.md) | | | [HttpFetchOptions](./kibana-plugin-core-public.httpfetchoptions.md) | All options that may be used with a [HttpHandler](./kibana-plugin-core-public.httphandler.md). | | [HttpFetchOptionsWithPath](./kibana-plugin-core-public.httpfetchoptionswithpath.md) | Similar to [HttpFetchOptions](./kibana-plugin-core-public.httpfetchoptions.md) but with the URL path included. | | [HttpFetchQuery](./kibana-plugin-core-public.httpfetchquery.md) | | @@ -155,9 +154,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeHelpExtensionLinkBase](./kibana-plugin-core-public.chromehelpextensionlinkbase.md) | | | [ChromeHelpExtensionMenuLink](./kibana-plugin-core-public.chromehelpextensionmenulink.md) | | | [ChromeNavLinkUpdateableFields](./kibana-plugin-core-public.chromenavlinkupdateablefields.md) | | -| [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) | DeprecationsService provides methods to fetch plugin deprecation details from the Kibana server. | | [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | -| [GetAllDeprecationsConfig](./kibana-plugin-core-public.getalldeprecationsconfig.md) | | | [HttpStart](./kibana-plugin-core-public.httpstart.md) | See [HttpSetup](./kibana-plugin-core-public.httpsetup.md) | | [IToasts](./kibana-plugin-core-public.itoasts.md) | Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-core-public.toastsapi.md). | | [MountPoint](./kibana-plugin-core-public.mountpoint.md) | A function that should mount DOM content inside the provided container element and return a handler to unmount it. | diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.level.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.level.md index 5f0dbe8d8c4b..64ad22e2c87f 100644 --- a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.level.md +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.level.md @@ -4,8 +4,10 @@ ## DeprecationsDetails.level property +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. + Signature: ```typescript -level: 'warning' | 'critical'; +level: 'warning' | 'critical' | 'fetch_error'; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.md index affc52f1830d..bb77e4247711 100644 --- a/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.md +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsdetails.md @@ -16,6 +16,6 @@ export interface DeprecationsDetails | --- | --- | --- | | [correctiveActions](./kibana-plugin-core-server.deprecationsdetails.correctiveactions.md) | {
api?: {
path: string;
method: 'POST' | 'PUT';
body?: {
[key: string]: any;
};
};
manualSteps?: string[];
} | | | [documentationUrl](./kibana-plugin-core-server.deprecationsdetails.documentationurl.md) | string | | -| [level](./kibana-plugin-core-server.deprecationsdetails.level.md) | 'warning' | 'critical' | | +| [level](./kibana-plugin-core-server.deprecationsdetails.level.md) | 'warning' | 'critical' | 'fetch_error' | 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) | string | | diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md index 7d214927621a..ff8e49f9bccb 100644 --- a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md @@ -18,24 +18,33 @@ export interface DeprecationsServiceSetup ```ts import { DeprecationsDetails, GetDeprecationsContext, CoreSetup } from 'src/core/server'; -const getDeprecations = async ({ esClient, savedObjectsClient }: GetDeprecationsContext): DeprecationsDetails[] => { - return [ - { - message: string; - level: 'warning' | 'critical'; - documentationUrl?: string; - correctiveActions: { - api?: { - path: string; - method: 'POST' | 'PUT'; - body?: { [key: string]: any }, - }, - manualSteps?: string[]; - } - } - ] +async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecationsContext): Promise { + const deprecations: DeprecationsDetails[] = []; + const count = await getTimelionSheetsCount(savedObjectsClient); + + if (count > 0) { + deprecations.push({ + message: `You have ${count} Timelion worksheets. The Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard.`, + documentationUrl: + 'https://www.elastic.co/guide/en/kibana/current/create-panels-with-timelion.html', + level: 'warning', + correctiveActions: { + manualSteps: [ + 'Navigate to the Kibana Dashboard and click "Create dashboard".', + 'Select Timelion from the "New Visualization" window.', + 'Open a new tab, open the Timelion app, select the chart you want to copy, then copy the chart expression.', + 'Go to Timelion, paste the chart expression in the Timelion expression field, then click Update.', + 'In the toolbar, click Save.', + 'On the Save visualization window, enter the visualization Title, then click Save and return.', + ], + }, + }); + } + + return deprecations; } + export class Plugin() { setup: (core: CoreSetup) => { core.deprecations.registerDeprecations({ getDeprecations }); diff --git a/docs/development/core/server/kibana-plugin-core-server.getdeprecationscontext.esclient.md b/docs/development/core/server/kibana-plugin-core-server.getdeprecationscontext.esclient.md new file mode 100644 index 000000000000..70c1864bf905 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.getdeprecationscontext.esclient.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [GetDeprecationsContext](./kibana-plugin-core-server.getdeprecationscontext.md) > [esClient](./kibana-plugin-core-server.getdeprecationscontext.esclient.md) + +## GetDeprecationsContext.esClient property + +Signature: + +```typescript +esClient: IScopedClusterClient; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.getdeprecationscontext.md b/docs/development/core/server/kibana-plugin-core-server.getdeprecationscontext.md new file mode 100644 index 000000000000..1018444f0849 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.getdeprecationscontext.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [GetDeprecationsContext](./kibana-plugin-core-server.getdeprecationscontext.md) + +## GetDeprecationsContext interface + +Signature: + +```typescript +export interface GetDeprecationsContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [esClient](./kibana-plugin-core-server.getdeprecationscontext.esclient.md) | IScopedClusterClient | | +| [savedObjectsClient](./kibana-plugin-core-server.getdeprecationscontext.savedobjectsclient.md) | SavedObjectsClientContract | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.getdeprecationscontext.savedobjectsclient.md b/docs/development/core/server/kibana-plugin-core-server.getdeprecationscontext.savedobjectsclient.md new file mode 100644 index 000000000000..66da52d3b582 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.getdeprecationscontext.savedobjectsclient.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [GetDeprecationsContext](./kibana-plugin-core-server.getdeprecationscontext.md) > [savedObjectsClient](./kibana-plugin-core-server.getdeprecationscontext.savedobjectsclient.md) + +## GetDeprecationsContext.savedObjectsClient property + +Signature: + +```typescript +savedObjectsClient: SavedObjectsClientContract; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index ef981efbbbaf..f28cd1c5c844 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -78,6 +78,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ElasticsearchStatusMeta](./kibana-plugin-core-server.elasticsearchstatusmeta.md) | | | [ErrorHttpResponseOptions](./kibana-plugin-core-server.errorhttpresponseoptions.md) | HTTP response parameters | | [FakeRequest](./kibana-plugin-core-server.fakerequest.md) | Fake request object created manually by Kibana plugins. | +| [GetDeprecationsContext](./kibana-plugin-core-server.getdeprecationscontext.md) | | | [GetResponse](./kibana-plugin-core-server.getresponse.md) | | | [HttpAuth](./kibana-plugin-core-server.httpauth.md) | | | [HttpResources](./kibana-plugin-core-server.httpresources.md) | HttpResources service is responsible for serving static & dynamic assets for Kibana application via HTTP. Provides API allowing plug-ins to respond with: - a pre-configured HTML page bootstrapping Kibana client app - custom HTML page - custom JS script file. | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.fetch_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.fetch_.md index bcf220a9a27e..d5641107a88a 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.fetch_.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.fetch_.md @@ -9,7 +9,7 @@ Fetch this source from Elasticsearch, returning an observable over the response( Signature: ```typescript -fetch$(options?: ISearchOptions): import("rxjs").Observable>; +fetch$(options?: ISearchOptions): import("rxjs").Observable>; ``` ## Parameters @@ -20,5 +20,5 @@ fetch$(options?: ISearchOptions): import("rxjs").ObservableReturns: -`import("rxjs").Observable>` +`import("rxjs").Observable>` diff --git a/packages/kbn-config/src/config_service.test.mocks.ts b/packages/kbn-config/src/config_service.test.mocks.ts index c5a31b6dd098..d8da2852b925 100644 --- a/packages/kbn-config/src/config_service.test.mocks.ts +++ b/packages/kbn-config/src/config_service.test.mocks.ts @@ -7,14 +7,14 @@ */ export const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); -import type { ConfigDeprecationWithContext, ConfigDeprecationHook } from './deprecation/types'; +import type { applyDeprecations } from './deprecation/apply_deprecations'; jest.mock('../../../package.json', () => mockPackage); export const mockApplyDeprecations = jest.fn< Record, - [Record, ConfigDeprecationWithContext[], (pluginId: string) => ConfigDeprecationHook] ->((config, deprecations, deprecationFactory) => config); + Parameters +>((config, deprecations, createAddDeprecation) => config); jest.mock('./deprecation/apply_deprecations', () => ({ applyDeprecations: mockApplyDeprecations, diff --git a/packages/kbn-config/src/config_service.test.ts b/packages/kbn-config/src/config_service.test.ts index e65ba79abb3e..60fcb3eb1e3c 100644 --- a/packages/kbn-config/src/config_service.test.ts +++ b/packages/kbn-config/src/config_service.test.ts @@ -416,10 +416,10 @@ test('throws during validation is any schema is invalid', async () => { test('logs deprecation warning during validation', async () => { const rawConfig = getRawConfigProvider({}); const configService = new ConfigService(rawConfig, defaultEnv, logger); - mockApplyDeprecations.mockImplementationOnce((config, deprecations, deprecationFactory) => { - const deprecationHook = deprecationFactory(''); - deprecationHook({ message: 'some deprecation message' }); - deprecationHook({ message: 'another deprecation message' }); + mockApplyDeprecations.mockImplementationOnce((config, deprecations, createAddDeprecation) => { + const addDeprecation = createAddDeprecation!(''); + addDeprecation({ message: 'some deprecation message' }); + addDeprecation({ message: 'another deprecation message' }); return config; }); @@ -440,10 +440,10 @@ test('logs deprecation warning during validation', async () => { test('does not log warnings for silent deprecations during validation', async () => { const rawConfig = getRawConfigProvider({}); const configService = new ConfigService(rawConfig, defaultEnv, logger); - mockApplyDeprecations.mockImplementationOnce((config, deprecations, deprecationFactory) => { - const deprecationHook = deprecationFactory(''); - deprecationHook({ message: 'some deprecation message', silent: true }); - deprecationHook({ message: 'another deprecation message' }); + mockApplyDeprecations.mockImplementationOnce((config, deprecations, createAddDeprecation) => { + const addDeprecation = createAddDeprecation!(''); + addDeprecation({ message: 'some deprecation message', silent: true }); + addDeprecation({ message: 'another deprecation message' }); return config; }); @@ -506,10 +506,10 @@ describe('getHandledDeprecatedConfigs', () => { configService.addDeprecationProvider('base', ({ unused }) => [unused('unused')]); - mockApplyDeprecations.mockImplementationOnce((config, deprecations, deprecationFactory) => { + mockApplyDeprecations.mockImplementationOnce((config, deprecations, createAddDeprecation) => { deprecations.forEach((deprecation) => { - const deprecationHook = deprecationFactory(deprecation.path); - deprecationHook({ message: `some deprecation message`, documentationUrl: 'some-url' }); + const addDeprecation = createAddDeprecation!(deprecation.path); + addDeprecation({ message: `some deprecation message`, documentationUrl: 'some-url' }); }); return config; }); diff --git a/packages/kbn-config/src/config_service.ts b/packages/kbn-config/src/config_service.ts index 3a5c95f27a19..a1f23574594d 100644 --- a/packages/kbn-config/src/config_service.ts +++ b/packages/kbn-config/src/config_service.ts @@ -195,7 +195,7 @@ export class ConfigService { const rawConfig = await this.rawConfigProvider.getConfig$().pipe(take(1)).toPromise(); const deprecations = await this.deprecations.pipe(take(1)).toPromise(); const deprecationMessages: string[] = []; - const deprecationHookFactory = (pluginId: string) => (context: DeprecatedConfigDetails) => { + const createAddDeprecation = (pluginId: string) => (context: DeprecatedConfigDetails) => { if (!context.silent) { deprecationMessages.push(context.message); } @@ -204,7 +204,7 @@ export class ConfigService { this.handledDeprecatedConfigs.set(pluginId, handledDeprecatedConfig); }; - applyDeprecations(rawConfig, deprecations, deprecationHookFactory); + applyDeprecations(rawConfig, deprecations, createAddDeprecation); deprecationMessages.forEach((msg) => { this.deprecationLog.warn(msg); }); diff --git a/packages/kbn-config/src/deprecation/apply_deprecations.test.ts b/packages/kbn-config/src/deprecation/apply_deprecations.test.ts index 99cab12ef5cf..f2c0a4391634 100644 --- a/packages/kbn-config/src/deprecation/apply_deprecations.test.ts +++ b/packages/kbn-config/src/deprecation/apply_deprecations.test.ts @@ -32,9 +32,9 @@ describe('applyDeprecations', () => { expect(handlerC).toHaveBeenCalledTimes(1); }); - it('passes path to deprecationHook factory', () => { - const deprecationHook = jest.fn(); - const deprecationHookFactory = jest.fn().mockReturnValue(deprecationHook); + it('passes path to addDeprecation factory', () => { + const addDeprecation = jest.fn(); + const createAddDeprecation = jest.fn().mockReturnValue(addDeprecation); const initialConfig = { foo: 'bar', deprecated: 'deprecated' }; const alteredConfig = { foo: 'bar' }; @@ -44,19 +44,19 @@ describe('applyDeprecations', () => { applyDeprecations( initialConfig, [wrapHandler(handlerA, 'pathA'), wrapHandler(handlerB, 'pathB')], - deprecationHookFactory + createAddDeprecation ); - expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', deprecationHook); - expect(handlerB).toHaveBeenCalledWith(alteredConfig, 'pathB', deprecationHook); - expect(deprecationHookFactory).toBeCalledTimes(2); - expect(deprecationHookFactory).toHaveBeenNthCalledWith(1, 'pathA'); - expect(deprecationHookFactory).toHaveBeenNthCalledWith(2, 'pathB'); + expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', addDeprecation); + expect(handlerB).toHaveBeenCalledWith(alteredConfig, 'pathB', addDeprecation); + expect(createAddDeprecation).toBeCalledTimes(2); + expect(createAddDeprecation).toHaveBeenNthCalledWith(1, 'pathA'); + expect(createAddDeprecation).toHaveBeenNthCalledWith(2, 'pathB'); }); it('calls handlers with correct arguments', () => { - const deprecationHook = jest.fn(); - const deprecationHookFactory = jest.fn().mockReturnValue(deprecationHook); + const addDeprecation = jest.fn(); + const createAddDeprecation = jest.fn().mockReturnValue(addDeprecation); const initialConfig = { foo: 'bar', deprecated: 'deprecated' }; const alteredConfig = { foo: 'bar' }; @@ -66,11 +66,11 @@ describe('applyDeprecations', () => { applyDeprecations( initialConfig, [wrapHandler(handlerA, 'pathA'), wrapHandler(handlerB, 'pathB')], - deprecationHookFactory + createAddDeprecation ); - expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', deprecationHook); - expect(handlerB).toHaveBeenCalledWith(alteredConfig, 'pathB', deprecationHook); + expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', addDeprecation); + expect(handlerB).toHaveBeenCalledWith(alteredConfig, 'pathB', addDeprecation); }); it('returns the migrated config', () => { diff --git a/packages/kbn-config/src/deprecation/apply_deprecations.ts b/packages/kbn-config/src/deprecation/apply_deprecations.ts index 0eee001cddb4..6aced541dc30 100644 --- a/packages/kbn-config/src/deprecation/apply_deprecations.ts +++ b/packages/kbn-config/src/deprecation/apply_deprecations.ts @@ -7,11 +7,11 @@ */ import { cloneDeep } from 'lodash'; -import { ConfigDeprecationWithContext, ConfigDeprecationHook } from './types'; +import { ConfigDeprecationWithContext, AddConfigDeprecation } from './types'; -const noopDeprecationHookFactory: () => ConfigDeprecationHook = () => () => undefined; +const noopAddDeprecationFactory: () => AddConfigDeprecation = () => () => undefined; /** - * Applies deprecations on given configuration and passes handled deprecation deprecationHook + * Applies deprecations on given configuration and passes addDeprecation hook. * This hook is used for logging any deprecation warning using provided logger. * This hook is used for exposing deprecated configs that must be handled by the user before upgrading to next major. * @@ -20,11 +20,11 @@ const noopDeprecationHookFactory: () => ConfigDeprecationHook = () => () => unde export const applyDeprecations = ( config: Record, deprecations: ConfigDeprecationWithContext[], - deprecationHookFactory: (pluginId: string) => ConfigDeprecationHook = noopDeprecationHookFactory + createAddDeprecation: (pluginId: string) => AddConfigDeprecation = noopAddDeprecationFactory ) => { let processed = cloneDeep(config); deprecations.forEach(({ deprecation, path }) => { - processed = deprecation(processed, path, deprecationHookFactory(path)); + processed = deprecation(processed, path, createAddDeprecation(path)); }); return processed; }; diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts index 64ac51c4e230..20f4a011dec9 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts @@ -12,10 +12,10 @@ import { configDeprecationFactory } from './deprecation_factory'; describe('DeprecationFactory', () => { const { rename, unused, renameFromRoot, unusedFromRoot } = configDeprecationFactory; - const deprecationHook = jest.fn(); + const addDeprecation = jest.fn(); beforeEach(() => { - deprecationHook.mockClear(); + addDeprecation.mockClear(); }); describe('rename', () => { @@ -29,7 +29,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }; - const processed = rename('deprecated', 'renamed')(rawConfig, 'myplugin', deprecationHook); + const processed = rename('deprecated', 'renamed')(rawConfig, 'myplugin', addDeprecation); expect(processed).toEqual({ myplugin: { renamed: 'toberenamed', @@ -39,7 +39,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationHook).toBeCalledWith({ + expect(addDeprecation).toBeCalledWith({ correctiveActions: { manualSteps: [ 'Replace "myplugin.deprecated" in the kibana.yml file with "myplugin.renamed"', @@ -58,7 +58,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }; - const processed = rename('deprecated', 'new')(rawConfig, 'myplugin', deprecationHook); + const processed = rename('deprecated', 'new')(rawConfig, 'myplugin', addDeprecation); expect(processed).toEqual({ myplugin: { new: 'new', @@ -68,7 +68,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationHook).toHaveBeenCalledTimes(0); + expect(addDeprecation).toHaveBeenCalledTimes(0); }); it('handles nested keys', () => { const rawConfig = { @@ -85,7 +85,7 @@ describe('DeprecationFactory', () => { const processed = rename('oldsection.deprecated', 'newsection.renamed')( rawConfig, 'myplugin', - deprecationHook + addDeprecation ); expect(processed).toEqual({ myplugin: { @@ -99,7 +99,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationHook).toBeCalledWith({ + expect(addDeprecation).toBeCalledWith({ correctiveActions: { manualSteps: [ 'Replace "myplugin.oldsection.deprecated" in the kibana.yml file with "myplugin.newsection.renamed"', @@ -116,13 +116,13 @@ describe('DeprecationFactory', () => { renamed: 'renamed', }, }; - const processed = rename('deprecated', 'renamed')(rawConfig, 'myplugin', deprecationHook); + const processed = rename('deprecated', 'renamed')(rawConfig, 'myplugin', addDeprecation); expect(processed).toEqual({ myplugin: { renamed: 'renamed', }, }); - expect(deprecationHook).toBeCalledWith({ + expect(addDeprecation).toBeCalledWith({ correctiveActions: { manualSteps: [ 'Make sure "myplugin.renamed" contains the correct value in the kibana.yml file."', @@ -149,7 +149,7 @@ describe('DeprecationFactory', () => { const processed = renameFromRoot('myplugin.deprecated', 'myplugin.renamed')( rawConfig, 'does-not-matter', - deprecationHook + addDeprecation ); expect(processed).toEqual({ myplugin: { @@ -160,7 +160,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationHook).toBeCalledWith({ + expect(addDeprecation).toBeCalledWith({ correctiveActions: { manualSteps: [ 'Replace "myplugin.deprecated" in the kibana.yml file with "myplugin.renamed"', @@ -183,7 +183,7 @@ describe('DeprecationFactory', () => { const processed = renameFromRoot('oldplugin.deprecated', 'newplugin.renamed')( rawConfig, 'does-not-matter', - deprecationHook + addDeprecation ); expect(processed).toEqual({ oldplugin: { @@ -194,7 +194,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationHook).toBeCalledWith({ + expect(addDeprecation).toBeCalledWith({ correctiveActions: { manualSteps: [ 'Replace "oldplugin.deprecated" in the kibana.yml file with "newplugin.renamed"', @@ -218,7 +218,7 @@ describe('DeprecationFactory', () => { const processed = renameFromRoot('myplugin.deprecated', 'myplugin.new')( rawConfig, 'does-not-matter', - deprecationHook + addDeprecation ); expect(processed).toEqual({ myplugin: { @@ -229,7 +229,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationHook).toBeCalledTimes(0); + expect(addDeprecation).toBeCalledTimes(0); }); it('remove the old property but does not overrides the new one if they both exist, and logs a specific message', () => { @@ -242,7 +242,7 @@ describe('DeprecationFactory', () => { const processed = renameFromRoot('myplugin.deprecated', 'myplugin.renamed')( rawConfig, 'does-not-matter', - deprecationHook + addDeprecation ); expect(processed).toEqual({ myplugin: { @@ -250,7 +250,7 @@ describe('DeprecationFactory', () => { }, }); - expect(deprecationHook).toBeCalledWith({ + expect(addDeprecation).toBeCalledWith({ correctiveActions: { manualSteps: [ 'Make sure "myplugin.renamed" contains the correct value in the kibana.yml file."', @@ -274,7 +274,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }; - const processed = unused('deprecated')(rawConfig, 'myplugin', deprecationHook); + const processed = unused('deprecated')(rawConfig, 'myplugin', addDeprecation); expect(processed).toEqual({ myplugin: { valid: 'valid', @@ -283,7 +283,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationHook).toBeCalledWith({ + expect(addDeprecation).toBeCalledWith({ correctiveActions: { manualSteps: ['Remove "myplugin.deprecated" from the kibana.yml file."'], }, @@ -303,7 +303,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }; - const processed = unused('section.deprecated')(rawConfig, 'myplugin', deprecationHook); + const processed = unused('section.deprecated')(rawConfig, 'myplugin', addDeprecation); expect(processed).toEqual({ myplugin: { valid: 'valid', @@ -314,7 +314,7 @@ describe('DeprecationFactory', () => { }, }); - expect(deprecationHook).toBeCalledWith({ + expect(addDeprecation).toBeCalledWith({ correctiveActions: { manualSteps: ['Remove "myplugin.section.deprecated" from the kibana.yml file."'], }, @@ -331,7 +331,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }; - const processed = unused('deprecated')(rawConfig, 'myplugin', deprecationHook); + const processed = unused('deprecated')(rawConfig, 'myplugin', addDeprecation); expect(processed).toEqual({ myplugin: { valid: 'valid', @@ -340,7 +340,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationHook).toBeCalledTimes(0); + expect(addDeprecation).toBeCalledTimes(0); }); }); @@ -358,7 +358,7 @@ describe('DeprecationFactory', () => { const processed = unusedFromRoot('myplugin.deprecated')( rawConfig, 'does-not-matter', - deprecationHook + addDeprecation ); expect(processed).toEqual({ myplugin: { @@ -369,7 +369,7 @@ describe('DeprecationFactory', () => { }, }); - expect(deprecationHook).toBeCalledWith({ + expect(addDeprecation).toBeCalledWith({ correctiveActions: { manualSteps: ['Remove "myplugin.deprecated" from the kibana.yml file."'], }, @@ -389,7 +389,7 @@ describe('DeprecationFactory', () => { const processed = unusedFromRoot('myplugin.deprecated')( rawConfig, 'does-not-matter', - deprecationHook + addDeprecation ); expect(processed).toEqual({ myplugin: { @@ -399,7 +399,7 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(deprecationHook).toBeCalledTimes(0); + expect(addDeprecation).toBeCalledTimes(0); }); }); }); diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.ts b/packages/kbn-config/src/deprecation/deprecation_factory.ts index 836bb338109d..839ee5f9fc0e 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.ts @@ -11,7 +11,7 @@ import { set } from '@elastic/safer-lodash-set'; import { unset } from '@kbn/std'; import { ConfigDeprecation, - ConfigDeprecationHook, + AddConfigDeprecation, ConfigDeprecationFactory, DeprecatedConfigDetails, } from './types'; @@ -19,7 +19,7 @@ import { const _rename = ( config: Record, rootPath: string, - deprecationHook: ConfigDeprecationHook, + addDeprecation: AddConfigDeprecation, oldKey: string, newKey: string, details?: Partial @@ -37,7 +37,7 @@ const _rename = ( if (newValue === undefined) { set(config, fullNewPath, oldValue); - deprecationHook({ + addDeprecation({ message: `"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}"`, correctiveActions: { manualSteps: [`Replace "${fullOldPath}" in the kibana.yml file with "${fullNewPath}"`], @@ -45,7 +45,7 @@ const _rename = ( ...details, }); } else { - deprecationHook({ + addDeprecation({ message: `"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}". However both key are present, ignoring "${fullOldPath}"`, correctiveActions: { manualSteps: [ @@ -63,7 +63,7 @@ const _rename = ( const _unused = ( config: Record, rootPath: string, - deprecationHook: ConfigDeprecationHook, + addDeprecation: AddConfigDeprecation, unusedKey: string, details?: Partial ) => { @@ -72,7 +72,7 @@ const _unused = ( return config; } unset(config, fullPath); - deprecationHook({ + addDeprecation({ message: `${fullPath} is deprecated and is no longer used`, correctiveActions: { manualSteps: [`Remove "${fullPath}" from the kibana.yml file."`], @@ -86,27 +86,27 @@ const rename = ( oldKey: string, newKey: string, details?: Partial -): ConfigDeprecation => (config, rootPath, deprecationHook) => - _rename(config, rootPath, deprecationHook, oldKey, newKey, details); +): ConfigDeprecation => (config, rootPath, addDeprecation) => + _rename(config, rootPath, addDeprecation, oldKey, newKey, details); const renameFromRoot = ( oldKey: string, newKey: string, details?: Partial -): ConfigDeprecation => (config, rootPath, deprecationHook) => - _rename(config, '', deprecationHook, oldKey, newKey, details); +): ConfigDeprecation => (config, rootPath, addDeprecation) => + _rename(config, '', addDeprecation, oldKey, newKey, details); const unused = ( unusedKey: string, details?: Partial -): ConfigDeprecation => (config, rootPath, deprecationHook) => - _unused(config, rootPath, deprecationHook, unusedKey, details); +): ConfigDeprecation => (config, rootPath, addDeprecation) => + _unused(config, rootPath, addDeprecation, unusedKey, details); const unusedFromRoot = ( unusedKey: string, details?: Partial -): ConfigDeprecation => (config, rootPath, deprecationHook) => - _unused(config, '', deprecationHook, unusedKey, details); +): ConfigDeprecation => (config, rootPath, addDeprecation) => + _unused(config, '', addDeprecation, unusedKey, details); const getPath = (rootPath: string, subPath: string) => rootPath !== '' ? `${rootPath}.${subPath}` : subPath; diff --git a/packages/kbn-config/src/deprecation/index.ts b/packages/kbn-config/src/deprecation/index.ts index 2552396de809..3286acca9e58 100644 --- a/packages/kbn-config/src/deprecation/index.ts +++ b/packages/kbn-config/src/deprecation/index.ts @@ -10,7 +10,7 @@ export type { ConfigDeprecation, ConfigDeprecationWithContext, ConfigDeprecationFactory, - ConfigDeprecationHook, + AddConfigDeprecation, ConfigDeprecationProvider, DeprecatedConfigDetails, } from './types'; diff --git a/packages/kbn-config/src/deprecation/types.ts b/packages/kbn-config/src/deprecation/types.ts index 96efe6eaa33f..3b1d004d7ec7 100644 --- a/packages/kbn-config/src/deprecation/types.ts +++ b/packages/kbn-config/src/deprecation/types.ts @@ -11,7 +11,7 @@ * * @public */ -export type ConfigDeprecationHook = (details: DeprecatedConfigDetails) => void; +export type AddConfigDeprecation = (details: DeprecatedConfigDetails) => void; /** * Deprecated Config Details @@ -19,18 +19,19 @@ export type ConfigDeprecationHook = (details: DeprecatedConfigDetails) => void; * @public */ export interface DeprecatedConfigDetails { + /* The message to be displayed for the deprecation. */ message: string; + /* (optional) set false to prevent the config service from logging the deprecation message. */ silent?: boolean; + /* (optional) link to the documentation for more details on the deprecation. */ documentationUrl?: string; + /* (optional) corrective action needed to fix this deprecation. */ correctiveActions?: { - api?: { - path: string; - method: 'POST' | 'PUT'; - body?: { - [key: string]: any; - }; - }; - manualSteps?: string[]; + /** + * Specify a list of manual steps our users need to follow + * to fix the deprecation before upgrade. + */ + manualSteps: string[]; }; } @@ -46,7 +47,7 @@ export interface DeprecatedConfigDetails { export type ConfigDeprecation = ( config: Record, fromPath: string, - deprecationHook: ConfigDeprecationHook + addDeprecation: AddConfigDeprecation ) => Record; /** diff --git a/packages/kbn-config/src/index.ts b/packages/kbn-config/src/index.ts index be5225d1fdd3..24e8c1cd0325 100644 --- a/packages/kbn-config/src/index.ts +++ b/packages/kbn-config/src/index.ts @@ -6,16 +6,16 @@ * Side Public License, v 1. */ -export { - applyDeprecations, - ConfigDeprecation, +export type { ConfigDeprecationFactory, - configDeprecationFactory, - ConfigDeprecationHook, + AddConfigDeprecation, ConfigDeprecationProvider, ConfigDeprecationWithContext, + ConfigDeprecation, } from './deprecation'; +export { applyDeprecations, configDeprecationFactory } from './deprecation'; + export { RawConfigurationProvider, RawConfigService, getConfigFromFiles } from './raw'; export { ConfigService, IConfigService } from './config_service'; diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 90d29ce076d6..b68a7ced118d 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -84,7 +84,6 @@ export class CoreSystem { private readonly integrations: IntegrationsService; private readonly coreApp: CoreApp; private readonly deprecations: DeprecationsService; - private readonly rootDomElement: HTMLElement; private readonly coreContext: CoreContext; private fatalErrorsSetup: FatalErrorsSetup | null = null; @@ -136,7 +135,6 @@ export class CoreSystem { const http = this.http.setup({ injectedMetadata, fatalErrors: this.fatalErrorsSetup }); const uiSettings = this.uiSettings.setup({ http, injectedMetadata }); const notifications = this.notifications.setup({ uiSettings }); - const deprecations = this.deprecations.setup({ http }); const application = this.application.setup({ http }); this.coreApp.setup({ application, http, injectedMetadata, notifications }); @@ -148,7 +146,6 @@ export class CoreSystem { injectedMetadata, notifications, uiSettings, - deprecations, }; // Services that do not expose contracts at setup @@ -200,7 +197,7 @@ export class CoreSystem { injectedMetadata, notifications, }); - const deprecations = this.deprecations.start(); + const deprecations = this.deprecations.start({ http }); this.coreApp.start({ application, http, notifications, uiSettings }); diff --git a/src/core/public/deprecations/deprecations_client.test.ts b/src/core/public/deprecations/deprecations_client.test.ts index 70aea62f27f9..e4dccc862631 100644 --- a/src/core/public/deprecations/deprecations_client.test.ts +++ b/src/core/public/deprecations/deprecations_client.test.ts @@ -33,32 +33,6 @@ describe('DeprecationsClient', () => { expect(deprecations).toEqual(mockDeprecationsInfo); }); - - it('caches the results', async () => { - const deprecationsClient = new DeprecationsClient({ http }); - const results = [ - await deprecationsClient.getAllDeprecations(), - await deprecationsClient.getAllDeprecations(), - ]; - - expect(http.fetch).toBeCalledTimes(1); - - expect(results).toEqual([mockDeprecationsInfo, mockDeprecationsInfo]); - }); - - it('calls the fetch api on skipCache: true', async () => { - const deprecationsClient = new DeprecationsClient({ http }); - http.fetch.mockResolvedValueOnce({ deprecationsInfo: ['test2'] }); - http.fetch.mockResolvedValueOnce({ deprecationsInfo: ['test3'] }); - const results = [ - await deprecationsClient.getAllDeprecations({ skipCache: true }), - await deprecationsClient.getAllDeprecations({ skipCache: true }), - ]; - - expect(http.fetch).toBeCalledTimes(2); - - expect(results).toEqual([['test2'], ['test3']]); - }); }); describe('getDeprecations', () => { @@ -80,18 +54,7 @@ describe('DeprecationsClient', () => { expect(deprecations).toEqual([]); }); - it('caches the results', async () => { - const deprecationsClient = new DeprecationsClient({ http }); - const results = [ - ...(await deprecationsClient.getDeprecations('testPluginId-1')), - ...(await deprecationsClient.getDeprecations('testPluginId-2')), - ]; - - expect(http.fetch).toBeCalledTimes(1); - expect(results).toEqual(mockDeprecationsInfo); - }); - - it('calls the fetch api on skipCache: true', async () => { + it('calls the fetch api', async () => { const deprecationsClient = new DeprecationsClient({ http }); http.fetch.mockResolvedValueOnce({ deprecationsInfo: [{ pluginId: 'testPluginId-1' }, { pluginId: 'testPluginId-1' }], @@ -100,8 +63,8 @@ describe('DeprecationsClient', () => { deprecationsInfo: [{ pluginId: 'testPluginId-2' }, { pluginId: 'testPluginId-2' }], }); const results = [ - ...(await deprecationsClient.getDeprecations('testPluginId-1', { skipCache: true })), - ...(await deprecationsClient.getDeprecations('testPluginId-2', { skipCache: true })), + ...(await deprecationsClient.getDeprecations('testPluginId-1')), + ...(await deprecationsClient.getDeprecations('testPluginId-2')), ]; expect(http.fetch).toBeCalledTimes(2); diff --git a/src/core/public/deprecations/deprecations_client.ts b/src/core/public/deprecations/deprecations_client.ts index cbecd415b525..72f3c5140a8f 100644 --- a/src/core/public/deprecations/deprecations_client.ts +++ b/src/core/public/deprecations/deprecations_client.ts @@ -6,44 +6,30 @@ * Side Public License, v 1. */ -import { HttpSetup } from 'src/core/public'; -import type { PluginDeprecationDetails } from '../../server/types'; +import type { HttpStart } from '../http'; +import type { DomainDeprecationDetails } from '../../server/types'; /** * @internal */ interface DeprecationsGetResponse { - deprecationsInfo: PluginDeprecationDetails[]; + deprecationsInfo: DomainDeprecationDetails[]; } /** * @internal */ export interface DeprecationsClientDeps { - http: Pick; + http: Pick; } -/** @public */ -export interface GetDeprecationsConfig { - /** set true to fetch a fresh copy of the deprecations from the kibana server. */ - skipCache?: boolean; -} - -/** @public */ -export type GetAllDeprecationsConfig = GetDeprecationsConfig; - export class DeprecationsClient { - private readonly http: Pick; - private deprecations?: PluginDeprecationDetails[]; + private readonly http: Pick; constructor({ http }: DeprecationsClientDeps) { this.http = http; } - private fetchDeprecations = async (skipCache?: boolean): Promise => { - if (!skipCache && this.deprecations) { - return this.deprecations; - } - + private fetchDeprecations = async (): Promise => { const { deprecationsInfo } = await this.http.fetch( '/api/deprecations/', { @@ -51,20 +37,15 @@ export class DeprecationsClient { } ); - this.deprecations = deprecationsInfo; return deprecationsInfo; }; - public getAllDeprecations = async ({ skipCache }: GetAllDeprecationsConfig = {}) => { - return await this.fetchDeprecations(skipCache); - }; - - public getDeprecations = async (pluginId: string, { skipCache }: GetDeprecationsConfig = {}) => { - const deprecations = await this.fetchDeprecations(skipCache); - return deprecations.filter((deprecation) => deprecation.pluginId === pluginId); + public getAllDeprecations = async () => { + return await this.fetchDeprecations(); }; - public clearCache = () => { - this.deprecations = undefined; + public getDeprecations = async (domainId: string) => { + const deprecations = await this.fetchDeprecations(); + return deprecations.filter((deprecation) => deprecation.domainId === domainId); }; } diff --git a/src/core/public/deprecations/deprecations_service.mock.ts b/src/core/public/deprecations/deprecations_service.mock.ts index 7cc4ef3e6aae..5fc554ed9746 100644 --- a/src/core/public/deprecations/deprecations_service.mock.ts +++ b/src/core/public/deprecations/deprecations_service.mock.ts @@ -8,9 +8,9 @@ import type { PublicMethodsOf } from '@kbn/utility-types'; import { DeprecationsService } from './deprecations_service'; -import type { DeprecationsServiceSetup, DeprecationsServiceStart } from './deprecations_service'; +import type { DeprecationsServiceStart } from './deprecations_service'; -const createServiceMock = (): jest.Mocked => ({ +const createServiceMock = (): jest.Mocked => ({ getAllDeprecations: jest.fn().mockResolvedValue([]), getDeprecations: jest.fn().mockResolvedValue([]), }); @@ -22,13 +22,13 @@ const createMock = () => { stop: jest.fn(), }; - mocked.setup.mockReturnValue(createServiceMock()); + mocked.setup.mockReturnValue(void 0); mocked.start.mockReturnValue(createServiceMock()); return mocked; }; export const deprecationsServiceMock = { create: createMock, - createSetupContract: createServiceMock as () => jest.Mocked, - createStartContract: createServiceMock as () => jest.Mocked, + createSetupContract: () => void 0, + createStartContract: createServiceMock, }; diff --git a/src/core/public/deprecations/deprecations_service.ts b/src/core/public/deprecations/deprecations_service.ts index 56459e823b70..13a29184a9e0 100644 --- a/src/core/public/deprecations/deprecations_service.ts +++ b/src/core/public/deprecations/deprecations_service.ts @@ -6,68 +6,41 @@ * Side Public License, v 1. */ -import { CoreService } from 'src/core/types'; -import { CoreSetup } from 'src/core/public'; +import type { CoreService } from '../../types'; +import type { HttpStart } from '../http'; import { DeprecationsClient } from './deprecations_client'; +import type { DomainDeprecationDetails } from '../../server/types'; /** - * DeprecationsService provides methods to fetch plugin deprecation details from + * DeprecationsService provides methods to fetch domain deprecation details from * the Kibana server. * * @public */ -export interface DeprecationsServiceSetup { +export interface DeprecationsServiceStart { /** - * Grabs deprecations for all plugins. - * - * @param {Object} configs { skipCache: boolean }; - * set skipCache: true to fetch a fresh copy of the deprecations from the kibana server. + * Grabs deprecations details for all domains. */ - getAllDeprecations: DeprecationsClient['getAllDeprecations']; + getAllDeprecations: () => Promise; /** - * Grabs deprecations for a specific plugin. + * Grabs deprecations for a specific domain. * - * @param {string} pluginId - * @param {Object} configs { skipCache: boolean }; - * set skipCache: true to fetch a fresh copy of the deprecations from the kibana server. + * @param {string} domainId */ - getDeprecations: DeprecationsClient['getDeprecations']; + getDeprecations: (domainId: string) => Promise; } -/** - * DeprecationsService provides methods to fetch plugin deprecation details from - * the Kibana server. - * - * @public - */ -export type DeprecationsServiceStart = DeprecationsServiceSetup; - -export class DeprecationsService - implements CoreService { - private deprecationsClient?: DeprecationsClient; - - public setup({ http }: Pick): DeprecationsServiceSetup { - this.deprecationsClient = new DeprecationsClient({ http }); - return { - getAllDeprecations: this.deprecationsClient.getAllDeprecations, - getDeprecations: this.deprecationsClient.getDeprecations, - }; - } +export class DeprecationsService implements CoreService { + public setup(): void {} - public start(): DeprecationsServiceStart { - if (!this.deprecationsClient) { - throw new Error('#setup must be called first.'); - } + public start({ http }: { http: HttpStart }): DeprecationsServiceStart { + const deprecationsClient = new DeprecationsClient({ http }); return { - getAllDeprecations: this.deprecationsClient.getAllDeprecations, - getDeprecations: this.deprecationsClient.getDeprecations, + getAllDeprecations: deprecationsClient.getAllDeprecations, + getDeprecations: deprecationsClient.getDeprecations, }; } - public stop() { - if (this.deprecationsClient) { - this.deprecationsClient.clearCache(); - } - } + public stop(): void {} } diff --git a/src/core/public/deprecations/index.ts b/src/core/public/deprecations/index.ts index cf4ac4cff9d1..8f5e44d84566 100644 --- a/src/core/public/deprecations/index.ts +++ b/src/core/public/deprecations/index.ts @@ -7,5 +7,4 @@ */ export { DeprecationsService } from './deprecations_service'; -export type { DeprecationsServiceSetup, DeprecationsServiceStart } from './deprecations_service'; -export type { GetDeprecationsConfig, GetAllDeprecationsConfig } from './deprecations_client'; +export type { DeprecationsServiceStart } from './deprecations_service'; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 9506975ae8d2..b5ff54365a9f 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -65,7 +65,7 @@ import { UiSettingsState, IUiSettingsClient } from './ui_settings'; import { ApplicationSetup, Capabilities, ApplicationStart } from './application'; import { DocLinksStart } from './doc_links'; import { SavedObjectsStart } from './saved_objects'; -import { DeprecationsServiceSetup, DeprecationsServiceStart } from './deprecations'; +import { DeprecationsServiceStart } from './deprecations'; export type { PackageInfo, EnvironmentMode, IExternalUrlPolicy } from '../server/types'; export type { CoreContext, CoreSystem } from './core_system'; @@ -185,12 +185,7 @@ export type { ErrorToastOptions, } from './notifications'; -export type { - DeprecationsServiceSetup, - DeprecationsServiceStart, - GetAllDeprecationsConfig, - GetDeprecationsConfig, -} from './deprecations'; +export type { DeprecationsServiceStart } from './deprecations'; export type { MountPoint, UnmountCallback, PublicUiSettingsParams } from './types'; @@ -221,8 +216,6 @@ export interface CoreSetup { injectedMetadata: injectedMetadataServiceMock.createStartContract(), notifications: notificationServiceMock.createSetupContract(), uiSettings: uiSettingsServiceMock.createSetupContract(), - deprecations: deprecationsServiceMock.createSetupContract(), }; mockSetupContext = { ...mockSetupDeps, diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index b2c3e68e935d..306d4eb84402 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -19,7 +19,6 @@ import { EuiFlyoutSize } from '@elastic/eui'; import { EuiGlobalToastListToast } from '@elastic/eui'; import { History } from 'history'; import { Href } from 'history'; -import { HttpSetup as HttpSetup_2 } from 'src/core/public'; import { IconType } from '@elastic/eui'; import { IncomingHttpHeaders } from 'http'; import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; @@ -411,8 +410,6 @@ export interface CoreSetup; @@ -478,15 +475,12 @@ export class CoreSystem { export const DEFAULT_APP_CATEGORIES: Record; // @public -export interface DeprecationsServiceSetup { - // Warning: (ae-forgotten-export) The symbol "DeprecationsClient" needs to be exported by the entry point index.d.ts - getAllDeprecations: DeprecationsClient['getAllDeprecations']; - getDeprecations: DeprecationsClient['getDeprecations']; +export interface DeprecationsServiceStart { + // Warning: (ae-forgotten-export) The symbol "DomainDeprecationDetails" needs to be exported by the entry point index.d.ts + getAllDeprecations: () => Promise; + getDeprecations: (domainId: string) => Promise; } -// @public -export type DeprecationsServiceStart = DeprecationsServiceSetup; - // @public (undocumented) export interface DocLinksStart { // (undocumented) @@ -680,14 +674,6 @@ export interface FatalErrorsSetup { // @public export type FatalErrorsStart = FatalErrorsSetup; -// @public (undocumented) -export type GetAllDeprecationsConfig = GetDeprecationsConfig; - -// @public (undocumented) -export interface GetDeprecationsConfig { - skipCache?: boolean; -} - // @internal (undocumented) export class HttpFetchError extends Error implements IHttpFetchError { constructor(message: string, name: string, request: Request, response?: Response | undefined, body?: any); @@ -1607,6 +1593,6 @@ export interface UserProvidedValues { // Warnings were encountered during analysis: // -// src/core/public/core_system.ts:169:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts +// src/core/public/core_system.ts:166:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts ``` diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts index 4f8fb24a6d81..2e77374e3068 100644 --- a/src/core/server/config/deprecation/core_deprecations.ts +++ b/src/core/server/config/deprecation/core_deprecations.ts @@ -9,27 +9,27 @@ import { has, get } from 'lodash'; import { ConfigDeprecationProvider, ConfigDeprecation } from '@kbn/config'; -const configPathDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const configPathDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(process.env, 'CONFIG_PATH')) { - deprecationHook({ + addDeprecation({ message: `Environment variable CONFIG_PATH is deprecated. It has been replaced with KBN_PATH_CONF pointing to a config folder`, }); } return settings; }; -const dataPathDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const dataPathDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(process.env, 'DATA_PATH')) { - deprecationHook({ + addDeprecation({ message: `Environment variable "DATA_PATH" will be removed. It has been replaced with kibana.yml setting "path.data"`, }); } return settings; }; -const rewriteBasePathDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const rewriteBasePathDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(settings, 'server.basePath') && !has(settings, 'server.rewriteBasePath')) { - deprecationHook({ + addDeprecation({ message: 'You should set server.basePath along with server.rewriteBasePath. Starting in 7.0, Kibana ' + 'will expect that all requests start with server.basePath rather than expecting you to rewrite ' + @@ -40,10 +40,10 @@ const rewriteBasePathDeprecation: ConfigDeprecation = (settings, fromPath, depre return settings; }; -const rewriteCorsSettings: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const rewriteCorsSettings: ConfigDeprecation = (settings, fromPath, addDeprecation) => { const corsSettings = get(settings, 'server.cors'); if (typeof get(settings, 'server.cors') === 'boolean') { - deprecationHook({ + addDeprecation({ message: '"server.cors" is deprecated and has been replaced by "server.cors.enabled"', }); settings.server.cors = { @@ -53,7 +53,7 @@ const rewriteCorsSettings: ConfigDeprecation = (settings, fromPath, deprecationH return settings; }; -const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { const NONCE_STRING = `{nonce}`; // Policies that should include the 'self' source const SELF_POLICIES = Object.freeze(['script-src', 'style-src']); @@ -70,7 +70,7 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, deprecationH settings.csp.rules = [...parsed].map(([policy, sourceList]) => { if (sourceList.find((source) => source.includes(NONCE_STRING))) { - deprecationHook({ + addDeprecation({ message: `csp.rules no longer supports the {nonce} syntax. Replacing with 'self' in ${policy}`, }); sourceList = sourceList.filter((source) => !source.includes(NONCE_STRING)); @@ -85,7 +85,7 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, deprecationH SELF_POLICIES.includes(policy) && !sourceList.find((source) => source.includes(SELF_STRING)) ) { - deprecationHook({ + addDeprecation({ message: `csp.rules must contain the 'self' source. Automatically adding to ${policy}.`, }); sourceList.push(SELF_STRING); @@ -101,10 +101,10 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, deprecationH const mapManifestServiceUrlDeprecation: ConfigDeprecation = ( settings, fromPath, - deprecationHook + addDeprecation ) => { if (has(settings, 'map.manifestServiceUrl')) { - deprecationHook({ + addDeprecation({ message: 'You should no longer use the map.manifestServiceUrl setting in kibana.yml to configure the location ' + 'of the Elastic Maps Service settings. These settings have moved to the "map.emsTileApiUrl" and ' + @@ -115,9 +115,9 @@ const mapManifestServiceUrlDeprecation: ConfigDeprecation = ( return settings; }; -const opsLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const opsLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(settings, 'logging.events.ops')) { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents', message: @@ -130,9 +130,9 @@ const opsLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, depre return settings; }; -const requestLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const requestLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(settings, 'logging.events.request') || has(settings, 'logging.events.response')) { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents', message: @@ -145,9 +145,9 @@ const requestLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, d return settings; }; -const timezoneLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const timezoneLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(settings, 'logging.timezone')) { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingtimezone', message: @@ -160,9 +160,9 @@ const timezoneLoggingDeprecation: ConfigDeprecation = (settings, fromPath, depre return settings; }; -const destLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const destLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(settings, 'logging.dest')) { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingdest', message: @@ -175,9 +175,9 @@ const destLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecati return settings; }; -const quietLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const quietLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(settings, 'logging.quiet')) { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingquiet', message: @@ -188,9 +188,9 @@ const quietLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecat return settings; }; -const silentLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const silentLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(settings, 'logging.silent')) { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingsilent', message: @@ -201,9 +201,9 @@ const silentLoggingDeprecation: ConfigDeprecation = (settings, fromPath, depreca return settings; }; -const verboseLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const verboseLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(settings, 'logging.verbose')) { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingverbose', message: @@ -214,13 +214,13 @@ const verboseLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprec return settings; }; -const jsonLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const jsonLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { // We silence the deprecation warning when running in development mode because // the dev CLI code in src/dev/cli_dev_mode/using_server_process.ts manually // specifies `--logging.json=false`. Since it's executed in a child process, the // ` legacyLoggingConfigSchema` returns `true` for the TTY check on `process.stdout.isTTY` if (has(settings, 'logging.json') && settings.env !== 'development') { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx', message: @@ -235,9 +235,9 @@ const jsonLoggingDeprecation: ConfigDeprecation = (settings, fromPath, deprecati return settings; }; -const logRotateDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const logRotateDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(settings, 'logging.rotate')) { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#rolling-file-appender', message: @@ -250,9 +250,9 @@ const logRotateDeprecation: ConfigDeprecation = (settings, fromPath, deprecation return settings; }; -const logEventsLogDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const logEventsLogDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(settings, 'logging.events.log')) { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents', message: @@ -263,9 +263,9 @@ const logEventsLogDeprecation: ConfigDeprecation = (settings, fromPath, deprecat return settings; }; -const logEventsErrorDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const logEventsErrorDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(settings, 'logging.events.error')) { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents', message: @@ -276,9 +276,9 @@ const logEventsErrorDeprecation: ConfigDeprecation = (settings, fromPath, deprec return settings; }; -const logFilterDeprecation: ConfigDeprecation = (settings, fromPath, deprecationHook) => { +const logFilterDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (has(settings, 'logging.filter')) { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingfilter', message: '"logging.filter" has been deprecated and will be removed in 8.0.', diff --git a/src/core/server/config/index.ts b/src/core/server/config/index.ts index c16133176037..b1086d447033 100644 --- a/src/core/server/config/index.ts +++ b/src/core/server/config/index.ts @@ -24,7 +24,7 @@ export type { ConfigPath, CliArgs, ConfigDeprecation, - ConfigDeprecationHook, + AddConfigDeprecation, ConfigDeprecationProvider, ConfigDeprecationFactory, EnvironmentMode, diff --git a/src/core/server/deprecations/deprecations_factory.test.ts b/src/core/server/deprecations/deprecations_factory.test.ts index b89b404dedda..3b54b5c64bb1 100644 --- a/src/core/server/deprecations/deprecations_factory.test.ts +++ b/src/core/server/deprecations/deprecations_factory.test.ts @@ -17,31 +17,31 @@ describe('DeprecationsFactory', () => { }); describe('createRegistry', () => { - it('creates a registry for a pluginId', async () => { + it('creates a registry for a domainId', async () => { const deprecationsFactory = new DeprecationsFactory({ logger }); - const pluginId = 'test-plugin'; - const registry = deprecationsFactory.createRegistry(pluginId); + const domainId = 'test-plugin'; + const registry = deprecationsFactory.createRegistry(domainId); expect(registry).toHaveProperty('registerDeprecations'); expect(registry).toHaveProperty('getDeprecations'); }); - it('creates one registry for a pluginId', async () => { + it('creates one registry for a domainId', async () => { const deprecationsFactory = new DeprecationsFactory({ logger }); - const pluginId = 'test-plugin'; - const registry = deprecationsFactory.createRegistry(pluginId); - const sameRegistry = deprecationsFactory.createRegistry(pluginId); + const domainId = 'test-plugin'; + const registry = deprecationsFactory.createRegistry(domainId); + const sameRegistry = deprecationsFactory.createRegistry(domainId); expect(registry).toStrictEqual(sameRegistry); }); }); describe('getRegistry', () => { - const pluginId = 'test-plugin'; + const domainId = 'test-plugin'; const deprecationsFactory = new DeprecationsFactory({ logger }); it('returns a registered registry', () => { - const registry = deprecationsFactory.createRegistry(pluginId); - expect(deprecationsFactory.getRegistry(pluginId)).toStrictEqual(registry); + const registry = deprecationsFactory.createRegistry(domainId); + expect(deprecationsFactory.getRegistry(domainId)).toStrictEqual(registry); }); it('returns undefined if no registry is defined', () => { expect(deprecationsFactory.getRegistry('never-registered-plugin')).toBe(undefined); @@ -94,10 +94,10 @@ describe('DeprecationsFactory', () => { const derpecationsInfo = await deprecationsFactory.getAllDeprecations(mockDependencies); expect(derpecationsInfo).toStrictEqual( [ - mockPluginDeprecationsInfo.map((info) => ({ ...info, pluginId: 'mockPlugin' })), + mockPluginDeprecationsInfo.map((info) => ({ ...info, domainId: 'mockPlugin' })), anotherMockPluginDeprecationsInfo.map((info) => ({ ...info, - pluginId: 'anotherMockPlugin', + domainId: 'anotherMockPlugin', })), ].flat() ); @@ -105,23 +105,23 @@ describe('DeprecationsFactory', () => { it(`returns a failure message for failed getDeprecations functions`, async () => { const deprecationsFactory = new DeprecationsFactory({ logger }); - const pluginId = 'mockPlugin'; + const domainId = 'mockPlugin'; const mockError = new Error(); - const deprecationsRegistry = deprecationsFactory.createRegistry(pluginId); + const deprecationsRegistry = deprecationsFactory.createRegistry(domainId); deprecationsRegistry.registerDeprecations({ getDeprecations: jest.fn().mockRejectedValue(mockError), }); const derpecationsInfo = await deprecationsFactory.getAllDeprecations(mockDependencies); expect(logger.warn).toBeCalledTimes(1); expect(logger.warn).toBeCalledWith( - `Failed to get deprecations info for plugin "${pluginId}".`, + `Failed to get deprecations info for plugin "${domainId}".`, mockError ); expect(derpecationsInfo).toStrictEqual([ { - pluginId, - message: `Failed to get deprecations info for plugin "${pluginId}".`, + domainId, + message: `Failed to get deprecations info for plugin "${domainId}".`, level: 'warning', correctiveActions: { manualSteps: ['Check Kibana server logs for error message.'], @@ -158,9 +158,9 @@ describe('DeprecationsFactory', () => { mockError ); expect(derpecationsInfo).toStrictEqual([ - ...mockPluginDeprecationsInfo.map((info) => ({ ...info, pluginId: 'mockPlugin' })), + ...mockPluginDeprecationsInfo.map((info) => ({ ...info, domainId: 'mockPlugin' })), { - pluginId: 'anotherMockPlugin', + domainId: 'anotherMockPlugin', message: `Failed to get deprecations info for plugin "anotherMockPlugin".`, level: 'warning', correctiveActions: { @@ -208,7 +208,7 @@ describe('DeprecationsFactory', () => { mockDependencies ); expect(derpecationsInfo).toStrictEqual( - deprecationsInfoBody.flat().map((body) => ({ ...body, pluginId: 'mockPlugin' })) + deprecationsInfoBody.flat().map((body) => ({ ...body, domainId: 'mockPlugin' })) ); }); @@ -237,7 +237,7 @@ describe('DeprecationsFactory', () => { ); expect(derpecationsInfo).toHaveLength(1); expect(derpecationsInfo).toStrictEqual([ - { ...deprecationsInfoBody[0], pluginId: 'mockPlugin' }, + { ...deprecationsInfoBody[0], domainId: 'mockPlugin' }, ]); }); }); diff --git a/src/core/server/deprecations/deprecations_factory.ts b/src/core/server/deprecations/deprecations_factory.ts index f41d4b86690b..2ffa087912ae 100644 --- a/src/core/server/deprecations/deprecations_factory.ts +++ b/src/core/server/deprecations/deprecations_factory.ts @@ -9,7 +9,7 @@ import { DeprecationsRegistry } from './deprecations_registry'; import type { Logger } from '../logging'; import type { - PluginDeprecationDetails, + DomainDeprecationDetails, DeprecationsDetails, GetDeprecationsContext, } from './types'; @@ -25,37 +25,37 @@ export class DeprecationsFactory { this.logger = logger; } - public createRegistry = (pluginId: string): DeprecationsRegistry => { - const exsiting = this.registries.get(pluginId); - if (exsiting) { - return exsiting; + public createRegistry = (domainId: string): DeprecationsRegistry => { + const existing = this.registries.get(domainId); + if (existing) { + return existing; } const registry = new DeprecationsRegistry(); - this.registries.set(pluginId, registry); + this.registries.set(domainId, registry); return registry; }; - public getRegistry = (pluginId: string): DeprecationsRegistry | undefined => { - return this.registries.get(pluginId); + public getRegistry = (domainId: string): DeprecationsRegistry | undefined => { + return this.registries.get(domainId); }; public getDeprecations = async ( - pluginId: string, + domainId: string, dependencies: GetDeprecationsContext - ): Promise => { - const infoBody = await this.getDeprecationsBody(pluginId, dependencies); - return this.createDeprecationInfo(pluginId, infoBody).flat(); + ): Promise => { + const infoBody = await this.getDeprecationsBody(domainId, dependencies); + return this.createDeprecationInfo(domainId, infoBody).flat(); }; public getAllDeprecations = async ( dependencies: GetDeprecationsContext - ): Promise => { - const pluginIds = [...this.registries.keys()]; + ): Promise => { + const domainIds = [...this.registries.keys()]; const deprecationsInfo = await Promise.all( - pluginIds.map(async (pluginId) => { - const infoBody = await this.getDeprecationsBody(pluginId, dependencies); - return this.createDeprecationInfo(pluginId, infoBody); + domainIds.map(async (domainId) => { + const infoBody = await this.getDeprecationsBody(domainId, dependencies); + return this.createDeprecationInfo(domainId, infoBody); }) ); @@ -63,23 +63,23 @@ export class DeprecationsFactory { }; private createDeprecationInfo = ( - pluginId: string, + domainId: string, deprecationInfoBody: DeprecationsDetails[] - ): PluginDeprecationDetails[] => { + ): DomainDeprecationDetails[] => { return deprecationInfoBody .flat() .filter(Boolean) .map((pluginDeprecation) => ({ ...pluginDeprecation, - pluginId, + domainId, })); }; private getDeprecationsBody = async ( - pluginId: string, + domainId: string, dependencies: GetDeprecationsContext ): Promise => { - const deprecationsRegistry = this.registries.get(pluginId); + const deprecationsRegistry = this.registries.get(domainId); if (!deprecationsRegistry) { return []; } @@ -88,13 +88,13 @@ export class DeprecationsFactory { return settledResults.flatMap((settledResult) => { if (settledResult.status === 'rejected') { this.logger.warn( - `Failed to get deprecations info for plugin "${pluginId}".`, + `Failed to get deprecations info for plugin "${domainId}".`, settledResult.reason ); return [ { - message: `Failed to get deprecations info for plugin "${pluginId}".`, - level: 'warning', + message: `Failed to get deprecations info for plugin "${domainId}".`, + level: 'fetch_error', correctiveActions: { manualSteps: ['Check Kibana server logs for error message.'], }, @@ -105,7 +105,7 @@ export class DeprecationsFactory { return settledResult.value; }); } catch (err) { - this.logger.warn(`Failed to get deprecations info for plugin "${pluginId}".`, err); + this.logger.warn(`Failed to get deprecations info for plugin "${domainId}".`, err); return []; } }; diff --git a/src/core/server/deprecations/deprecations_service.ts b/src/core/server/deprecations/deprecations_service.ts index f8faa87a04d2..acc6c20c61b8 100644 --- a/src/core/server/deprecations/deprecations_service.ts +++ b/src/core/server/deprecations/deprecations_service.ts @@ -27,24 +27,33 @@ import { registerRoutes } from './routes'; * ```ts * import { DeprecationsDetails, GetDeprecationsContext, CoreSetup } from 'src/core/server'; * - * const getDeprecations = async ({ esClient, savedObjectsClient }: GetDeprecationsContext): DeprecationsDetails[] => { - * return [ - * { - * message: string; - * level: 'warning' | 'critical'; - * documentationUrl?: string; - * correctiveActions: { - * api?: { - * path: string; - * method: 'POST' | 'PUT'; - * body?: { [key: string]: any }, - * }, - * manualSteps?: string[]; - * } - * } - * ] + * async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecationsContext): Promise { + * const deprecations: DeprecationsDetails[] = []; + * const count = await getTimelionSheetsCount(savedObjectsClient); + * + * if (count > 0) { + * deprecations.push({ + * message: `You have ${count} Timelion worksheets. The Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard.`, + * documentationUrl: + * 'https://www.elastic.co/guide/en/kibana/current/create-panels-with-timelion.html', + * level: 'warning', + * correctiveActions: { + * manualSteps: [ + * 'Navigate to the Kibana Dashboard and click "Create dashboard".', + * 'Select Timelion from the "New Visualization" window.', + * 'Open a new tab, open the Timelion app, select the chart you want to copy, then copy the chart expression.', + * 'Go to Timelion, paste the chart expression in the Timelion expression field, then click Update.', + * 'In the toolbar, click Save.', + * 'On the Save visualization window, enter the visualization Title, then click Save and return.', + * ], + * }, + * }); + * } + * + * return deprecations; * } * + * * export class Plugin() { * setup: (core: CoreSetup) => { * core.deprecations.registerDeprecations({ getDeprecations }); @@ -60,7 +69,7 @@ export interface DeprecationsServiceSetup { /** @internal */ export interface InternalDeprecationsServiceSetup { - createRegistry: (pluginId: string) => DeprecationsServiceSetup; + createRegistry: (domainId: string) => DeprecationsServiceSetup; } /** @internal */ @@ -88,8 +97,8 @@ export class DeprecationsService implements CoreService { - const registry = deprecationsFactory.createRegistry(pluginId); + createRegistry: (domainId: string): DeprecationsServiceSetup => { + const registry = deprecationsFactory.createRegistry(domainId); return { registerDeprecations: registry.registerDeprecations, }; @@ -103,8 +112,8 @@ export class DeprecationsService implements CoreService { return deprecationsContexts.map(({ message, correctiveActions, documentationUrl }) => { diff --git a/src/core/server/deprecations/index.ts b/src/core/server/deprecations/index.ts index 6704c0bdea95..8ece06f82643 100644 --- a/src/core/server/deprecations/index.ts +++ b/src/core/server/deprecations/index.ts @@ -6,7 +6,11 @@ * Side Public License, v 1. */ -export type { DeprecationsDetails, RegisterDeprecationsConfig } from './types'; +export type { + DeprecationsDetails, + GetDeprecationsContext, + RegisterDeprecationsConfig, +} from './types'; export type { DeprecationsServiceSetup, diff --git a/src/core/server/deprecations/types.ts b/src/core/server/deprecations/types.ts index 78bc03f0e135..1a40b1410fe5 100644 --- a/src/core/server/deprecations/types.ts +++ b/src/core/server/deprecations/types.ts @@ -6,26 +6,49 @@ * Side Public License, v 1. */ -import type { IScopedClusterClient, SavedObjectsClientContract } from '../../server'; +import type { SavedObjectsClientContract } from '../saved_objects/types'; +import type { IScopedClusterClient } from '../elasticsearch'; type MaybePromise = T | Promise; -export interface PluginDeprecationDetails extends DeprecationsDetails { - pluginId: string; +export interface DomainDeprecationDetails extends DeprecationsDetails { + domainId: string; } export interface DeprecationsDetails { + /* The message to be displayed for the deprecation. */ message: string; - level: 'warning' | 'critical'; + /** + * 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. + */ + level: 'warning' | 'critical' | 'fetch_error'; + /* (optional) link to the documentation for more details on the deprecation. */ documentationUrl?: string; + /* corrective action needed to fix this deprecation. */ correctiveActions: { + /** + * (optional) The api to be called to automatically fix the deprecation + * Each domain should implement a POST/PUT route for their plugin to + * handle their deprecations. + */ api?: { + /* Kibana route path. Passing a query string is allowed */ path: string; + /* Kibana route method: 'POST' or 'PUT'. */ method: 'POST' | 'PUT'; + /* Additional details to be passed to the route. */ body?: { [key: string]: any; }; }; + /** + * (optional) If this deprecation cannot be automtically fixed + * via an API corrective action. Specify a list of manual steps + * users need to follow to fix the deprecation before upgrade. + */ manualSteps?: string[]; }; } diff --git a/src/core/server/elasticsearch/elasticsearch_config.ts b/src/core/server/elasticsearch/elasticsearch_config.ts index 4dfea9451bb0..7d09af44308d 100644 --- a/src/core/server/elasticsearch/elasticsearch_config.ts +++ b/src/core/server/elasticsearch/elasticsearch_config.ts @@ -144,30 +144,30 @@ export const configSchema = schema.object({ }); const deprecations: ConfigDeprecationProvider = () => [ - (settings, fromPath, deprecationHook) => { + (settings, fromPath, addDeprecation) => { const es = settings[fromPath]; if (!es) { return settings; } if (es.username === 'elastic') { - deprecationHook({ + addDeprecation({ message: `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.`, }); } else if (es.username === 'kibana') { - deprecationHook({ + addDeprecation({ message: `Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.`, }); } if (es.ssl?.key !== undefined && es.ssl?.certificate === undefined) { - deprecationHook({ + addDeprecation({ message: `Setting [${fromPath}.ssl.key] without [${fromPath}.ssl.certificate] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`, }); } else if (es.ssl?.certificate !== undefined && es.ssl?.key === undefined) { - deprecationHook({ + addDeprecation({ message: `Setting [${fromPath}.ssl.certificate] without [${fromPath}.ssl.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`, }); } else if (es.logQueries === true) { - deprecationHook({ + addDeprecation({ message: `Setting [${fromPath}.logQueries] is deprecated and no longer used. You should set the log level to "debug" for the "elasticsearch.queries" context in "logging.loggers" or use "logging.verbose: true".`, }); } diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 0130a0726878..963b69eac4f7 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -89,7 +89,7 @@ export type { ConfigDeprecation, ConfigDeprecationProvider, ConfigDeprecationFactory, - ConfigDeprecationHook, + AddConfigDeprecation, EnvironmentMode, PackageInfo, } from './config'; @@ -384,6 +384,7 @@ export type { I18nServiceSetup } from './i18n'; export type { DeprecationsDetails, RegisterDeprecationsConfig, + GetDeprecationsContext, DeprecationsServiceSetup, } from './deprecations'; @@ -486,10 +487,10 @@ export interface CoreSetup; /** {@link DeprecationsServiceSetup} */ deprecations: DeprecationsServiceSetup; + /** {@link StartServicesAccessor} */ + getStartServices: StartServicesAccessor; } /** diff --git a/src/core/server/kibana_config.ts b/src/core/server/kibana_config.ts index 3c4bd0eab4b1..97783a7657db 100644 --- a/src/core/server/kibana_config.ts +++ b/src/core/server/kibana_config.ts @@ -12,10 +12,10 @@ import { ConfigDeprecationProvider } from '@kbn/config'; export type KibanaConfigType = TypeOf; const deprecations: ConfigDeprecationProvider = () => [ - (settings, fromPath, deprecationHook) => { + (settings, fromPath, addDeprecation) => { const kibana = settings[fromPath]; if (kibana?.index) { - deprecationHook({ + addDeprecation({ message: `"kibana.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details`, documentationUrl: 'https://ela.st/kbn-remove-legacy-multitenancy', }); diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 8481113f32ed..6e867b67436c 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -4,6 +4,7 @@ ```ts +import { AddConfigDeprecation } from '@kbn/config'; import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; import Boom from '@hapi/boom'; import { BulkIndexDocumentsParams } from 'elasticsearch'; @@ -35,7 +36,6 @@ import { ClusterStateParams } from 'elasticsearch'; import { ClusterStatsParams } from 'elasticsearch'; import { ConfigDeprecation } from '@kbn/config'; import { ConfigDeprecationFactory } from '@kbn/config'; -import { ConfigDeprecationHook } from '@kbn/config'; import { ConfigDeprecationProvider } from '@kbn/config'; import { ConfigOptions } from 'elasticsearch'; import { ConfigPath } from '@kbn/config'; @@ -169,6 +169,8 @@ import { UpdateDocumentByQueryParams } from 'elasticsearch'; import { UpdateDocumentParams } from 'elasticsearch'; import { URL } from 'url'; +export { AddConfigDeprecation } + // @public export interface AppCategory { ariaLabel?: string; @@ -374,8 +376,6 @@ export { ConfigDeprecation } export { ConfigDeprecationFactory } -export { ConfigDeprecationHook } - export { ConfigDeprecationProvider } export { ConfigPath } @@ -849,8 +849,7 @@ export interface DeprecationsDetails { }; // (undocumented) documentationUrl?: string; - // (undocumented) - level: 'warning' | 'critical'; + level: 'warning' | 'critical' | 'fetch_error'; // (undocumented) message: string; } @@ -972,6 +971,16 @@ export type GetAuthState = (request: KibanaRequest | LegacyRequest) state: T; }; +// Warning: (ae-missing-release-tag) "GetDeprecationsContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface GetDeprecationsContext { + // (undocumented) + esClient: IScopedClusterClient; + // (undocumented) + savedObjectsClient: SavedObjectsClientContract; +} + // @public (undocumented) export interface GetResponse { // (undocumented) @@ -1949,7 +1958,6 @@ export type RedirectResponseOptions = HttpResponseOptions & { // // @public (undocumented) export interface RegisterDeprecationsConfig { - // Warning: (ae-forgotten-export) The symbol "GetDeprecationsContext" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "MaybePromise" needs to be exported by the entry point index.d.ts // // (undocumented) diff --git a/src/core/server/types.ts b/src/core/server/types.ts index 110b1ac09746..54dd9158fc86 100644 --- a/src/core/server/types.ts +++ b/src/core/server/types.ts @@ -37,7 +37,7 @@ export type { SavedObjectsClientContract, SavedObjectsNamespaceType, } from './saved_objects/types'; -export type { PluginDeprecationDetails } from './deprecations/types'; +export type { DomainDeprecationDetails } from './deprecations/types'; export * from './ui_settings/types'; export * from './legacy/types'; export type { EnvironmentMode, PackageInfo } from '@kbn/config'; diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 37a715a171ed..4eae5629af3a 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -47,7 +47,6 @@ import { FormatFactory as FormatFactory_2 } from 'src/plugins/data/common/field_ import { History } from 'history'; import { Href } from 'history'; import { HttpSetup } from 'kibana/public'; -import { HttpSetup as HttpSetup_3 } from 'src/core/public'; import { IconType } from '@elastic/eui'; import { IncomingHttpHeaders } from 'http'; import { InjectedIntl } from '@kbn/i18n/react'; diff --git a/src/plugins/embeddable/public/public.api.md b/src/plugins/embeddable/public/public.api.md index 9accc2e713fa..b9719542adc8 100644 --- a/src/plugins/embeddable/public/public.api.md +++ b/src/plugins/embeddable/public/public.api.md @@ -25,7 +25,6 @@ import { EuiGlobalToastListToast } from '@elastic/eui'; import { EventEmitter } from 'events'; import { History } from 'history'; import { Href } from 'history'; -import { HttpSetup as HttpSetup_2 } from 'src/core/public'; import { I18nStart as I18nStart_2 } from 'src/core/public'; import { IconType } from '@elastic/eui'; import { IncomingHttpHeaders } from 'http'; diff --git a/src/plugins/kibana_legacy/server/index.ts b/src/plugins/kibana_legacy/server/index.ts index 8899b0e9daa1..1402416d69c9 100644 --- a/src/plugins/kibana_legacy/server/index.ts +++ b/src/plugins/kibana_legacy/server/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ConfigDeprecationHook, CoreSetup, CoreStart, PluginConfigDescriptor } from 'kibana/server'; +import { AddConfigDeprecation, CoreSetup, CoreStart, PluginConfigDescriptor } from 'kibana/server'; import { get } from 'lodash'; import { configSchema, ConfigSchema } from '../config'; @@ -22,7 +22,7 @@ export const config: PluginConfigDescriptor = { ( completeConfig: Record, rootPath: string, - deprecationHook: ConfigDeprecationHook + addDeprecation: AddConfigDeprecation ) => { if ( get(completeConfig, 'kibana.defaultAppId') === undefined && @@ -30,7 +30,7 @@ export const config: PluginConfigDescriptor = { ) { return completeConfig; } - deprecationHook({ + addDeprecation({ message: `kibana.defaultAppId is deprecated and will be removed in 8.0. Please use the \`defaultRoute\` advanced setting instead`, correctiveActions: { manualSteps: [ diff --git a/src/plugins/timelion/server/deprecations.ts b/src/plugins/timelion/server/deprecations.ts index ea87442dcb1f..3d4e687f154c 100644 --- a/src/plugins/timelion/server/deprecations.ts +++ b/src/plugins/timelion/server/deprecations.ts @@ -10,7 +10,7 @@ import { CoreStart, SavedObjectsClient, Logger, - RegisterDeprecationsConfig, + GetDeprecationsContext, DeprecationsDetails, } from 'src/core/server'; @@ -41,9 +41,9 @@ export const showWarningMessageIfTimelionSheetWasFound = async ( * * @link https://www.elastic.co/guide/en/kibana/master/timelion.html#timelion-deprecation **/ -export const getDeprecations: RegisterDeprecationsConfig['getDeprecations'] = async ({ +export async function getDeprecations({ savedObjectsClient, -}) => { +}: GetDeprecationsContext): Promise { const deprecations: DeprecationsDetails[] = []; const count = await getTimelionSheetsCount(savedObjectsClient); @@ -67,4 +67,4 @@ export const getDeprecations: RegisterDeprecationsConfig['getDeprecations'] = as } return deprecations; -}; +} diff --git a/x-pack/plugins/monitoring/server/deprecations.test.js b/x-pack/plugins/monitoring/server/deprecations.test.js index 7e9e3e1bcfbb..c384f6f4b136 100644 --- a/x-pack/plugins/monitoring/server/deprecations.test.js +++ b/x-pack/plugins/monitoring/server/deprecations.test.js @@ -16,8 +16,8 @@ describe('monitoring plugin deprecations', function () { beforeAll(function () { const deprecations = deprecationsModule({ rename, renameFromRoot }); - transformDeprecations = (settings, fromPath, deprecationHook = noop) => { - deprecations.forEach((deprecation) => deprecation(settings, fromPath, deprecationHook)); + transformDeprecations = (settings, fromPath, addDeprecation = noop) => { + deprecations.forEach((deprecation) => deprecation(settings, fromPath, addDeprecation)); }; }); @@ -31,9 +31,9 @@ describe('monitoring plugin deprecations', function () { }, }; - const deprecationHook = jest.fn(); - transformDeprecations(settings, fromPath, deprecationHook); - expect(deprecationHook).not.toHaveBeenCalled(); + const addDeprecation = jest.fn(); + transformDeprecations(settings, fromPath, addDeprecation); + expect(addDeprecation).not.toHaveBeenCalled(); }); it(`shouldn't log when cluster alerts are disabled`, function () { @@ -46,9 +46,9 @@ describe('monitoring plugin deprecations', function () { }, }; - const deprecationHook = jest.fn(); - transformDeprecations(settings, fromPath, deprecationHook); - expect(deprecationHook).not.toHaveBeenCalled(); + const addDeprecation = jest.fn(); + transformDeprecations(settings, fromPath, addDeprecation); + expect(addDeprecation).not.toHaveBeenCalled(); }); it(`shouldn't log when email_address is specified`, function () { @@ -62,9 +62,9 @@ describe('monitoring plugin deprecations', function () { }, }; - const deprecationHook = jest.fn(); - transformDeprecations(settings, fromPath, deprecationHook); - expect(deprecationHook).not.toHaveBeenCalled(); + const addDeprecation = jest.fn(); + transformDeprecations(settings, fromPath, addDeprecation); + expect(addDeprecation).not.toHaveBeenCalled(); }); it(`should log when email_address is missing, but alerts/notifications are both enabled`, function () { @@ -77,9 +77,9 @@ describe('monitoring plugin deprecations', function () { }, }; - const deprecationHook = jest.fn(); - transformDeprecations(settings, fromPath, deprecationHook); - expect(deprecationHook).toHaveBeenCalled(); + const addDeprecation = jest.fn(); + transformDeprecations(settings, fromPath, addDeprecation); + expect(addDeprecation).toHaveBeenCalled(); }); }); @@ -87,65 +87,65 @@ describe('monitoring plugin deprecations', function () { it('logs a warning if elasticsearch.username is set to "elastic"', () => { const settings = { elasticsearch: { username: 'elastic' } }; - const deprecationHook = jest.fn(); - transformDeprecations(settings, fromPath, deprecationHook); - expect(deprecationHook).toHaveBeenCalled(); + const addDeprecation = jest.fn(); + transformDeprecations(settings, fromPath, addDeprecation); + expect(addDeprecation).toHaveBeenCalled(); }); it('logs a warning if elasticsearch.username is set to "kibana"', () => { const settings = { elasticsearch: { username: 'kibana' } }; - const deprecationHook = jest.fn(); - transformDeprecations(settings, fromPath, deprecationHook); - expect(deprecationHook).toHaveBeenCalled(); + const addDeprecation = jest.fn(); + transformDeprecations(settings, fromPath, addDeprecation); + expect(addDeprecation).toHaveBeenCalled(); }); it('does not log a warning if elasticsearch.username is set to something besides "elastic" or "kibana"', () => { const settings = { elasticsearch: { username: 'otheruser' } }; - const deprecationHook = jest.fn(); - transformDeprecations(settings, fromPath, deprecationHook); - expect(deprecationHook).not.toHaveBeenCalled(); + const addDeprecation = jest.fn(); + transformDeprecations(settings, fromPath, addDeprecation); + expect(addDeprecation).not.toHaveBeenCalled(); }); it('does not log a warning if elasticsearch.username is unset', () => { const settings = { elasticsearch: { username: undefined } }; - const deprecationHook = jest.fn(); - transformDeprecations(settings, fromPath, deprecationHook); - expect(deprecationHook).not.toHaveBeenCalled(); + const addDeprecation = jest.fn(); + transformDeprecations(settings, fromPath, addDeprecation); + expect(addDeprecation).not.toHaveBeenCalled(); }); it('logs a warning if ssl.key is set and ssl.certificate is not', () => { const settings = { elasticsearch: { ssl: { key: '' } } }; - const deprecationHook = jest.fn(); - transformDeprecations(settings, fromPath, deprecationHook); - expect(deprecationHook).toHaveBeenCalled(); + const addDeprecation = jest.fn(); + transformDeprecations(settings, fromPath, addDeprecation); + expect(addDeprecation).toHaveBeenCalled(); }); it('logs a warning if ssl.certificate is set and ssl.key is not', () => { const settings = { elasticsearch: { ssl: { certificate: '' } } }; - const deprecationHook = jest.fn(); - transformDeprecations(settings, fromPath, deprecationHook); - expect(deprecationHook).toHaveBeenCalled(); + const addDeprecation = jest.fn(); + transformDeprecations(settings, fromPath, addDeprecation); + expect(addDeprecation).toHaveBeenCalled(); }); it('does not log a warning if both ssl.key and ssl.certificate are set', () => { const settings = { elasticsearch: { ssl: { key: '', certificate: '' } } }; - const deprecationHook = jest.fn(); - transformDeprecations(settings, fromPath, deprecationHook); - expect(deprecationHook).not.toHaveBeenCalled(); + const addDeprecation = jest.fn(); + transformDeprecations(settings, fromPath, addDeprecation); + expect(addDeprecation).not.toHaveBeenCalled(); }); }); describe('xpack_api_polling_frequency_millis', () => { it('should call rename for this renamed config key', () => { const settings = { xpack_api_polling_frequency_millis: 30000 }; - const deprecationHook = jest.fn(); - transformDeprecations(settings, fromPath, deprecationHook); + const addDeprecation = jest.fn(); + transformDeprecations(settings, fromPath, addDeprecation); expect(rename).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/monitoring/server/deprecations.ts b/x-pack/plugins/monitoring/server/deprecations.ts index 71e3891c3ad0..5ed6b0c32087 100644 --- a/x-pack/plugins/monitoring/server/deprecations.ts +++ b/x-pack/plugins/monitoring/server/deprecations.ts @@ -44,41 +44,41 @@ export const deprecations = ({ 'monitoring.ui.elasticsearch.logFetchCount' ), renameFromRoot('xpack.monitoring', 'monitoring'), - (config, fromPath, deprecationHook) => { + (config, fromPath, addDeprecation) => { const clusterAlertsEnabled = get(config, 'cluster_alerts.enabled'); const emailNotificationsEnabled = clusterAlertsEnabled && get(config, 'cluster_alerts.email_notifications.enabled'); if (emailNotificationsEnabled && !get(config, CLUSTER_ALERTS_ADDRESS_CONFIG_KEY)) { - deprecationHook({ + addDeprecation({ message: `Config key [${fromPath}.${CLUSTER_ALERTS_ADDRESS_CONFIG_KEY}] will be required for email notifications to work in 7.0."`, }); } return config; }, - (config, fromPath, deprecationHook) => { + (config, fromPath, addDeprecation) => { const es: Record = get(config, 'elasticsearch'); if (es) { if (es.username === 'elastic') { - deprecationHook({ + addDeprecation({ message: `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.`, }); } else if (es.username === 'kibana') { - deprecationHook({ + addDeprecation({ message: `Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.`, }); } } return config; }, - (config, fromPath, deprecationHook) => { + (config, fromPath, addDeprecation) => { const ssl: Record = get(config, 'elasticsearch.ssl'); if (ssl) { if (ssl.key !== undefined && ssl.certificate === undefined) { - deprecationHook({ + addDeprecation({ message: `Setting [${fromPath}.key] without [${fromPath}.certificate] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`, }); } else if (ssl.certificate !== undefined && ssl.key === undefined) { - deprecationHook({ + addDeprecation({ message: `Setting [${fromPath}.certificate] without [${fromPath}.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`, }); } diff --git a/x-pack/plugins/reporting/server/config/index.ts b/x-pack/plugins/reporting/server/config/index.ts index c537e03e9fa0..4b97dbc1e2a8 100644 --- a/x-pack/plugins/reporting/server/config/index.ts +++ b/x-pack/plugins/reporting/server/config/index.ts @@ -24,10 +24,10 @@ export const config: PluginConfigDescriptor = { unused('poll.jobCompletionNotifier.intervalErrorMultiplier'), unused('poll.jobsRefresh.intervalErrorMultiplier'), unused('kibanaApp'), - (settings, fromPath, deprecationHook) => { + (settings, fromPath, addDeprecation) => { const reporting = get(settings, fromPath); if (reporting?.index) { - deprecationHook({ + addDeprecation({ message: `"${fromPath}.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details`, }); } diff --git a/x-pack/plugins/security/server/config_deprecations.ts b/x-pack/plugins/security/server/config_deprecations.ts index 0005ec70906c..eae996fe2a5c 100644 --- a/x-pack/plugins/security/server/config_deprecations.ts +++ b/x-pack/plugins/security/server/config_deprecations.ts @@ -22,9 +22,9 @@ export const securityConfigDeprecationProvider: ConfigDeprecationProvider = ({ unused('authorization.legacyFallback.enabled'), unused('authc.saml.maxRedirectURLSize'), // Deprecation warning for the old array-based format of `xpack.security.authc.providers`. - (settings, fromPath, deprecationHook) => { + (settings, fromPath, addDeprecation) => { if (Array.isArray(settings?.xpack?.security?.authc?.providers)) { - deprecationHook({ + addDeprecation({ message: 'Defining `xpack.security.authc.providers` as an array of provider types is deprecated. Use extended `object` format instead.', }); @@ -32,7 +32,7 @@ export const securityConfigDeprecationProvider: ConfigDeprecationProvider = ({ return settings; }, - (settings, fromPath, deprecationHook) => { + (settings, fromPath, addDeprecation) => { const hasProviderType = (providerType: string) => { const providers = settings?.xpack?.security?.authc?.providers; if (Array.isArray(providers)) { @@ -45,20 +45,20 @@ export const securityConfigDeprecationProvider: ConfigDeprecationProvider = ({ }; if (hasProviderType('basic') && hasProviderType('token')) { - deprecationHook({ + addDeprecation({ message: 'Enabling both `basic` and `token` authentication providers in `xpack.security.authc.providers` is deprecated. Login page will only use `token` provider.', }); } return settings; }, - (settings, fromPath, deprecationHook) => { + (settings, fromPath, addDeprecation) => { const samlProviders = (settings?.xpack?.security?.authc?.providers?.saml ?? {}) as Record< string, any >; if (Object.values(samlProviders).find((provider) => !!provider.maxRedirectURLSize)) { - deprecationHook({ + addDeprecation({ message: '`xpack.security.authc.providers.saml..maxRedirectURLSize` is deprecated and is no longer used', }); @@ -66,9 +66,9 @@ export const securityConfigDeprecationProvider: ConfigDeprecationProvider = ({ return settings; }, - (settings, fromPath, deprecationHook) => { + (settings, fromPath, addDeprecation) => { if (settings?.xpack?.security?.enabled === false) { - deprecationHook({ + addDeprecation({ message: 'Disabling the security plugin (`xpack.security.enabled`) will not be supported in the next major version (8.0). ' + 'To turn off security features, disable them in Elasticsearch instead.', diff --git a/x-pack/plugins/spaces/server/config.ts b/x-pack/plugins/spaces/server/config.ts index 5ad13aa38815..ed541fda6c29 100644 --- a/x-pack/plugins/spaces/server/config.ts +++ b/x-pack/plugins/spaces/server/config.ts @@ -24,9 +24,9 @@ export function createConfig$(context: PluginInitializerContext) { return context.config.create>(); } -const disabledDeprecation: ConfigDeprecation = (config, fromPath, deprecationHook) => { +const disabledDeprecation: ConfigDeprecation = (config, fromPath, addDeprecation) => { if (config.xpack?.spaces?.enabled === false) { - deprecationHook({ + addDeprecation({ message: `Disabling the spaces plugin (xpack.spaces.enabled) will not be supported in the next major version (8.0)`, }); } diff --git a/x-pack/plugins/task_manager/server/index.ts b/x-pack/plugins/task_manager/server/index.ts index 02d114fda1d7..a34f5a87fddb 100644 --- a/x-pack/plugins/task_manager/server/index.ts +++ b/x-pack/plugins/task_manager/server/index.ts @@ -31,16 +31,16 @@ export { export const config: PluginConfigDescriptor = { schema: configSchema, deprecations: () => [ - (settings, fromPath, deprecationHook) => { + (settings, fromPath, addDeprecation) => { const taskManager = get(settings, fromPath); if (taskManager?.index) { - deprecationHook({ + addDeprecation({ documentationUrl: 'https://ela.st/kbn-remove-legacy-multitenancy', message: `"${fromPath}.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details`, }); } if (taskManager?.max_workers > MAX_WORKERS_LIMIT) { - deprecationHook({ + addDeprecation({ message: `setting "${fromPath}.max_workers" (${taskManager?.max_workers}) greater than ${MAX_WORKERS_LIMIT} is deprecated. Values greater than ${MAX_WORKERS_LIMIT} will not be supported starting in 8.0.`, }); } From 94d5129142f3c37741f5f97b3ca47a4b1043287c Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 25 Mar 2021 18:00:48 +0200 Subject: [PATCH 14/23] add functional tests --- .../deprecations/deprecations_client.test.ts | 136 ++++++++++++++++-- .../deprecations/deprecations_client.ts | 48 +++++-- .../deprecations/deprecations_factory.test.ts | 4 +- src/core/server/deprecations/index.ts | 1 + src/core/server/deprecations/routes/get.ts | 11 +- src/core/server/deprecations/types.ts | 4 + src/core/server/types.ts | 2 +- .../deprecations_service/data.json | 14 ++ .../deprecations_service/mappings.json | 18 +++ test/plugin_functional/config.ts | 22 +-- .../core_plugin_deprecations/kibana.json | 8 ++ .../core_plugin_deprecations/package.json | 14 ++ .../core_plugin_deprecations/server/config.ts | 41 ++++++ .../core_plugin_deprecations/server/index.ts | 12 ++ .../core_plugin_deprecations/server/plugin.ts | 56 ++++++++ .../core_plugin_deprecations/tsconfig.json | 18 +++ .../test_suites/core/deprecations.ts | 93 ++++++++++++ .../test_suites/core/index.ts | 1 + 18 files changed, 461 insertions(+), 42 deletions(-) create mode 100644 test/functional/fixtures/es_archiver/deprecations_service/data.json create mode 100644 test/functional/fixtures/es_archiver/deprecations_service/mappings.json create mode 100644 test/plugin_functional/plugins/core_plugin_deprecations/kibana.json create mode 100644 test/plugin_functional/plugins/core_plugin_deprecations/package.json create mode 100644 test/plugin_functional/plugins/core_plugin_deprecations/server/config.ts create mode 100644 test/plugin_functional/plugins/core_plugin_deprecations/server/index.ts create mode 100644 test/plugin_functional/plugins/core_plugin_deprecations/server/plugin.ts create mode 100644 test/plugin_functional/plugins/core_plugin_deprecations/tsconfig.json create mode 100644 test/plugin_functional/test_suites/core/deprecations.ts diff --git a/src/core/public/deprecations/deprecations_client.test.ts b/src/core/public/deprecations/deprecations_client.test.ts index e4dccc862631..1138f043d948 100644 --- a/src/core/public/deprecations/deprecations_client.test.ts +++ b/src/core/public/deprecations/deprecations_client.test.ts @@ -8,13 +8,14 @@ import { httpServiceMock } from '../http/http_service.mock'; import { DeprecationsClient } from './deprecations_client'; +import type { DomainDeprecationDetails } from '../../server/types'; describe('DeprecationsClient', () => { const http = httpServiceMock.createSetupContract(); const mockDeprecationsInfo = [ - { pluginId: 'testPluginId-1' }, - { pluginId: 'testPluginId-1' }, - { pluginId: 'testPluginId-2' }, + { domainId: 'testPluginId-1' }, + { domainId: 'testPluginId-1' }, + { domainId: 'testPluginId-2' }, ]; beforeEach(() => { @@ -36,18 +37,18 @@ describe('DeprecationsClient', () => { }); describe('getDeprecations', () => { - it('returns deprecations for a single pluginId', async () => { + it('returns deprecations for a single domainId', async () => { const deprecationsClient = new DeprecationsClient({ http }); const deprecations = await deprecationsClient.getDeprecations('testPluginId-1'); expect(deprecations.length).toBe(2); expect(deprecations).toEqual([ - { pluginId: 'testPluginId-1' }, - { pluginId: 'testPluginId-1' }, + { domainId: 'testPluginId-1' }, + { domainId: 'testPluginId-1' }, ]); }); - it('returns [] if the pluginId does not have any deprecations', async () => { + it('returns [] if the domainId does not have any deprecations', async () => { const deprecationsClient = new DeprecationsClient({ http }); const deprecations = await deprecationsClient.getDeprecations('testPluginId-4'); @@ -57,10 +58,10 @@ describe('DeprecationsClient', () => { it('calls the fetch api', async () => { const deprecationsClient = new DeprecationsClient({ http }); http.fetch.mockResolvedValueOnce({ - deprecationsInfo: [{ pluginId: 'testPluginId-1' }, { pluginId: 'testPluginId-1' }], + deprecationsInfo: [{ domainId: 'testPluginId-1' }, { domainId: 'testPluginId-1' }], }); http.fetch.mockResolvedValueOnce({ - deprecationsInfo: [{ pluginId: 'testPluginId-2' }, { pluginId: 'testPluginId-2' }], + deprecationsInfo: [{ domainId: 'testPluginId-2' }, { domainId: 'testPluginId-2' }], }); const results = [ ...(await deprecationsClient.getDeprecations('testPluginId-1')), @@ -69,11 +70,120 @@ describe('DeprecationsClient', () => { expect(http.fetch).toBeCalledTimes(2); expect(results).toEqual([ - { pluginId: 'testPluginId-1' }, - { pluginId: 'testPluginId-1' }, - { pluginId: 'testPluginId-2' }, - { pluginId: 'testPluginId-2' }, + { domainId: 'testPluginId-1' }, + { domainId: 'testPluginId-1' }, + { domainId: 'testPluginId-2' }, + { domainId: 'testPluginId-2' }, ]); }); }); + + describe('isDeprecationResolvable', () => { + it('returns true if deprecation has correctiveActions.api', async () => { + const deprecationsClient = new DeprecationsClient({ http }); + const mockDeprecationDetails: DomainDeprecationDetails = { + domainId: 'testPluginId-1', + message: 'some-message', + level: 'warning', + correctiveActions: { + api: { + path: 'some-path', + method: 'POST', + }, + }, + }; + + const isResolvable = deprecationsClient.isDeprecationResolvable(mockDeprecationDetails); + + expect(isResolvable).toBe(true); + }); + + it('returns false if deprecation is missing correctiveActions.api', async () => { + const deprecationsClient = new DeprecationsClient({ http }); + const mockDeprecationDetails: DomainDeprecationDetails = { + domainId: 'testPluginId-1', + message: 'some-message', + level: 'warning', + correctiveActions: {}, + }; + + const isResolvable = deprecationsClient.isDeprecationResolvable(mockDeprecationDetails); + + expect(isResolvable).toBe(false); + }); + }); + + describe('resolveDepreaction', () => { + it('fails if deprecation is not resolvable', async () => { + const deprecationsClient = new DeprecationsClient({ http }); + const mockDeprecationDetails: DomainDeprecationDetails = { + domainId: 'testPluginId-1', + message: 'some-message', + level: 'warning', + correctiveActions: {}, + }; + const result = await deprecationsClient.resolveDepreaction(mockDeprecationDetails); + + expect(result).toEqual({ + status: 'fail', + payload: 'deprecation has no correctiveAction via api.', + }); + }); + + it('fetches the deprecation api', async () => { + const deprecationsClient = new DeprecationsClient({ http }); + const mockPayload = {}; + const mockDeprecationDetails: DomainDeprecationDetails = { + domainId: 'testPluginId-1', + message: 'some-message', + level: 'warning', + correctiveActions: { + api: { + path: 'some-path', + method: 'POST', + body: { + extra_param: 123, + }, + }, + }, + }; + http.fetch.mockResolvedValue(mockPayload); + const result = await deprecationsClient.resolveDepreaction(mockDeprecationDetails); + + expect(http.fetch).toBeCalledTimes(1); + expect(http.fetch).toBeCalledWith({ + path: 'some-path', + method: 'POST', + asSystemRequest: true, + body: JSON.stringify({ + extra_param: 123, + deprecationDetails: { domainId: 'testPluginId-1' }, + }), + }); + expect(result).toEqual({ status: 'ok', payload: mockPayload }); + }); + + it('fails when fetch fails', async () => { + const deprecationsClient = new DeprecationsClient({ http }); + const mockPayload = new Error('Failed to fetch'); + const mockDeprecationDetails: DomainDeprecationDetails = { + domainId: 'testPluginId-1', + message: 'some-message', + level: 'warning', + correctiveActions: { + api: { + path: 'some-path', + method: 'POST', + body: { + extra_param: 123, + }, + }, + }, + }; + http.fetch.mockRejectedValue(mockPayload); + const result = await deprecationsClient.resolveDepreaction(mockDeprecationDetails); + + expect(result).toEqual({ status: 'fail', payload: mockPayload }); + }); + }); }); diff --git a/src/core/public/deprecations/deprecations_client.ts b/src/core/public/deprecations/deprecations_client.ts index 72f3c5140a8f..3e820a3adb4c 100644 --- a/src/core/public/deprecations/deprecations_client.ts +++ b/src/core/public/deprecations/deprecations_client.ts @@ -7,18 +7,9 @@ */ import type { HttpStart } from '../http'; -import type { DomainDeprecationDetails } from '../../server/types'; +import type { DomainDeprecationDetails, DeprecationsGetResponse } from '../../server/types'; -/** - * @internal - */ -interface DeprecationsGetResponse { - deprecationsInfo: DomainDeprecationDetails[]; -} - -/** - * @internal - */ +/* @internal */ export interface DeprecationsClientDeps { http: Pick; } @@ -48,4 +39,39 @@ export class DeprecationsClient { const deprecations = await this.fetchDeprecations(); return deprecations.filter((deprecation) => deprecation.domainId === domainId); }; + + public isDeprecationResolvable = (details: DomainDeprecationDetails) => { + return typeof details.correctiveActions.api === 'object'; + }; + + public resolveDepreaction = async (details: DomainDeprecationDetails) => { + const { domainId, correctiveActions } = details; + // explicit check required for TS type guard + if (typeof correctiveActions.api !== 'object') { + return { + status: 'fail', + payload: 'deprecation has no correctiveAction via api.', + }; + } + + const { body, method, path } = correctiveActions.api; + try { + const payload = await this.http.fetch({ + path, + method, + asSystemRequest: true, + body: JSON.stringify({ + ...body, + deprecationDetails: { domainId }, + }), + }); + + return { status: 'ok', payload }; + } catch (err) { + return { + status: 'fail', + payload: err, + }; + } + }; } diff --git a/src/core/server/deprecations/deprecations_factory.test.ts b/src/core/server/deprecations/deprecations_factory.test.ts index 3b54b5c64bb1..8e54827eb204 100644 --- a/src/core/server/deprecations/deprecations_factory.test.ts +++ b/src/core/server/deprecations/deprecations_factory.test.ts @@ -122,7 +122,7 @@ describe('DeprecationsFactory', () => { { domainId, message: `Failed to get deprecations info for plugin "${domainId}".`, - level: 'warning', + level: 'fetch_error', correctiveActions: { manualSteps: ['Check Kibana server logs for error message.'], }, @@ -162,7 +162,7 @@ describe('DeprecationsFactory', () => { { domainId: 'anotherMockPlugin', message: `Failed to get deprecations info for plugin "anotherMockPlugin".`, - level: 'warning', + level: 'fetch_error', correctiveActions: { manualSteps: ['Check Kibana server logs for error message.'], }, diff --git a/src/core/server/deprecations/index.ts b/src/core/server/deprecations/index.ts index 8ece06f82643..c7d1a1380069 100644 --- a/src/core/server/deprecations/index.ts +++ b/src/core/server/deprecations/index.ts @@ -10,6 +10,7 @@ export type { DeprecationsDetails, GetDeprecationsContext, RegisterDeprecationsConfig, + DeprecationsGetResponse, } from './types'; export type { diff --git a/src/core/server/deprecations/routes/get.ts b/src/core/server/deprecations/routes/get.ts index 7408c14e1f9d..2836a132a4d5 100644 --- a/src/core/server/deprecations/routes/get.ts +++ b/src/core/server/deprecations/routes/get.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ import { IRouter } from '../../http'; -import { GetDeprecationsContext } from '../types'; +import { GetDeprecationsContext, DeprecationsGetResponse } from '../types'; import { DeprecationsFactory } from '../deprecations_factory'; interface RouteDependencies { @@ -26,12 +26,11 @@ export const registerGetRoute = (router: IRouter, { deprecationsFactory }: Route }; const deprecationsInfo = await deprecationsFactory.getAllDeprecations(dependencies); + const body: DeprecationsGetResponse = { + deprecationsInfo, + }; - return res.ok({ - body: { - deprecationsInfo, - }, - }); + return res.ok({ body }); } ); }; diff --git a/src/core/server/deprecations/types.ts b/src/core/server/deprecations/types.ts index 1a40b1410fe5..928007353236 100644 --- a/src/core/server/deprecations/types.ts +++ b/src/core/server/deprecations/types.ts @@ -61,3 +61,7 @@ export interface GetDeprecationsContext { esClient: IScopedClusterClient; savedObjectsClient: SavedObjectsClientContract; } + +export interface DeprecationsGetResponse { + deprecationsInfo: DomainDeprecationDetails[]; +} diff --git a/src/core/server/types.ts b/src/core/server/types.ts index 54dd9158fc86..ab1d6c6d95d0 100644 --- a/src/core/server/types.ts +++ b/src/core/server/types.ts @@ -37,7 +37,7 @@ export type { SavedObjectsClientContract, SavedObjectsNamespaceType, } from './saved_objects/types'; -export type { DomainDeprecationDetails } from './deprecations/types'; +export type { DomainDeprecationDetails, DeprecationsGetResponse } from './deprecations/types'; export * from './ui_settings/types'; export * from './legacy/types'; export type { EnvironmentMode, PackageInfo } from '@kbn/config'; diff --git a/test/functional/fixtures/es_archiver/deprecations_service/data.json b/test/functional/fixtures/es_archiver/deprecations_service/data.json new file mode 100644 index 000000000000..31ce5af20b46 --- /dev/null +++ b/test/functional/fixtures/es_archiver/deprecations_service/data.json @@ -0,0 +1,14 @@ +{ + "type": "doc", + "value": { + "index": ".kibana", + "id": "test-deprecations-plugin:ff3733a0-9fty-11e7-ahb3-3dcb94193fab", + "source": { + "type": "test-deprecations-plugin", + "updated_at": "2021-02-11T18:51:23.794Z", + "test-deprecations-plugin": { + "title": "Test saved object" + } + } + } +} diff --git a/test/functional/fixtures/es_archiver/deprecations_service/mappings.json b/test/functional/fixtures/es_archiver/deprecations_service/mappings.json new file mode 100644 index 000000000000..bcec9c93e30a --- /dev/null +++ b/test/functional/fixtures/es_archiver/deprecations_service/mappings.json @@ -0,0 +1,18 @@ +{ + "type": "index", + "value": { + "index": ".kibana", + "settings": { + "index": { + "number_of_shards": "1", + "number_of_replicas": "0" + } + }, + "mappings": { + "dynamic": "true", + "properties": { + "title": { "type": "text" } + } + } + } +} diff --git a/test/plugin_functional/config.ts b/test/plugin_functional/config.ts index fc747fcd71f1..0a43abbfe5a7 100644 --- a/test/plugin_functional/config.ts +++ b/test/plugin_functional/config.ts @@ -22,15 +22,16 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { return { testFiles: [ require.resolve('./test_suites/core'), - require.resolve('./test_suites/custom_visualizations'), - require.resolve('./test_suites/panel_actions'), - require.resolve('./test_suites/core_plugins'), - require.resolve('./test_suites/management'), - require.resolve('./test_suites/doc_views'), - require.resolve('./test_suites/application_links'), - require.resolve('./test_suites/data_plugin'), - require.resolve('./test_suites/saved_objects_management'), - require.resolve('./test_suites/saved_objects_hidden_type'), + + // require.resolve('./test_suites/custom_visualizations'), + // require.resolve('./test_suites/panel_actions'), + // require.resolve('./test_suites/core_plugins'), + // require.resolve('./test_suites/management'), + // require.resolve('./test_suites/doc_views'), + // require.resolve('./test_suites/application_links'), + // require.resolve('./test_suites/data_plugin'), + // require.resolve('./test_suites/saved_objects_management'), + // require.resolve('./test_suites/saved_objects_hidden_type'), ], services: { ...functionalConfig.get('services'), @@ -56,6 +57,9 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { // Required to load new platform plugins via `--plugin-path` flag. '--env.name=development', + '--corePluginDeprecations.oldProperty=hello', + '--corePluginDeprecations.secret=100', + '--corePluginDeprecations.noLongerUsed=still_using', ...plugins.map( (pluginDir) => `--plugin-path=${path.resolve(__dirname, 'plugins', pluginDir)}` ), diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/kibana.json b/test/plugin_functional/plugins/core_plugin_deprecations/kibana.json new file mode 100644 index 000000000000..bc251f97bea5 --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_deprecations/kibana.json @@ -0,0 +1,8 @@ +{ + "id": "corePluginDeprecations", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["corePluginDeprecations"], + "server": true, + "ui": false +} diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/package.json b/test/plugin_functional/plugins/core_plugin_deprecations/package.json new file mode 100644 index 000000000000..e658f0a25085 --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_deprecations/package.json @@ -0,0 +1,14 @@ +{ + "name": "core_plugin_deprecations", + "version": "1.0.0", + "main": "target/test/plugin_functional/plugins/core_plugin_deprecations", + "kibana": { + "version": "kibana", + "templateVersion": "1.0.0" + }, + "license": "SSPL-1.0 OR Elastic License 2.0", + "scripts": { + "kbn": "node ../../../../scripts/kbn.js", + "build": "rm -rf './target' && ../../../../node_modules/.bin/tsc" + } +} \ No newline at end of file diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/server/config.ts b/test/plugin_functional/plugins/core_plugin_deprecations/server/config.ts new file mode 100644 index 000000000000..db4288d26a3d --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_deprecations/server/config.ts @@ -0,0 +1,41 @@ +/* + * 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 { schema, TypeOf } from '@kbn/config-schema'; +import { get } from 'lodash'; +import type { PluginConfigDescriptor } from 'kibana/server'; +import type { ConfigDeprecation } from '@kbn/config'; + +const configSchema = schema.object({ + newProperty: schema.maybe(schema.string({ defaultValue: 'Some string' })), + noLongerUsed: schema.maybe(schema.string()), + secret: schema.maybe(schema.number({ defaultValue: 42 })), +}); + +type ConfigType = TypeOf; + +const configSecretDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { + if (get(settings, 'corePluginDeprecations.secret') !== 42) { + addDeprecation({ + documentationUrl: 'config-secret-doc-url', + message: + 'Kibana plugin funcitonal tests will no longer allow corePluginDeprecations.secret ' + + 'config to be set to anything except 42.', + }); + } + return settings; +}; + +export const config: PluginConfigDescriptor = { + schema: configSchema, + deprecations: ({ rename, unused }) => [ + rename('oldProperty', 'newProperty'), + unused('noLongerUsed'), + configSecretDeprecation, + ], +}; diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/server/index.ts b/test/plugin_functional/plugins/core_plugin_deprecations/server/index.ts new file mode 100644 index 000000000000..1968c011a327 --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_deprecations/server/index.ts @@ -0,0 +1,12 @@ +/* + * 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 { CorePluginDeprecationsPlugin } from './plugin'; + +export { config } from './config'; +export const plugin = () => new CorePluginDeprecationsPlugin(); diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/server/plugin.ts b/test/plugin_functional/plugins/core_plugin_deprecations/server/plugin.ts new file mode 100644 index 000000000000..a205adaeb4df --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_deprecations/server/plugin.ts @@ -0,0 +1,56 @@ +/* + * 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 { Plugin, CoreSetup, GetDeprecationsContext, DeprecationsDetails } from 'kibana/server'; + +async function getDeprecations({ + savedObjectsClient, +}: GetDeprecationsContext): Promise { + const deprecations: DeprecationsDetails[] = []; + const { total } = await savedObjectsClient.find({ type: 'test-deprecations-plugin', perPage: 1 }); + + deprecations.push({ + message: `CorePluginDeprecationsPlugin is a deprecated feature for testing.`, + documentationUrl: 'test-url', + level: 'warning', + correctiveActions: { + manualSteps: ['Step a', 'Step b'], + }, + }); + + if (total > 0) { + deprecations.push({ + message: `SavedObject test-deprecations-plugin is still being used.`, + documentationUrl: 'another-test-url', + level: 'critical', + correctiveActions: {}, + }); + } + + return deprecations; +} + +export class CorePluginDeprecationsPlugin implements Plugin { + public setup(core: CoreSetup, deps: {}) { + core.savedObjects.registerType({ + name: 'test-deprecations-plugin', + hidden: false, + namespaceType: 'single', + mappings: { + properties: { + title: { type: 'text' }, + }, + }, + }); + + core.deprecations.registerDeprecations({ getDeprecations }); + } + + public start() {} + public stop() {} +} diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/tsconfig.json b/test/plugin_functional/plugins/core_plugin_deprecations/tsconfig.json new file mode 100644 index 000000000000..3d9d8ca9451d --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_deprecations/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "server/**/*.ts", + "../../../../typings/**/*", + ], + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] +} diff --git a/test/plugin_functional/test_suites/core/deprecations.ts b/test/plugin_functional/test_suites/core/deprecations.ts new file mode 100644 index 000000000000..5dbf3064608c --- /dev/null +++ b/test/plugin_functional/test_suites/core/deprecations.ts @@ -0,0 +1,93 @@ +/* + * 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 expect from '@kbn/expect'; +import type { DeprecationsGetResponse } from 'src/core/server/types'; +import { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ getService }: PluginFunctionalProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('deprecations service', () => { + describe('GET /api/deprecations/', async () => { + it('returns registered config deprecations and feature deprecations', async () => { + const { body } = await supertest.get('/api/deprecations/').set('kbn-xsrf', 'true'); + + const { deprecationsInfo } = body as DeprecationsGetResponse; + expect(Array.isArray(deprecationsInfo)).to.be(true); + const corePluginDeprecations = deprecationsInfo.filter( + ({ domainId }) => domainId === 'corePluginDeprecations' + ); + + expect(corePluginDeprecations).to.eql([ + { + level: 'critical', + message: + '"corePluginDeprecations.oldProperty" is deprecated and has been replaced by "corePluginDeprecations.newProperty"', + correctiveActions: { + manualSteps: [ + 'Replace "corePluginDeprecations.oldProperty" in the kibana.yml file with "corePluginDeprecations.newProperty"', + ], + }, + domainId: 'corePluginDeprecations', + }, + { + level: 'critical', + message: 'corePluginDeprecations.noLongerUsed is deprecated and is no longer used', + correctiveActions: { + manualSteps: [ + 'Remove "corePluginDeprecations.noLongerUsed" from the kibana.yml file."', + ], + }, + domainId: 'corePluginDeprecations', + }, + { + level: 'critical', + message: + 'Kibana plugin funcitonal tests will no longer allow corePluginDeprecations.secret config to be set to anything except 42.', + correctiveActions: {}, + documentationUrl: 'config-secret-doc-url', + domainId: 'corePluginDeprecations', + }, + { + message: 'CorePluginDeprecationsPlugin is a deprecated feature for testing.', + documentationUrl: 'test-url', + level: 'warning', + correctiveActions: { + manualSteps: ['Step a', 'Step b'], + }, + domainId: 'corePluginDeprecations', + }, + ]); + }); + }); + + describe('registerDeprecations', () => { + before(() => esArchiver.load('../functional/fixtures/es_archiver/deprecations_service')); + after(() => esArchiver.unload('../functional/fixtures/es_archiver/deprecations_service')); + it('calls registered getDeprecations', async () => { + const { body } = await supertest.get('/api/deprecations/').set('kbn-xsrf', 'true'); + + const { deprecationsInfo } = body as DeprecationsGetResponse; + + const deprecation = deprecationsInfo.find( + ({ message }) => message === 'SavedObject test-deprecations-plugin is still being used.' + ); + + expect(deprecation).to.eql({ + message: 'SavedObject test-deprecations-plugin is still being used.', + documentationUrl: 'another-test-url', + level: 'critical', + correctiveActions: {}, + domainId: 'corePluginDeprecations', + }); + }); + }); + }); +} diff --git a/test/plugin_functional/test_suites/core/index.ts b/test/plugin_functional/test_suites/core/index.ts index 9baa1ab0b394..8591c2fdec8d 100644 --- a/test/plugin_functional/test_suites/core/index.ts +++ b/test/plugin_functional/test_suites/core/index.ts @@ -10,6 +10,7 @@ import { PluginFunctionalProviderContext } from '../../services'; export default function ({ loadTestFile }: PluginFunctionalProviderContext) { describe('core', function () { + loadTestFile(require.resolve('./deprecations')); loadTestFile(require.resolve('./route')); }); } From 50f62852f87a6b71aa529e349c584ec7babc7351 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 25 Mar 2021 18:17:58 +0200 Subject: [PATCH 15/23] udpate core public api --- .../deprecations/deprecations_client.ts | 19 ++++++++++++++++--- .../deprecations/deprecations_service.ts | 18 +++++++++++++++++- src/core/public/deprecations/index.ts | 1 + src/core/public/index.ts | 2 +- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/core/public/deprecations/deprecations_client.ts b/src/core/public/deprecations/deprecations_client.ts index 3e820a3adb4c..90300980a3f2 100644 --- a/src/core/public/deprecations/deprecations_client.ts +++ b/src/core/public/deprecations/deprecations_client.ts @@ -14,6 +14,17 @@ export interface DeprecationsClientDeps { http: Pick; } +/* @internal */ +export type ResolveDeprecationResponse = + | { + status: 'ok'; + payload: Payload; + } + | { + status: 'fail'; + payload: string | Error; + }; + export class DeprecationsClient { private readonly http: Pick; constructor({ http }: DeprecationsClientDeps) { @@ -44,19 +55,21 @@ export class DeprecationsClient { return typeof details.correctiveActions.api === 'object'; }; - public resolveDepreaction = async (details: DomainDeprecationDetails) => { + public resolveDepreaction = async ( + details: DomainDeprecationDetails + ): Promise> => { const { domainId, correctiveActions } = details; // explicit check required for TS type guard if (typeof correctiveActions.api !== 'object') { return { status: 'fail', - payload: 'deprecation has no correctiveAction via api.', + payload: new Error('deprecation has no correctiveAction via api.'), }; } const { body, method, path } = correctiveActions.api; try { - const payload = await this.http.fetch({ + const payload = await this.http.fetch({ path, method, asSystemRequest: true, diff --git a/src/core/public/deprecations/deprecations_service.ts b/src/core/public/deprecations/deprecations_service.ts index 13a29184a9e0..520341529e1d 100644 --- a/src/core/public/deprecations/deprecations_service.ts +++ b/src/core/public/deprecations/deprecations_service.ts @@ -8,7 +8,7 @@ import type { CoreService } from '../../types'; import type { HttpStart } from '../http'; -import { DeprecationsClient } from './deprecations_client'; +import { DeprecationsClient, ResolveDeprecationResponse } from './deprecations_client'; import type { DomainDeprecationDetails } from '../../server/types'; /** @@ -28,6 +28,20 @@ export interface DeprecationsServiceStart { * @param {string} domainId */ getDeprecations: (domainId: string) => Promise; + /** + * Returns a boolean if the pprovided deprecation can be automtically resolvable. + * + * @param {DomainDeprecationDetails} details + */ + isDeprecationResolvable: (details: DomainDeprecationDetails) => boolean; + /** + * Calls the correctiveActions.api to automatically resolve the depprecation. + * + * @param {DomainDeprecationDetails} details + */ + resolveDepreaction: ( + details: DomainDeprecationDetails + ) => Promise>; } export class DeprecationsService implements CoreService { @@ -39,6 +53,8 @@ export class DeprecationsService implements CoreService Date: Thu, 25 Mar 2021 18:23:13 +0200 Subject: [PATCH 16/23] update public docs --- ...tionsservicestart.isdeprecationresolvable.md | 13 +++++++++++++ ...ugin-core-public.deprecationsservicestart.md | 2 ++ ...precationsservicestart.resolvedepreaction.md | 13 +++++++++++++ .../core/public/kibana-plugin-core-public.md | 1 + ...in-core-public.resolvedeprecationresponse.md | 17 +++++++++++++++++ src/core/public/public.api.md | 13 +++++++++++++ 6 files changed, 59 insertions(+) create mode 100644 docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.resolvedeprecationresponse.md diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md new file mode 100644 index 000000000000..e67423bf2f8f --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) > [isDeprecationResolvable](./kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md) + +## DeprecationsServiceStart.isDeprecationResolvable property + +Returns a boolean if the pprovided deprecation can be automtically resolvable. + +Signature: + +```typescript +isDeprecationResolvable: (details: DomainDeprecationDetails) => boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md index 60f0ccce42fd..7f8c26d20502 100644 --- a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md @@ -18,4 +18,6 @@ export interface DeprecationsServiceStart | --- | --- | --- | | [getAllDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getalldeprecations.md) | () => Promise<DomainDeprecationDetails[]> | Grabs deprecations details for all domains. | | [getDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getdeprecations.md) | (domainId: string) => Promise<DomainDeprecationDetails[]> | Grabs deprecations for a specific domain. | +| [isDeprecationResolvable](./kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md) | (details: DomainDeprecationDetails) => boolean | Returns a boolean if the pprovided deprecation can be automtically resolvable. | +| [resolveDepreaction](./kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md) | <Payload = unknown>(details: DomainDeprecationDetails) => Promise<ResolveDeprecationResponse<Payload>> | Calls the correctiveActions.api to automatically resolve the depprecation. | diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md new file mode 100644 index 000000000000..158a91e2956c --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) > [resolveDepreaction](./kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md) + +## DeprecationsServiceStart.resolveDepreaction property + +Calls the correctiveActions.api to automatically resolve the depprecation. + +Signature: + +```typescript +resolveDepreaction: (details: DomainDeprecationDetails) => Promise>; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index 695551802c1e..32f17d5488f6 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -165,6 +165,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [PublicAppMetaInfo](./kibana-plugin-core-public.publicappmetainfo.md) | Public information about a registered app's [keywords](./kibana-plugin-core-public.appmeta.md) | | [PublicAppSearchDeepLinkInfo](./kibana-plugin-core-public.publicappsearchdeeplinkinfo.md) | Public information about a registered app's [searchDeepLinks](./kibana-plugin-core-public.appsearchdeeplink.md) | | [PublicUiSettingsParams](./kibana-plugin-core-public.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) exposed to the client-side. | +| [ResolveDeprecationResponse](./kibana-plugin-core-public.resolvedeprecationresponse.md) | | | [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value | | [SavedObjectAttributeSingle](./kibana-plugin-core-public.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | | [SavedObjectsClientContract](./kibana-plugin-core-public.savedobjectsclientcontract.md) | SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-core-public.savedobjectsclient.md) | diff --git a/docs/development/core/public/kibana-plugin-core-public.resolvedeprecationresponse.md b/docs/development/core/public/kibana-plugin-core-public.resolvedeprecationresponse.md new file mode 100644 index 000000000000..cda6c985de26 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.resolvedeprecationresponse.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ResolveDeprecationResponse](./kibana-plugin-core-public.resolvedeprecationresponse.md) + +## ResolveDeprecationResponse type + +Signature: + +```typescript +export declare type ResolveDeprecationResponse = { + status: 'ok'; + payload: Payload; +} | { + status: 'fail'; + payload: string | Error; +}; +``` diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 306d4eb84402..eb7e9f925b25 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -479,6 +479,8 @@ export interface DeprecationsServiceStart { // Warning: (ae-forgotten-export) The symbol "DomainDeprecationDetails" needs to be exported by the entry point index.d.ts getAllDeprecations: () => Promise; getDeprecations: (domainId: string) => Promise; + isDeprecationResolvable: (details: DomainDeprecationDetails) => boolean; + resolveDepreaction: (details: DomainDeprecationDetails) => Promise>; } // @public (undocumented) @@ -1082,6 +1084,17 @@ export type PublicAppSearchDeepLinkInfo = Omit; +// Warning: (ae-missing-release-tag) "ResolveDeprecationResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ResolveDeprecationResponse = { + status: 'ok'; + payload: Payload; +} | { + status: 'fail'; + payload: string | Error; +}; + // Warning: (ae-missing-release-tag) "SavedObject" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) From 446c5044a0908546d90d1b58c4e68fd284859e30 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 25 Mar 2021 18:57:12 +0200 Subject: [PATCH 17/23] fix type check --- src/core/public/deprecations/deprecations_service.mock.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/public/deprecations/deprecations_service.mock.ts b/src/core/public/deprecations/deprecations_service.mock.ts index 5fc554ed9746..2c54799d5d45 100644 --- a/src/core/public/deprecations/deprecations_service.mock.ts +++ b/src/core/public/deprecations/deprecations_service.mock.ts @@ -13,6 +13,8 @@ import type { DeprecationsServiceStart } from './deprecations_service'; const createServiceMock = (): jest.Mocked => ({ getAllDeprecations: jest.fn().mockResolvedValue([]), getDeprecations: jest.fn().mockResolvedValue([]), + isDeprecationResolvable: jest.fn().mockReturnValue(false), + resolveDepreaction: jest.fn().mockResolvedValue({ status: 'ok', payload: {} }), }); const createMock = () => { From ca7f6caeb4fc26ac293d52a2fdf204ce2c083a2e Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 25 Mar 2021 19:18:15 +0200 Subject: [PATCH 18/23] update docs --- ...onsservicestart.isdeprecationresolvable.md | 2 +- ...in-core-public.deprecationsservicestart.md | 4 +- ...ecationsservicestart.resolvedepreaction.md | 6 +-- .../deprecations/deprecations_client.test.ts | 8 +-- .../deprecations/deprecations_client.ts | 2 +- .../deprecations/deprecations_service.mock.ts | 2 +- .../deprecations/deprecations_service.ts | 6 +-- src/core/public/public.api.md | 2 +- .../deprecations/deprecations_service.ts | 52 +++++++++++++++++++ 9 files changed, 68 insertions(+), 16 deletions(-) diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md index e67423bf2f8f..842761f6b7ce 100644 --- a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md @@ -4,7 +4,7 @@ ## DeprecationsServiceStart.isDeprecationResolvable property -Returns a boolean if the pprovided deprecation can be automtically resolvable. +Returns a boolean if the provided deprecation can be automatically resolvable. Signature: diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md index 7f8c26d20502..81f3ba181efc 100644 --- a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md @@ -18,6 +18,6 @@ export interface DeprecationsServiceStart | --- | --- | --- | | [getAllDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getalldeprecations.md) | () => Promise<DomainDeprecationDetails[]> | Grabs deprecations details for all domains. | | [getDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getdeprecations.md) | (domainId: string) => Promise<DomainDeprecationDetails[]> | Grabs deprecations for a specific domain. | -| [isDeprecationResolvable](./kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md) | (details: DomainDeprecationDetails) => boolean | Returns a boolean if the pprovided deprecation can be automtically resolvable. | -| [resolveDepreaction](./kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md) | <Payload = unknown>(details: DomainDeprecationDetails) => Promise<ResolveDeprecationResponse<Payload>> | Calls the correctiveActions.api to automatically resolve the depprecation. | +| [isDeprecationResolvable](./kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md) | (details: DomainDeprecationDetails) => boolean | Returns a boolean if the provided deprecation can be automatically resolvable. | +| [resolveDeprecation](./kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md) | <Payload = unknown>(details: DomainDeprecationDetails) => Promise<ResolveDeprecationResponse<Payload>> | Calls the correctiveActions.api to automatically resolve the depprecation. | diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md index 158a91e2956c..1481e674bec4 100644 --- a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md @@ -1,13 +1,13 @@ -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) > [resolveDepreaction](./kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md) +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) > [resolveDeprecation](./kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md) -## DeprecationsServiceStart.resolveDepreaction property +## DeprecationsServiceStart.resolveDeprecation property Calls the correctiveActions.api to automatically resolve the depprecation. Signature: ```typescript -resolveDepreaction: (details: DomainDeprecationDetails) => Promise>; +resolveDeprecation: (details: DomainDeprecationDetails) => Promise>; ``` diff --git a/src/core/public/deprecations/deprecations_client.test.ts b/src/core/public/deprecations/deprecations_client.test.ts index 1138f043d948..2436f0fcfcc2 100644 --- a/src/core/public/deprecations/deprecations_client.test.ts +++ b/src/core/public/deprecations/deprecations_client.test.ts @@ -113,7 +113,7 @@ describe('DeprecationsClient', () => { }); }); - describe('resolveDepreaction', () => { + describe('resolveDeprecation', () => { it('fails if deprecation is not resolvable', async () => { const deprecationsClient = new DeprecationsClient({ http }); const mockDeprecationDetails: DomainDeprecationDetails = { @@ -122,7 +122,7 @@ describe('DeprecationsClient', () => { level: 'warning', correctiveActions: {}, }; - const result = await deprecationsClient.resolveDepreaction(mockDeprecationDetails); + const result = await deprecationsClient.resolveDeprecation(mockDeprecationDetails); expect(result).toEqual({ status: 'fail', @@ -148,7 +148,7 @@ describe('DeprecationsClient', () => { }, }; http.fetch.mockResolvedValue(mockPayload); - const result = await deprecationsClient.resolveDepreaction(mockDeprecationDetails); + const result = await deprecationsClient.resolveDeprecation(mockDeprecationDetails); expect(http.fetch).toBeCalledTimes(1); expect(http.fetch).toBeCalledWith({ @@ -181,7 +181,7 @@ describe('DeprecationsClient', () => { }, }; http.fetch.mockRejectedValue(mockPayload); - const result = await deprecationsClient.resolveDepreaction(mockDeprecationDetails); + const result = await deprecationsClient.resolveDeprecation(mockDeprecationDetails); expect(result).toEqual({ status: 'fail', payload: mockPayload }); }); diff --git a/src/core/public/deprecations/deprecations_client.ts b/src/core/public/deprecations/deprecations_client.ts index 90300980a3f2..bbc754904366 100644 --- a/src/core/public/deprecations/deprecations_client.ts +++ b/src/core/public/deprecations/deprecations_client.ts @@ -55,7 +55,7 @@ export class DeprecationsClient { return typeof details.correctiveActions.api === 'object'; }; - public resolveDepreaction = async ( + public resolveDeprecation = async ( details: DomainDeprecationDetails ): Promise> => { const { domainId, correctiveActions } = details; diff --git a/src/core/public/deprecations/deprecations_service.mock.ts b/src/core/public/deprecations/deprecations_service.mock.ts index 2c54799d5d45..5bcd52982d51 100644 --- a/src/core/public/deprecations/deprecations_service.mock.ts +++ b/src/core/public/deprecations/deprecations_service.mock.ts @@ -14,7 +14,7 @@ const createServiceMock = (): jest.Mocked => ({ getAllDeprecations: jest.fn().mockResolvedValue([]), getDeprecations: jest.fn().mockResolvedValue([]), isDeprecationResolvable: jest.fn().mockReturnValue(false), - resolveDepreaction: jest.fn().mockResolvedValue({ status: 'ok', payload: {} }), + resolveDeprecation: jest.fn().mockResolvedValue({ status: 'ok', payload: {} }), }); const createMock = () => { diff --git a/src/core/public/deprecations/deprecations_service.ts b/src/core/public/deprecations/deprecations_service.ts index 520341529e1d..2f9447412f38 100644 --- a/src/core/public/deprecations/deprecations_service.ts +++ b/src/core/public/deprecations/deprecations_service.ts @@ -29,7 +29,7 @@ export interface DeprecationsServiceStart { */ getDeprecations: (domainId: string) => Promise; /** - * Returns a boolean if the pprovided deprecation can be automtically resolvable. + * Returns a boolean if the provided deprecation can be automatically resolvable. * * @param {DomainDeprecationDetails} details */ @@ -39,7 +39,7 @@ export interface DeprecationsServiceStart { * * @param {DomainDeprecationDetails} details */ - resolveDepreaction: ( + resolveDeprecation: ( details: DomainDeprecationDetails ) => Promise>; } @@ -54,7 +54,7 @@ export class DeprecationsService implements CoreService Promise; getDeprecations: (domainId: string) => Promise; isDeprecationResolvable: (details: DomainDeprecationDetails) => boolean; - resolveDepreaction: (details: DomainDeprecationDetails) => Promise>; + resolveDeprecation: (details: DomainDeprecationDetails) => Promise>; } // @public (undocumented) diff --git a/src/core/server/deprecations/deprecations_service.ts b/src/core/server/deprecations/deprecations_service.ts index acc6c20c61b8..b2dafeb16d6d 100644 --- a/src/core/server/deprecations/deprecations_service.ts +++ b/src/core/server/deprecations/deprecations_service.ts @@ -23,6 +23,9 @@ import { registerRoutes } from './routes'; * if the deployment is using these features. Allowing for a user tailored experience * for upgrading the stack version. * + * The Deprecation service is consumed by the upgrade assistant to assist with the upgrade + * experience. + * * @example * ```ts * import { DeprecationsDetails, GetDeprecationsContext, CoreSetup } from 'src/core/server'; @@ -50,6 +53,18 @@ import { registerRoutes } from './routes'; * }); * } * + * deprecations.push({ + * message: `You have ${count} Timelion worksheets. The Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard.`, + * documentationUrl: + * 'https://www.elastic.co/guide/en/kibana/current/create-panels-with-timelion.html', + * level: 'critical', + * correctiveActions: { + * api: { + * path: '', + * } + * }, + * }); + * * return deprecations; * } * @@ -61,6 +76,43 @@ import { registerRoutes } from './routes'; * } * ``` * + * If a deprecated feature can be resolved without manual user intervention. + * Using correctiveActions.api allows the Upgrade Assistant to use this api to correct the + * deprecation upon a user trigger. + * + * @example + * ``` + * core.deprecations.registerDeprecations({ getDeprecations: () => [ + * { + * "message": "User 'test_dashboard_user' is using a deprecated role: 'kibana_user'", + * "correctiveActions": { + * "api": { + * "path": "/internal/security/users/test_dashboard_user", + * "method": "POST", + * "body": { + * "username": "test_dashboard_user", + * "roles": [ + * "machine_learning_user", + * "enrich_user", + * "kibana_admin" + * ], + * "full_name": "Alison Goryachev", + * "email": "alisongoryachev@gmail.com", + * "metadata": {}, + * "enabled": true + * } + * }, + * "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." + * ] + * }, + * "documentationUrl": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-user.html", + * "level": "critical", + * "domainId": "security" + * }, + * ]}); + * ``` * @public */ export interface DeprecationsServiceSetup { From f16a7b8b0d0ec9540aeb3e9ba434fc4a6b86926b Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 25 Mar 2021 19:38:30 +0200 Subject: [PATCH 19/23] update docs --- ...in-core-server.deprecationsservicesetup.md | 36 ++++++++++- ...ationsservicesetup.registerdeprecations.md | 2 +- .../core/server/kibana-plugin-core-server.md | 2 +- .../deprecations/deprecations_service.ts | 63 +++++++------------ src/core/server/server.api.md | 4 +- 5 files changed, 62 insertions(+), 45 deletions(-) diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md index ff8e49f9bccb..7d9d3dcdda4d 100644 --- a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md @@ -6,6 +6,10 @@ The deprecations service provides a way for the Kibana platform to communicate deprecated features and configs with its users. These deprecations are only communicated if the deployment is using these features. Allowing for a user tailored experience for upgrading the stack version. +The Deprecation service is consumed by the upgrade assistant to assist with the upgrade experience. + +If a deprecated feature can be resolved without manual user intervention. Using correctiveActions.api allows the Upgrade Assistant to use this api to correct the deprecation upon a user trigger. + Signature: ```typescript @@ -23,6 +27,7 @@ async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecations const count = await getTimelionSheetsCount(savedObjectsClient); if (count > 0) { + // Example of a manual correctiveAction deprecations.push({ message: `You have ${count} Timelion worksheets. The Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard.`, documentationUrl: @@ -41,6 +46,35 @@ async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecations }); } + // Example of an api correctiveAction + deprecations.push({ + "message": "User 'test_dashboard_user' is using a deprecated role: 'kibana_user'", + "documentationUrl": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-user.html", + "level": "critical", + "correctiveActions": { + "api": { + "path": "/internal/security/users/test_dashboard_user", + "method": "POST", + "body": { + "username": "test_dashboard_user", + "roles": [ + "machine_learning_user", + "enrich_user", + "kibana_admin" + ], + "full_name": "Alison Goryachev", + "email": "alisongoryachev@gmail.com", + "metadata": {}, + "enabled": true + } + }, + "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." + ] + }, + }); + return deprecations; } @@ -57,5 +91,5 @@ export class Plugin() { | Property | Type | Description | | --- | --- | --- | -| [registerDeprecations](./kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md) | DeprecationsRegistry['registerDeprecations'] | | +| [registerDeprecations](./kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md) | (deprecationContext: RegisterDeprecationsConfig) => void | | diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md index f79e8875238b..07c2a3ad0ce5 100644 --- a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md @@ -7,5 +7,5 @@ Signature: ```typescript -registerDeprecations: DeprecationsRegistry['registerDeprecations']; +registerDeprecations: (deprecationContext: RegisterDeprecationsConfig) => void; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index f28cd1c5c844..faac8108de82 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -71,7 +71,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [DeprecationInfo](./kibana-plugin-core-server.deprecationinfo.md) | | | [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) | | | [DeprecationSettings](./kibana-plugin-core-server.deprecationsettings.md) | UiSettings deprecation field options. | -| [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) | The deprecations service provides a way for the Kibana platform to communicate deprecated features and configs with its users. These deprecations are only communicated if the deployment is using these features. Allowing for a user tailored experience for upgrading the stack version. | +| [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) | The deprecations service provides a way for the Kibana platform to communicate deprecated features and configs with its users. These deprecations are only communicated if the deployment is using these features. Allowing for a user tailored experience for upgrading the stack version.The Deprecation service is consumed by the upgrade assistant to assist with the upgrade experience.If a deprecated feature can be resolved without manual user intervention. Using correctiveActions.api allows the Upgrade Assistant to use this api to correct the deprecation upon a user trigger. | | [DiscoveredPlugin](./kibana-plugin-core-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. | | [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) | | | [ElasticsearchServiceStart](./kibana-plugin-core-server.elasticsearchservicestart.md) | | diff --git a/src/core/server/deprecations/deprecations_service.ts b/src/core/server/deprecations/deprecations_service.ts index b2dafeb16d6d..dfbf05bde503 100644 --- a/src/core/server/deprecations/deprecations_service.ts +++ b/src/core/server/deprecations/deprecations_service.ts @@ -6,16 +6,16 @@ * Side Public License, v 1. */ -import { CoreService } from '../../types'; import { DeprecationsFactory } from './deprecations_factory'; -import { DeprecationsRegistry } from './deprecations_registry'; +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'; -import { registerRoutes } from './routes'; /** * The deprecations service provides a way for the Kibana platform to communicate deprecated @@ -26,6 +26,10 @@ import { registerRoutes } from './routes'; * The Deprecation service is consumed by the upgrade assistant to assist with the upgrade * experience. * + * If a deprecated feature can be resolved without manual user intervention. + * Using correctiveActions.api allows the Upgrade Assistant to use this api to correct the + * deprecation upon a user trigger. + * * @example * ```ts * import { DeprecationsDetails, GetDeprecationsContext, CoreSetup } from 'src/core/server'; @@ -35,6 +39,7 @@ import { registerRoutes } from './routes'; * const count = await getTimelionSheetsCount(savedObjectsClient); * * if (count > 0) { + * // Example of a manual correctiveAction * deprecations.push({ * message: `You have ${count} Timelion worksheets. The Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard.`, * documentationUrl: @@ -53,38 +58,11 @@ import { registerRoutes } from './routes'; * }); * } * + * // Example of an api correctiveAction * deprecations.push({ - * message: `You have ${count} Timelion worksheets. The Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard.`, - * documentationUrl: - * 'https://www.elastic.co/guide/en/kibana/current/create-panels-with-timelion.html', - * level: 'critical', - * correctiveActions: { - * api: { - * path: '', - * } - * }, - * }); - * - * return deprecations; - * } - * - * - * export class Plugin() { - * setup: (core: CoreSetup) => { - * core.deprecations.registerDeprecations({ getDeprecations }); - * } - * } - * ``` - * - * If a deprecated feature can be resolved without manual user intervention. - * Using correctiveActions.api allows the Upgrade Assistant to use this api to correct the - * deprecation upon a user trigger. - * - * @example - * ``` - * core.deprecations.registerDeprecations({ getDeprecations: () => [ - * { * "message": "User 'test_dashboard_user' is using a deprecated role: 'kibana_user'", + * "documentationUrl": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-user.html", + * "level": "critical", * "correctiveActions": { * "api": { * "path": "/internal/security/users/test_dashboard_user", @@ -107,16 +85,23 @@ import { registerRoutes } from './routes'; * "Using Kibana role-mapping management, change all role-mappings which assing the kibana_user role to the kibana_admin role." * ] * }, - * "documentationUrl": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-user.html", - * "level": "critical", - * "domainId": "security" - * }, - * ]}); + * }); + * + * return deprecations; + * } + * + * + * export class Plugin() { + * setup: (core: CoreSetup) => { + * core.deprecations.registerDeprecations({ getDeprecations }); + * } + * } * ``` + * * @public */ export interface DeprecationsServiceSetup { - registerDeprecations: DeprecationsRegistry['registerDeprecations']; + registerDeprecations: (deprecationContext: RegisterDeprecationsConfig) => void; } /** @internal */ diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 6e867b67436c..f690ee0acfca 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -862,10 +862,8 @@ export interface DeprecationSettings { // @public export interface DeprecationsServiceSetup { - // Warning: (ae-forgotten-export) The symbol "DeprecationsRegistry" needs to be exported by the entry point index.d.ts - // // (undocumented) - registerDeprecations: DeprecationsRegistry['registerDeprecations']; + registerDeprecations: (deprecationContext: RegisterDeprecationsConfig) => void; } // @public From 0800f22bff75fddaf6ac483502b32ef03414d278 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 25 Mar 2021 20:10:31 +0200 Subject: [PATCH 20/23] fix test case --- src/core/public/deprecations/deprecations_client.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/public/deprecations/deprecations_client.test.ts b/src/core/public/deprecations/deprecations_client.test.ts index 2436f0fcfcc2..69b0be9b70f4 100644 --- a/src/core/public/deprecations/deprecations_client.test.ts +++ b/src/core/public/deprecations/deprecations_client.test.ts @@ -126,7 +126,7 @@ describe('DeprecationsClient', () => { expect(result).toEqual({ status: 'fail', - payload: 'deprecation has no correctiveAction via api.', + payload: new Error('deprecation has no correctiveAction via api.'), }); }); From a749ad73ec33e462f56e63324a3a83699079a379 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 30 Mar 2021 11:53:40 +0300 Subject: [PATCH 21/23] code review changes --- ...in-core-public.deprecationsservicestart.md | 2 +- ...cationsservicestart.resolvedeprecation.md} | 4 +- ...-core-public.resolvedeprecationresponse.md | 5 +- .../kbn-config/src/config_service.test.ts | 34 ++- packages/kbn-config/src/config_service.ts | 6 +- .../deprecation/deprecation_factory.test.ts | 188 ++++++++---- .../src/deprecation/deprecation_factory.ts | 12 +- .../deprecations/deprecations_client.test.ts | 22 +- .../deprecations/deprecations_client.ts | 34 +-- .../deprecations/deprecations_service.ts | 4 +- src/core/public/public.api.md | 7 +- .../deprecations/deprecations_factory.test.ts | 84 ++--- .../deprecations/deprecations_factory.ts | 6 +- .../deprecations/deprecations_service.mock.ts | 4 +- .../deprecations/deprecations_service.ts | 10 +- src/core/server/deprecations/routes/get.ts | 3 +- src/core/server/deprecations/types.ts | 2 +- src/core/server/plugins/plugin_context.ts | 2 +- .../deprecations_service/mappings.json | 287 +++++++++++++++++- test/plugin_functional/config.ts | 19 +- .../core_plugin_deprecations/package.json | 2 +- .../public/application.tsx | 19 ++ .../core_plugin_deprecations/public/index.ts | 19 ++ .../public/plugin.tsx | 40 +++ .../core_plugin_deprecations/server/plugin.ts | 3 +- .../core_plugin_deprecations/server/routes.ts | 45 +++ .../test_suites/core/deprecations.ts | 270 ++++++++++++---- 27 files changed, 865 insertions(+), 268 deletions(-) rename docs/development/core/public/{kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md => kibana-plugin-core-public.deprecationsservicestart.resolvedeprecation.md} (78%) create mode 100644 test/plugin_functional/plugins/core_plugin_deprecations/public/application.tsx create mode 100644 test/plugin_functional/plugins/core_plugin_deprecations/public/index.ts create mode 100644 test/plugin_functional/plugins/core_plugin_deprecations/public/plugin.tsx create mode 100644 test/plugin_functional/plugins/core_plugin_deprecations/server/routes.ts diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md index 81f3ba181efc..0d2c963ec554 100644 --- a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.md @@ -19,5 +19,5 @@ export interface DeprecationsServiceStart | [getAllDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getalldeprecations.md) | () => Promise<DomainDeprecationDetails[]> | Grabs deprecations details for all domains. | | [getDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getdeprecations.md) | (domainId: string) => Promise<DomainDeprecationDetails[]> | Grabs deprecations for a specific domain. | | [isDeprecationResolvable](./kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md) | (details: DomainDeprecationDetails) => boolean | Returns a boolean if the provided deprecation can be automatically resolvable. | -| [resolveDeprecation](./kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md) | <Payload = unknown>(details: DomainDeprecationDetails) => Promise<ResolveDeprecationResponse<Payload>> | Calls the correctiveActions.api to automatically resolve the depprecation. | +| [resolveDeprecation](./kibana-plugin-core-public.deprecationsservicestart.resolvedeprecation.md) | (details: DomainDeprecationDetails) => Promise<ResolveDeprecationResponse> | Calls the correctiveActions.api to automatically resolve the depprecation. | diff --git a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedeprecation.md similarity index 78% rename from docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md rename to docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedeprecation.md index 1481e674bec4..fae623fed3cc 100644 --- a/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md +++ b/docs/development/core/public/kibana-plugin-core-public.deprecationsservicestart.resolvedeprecation.md @@ -1,6 +1,6 @@ -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) > [resolveDeprecation](./kibana-plugin-core-public.deprecationsservicestart.resolvedepreaction.md) +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) > [resolveDeprecation](./kibana-plugin-core-public.deprecationsservicestart.resolvedeprecation.md) ## DeprecationsServiceStart.resolveDeprecation property @@ -9,5 +9,5 @@ Calls the correctiveActions.api to automatically resolve the depprecation. Signature: ```typescript -resolveDeprecation: (details: DomainDeprecationDetails) => Promise>; +resolveDeprecation: (details: DomainDeprecationDetails) => Promise; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.resolvedeprecationresponse.md b/docs/development/core/public/kibana-plugin-core-public.resolvedeprecationresponse.md index cda6c985de26..928bf8c07004 100644 --- a/docs/development/core/public/kibana-plugin-core-public.resolvedeprecationresponse.md +++ b/docs/development/core/public/kibana-plugin-core-public.resolvedeprecationresponse.md @@ -7,11 +7,10 @@ Signature: ```typescript -export declare type ResolveDeprecationResponse = { +export declare type ResolveDeprecationResponse = { status: 'ok'; - payload: Payload; } | { status: 'fail'; - payload: string | Error; + reason: string; }; ``` diff --git a/packages/kbn-config/src/config_service.test.ts b/packages/kbn-config/src/config_service.test.ts index 60fcb3eb1e3c..64404341bc64 100644 --- a/packages/kbn-config/src/config_service.test.ts +++ b/packages/kbn-config/src/config_service.test.ts @@ -97,12 +97,12 @@ test('re-validate config when updated', async () => { rawConfig$.next({ key: 123 }); - await expect(valuesReceived).toMatchInlineSnapshot(` - Array [ - "value", - [Error: [config validation of [key]]: expected value of type [string] but got [number]], - ] - `); + expect(valuesReceived).toMatchInlineSnapshot(` + Array [ + "value", + [Error: [config validation of [key]]: expected value of type [string] but got [number]], + ] + `); }); test("does not push new configs when reloading if config at path hasn't changed", async () => { @@ -440,12 +440,19 @@ test('logs deprecation warning during validation', async () => { test('does not log warnings for silent deprecations during validation', async () => { const rawConfig = getRawConfigProvider({}); const configService = new ConfigService(rawConfig, defaultEnv, logger); - mockApplyDeprecations.mockImplementationOnce((config, deprecations, createAddDeprecation) => { - const addDeprecation = createAddDeprecation!(''); - addDeprecation({ message: 'some deprecation message', silent: true }); - addDeprecation({ message: 'another deprecation message' }); - return config; - }); + + mockApplyDeprecations + .mockImplementationOnce((config, deprecations, createAddDeprecation) => { + const addDeprecation = createAddDeprecation!(''); + addDeprecation({ message: 'some deprecation message', silent: true }); + addDeprecation({ message: 'another deprecation message' }); + return config; + }) + .mockImplementationOnce((config, deprecations, createAddDeprecation) => { + const addDeprecation = createAddDeprecation!(''); + addDeprecation({ message: 'I am silent', silent: true }); + return config; + }); loggerMock.clear(logger); await configService.validate(); @@ -456,6 +463,9 @@ test('does not log warnings for silent deprecations during validation', async () ], ] `); + loggerMock.clear(logger); + await configService.validate(); + expect(loggerMock.collect(logger).warn).toMatchInlineSnapshot(`Array []`); }); describe('atPathSync', () => { diff --git a/packages/kbn-config/src/config_service.ts b/packages/kbn-config/src/config_service.ts index a1f23574594d..91927b4c7b5c 100644 --- a/packages/kbn-config/src/config_service.ts +++ b/packages/kbn-config/src/config_service.ts @@ -195,13 +195,13 @@ export class ConfigService { const rawConfig = await this.rawConfigProvider.getConfig$().pipe(take(1)).toPromise(); const deprecations = await this.deprecations.pipe(take(1)).toPromise(); const deprecationMessages: string[] = []; - const createAddDeprecation = (pluginId: string) => (context: DeprecatedConfigDetails) => { + const createAddDeprecation = (domainId: string) => (context: DeprecatedConfigDetails) => { if (!context.silent) { deprecationMessages.push(context.message); } - const handledDeprecatedConfig = this.handledDeprecatedConfigs.get(pluginId) || []; + const handledDeprecatedConfig = this.handledDeprecatedConfigs.get(domainId) || []; handledDeprecatedConfig.push(context); - this.handledDeprecatedConfigs.set(pluginId, handledDeprecatedConfig); + this.handledDeprecatedConfigs.set(domainId, handledDeprecatedConfig); }; applyDeprecations(rawConfig, deprecations, createAddDeprecation); diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts index 20f4a011dec9..f21ea66c8186 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts @@ -39,14 +39,20 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(addDeprecation).toBeCalledWith({ - correctiveActions: { - manualSteps: [ - 'Replace "myplugin.deprecated" in the kibana.yml file with "myplugin.renamed"', + expect(addDeprecation.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Replace \\"myplugin.deprecated\\" with \\"myplugin.renamed\\" in the Kibana config file, CLI flag, or environment variable (in Docker only).", + ], + }, + "message": "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\"", + }, ], - }, - message: '"myplugin.deprecated" is deprecated and has been replaced by "myplugin.renamed"', - }); + ] + `); }); it('does not alter config and does not log if old property is not present', () => { const rawConfig = { @@ -99,15 +105,20 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(addDeprecation).toBeCalledWith({ - correctiveActions: { - manualSteps: [ - 'Replace "myplugin.oldsection.deprecated" in the kibana.yml file with "myplugin.newsection.renamed"', + expect(addDeprecation.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Replace \\"myplugin.oldsection.deprecated\\" with \\"myplugin.newsection.renamed\\" in the Kibana config file, CLI flag, or environment variable (in Docker only).", + ], + }, + "message": "\\"myplugin.oldsection.deprecated\\" is deprecated and has been replaced by \\"myplugin.newsection.renamed\\"", + }, ], - }, - message: - '"myplugin.oldsection.deprecated" is deprecated and has been replaced by "myplugin.newsection.renamed"', - }); + ] + `); }); it('remove the old property but does not overrides the new one if they both exist, and logs a specific message', () => { const rawConfig = { @@ -122,16 +133,21 @@ describe('DeprecationFactory', () => { renamed: 'renamed', }, }); - expect(addDeprecation).toBeCalledWith({ - correctiveActions: { - manualSteps: [ - 'Make sure "myplugin.renamed" contains the correct value in the kibana.yml file."', - 'Remove "myplugin.deprecated" from the kibana.yml file."', + expect(addDeprecation.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Make sure \\"myplugin.renamed\\" contains the correct value in the config file, CLI flag, or environment variable (in Docker only).\\"", + "Remove \\"myplugin.deprecated\\" from the config.\\"", + ], + }, + "message": "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\". However both key are present, ignoring \\"myplugin.deprecated\\"", + }, ], - }, - message: - '"myplugin.deprecated" is deprecated and has been replaced by "myplugin.renamed". However both key are present, ignoring "myplugin.deprecated"', - }); + ] + `); }); }); @@ -160,14 +176,20 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(addDeprecation).toBeCalledWith({ - correctiveActions: { - manualSteps: [ - 'Replace "myplugin.deprecated" in the kibana.yml file with "myplugin.renamed"', + expect(addDeprecation.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Replace \\"myplugin.deprecated\\" with \\"myplugin.renamed\\" in the Kibana config file, CLI flag, or environment variable (in Docker only).", + ], + }, + "message": "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\"", + }, ], - }, - message: '"myplugin.deprecated" is deprecated and has been replaced by "myplugin.renamed"', - }); + ] + `); }); it('can move a property to a different namespace', () => { @@ -194,15 +216,20 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(addDeprecation).toBeCalledWith({ - correctiveActions: { - manualSteps: [ - 'Replace "oldplugin.deprecated" in the kibana.yml file with "newplugin.renamed"', + expect(addDeprecation.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Replace \\"oldplugin.deprecated\\" with \\"newplugin.renamed\\" in the Kibana config file, CLI flag, or environment variable (in Docker only).", + ], + }, + "message": "\\"oldplugin.deprecated\\" is deprecated and has been replaced by \\"newplugin.renamed\\"", + }, ], - }, - message: - '"oldplugin.deprecated" is deprecated and has been replaced by "newplugin.renamed"', - }); + ] + `); }); it('does not alter config and does not log if old property is not present', () => { @@ -250,16 +277,21 @@ describe('DeprecationFactory', () => { }, }); - expect(addDeprecation).toBeCalledWith({ - correctiveActions: { - manualSteps: [ - 'Make sure "myplugin.renamed" contains the correct value in the kibana.yml file."', - 'Remove "myplugin.deprecated" from the kibana.yml file."', + expect(addDeprecation.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Make sure \\"myplugin.renamed\\" contains the correct value in the config file, CLI flag, or environment variable (in Docker only).\\"", + "Remove \\"myplugin.deprecated\\" from the config.\\"", + ], + }, + "message": "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\". However both key are present, ignoring \\"myplugin.deprecated\\"", + }, ], - }, - message: - '"myplugin.deprecated" is deprecated and has been replaced by "myplugin.renamed". However both key are present, ignoring "myplugin.deprecated"', - }); + ] + `); }); }); @@ -283,12 +315,20 @@ describe('DeprecationFactory', () => { property: 'value', }, }); - expect(addDeprecation).toBeCalledWith({ - correctiveActions: { - manualSteps: ['Remove "myplugin.deprecated" from the kibana.yml file."'], - }, - message: 'myplugin.deprecated is deprecated and is no longer used', - }); + expect(addDeprecation.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Remove \\"myplugin.deprecated\\" from the Kibana config file, CLI flag, or environment variable (in Docker only)\\"", + ], + }, + "message": "myplugin.deprecated is deprecated and is no longer used", + }, + ], + ] + `); }); it('handles deeply nested keys', () => { @@ -314,12 +354,20 @@ describe('DeprecationFactory', () => { }, }); - expect(addDeprecation).toBeCalledWith({ - correctiveActions: { - manualSteps: ['Remove "myplugin.section.deprecated" from the kibana.yml file."'], - }, - message: 'myplugin.section.deprecated is deprecated and is no longer used', - }); + expect(addDeprecation.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Remove \\"myplugin.section.deprecated\\" from the Kibana config file, CLI flag, or environment variable (in Docker only)\\"", + ], + }, + "message": "myplugin.section.deprecated is deprecated and is no longer used", + }, + ], + ] + `); }); it('does not alter config and does not log if unused property is not present', () => { @@ -369,12 +417,20 @@ describe('DeprecationFactory', () => { }, }); - expect(addDeprecation).toBeCalledWith({ - correctiveActions: { - manualSteps: ['Remove "myplugin.deprecated" from the kibana.yml file."'], - }, - message: 'myplugin.deprecated is deprecated and is no longer used', - }); + expect(addDeprecation.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Remove \\"myplugin.deprecated\\" from the Kibana config file, CLI flag, or environment variable (in Docker only)\\"", + ], + }, + "message": "myplugin.deprecated is deprecated and is no longer used", + }, + ], + ] + `); }); it('does not alter config and does not log if unused property is not present', () => { diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.ts b/packages/kbn-config/src/deprecation/deprecation_factory.ts index 839ee5f9fc0e..c4e59cfa89c9 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.ts @@ -40,7 +40,9 @@ const _rename = ( addDeprecation({ message: `"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}"`, correctiveActions: { - manualSteps: [`Replace "${fullOldPath}" in the kibana.yml file with "${fullNewPath}"`], + manualSteps: [ + `Replace "${fullOldPath}" with "${fullNewPath}" in the Kibana config file, CLI flag, or environment variable (in Docker only).`, + ], }, ...details, }); @@ -49,8 +51,8 @@ const _rename = ( message: `"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}". However both key are present, ignoring "${fullOldPath}"`, correctiveActions: { manualSteps: [ - `Make sure "${fullNewPath}" contains the correct value in the kibana.yml file."`, - `Remove "${fullOldPath}" from the kibana.yml file."`, + `Make sure "${fullNewPath}" contains the correct value in the config file, CLI flag, or environment variable (in Docker only)."`, + `Remove "${fullOldPath}" from the config."`, ], }, ...details, @@ -75,7 +77,9 @@ const _unused = ( addDeprecation({ message: `${fullPath} is deprecated and is no longer used`, correctiveActions: { - manualSteps: [`Remove "${fullPath}" from the kibana.yml file."`], + manualSteps: [ + `Remove "${fullPath}" from the Kibana config file, CLI flag, or environment variable (in Docker only)"`, + ], }, ...details, }); diff --git a/src/core/public/deprecations/deprecations_client.test.ts b/src/core/public/deprecations/deprecations_client.test.ts index 69b0be9b70f4..2f52f7b4af19 100644 --- a/src/core/public/deprecations/deprecations_client.test.ts +++ b/src/core/public/deprecations/deprecations_client.test.ts @@ -12,7 +12,7 @@ import type { DomainDeprecationDetails } from '../../server/types'; describe('DeprecationsClient', () => { const http = httpServiceMock.createSetupContract(); - const mockDeprecationsInfo = [ + const mockDeprecations = [ { domainId: 'testPluginId-1' }, { domainId: 'testPluginId-1' }, { domainId: 'testPluginId-2' }, @@ -20,7 +20,7 @@ describe('DeprecationsClient', () => { beforeEach(() => { http.fetch.mockReset(); - http.fetch.mockResolvedValue({ deprecationsInfo: mockDeprecationsInfo }); + http.fetch.mockResolvedValue({ deprecations: mockDeprecations }); }); describe('getAllDeprecations', () => { @@ -32,7 +32,7 @@ describe('DeprecationsClient', () => { asSystemRequest: true, }); - expect(deprecations).toEqual(mockDeprecationsInfo); + expect(deprecations).toEqual(mockDeprecations); }); }); @@ -58,10 +58,10 @@ describe('DeprecationsClient', () => { it('calls the fetch api', async () => { const deprecationsClient = new DeprecationsClient({ http }); http.fetch.mockResolvedValueOnce({ - deprecationsInfo: [{ domainId: 'testPluginId-1' }, { domainId: 'testPluginId-1' }], + deprecations: [{ domainId: 'testPluginId-1' }, { domainId: 'testPluginId-1' }], }); http.fetch.mockResolvedValueOnce({ - deprecationsInfo: [{ domainId: 'testPluginId-2' }, { domainId: 'testPluginId-2' }], + deprecations: [{ domainId: 'testPluginId-2' }, { domainId: 'testPluginId-2' }], }); const results = [ ...(await deprecationsClient.getDeprecations('testPluginId-1')), @@ -126,13 +126,12 @@ describe('DeprecationsClient', () => { expect(result).toEqual({ status: 'fail', - payload: new Error('deprecation has no correctiveAction via api.'), + reason: 'deprecation has no correctiveAction via api.', }); }); it('fetches the deprecation api', async () => { const deprecationsClient = new DeprecationsClient({ http }); - const mockPayload = {}; const mockDeprecationDetails: DomainDeprecationDetails = { domainId: 'testPluginId-1', message: 'some-message', @@ -147,7 +146,6 @@ describe('DeprecationsClient', () => { }, }, }; - http.fetch.mockResolvedValue(mockPayload); const result = await deprecationsClient.resolveDeprecation(mockDeprecationDetails); expect(http.fetch).toBeCalledTimes(1); @@ -160,12 +158,12 @@ describe('DeprecationsClient', () => { deprecationDetails: { domainId: 'testPluginId-1' }, }), }); - expect(result).toEqual({ status: 'ok', payload: mockPayload }); + expect(result).toEqual({ status: 'ok' }); }); it('fails when fetch fails', async () => { const deprecationsClient = new DeprecationsClient({ http }); - const mockPayload = new Error('Failed to fetch'); + const mockResponse = 'Failed to fetch'; const mockDeprecationDetails: DomainDeprecationDetails = { domainId: 'testPluginId-1', message: 'some-message', @@ -180,10 +178,10 @@ describe('DeprecationsClient', () => { }, }, }; - http.fetch.mockRejectedValue(mockPayload); + http.fetch.mockRejectedValue({ body: { message: mockResponse } }); const result = await deprecationsClient.resolveDeprecation(mockDeprecationDetails); - expect(result).toEqual({ status: 'fail', payload: mockPayload }); + expect(result).toEqual({ status: 'fail', reason: mockResponse }); }); }); }); diff --git a/src/core/public/deprecations/deprecations_client.ts b/src/core/public/deprecations/deprecations_client.ts index bbc754904366..e510ab1e79d1 100644 --- a/src/core/public/deprecations/deprecations_client.ts +++ b/src/core/public/deprecations/deprecations_client.ts @@ -15,15 +15,7 @@ export interface DeprecationsClientDeps { } /* @internal */ -export type ResolveDeprecationResponse = - | { - status: 'ok'; - payload: Payload; - } - | { - status: 'fail'; - payload: string | Error; - }; +export type ResolveDeprecationResponse = { status: 'ok' } | { status: 'fail'; reason: string }; export class DeprecationsClient { private readonly http: Pick; @@ -32,14 +24,11 @@ export class DeprecationsClient { } private fetchDeprecations = async (): Promise => { - const { deprecationsInfo } = await this.http.fetch( - '/api/deprecations/', - { - asSystemRequest: true, - } - ); + const { deprecations } = await this.http.fetch('/api/deprecations/', { + asSystemRequest: true, + }); - return deprecationsInfo; + return deprecations; }; public getAllDeprecations = async () => { @@ -55,21 +44,21 @@ export class DeprecationsClient { return typeof details.correctiveActions.api === 'object'; }; - public resolveDeprecation = async ( + public resolveDeprecation = async ( details: DomainDeprecationDetails - ): Promise> => { + ): Promise => { const { domainId, correctiveActions } = details; // explicit check required for TS type guard if (typeof correctiveActions.api !== 'object') { return { status: 'fail', - payload: new Error('deprecation has no correctiveAction via api.'), + reason: 'deprecation has no correctiveAction via api.', }; } const { body, method, path } = correctiveActions.api; try { - const payload = await this.http.fetch({ + await this.http.fetch({ path, method, asSystemRequest: true, @@ -78,12 +67,11 @@ export class DeprecationsClient { deprecationDetails: { domainId }, }), }); - - return { status: 'ok', payload }; + return { status: 'ok' }; } catch (err) { return { status: 'fail', - payload: err, + reason: err.body.message, }; } }; diff --git a/src/core/public/deprecations/deprecations_service.ts b/src/core/public/deprecations/deprecations_service.ts index 2f9447412f38..d06e0071d2bc 100644 --- a/src/core/public/deprecations/deprecations_service.ts +++ b/src/core/public/deprecations/deprecations_service.ts @@ -39,9 +39,7 @@ export interface DeprecationsServiceStart { * * @param {DomainDeprecationDetails} details */ - resolveDeprecation: ( - details: DomainDeprecationDetails - ) => Promise>; + resolveDeprecation: (details: DomainDeprecationDetails) => Promise; } export class DeprecationsService implements CoreService { diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 28a50ffe305f..bef8277611b8 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -480,7 +480,7 @@ export interface DeprecationsServiceStart { getAllDeprecations: () => Promise; getDeprecations: (domainId: string) => Promise; isDeprecationResolvable: (details: DomainDeprecationDetails) => boolean; - resolveDeprecation: (details: DomainDeprecationDetails) => Promise>; + resolveDeprecation: (details: DomainDeprecationDetails) => Promise; } // @public (undocumented) @@ -1087,12 +1087,11 @@ export type PublicUiSettingsParams = Omit; // Warning: (ae-missing-release-tag) "ResolveDeprecationResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export type ResolveDeprecationResponse = { +export type ResolveDeprecationResponse = { status: 'ok'; - payload: Payload; } | { status: 'fail'; - payload: string | Error; + reason: string; }; // Warning: (ae-missing-release-tag) "SavedObject" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/src/core/server/deprecations/deprecations_factory.test.ts b/src/core/server/deprecations/deprecations_factory.test.ts index 8e54827eb204..469451b0020c 100644 --- a/src/core/server/deprecations/deprecations_factory.test.ts +++ b/src/core/server/deprecations/deprecations_factory.test.ts @@ -16,11 +16,12 @@ describe('DeprecationsFactory', () => { loggerMock.clear(logger); }); - describe('createRegistry', () => { + describe('getRegistry', () => { + const domainId = 'test-plugin'; + it('creates a registry for a domainId', async () => { const deprecationsFactory = new DeprecationsFactory({ logger }); - const domainId = 'test-plugin'; - const registry = deprecationsFactory.createRegistry(domainId); + const registry = deprecationsFactory.getRegistry(domainId); expect(registry).toHaveProperty('registerDeprecations'); expect(registry).toHaveProperty('getDeprecations'); @@ -28,23 +29,28 @@ describe('DeprecationsFactory', () => { it('creates one registry for a domainId', async () => { const deprecationsFactory = new DeprecationsFactory({ logger }); - const domainId = 'test-plugin'; - const registry = deprecationsFactory.createRegistry(domainId); - const sameRegistry = deprecationsFactory.createRegistry(domainId); + const registry = deprecationsFactory.getRegistry(domainId); + const sameRegistry = deprecationsFactory.getRegistry(domainId); expect(registry).toStrictEqual(sameRegistry); }); - }); - describe('getRegistry', () => { - const domainId = 'test-plugin'; - const deprecationsFactory = new DeprecationsFactory({ logger }); it('returns a registered registry', () => { - const registry = deprecationsFactory.createRegistry(domainId); - expect(deprecationsFactory.getRegistry(domainId)).toStrictEqual(registry); - }); - it('returns undefined if no registry is defined', () => { - expect(deprecationsFactory.getRegistry('never-registered-plugin')).toBe(undefined); + const deprecationsFactory = new DeprecationsFactory({ logger }); + const mockRegistry = 'mock-reg'; + const mockRegistries = { + set: jest.fn(), + get: jest.fn().mockReturnValue(mockRegistry), + }; + + // @ts-expect-error + deprecationsFactory.registries = mockRegistries; + const result = deprecationsFactory.getRegistry(domainId); + + expect(mockRegistries.get).toBeCalledTimes(1); + expect(mockRegistries.get).toBeCalledWith(domainId); + expect(mockRegistries.set).toBeCalledTimes(0); + expect(result).toStrictEqual(mockRegistry); }); }); @@ -82,8 +88,8 @@ describe('DeprecationsFactory', () => { }, ]; - const mockPluginRegistry = deprecationsFactory.createRegistry('mockPlugin'); - const anotherMockPluginRegistry = deprecationsFactory.createRegistry('anotherMockPlugin'); + const mockPluginRegistry = deprecationsFactory.getRegistry('mockPlugin'); + const anotherMockPluginRegistry = deprecationsFactory.getRegistry('anotherMockPlugin'); mockPluginRegistry.registerDeprecations({ getDeprecations: jest.fn().mockResolvedValue(mockPluginDeprecationsInfo), }); @@ -91,8 +97,8 @@ describe('DeprecationsFactory', () => { getDeprecations: jest.fn().mockResolvedValue(anotherMockPluginDeprecationsInfo), }); - const derpecationsInfo = await deprecationsFactory.getAllDeprecations(mockDependencies); - expect(derpecationsInfo).toStrictEqual( + const derpecations = await deprecationsFactory.getAllDeprecations(mockDependencies); + expect(derpecations).toStrictEqual( [ mockPluginDeprecationsInfo.map((info) => ({ ...info, domainId: 'mockPlugin' })), anotherMockPluginDeprecationsInfo.map((info) => ({ @@ -108,17 +114,17 @@ describe('DeprecationsFactory', () => { const domainId = 'mockPlugin'; const mockError = new Error(); - const deprecationsRegistry = deprecationsFactory.createRegistry(domainId); + const deprecationsRegistry = deprecationsFactory.getRegistry(domainId); deprecationsRegistry.registerDeprecations({ getDeprecations: jest.fn().mockRejectedValue(mockError), }); - const derpecationsInfo = await deprecationsFactory.getAllDeprecations(mockDependencies); + const derpecations = await deprecationsFactory.getAllDeprecations(mockDependencies); expect(logger.warn).toBeCalledTimes(1); expect(logger.warn).toBeCalledWith( `Failed to get deprecations info for plugin "${domainId}".`, mockError ); - expect(derpecationsInfo).toStrictEqual([ + expect(derpecations).toStrictEqual([ { domainId, message: `Failed to get deprecations info for plugin "${domainId}".`, @@ -132,8 +138,8 @@ describe('DeprecationsFactory', () => { it(`returns successful results even when some getDeprecations fail`, async () => { const deprecationsFactory = new DeprecationsFactory({ logger }); - const mockPluginRegistry = deprecationsFactory.createRegistry('mockPlugin'); - const anotherMockPluginRegistry = deprecationsFactory.createRegistry('anotherMockPlugin'); + const mockPluginRegistry = deprecationsFactory.getRegistry('mockPlugin'); + const anotherMockPluginRegistry = deprecationsFactory.getRegistry('anotherMockPlugin'); const mockError = new Error(); const mockPluginDeprecationsInfo = [ { @@ -150,14 +156,14 @@ describe('DeprecationsFactory', () => { anotherMockPluginRegistry.registerDeprecations({ getDeprecations: jest.fn().mockRejectedValue(mockError), }); - const derpecationsInfo = await deprecationsFactory.getAllDeprecations(mockDependencies); + const derpecations = await deprecationsFactory.getAllDeprecations(mockDependencies); expect(logger.warn).toBeCalledTimes(1); expect(logger.warn).toBeCalledWith( `Failed to get deprecations info for plugin "anotherMockPlugin".`, mockError ); - expect(derpecationsInfo).toStrictEqual([ + expect(derpecations).toStrictEqual([ ...mockPluginDeprecationsInfo.map((info) => ({ ...info, domainId: 'mockPlugin' })), { domainId: 'anotherMockPlugin', @@ -179,8 +185,8 @@ describe('DeprecationsFactory', () => { it('returns a flattened array of DeprecationInfo', async () => { const deprecationsFactory = new DeprecationsFactory({ logger }); - const deprecationsRegistry = deprecationsFactory.createRegistry('mockPlugin'); - const deprecationsInfoBody = [ + const deprecationsRegistry = deprecationsFactory.getRegistry('mockPlugin'); + const deprecationsBody = [ { message: 'mockPlugin message', level: 'critical', @@ -200,22 +206,22 @@ describe('DeprecationsFactory', () => { ]; deprecationsRegistry.registerDeprecations({ - getDeprecations: jest.fn().mockResolvedValue(deprecationsInfoBody), + getDeprecations: jest.fn().mockResolvedValue(deprecationsBody), }); - const derpecationsInfo = await deprecationsFactory.getDeprecations( + const derpecations = await deprecationsFactory.getDeprecations( 'mockPlugin', mockDependencies ); - expect(derpecationsInfo).toStrictEqual( - deprecationsInfoBody.flat().map((body) => ({ ...body, domainId: 'mockPlugin' })) + expect(derpecations).toStrictEqual( + deprecationsBody.flat().map((body) => ({ ...body, domainId: 'mockPlugin' })) ); }); it('removes empty entries from the returned array', async () => { const deprecationsFactory = new DeprecationsFactory({ logger }); - const deprecationsRegistry = deprecationsFactory.createRegistry('mockPlugin'); - const deprecationsInfoBody = [ + const deprecationsRegistry = deprecationsFactory.getRegistry('mockPlugin'); + const deprecationsBody = [ { message: 'mockPlugin message', level: 'critical', @@ -228,17 +234,15 @@ describe('DeprecationsFactory', () => { ]; deprecationsRegistry.registerDeprecations({ - getDeprecations: jest.fn().mockResolvedValue(deprecationsInfoBody), + getDeprecations: jest.fn().mockResolvedValue(deprecationsBody), }); - const derpecationsInfo = await deprecationsFactory.getDeprecations( + const derpecations = await deprecationsFactory.getDeprecations( 'mockPlugin', mockDependencies ); - expect(derpecationsInfo).toHaveLength(1); - expect(derpecationsInfo).toStrictEqual([ - { ...deprecationsInfoBody[0], domainId: 'mockPlugin' }, - ]); + expect(derpecations).toHaveLength(1); + expect(derpecations).toStrictEqual([{ ...deprecationsBody[0], domainId: 'mockPlugin' }]); }); }); }); diff --git a/src/core/server/deprecations/deprecations_factory.ts b/src/core/server/deprecations/deprecations_factory.ts index 2ffa087912ae..3699c088e20f 100644 --- a/src/core/server/deprecations/deprecations_factory.ts +++ b/src/core/server/deprecations/deprecations_factory.ts @@ -25,7 +25,7 @@ export class DeprecationsFactory { this.logger = logger; } - public createRegistry = (domainId: string): DeprecationsRegistry => { + public getRegistry = (domainId: string): DeprecationsRegistry => { const existing = this.registries.get(domainId); if (existing) { return existing; @@ -35,10 +35,6 @@ export class DeprecationsFactory { return registry; }; - public getRegistry = (domainId: string): DeprecationsRegistry | undefined => { - return this.registries.get(domainId); - }; - public getDeprecations = async ( domainId: string, dependencies: GetDeprecationsContext diff --git a/src/core/server/deprecations/deprecations_service.mock.ts b/src/core/server/deprecations/deprecations_service.mock.ts index f4e680c475dd..c0febf90a489 100644 --- a/src/core/server/deprecations/deprecations_service.mock.ts +++ b/src/core/server/deprecations/deprecations_service.mock.ts @@ -24,10 +24,10 @@ const createSetupContractMock = () => { const createInternalSetupContractMock = () => { const internalSetupContract: jest.Mocked = { - createRegistry: jest.fn(), + getRegistry: jest.fn(), }; - internalSetupContract.createRegistry.mockReturnValue(createSetupContractMock()); + internalSetupContract.getRegistry.mockReturnValue(createSetupContractMock()); return internalSetupContract; }; diff --git a/src/core/server/deprecations/deprecations_service.ts b/src/core/server/deprecations/deprecations_service.ts index dfbf05bde503..8eca1ba5790c 100644 --- a/src/core/server/deprecations/deprecations_service.ts +++ b/src/core/server/deprecations/deprecations_service.ts @@ -106,7 +106,7 @@ export interface DeprecationsServiceSetup { /** @internal */ export interface InternalDeprecationsServiceSetup { - createRegistry: (domainId: string) => DeprecationsServiceSetup; + getRegistry: (domainId: string) => DeprecationsServiceSetup; } /** @internal */ @@ -121,7 +121,7 @@ export class DeprecationsService implements CoreService { - const registry = deprecationsFactory.createRegistry(domainId); + getRegistry: (domainId: string): DeprecationsServiceSetup => { + const registry = deprecationsFactory.getRegistry(domainId); return { registerDeprecations: registry.registerDeprecations, }; @@ -150,7 +150,7 @@ export class DeprecationsService implements CoreService { return deprecationsContexts.map(({ message, correctiveActions, documentationUrl }) => { diff --git a/src/core/server/deprecations/routes/get.ts b/src/core/server/deprecations/routes/get.ts index 2836a132a4d5..fed3fcfbd180 100644 --- a/src/core/server/deprecations/routes/get.ts +++ b/src/core/server/deprecations/routes/get.ts @@ -25,9 +25,8 @@ export const registerGetRoute = (router: IRouter, { deprecationsFactory }: Route savedObjectsClient: context.core.savedObjects.client, }; - const deprecationsInfo = await deprecationsFactory.getAllDeprecations(dependencies); const body: DeprecationsGetResponse = { - deprecationsInfo, + deprecations: await deprecationsFactory.getAllDeprecations(dependencies), }; return res.ok({ body }); diff --git a/src/core/server/deprecations/types.ts b/src/core/server/deprecations/types.ts index 928007353236..31734b51b46b 100644 --- a/src/core/server/deprecations/types.ts +++ b/src/core/server/deprecations/types.ts @@ -63,5 +63,5 @@ export interface GetDeprecationsContext { } export interface DeprecationsGetResponse { - deprecationsInfo: DomainDeprecationDetails[]; + deprecations: DomainDeprecationDetails[]; } diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index 2253cfc9b9ff..c466eb2b9ee0 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -165,7 +165,7 @@ export function createPluginSetupContext( register: deps.uiSettings.register, }, getStartServices: () => plugin.startDependencies, - deprecations: deps.deprecations.createRegistry(plugin.name), + deprecations: deps.deprecations.getRegistry(plugin.name), }; } diff --git a/test/functional/fixtures/es_archiver/deprecations_service/mappings.json b/test/functional/fixtures/es_archiver/deprecations_service/mappings.json index bcec9c93e30a..5f7c7e0e7b7d 100644 --- a/test/functional/fixtures/es_archiver/deprecations_service/mappings.json +++ b/test/functional/fixtures/es_archiver/deprecations_service/mappings.json @@ -2,16 +2,287 @@ "type": "index", "value": { "index": ".kibana", - "settings": { - "index": { - "number_of_shards": "1", - "number_of_replicas": "0" - } - }, "mappings": { - "dynamic": "true", "properties": { - "title": { "type": "text" } + "config": { + "dynamic": "true", + "properties": { + "buildNum": { + "type": "keyword" + }, + "dateFormat:tz": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "dashboard": { + "dynamic": "strict", + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "optionsJSON": { + "type": "text" + }, + "panelsJSON": { + "type": "text" + }, + "refreshInterval": { + "properties": { + "display": { + "type": "keyword" + }, + "pause": { + "type": "boolean" + }, + "section": { + "type": "integer" + }, + "value": { + "type": "integer" + } + } + }, + "timeFrom": { + "type": "keyword" + }, + "timeRestore": { + "type": "boolean" + }, + "timeTo": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "index-pattern": { + "dynamic": "strict", + "properties": { + "fieldFormatMap": { + "type": "text" + }, + "fields": { + "type": "text" + }, + "intervalName": { + "type": "keyword" + }, + "notExpandable": { + "type": "boolean" + }, + "sourceFilters": { + "type": "text" + }, + "timeFieldName": { + "type": "keyword" + }, + "title": { + "type": "text" + } + } + }, + "search": { + "dynamic": "strict", + "properties": { + "columns": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "sort": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "server": { + "dynamic": "strict", + "properties": { + "uuid": { + "type": "keyword" + } + } + }, + "timelion-sheet": { + "dynamic": "strict", + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "timelion_chart_height": { + "type": "integer" + }, + "timelion_columns": { + "type": "integer" + }, + "timelion_interval": { + "type": "keyword" + }, + "timelion_other_interval": { + "type": "keyword" + }, + "timelion_rows": { + "type": "integer" + }, + "timelion_sheet": { + "type": "text" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "type": { + "type": "keyword" + }, + "url": { + "dynamic": "strict", + "properties": { + "accessCount": { + "type": "long" + }, + "accessDate": { + "type": "date" + }, + "createDate": { + "type": "date" + }, + "url": { + "fields": { + "keyword": { + "ignore_above": 2048, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "visualization": { + "dynamic": "strict", + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "savedSearchId": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "type": "text" + } + } + }, + "query": { + "properties": { + "title": { + "type": "text" + }, + "description": { + "type": "text" + }, + "query": { + "properties": { + "language": { + "type": "keyword" + }, + "query": { + "type": "keyword", + "index": false + } + } + }, + "filters": { + "type": "object", + "enabled": false + }, + "timefilter": { + "type": "object", + "enabled": false + } + } + }, + "test-deprecations-plugin": { + "properties": { + "title": { + "type": "text" + } + } + } + } + }, + "settings": { + "index": { + "number_of_replicas": "0", + "number_of_shards": "1" } } } diff --git a/test/plugin_functional/config.ts b/test/plugin_functional/config.ts index 0a43abbfe5a7..1651e213ee82 100644 --- a/test/plugin_functional/config.ts +++ b/test/plugin_functional/config.ts @@ -22,16 +22,15 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { return { testFiles: [ require.resolve('./test_suites/core'), - - // require.resolve('./test_suites/custom_visualizations'), - // require.resolve('./test_suites/panel_actions'), - // require.resolve('./test_suites/core_plugins'), - // require.resolve('./test_suites/management'), - // require.resolve('./test_suites/doc_views'), - // require.resolve('./test_suites/application_links'), - // require.resolve('./test_suites/data_plugin'), - // require.resolve('./test_suites/saved_objects_management'), - // require.resolve('./test_suites/saved_objects_hidden_type'), + require.resolve('./test_suites/custom_visualizations'), + require.resolve('./test_suites/panel_actions'), + require.resolve('./test_suites/core_plugins'), + require.resolve('./test_suites/management'), + require.resolve('./test_suites/doc_views'), + require.resolve('./test_suites/application_links'), + require.resolve('./test_suites/data_plugin'), + require.resolve('./test_suites/saved_objects_management'), + require.resolve('./test_suites/saved_objects_hidden_type'), ], services: { ...functionalConfig.get('services'), diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/package.json b/test/plugin_functional/plugins/core_plugin_deprecations/package.json index e658f0a25085..f14ec933f59b 100644 --- a/test/plugin_functional/plugins/core_plugin_deprecations/package.json +++ b/test/plugin_functional/plugins/core_plugin_deprecations/package.json @@ -11,4 +11,4 @@ "kbn": "node ../../../../scripts/kbn.js", "build": "rm -rf './target' && ../../../../node_modules/.bin/tsc" } -} \ No newline at end of file +} diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/public/application.tsx b/test/plugin_functional/plugins/core_plugin_deprecations/public/application.tsx new file mode 100644 index 000000000000..e2166a249e34 --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_deprecations/public/application.tsx @@ -0,0 +1,19 @@ +/* + * 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 React from 'react'; +import ReactDOM from 'react-dom'; +import { AppMountParameters } from 'kibana/public'; + +const DeprecationsApp = () =>

Deprcations App
; + +export const renderApp = ({ element }: AppMountParameters) => { + ReactDOM.render(, element); + + return () => ReactDOM.unmountComponentAtNode(element); +}; diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/public/index.ts b/test/plugin_functional/plugins/core_plugin_deprecations/public/index.ts new file mode 100644 index 000000000000..bb6b3f0740b3 --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_deprecations/public/index.ts @@ -0,0 +1,19 @@ +/* + * 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 { PluginInitializer, PluginInitializerContext } from 'kibana/public'; +import { + CorePluginDeprecationsPlugin, + CorePluginDeprecationsPluginSetup, + CorePluginDeprecationsPluginStart, +} from './plugin'; + +export const plugin: PluginInitializer< + CorePluginDeprecationsPluginSetup, + CorePluginDeprecationsPluginStart +> = (context: PluginInitializerContext) => new CorePluginDeprecationsPlugin(context); diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/public/plugin.tsx b/test/plugin_functional/plugins/core_plugin_deprecations/public/plugin.tsx new file mode 100644 index 000000000000..bf807145e14b --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_deprecations/public/plugin.tsx @@ -0,0 +1,40 @@ +/* + * 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 { CoreSetup, Plugin, PluginInitializerContext } from 'kibana/public'; + +declare global { + interface Window { + env?: PluginInitializerContext['env']; + } +} + +export class CorePluginDeprecationsPlugin + implements Plugin { + constructor(pluginContext: PluginInitializerContext) { + window.env = pluginContext.env; + } + public setup(core: CoreSetup) { + core.application.register({ + id: 'core-plugin-deprecations', + title: 'Core Plugin Deprecations', + async mount(params) { + const { renderApp } = await import('./application'); + await core.getStartServices(); + return renderApp(params); + }, + }); + } + + public start() {} + + public stop() {} +} + +export type CorePluginDeprecationsPluginSetup = ReturnType; +export type CorePluginDeprecationsPluginStart = ReturnType; diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/server/plugin.ts b/test/plugin_functional/plugins/core_plugin_deprecations/server/plugin.ts index a205adaeb4df..38565b1e2c0a 100644 --- a/test/plugin_functional/plugins/core_plugin_deprecations/server/plugin.ts +++ b/test/plugin_functional/plugins/core_plugin_deprecations/server/plugin.ts @@ -7,7 +7,7 @@ */ import type { Plugin, CoreSetup, GetDeprecationsContext, DeprecationsDetails } from 'kibana/server'; - +import { registerRoutes } from './routes'; async function getDeprecations({ savedObjectsClient, }: GetDeprecationsContext): Promise { @@ -37,6 +37,7 @@ async function getDeprecations({ export class CorePluginDeprecationsPlugin implements Plugin { public setup(core: CoreSetup, deps: {}) { + registerRoutes(core.http); core.savedObjects.registerType({ name: 'test-deprecations-plugin', hidden: false, diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/server/routes.ts b/test/plugin_functional/plugins/core_plugin_deprecations/server/routes.ts new file mode 100644 index 000000000000..d6bf065898f9 --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_deprecations/server/routes.ts @@ -0,0 +1,45 @@ +/* + * 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 { HttpServiceSetup } from 'kibana/server'; +import { schema } from '@kbn/config-schema'; + +export function registerRoutes(http: HttpServiceSetup) { + const router = http.createRouter(); + router.post( + { + path: '/api/core_deprecations_resolve/', + validate: { + body: schema.object({ + mockFail: schema.maybe(schema.boolean()), + keyId: schema.maybe(schema.string()), + deprecationDetails: schema.object({ + domainId: schema.string(), + }), + }), + }, + }, + async (context, req, res) => { + const { mockFail, keyId } = req.body; + if (mockFail === true) { + return res.badRequest({ + body: new Error('Mocking api failure'), + }); + } + + if (keyId) { + const client = context.core.savedObjects.getClient(); + await client.delete('test-deprecations-plugin', keyId, { + refresh: true, + }); + } + + return res.ok(); + } + ); +} diff --git a/test/plugin_functional/test_suites/core/deprecations.ts b/test/plugin_functional/test_suites/core/deprecations.ts index 5dbf3064608c..e6fa6df5505b 100644 --- a/test/plugin_functional/test_suites/core/deprecations.ts +++ b/test/plugin_functional/test_suites/core/deprecations.ts @@ -7,85 +7,237 @@ */ import expect from '@kbn/expect'; -import type { DeprecationsGetResponse } from 'src/core/server/types'; +import type { DomainDeprecationDetails, DeprecationsGetResponse } from 'src/core/server/types'; +import type { ResolveDeprecationResponse } from 'src/core/public'; import { PluginFunctionalProviderContext } from '../../services'; -export default function ({ getService }: PluginFunctionalProviderContext) { +export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const PageObjects = getPageObjects(['common']); + const browser = getService('browser'); + + const CorePluginDeprecationsPluginDeprecations = [ + { + level: 'critical', + message: + '"corePluginDeprecations.oldProperty" is deprecated and has been replaced by "corePluginDeprecations.newProperty"', + correctiveActions: { + manualSteps: [ + 'Replace "corePluginDeprecations.oldProperty" in the kibana.yml file with "corePluginDeprecations.newProperty"', + ], + }, + domainId: 'corePluginDeprecations', + }, + { + level: 'critical', + message: 'corePluginDeprecations.noLongerUsed is deprecated and is no longer used', + correctiveActions: { + manualSteps: ['Remove "corePluginDeprecations.noLongerUsed" from the kibana.yml file."'], + }, + domainId: 'corePluginDeprecations', + }, + { + level: 'critical', + message: + 'Kibana plugin funcitonal tests will no longer allow corePluginDeprecations.secret config to be set to anything except 42.', + correctiveActions: {}, + documentationUrl: 'config-secret-doc-url', + domainId: 'corePluginDeprecations', + }, + { + message: 'CorePluginDeprecationsPlugin is a deprecated feature for testing.', + documentationUrl: 'test-url', + level: 'warning', + correctiveActions: { + manualSteps: ['Step a', 'Step b'], + }, + domainId: 'corePluginDeprecations', + }, + { + message: 'SavedObject test-deprecations-plugin is still being used.', + documentationUrl: 'another-test-url', + level: 'critical', + correctiveActions: {}, + domainId: 'corePluginDeprecations', + }, + ]; describe('deprecations service', () => { + before(() => esArchiver.load('../functional/fixtures/es_archiver/deprecations_service')); + after(() => esArchiver.unload('../functional/fixtures/es_archiver/deprecations_service')); + describe('GET /api/deprecations/', async () => { it('returns registered config deprecations and feature deprecations', async () => { const { body } = await supertest.get('/api/deprecations/').set('kbn-xsrf', 'true'); - const { deprecationsInfo } = body as DeprecationsGetResponse; - expect(Array.isArray(deprecationsInfo)).to.be(true); - const corePluginDeprecations = deprecationsInfo.filter( + const { deprecations } = body as DeprecationsGetResponse; + expect(Array.isArray(deprecations)).to.be(true); + const corePluginDeprecations = deprecations.filter( ({ domainId }) => domainId === 'corePluginDeprecations' ); - expect(corePluginDeprecations).to.eql([ - { - level: 'critical', - message: - '"corePluginDeprecations.oldProperty" is deprecated and has been replaced by "corePluginDeprecations.newProperty"', - correctiveActions: { - manualSteps: [ - 'Replace "corePluginDeprecations.oldProperty" in the kibana.yml file with "corePluginDeprecations.newProperty"', - ], - }, - domainId: 'corePluginDeprecations', - }, - { - level: 'critical', - message: 'corePluginDeprecations.noLongerUsed is deprecated and is no longer used', - correctiveActions: { - manualSteps: [ - 'Remove "corePluginDeprecations.noLongerUsed" from the kibana.yml file."', - ], - }, - domainId: 'corePluginDeprecations', - }, - { - level: 'critical', - message: - 'Kibana plugin funcitonal tests will no longer allow corePluginDeprecations.secret config to be set to anything except 42.', - correctiveActions: {}, - documentationUrl: 'config-secret-doc-url', - domainId: 'corePluginDeprecations', - }, - { - message: 'CorePluginDeprecationsPlugin is a deprecated feature for testing.', - documentationUrl: 'test-url', - level: 'warning', - correctiveActions: { - manualSteps: ['Step a', 'Step b'], - }, - domainId: 'corePluginDeprecations', - }, - ]); + expect(corePluginDeprecations).to.eql(CorePluginDeprecationsPluginDeprecations); }); }); - describe('registerDeprecations', () => { - before(() => esArchiver.load('../functional/fixtures/es_archiver/deprecations_service')); - after(() => esArchiver.unload('../functional/fixtures/es_archiver/deprecations_service')); - it('calls registered getDeprecations', async () => { - const { body } = await supertest.get('/api/deprecations/').set('kbn-xsrf', 'true'); + describe('Public API', () => { + before(async () => await PageObjects.common.navigateToApp('home')); - const { deprecationsInfo } = body as DeprecationsGetResponse; + it('#getAllDeprecations returns all deprecations plugin deprecations', async () => { + const result = await browser.executeAsync((cb) => { + return window._coreProvider.start.core.deprecations.getAllDeprecations().then(cb); + }); - const deprecation = deprecationsInfo.find( - ({ message }) => message === 'SavedObject test-deprecations-plugin is still being used.' + const corePluginDeprecations = result.filter( + ({ domainId }) => domainId === 'corePluginDeprecations' ); - expect(deprecation).to.eql({ - message: 'SavedObject test-deprecations-plugin is still being used.', - documentationUrl: 'another-test-url', - level: 'critical', - correctiveActions: {}, - domainId: 'corePluginDeprecations', + expect(corePluginDeprecations).to.eql(CorePluginDeprecationsPluginDeprecations); + }); + + it('#getDeprecations returns domain deprecations', async () => { + const corePluginDeprecations = await browser.executeAsync( + (cb) => { + return window._coreProvider.start.core.deprecations + .getDeprecations('corePluginDeprecations') + .then(cb); + } + ); + + expect(corePluginDeprecations).to.eql(CorePluginDeprecationsPluginDeprecations); + }); + + describe('resolveDeprecation', () => { + it('fails on missing correctiveActions.api', async () => { + const resolveResult = await browser.executeAsync((cb) => { + return window._coreProvider.start.core.deprecations + .resolveDeprecation({ + message: 'CorePluginDeprecationsPlugin is a deprecated feature for testing.', + documentationUrl: 'test-url', + level: 'warning', + correctiveActions: { + manualSteps: ['Step a', 'Step b'], + }, + domainId: 'corePluginDeprecations', + }) + .then(cb); + }); + + expect(resolveResult).to.eql({ + reason: 'deprecation has no correctiveAction via api.', + status: 'fail', + }); + }); + + it('fails on bad request from correctiveActions.api', async () => { + const resolveResult = await browser.executeAsync((cb) => { + return window._coreProvider.start.core.deprecations + .resolveDeprecation({ + message: 'CorePluginDeprecationsPlugin is a deprecated feature for testing.', + documentationUrl: 'test-url', + level: 'warning', + correctiveActions: { + api: { + method: 'POST', + path: '/api/core_deprecations_resolve/', + body: { + mockFail: true, + }, + }, + }, + domainId: 'corePluginDeprecations', + }) + .then(cb); + }); + + expect(resolveResult).to.eql({ + reason: 'Mocking api failure', + status: 'fail', + }); + }); + + it('fails on 404 request from correctiveActions.api', async () => { + const resolveResult = await browser.executeAsync((cb) => { + return window._coreProvider.start.core.deprecations + .resolveDeprecation({ + message: 'CorePluginDeprecationsPlugin is a deprecated feature for testing.', + documentationUrl: 'test-url', + level: 'warning', + correctiveActions: { + api: { + method: 'POST', + path: '/api/invalid_route_not_registered/', + body: { + mockFail: true, + }, + }, + }, + domainId: 'corePluginDeprecations', + }) + .then(cb); + }); + + expect(resolveResult).to.eql({ + reason: 'Not Found', + status: 'fail', + }); + }); + + it('returns { status: ok } on successful correctiveActions.api', async () => { + const savedObjectId = await supertest + .get('/api/saved_objects/_find?type=test-deprecations-plugin') + .set('kbn-xsrf', 'true') + .expect(200) + .then(({ body }) => { + expect(body.total).to.be(1); + return body.saved_objects[0].id; + }); + + const resolveResult = await browser.executeAsync( + (keyId, cb) => { + return window._coreProvider.start.core.deprecations + .resolveDeprecation({ + message: 'CorePluginDeprecationsPlugin is a deprecated feature for testing.', + documentationUrl: 'test-url', + level: 'warning', + correctiveActions: { + api: { + method: 'POST', + path: '/api/core_deprecations_resolve/', + body: { keyId }, + }, + }, + domainId: 'corePluginDeprecations', + }) + .then(cb); + }, + savedObjectId + ); + + expect(resolveResult).to.eql({ status: 'ok' }); + await supertest + .get('/api/saved_objects/_find?type=test-deprecations-plugin') + .set('kbn-xsrf', 'true') + .expect(200) + .then(({ body }) => { + expect(body.total).to.be(0); + }); + + const { deprecations } = await supertest + .get('/api/deprecations/') + .set('kbn-xsrf', 'true') + .then( + ({ body }): Promise => { + return body; + } + ); + + const deprecation = deprecations.find( + ({ message }) => message === 'SavedObject test-deprecations-plugin is still being used.' + ); + + expect(deprecation).to.eql(undefined); }); }); }); From 61d49afbe51c443d3c3bcdc44128cecf0284abe5 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 30 Mar 2021 13:41:13 +0300 Subject: [PATCH 22/23] update tests --- .../src/deprecation/deprecation_factory.test.ts | 14 +++++++------- .../src/deprecation/deprecation_factory.ts | 6 +++--- .../test_suites/core/deprecations.ts | 6 ++++-- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts index f21ea66c8186..11a49ed79d17 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts @@ -139,8 +139,8 @@ describe('DeprecationFactory', () => { Object { "correctiveActions": Object { "manualSteps": Array [ - "Make sure \\"myplugin.renamed\\" contains the correct value in the config file, CLI flag, or environment variable (in Docker only).\\"", - "Remove \\"myplugin.deprecated\\" from the config.\\"", + "Make sure \\"myplugin.renamed\\" contains the correct value in the config file, CLI flag, or environment variable (in Docker only).", + "Remove \\"myplugin.deprecated\\" from the config.", ], }, "message": "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\". However both key are present, ignoring \\"myplugin.deprecated\\"", @@ -283,8 +283,8 @@ describe('DeprecationFactory', () => { Object { "correctiveActions": Object { "manualSteps": Array [ - "Make sure \\"myplugin.renamed\\" contains the correct value in the config file, CLI flag, or environment variable (in Docker only).\\"", - "Remove \\"myplugin.deprecated\\" from the config.\\"", + "Make sure \\"myplugin.renamed\\" contains the correct value in the config file, CLI flag, or environment variable (in Docker only).", + "Remove \\"myplugin.deprecated\\" from the config.", ], }, "message": "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\". However both key are present, ignoring \\"myplugin.deprecated\\"", @@ -321,7 +321,7 @@ describe('DeprecationFactory', () => { Object { "correctiveActions": Object { "manualSteps": Array [ - "Remove \\"myplugin.deprecated\\" from the Kibana config file, CLI flag, or environment variable (in Docker only)\\"", + "Remove \\"myplugin.deprecated\\" from the Kibana config file, CLI flag, or environment variable (in Docker only)", ], }, "message": "myplugin.deprecated is deprecated and is no longer used", @@ -360,7 +360,7 @@ describe('DeprecationFactory', () => { Object { "correctiveActions": Object { "manualSteps": Array [ - "Remove \\"myplugin.section.deprecated\\" from the Kibana config file, CLI flag, or environment variable (in Docker only)\\"", + "Remove \\"myplugin.section.deprecated\\" from the Kibana config file, CLI flag, or environment variable (in Docker only)", ], }, "message": "myplugin.section.deprecated is deprecated and is no longer used", @@ -423,7 +423,7 @@ describe('DeprecationFactory', () => { Object { "correctiveActions": Object { "manualSteps": Array [ - "Remove \\"myplugin.deprecated\\" from the Kibana config file, CLI flag, or environment variable (in Docker only)\\"", + "Remove \\"myplugin.deprecated\\" from the Kibana config file, CLI flag, or environment variable (in Docker only)", ], }, "message": "myplugin.deprecated is deprecated and is no longer used", diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.ts b/packages/kbn-config/src/deprecation/deprecation_factory.ts index c4e59cfa89c9..140846d86ae0 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.ts @@ -51,8 +51,8 @@ const _rename = ( message: `"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}". However both key are present, ignoring "${fullOldPath}"`, correctiveActions: { manualSteps: [ - `Make sure "${fullNewPath}" contains the correct value in the config file, CLI flag, or environment variable (in Docker only)."`, - `Remove "${fullOldPath}" from the config."`, + `Make sure "${fullNewPath}" contains the correct value in the config file, CLI flag, or environment variable (in Docker only).`, + `Remove "${fullOldPath}" from the config.`, ], }, ...details, @@ -78,7 +78,7 @@ const _unused = ( message: `${fullPath} is deprecated and is no longer used`, correctiveActions: { manualSteps: [ - `Remove "${fullPath}" from the Kibana config file, CLI flag, or environment variable (in Docker only)"`, + `Remove "${fullPath}" from the Kibana config file, CLI flag, or environment variable (in Docker only)`, ], }, ...details, diff --git a/test/plugin_functional/test_suites/core/deprecations.ts b/test/plugin_functional/test_suites/core/deprecations.ts index e6fa6df5505b..c44781ab284c 100644 --- a/test/plugin_functional/test_suites/core/deprecations.ts +++ b/test/plugin_functional/test_suites/core/deprecations.ts @@ -24,7 +24,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide '"corePluginDeprecations.oldProperty" is deprecated and has been replaced by "corePluginDeprecations.newProperty"', correctiveActions: { manualSteps: [ - 'Replace "corePluginDeprecations.oldProperty" in the kibana.yml file with "corePluginDeprecations.newProperty"', + 'Replace "corePluginDeprecations.oldProperty" with "corePluginDeprecations.newProperty" in the Kibana config file, CLI flag, or environment variable (in Docker only).', ], }, domainId: 'corePluginDeprecations', @@ -33,7 +33,9 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide level: 'critical', message: 'corePluginDeprecations.noLongerUsed is deprecated and is no longer used', correctiveActions: { - manualSteps: ['Remove "corePluginDeprecations.noLongerUsed" from the kibana.yml file."'], + manualSteps: [ + 'Remove "corePluginDeprecations.noLongerUsed" from the Kibana config file, CLI flag, or environment variable (in Docker only)', + ], }, domainId: 'corePluginDeprecations', }, From 55c988998a84b8c79ec0253fcc2abc783acbd400 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 30 Mar 2021 17:02:04 +0300 Subject: [PATCH 23/23] fix eslint --- packages/kbn-config/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-config/src/index.ts b/packages/kbn-config/src/index.ts index e56f8bc644e9..a9ea8265a376 100644 --- a/packages/kbn-config/src/index.ts +++ b/packages/kbn-config/src/index.ts @@ -15,7 +15,7 @@ export type { } from './deprecation'; export { applyDeprecations, configDeprecationFactory } from './deprecation'; - + export { RawConfigurationProvider, RawConfigService,