Skip to content

Commit

Permalink
inject client plugin configs in injectedMetadata
Browse files Browse the repository at this point in the history
  • Loading branch information
pgayvallet committed Nov 14, 2019
1 parent fb2b28c commit daf09e3
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ export interface InjectedMetadataParams {
uiPlugins: Array<{
id: PluginName;
plugin: DiscoveredPlugin;
config?: {
[key: string]: unknown;
};
}>;
capabilities: Capabilities;
legacyMode: boolean;
Expand Down Expand Up @@ -168,6 +171,9 @@ export interface InjectedMetadataSetup {
getPlugins: () => Array<{
id: string;
plugin: DiscoveredPlugin;
config?: {
[key: string]: unknown;
};
}>;
/** Indicates whether or not we are rendering a known legacy app. */
getLegacyMode: () => boolean;
Expand Down
1 change: 1 addition & 0 deletions src/core/server/legacy/legacy_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ beforeEach(() => {
uiPlugins: {
public: new Map([['plugin-id', {} as DiscoveredPlugin]]),
internal: new Map([['plugin-id', {} as DiscoveredPluginInternal]]),
config: new Map([['plugin-id', null]]),
},
},
},
Expand Down
1 change: 1 addition & 0 deletions src/core/server/plugins/plugins_service.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const createServiceMock = () => {
uiPlugins: {
public: new Map(),
internal: new Map(),
config: new Map(),
},
});
mocked.start.mockResolvedValue({ contracts: new Map() });
Expand Down
52 changes: 44 additions & 8 deletions src/core/server/plugins/plugins_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,33 @@
* under the License.
*/

import { Observable } from 'rxjs';
import { Observable, of } from 'rxjs';
import { filter, first, map, mergeMap, tap, toArray } from 'rxjs/operators';
import { CoreService } from '../../types';
import { CoreContext } from '../core_context';

import { Logger } from '../logging';
import { discover, PluginDiscoveryError, PluginDiscoveryErrorType } from './discovery';
import { PluginWrapper } from './plugin';
import { DiscoveredPlugin, DiscoveredPluginInternal, PluginName } from './types';
import {
DiscoveredPlugin,
DiscoveredPluginInternal,
PluginConfigDescriptor,
PluginName,
} from './types';
import { PluginsConfig, PluginsConfigType } from './plugins_config';
import { PluginsSystem } from './plugins_system';
import { InternalCoreSetup } from '../internal_types';
import { IConfigService } from '../config';
import { pick } from '../../utils';

/** @public */
export interface PluginsServiceSetup {
contracts: Map<PluginName, unknown>;
uiPlugins: {
public: Map<PluginName, DiscoveredPlugin>;
internal: Map<PluginName, DiscoveredPluginInternal>;
config: Map<PluginName, Observable<unknown> | null>;
};
}

Expand All @@ -54,11 +62,14 @@ export interface PluginsServiceStartDeps {} // eslint-disable-line @typescript-e
export class PluginsService implements CoreService<PluginsServiceSetup, PluginsServiceStart> {
private readonly log: Logger;
private readonly pluginsSystem: PluginsSystem;
private readonly configService: IConfigService;
private readonly config$: Observable<PluginsConfig>;
private readonly pluginConfigDescriptors = new Map<PluginName, PluginConfigDescriptor>();

constructor(private readonly coreContext: CoreContext) {
this.log = coreContext.logger.get('plugins-service');
this.pluginsSystem = new PluginsSystem(coreContext);
this.configService = coreContext.configService;
this.config$ = coreContext.configService
.atPath<PluginsConfigType>('plugins')
.pipe(map(rawConfig => new PluginsConfig(rawConfig, coreContext.env)));
Expand All @@ -82,17 +93,20 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS

const config = await this.config$.pipe(first()).toPromise();

let contracts = new Map<PluginName, unknown>();
if (!config.initialize || this.coreContext.env.isDevClusterMaster) {
this.log.info('Plugin initialization disabled.');
return {
contracts: new Map(),
uiPlugins: this.pluginsSystem.uiPlugins(),
};
} else {
contracts = await this.pluginsSystem.setupPlugins(deps);
}

const uiPlugins = this.pluginsSystem.uiPlugins();
return {
contracts: await this.pluginsSystem.setupPlugins(deps),
uiPlugins: this.pluginsSystem.uiPlugins(),
contracts,
uiPlugins: {
...uiPlugins,
config: this.generateUiPluginsConfigs(uiPlugins.public),
},
};
}

Expand All @@ -107,6 +121,27 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
await this.pluginsSystem.stopPlugins();
}

private generateUiPluginsConfigs(
uiPlugins: Map<string, DiscoveredPlugin>
): Map<PluginName, Observable<unknown>> {
return new Map(
[...uiPlugins].map(([pluginId, plugin]) => {
const configDescriptor = this.pluginConfigDescriptors.get(pluginId);
if (configDescriptor && configDescriptor.exposeToBrowser) {
return [
pluginId,
this.configService
.atPath(plugin.configPath)
.pipe(
map((config: any) => pick(config || {}, configDescriptor.exposeToBrowser || []))
),
];
}
return [pluginId, of({})];
})
);
}

private async handleDiscoveryErrors(error$: Observable<PluginDiscoveryError>) {
// At this stage we report only errors that can occur when new platform plugin
// manifest is present, otherwise we can't be sure that the plugin is for the new
Expand Down Expand Up @@ -140,6 +175,7 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
mergeMap(async plugin => {
const configDescriptor = plugin.getConfigDescriptor();
if (configDescriptor) {
this.pluginConfigDescriptors.set(plugin.name, configDescriptor);
await this.coreContext.configService.setSchema(
plugin.configPath,
configDescriptor.schema
Expand Down
112 changes: 67 additions & 45 deletions src/legacy/ui/ui_render/ui_render_mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* under the License.
*/

import { take } from 'rxjs/operators';
import { createHash } from 'crypto';
import { props, reduce as reduceAsync } from 'bluebird';
import Boom from 'boom';
Expand All @@ -42,21 +43,31 @@ export function uiRenderMixin(kbnServer, server, config) {
let defaultInjectedVars = {};
kbnServer.afterPluginsInit(() => {
const { defaultInjectedVarProviders = [] } = kbnServer.uiExports;
defaultInjectedVars = defaultInjectedVarProviders
.reduce((allDefaults, { fn, pluginSpec }) => (
defaultInjectedVars = defaultInjectedVarProviders.reduce(
(allDefaults, { fn, pluginSpec }) =>
mergeVariables(
allDefaults,
fn(kbnServer.server, pluginSpec.readConfigValue(kbnServer.config, []))
)
), {});
),
{}
);
});

// render all views from ./views
server.setupViews(resolve(__dirname, 'views'));

server.exposeStaticDir('/node_modules/@elastic/eui/dist/{path*}', fromRoot('node_modules/@elastic/eui/dist'));
server.exposeStaticDir('/node_modules/@kbn/ui-framework/dist/{path*}', fromRoot('node_modules/@kbn/ui-framework/dist'));
server.exposeStaticDir('/node_modules/@elastic/charts/dist/{path*}', fromRoot('node_modules/@elastic/charts/dist'));
server.exposeStaticDir(
'/node_modules/@elastic/eui/dist/{path*}',
fromRoot('node_modules/@elastic/eui/dist')
);
server.exposeStaticDir(
'/node_modules/@kbn/ui-framework/dist/{path*}',
fromRoot('node_modules/@kbn/ui-framework/dist')
);
server.exposeStaticDir(
'/node_modules/@elastic/charts/dist/{path*}',
fromRoot('node_modules/@elastic/charts/dist')
);

const translationsCache = { translations: null, hash: null };
server.route({
Expand All @@ -80,11 +91,12 @@ export function uiRenderMixin(kbnServer, server, config) {
.digest('hex');
}

return h.response(translationsCache.translations)
return h
.response(translationsCache.translations)
.header('cache-control', 'must-revalidate')
.header('content-type', 'application/json')
.etag(translationsCache.hash);
}
},
});

// register the bootstrap.js route after plugins are initialized so that we can
Expand All @@ -105,42 +117,38 @@ export function uiRenderMixin(kbnServer, server, config) {
const isCore = !app;

const uiSettings = request.getUiSettingsService();
const darkMode = !authEnabled || request.auth.isAuthenticated
? await uiSettings.get('theme:darkMode')
: false;
const darkMode =
!authEnabled || request.auth.isAuthenticated
? await uiSettings.get('theme:darkMode')
: false;

const basePath = config.get('server.basePath');
const regularBundlePath = `${basePath}/bundles`;
const dllBundlePath = `${basePath}/built_assets/dlls`;
const styleSheetPaths = [
`${dllBundlePath}/vendors.style.dll.css`,
...(
darkMode ?
[
`${basePath}/node_modules/@elastic/eui/dist/eui_theme_dark.css`,
`${basePath}/node_modules/@kbn/ui-framework/dist/kui_dark.css`,
`${basePath}/node_modules/@elastic/charts/dist/theme_only_dark.css`,
] : [
`${basePath}/node_modules/@elastic/eui/dist/eui_theme_light.css`,
`${basePath}/node_modules/@kbn/ui-framework/dist/kui_light.css`,
`${basePath}/node_modules/@elastic/charts/dist/theme_only_light.css`,
]
),
...(darkMode
? [
`${basePath}/node_modules/@elastic/eui/dist/eui_theme_dark.css`,
`${basePath}/node_modules/@kbn/ui-framework/dist/kui_dark.css`,
`${basePath}/node_modules/@elastic/charts/dist/theme_only_dark.css`,
]
: [
`${basePath}/node_modules/@elastic/eui/dist/eui_theme_light.css`,
`${basePath}/node_modules/@kbn/ui-framework/dist/kui_light.css`,
`${basePath}/node_modules/@elastic/charts/dist/theme_only_light.css`,
]),
`${regularBundlePath}/${darkMode ? 'dark' : 'light'}_theme.style.css`,
`${regularBundlePath}/commons.style.css`,
...(
!isCore ? [`${regularBundlePath}/${app.getId()}.style.css`] : []
),
...(!isCore ? [`${regularBundlePath}/${app.getId()}.style.css`] : []),
...kbnServer.uiExports.styleSheetPaths
.filter(path => (
path.theme === '*' || path.theme === (darkMode ? 'dark' : 'light')
))
.map(path => (
.filter(path => path.theme === '*' || path.theme === (darkMode ? 'dark' : 'light'))
.map(path =>
path.localPath.endsWith('.scss')
? `${basePath}/built_assets/css/${path.publicPath}`
: `${basePath}/${path.publicPath}`
))
.reverse()
)
.reverse(),
];

const bootstrap = new AppBootstrap({
Expand All @@ -149,17 +157,18 @@ export function uiRenderMixin(kbnServer, server, config) {
regularBundlePath,
dllBundlePath,
styleSheetPaths,
}
},
});

const body = await bootstrap.getJsFile();
const etag = await bootstrap.getJsFileHash();

return h.response(body)
return h
.response(body)
.header('cache-control', 'must-revalidate')
.header('content-type', 'application/javascript')
.etag(etag);
}
},
});
});

Expand All @@ -179,14 +188,14 @@ export function uiRenderMixin(kbnServer, server, config) {
} catch (err) {
throw Boom.boomify(err);
}
}
},
});

async function getUiSettings({ request, includeUserProvidedConfig }) {
const uiSettings = request.getUiSettingsService();
return props({
defaults: uiSettings.getRegistered(),
user: includeUserProvidedConfig && uiSettings.getUserProvided()
user: includeUserProvidedConfig && uiSettings.getUserProvided(),
});
}

Expand All @@ -206,7 +215,12 @@ export function uiRenderMixin(kbnServer, server, config) {
};
}

async function renderApp({ app, h, includeUserProvidedConfig = true, injectedVarsOverrides = {} }) {
async function renderApp({
app,
h,
includeUserProvidedConfig = true,
injectedVarsOverrides = {},
}) {
const request = h.request;
const basePath = request.getBasePath();
const uiSettings = await getUiSettings({ request, includeUserProvidedConfig });
Expand All @@ -215,14 +229,22 @@ export function uiRenderMixin(kbnServer, server, config) {
const legacyMetadata = getLegacyKibanaPayload({
app,
basePath,
uiSettings
uiSettings,
});

// Get the list of new platform plugins.
// Convert the Map into an array of objects so it is JSON serializable and order is preserved.
const uiPlugins = [
...kbnServer.newPlatform.__internals.uiPlugins.public.entries()
].map(([id, plugin]) => ({ id, plugin }));
const uiPluginConfigs = kbnServer.newPlatform.__internals.uiPlugins.config;
const uiPlugins = await Promise.all([
...kbnServer.newPlatform.__internals.uiPlugins.public.entries(),
].map(async ([id, plugin]) => {
const config$ = uiPluginConfigs.get(id);
if (config$) {
return { id, plugin, config: await config$.pipe(take(1)).toPromise() };
} else {
return { id, plugin, config: {} };
}
}));

const response = h.view('ui_app', {
strictCsp: config.get('csp.strict'),
Expand Down Expand Up @@ -250,8 +272,8 @@ export function uiRenderMixin(kbnServer, server, config) {
mergeVariables(
injectedVarsOverrides,
app ? await server.getInjectedUiAppVars(app.getId()) : {},
defaultInjectedVars,
),
defaultInjectedVars
)
),

uiPlugins,
Expand Down

0 comments on commit daf09e3

Please sign in to comment.