Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Reporting/Migration] ReportingSetup, LegacySetup #54198

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 13 additions & 65 deletions x-pack/legacy/plugins/reporting/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,47 +7,20 @@
import { resolve } from 'path';
import { i18n } from '@kbn/i18n';
import { Legacy } from 'kibana';
import { IUiSettingsClient } from 'src/core/server';
import { XPackMainPlugin } from '../xpack_main/server/xpack_main';
import { PLUGIN_ID, UI_SETTINGS_CUSTOM_PDF_LOGO } from './common/constants';
// @ts-ignore untyped module defintition
import { mirrorPluginStatus } from '../../server/lib/mirror_plugin_status';
import { registerRoutes } from './server/routes';
import {
LevelLogger,
checkLicenseFactory,
getExportTypesRegistry,
runValidations,
} from './server/lib';
import { createBrowserDriverFactory } from './server/browsers';
import { registerReportingUsageCollector } from './server/usage';
import { ReportingConfigOptions, ReportingPluginSpecOptions } from './types.d';
import { config as reportingConfig } from './config';
import { logConfiguration } from './log_configuration';
import {
LegacySetup,
ReportingPlugin,
ReportingSetupDeps,
reportingPluginFactory,
} from './server/plugin';

const kbToBase64Length = (kb: number) => {
return Math.floor((kb * 1024 * 8) / 6);
};

type LegacyPlugins = Legacy.Server['plugins'];

export interface ServerFacade {
config: Legacy.Server['config'];
info: Legacy.Server['info'];
log: Legacy.Server['log'];
plugins: {
elasticsearch: LegacyPlugins['elasticsearch'];
security: LegacyPlugins['security'];
xpack_main: XPackMainPlugin & {
status?: any;
};
};
route: Legacy.Server['route'];
savedObjects: Legacy.Server['savedObjects'];
uiSettingsServiceFactory: Legacy.Server['uiSettingsServiceFactory'];
fieldFormatServiceFactory: (uiConfig: IUiSettingsClient) => unknown;
}

export const reporting = (kibana: any) => {
return new kibana.Plugin({
id: PLUGIN_ID,
Expand Down Expand Up @@ -93,7 +66,11 @@ export const reporting = (kibana: any) => {
},

async init(server: Legacy.Server) {
const serverFacade: ServerFacade = {
const coreSetup = server.newPlatform.setup.core;
const pluginsSetup: ReportingSetupDeps = {
usageCollection: server.newPlatform.setup.plugins.usageCollection,
};
const __LEGACY: LegacySetup = {
config: server.config,
info: server.info,
route: server.route.bind(server),
Expand All @@ -108,38 +85,9 @@ export const reporting = (kibana: any) => {
fieldFormatServiceFactory: server.fieldFormatServiceFactory,
log: server.log.bind(server),
};
const exportTypesRegistry = getExportTypesRegistry();

let isCollectorReady = false;
// Register a function with server to manage the collection of usage stats
const { usageCollection } = server.newPlatform.setup.plugins;
registerReportingUsageCollector(
usageCollection,
serverFacade,
() => isCollectorReady,
exportTypesRegistry
);

const logger = LevelLogger.createForServer(serverFacade, [PLUGIN_ID]);
const browserDriverFactory = await createBrowserDriverFactory(serverFacade);

logConfiguration(serverFacade, logger);
runValidations(serverFacade, logger, browserDriverFactory);

const { xpack_main: xpackMainPlugin } = serverFacade.plugins;
mirrorPluginStatus(xpackMainPlugin, this);
const checkLicense = checkLicenseFactory(exportTypesRegistry);
(xpackMainPlugin as any).status.once('green', () => {
// Register a function that is called whenever the xpack info changes,
// to re-compute the license check results for this plugin
xpackMainPlugin.info.feature(this.id).registerLicenseCheckResultsGenerator(checkLicense);
});

// Post initialization of the above code, the collector is now ready to fetch its data
isCollectorReady = true;

// Reporting routes
registerRoutes(serverFacade, exportTypesRegistry, browserDriverFactory, logger);
const plugin: ReportingPlugin = reportingPluginFactory(__LEGACY, this);
await plugin.setup(coreSetup, pluginsSetup);
},

deprecations({ unused }: any) {
Expand Down
107 changes: 107 additions & 0 deletions x-pack/legacy/plugins/reporting/server/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { Legacy } from 'kibana';
import { CoreSetup, CoreStart, Plugin } from 'src/core/server';
import { IUiSettingsClient } from 'src/core/server';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { XPackMainPlugin } from '../../xpack_main/server/xpack_main';
// @ts-ignore
import { mirrorPluginStatus } from '../../../server/lib/mirror_plugin_status';
import { PLUGIN_ID } from '../common/constants';
import { ReportingPluginSpecOptions } from '../types.d';
import { registerRoutes } from './routes';
import { LevelLogger, checkLicenseFactory, getExportTypesRegistry, runValidations } from './lib';
import { createBrowserDriverFactory } from './browsers';
import { registerReportingUsageCollector } from './usage';
import { logConfiguration } from '../log_configuration';

// For now there is no exposed functionality to other plugins
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the near future, we will expose functionality to other plugins so they have an API to schedule reports of their data visualizations / CSV exports

export type ReportingSetup = object;
export type ReportingStart = object;

export interface ReportingSetupDeps {
usageCollection: UsageCollectionSetup;
}
export type ReportingStartDeps = object;

type LegacyPlugins = Legacy.Server['plugins'];

export interface LegacySetup {
config: Legacy.Server['config'];
info: Legacy.Server['info'];
log: Legacy.Server['log'];
plugins: {
elasticsearch: LegacyPlugins['elasticsearch'];
security: LegacyPlugins['security'];
xpack_main: XPackMainPlugin & {
status?: any;
};
};
route: Legacy.Server['route'];
savedObjects: Legacy.Server['savedObjects'];
uiSettingsServiceFactory: Legacy.Server['uiSettingsServiceFactory'];
fieldFormatServiceFactory: (uiConfig: IUiSettingsClient) => unknown;
}

export type ReportingPlugin = Plugin<
ReportingSetup,
ReportingStart,
ReportingSetupDeps,
ReportingStartDeps
>;

/* We need a factory that returns an instance of the class because the class
* implementation itself restricts against having Legacy dependencies passed
* into `setup`. The factory parameters take the legacy dependencies, and the
* `setup` method gets it from enclosure */
export function reportingPluginFactory(
Copy link
Member Author

@tsullivan tsullivan Jan 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this factory function to accept parameters that can not directly be passed into the ReportingPlugin constructor and setup method.

I had to come up with this solution, because the guidance from the Migration guide had outdated info:

/* this is not possible if the Plugin class extends the core plugin class:
 * the setup method doesn't accept a 3rd parameter */ 
const demoSetup = new Plugin().setup(coreSetup, pluginsSetup, __LEGACY); 

cc @rudolf @pgayvallet

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could make this type more permissive:

interface Plugin<...> {
  setup(core: CoreSetup, plugins: TPluginsSetup, ...args: any[]): MaybePromise<TSetup>;
  /* ... */
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(sorry, I'm a little late) I'm not a big fan of 'poluting' the Plugin interface, as the additional parameters will not be able to actually be injected/used once the plugin is migrated and core actually instantiate the plugin.

Maybe we could instead introduce a sub-interface for the migration period,

interface ShimedPlugin<
  TSetup = void,
  TStart = void,
  TPluginsSetup extends object = object,
  TPluginsStart extends object = object,
  TLegacySetupDeps extends object = object
> extends Plugin<TSetup, TStart, TPluginsSetup, TPluginsStart> {
  setup(
    core: CoreSetup,
    plugins: TPluginsSetup,
    legacy: TLegacySetupDeps
  ): TSetup | Promise<TSetup>;
}

@tsullivan The factory is a workaround that will do just fine however. Sorry for the outdated documentation

__LEGACY: LegacySetup,
legacyPlugin: ReportingPluginSpecOptions
) {
return new (class ReportingPlugin implements ReportingPlugin {
public async setup(core: CoreSetup, plugins: ReportingSetupDeps): Promise<ReportingSetup> {
const exportTypesRegistry = getExportTypesRegistry();

let isCollectorReady = false;
// Register a function with server to manage the collection of usage stats
const { usageCollection } = plugins;
registerReportingUsageCollector(
usageCollection,
__LEGACY,
() => isCollectorReady,
exportTypesRegistry
);

const logger = LevelLogger.createForServer(__LEGACY, [PLUGIN_ID]);
const browserDriverFactory = await createBrowserDriverFactory(__LEGACY);

logConfiguration(__LEGACY, logger);
runValidations(__LEGACY, logger, browserDriverFactory);

const { xpack_main: xpackMainPlugin } = __LEGACY.plugins;
mirrorPluginStatus(xpackMainPlugin, legacyPlugin);
const checkLicense = checkLicenseFactory(exportTypesRegistry);
(xpackMainPlugin as any).status.once('green', () => {
// Register a function that is called whenever the xpack info changes,
// to re-compute the license check results for this plugin
xpackMainPlugin.info.feature(PLUGIN_ID).registerLicenseCheckResultsGenerator(checkLicense);
});

// Post initialization of the above code, the collector is now ready to fetch its data
isCollectorReady = true;

// Reporting routes
registerRoutes(__LEGACY, exportTypesRegistry, browserDriverFactory, logger);

return {};
}

public start(core: CoreStart, plugins: ReportingStartDeps): ReportingStart {
return {};
}
})();
}
6 changes: 3 additions & 3 deletions x-pack/legacy/plugins/reporting/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { CancellationToken } from './common/cancellation_token';
import { LevelLogger } from './server/lib/level_logger';
import { HeadlessChromiumDriverFactory } from './server/browsers/chromium/driver_factory';
import { BrowserType } from './server/browsers/types';
import { ServerFacade } from './index';
import { LegacySetup } from './server/plugin';

export type ReportingPlugin = object; // For Plugin contract

Expand Down Expand Up @@ -69,6 +69,8 @@ interface GenerateExportTypePayload {
* Legacy System
*/

export type ServerFacade = LegacySetup;

export type ReportingPluginSpecOptions = Legacy.PluginSpecOptions;

export type EnqueueJobFn = <JobParamsType>(
Expand Down Expand Up @@ -338,5 +340,3 @@ export interface AbsoluteURLFactoryOptions {
hostname: string;
port: string | number;
}

export { ServerFacade };