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

Initialize reporting dashboards-plugin configurations and with reporting server settings #222

Merged
merged 1 commit into from
Nov 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion dashboards-reports/opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
"requiredPlugins": ["navigation", "data", "opensearchDashboardsUtils"],
"optionalPlugins": ["share"],
"server": true,
"ui": true
"ui": true,
"configPath": ["opensearch_reporting"]
}
69 changes: 69 additions & 0 deletions dashboards-reports/server/config/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

import {
CoreSetup,
Logger,
PluginInitializerContext,
} from '../../../../src/core/server';
import { ReportingConfigType } from './schema';
import { get } from 'lodash';
import { first, map } from 'rxjs/operators';
import { createConfig$ } from './createConfig';

interface Config<BaseType> {
get<Key1 extends keyof BaseType>(key1: Key1): BaseType[Key1];
get<Key1 extends keyof BaseType, Key2 extends keyof BaseType[Key1]>(
key1: Key1,
key2: Key2
): BaseType[Key1][Key2];
}

interface OsdServerConfigType {
server: {
basePath: string;
host: string;
name: string;
port: number;
protocol: string;
};
}

export interface ReportingConfig extends Config<ReportingConfigType> {
osdConfig: Config<OsdServerConfigType>;
}

export const buildConfig = async (
initContext: PluginInitializerContext<ReportingConfigType>,
core: CoreSetup,
logger: Logger
): Promise<ReportingConfig> => {
const config$ = initContext.config.create<ReportingConfigType>();
const serverInfo = core.http.getServerInfo();
const osdConfig = {
server: {
basePath: core.http.basePath.serverBasePath,
host: serverInfo.hostname,
name: serverInfo.name,
port: serverInfo.port,
protocol: serverInfo.protocol,
},
};

const reportingConfig$ = createConfig$(core, config$, logger);
const reportingConfig = await reportingConfig$.pipe(first()).toPromise();
return {
get: (...keys: string[]) => get(reportingConfig, keys.join('.'), null),
osdConfig: {
get: (...keys: string[]) => get(osdConfig, keys.join('.'), null),
},
};
};
53 changes: 53 additions & 0 deletions dashboards-reports/server/config/createConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { CoreSetup, Logger } from '../../../../src/core/server';

import { ReportingConfigType } from './schema';

/*
* Set up dynamic config defaults
*/
export function createConfig$(
core: CoreSetup,
config$: Observable<ReportingConfigType>,
logger: Logger
) {
return config$.pipe(
map((config) => {
const { osd_server: reportingServer } = config;
const serverInfo = core.http.getServerInfo();
// osd_server.hostname, default to server.host
const osdServerHostname = reportingServer.hostname
? reportingServer.hostname
: serverInfo.hostname;

// osd_server.port, default to server.port
const osdServerPort = reportingServer.port
? reportingServer.port
: serverInfo.port;
// osd_server.protocol, default to server.protocol
const osdServerProtocol = reportingServer.protocol
? reportingServer.protocol
: serverInfo.protocol;
return {
...config,
osd_server: {
hostname: osdServerHostname,
port: osdServerPort,
protocol: osdServerProtocol,
},
};
})
);
}
19 changes: 19 additions & 0 deletions dashboards-reports/server/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

import { PluginConfigDescriptor } from '../../../../src/core/server';
import { ConfigSchema, ReportingConfigType } from './schema';
export { buildConfig } from './config';
export { ConfigSchema, ReportingConfigType };

export const config: PluginConfigDescriptor<ReportingConfigType> = {
schema: ConfigSchema,
};
41 changes: 41 additions & 0 deletions dashboards-reports/server/config/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

import { schema, TypeOf } from '@osd/config-schema';

const OsdServerSchema = schema.object({
hostname: schema.maybe(
schema.string({
validate(value) {
if (value === '0') {
Copy link
Member

Choose a reason for hiding this comment

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

would 0.0.0.0 and 127.0.0.1 work?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes

return 'must not be "0" for the headless browser to correctly resolve the host';
}
},
hostname: true,
Copy link
Member

Choose a reason for hiding this comment

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

what does this do?

Copy link
Member Author

Choose a reason for hiding this comment

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

})
),
port: schema.maybe(schema.number()),
protocol: schema.maybe(
schema.string({
validate(value) {
if (!/^https?$/.test(value)) {
return 'must be "http" or "https"';
}
},
})
),
}); // default values are all dynamic in createConfig$

export const ConfigSchema = schema.object({
osd_server: OsdServerSchema,
});

export type ReportingConfigType = TypeOf<typeof ConfigSchema>;
18 changes: 8 additions & 10 deletions dashboards-reports/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,19 @@
* permissions and limitations under the License.
*/

import {
HttpServerInfo,
PluginInitializerContext,
} from '../../../src/core/server';
import { PluginInitializerContext } from '../../../src/core/server';
import { ReportingConfigType } from './config';
zhongnansu marked this conversation as resolved.
Show resolved Hide resolved
import { ReportsDashboardsPlugin } from './plugin';

export type AccessInfoType = {
basePath: string;
serverInfo: HttpServerInfo;
};
export { config } from './config';
export { ReportingConfig } from './config/config';
export { ReportsDashboardsPlugin as Plugin };

// This exports static code and TypeScript types,
// as well as, OpenSearch Dashboards Platform `plugin()` initializer.

export function plugin(initializerContext: PluginInitializerContext) {
export function plugin(
initializerContext: PluginInitializerContext<ReportingConfigType>
) {
return new ReportsDashboardsPlugin(initializerContext);
}

Expand Down
45 changes: 31 additions & 14 deletions dashboards-reports/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ import {
import registerRoutes from './routes';
import { pollAndExecuteJob } from './executor/executor';
import { POLL_INTERVAL } from './utils/constants';
import { AccessInfoType } from 'server';
import { NotificationsPlugin } from './clusters/notificationsPlugin';
import { buildConfig, ReportingConfigType } from './config';
import { ReportingConfig } from './config/config';

export interface ReportsPluginRequestContext {
logger: Logger;
Expand All @@ -61,24 +62,40 @@ export class ReportsDashboardsPlugin
Plugin<ReportsDashboardsPluginSetup, ReportsDashboardsPluginStart> {
private readonly logger: Logger;
private readonly semaphore: SemaphoreInterface;

constructor(initializerContext: PluginInitializerContext) {
this.logger = initializerContext.logger.get();

private readonly initializerContext: PluginInitializerContext<
ReportingConfigType
>;
private reportingConfig?: ReportingConfig;

constructor(context: PluginInitializerContext<ReportingConfigType>) {
this.logger = context.logger.get();
this.initializerContext = context;
const timeoutError = new Error('Server busy');
timeoutError.statusCode = 503;
this.semaphore = withTimeout(new Semaphore(1), 180000, timeoutError);
}

public setup(core: CoreSetup) {
public async setup(core: CoreSetup) {
this.logger.debug('reports-dashboards: Setup');

const config = core.http.getServerInfo();
const serverBasePath = core.http.basePath.serverBasePath;
const accessInfo: AccessInfoType = {
basePath: serverBasePath,
serverInfo: config,
};
try {
const config = await buildConfig(
this.initializerContext,
core,
this.logger
);
this.reportingConfig = config;
this.logger.debug('Setup complete');
} catch (error) {
this.logger.error(
`Error in Reporting setup, reporting may not function properly`
);
this.logger.error(error);
}

if (!this.reportingConfig) {
throw new Error('Reporting Config is not initialized');
}

const router = core.http.createRouter();
// Deprecated API. Switch to the new opensearch client as soon as https://github.com/elastic/kibana/issues/35508 done.
Expand All @@ -97,7 +114,7 @@ export class ReportsDashboardsPlugin
);

// Register server side APIs
registerRoutes(router, accessInfo);
registerRoutes(router, this.reportingConfig);

// put logger into route handler context, so that we don't need to pass through parameters
core.http.registerRouteHandlerContext(
Expand All @@ -108,7 +125,7 @@ export class ReportsDashboardsPlugin
logger: this.logger,
semaphore: this.semaphore,
opensearchReportsClient,
notificationsClient
notificationsClient,
};
}
);
Expand Down
8 changes: 4 additions & 4 deletions dashboards-reports/server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ import registerReportSourceRoute from './reportSource';
import registerMetricRoute from './metric';
import registerNotificationRoute from './notifications';
import { IRouter } from '../../../../src/core/server';
import { AccessInfoType } from 'server';
import { ReportingConfig } from 'server/config/config';

export default function (router: IRouter, accessInfo: AccessInfoType) {
registerReportRoute(router, accessInfo);
registerReportDefinitionRoute(router, accessInfo);
export default function (router: IRouter, config: ReportingConfig) {
registerReportRoute(router, config);
registerReportDefinitionRoute(router, config);
registerReportSourceRoute(router);
registerMetricRoute(router);
registerNotificationRoute(router);
Expand Down
12 changes: 6 additions & 6 deletions dashboards-reports/server/routes/lib/createReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ import { SetCookie, Headers } from 'puppeteer-core';
import { updateReportState } from './updateReportState';
import { saveReport } from './saveReport';
import { SemaphoreInterface } from 'async-mutex';
import { AccessInfoType } from 'server';
import { ReportingConfig } from 'server';
import _ from 'lodash';

export const createReport = async (
request: OpenSearchDashboardsRequest,
context: RequestHandlerContext,
report: ReportSchemaType,
accessInfo: AccessInfoType,
config: ReportingConfig,
savedReportId?: string
): Promise<CreateReportResultType> => {
const isScheduledTask = false;
Expand All @@ -73,10 +73,10 @@ export const createReport = async (
request.query.dateFormat || DATA_REPORT_CONFIG.excelDateFormat;
// @ts-ignore
const csvSeparator = request.query.csvSeparator || ',';
const {
basePath,
serverInfo: { protocol, port, hostname },
} = accessInfo;
const protocol = config.get('osd_server', 'protocol');
const hostname = config.get('osd_server', 'hostname');
const port = config.get('osd_server', 'port');
const basePath = config.osdConfig.get('server', 'basePath');

let createReportResult: CreateReportResultType;
let reportId;
Expand Down
Loading