Skip to content

Commit

Permalink
[Reporting] Refactoring of ExportTypes (elastic#162276)
Browse files Browse the repository at this point in the history
## Summary

This PR refactors the getExportType() implementation in the reporting
plugin. With these changes, export types are now classes that are
registered into the export_types_registry in reporting core.
Export Type Classes:
- CsvSearchSourceExportType
- CsvSearchSourceImmediateExportType (this is not registered but can be
called by getCsvSearchSourceImmediate() in core.ts)
- CsvV2ExportType
- PngV1ExportType (deprecated) 
- PngExportType 
- PdfV1ExportType (deprecated)
- PdfExportType 

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------
Co-authored-by: Timothy Sullivan <tsullivan@elastic.co>
  • Loading branch information
rshen91 authored Jul 24, 2023
1 parent e3cc4a9 commit 71ebc38
Show file tree
Hide file tree
Showing 65 changed files with 1,563 additions and 1,754 deletions.
13 changes: 4 additions & 9 deletions x-pack/plugins/canvas/server/feature.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@
* 2.0.
*/

import { ReportingStart } from '@kbn/reporting-plugin/server/types';
import { getCanvasFeature } from './feature';
import { ReportingStart } from '@kbn/reporting-plugin/server/types';
import { reportingMock } from '@kbn/reporting-plugin/server/mocks';

let mockReportingPlugin: ReportingStart;
beforeEach(() => {
mockReportingPlugin = {
usesUiCapabilities: () => false,
registerExportTypes: () => {},
};
mockReportingPlugin = reportingMock.createStart();
});

it('Provides a feature declaration ', () => {
Expand Down Expand Up @@ -86,10 +84,7 @@ it('Provides a feature declaration ', () => {
});

it(`Calls on Reporting whether to include Generate PDF as a sub-feature`, () => {
mockReportingPlugin = {
usesUiCapabilities: () => true,
registerExportTypes: () => {},
};
mockReportingPlugin.usesUiCapabilities = () => true;
expect(getCanvasFeature({ reporting: mockReportingPlugin })).toMatchInlineSnapshot(`
Object {
"app": Array [
Expand Down
12 changes: 6 additions & 6 deletions x-pack/plugins/reporting/common/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ export const USES_HEADLESS_JOB_TYPES = [
export const DEPRECATED_JOB_TYPES = [CSV_JOB_TYPE_DEPRECATED];

// Licenses
export const LICENSE_TYPE_TRIAL = 'trial';
export const LICENSE_TYPE_BASIC = 'basic';
export const LICENSE_TYPE_CLOUD_STANDARD = 'standard';
export const LICENSE_TYPE_GOLD = 'gold';
export const LICENSE_TYPE_PLATINUM = 'platinum';
export const LICENSE_TYPE_ENTERPRISE = 'enterprise';
export const LICENSE_TYPE_TRIAL = 'trial' as const;
export const LICENSE_TYPE_BASIC = 'basic' as const;
export const LICENSE_TYPE_CLOUD_STANDARD = 'standard' as const;
export const LICENSE_TYPE_GOLD = 'gold' as const;
export const LICENSE_TYPE_PLATINUM = 'platinum' as const;
export const LICENSE_TYPE_ENTERPRISE = 'enterprise' as const;

// Routes
export const API_BASE_URL = '/api/reporting'; // "Generation URL" from share menu
Expand Down
129 changes: 65 additions & 64 deletions x-pack/plugins/reporting/server/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,16 @@
import type {
CoreSetup,
DocLinksServiceSetup,
FakeRawRequest,
Headers,
IBasePath,
IClusterClient,
KibanaRequest,
Logger,
PackageInfo,
PluginInitializerContext,
SavedObjectsClientContract,
SavedObjectsServiceStart,
StatusServiceSetup,
UiSettingsServiceStart,
} from '@kbn/core/server';
import { CoreKibanaRequest } from '@kbn/core/server';
import type { PluginStart as DataPluginStart } from '@kbn/data-plugin/server';
import type { DiscoverServerPluginStart } from '@kbn/discover-plugin/server';
import type { PluginSetupContract as FeaturesPluginSetup } from '@kbn/features-plugin/server';
Expand All @@ -34,7 +30,7 @@ import {
ScreenshottingStart,
} from '@kbn/screenshotting-plugin/server';
import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import type { SpacesPluginSetup } from '@kbn/spaces-plugin/server';
import type {
TaskManagerSetupContract,
Expand All @@ -46,11 +42,19 @@ import { map, switchMap, take } from 'rxjs/operators';
import type { ReportingSetup } from '.';
import { REPORTING_REDIRECT_LOCATOR_STORE_KEY } from '../common/constants';
import { createConfig, ReportingConfigType } from './config';
import { checkLicense, getExportTypesRegistry } from './lib';
import { CsvSearchSourceExportType } from './export_types/csv_searchsource';
import { CsvV2ExportType } from './export_types/csv_v2';
import { PdfV1ExportType } from './export_types/printable_pdf';
import { PdfExportType } from './export_types/printable_pdf_v2';
import { PngV1ExportType } from './export_types/png';
import { PngExportType } from './export_types/png_v2';
import { checkLicense, ExportTypesRegistry } from './lib';
import { reportingEventLoggerFactory } from './lib/event_logger/logger';
import type { IReport, ReportingStore } from './lib/store';
import { ExecuteReportTask, MonitorReportsTask, ReportTaskParams } from './lib/tasks';
import type { PdfScreenshotOptions, PngScreenshotOptions, ReportingPluginRouter } from './types';
import { CsvSearchSourceImmediateExportType } from './export_types/csv_searchsource_immediate';
import { ExportType } from './export_types/common';

export interface ReportingInternalSetup {
basePath: Pick<IBasePath, 'set'>;
Expand Down Expand Up @@ -102,11 +106,12 @@ export class ReportingCore {
private readonly pluginSetup$ = new Rx.ReplaySubject<boolean>(); // observe async background setupDeps each are done
private readonly pluginStart$ = new Rx.ReplaySubject<ReportingInternalStart>(); // observe async background startDeps
private deprecatedAllowedRoles: string[] | false = false; // DEPRECATED. If `false`, the deprecated features have been disableed
private exportTypesRegistry = getExportTypesRegistry();
private executeTask: ExecuteReportTask;
private monitorTask: MonitorReportsTask;
private config: ReportingConfigType;
private executing: Set<string>;
private exportTypes: ExportType[] = [];
private exportTypesRegistry = new ExportTypesRegistry();

public getContract: () => ReportingSetup;

Expand All @@ -121,13 +126,30 @@ export class ReportingCore {
const config = createConfig(core, context.config.get<ReportingConfigType>(), logger);
this.config = config;

// Export Type declarations
this.exportTypes.push(
new CsvSearchSourceExportType(this.core, this.config, this.logger, this.context)
);
this.exportTypes.push(new CsvV2ExportType(this.core, this.config, this.logger, this.context));
this.exportTypes.push(new PdfExportType(this.core, this.config, this.logger, this.context));
this.exportTypes.push(new PngExportType(this.core, this.config, this.logger, this.context));
// deprecated export types for tests
this.exportTypes.push(new PdfV1ExportType(this.core, this.config, this.logger, this.context));
this.exportTypes.push(new PngV1ExportType(this.core, this.config, this.logger, this.context));

this.exportTypes.forEach((et) => {
this.exportTypesRegistry.register(et);
});

this.deprecatedAllowedRoles = config.roles.enabled ? config.roles.allow : false;
this.executeTask = new ExecuteReportTask(this, config, this.logger);
this.monitorTask = new MonitorReportsTask(this, config, this.logger);

this.getContract = () => ({
usesUiCapabilities: () => config.roles.enabled === false,
registerExportTypes: (id) => id,
getScreenshots: this.getScreenshots.bind(this),
getSpaceId: this.getSpaceId.bind(this),
});

this.executing = new Set();
Expand All @@ -144,6 +166,10 @@ export class ReportingCore {
this.pluginSetup$.next(true); // trigger the observer
this.pluginSetupDeps = setupDeps; // cache

this.exportTypes.forEach((et) => {
et.setup(setupDeps);
});

const { executeTask, monitorTask } = this;
setupDeps.taskManager.registerTaskDefinitions({
[executeTask.TYPE]: executeTask.getTaskDefinition(),
Expand All @@ -158,6 +184,10 @@ export class ReportingCore {
this.pluginStart$.next(startDeps); // trigger the observer
this.pluginStartDeps = startDeps; // cache

this.exportTypes.forEach((et) => {
et.start({ ...startDeps, reporting: this.getContract() });
});

const { taskManager } = startDeps;
const { executeTask, monitorTask } = this;
// enable this instance to generate reports and to monitor for pending reports
Expand Down Expand Up @@ -322,63 +352,6 @@ export class ReportingCore {
return this.pluginSetupDeps;
}

private async getSavedObjectsClient(request: KibanaRequest) {
const { savedObjects } = await this.getPluginStartDeps();
return savedObjects.getScopedClient(request) as SavedObjectsClientContract;
}

public async getUiSettingsServiceFactory(savedObjectsClient: SavedObjectsClientContract) {
const { uiSettings: uiSettingsService } = await this.getPluginStartDeps();
const scopedUiSettingsService = uiSettingsService.asScopedToClient(savedObjectsClient);
return scopedUiSettingsService;
}

public getSpaceId(request: KibanaRequest, logger = this.logger): string | undefined {
const spacesService = this.getPluginSetupDeps().spaces?.spacesService;
if (spacesService) {
const spaceId = spacesService?.getSpaceId(request);

if (spaceId !== DEFAULT_SPACE_ID) {
logger.info(`Request uses Space ID: ${spaceId}`);
return spaceId;
} else {
logger.debug(`Request uses default Space`);
}
}
}

public getFakeRequest(
headers: Headers,
spaceId: string | undefined,
logger = this.logger
): KibanaRequest {
const rawRequest: FakeRawRequest = {
headers,
path: '/',
};
const fakeRequest = CoreKibanaRequest.from(rawRequest);

const spacesService = this.getPluginSetupDeps().spaces?.spacesService;
if (spacesService) {
if (spaceId && spaceId !== DEFAULT_SPACE_ID) {
logger.info(`Generating request for space: ${spaceId}`);
this.getPluginSetupDeps().basePath.set(fakeRequest, `/s/${spaceId}`);
}
}

return fakeRequest;
}

public async getUiSettingsClient(request: KibanaRequest, logger = this.logger) {
const spacesService = this.getPluginSetupDeps().spaces?.spacesService;
const spaceId = this.getSpaceId(request, logger);
if (spacesService && spaceId) {
logger.info(`Creating UI Settings Client for space: ${spaceId}`);
}
const savedObjectsClient = await this.getSavedObjectsClient(request);
return await this.getUiSettingsServiceFactory(savedObjectsClient);
}

public async getDataViewsService(request: KibanaRequest) {
const { savedObjects } = await this.getPluginStartDeps();
const savedObjectsClient = savedObjects.getScopedClient(request);
Expand All @@ -399,6 +372,20 @@ export class ReportingCore {
return startDeps.esClient;
}

public getSpaceId(request: KibanaRequest, logger = this.logger): string | undefined {
const spacesService = this.getPluginSetupDeps().spaces?.spacesService;
if (spacesService) {
const spaceId = spacesService?.getSpaceId(request);

if (spaceId !== DEFAULT_SPACE_ID) {
logger.info(`Request uses Space ID: ${spaceId}`);
return spaceId;
} else {
logger.debug(`Request uses default Space`);
}
}
}

public getScreenshots(options: PdfScreenshotOptions): Rx.Observable<PdfScreenshotResult>;
public getScreenshots(options: PngScreenshotOptions): Rx.Observable<PngScreenshotResult>;
public getScreenshots(
Expand Down Expand Up @@ -434,4 +421,18 @@ export class ReportingCore {
const ReportingEventLogger = reportingEventLoggerFactory(this.logger);
return new ReportingEventLogger(report, task);
}

public async getCsvSearchSourceImmediate() {
const startDeps = await this.getPluginStartDeps();

const csvImmediateExport = new CsvSearchSourceImmediateExportType(
this.core,
this.config,
this.logger,
this.context
);
csvImmediateExport.setup(this.getPluginSetupDeps());
csvImmediateExport.start({ ...startDeps, reporting: this.getContract() });
return csvImmediateExport;
}
}
Loading

0 comments on commit 71ebc38

Please sign in to comment.