From 896965d5b70f34075b9b6c5a3b87a97cfbb8841b Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 26 Apr 2016 14:29:45 -0700 Subject: [PATCH 1/4] Plugins: Add preInit capability --- src/server/plugins/initialize.js | 4 ++++ src/server/plugins/plugin.js | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/server/plugins/initialize.js b/src/server/plugins/initialize.js index f54a6d3627b56..751e9a4a7500e 100644 --- a/src/server/plugins/initialize.js +++ b/src/server/plugins/initialize.js @@ -40,6 +40,10 @@ module.exports = async function (kbnServer, server, config) { path.pop(); }; + for (let plugin of plugins) { + await plugin.preInit(); + } + for (let {id} of plugins) { await initialize(id); } diff --git a/src/server/plugins/plugin.js b/src/server/plugins/plugin.js index dfccce43c8331..b059c99f82416 100644 --- a/src/server/plugins/plugin.js +++ b/src/server/plugins/plugin.js @@ -59,9 +59,11 @@ module.exports = class Plugin { this.uiExportsSpecs = opts.uiExports || {}; this.requiredIds = opts.require || []; this.version = opts.version || pkg.version; + this.externalPreInit = opts.preInit || _.noop; this.externalInit = opts.init || _.noop; this.configPrefix = opts.configPrefix || this.id; this.getConfigSchema = opts.config || _.noop; + this.preInit = _.once(this.preInit); this.init = _.once(this.init); this[extendInitFns] = []; @@ -100,6 +102,10 @@ module.exports = class Plugin { } } + async preInit() { + return await this.externalPreInit(this.kbnServer.server); + } + async init() { let { id, version, kbnServer, configPrefix } = this; let { config } = kbnServer; From 4ae4c4e66a34742e66f59019199fc6fea583da18 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Wed, 27 Apr 2016 10:32:37 -0700 Subject: [PATCH 2/4] Make plugin preInit follow dependency tree just like init --- src/server/plugins/initialize.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/server/plugins/initialize.js b/src/server/plugins/initialize.js index 751e9a4a7500e..f5785479fa85e 100644 --- a/src/server/plugins/initialize.js +++ b/src/server/plugins/initialize.js @@ -19,7 +19,7 @@ module.exports = async function (kbnServer, server, config) { let path = []; - const initialize = async function (id) { + const initialize = async function (id, fn) { let plugin = plugins.byId[id]; if (includes(path, id)) { @@ -33,18 +33,18 @@ module.exports = async function (kbnServer, server, config) { throw new Error(`Unmet requirement "${reqId}" for plugin "${id}"`); } - await initialize(reqId); + await initialize(reqId, fn); } - await plugin.init(); + await plugin[fn](); path.pop(); }; - for (let plugin of plugins) { - await plugin.preInit(); + for (let {id} of plugins) { + await initialize(id, 'preInit'); } for (let {id} of plugins) { - await initialize(id); + await initialize(id, 'init'); } }; From 6f986b3ee9b6ee27742d679f3ac2a937de5d930c Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Wed, 27 Apr 2016 16:02:16 -0700 Subject: [PATCH 3/4] Separate initialize into its own module and write tests --- src/server/plugins/__tests__/plugin_init.js | 77 +++++++++++++++++++++ src/server/plugins/initialize.js | 34 +-------- src/server/plugins/plugin_init.js | 35 ++++++++++ 3 files changed, 115 insertions(+), 31 deletions(-) create mode 100644 src/server/plugins/__tests__/plugin_init.js create mode 100644 src/server/plugins/plugin_init.js diff --git a/src/server/plugins/__tests__/plugin_init.js b/src/server/plugins/__tests__/plugin_init.js new file mode 100644 index 0000000000000..e84325fd5275b --- /dev/null +++ b/src/server/plugins/__tests__/plugin_init.js @@ -0,0 +1,77 @@ +import {values} from 'lodash'; +import expect from 'expect.js'; +import sinon from 'auto-release-sinon'; +import pluginInit from '../plugin_init'; + +describe.only('Plugin init', () => { + const getPluginCollection = (plugins) => ({ + byId: plugins, + toArray: () => values(plugins) + }); + + it('should call preInit before init', async () => { + const plugins = { + foo: { + id: 'foo', + init: sinon.spy(), + preInit: sinon.spy(), + requiredIds: [] + }, + bar: { + id: 'bar', + init: sinon.spy(), + preInit: sinon.spy(), + requiredIds: [] + }, + baz: { + id: 'baz', + init: sinon.spy(), + preInit: sinon.spy(), + requiredIds: [] + } + }; + + await pluginInit(getPluginCollection(plugins)); + + expect(plugins.foo.preInit.calledBefore(plugins.foo.init)).to.be.ok(); + expect(plugins.foo.preInit.calledBefore(plugins.bar.init)).to.be.ok(); + expect(plugins.foo.preInit.calledBefore(plugins.baz.init)).to.be.ok(); + + expect(plugins.bar.preInit.calledBefore(plugins.foo.init)).to.be.ok(); + expect(plugins.bar.preInit.calledBefore(plugins.bar.init)).to.be.ok(); + expect(plugins.bar.preInit.calledBefore(plugins.baz.init)).to.be.ok(); + + expect(plugins.baz.preInit.calledBefore(plugins.foo.init)).to.be.ok(); + expect(plugins.baz.preInit.calledBefore(plugins.bar.init)).to.be.ok(); + expect(plugins.baz.preInit.calledBefore(plugins.baz.init)).to.be.ok(); + }); + + it('should call preInits in correct order based on requirements', async () => { + const plugins = { + foo: { + id: 'foo', + init: sinon.spy(), + preInit: sinon.spy(), + requiredIds: ['bar', 'baz'] + }, + bar: { + id: 'bar', + init: sinon.spy(), + preInit: sinon.spy(), + requiredIds: [] + }, + baz: { + id: 'baz', + init: sinon.spy(), + preInit: sinon.spy(), + requiredIds: ['bar'] + } + }; + + await pluginInit(getPluginCollection(plugins)); + + expect(plugins.bar.preInit.firstCall.calledBefore(plugins.foo.init.firstCall)).to.be.ok(); + expect(plugins.bar.preInit.firstCall.calledBefore(plugins.baz.init.firstCall)).to.be.ok(); + expect(plugins.baz.preInit.firstCall.calledBefore(plugins.foo.init.firstCall)).to.be.ok(); + }); +}); diff --git a/src/server/plugins/initialize.js b/src/server/plugins/initialize.js index f5785479fa85e..402b750fbcc03 100644 --- a/src/server/plugins/initialize.js +++ b/src/server/plugins/initialize.js @@ -1,4 +1,5 @@ -import { includes, keys } from 'lodash'; +import pluginInit from './plugin_init'; + module.exports = async function (kbnServer, server, config) { if (!config.get('plugins.initialize')) { @@ -17,34 +18,5 @@ module.exports = async function (kbnServer, server, config) { }); - - let path = []; - const initialize = async function (id, fn) { - let plugin = plugins.byId[id]; - - if (includes(path, id)) { - throw new Error(`circular dependencies found: "${path.concat(id).join(' -> ')}"`); - } - - path.push(id); - - for (let reqId of plugin.requiredIds) { - if (!plugins.byId[reqId]) { - throw new Error(`Unmet requirement "${reqId}" for plugin "${id}"`); - } - - await initialize(reqId, fn); - } - - await plugin[fn](); - path.pop(); - }; - - for (let {id} of plugins) { - await initialize(id, 'preInit'); - } - - for (let {id} of plugins) { - await initialize(id, 'init'); - } + await pluginInit(plugins); }; diff --git a/src/server/plugins/plugin_init.js b/src/server/plugins/plugin_init.js new file mode 100644 index 0000000000000..8f5e9e3184478 --- /dev/null +++ b/src/server/plugins/plugin_init.js @@ -0,0 +1,35 @@ +import { includes } from 'lodash'; + +export default async (plugins) => { + let path = []; + + const initialize = async function (id, fn) { + let plugin = plugins.byId[id]; + + if (includes(path, id)) { + throw new Error(`circular dependencies found: "${path.concat(id).join(' -> ')}"`); + } + + path.push(id); + + for (let reqId of plugin.requiredIds) { + if (!plugins.byId[reqId]) { + throw new Error(`Unmet requirement "${reqId}" for plugin "${id}"`); + } + + await initialize(reqId, fn); + } + + await plugin[fn](); + path.pop(); + }; + + const collection = plugins.toArray(); + for (let {id} of collection) { + await initialize(id, 'preInit'); + } + + for (let {id} of collection) { + await initialize(id, 'init'); + } +}; From 0e947a59ba0561011c0cc8c48601d6a3310738dc Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Wed, 27 Apr 2016 16:02:42 -0700 Subject: [PATCH 4/4] Remove .only from test --- src/server/plugins/__tests__/plugin_init.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/plugins/__tests__/plugin_init.js b/src/server/plugins/__tests__/plugin_init.js index e84325fd5275b..1a38d334969ec 100644 --- a/src/server/plugins/__tests__/plugin_init.js +++ b/src/server/plugins/__tests__/plugin_init.js @@ -3,7 +3,7 @@ import expect from 'expect.js'; import sinon from 'auto-release-sinon'; import pluginInit from '../plugin_init'; -describe.only('Plugin init', () => { +describe('Plugin init', () => { const getPluginCollection = (plugins) => ({ byId: plugins, toArray: () => values(plugins)