Merge pull request #6546 from spalger/implement/uiExportsInjectVars

[uiExports] add uiExport type "injectDefaultVars"
This commit is contained in:
Joe Fleming 2016-03-18 14:15:06 -07:00
commit 6c9c9b96f1
14 changed files with 199 additions and 31 deletions

View file

@ -33,6 +33,16 @@ module.exports = function ({ Plugin }) {
}).default();
},
uiExports: {
injectDefaultVars(server, options) {
return {
esRequestTimeout: options.requestTimeout,
esShardTimeout: options.shardTimeout,
esApiVersion: options.apiVersion,
};
}
},
init(server, options) {
const kibanaIndex = server.config().get('kibana.index');

View file

@ -1,9 +1,8 @@
import expect from 'expect.js';
import util from 'util';
import { format } from 'util';
import * as kbnTestServer from '../../../../../test/utils/kbn_server';
const format = util.format;
import fromRoot from '../../../../utils/from_root';
describe('plugins/elasticsearch', function () {
describe('routes', function () {
@ -13,7 +12,13 @@ describe('plugins/elasticsearch', function () {
before(function () {
this.timeout(60000); // sometimes waiting for server takes longer than 10
kbnServer = kbnTestServer.createServer();
kbnServer = kbnTestServer.createServer({
plugins: {
scanDirs: [
fromRoot('src/plugins')
]
}
});
return kbnServer.ready()
.then(() => kbnServer.server.plugins.elasticsearch.waitUntilReady());
});

View file

@ -34,7 +34,13 @@ module.exports = function (kibana) {
kbnDefaultAppId: config.get('kibana.defaultAppId')
};
}
}
},
injectDefaultVars(server, options) {
return {
kbnIndex: options.index
};
},
},
init: function (server, options) {

View file

@ -1,9 +1,11 @@
import _ from 'lodash';
import Joi from 'joi';
import { attempt, fromNode } from 'bluebird';
import Bluebird, { attempt, fromNode } from 'bluebird';
import { basename, resolve } from 'path';
import { inherits } from 'util';
const extendInitFns = Symbol('extend plugin initialization');
const defaultConfigSchema = Joi.object({
enabled: Joi.boolean().default(true)
}).default();
@ -57,6 +59,7 @@ module.exports = class Plugin {
this.externalInit = opts.init || _.noop;
this.getConfigSchema = opts.config || _.noop;
this.init = _.once(this.init);
this[extendInitFns] = [];
if (opts.publicDir === false) {
this.publicDir = null;
@ -98,14 +101,12 @@ module.exports = class Plugin {
let { config } = kbnServer;
// setup the hapi register function and get on with it
let register = (server, options, next) => {
const asyncRegister = async (server, options) => {
this.server = server;
// bind the server and options to all
// apps created by this plugin
for (let app of this.apps) {
app.getInjectedVars = _.partial(app.getInjectedVars, server, options);
}
await Promise.all(this[extendInitFns].map(async fn => {
await fn.call(this, server, options);
}));
server.log(['plugins', 'debug'], {
tmpl: 'Initializing plugin <%= plugin.id %>',
@ -119,7 +120,11 @@ module.exports = class Plugin {
this.status = kbnServer.status.create(`plugin:${this.id}`);
server.expose('status', this.status);
attempt(this.externalInit, [server, options], this).nodeify(next);
return await attempt(this.externalInit, [server, options], this);
};
const register = (server, options, next) => {
Bluebird.resolve(asyncRegister(server, options)).nodeify(next);
};
register.attributes = { name: id, version: version };
@ -138,6 +143,10 @@ module.exports = class Plugin {
}
}
extendInit(fn) {
this[extendInitFns].push(fn);
}
toJSON() {
return this.pkg;
}

View file

@ -0,0 +1,18 @@
import Bluebird from 'bluebird';
export default kibana => new kibana.Plugin({
config(Joi) {
return Joi.object().keys({
enabled: Joi.boolean().default(true),
delay: Joi.number().required(),
shared: Joi.string(),
}).default();
},
uiExports: {
async injectDefaultVars(server, options) {
await Bluebird.delay(options.delay);
return { shared: options.shared };
}
}
});

View file

@ -0,0 +1,4 @@
{
"name": "plugin_async_foo",
"version": "0.0.0"
}

View file

@ -0,0 +1,14 @@
export default kibana => new kibana.Plugin({
config(Joi) {
return Joi.object().keys({
enabled: Joi.boolean().default(true),
shared: Joi.string()
}).default();
},
uiExports: {
injectDefaultVars(server, options) {
return { shared: options.shared };
}
}
});

View file

@ -0,0 +1,4 @@
{
"name": "plugin_bar",
"version": "0.0.0"
}

View file

@ -0,0 +1,14 @@
export default kibana => new kibana.Plugin({
config(Joi) {
return Joi.object().keys({
enabled: Joi.boolean().default(true),
shared: Joi.string()
}).default();
},
uiExports: {
injectDefaultVars(server, options) {
return { shared: options.shared };
}
}
});

View file

@ -0,0 +1,4 @@
{
"name": "plugin_foo",
"version": "0.0.0"
}

View file

@ -1,6 +1,8 @@
import expect from 'expect.js';
import { resolve } from 'path';
import UiExports from '../ui_exports';
import * as kbnTestServer from '../../../test/utils/kbn_server';
describe('UiExports', function () {
describe('#find()', function () {
@ -23,4 +25,83 @@ describe('UiExports', function () {
expect(uiExports.find(['foo', 'bar'])).to.eql(['a', 'b', 'c']);
});
});
//
describe('#defaultInjectedVars', function () {
context('two plugins, two sync', function () {
this.slow(10000);
this.timeout(60000);
let kbnServer;
before(async function () {
kbnServer = kbnTestServer.createServer({
plugins: {
paths: [
resolve(__dirname, 'fixtures/plugin_bar'),
resolve(__dirname, 'fixtures/plugin_foo')
]
},
plugin_foo: {
shared: 'foo'
},
plugin_bar: {
shared: 'bar'
}
});
await kbnServer.ready();
});
after(async function () {
await kbnServer.close();
});
it('merges the two plugins in the order they are loaded', function () {
expect(kbnServer.uiExports.defaultInjectedVars).to.eql({
shared: 'foo'
});
});
});
context('two plugins, one async', function () {
this.slow(10000);
this.timeout(60000);
let kbnServer;
before(async function () {
kbnServer = kbnTestServer.createServer({
plugins: {
scanDirs: [],
paths: [
resolve(__dirname, 'fixtures/plugin_async_foo'),
resolve(__dirname, 'fixtures/plugin_foo')
]
},
plugin_async_foo: {
delay: 500,
shared: 'foo'
},
plugin_bar: {
shared: 'bar'
}
});
await kbnServer.ready();
});
after(async function () {
await kbnServer.close();
});
it('merges the two plugins in the order they are loaded', function () {
// even though plugin_async_foo loads 500ms later, it is still "first" to merge
expect(kbnServer.uiExports.defaultInjectedVars).to.eql({
shared: 'foo'
});
});
});
});
});

View file

@ -59,16 +59,6 @@ module.exports = async (kbnServer, server, config) => {
}
});
const defaultInjectedVars = {};
if (config.has('kibana')) {
defaultInjectedVars.kbnIndex = config.get('kibana.index');
}
if (config.has('elasticsearch')) {
defaultInjectedVars.esRequestTimeout = config.get('elasticsearch.requestTimeout');
defaultInjectedVars.esShardTimeout = config.get('elasticsearch.shardTimeout');
defaultInjectedVars.esApiVersion = config.get('elasticsearch.apiVersion');
}
server.decorate('reply', 'renderApp', function (app) {
const payload = {
app: app,
@ -77,7 +67,7 @@ module.exports = async (kbnServer, server, config) => {
buildNum: config.get('pkg.buildNum'),
buildSha: config.get('pkg.buildSha'),
basePath: config.get('server.basePath'),
vars: defaults(app.getInjectedVars() || {}, defaultInjectedVars),
vars: defaults(app.getInjectedVars() || {}, uiExports.defaultInjectedVars),
};
return this.view(app.templateName, {

View file

@ -11,6 +11,7 @@ class UiExports {
this.exportConsumer = _.memoize(this.exportConsumer);
this.consumers = [];
this.bundleProviders = [];
this.defaultInjectedVars = {};
}
consumePlugin(plugin) {
@ -53,6 +54,12 @@ class UiExports {
id: plugin.id,
urlBasePath: this.urlBasePath
}));
plugin.extendInit((server, options) => { // eslint-disable-line no-loop-func
const wrapped = app.getInjectedVars;
app.getInjectedVars = () => wrapped.call(plugin, server, options);
});
plugin.apps.add(app);
}
};
@ -80,6 +87,13 @@ class UiExports {
this.aliases[adhocType] = _.union(this.aliases[adhocType] || [], spec);
});
};
case 'injectDefaultVars':
return (plugin, injector) => {
plugin.extendInit(async (server, options) => {
_.merge(this.defaultInjectedVars, await injector.call(plugin, server, options));
});
};
}
}

View file

@ -3,7 +3,6 @@ import { defaultsDeep, set } from 'lodash';
import { header as basicAuthHeader } from './base_auth';
import { kibanaUser, kibanaServer } from '../shield';
import KbnServer from '../../src/server/kbn_server';
import fromRoot from '../../src/utils/from_root';
import serverConfig from '../server_config';
const SERVER_DEFAULTS = {
@ -16,11 +15,7 @@ const SERVER_DEFAULTS = {
logging: {
quiet: true
},
plugins: {
scanDirs: [
fromRoot('src/plugins')
]
},
plugins: {},
optimize: {
enabled: false
},