Skip to content

Commit a0e706e

Browse files
authored
add deprecation warning for legacy 3rd party plugins (#62401) (#63827)
* add warnings for legacy 3rd party plugins * use published doc page for 8.0 breaking changes * update message to remove fixed 8.0 version reference * fix generated doc
1 parent 3c8f3f8 commit a0e706e

File tree

8 files changed

+197
-8
lines changed

8 files changed

+197
-8
lines changed

src/core/server/legacy/legacy_service.test.mocks.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ export const findLegacyPluginSpecsMock = jest.fn().mockImplementation((settings:
3030
uiExports: {},
3131
navLinks: [],
3232
}));
33-
jest.doMock('./plugins/find_legacy_plugin_specs.ts', () => ({
33+
jest.doMock('./plugins/find_legacy_plugin_specs', () => ({
3434
findLegacyPluginSpecs: findLegacyPluginSpecsMock,
3535
}));
36+
37+
export const logLegacyThirdPartyPluginDeprecationWarningMock = jest.fn();
38+
jest.doMock('./plugins/log_legacy_plugins_warning', () => ({
39+
logLegacyThirdPartyPluginDeprecationWarning: logLegacyThirdPartyPluginDeprecationWarningMock,
40+
}));

src/core/server/legacy/legacy_service.test.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ jest.mock('../../../cli/cluster/cluster_manager');
2222
jest.mock('./config/legacy_deprecation_adapters', () => ({
2323
convertLegacyDeprecationProvider: (provider: any) => Promise.resolve(provider),
2424
}));
25-
import { findLegacyPluginSpecsMock } from './legacy_service.test.mocks';
25+
import {
26+
findLegacyPluginSpecsMock,
27+
logLegacyThirdPartyPluginDeprecationWarningMock,
28+
} from './legacy_service.test.mocks';
2629

2730
import { BehaviorSubject, throwError } from 'rxjs';
2831

@@ -476,6 +479,38 @@ describe('#discoverPlugins()', () => {
476479
expect(configService.addDeprecationProvider).toHaveBeenCalledWith('', 'providerA');
477480
expect(configService.addDeprecationProvider).toHaveBeenCalledWith('', 'providerB');
478481
});
482+
483+
it(`logs deprecations for legacy third party plugins`, async () => {
484+
const pluginSpecs = [
485+
{ getId: () => 'pluginA', getDeprecationsProvider: () => undefined },
486+
{ getId: () => 'pluginB', getDeprecationsProvider: () => undefined },
487+
];
488+
findLegacyPluginSpecsMock.mockImplementation(
489+
settings =>
490+
Promise.resolve({
491+
pluginSpecs,
492+
pluginExtendedConfig: settings,
493+
disabledPluginSpecs: [],
494+
uiExports: {},
495+
navLinks: [],
496+
}) as any
497+
);
498+
499+
const legacyService = new LegacyService({
500+
coreId,
501+
env,
502+
logger,
503+
configService: configService as any,
504+
});
505+
506+
await legacyService.discoverPlugins();
507+
508+
expect(logLegacyThirdPartyPluginDeprecationWarningMock).toHaveBeenCalledTimes(1);
509+
expect(logLegacyThirdPartyPluginDeprecationWarningMock).toHaveBeenCalledWith({
510+
specs: pluginSpecs,
511+
log: expect.any(Object),
512+
});
513+
});
479514
});
480515

481516
test('Sets the server.uuid property on the legacy configuration', async () => {

src/core/server/legacy/legacy_service.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { DevConfig, DevConfigType, config as devConfig } from '../dev';
2828
import { BasePathProxyServer, HttpConfig, HttpConfigType, config as httpConfig } from '../http';
2929
import { Logger } from '../logging';
3030
import { PathConfigType } from '../path';
31-
import { findLegacyPluginSpecs } from './plugins';
31+
import { findLegacyPluginSpecs, logLegacyThirdPartyPluginDeprecationWarning } from './plugins';
3232
import { convertLegacyDeprecationProvider } from './config';
3333
import {
3434
ILegacyInternals,
@@ -133,6 +133,11 @@ export class LegacyService implements CoreService {
133133
this.coreContext.env.packageInfo
134134
);
135135

136+
logLegacyThirdPartyPluginDeprecationWarning({
137+
specs: pluginSpecs,
138+
log: this.log,
139+
});
140+
136141
this.legacyPlugins = {
137142
pluginSpecs,
138143
disabledPluginSpecs,

src/core/server/legacy/plugins/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@
1818
*/
1919

2020
export { findLegacyPluginSpecs } from './find_legacy_plugin_specs';
21+
export { logLegacyThirdPartyPluginDeprecationWarning } from './log_legacy_plugins_warning';
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import { loggerMock } from '../../logging/logger.mock';
21+
import { logLegacyThirdPartyPluginDeprecationWarning } from './log_legacy_plugins_warning';
22+
import { LegacyPluginSpec } from '../types';
23+
24+
const createPluginSpec = ({ id, path }: { id: string; path: string }): LegacyPluginSpec => {
25+
return {
26+
getId: () => id,
27+
getExpectedKibanaVersion: () => 'kibana',
28+
getConfigPrefix: () => 'plugin.config',
29+
getDeprecationsProvider: () => undefined,
30+
getPack: () => ({
31+
getPath: () => path,
32+
}),
33+
};
34+
};
35+
36+
describe('logLegacyThirdPartyPluginDeprecationWarning', () => {
37+
let log: ReturnType<typeof loggerMock.create>;
38+
39+
beforeEach(() => {
40+
log = loggerMock.create();
41+
});
42+
43+
it('logs warning for third party plugins', () => {
44+
logLegacyThirdPartyPluginDeprecationWarning({
45+
specs: [createPluginSpec({ id: 'plugin', path: '/some-external-path' })],
46+
log,
47+
});
48+
expect(log.warn).toHaveBeenCalledTimes(1);
49+
expect(log.warn.mock.calls[0]).toMatchInlineSnapshot(`
50+
Array [
51+
"Some installed third party plugin(s) [plugin] are using the legacy plugin format and will no longer work in a future Kibana release. Please refer to https://www.elastic.co/guide/en/kibana/master/breaking-changes-8.0.html for a list of breaking changes and https://github.com/elastic/kibana/blob/master/src/core/MIGRATION.md for documentation on how to migrate legacy plugins.",
52+
]
53+
`);
54+
});
55+
56+
it('lists all the deprecated plugins and only log once', () => {
57+
logLegacyThirdPartyPluginDeprecationWarning({
58+
specs: [
59+
createPluginSpec({ id: 'pluginA', path: '/abs/path/to/pluginA' }),
60+
createPluginSpec({ id: 'pluginB', path: '/abs/path/to/pluginB' }),
61+
createPluginSpec({ id: 'pluginC', path: '/abs/path/to/pluginC' }),
62+
],
63+
log,
64+
});
65+
expect(log.warn).toHaveBeenCalledTimes(1);
66+
expect(log.warn.mock.calls[0]).toMatchInlineSnapshot(`
67+
Array [
68+
"Some installed third party plugin(s) [pluginA, pluginB, pluginC] are using the legacy plugin format and will no longer work in a future Kibana release. Please refer to https://www.elastic.co/guide/en/kibana/master/breaking-changes-8.0.html for a list of breaking changes and https://github.com/elastic/kibana/blob/master/src/core/MIGRATION.md for documentation on how to migrate legacy plugins.",
69+
]
70+
`);
71+
});
72+
73+
it('does not log warning for internal legacy plugins', () => {
74+
logLegacyThirdPartyPluginDeprecationWarning({
75+
specs: [
76+
createPluginSpec({
77+
id: 'plugin',
78+
path: '/absolute/path/to/kibana/src/legacy/core_plugins',
79+
}),
80+
createPluginSpec({
81+
id: 'plugin',
82+
path: '/absolute/path/to/kibana/x-pack',
83+
}),
84+
],
85+
log,
86+
});
87+
88+
expect(log.warn).not.toHaveBeenCalled();
89+
});
90+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import { Logger } from '../../logging';
21+
import { LegacyPluginSpec } from '../types';
22+
23+
const internalPaths = ['/src/legacy/core_plugins', '/x-pack'];
24+
25+
const breakingChangesUrl =
26+
'https://www.elastic.co/guide/en/kibana/master/breaking-changes-8.0.html';
27+
const migrationGuideUrl = 'https://github.com/elastic/kibana/blob/master/src/core/MIGRATION.md';
28+
29+
export const logLegacyThirdPartyPluginDeprecationWarning = ({
30+
specs,
31+
log,
32+
}: {
33+
specs: LegacyPluginSpec[];
34+
log: Logger;
35+
}) => {
36+
const thirdPartySpecs = specs.filter(isThirdPartyPluginSpec);
37+
if (thirdPartySpecs.length > 0) {
38+
const pluginIds = thirdPartySpecs.map(spec => spec.getId());
39+
log.warn(
40+
`Some installed third party plugin(s) [${pluginIds.join(
41+
', '
42+
)}] are using the legacy plugin format and will no longer work in a future Kibana release. ` +
43+
`Please refer to ${breakingChangesUrl} for a list of breaking changes ` +
44+
`and ${migrationGuideUrl} for documentation on how to migrate legacy plugins.`
45+
);
46+
}
47+
};
48+
49+
const isThirdPartyPluginSpec = (spec: LegacyPluginSpec): boolean => {
50+
const pluginPath = spec.getPack().getPath();
51+
return !internalPaths.some(internalPath => pluginPath.indexOf(internalPath) > -1);
52+
};

src/core/server/legacy/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ export interface LegacyPluginSpec {
9898
getExpectedKibanaVersion: () => string;
9999
getConfigPrefix: () => string;
100100
getDeprecationsProvider: () => LegacyConfigDeprecationProvider | undefined;
101+
getPack: () => LegacyPluginPack;
101102
}
102103

103104
/**

src/core/server/server.api.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2468,11 +2468,11 @@ export const validBodyOutput: readonly ["data", "stream"];
24682468
// Warnings were encountered during analysis:
24692469
//
24702470
// src/core/server/http/router/response.ts:316:3 - (ae-forgotten-export) The symbol "KibanaResponse" needs to be exported by the entry point index.d.ts
2471-
// src/core/server/legacy/types.ts:162:3 - (ae-forgotten-export) The symbol "VarsProvider" needs to be exported by the entry point index.d.ts
2472-
// src/core/server/legacy/types.ts:163:3 - (ae-forgotten-export) The symbol "VarsReplacer" needs to be exported by the entry point index.d.ts
2473-
// src/core/server/legacy/types.ts:164:3 - (ae-forgotten-export) The symbol "LegacyNavLinkSpec" needs to be exported by the entry point index.d.ts
2474-
// src/core/server/legacy/types.ts:165:3 - (ae-forgotten-export) The symbol "LegacyAppSpec" needs to be exported by the entry point index.d.ts
2475-
// src/core/server/legacy/types.ts:166:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts
2471+
// src/core/server/legacy/types.ts:163:3 - (ae-forgotten-export) The symbol "VarsProvider" needs to be exported by the entry point index.d.ts
2472+
// src/core/server/legacy/types.ts:164:3 - (ae-forgotten-export) The symbol "VarsReplacer" needs to be exported by the entry point index.d.ts
2473+
// src/core/server/legacy/types.ts:165:3 - (ae-forgotten-export) The symbol "LegacyNavLinkSpec" needs to be exported by the entry point index.d.ts
2474+
// src/core/server/legacy/types.ts:166:3 - (ae-forgotten-export) The symbol "LegacyAppSpec" needs to be exported by the entry point index.d.ts
2475+
// src/core/server/legacy/types.ts:167:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts
24762476
// src/core/server/plugins/types.ts:230:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
24772477
// src/core/server/plugins/types.ts:230:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
24782478
// src/core/server/plugins/types.ts:232:3 - (ae-forgotten-export) The symbol "PathConfigType" needs to be exported by the entry point index.d.ts

0 commit comments

Comments
 (0)