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

[RAM] Window Maintenance Client/Saved Object and Mapping/REST APIs #153411

Merged
merged 26 commits into from
Apr 13, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
df480b9
WIP
JiaweiWu Mar 20, 2023
8964c59
Fix merge conflict
JiaweiWu Mar 20, 2023
5e38793
Implement SO, mappings, and API methods
JiaweiWu Mar 21, 2023
6530f9c
Integration tests
JiaweiWu Mar 27, 2023
55d1a1e
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Mar 27, 2023
ef9d175
Don't index metadata
JiaweiWu Mar 27, 2023
6cdc4a9
Merge branch 'main' into issue-152270-window-maintenance-SO
kibanamachine Mar 27, 2023
83c2e85
Improve unit testing
JiaweiWu Mar 28, 2023
0fa810a
Fix tz differences in unit tests
JiaweiWu Mar 29, 2023
7658df8
Add new finish route, make tests involving timezone more consistent
JiaweiWu Mar 30, 2023
3ec6503
Route unit tests
JiaweiWu Mar 30, 2023
4c02533
Make update APIs idempotent and commutative, fix rest of the tests
JiaweiWu Apr 3, 2023
9e5bc4f
Merge branch 'main' into issue-152270-window-maintenance-SO
kibanamachine Apr 3, 2023
3ee27f4
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Apr 3, 2023
fba8c7e
Add total property to find response, change start/end date names
JiaweiWu Apr 4, 2023
29f1da7
Fix merge conflict
JiaweiWu Apr 6, 2023
f5751bc
Change maintenance window SO namespaceType
JiaweiWu Apr 6, 2023
0433225
Update test snapshot
JiaweiWu Apr 6, 2023
a54fbe0
Remove aggregate to active function
JiaweiWu Apr 11, 2023
fd48776
Undo changes to bucket_aggs.ts
JiaweiWu Apr 11, 2023
5c94aa6
Merge branch 'main' into issue-152270-window-maintenance-SO
kibanamachine Apr 12, 2023
1bb7216
Merge branch 'main' into issue-152270-window-maintenance-SO
kibanamachine Apr 12, 2023
6381964
Fix getActiveMaintenanceWindow filter
JiaweiWu Apr 12, 2023
d65b6a9
Addressed comments
JiaweiWu Apr 13, 2023
1525d5e
Revert changes to merge event
JiaweiWu Apr 13, 2023
6e0d36f
Merge branch 'main' into issue-152270-window-maintenance-SO
kibanamachine Apr 13, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ import { sortOrderSchema } from './common_schemas';
* - filter
* - filters
* - composite
* - date_histogram
*
* Not implemented:
* - adjacency_matrix
* - auto_date_histogram
* - children
* - date_histogram
* - diversified_sampler
* - geo_distance
* - geohash_grid
Expand Down Expand Up @@ -161,6 +161,25 @@ const histogramSchema = s.object({
),
});

const dateHistogramSchema = s.object({
field: s.maybe(s.string()),
interval: s.maybe(s.oneOf([s.string(), s.literal(0), s.literal(-1)])),
fixed_interval: s.maybe(s.oneOf([s.string(), s.literal(0), s.literal(-1)])),
min_doc_count: s.maybe(s.number({ min: 0 })),
extended_bounds: s.maybe(
s.object({
min: s.oneOf([s.string(), s.number()]),
max: s.oneOf([s.string(), s.number()]),
})
),
hard_bounds: s.maybe(
s.object({
min: s.oneOf([s.string(), s.number()]),
max: s.oneOf([s.string(), s.number()]),
})
),
});

const compositeSchema = s.object({
size: s.maybe(s.number()),
after: s.maybe(s.recordOf(s.string(), s.nullable(s.oneOf([s.string(), s.number()])))),
Expand All @@ -183,6 +202,7 @@ export const bucketAggsSchemas: Record<string, ObjectType> = {
filters: s.recordOf(s.string(), s.oneOf([termSchema, boolSchema])),
}),
histogram: histogramSchema,
date_histogram: dateHistogramSchema,
nested: s.object({
path: s.string(),
}),
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/alerting/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export * from './rule_notify_when_type';
export * from './parse_duration';
export * from './execution_log_types';
export * from './rule_snooze_type';
export * from './rrule_type';
export * from './maintenance_window';
export * from './default_rule_aggregation';
export * from './rule_tags_aggregation';

Expand Down
60 changes: 60 additions & 0 deletions x-pack/plugins/alerting/common/maintenance_window.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { Logger, SavedObjectsClientContract } from '@kbn/core/server';
import { RRuleParams } from './rrule_type';

export enum MaintenanceWindowStatus {
Running = 'running',
Upcoming = 'upcoming',
Finished = 'finished',
Archived = 'archived',
}

export interface MaintenanceWindowModificationMetadata {
createdBy: string | null;
updatedBy: string | null;
createdAt: string;
updatedAt: string;
}

export interface DateRange {
gte: string;
lte: string;
}

export interface MaintenanceWindowSOProperties {
title: string;
enabled: boolean;
duration: number;
expirationDate: string;
events: DateRange[];
rRule: RRuleParams;
}

export type MaintenanceWindowSOAttributes = MaintenanceWindowSOProperties &
MaintenanceWindowModificationMetadata;

export type MaintenanceWindow = MaintenanceWindowSOAttributes & {
status: MaintenanceWindowStatus;
startDate: string | null;
endDate: string | null;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have these start and end dates that map to:
image

The dates indicate the start and end date of the current or upcoming EVENT, not the start and end date of the entire maintenance window schedule, should I name these something like eventStartDate instead?

Copy link
Contributor

Choose a reason for hiding this comment

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

eventStartDate sounds good to me, I agree that start and end date could be confusing

id: string;
};

export interface MaintenanceWindowClientContext {
getModificationMetadata: () => Promise<MaintenanceWindowModificationMetadata>;
savedObjectsClient: SavedObjectsClientContract;
logger: Logger;
}

export const MAINTENANCE_WINDOW_SAVED_OBJECT_TYPE = 'maintenance-window';
export const MAINTENANCE_WINDOW_FEATURE_ID = 'maintenanceWindow';
export const MAINTENANCE_WINDOW_API_PRIVILEGES = {
READ_MAINTENANCE_WINDOW: 'read-maintenance-window',
WRITE_MAINTENANCE_WINDOW: 'write-maintenance-window',
};
30 changes: 30 additions & 0 deletions x-pack/plugins/alerting/common/rrule_type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import type { WeekdayStr } from 'rrule';

export type RRuleParams = Partial<RRuleRecord> & Pick<RRuleRecord, 'dtstart' | 'tzid'>;

// An iCal RRULE to define a recurrence schedule, see https://github.com/jakubroztocil/rrule for the spec
export interface RRuleRecord {
dtstart: string;
tzid: string;
freq?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
until?: string;
count?: number;
interval?: number;
wkst?: WeekdayStr;
byweekday?: Array<string | number>;
bymonth?: number[];
bysetpos?: number[];
bymonthday: number[];
byyearday: number[];
byweekno: number[];
byhour: number[];
byminute: number[];
bysecond: number[];
}
28 changes: 3 additions & 25 deletions x-pack/plugins/alerting/common/rule_snooze_type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@
* 2.0.
*/

import type { WeekdayStr } from 'rrule';

type SnoozeRRule = Partial<RRuleRecord> & Pick<RRuleRecord, 'dtstart' | 'tzid'>;
import { RRuleParams } from './rrule_type';

export interface RuleSnoozeSchedule {
duration: number;
rRule: SnoozeRRule;
rRule: RRuleParams;
// For scheduled/recurring snoozes, `id` uniquely identifies them so that they can be displayed, modified, and deleted individually
id?: string;
skipRecurrences?: string[];
Expand All @@ -21,27 +19,7 @@ export interface RuleSnoozeSchedule {
// RuleSnooze = RuleSnoozeSchedule[] throws typescript errors across the whole lib
export type RuleSnooze = Array<{
duration: number;
rRule: SnoozeRRule;
rRule: RRuleParams;
id?: string;
skipRecurrences?: string[];
}>;

// An iCal RRULE to define a recurrence schedule, see https://github.com/jakubroztocil/rrule for the spec
export interface RRuleRecord {
dtstart: string;
tzid: string;
freq?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
until?: string;
count?: number;
interval?: number;
wkst?: WeekdayStr;
byweekday?: Array<string | number>;
bymonth?: number[];
bysetpos?: number[];
bymonthday: number[];
byyearday: number[];
byweekno: number[];
byhour: number[];
byminute: number[];
bysecond: number[];
}
8 changes: 8 additions & 0 deletions x-pack/plugins/alerting/server/lib/rrule/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export * from './parse_by_weekday';
13 changes: 13 additions & 0 deletions x-pack/plugins/alerting/server/lib/rrule/parse_by_weekday.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { ByWeekday, rrulestr } from 'rrule';

export function parseByWeekday(byweekday: Array<string | number>): ByWeekday[] {
const rRuleString = `RRULE:BYDAY=${byweekday.join(',')}`;
const parsedRRule = rrulestr(rRuleString);
return parsedRRule.origOptions.byweekday as ByWeekday[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import moment from 'moment';
import { generateMaintenanceWindowEvents } from './generate_maintenance_window_events';

describe('generateMaintenanceWindowEvents', () => {
beforeAll(() => {
jest.useFakeTimers().setSystemTime(new Date('2023-02-27T00:00:00.000Z'));
});

it('should generate events', () => {
const result = generateMaintenanceWindowEvents({
duration: 1 * 60 * 60 * 1000,
expirationDate: moment(new Date('2023-02-27T00:00:00.000Z')).add(5, 'weeks').toISOString(),
rRule: {
tzid: 'UTC',
freq: 2,
interval: 1,
dtstart: '2023-02-27T00:00:00.000Z',
},
});

expect(result.length).toEqual(5);

expect(result[0].gte).toEqual('2023-02-27T00:00:00.000Z');
expect(result[0].lte).toEqual('2023-02-27T01:00:00.000Z');

expect(result[4].gte).toEqual('2023-03-27T00:00:00.000Z');
expect(result[4].lte).toEqual('2023-03-27T01:00:00.000Z');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import moment from 'moment';
import { RRule, Weekday } from 'rrule';
import { parseByWeekday } from '../lib/rrule';
import { RRuleParams } from '../../common';

export interface GenerateMaintenanceWindowEventsParams {
rRule: RRuleParams;
expirationDate: string;
duration: number;
}

export const generateMaintenanceWindowEvents = ({
rRule,
expirationDate,
duration,
}: GenerateMaintenanceWindowEventsParams) => {
const { dtstart, until, wkst, byweekday } = rRule;
const rRuleOptions = {
...rRule,
dtstart: new Date(dtstart),
until: until ? new Date(until) : null,
wkst: wkst ? Weekday.fromStr(wkst) : null,
byweekday: byweekday ? parseByWeekday(byweekday) : null,
};

try {
const startDate = new Date(dtstart);
const endDate = new Date(expirationDate);
const recurrenceRule = new RRule(rRuleOptions);
const occurrenceDates = recurrenceRule.between(startDate, endDate, true);

return occurrenceDates.map((date) => ({
gte: date.toISOString(),
lte: moment(date).add(duration, 'ms').toISOString(),
}));
} catch (e) {
throw new Error(`Failed to process RRule ${rRule}. Error: ${e}`);
}
};
Loading