mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[RAM][8.8] Fix get active maintenance window query (#157112)
## Summary Fix the active maintenance window query, originally the KQL query got converted to something like: ``` query: { bool: { filter: [ { range: { 'maintenance-window.attributes.events': { gte: from, }, }, }, { range: { 'maintenance-window.attributes.events': { lte: to, }, }, }, ], }, }, ``` When in reality we wanted a query like: ``` query: { bool: { filter: range: { 'maintenance-window.attributes.events': { gte: from, lte: to, }, }, }, }, }, ``` Which return some upcoming maintenance windows that we did not want. ### 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
This commit is contained in:
parent
b3e495038b
commit
6d4f695b75
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