Skip to content

Commit daebba1

Browse files
committed
PR review feedback
* Improve error message * Add source field to PluginWrapper
1 parent c54c2b5 commit daebba1

File tree

4 files changed

+84
-68
lines changed

4 files changed

+84
-68
lines changed

src/core/server/plugins/plugin.test.ts

+44
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ jest.doMock(join('plugin-with-wrong-initializer-path', 'server'), () => ({ plugi
3939
virtual: true,
4040
});
4141

42+
const OSS_PLUGIN_PATH_POSIX = '/kibana/src/plugins/ossPlugin';
43+
const OSS_PLUGIN_PATH_WINDOWS = 'C:\\kibana\\src\\plugins\\ossPlugin';
44+
const XPACK_PLUGIN_PATH_POSIX = '/kibana/x-pack/plugins/xPackPlugin';
45+
const XPACK_PLUGIN_PATH_WINDOWS = 'C:\\kibana\\x-pack\\plugins\\xPackPlugin';
46+
4247
function createPluginManifest(manifestProps: Partial<PluginManifest> = {}): PluginManifest {
4348
return {
4449
id: 'some-plugin-id',
@@ -97,10 +102,49 @@ test('`constructor` correctly initializes plugin instance', () => {
97102
expect(plugin.name).toBe('some-plugin-id');
98103
expect(plugin.configPath).toBe('path');
99104
expect(plugin.path).toBe('some-plugin-path');
105+
expect(plugin.source).toBe('external'); // see below for test cases for non-external sources (OSS and X-Pack)
100106
expect(plugin.requiredPlugins).toEqual(['some-required-dep']);
101107
expect(plugin.optionalPlugins).toEqual(['some-optional-dep']);
102108
});
103109

110+
describe('`constructor` correctly sets non-external source', () => {
111+
function createPlugin(path: string) {
112+
const manifest = createPluginManifest();
113+
const opaqueId = Symbol();
114+
return new PluginWrapper({
115+
path,
116+
manifest,
117+
opaqueId,
118+
initializerContext: createPluginInitializerContext(
119+
coreContext,
120+
opaqueId,
121+
manifest,
122+
instanceInfo
123+
),
124+
});
125+
}
126+
127+
test('for OSS plugin in POSIX', () => {
128+
const plugin = createPlugin(OSS_PLUGIN_PATH_POSIX);
129+
expect(plugin.source).toBe('oss');
130+
});
131+
132+
test('for OSS plugin in Windows', () => {
133+
const plugin = createPlugin(OSS_PLUGIN_PATH_WINDOWS);
134+
expect(plugin.source).toBe('oss');
135+
});
136+
137+
test('for X-Pack plugin in POSIX', () => {
138+
const plugin = createPlugin(XPACK_PLUGIN_PATH_POSIX);
139+
expect(plugin.source).toBe('x-pack');
140+
});
141+
142+
test('for X-Pack plugin in Windows', () => {
143+
const plugin = createPlugin(XPACK_PLUGIN_PATH_WINDOWS);
144+
expect(plugin.source).toBe('x-pack');
145+
});
146+
});
147+
104148
test('`setup` fails if `plugin` initializer is not exported', () => {
105149
const manifest = createPluginManifest();
106150
const opaqueId = Symbol();

src/core/server/plugins/plugin.ts

+14
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ import {
2727
} from './types';
2828
import { CorePreboot, CoreSetup, CoreStart } from '..';
2929

30+
const OSS_PATH_REGEX = /[\/|\\]src[\/|\\]plugins[\/|\\]/; // Matches src/plugins directory on POSIX and Windows
31+
const XPACK_PATH_REGEX = /[\/|\\]x-pack[\/|\\]plugins[\/|\\]/; // Matches x-pack/plugins directory on POSIX and Windows
32+
3033
/**
3134
* Lightweight wrapper around discovered plugin that is responsible for instantiating
3235
* plugin and dispatching proper context and dependencies into plugin's lifecycle hooks.
@@ -40,6 +43,7 @@ export class PluginWrapper<
4043
TPluginsStart extends object = object
4144
> {
4245
public readonly path: string;
46+
public readonly source: 'oss' | 'x-pack' | 'external';
4347
public readonly manifest: PluginManifest;
4448
public readonly opaqueId: PluginOpaqueId;
4549
public readonly name: PluginManifest['id'];
@@ -70,6 +74,7 @@ export class PluginWrapper<
7074
}
7175
) {
7276
this.path = params.path;
77+
this.source = getPluginSource(params.path);
7378
this.manifest = params.manifest;
7479
this.opaqueId = params.opaqueId;
7580
this.initializerContext = params.initializerContext;
@@ -204,3 +209,12 @@ export class PluginWrapper<
204209
return this.manifest.type === PluginType.preboot;
205210
}
206211
}
212+
213+
function getPluginSource(path: string): 'oss' | 'x-pack' | 'external' {
214+
if (OSS_PATH_REGEX.test(path)) {
215+
return 'oss';
216+
} else if (XPACK_PATH_REGEX.test(path)) {
217+
return 'x-pack';
218+
}
219+
return 'external';
220+
}

src/core/server/plugins/plugins_service.test.ts

+23-62
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,9 @@ expect.addSnapshotSerializer(createAbsolutePathSerializer());
5252
});
5353
});
5454

55-
const OSS_PLUGIN_PATH_POSIX = '/kibana/src/plugins/ossPlugin';
56-
const OSS_PLUGIN_PATH_WINDOWS = 'C:\\kibana\\src\\plugins\\ossPlugin';
57-
const XPACK_PLUGIN_PATH_POSIX = '/kibana/x-pack/plugins/xPackPlugin';
58-
const XPACK_PLUGIN_PATH_WINDOWS = 'C:\\kibana\\x-pack\\plugins\\xPackPlugin';
59-
[
60-
OSS_PLUGIN_PATH_POSIX,
61-
OSS_PLUGIN_PATH_WINDOWS,
62-
XPACK_PLUGIN_PATH_POSIX,
63-
XPACK_PLUGIN_PATH_WINDOWS,
64-
].forEach((path) => {
55+
const OSS_PLUGIN_PATH = '/kibana/src/plugins/ossPlugin';
56+
const XPACK_PLUGIN_PATH = '/kibana/x-pack/plugins/xPackPlugin';
57+
[OSS_PLUGIN_PATH, XPACK_PLUGIN_PATH].forEach((path) => {
6558
jest.doMock(join(path, 'server'), () => ({}), {
6659
virtual: true,
6760
});
@@ -272,6 +265,7 @@ describe('PluginsService', () => {
272265
xPackPath: string;
273266
dependency: 'requiredPlugin' | 'requiredBundle' | 'optionalPlugin';
274267
}) {
268+
// Each plugin's source is derived from its path; the PluginWrapper test suite contains more detailed test cases around the paths (for both POSIX and Windows)
275269
mockDiscover.mockReturnValue({
276270
error$: from([]),
277271
plugin$: from([
@@ -296,7 +290,7 @@ describe('PluginsService', () => {
296290

297291
async function expectError() {
298292
await expect(pluginsService.discover({ environment: environmentPreboot })).rejects.toThrow(
299-
`X-Pack plugin or bundle with id "xPackPlugin" is required by OSS plugin "ossPlugin", which is prohibited.`
293+
`X-Pack plugin or bundle with id "xPackPlugin" is required by OSS plugin "ossPlugin", which is prohibited. Consider making this an optional dependency instead.`
300294
);
301295
expect(standardMockPluginSystem.addPlugin).not.toHaveBeenCalled();
302296
}
@@ -307,64 +301,31 @@ describe('PluginsService', () => {
307301
expect(standardMockPluginSystem.addPlugin).toHaveBeenCalledTimes(2);
308302
}
309303

310-
describe('throws if an OSS plugin requires an X-Pack plugin', () => {
311-
it('in POSIX', async () => {
312-
mockDiscoveryResults({
313-
ossPath: OSS_PLUGIN_PATH_POSIX,
314-
xPackPath: XPACK_PLUGIN_PATH_POSIX,
315-
dependency: 'requiredPlugin',
316-
});
317-
await expectError();
318-
});
319-
320-
it('in Windows', async () => {
321-
mockDiscoveryResults({
322-
ossPath: OSS_PLUGIN_PATH_WINDOWS,
323-
xPackPath: XPACK_PLUGIN_PATH_WINDOWS,
324-
dependency: 'requiredPlugin',
325-
});
326-
await expectError();
304+
it('throws if an OSS plugin requires an X-Pack plugin', async () => {
305+
mockDiscoveryResults({
306+
ossPath: OSS_PLUGIN_PATH,
307+
xPackPath: XPACK_PLUGIN_PATH,
308+
dependency: 'requiredPlugin',
327309
});
310+
await expectError();
328311
});
329312

330-
describe('throws if an OSS plugin requires an X-Pack bundle', () => {
331-
it('in POSIX', async () => {
332-
mockDiscoveryResults({
333-
ossPath: OSS_PLUGIN_PATH_POSIX,
334-
xPackPath: XPACK_PLUGIN_PATH_POSIX,
335-
dependency: 'requiredBundle',
336-
});
337-
await expectError();
338-
});
339-
340-
it('in Windows', async () => {
341-
mockDiscoveryResults({
342-
ossPath: OSS_PLUGIN_PATH_WINDOWS,
343-
xPackPath: XPACK_PLUGIN_PATH_WINDOWS,
344-
dependency: 'requiredBundle',
345-
});
346-
await expectError();
313+
it('throws if an OSS plugin requires an X-Pack bundle', async () => {
314+
mockDiscoveryResults({
315+
ossPath: OSS_PLUGIN_PATH,
316+
xPackPath: XPACK_PLUGIN_PATH,
317+
dependency: 'requiredBundle',
347318
});
319+
await expectError();
348320
});
349321

350-
describe('does not throw if an OSS plugin has an optional dependency on an X-Pack plugin', () => {
351-
it('in POSIX', async () => {
352-
mockDiscoveryResults({
353-
ossPath: OSS_PLUGIN_PATH_POSIX,
354-
xPackPath: XPACK_PLUGIN_PATH_POSIX,
355-
dependency: 'optionalPlugin',
356-
});
357-
await expectSuccess();
358-
});
359-
360-
it('in Windows', async () => {
361-
mockDiscoveryResults({
362-
ossPath: OSS_PLUGIN_PATH_WINDOWS,
363-
xPackPath: XPACK_PLUGIN_PATH_WINDOWS,
364-
dependency: 'optionalPlugin',
365-
});
366-
await expectSuccess();
322+
it('does not throw if an OSS plugin has an optional dependency on an X-Pack plugin', async () => {
323+
mockDiscoveryResults({
324+
ossPath: OSS_PLUGIN_PATH,
325+
xPackPath: XPACK_PLUGIN_PATH,
326+
dependency: 'optionalPlugin',
367327
});
328+
await expectSuccess();
368329
});
369330
});
370331

src/core/server/plugins/plugins_service.ts

+3-6
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,6 @@ export interface PluginsServiceDiscoverDeps {
8686
environment: InternalEnvironmentServicePreboot;
8787
}
8888

89-
const OSS_PATH_REGEX = /[\/|\\]src[\/|\\]plugins[\/|\\]/; // Matches src/plugins directory on POSIX and Windows
90-
const XPACK_PATH_REGEX = /[\/|\\]x-pack[\/|\\]plugins[\/|\\]/; // Matches x-pack/plugins directory on POSIX and Windows
91-
9289
/** @internal */
9390
export class PluginsService implements CoreService<PluginsServiceSetup, PluginsServiceStart> {
9491
private readonly log: Logger;
@@ -340,12 +337,12 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
340337
}
341338

342339
// validate that OSS plugins do not have required dependencies on X-Pack plugins
343-
if (OSS_PATH_REGEX.test(plugin.path)) {
340+
if (plugin.source === 'oss') {
344341
for (const id of [...plugin.requiredPlugins, ...plugin.requiredBundles]) {
345342
const requiredPlugin = pluginEnableStatuses.get(id);
346-
if (requiredPlugin && XPACK_PATH_REGEX.test(requiredPlugin.plugin.path)) {
343+
if (requiredPlugin && requiredPlugin.plugin.source === 'x-pack') {
347344
throw new Error(
348-
`X-Pack plugin or bundle with id "${id}" is required by OSS plugin "${pluginName}", which is prohibited.`
345+
`X-Pack plugin or bundle with id "${id}" is required by OSS plugin "${pluginName}", which is prohibited. Consider making this an optional dependency instead.`
349346
);
350347
}
351348
}

0 commit comments

Comments
 (0)