diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/active_maintenance_windows.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/active_maintenance_windows.ts index ac1429ae4fc34..6fcbd569594ff 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/active_maintenance_windows.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/active_maintenance_windows.ts @@ -33,8 +33,7 @@ export default function activeMaintenanceWindowTests({ getService }: FtrProvider for (const scenario of UserAtSpaceScenarios) { const { user, space } = scenario; describe(scenario.id, () => { - afterEach(() => objectRemover.removeAll()); - it('should handle update maintenance window request appropriately', async () => { + it('should handle get active maintenance window request appropriately', async () => { // Create 2 active and 1 inactive maintenance window const { body: createdMaintenanceWindow1 } = await supertest .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/maintenance_window`) diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/archive_maintenance_window.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/archive_maintenance_window.ts index da9e35165a63d..589c552a2489a 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/archive_maintenance_window.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/archive_maintenance_window.ts @@ -27,7 +27,7 @@ export default function updateMaintenanceWindowTests({ getService }: FtrProvider freq: 2, // weekly }, }; - after(() => objectRemover.removeAll()); + afterEach(() => objectRemover.removeAll()); for (const scenario of UserAtSpaceScenarios) { const { user, space } = scenario; @@ -84,5 +84,103 @@ export default function updateMaintenanceWindowTests({ getService }: FtrProvider }); }); } + + it('can archive and unarchive a maintenance window', async () => { + const space1 = UserAtSpaceScenarios[1].space.id; + const { body: createdMaintenanceWindow } = await supertest + .post(`${getUrlPrefix(space1)}/internal/alerting/rules/maintenance_window`) + .set('kbn-xsrf', 'foo') + .send(createParams) + .expect(200); + + objectRemover.add( + space1, + createdMaintenanceWindow.id, + 'rules/maintenance_window', + 'alerting', + true + ); + + expect(createdMaintenanceWindow.status).eql('running'); + + const { body: archive } = await supertest + .post( + `${getUrlPrefix(space1)}/internal/alerting/rules/maintenance_window/${ + createdMaintenanceWindow.id + }/_archive` + ) + .set('kbn-xsrf', 'foo') + .send({ archive: true }) + .expect(200); + + expect(archive.status).eql('archived'); + + const { body: unarchived } = await supertest + .post( + `${getUrlPrefix(space1)}/internal/alerting/rules/maintenance_window/${ + createdMaintenanceWindow.id + }/_archive` + ) + .set('kbn-xsrf', 'foo') + .send({ archive: false }) + .expect(200); + + expect(unarchived.status).eql('running'); + }); + + it('archiving a finished maintenance window does not change the events', async () => { + const space1 = UserAtSpaceScenarios[1].space.id; + const { body: createdMaintenanceWindow } = await supertest + .post(`${getUrlPrefix(space1)}/internal/alerting/rules/maintenance_window`) + .set('kbn-xsrf', 'foo') + .send({ + ...createParams, + r_rule: { + ...createParams.r_rule, + dtstart: moment.utc().subtract(1, 'day').toISOString(), + freq: 3, // daily + count: 4, + }, + }) + .expect(200); + + objectRemover.add( + space1, + createdMaintenanceWindow.id, + 'rules/maintenance_window', + 'alerting', + true + ); + + const { body: finish } = await supertest + .post( + `${getUrlPrefix(space1)}/internal/alerting/rules/maintenance_window/${ + createdMaintenanceWindow.id + }/_finish` + ) + .set('kbn-xsrf', 'foo') + .send() + .expect(200); + + // The finished maintenance window has a different end date for the first event + expect(finish.events[0].lte).eql(createdMaintenanceWindow.events[0].lte); + expect(finish.events[1].lte).not.eql(createdMaintenanceWindow.events[1].lte); + expect(finish.events[2].lte).eql(createdMaintenanceWindow.events[2].lte); + expect(finish.events[3].lte).eql(createdMaintenanceWindow.events[3].lte); + + const { body: archive } = await supertest + .post( + `${getUrlPrefix(space1)}/internal/alerting/rules/maintenance_window/${ + createdMaintenanceWindow.id + }/_archive` + ) + .set('kbn-xsrf', 'foo') + .send({ archive: true }) + .expect(200); + + // Archiving should not change the events + expect(finish.events[0].lte).eql(archive.events[0].lte); + expect(finish.events[1].lte).eql(archive.events[1].lte); + }); }); } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/create_maintenance_window.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/create_maintenance_window.ts index a8ab4b340fd53..424c39fc1c142 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/create_maintenance_window.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/create_maintenance_window.ts @@ -26,7 +26,7 @@ export default function createMaintenanceWindowTests({ getService }: FtrProvider freq: 2, // weekly }, }; - after(() => objectRemover.removeAll()); + afterEach(() => objectRemover.removeAll()); for (const scenario of UserAtSpaceScenarios) { const { user, space } = scenario; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/delete_maintenance_window.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/delete_maintenance_window.ts index 1af86317435d4..63175f1a0dffd 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/delete_maintenance_window.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/delete_maintenance_window.ts @@ -26,7 +26,7 @@ export default function deleteMaintenanceWindowTests({ getService }: FtrProvider freq: 2, // weekly }, }; - after(() => objectRemover.removeAll()); + afterEach(() => objectRemover.removeAll()); for (const scenario of UserAtSpaceScenarios) { const { user, space } = scenario; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/find_maintenance_windows.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/find_maintenance_windows.ts index 1ebae969b05a6..0efdfb72f7626 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/find_maintenance_windows.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/find_maintenance_windows.ts @@ -26,13 +26,12 @@ export default function findMaintenanceWindowTests({ getService }: FtrProviderCo freq: 2, // weekly }, }; - after(() => objectRemover.removeAll()); + afterEach(() => objectRemover.removeAll()); for (const scenario of UserAtSpaceScenarios) { const { user, space } = scenario; describe(scenario.id, () => { - afterEach(() => objectRemover.removeAll()); - it('should handle update maintenance window request appropriately', async () => { + it('should handle find maintenance window request appropriately', async () => { const { body: createdMaintenanceWindow1 } = await supertest .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/maintenance_window`) .set('kbn-xsrf', 'foo') diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/finish_maintenance_window.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/finish_maintenance_window.ts index 9612a3ecc0d3f..49db0500da75d 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/finish_maintenance_window.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/finish_maintenance_window.ts @@ -80,5 +80,99 @@ export default function findMaintenanceWindowTests({ getService }: FtrProviderCo }); }); } + + it('should error when trying to finish a finished maintenance window', async () => { + const space1 = UserAtSpaceScenarios[1].space.id; + const { body: createdMaintenanceWindow } = await supertest + .post(`${getUrlPrefix(space1)}/internal/alerting/rules/maintenance_window`) + .set('kbn-xsrf', 'foo') + .send({ + ...createParams, + r_rule: { + ...createParams.r_rule, + count: 1, + }, + }) + .expect(200); + + objectRemover.add( + space1, + createdMaintenanceWindow.id, + 'rules/maintenance_window', + 'alerting', + true + ); + + const { body: finish } = await supertest + .post( + `${getUrlPrefix(space1)}/internal/alerting/rules/maintenance_window/${ + createdMaintenanceWindow.id + }/_finish` + ) + .set('kbn-xsrf', 'foo') + .send() + .expect(200); + expect(finish.status).eql('finished'); + + // Cant finish a finished maintenance window + await supertest + .post( + `${getUrlPrefix(space1)}/internal/alerting/rules/maintenance_window/${ + createdMaintenanceWindow.id + }/_finish` + ) + .set('kbn-xsrf', 'foo') + .send() + .expect(400); + }); + + it('should error when trying to finish a upcoming maintenance window', async () => { + const space1 = UserAtSpaceScenarios[1].space.id; + const { body: createdMaintenanceWindow } = await supertest + .post(`${getUrlPrefix(space1)}/internal/alerting/rules/maintenance_window`) + .set('kbn-xsrf', 'foo') + .send({ + ...createParams, + r_rule: { + ...createParams.r_rule, + count: 2, // 2 occurrences + }, + }) + .expect(200); + + objectRemover.add( + space1, + createdMaintenanceWindow.id, + 'rules/maintenance_window', + 'alerting', + true + ); + + const { body: finish } = await supertest + .post( + `${getUrlPrefix(space1)}/internal/alerting/rules/maintenance_window/${ + createdMaintenanceWindow.id + }/_finish` + ) + .set('kbn-xsrf', 'foo') + .send() + .expect(200); + + // Status now upcoming, new start and end dates reflect the upcoming event + expect(finish.status).eql('upcoming'); + expect(finish.event_start_time).eql(createdMaintenanceWindow.events[1].gte); + expect(finish.event_end_time).eql(createdMaintenanceWindow.events[1].lte); + + // Cannot finish an upcoming maintenance window + await supertest + .post( + `${getUrlPrefix(space1)}/internal/alerting/rules/maintenance_window/${ + createdMaintenanceWindow.id + }/_finish` + ) + .set('kbn-xsrf', 'foo') + .send() + .expect(400); + }); }); } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/get_maintenance_window.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/get_maintenance_window.ts index f2d6d8faa0b53..4641c1a309abb 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/get_maintenance_window.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/get_maintenance_window.ts @@ -26,7 +26,7 @@ export default function getMaintenanceWindowTests({ getService }: FtrProviderCon freq: 2, // weekly }, }; - after(() => objectRemover.removeAll()); + afterEach(() => objectRemover.removeAll()); for (const scenario of UserAtSpaceScenarios) { const { user, space } = scenario; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/update_maintenance_window.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/update_maintenance_window.ts index 40550997eed06..fd4879e3e098f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/update_maintenance_window.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/maintenance_window/update_maintenance_window.ts @@ -27,7 +27,7 @@ export default function updateMaintenanceWindowTests({ getService }: FtrProvider freq: 2, // weekly }, }; - after(() => objectRemover.removeAll()); + afterEach(() => objectRemover.removeAll()); for (const scenario of UserAtSpaceScenarios) { const { user, space } = scenario; @@ -90,6 +90,58 @@ export default function updateMaintenanceWindowTests({ getService }: FtrProvider }); } + it('should update fields correctly', async () => { + const { body: createdMaintenanceWindow } = await supertest + .post(`${getUrlPrefix('space1')}/internal/alerting/rules/maintenance_window`) + .set('kbn-xsrf', 'foo') + .send({ + title: 'test-maintenance-window', + duration: 60 * 60 * 1000, // 1 hr + r_rule: { + dtstart: new Date().toISOString(), + tzid: 'UTC', + freq: 2, // weekly + count: 1, + }, + }) + .expect(200); + + objectRemover.add( + 'space1', + createdMaintenanceWindow.id, + 'rules/maintenance_window', + 'alerting', + true + ); + + const newRRule = { + dtstart: moment.utc().add(1, 'day').toISOString(), + tzid: 'CET', + freq: 3, + count: 5, + }; + + const { body: updatedMW } = await supertest + .post( + `${getUrlPrefix('space1')}/internal/alerting/rules/maintenance_window/${ + createdMaintenanceWindow.id + }` + ) + .set('kbn-xsrf', 'foo') + .send({ + title: 'test-maintenance-window-new', + duration: 60 * 1000, + r_rule: newRRule, + enabled: false, + }) + .expect(200); + + expect(updatedMW.title).eql('test-maintenance-window-new'); + expect(updatedMW.duration).eql(60 * 1000); + expect(updatedMW.r_rule).eql(newRRule); + expect(updatedMW.title).eql('test-maintenance-window-new'); + }); + it('should update RRule correctly when removing fields', async () => { const { body: createdMaintenanceWindow } = await supertest .post(`${getUrlPrefix('space1')}/internal/alerting/rules/maintenance_window`) diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/event_log.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/event_log.ts index 4e3a3fb70a455..2fe26f2bdb927 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/event_log.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/event_log.ts @@ -1308,6 +1308,104 @@ export default function eventLogTests({ getService }: FtrProviderContext) { } }); }); + + it('should not fire summary actions during maintenance window', async () => { + const { body: window } = await supertest + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/maintenance_window`) + .set('kbn-xsrf', 'foo') + .send({ + title: 'test-maintenance-window-1', + duration: 60 * 60 * 1000, // 1 hr + r_rule: { + dtstart: moment.utc().toISOString(), + tzid: 'UTC', + freq: 0, // yearly + count: 1, + }, + }) + .expect(200); + objectRemover.add(space.id, window.id, 'rules/maintenance_window', 'alerting', true); + + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(space.id)}/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'Test conn', + connector_type_id: 'test.noop', + config: {}, + secrets: {}, + }) + .expect(200); + objectRemover.add(space.id, createdAction.id, 'action', 'actions'); + + const { body: createdRule } = await supertest + .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getTestRuleData({ + rule_type_id: 'test.always-firing-alert-as-data', + schedule: { interval: '24h' }, + throttle: undefined, + notify_when: undefined, + params: { + index: ES_TEST_INDEX_NAME, + reference: 'test', + }, + actions: [ + { + id: createdAction.id, + group: 'default', + params: { + index: ES_TEST_INDEX_NAME, + reference: 'test', + message: '', + }, + frequency: { + summary: true, + throttle: null, + notify_when: 'onActiveAlert', + }, + }, + ], + }) + ) + .expect(200); + objectRemover.add(space.id, createdRule.id, 'rule', 'alerting'); + + // get the events we're expecting + await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: space.id, + type: 'alert', + id: createdRule.id, + provider: 'alerting', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ['active-instance', { equal: 2 }], + ]), + }); + }); + + // Try to get actions, should fail + let hasActions = false; + try { + await getEventLog({ + getService, + spaceId: space.id, + type: 'alert', + id: createdRule.id, + provider: 'alerting', + actions: new Map([['execute-action', { equal: 1 }]]), + }); + hasActions = true; + } catch (e) { + hasActions = false; + } + + expect(hasActions).eql(false); + }); }); } }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/index.ts index 05fcb4f95d901..0b8e43039c33a 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/index.ts @@ -15,5 +15,6 @@ export default function alertingTests({ loadTestFile, getService }: FtrProviderC after(async () => await tearDown(getService)); loadTestFile(require.resolve('./builtin_alert_types')); + loadTestFile(require.resolve('./maintenance_window_flows')); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/maintenance_window_flows.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/maintenance_window_flows.ts new file mode 100644 index 0000000000000..fd7f695c9fb62 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/maintenance_window_flows.ts @@ -0,0 +1,323 @@ +/* + * 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 { IValidatedEvent } from '@kbn/event-log-plugin/server'; +import moment from 'moment'; +import expect from '@kbn/expect'; +import { Spaces } from '../../../scenarios'; +import { getUrlPrefix, getTestRuleData, ObjectRemover, getEventLog } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function maintenanceWindowFlowsTests({ getService }: FtrProviderContext) { + const supertestWithoutAuth = getService('supertestWithoutAuth'); + const supertest = getService('supertest'); + const retry = getService('retry'); + + describe('maintenanceWindowFlows', () => { + const objectRemover = new ObjectRemover(supertestWithoutAuth); + + afterEach(async () => { + await objectRemover.removeAll(); + }); + + it('alerts triggered before a MW should fire actions when active or recovered during a MW', async () => { + const pattern = { + instance: [true, true, false, true], + }; + + // Create action and rule + const action = await createAction(); + const rule = await createRule({ actionId: action.id, pattern }); + + // Run the first time - active + await getRuleEvents({ + id: rule.id, + action: 1, + activeInstance: 1, + }); + + // Run again - active, 2 action + await runSoon(rule.id); + await getRuleEvents({ + id: rule.id, + action: 2, + activeInstance: 2, + }); + + // Create active maintenance window + const maintenanceWindow = await createMaintenanceWindow(); + const activeMaintenanceWindows = await getActiveMaintenanceWindows(); + expect(activeMaintenanceWindows[0].id).eql(maintenanceWindow.id); + + // Run again - recovered, 3 actions, fired in MW + await runSoon(rule.id); + await getRuleEvents({ + id: rule.id, + action: 3, + activeInstance: 2, + recoveredInstance: 1, + }); + + // Run again - active, 3 actions, new active action NOT fired in MW + await runSoon(rule.id); + await getRuleEvents({ + id: rule.id, + action: 3, + activeInstance: 3, + recoveredInstance: 1, + }); + }); + + it('alerts triggered within a MW should not fire actions if active or recovered during a MW', async () => { + const pattern = { + instance: [true, true, false, true], + }; + + // Create active maintenance window + const maintenanceWindow = await createMaintenanceWindow(); + const activeMaintenanceWindows = await getActiveMaintenanceWindows(); + expect(activeMaintenanceWindows[0].id).eql(maintenanceWindow.id); + + // Create action and rule + const action = await createAction(); + const rule = await createRule({ actionId: action.id, pattern }); + + // Run the first time - active + await getRuleEvents({ id: rule.id, activeInstance: 1 }); + + await expectNoActionsFired(rule.id); + + // Run again - active + await runSoon(rule.id); + await getRuleEvents({ id: rule.id, activeInstance: 2 }); + + await expectNoActionsFired(rule.id); + + // Run again - recovered + await runSoon(rule.id); + await getRuleEvents({ id: rule.id, activeInstance: 2, recoveredInstance: 1 }); + + await expectNoActionsFired(rule.id); + + // Run again - active again + await runSoon(rule.id); + await getRuleEvents({ id: rule.id, activeInstance: 3, recoveredInstance: 1 }); + + await expectNoActionsFired(rule.id); + }); + + it('alerts triggered within a MW should not fire actions if active or recovered outside a MW', async () => { + const pattern = { + instance: [true, true, false, true], + }; + + // Create active maintenance window + const maintenanceWindow = await createMaintenanceWindow(); + const activeMaintenanceWindows = await getActiveMaintenanceWindows(); + expect(activeMaintenanceWindows[0].id).eql(maintenanceWindow.id); + + // Create action and rule + const action = await createAction(); + const rule = await createRule({ actionId: action.id, pattern }); + + // Run the first time - active + await getRuleEvents({ id: rule.id, activeInstance: 1 }); + + await expectNoActionsFired(rule.id); + + // End the maintenance window + await finishMaintenanceWindow(maintenanceWindow.id); + const empty = await getActiveMaintenanceWindows(); + expect(empty).eql([]); + + // Run again - active + await runSoon(rule.id); + await getRuleEvents({ id: rule.id, activeInstance: 2 }); + + await expectNoActionsFired(rule.id); + + // Run again - recovered + await runSoon(rule.id); + await getRuleEvents({ id: rule.id, activeInstance: 2, recoveredInstance: 1 }); + + await expectNoActionsFired(rule.id); + + // Run again - active again, this time fire the action since its a new alert instance + await runSoon(rule.id); + await getRuleEvents({ + id: rule.id, + action: 1, + activeInstance: 3, + recoveredInstance: 1, + }); + }); + + // Helper functions: + async function createRule({ + actionId, + pattern, + }: { + actionId: string; + pattern: { instance: boolean[] }; + }) { + const { body: createdRule } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getTestRuleData({ + name: 'test-rule', + rule_type_id: 'test.patternFiring', + schedule: { interval: '24h' }, + throttle: null, + notify_when: 'onActiveAlert', + params: { + pattern, + }, + actions: [ + { + id: actionId, + group: 'default', + params: {}, + }, + { + id: actionId, + group: 'recovered', + params: {}, + }, + ], + }) + ) + .expect(200); + + objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting'); + return createdRule; + } + + async function createAction() { + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'MY action', + connector_type_id: 'test.noop', + config: {}, + secrets: {}, + }) + .expect(200); + + objectRemover.add(Spaces.space1.id, createdAction.id, 'action', 'actions'); + return createdAction; + } + + async function createMaintenanceWindow() { + const { body: window } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/maintenance_window`) + .set('kbn-xsrf', 'foo') + .send({ + title: 'test-maintenance-window-1', + duration: 60 * 60 * 1000, // 1 hr + r_rule: { + dtstart: moment.utc().toISOString(), + tzid: 'UTC', + freq: 0, // yearly + count: 1, + }, + }) + .expect(200); + + objectRemover.add(Spaces.space1.id, window.id, 'rules/maintenance_window', 'alerting', true); + return window; + } + + async function getActiveMaintenanceWindows() { + const { body: activeMaintenanceWindows } = await supertest + .get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/maintenance_window/_active`) + .set('kbn-xsrf', 'foo') + .expect(200); + + return activeMaintenanceWindows; + } + + function finishMaintenanceWindow(id: string) { + return supertest + .post( + `${getUrlPrefix( + Spaces.space1.id + )}/internal/alerting/rules/maintenance_window/${id}/_finish` + ) + .set('kbn-xsrf', 'foo') + .expect(200); + } + + async function getRuleEvents({ + id, + action, + newInstance, + activeInstance, + recoveredInstance, + }: { + id: string; + action?: number; + newInstance?: number; + activeInstance?: number; + recoveredInstance?: number; + }) { + const actions: Array<[string, { equal: number }]> = []; + if (action) { + actions.push(['execute-action', { equal: action }]); + } + if (newInstance) { + actions.push(['new-instance', { equal: newInstance }]); + } + if (activeInstance) { + actions.push(['active-instance', { equal: activeInstance }]); + } + if (recoveredInstance) { + actions.push(['recovered-instance', { equal: recoveredInstance }]); + } + return retry.try(async () => { + return await getEventLog({ + getService, + spaceId: Spaces.space1.id, + type: 'alert', + id, + provider: 'alerting', + actions: new Map(actions), + }); + }); + } + + async function expectNoActionsFired(id: string) { + const events = await retry.try(async () => { + const { body: result } = await supertest + .get(`${getUrlPrefix(Spaces.space1.id)}/_test/event_log/alert/${id}/_find?per_page=5000`) + .expect(200); + + if (!result.total) { + throw new Error('no events found yet'); + } + return result.data as IValidatedEvent[]; + }); + + const actionEvents = events.filter((event) => { + return event?.event?.action === 'execute-action'; + }); + + expect(actionEvents.length).eql(0); + } + + function runSoon(id: string) { + return retry.try(async () => { + await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${id}/_run_soon`) + .set('kbn-xsrf', 'foo') + .expect(204); + }); + } + }); +}