Skip to content

Commit fd0a43d

Browse files
ymao1ersin-erdalkibanamachineelasticmachine
authored
[Response Ops][Reporting] Scheduled Reports - Schedule API (#219771)
Towards #216313 > [!Note] > This PR will be merged into a feature branch - `elastic:scheduled-reports` > Once this is merged, I will open a draft PR from the feature branch into `main` ## Summary ### Schedule API - Added internal API `/internal/reporting/schedule/{exportTypeId}` ``` POST /internal/reporting/schedule/{exportTypeId} { "jobParams": <same jobParams format as existing generate single report API>, "schedule": { "rrule": <modified Task Manager rRule schema from #217728> } "notification": { "email": { "to": <optional list of email addresses>, "cc": <optional list of email addresses>, "bcc": <optional list of email addresses> } } ``` - Scheduling a report creates a new `scheduled_report` type saved object in the `.kibana-alerting-cases` index. - Uses the same role privileges as the current generate report API, so user must have the reporting subfeature privilege for one of the Analytics feature privileges (Discover/Dashboard/Visualize) ## Verify 1. Run ES and Kibana with examples and install the sample web logs data set. 2. In the DEV console, call the schedule API using ``` POST kbn:/internal/reporting/schedule/printablePdfV2 { "schedule": { "rrule": { "freq": 3, "interval": 3, "byhour": [12], "byminute": [0] } }, "jobParams": "(browserTimezone:America/New_York,layout:(dimensions:(height:2220,width:1364),id:preserve_layout),locatorParams:!((id:DASHBOARD_APP_LOCATOR,params:(dashboardId:edf84fe0-e1a0-11e7-b6d5-4dc382ef7f5b,preserveSavedFilters:!t,timeRange:(from:now-7d/d,to:now),useHash:!f,viewMode:view))),objectType:dashboard,title:'[Logs] Web Traffic',version:'9.1.0')" } ``` 3. Verify a saved object has been created using `GET .kibana_alerting_cases/_search?q=type:scheduled_report` 4. Try different requests with different schedules and notifications. It should respect the email domain allowlist if configured and reject invalid rrule schedules and email addresses. --------- Co-authored-by: Ersin Erdal <[email protected]> Co-authored-by: kibanamachine <[email protected]> Co-authored-by: Ersin Erdal <[email protected]> Co-authored-by: Elastic Machine <[email protected]>
1 parent 4c0b355 commit fd0a43d

File tree

49 files changed

+2743
-348
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2743
-348
lines changed

packages/kbn-check-mappings-update-cli/current_fields.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,9 @@
918918
"installCount",
919919
"unInstallCount"
920920
],
921+
"scheduled_report": [
922+
"createdBy"
923+
],
921924
"search": [
922925
"description",
923926
"title"

packages/kbn-check-mappings-update-cli/current_mappings.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3045,6 +3045,14 @@
30453045
}
30463046
}
30473047
},
3048+
"scheduled_report": {
3049+
"dynamic": false,
3050+
"properties": {
3051+
"createdBy": {
3052+
"type": "keyword"
3053+
}
3054+
}
3055+
},
30483056
"search": {
30493057
"dynamic": false,
30503058
"properties": {

src/core/server/integration_tests/saved_objects/registration/type_registrations.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ const previouslyRegisteredTypes = [
122122
'query',
123123
'rules-settings',
124124
'sample-data-telemetry',
125+
'scheduled_report',
125126
'search',
126127
'search-session',
127128
'search-telemetry',

src/platform/packages/private/kbn-reporting/common/routes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const INTERNAL_ROUTES = {
2626
},
2727
HEALTH: prefixInternalPath + '/_health',
2828
GENERATE_PREFIX: prefixInternalPath + '/generate', // exportTypeId is added to the final path
29+
SCHEDULE_PREFIX: prefixInternalPath + '/schedule', // exportTypeId is added to the final path
2930
};
3031

3132
const prefixPublicPath = '/api/reporting';

x-pack/platform/plugins/private/canvas/server/feature.test.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ it('Provides a feature declaration ', () => {
107107
"minimumLicense": "gold",
108108
"name": "Generate PDF reports",
109109
"savedObject": Object {
110-
"all": Array [],
110+
"all": Array [
111+
"scheduled_report",
112+
],
111113
"read": Array [],
112114
},
113115
"ui": Array [
@@ -216,7 +218,9 @@ it(`Calls on Reporting whether to include Generate PDF as a sub-feature`, () =>
216218
"minimumLicense": "gold",
217219
"name": "Generate PDF reports",
218220
"savedObject": Object {
219-
"all": Array [],
221+
"all": Array [
222+
"scheduled_report",
223+
],
220224
"read": Array [],
221225
},
222226
"ui": Array [

x-pack/platform/plugins/private/canvas/server/feature.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export function getCanvasFeature(plugins: { reporting?: ReportingStart }): Kiban
6868
includeIn: 'all',
6969
management: { insightsAndAlerting: ['reporting'] },
7070
minimumLicense: 'gold',
71-
savedObject: { all: [], read: [] },
71+
savedObject: { all: ['scheduled_report'], read: [] },
7272
api: ['generateReport'],
7373
ui: ['generatePdf'],
7474
},

x-pack/platform/plugins/private/reporting/kibana.jsonc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"reporting"
1717
],
1818
"requiredPlugins": [
19+
"actions",
1920
"data",
2021
"discover",
2122
"encryptedSavedObjects",

x-pack/platform/plugins/private/reporting/server/core.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import type {
2323
StatusServiceSetup,
2424
UiSettingsServiceStart,
2525
} from '@kbn/core/server';
26+
import { SECURITY_EXTENSION_ID } from '@kbn/core-saved-objects-server';
27+
import type { PluginSetupContract as ActionsPluginSetupContract } from '@kbn/actions-plugin/server';
2628
import type { PluginStart as DataPluginStart } from '@kbn/data-plugin/server';
2729
import type { DiscoverServerPluginStart } from '@kbn/discover-plugin/server';
2830
import type { FeaturesPluginSetup } from '@kbn/features-plugin/server';
@@ -55,8 +57,10 @@ import type { IReport, ReportingStore } from './lib/store';
5557
import { ExecuteReportTask, ReportTaskParams } from './lib/tasks';
5658
import type { ReportingPluginRouter } from './types';
5759
import { EventTracker } from './usage';
60+
import { SCHEDULED_REPORT_SAVED_OBJECT_TYPE } from './saved_objects';
5861

5962
export interface ReportingInternalSetup {
63+
actions: ActionsPluginSetupContract;
6064
basePath: Pick<IBasePath, 'set'>;
6165
docLinks: DocLinksServiceSetup;
6266
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup;
@@ -354,6 +358,13 @@ export class ReportingCore {
354358
);
355359
}
356360

361+
public validateNotificationEmails(emails: string[]): string | undefined {
362+
const pluginSetupDeps = this.getPluginSetupDeps();
363+
return pluginSetupDeps.actions
364+
.getActionsConfigurationUtilities()
365+
.validateEmailAddresses(emails);
366+
}
367+
357368
/*
358369
* Gives synchronous access to the setupDeps
359370
*/
@@ -374,6 +385,15 @@ export class ReportingCore {
374385
return dataViews;
375386
}
376387

388+
public async getSoClient(request: KibanaRequest) {
389+
const { savedObjects } = await this.getPluginStartDeps();
390+
const savedObjectsClient = savedObjects.getScopedClient(request, {
391+
excludedExtensions: [SECURITY_EXTENSION_ID],
392+
includedHiddenTypes: [SCHEDULED_REPORT_SAVED_OBJECT_TYPE],
393+
});
394+
return savedObjectsClient;
395+
}
396+
377397
public async getDataService() {
378398
const startDeps = await this.getPluginStartDeps();
379399
return startDeps.data;

x-pack/platform/plugins/private/reporting/server/plugin.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,21 @@ describe('Reporting Plugin', () => {
7676
);
7777
});
7878

79+
it('registers a saved object for scheduled reports', async () => {
80+
plugin.setup(coreSetup, pluginSetup);
81+
expect(coreSetup.savedObjects.registerType).toHaveBeenCalledWith(
82+
expect.objectContaining({
83+
name: 'scheduled_report',
84+
namespaceType: 'multiple',
85+
hidden: true,
86+
indexPattern: '.kibana_alerting_cases',
87+
management: {
88+
importableAndExportable: false,
89+
},
90+
})
91+
);
92+
});
93+
7994
it('logs start issues', async () => {
8095
// wait for the setup phase background work
8196
plugin.setup(coreSetup, pluginSetup);

x-pack/platform/plugins/private/reporting/server/plugin.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import type {
2727
import { ReportingRequestHandlerContext } from './types';
2828
import { registerReportingEventTypes, registerReportingUsageCollector } from './usage';
2929
import { registerFeatures } from './features';
30+
import { setupSavedObjects } from './saved_objects';
3031

3132
/*
3233
* @internal
@@ -75,6 +76,9 @@ export class ReportingPlugin
7576
registerReportingUsageCollector(reportingCore, plugins.usageCollection);
7677
registerReportingEventTypes(core);
7778

79+
// Saved objects
80+
setupSavedObjects(core.savedObjects);
81+
7882
// Routes
7983
registerRoutes(reportingCore, this.logger);
8084

0 commit comments

Comments
 (0)