mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Allow LP plugins to access NP plugin context providers (#47639)
This commit is contained in:
parent
b267704c49
commit
b03dfdf68a
15 changed files with 126 additions and 60 deletions
|
@ -168,6 +168,22 @@ describe('#setup()', () => {
|
|||
expect(MockContextService.setup).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('injects legacy dependency to context#setup()', async () => {
|
||||
const pluginA = Symbol();
|
||||
const pluginB = Symbol();
|
||||
const pluginDependencies = new Map<symbol, symbol[]>([[pluginA, []], [pluginB, [pluginA]]]);
|
||||
MockPluginsService.getOpaqueIds.mockReturnValue(pluginDependencies);
|
||||
await setupCore();
|
||||
|
||||
expect(MockContextService.setup).toHaveBeenCalledWith({
|
||||
pluginDependencies: new Map([
|
||||
[pluginA, []],
|
||||
[pluginB, [pluginA]],
|
||||
[MockLegacyPlatformService.legacyId, [pluginA, pluginB]],
|
||||
]),
|
||||
});
|
||||
});
|
||||
|
||||
it('calls injectedMetadata#setup()', async () => {
|
||||
await setupCore();
|
||||
expect(MockInjectedMetadataService.setup).toHaveBeenCalledTimes(1);
|
||||
|
|
|
@ -161,9 +161,14 @@ export class CoreSystem {
|
|||
|
||||
const pluginDependencies = this.plugins.getOpaqueIds();
|
||||
const context = this.context.setup({
|
||||
// We inject a fake "legacy plugin" with no dependencies so that legacy plugins can register context providers
|
||||
// that will only be available to other legacy plugins and will not leak into New Platform plugins.
|
||||
pluginDependencies: new Map([...pluginDependencies, [this.legacy.legacyId, []]]),
|
||||
// We inject a fake "legacy plugin" with dependencies on every plugin so that legacy plugins:
|
||||
// 1) Can access context from any NP plugin
|
||||
// 2) Can register context providers that will only be available to other legacy plugins and will not leak into
|
||||
// New Platform plugins.
|
||||
pluginDependencies: new Map([
|
||||
...pluginDependencies,
|
||||
[this.legacy.legacyId, [...pluginDependencies.keys()]],
|
||||
]),
|
||||
});
|
||||
const application = this.application.setup({ context });
|
||||
|
||||
|
|
|
@ -18,9 +18,11 @@
|
|||
*/
|
||||
import { LegacyPlatformService } from './legacy_service';
|
||||
|
||||
type LegacyPlatformServiceContract = PublicMethodsOf<LegacyPlatformService>;
|
||||
// Use Required to get only public properties
|
||||
type LegacyPlatformServiceContract = Required<LegacyPlatformService>;
|
||||
const createMock = () => {
|
||||
const mocked: jest.Mocked<LegacyPlatformServiceContract> = {
|
||||
legacyId: Symbol(),
|
||||
setup: jest.fn(),
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
|
|
|
@ -36,6 +36,7 @@ jest.doMock('./elasticsearch/elasticsearch_service', () => ({
|
|||
}));
|
||||
|
||||
export const mockLegacyService = {
|
||||
legacyId: Symbol(),
|
||||
setup: jest.fn().mockReturnValue({ uiExports: {} }),
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
|
@ -55,3 +56,9 @@ export const mockSavedObjectsService = savedObjectsServiceMock.create();
|
|||
jest.doMock('./saved_objects/saved_objects_service', () => ({
|
||||
SavedObjectsService: jest.fn(() => mockSavedObjectsService),
|
||||
}));
|
||||
|
||||
import { contextServiceMock } from './context/context_service.mock';
|
||||
export const mockContextService = contextServiceMock.create();
|
||||
jest.doMock('./context/context_service', () => ({
|
||||
ContextService: jest.fn(() => mockContextService),
|
||||
}));
|
|
@ -24,7 +24,8 @@ import {
|
|||
mockPluginsService,
|
||||
mockConfigService,
|
||||
mockSavedObjectsService,
|
||||
} from './index.test.mocks';
|
||||
mockContextService,
|
||||
} from './server.test.mocks';
|
||||
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { Env, Config, ObjectToConfigAdapter } from './config';
|
||||
|
@ -64,6 +65,25 @@ test('sets up services on "setup"', async () => {
|
|||
expect(mockSavedObjectsService.setup).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('injects legacy dependency to context#setup()', async () => {
|
||||
const server = new Server(config$, env, logger);
|
||||
|
||||
const pluginA = Symbol();
|
||||
const pluginB = Symbol();
|
||||
const pluginDependencies = new Map<symbol, symbol[]>([[pluginA, []], [pluginB, [pluginA]]]);
|
||||
mockPluginsService.discover.mockResolvedValue(pluginDependencies);
|
||||
|
||||
await server.setup();
|
||||
|
||||
expect(mockContextService.setup).toHaveBeenCalledWith({
|
||||
pluginDependencies: new Map([
|
||||
[pluginA, []],
|
||||
[pluginB, [pluginA]],
|
||||
[mockLegacyService.legacyId, [pluginA, pluginB]],
|
||||
]),
|
||||
});
|
||||
});
|
||||
|
||||
test('runs services on "start"', async () => {
|
||||
const server = new Server(config$, env, logger);
|
||||
|
||||
|
|
|
@ -78,9 +78,14 @@ export class Server {
|
|||
// Discover any plugins before continuing. This allows other systems to utilize the plugin dependency graph.
|
||||
const pluginDependencies = await this.plugins.discover();
|
||||
const contextServiceSetup = this.context.setup({
|
||||
// We inject a fake "legacy plugin" with no dependencies so that legacy plugins can register context providers
|
||||
// that will only be available to other legacy plugins and will not leak into New Platform plugins.
|
||||
pluginDependencies: new Map([...pluginDependencies, [this.legacy.legacyId, []]]),
|
||||
// We inject a fake "legacy plugin" with dependencies on every plugin so that legacy plugins:
|
||||
// 1) Can access context from any NP plugin
|
||||
// 2) Can register context providers that will only be available to other legacy plugins and will not leak into
|
||||
// New Platform plugins.
|
||||
pluginDependencies: new Map([
|
||||
...pluginDependencies,
|
||||
[this.legacy.legacyId, [...pluginDependencies.keys()]],
|
||||
]),
|
||||
});
|
||||
|
||||
const httpSetup = await this.http.setup({
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { services } from './services';
|
||||
|
||||
export default async function ({ readConfigFile }) {
|
||||
const functionalConfig = await readConfigFile(require.resolve('../functional/config'));
|
||||
|
@ -48,7 +49,10 @@ export default async function ({ readConfigFile }) {
|
|||
|
||||
require.resolve('./test_suites/core_plugins'),
|
||||
],
|
||||
services: functionalConfig.get('services'),
|
||||
services: {
|
||||
...functionalConfig.get('services'),
|
||||
...services,
|
||||
},
|
||||
pageObjects: functionalConfig.get('pageObjects'),
|
||||
servers: functionalConfig.get('servers'),
|
||||
esTestCluster: functionalConfig.get('esTestCluster'),
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"name": "core_legacy_compat",
|
||||
"version": "1.0.0",
|
||||
"main": "target/test/plugin_functional/plugins/core_legacy_compat",
|
||||
"kibana": {
|
||||
"version": "kibana",
|
||||
"templateVersion": "1.0.0"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"kbn": "node ../../../../scripts/kbn.js",
|
||||
"build": "rm -rf './target' && tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "3.5.3"
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"extends": "../../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./target",
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"index.ts",
|
||||
"public/**/*.ts",
|
||||
"public/**/*.tsx",
|
||||
"../../../../typings/**/*"
|
||||
],
|
||||
"exclude": []
|
||||
}
|
|
@ -24,6 +24,13 @@ export default function(kibana: any) {
|
|||
return new kibana.Plugin({
|
||||
id: 'core_plugin_legacy',
|
||||
require: ['kibana'],
|
||||
uiExports: {
|
||||
app: {
|
||||
title: 'Core Legacy Compat',
|
||||
description: 'This is a sample plugin to test core to legacy compatibility',
|
||||
main: 'plugins/core_plugin_legacy/index',
|
||||
},
|
||||
},
|
||||
init(server: KbnServer) {
|
||||
const { http } = server.newPlatform.setup.core;
|
||||
const router = http.createRouter();
|
||||
|
@ -32,6 +39,11 @@ export default function(kibana: any) {
|
|||
const response = await context.core.elasticsearch.adminClient.callAsInternalUser('ping');
|
||||
return res.ok({ body: `Pong in legacy via new platform: ${response}` });
|
||||
});
|
||||
|
||||
router.get({ path: '/api/np-context-in-legacy', validate: false }, (context, req, res) => {
|
||||
const contexts = Object.keys(context);
|
||||
return res.ok({ body: { contexts } });
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
24
test/plugin_functional/services/index.js
Normal file
24
test/plugin_functional/services/index.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { KibanaSupertestProvider } from './supertest';
|
||||
|
||||
export const services = {
|
||||
supertest: KibanaSupertestProvider,
|
||||
};
|
|
@ -17,19 +17,13 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { Server } from 'hapi';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function(kibana: any) {
|
||||
return new kibana.Plugin({
|
||||
uiExports: {
|
||||
app: {
|
||||
title: 'Core Legacy Compat',
|
||||
description: 'This is a sample plugin to test core to legacy compatibility',
|
||||
main: 'plugins/core_legacy_compat/index',
|
||||
},
|
||||
},
|
||||
import { format as formatUrl } from 'url';
|
||||
|
||||
init(server: Server) {},
|
||||
});
|
||||
import supertestAsPromised from 'supertest-as-promised';
|
||||
|
||||
export function KibanaSupertestProvider({ getService }) {
|
||||
const config = getService('config');
|
||||
const kibanaServerUrl = formatUrl(config.get('servers.kibana'));
|
||||
return supertestAsPromised(kibanaServerUrl);
|
||||
}
|
|
@ -21,21 +21,29 @@ import expect from '@kbn/expect';
|
|||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const PageObjects = getPageObjects(['common']);
|
||||
const browser = getService('browser');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const supertest = getService('supertest');
|
||||
|
||||
describe('legacy plugins', function describeIndexTests() {
|
||||
it('have access to New Platform HTTP service', async () => {
|
||||
const url = `${PageObjects.common.getHostPort()}/api/np-http-in-legacy`;
|
||||
await browser.get(url);
|
||||
describe('http', () => {
|
||||
it('has access to New Platform HTTP service', async () => {
|
||||
await supertest
|
||||
.get('/api/np-http-in-legacy')
|
||||
.expect(200)
|
||||
.expect('Pong in legacy via new platform: true');
|
||||
});
|
||||
|
||||
const pageSource = await browser.execute('return window.document.body.textContent;');
|
||||
expect(pageSource).to.equal('Pong in legacy via new platform: true');
|
||||
it('has access to New Platform HTTP context providers', async () => {
|
||||
await supertest
|
||||
.get('/api/np-context-in-legacy')
|
||||
.expect(200)
|
||||
.expect(JSON.stringify({ contexts: ['core', 'search', 'pluginA'] }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('application service compatibility layer', function describeIndexTests() {
|
||||
it('can render legacy apps', async () => {
|
||||
await PageObjects.common.navigateToApp('core_legacy_compat');
|
||||
await PageObjects.common.navigateToApp('core_plugin_legacy');
|
||||
expect(await testSubjects.exists('coreLegacyCompatH1')).to.be(true);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue