mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
# Backport This will backport the following commits from `main` to `8.8`: - [[RAM][8.8] Fix get active maintenance window query (#157112)](https://github.com/elastic/kibana/pull/157112) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Jiawei Wu","email":"74562234+JiaweiWu@users.noreply.github.com"},"sourceCommit":{"committedDate":"2023-05-09T02:27:59Z","message":"[RAM][8.8] Fix get active maintenance window query (#157112)\n\n## Summary\r\nFix the active maintenance window query, originally the KQL query got\r\nconverted to something like:\r\n\r\n```\r\n query: {\r\n bool: {\r\n filter: [\r\n {\r\n range: {\r\n 'maintenance-window.attributes.events': {\r\n gte: from,\r\n },\r\n },\r\n },\r\n {\r\n range: {\r\n 'maintenance-window.attributes.events': {\r\n lte: to,\r\n },\r\n },\r\n },\r\n ],\r\n },\r\n},\r\n```\r\nWhen in reality we wanted a query like:\r\n\r\n```\r\nquery: {\r\n bool: {\r\n filter: \r\n range: {\r\n 'maintenance-window.attributes.events': {\r\n gte: from,\r\n lte: to,\r\n },\r\n },\r\n },\r\n },\r\n},\r\n```\r\nWhich return some upcoming maintenance windows that we did not want.\r\n\r\n### Checklist\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios","sha":"6d4f695b759b8fe30ac7314951c39dce6f27e376","branchLabelMapping":{"^v8.9.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","backport","release_note:skip","Team:ResponseOps","Feature:Alerting/RulesManagement","v8.8.0","v8.9.0"],"number":157112,"url":"https://github.com/elastic/kibana/pull/157112","mergeCommit":{"message":"[RAM][8.8] Fix get active maintenance window query (#157112)\n\n## Summary\r\nFix the active maintenance window query, originally the KQL query got\r\nconverted to something like:\r\n\r\n```\r\n query: {\r\n bool: {\r\n filter: [\r\n {\r\n range: {\r\n 'maintenance-window.attributes.events': {\r\n gte: from,\r\n },\r\n },\r\n },\r\n {\r\n range: {\r\n 'maintenance-window.attributes.events': {\r\n lte: to,\r\n },\r\n },\r\n },\r\n ],\r\n },\r\n},\r\n```\r\nWhen in reality we wanted a query like:\r\n\r\n```\r\nquery: {\r\n bool: {\r\n filter: \r\n range: {\r\n 'maintenance-window.attributes.events': {\r\n gte: from,\r\n lte: to,\r\n },\r\n },\r\n },\r\n },\r\n},\r\n```\r\nWhich return some upcoming maintenance windows that we did not want.\r\n\r\n### Checklist\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios","sha":"6d4f695b759b8fe30ac7314951c39dce6f27e376"}},"sourceBranch":"main","suggestedTargetBranches":["8.8"],"targetPullRequestStates":[{"branch":"8.8","label":"v8.8.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.9.0","labelRegex":"^v8.9.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/157112","number":157112,"mergeCommit":{"message":"[RAM][8.8] Fix get active maintenance window query (#157112)\n\n## Summary\r\nFix the active maintenance window query, originally the KQL query got\r\nconverted to something like:\r\n\r\n```\r\n query: {\r\n bool: {\r\n filter: [\r\n {\r\n range: {\r\n 'maintenance-window.attributes.events': {\r\n gte: from,\r\n },\r\n },\r\n },\r\n {\r\n range: {\r\n 'maintenance-window.attributes.events': {\r\n lte: to,\r\n },\r\n },\r\n },\r\n ],\r\n },\r\n},\r\n```\r\nWhen in reality we wanted a query like:\r\n\r\n```\r\nquery: {\r\n bool: {\r\n filter: \r\n range: {\r\n 'maintenance-window.attributes.events': {\r\n gte: from,\r\n lte: to,\r\n },\r\n },\r\n },\r\n },\r\n},\r\n```\r\nWhich return some upcoming maintenance windows that we did not want.\r\n\r\n### Checklist\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios","sha":"6d4f695b759b8fe30ac7314951c39dce6f27e376"}}]}] BACKPORT--> Co-authored-by: Jiawei Wu <74562234+JiaweiWu@users.noreply.github.com>
This commit is contained in:
parent
28a26dd8e7
commit
f55816f117
5 changed files with 79 additions and 100 deletions
|
@ -12,10 +12,7 @@ import { update, UpdateParams } from './methods/update';
|
|||
import { find, FindResult } from './methods/find';
|
||||
import { deleteMaintenanceWindow, DeleteParams } from './methods/delete';
|
||||
import { archive, ArchiveParams } from './methods/archive';
|
||||
import {
|
||||
getActiveMaintenanceWindows,
|
||||
ActiveParams,
|
||||
} from './methods/get_active_maintenance_windows';
|
||||
import { getActiveMaintenanceWindows } from './methods/get_active_maintenance_windows';
|
||||
import { finish, FinishParams } from './methods/finish';
|
||||
|
||||
import {
|
||||
|
@ -71,6 +68,6 @@ export class MaintenanceWindowClient {
|
|||
archive(this.context, params);
|
||||
public finish = (params: FinishParams): Promise<MaintenanceWindow> =>
|
||||
finish(this.context, params);
|
||||
public getActiveMaintenanceWindows = (params?: ActiveParams): Promise<MaintenanceWindow[]> =>
|
||||
getActiveMaintenanceWindows(this.context, params);
|
||||
public getActiveMaintenanceWindows = (): Promise<MaintenanceWindow[]> =>
|
||||
getActiveMaintenanceWindows(this.context);
|
||||
}
|
||||
|
|
|
@ -48,12 +48,7 @@ describe('MaintenanceWindowClient - getActiveMaintenanceWindows', () => {
|
|||
],
|
||||
} as unknown as SavedObjectsFindResponse);
|
||||
|
||||
const startDate = new Date().toISOString();
|
||||
|
||||
const result = await getActiveMaintenanceWindows(mockContext, {
|
||||
start: startDate,
|
||||
interval: '1h',
|
||||
});
|
||||
const result = await getActiveMaintenanceWindows(mockContext);
|
||||
|
||||
const findCallParams = savedObjectsClient.find.mock.calls[0][0];
|
||||
|
||||
|
@ -65,33 +60,11 @@ describe('MaintenanceWindowClient - getActiveMaintenanceWindows', () => {
|
|||
"filter": Array [
|
||||
Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
"minimum_should_match": 1,
|
||||
"should": Array [
|
||||
Object {
|
||||
"bool": Object {
|
||||
"minimum_should_match": 1,
|
||||
"should": Array [
|
||||
Object {
|
||||
"range": Object {
|
||||
"maintenance-window.attributes.events": Object {
|
||||
"gte": "2023-02-26T00:00:00.000Z",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"bool": Object {
|
||||
"minimum_should_match": 1,
|
||||
"should": Array [
|
||||
Object {
|
||||
"range": Object {
|
||||
"maintenance-window.attributes.events": Object {
|
||||
"lte": "2023-02-26T01:00:00.000Z",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"match": Object {
|
||||
"maintenance-window.attributes.events": "2023-02-26T00:00:00.000Z",
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -131,12 +104,7 @@ describe('MaintenanceWindowClient - getActiveMaintenanceWindows', () => {
|
|||
saved_objects: [],
|
||||
} as unknown as SavedObjectsFindResponse);
|
||||
|
||||
const startDate = new Date().toISOString();
|
||||
|
||||
const result = await getActiveMaintenanceWindows(mockContext, {
|
||||
start: startDate,
|
||||
interval: '4d',
|
||||
});
|
||||
const result = await getActiveMaintenanceWindows(mockContext);
|
||||
|
||||
const findCallParams = savedObjectsClient.find.mock.calls[0][0];
|
||||
|
||||
|
@ -147,33 +115,11 @@ describe('MaintenanceWindowClient - getActiveMaintenanceWindows', () => {
|
|||
"filter": Array [
|
||||
Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
"minimum_should_match": 1,
|
||||
"should": Array [
|
||||
Object {
|
||||
"bool": Object {
|
||||
"minimum_should_match": 1,
|
||||
"should": Array [
|
||||
Object {
|
||||
"range": Object {
|
||||
"maintenance-window.attributes.events": Object {
|
||||
"gte": "2023-02-26T00:00:00.000Z",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"bool": Object {
|
||||
"minimum_should_match": 1,
|
||||
"should": Array [
|
||||
Object {
|
||||
"range": Object {
|
||||
"maintenance-window.attributes.events": Object {
|
||||
"lte": "2023-03-02T00:00:00.000Z",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"match": Object {
|
||||
"maintenance-window.attributes.events": "2023-02-26T00:00:00.000Z",
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -203,17 +149,12 @@ describe('MaintenanceWindowClient - getActiveMaintenanceWindows', () => {
|
|||
|
||||
savedObjectsClient.find.mockRejectedValueOnce('something went wrong');
|
||||
|
||||
const startDate = new Date().toISOString();
|
||||
|
||||
await expect(async () => {
|
||||
await getActiveMaintenanceWindows(mockContext, {
|
||||
start: startDate,
|
||||
interval: '4d',
|
||||
});
|
||||
await getActiveMaintenanceWindows(mockContext);
|
||||
}).rejects.toThrowError();
|
||||
|
||||
expect(mockContext.logger.error).toHaveBeenLastCalledWith(
|
||||
'Failed to find active maintenance window by interval: 4d with start date: 2023-02-26T00:00:00.000Z, Error: something went wrong'
|
||||
'Failed to find active maintenance window by interval, Error: something went wrong'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,14 +6,12 @@
|
|||
*/
|
||||
|
||||
import Boom from '@hapi/boom';
|
||||
import moment from 'moment';
|
||||
import { nodeBuilder, fromKueryExpression } from '@kbn/es-query';
|
||||
import { nodeBuilder } from '@kbn/es-query';
|
||||
import { getMaintenanceWindowFromRaw } from '../get_maintenance_window_from_raw';
|
||||
import {
|
||||
MaintenanceWindow,
|
||||
MaintenanceWindowSOAttributes,
|
||||
MAINTENANCE_WINDOW_SAVED_OBJECT_TYPE,
|
||||
parseDuration,
|
||||
MaintenanceWindowClientContext,
|
||||
} from '../../../common';
|
||||
|
||||
|
@ -27,30 +25,16 @@ export interface MaintenanceWindowAggregationResult {
|
|||
};
|
||||
}
|
||||
|
||||
export interface ActiveParams {
|
||||
start?: string;
|
||||
interval?: string;
|
||||
}
|
||||
|
||||
export async function getActiveMaintenanceWindows(
|
||||
context: MaintenanceWindowClientContext,
|
||||
params?: ActiveParams
|
||||
context: MaintenanceWindowClientContext
|
||||
): Promise<MaintenanceWindow[]> {
|
||||
const { savedObjectsClient, logger } = context;
|
||||
const { start, interval } = params || {};
|
||||
|
||||
const startDate = start ? new Date(start) : new Date();
|
||||
const duration = interval ? parseDuration(interval) : 0;
|
||||
const endDate = moment.utc(startDate).add(duration, 'ms').toDate();
|
||||
|
||||
const startDate = new Date();
|
||||
const startDateISO = startDate.toISOString();
|
||||
const endDateISO = endDate.toISOString();
|
||||
|
||||
const filter = nodeBuilder.and([
|
||||
nodeBuilder.and([
|
||||
fromKueryExpression(`maintenance-window.attributes.events >= "${startDateISO}"`),
|
||||
fromKueryExpression(`maintenance-window.attributes.events <= "${endDateISO}"`),
|
||||
]),
|
||||
nodeBuilder.is('maintenance-window.attributes.events', startDateISO),
|
||||
nodeBuilder.is('maintenance-window.attributes.enabled', 'true'),
|
||||
]);
|
||||
|
||||
|
@ -67,7 +51,7 @@ export async function getActiveMaintenanceWindows(
|
|||
})
|
||||
);
|
||||
} catch (e) {
|
||||
const errorMessage = `Failed to find active maintenance window by interval: ${interval} with start date: ${startDate.toISOString()}, Error: ${e}`;
|
||||
const errorMessage = `Failed to find active maintenance window by interval, Error: ${e}`;
|
||||
logger.error(errorMessage);
|
||||
throw Boom.boomify(e, { message: errorMessage });
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ export const activeMaintenanceWindowsRoute = (
|
|||
});
|
||||
}
|
||||
const maintenanceWindowClient = (await context.alerting).getMaintenanceWindowClient();
|
||||
const result = await maintenanceWindowClient.getActiveMaintenanceWindows({});
|
||||
const result = await maintenanceWindowClient.getActiveMaintenanceWindows();
|
||||
|
||||
return res.ok({
|
||||
body: result.map((maintenanceWindow) => rewriteMaintenanceWindowRes(maintenanceWindow)),
|
||||
|
|
|
@ -24,10 +24,11 @@ export default function activeMaintenanceWindowTests({ getService }: FtrProvider
|
|||
r_rule: {
|
||||
dtstart: new Date().toISOString(),
|
||||
tzid: 'UTC',
|
||||
count: 10,
|
||||
freq: 2, // weekly
|
||||
},
|
||||
};
|
||||
after(() => objectRemover.removeAll());
|
||||
afterEach(() => objectRemover.removeAll());
|
||||
|
||||
for (const scenario of UserAtSpaceScenarios) {
|
||||
const { user, space } = scenario;
|
||||
|
@ -121,6 +122,62 @@ export default function activeMaintenanceWindowTests({ getService }: FtrProvider
|
|||
});
|
||||
}
|
||||
|
||||
it('should return active maintenance windows', async () => {
|
||||
const { body: window1 } = await supertest
|
||||
.post(`${getUrlPrefix('space1')}/internal/alerting/rules/maintenance_window`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send({
|
||||
...createParams,
|
||||
duration: 30 * 60 * 1000,
|
||||
r_rule: {
|
||||
...createParams.r_rule,
|
||||
dtstart: moment().subtract(1, 'hour').toISOString(),
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
objectRemover.add('space1', window1.id, 'rules/maintenance_window', 'alerting', true);
|
||||
|
||||
const { body: window2 } = await supertest
|
||||
.post(`${getUrlPrefix('space1')}/internal/alerting/rules/maintenance_window`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send({
|
||||
...createParams,
|
||||
duration: 30 * 60 * 1000,
|
||||
r_rule: {
|
||||
...createParams.r_rule,
|
||||
dtstart: moment().subtract(5, 'minutes').toISOString(),
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
objectRemover.add('space1', window2.id, 'rules/maintenance_window', 'alerting', true);
|
||||
|
||||
const { body: window3 } = await supertest
|
||||
.post(`${getUrlPrefix('space1')}/internal/alerting/rules/maintenance_window`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send({
|
||||
...createParams,
|
||||
duration: 30 * 60 * 1000,
|
||||
r_rule: {
|
||||
...createParams.r_rule,
|
||||
dtstart: moment().add(1, 'hour').toISOString(),
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
objectRemover.add('space1', window3.id, 'rules/maintenance_window', 'alerting', true);
|
||||
|
||||
const { body: activeWindows } = await supertest
|
||||
.get(`${getUrlPrefix('space1')}/internal/alerting/rules/maintenance_window/_active`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send({})
|
||||
.expect(200);
|
||||
|
||||
expect(activeWindows.length).eql(1);
|
||||
expect(activeWindows[0].id).eql(window2.id);
|
||||
});
|
||||
|
||||
it('should return an empty array if there are no active maintenance windows', async () => {
|
||||
const { body: createdMaintenanceWindow } = await supertest
|
||||
.post(`${getUrlPrefix('space1')}/internal/alerting/rules/maintenance_window`)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue