mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
Rule find post (#148836)
## Summary FIX -> https://github.com/elastic/kibana/issues/148287 ### 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
e3c8b3cbe4
commit
f2342fc3a8
10 changed files with 906 additions and 79 deletions
|
@ -93,4 +93,29 @@ export const aggregateRulesRoute = (
|
|||
})
|
||||
)
|
||||
);
|
||||
router.post(
|
||||
{
|
||||
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rules/_aggregate`,
|
||||
validate: {
|
||||
body: querySchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(
|
||||
verifyAccessAndContext(licenseState, async function (context, req, res) {
|
||||
const rulesClient = (await context.alerting).getRulesClient();
|
||||
const options = rewriteQueryReq({
|
||||
...req.body,
|
||||
has_reference: req.body.has_reference || undefined,
|
||||
});
|
||||
trackLegacyTerminology(
|
||||
[req.body.search, req.body.search_fields].filter(Boolean) as string[],
|
||||
usageCounter
|
||||
);
|
||||
const aggregateResult = await rulesClient.aggregate({ options });
|
||||
return res.ok({
|
||||
body: rewriteBodyRes(aggregateResult),
|
||||
});
|
||||
})
|
||||
)
|
||||
);
|
||||
};
|
||||
|
|
|
@ -136,6 +136,51 @@ const buildFindRulesRoute = ({
|
|||
})
|
||||
)
|
||||
);
|
||||
if (path === `${INTERNAL_BASE_ALERTING_API_PATH}/rules/_find`) {
|
||||
router.post(
|
||||
{
|
||||
path,
|
||||
validate: {
|
||||
body: querySchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(
|
||||
verifyAccessAndContext(licenseState, async function (context, req, res) {
|
||||
const rulesClient = (await context.alerting).getRulesClient();
|
||||
|
||||
trackLegacyTerminology(
|
||||
[req.body.search, req.body.search_fields, req.body.sort_field].filter(
|
||||
Boolean
|
||||
) as string[],
|
||||
usageCounter
|
||||
);
|
||||
|
||||
const options = rewriteQueryReq({
|
||||
...req.body,
|
||||
has_reference: req.body.has_reference || undefined,
|
||||
search_fields: searchFieldsAsArray(req.body.search_fields),
|
||||
});
|
||||
|
||||
if (req.body.fields) {
|
||||
usageCounter?.incrementCounter({
|
||||
counterName: `alertingFieldsUsage`,
|
||||
counterType: 'alertingFieldsUsage',
|
||||
incrementBy: 1,
|
||||
});
|
||||
}
|
||||
|
||||
const findResult = await rulesClient.find({
|
||||
options,
|
||||
excludeFromPublicApi,
|
||||
includeSnoozeData: true,
|
||||
});
|
||||
return res.ok({
|
||||
body: rewriteBodyRes(findResult),
|
||||
});
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const findRulesRoute = (
|
||||
|
|
|
@ -23,7 +23,7 @@ describe('loadRuleAggregations', () => {
|
|||
unknown: 0,
|
||||
},
|
||||
};
|
||||
http.get.mockResolvedValueOnce(resolvedValue);
|
||||
http.post.mockResolvedValueOnce(resolvedValue);
|
||||
|
||||
const result = await loadRuleAggregations({ http });
|
||||
expect(result).toEqual({
|
||||
|
@ -35,16 +35,11 @@ describe('loadRuleAggregations', () => {
|
|||
unknown: 0,
|
||||
},
|
||||
});
|
||||
expect(http.get.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
expect(http.post.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/internal/alerting/rules/_aggregate",
|
||||
Object {
|
||||
"query": Object {
|
||||
"default_search_operator": "AND",
|
||||
"filter": undefined,
|
||||
"search": undefined,
|
||||
"search_fields": undefined,
|
||||
},
|
||||
"body": "{\\"default_search_operator\\":\\"AND\\"}",
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
@ -60,7 +55,7 @@ describe('loadRuleAggregations', () => {
|
|||
unknown: 0,
|
||||
},
|
||||
};
|
||||
http.get.mockResolvedValueOnce(resolvedValue);
|
||||
http.post.mockResolvedValueOnce(resolvedValue);
|
||||
|
||||
const result = await loadRuleAggregations({ http, searchText: 'apples' });
|
||||
expect(result).toEqual({
|
||||
|
@ -72,16 +67,11 @@ describe('loadRuleAggregations', () => {
|
|||
unknown: 0,
|
||||
},
|
||||
});
|
||||
expect(http.get.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
expect(http.post.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/internal/alerting/rules/_aggregate",
|
||||
Object {
|
||||
"query": Object {
|
||||
"default_search_operator": "AND",
|
||||
"filter": undefined,
|
||||
"search": "apples",
|
||||
"search_fields": "[\\"name\\",\\"tags\\"]",
|
||||
},
|
||||
"body": "{\\"search_fields\\":\\"[\\\\\\"name\\\\\\",\\\\\\"tags\\\\\\"]\\",\\"search\\":\\"apples\\",\\"default_search_operator\\":\\"AND\\"}",
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
@ -97,7 +87,7 @@ describe('loadRuleAggregations', () => {
|
|||
unknown: 0,
|
||||
},
|
||||
};
|
||||
http.get.mockResolvedValueOnce(resolvedValue);
|
||||
http.post.mockResolvedValueOnce(resolvedValue);
|
||||
|
||||
const result = await loadRuleAggregations({
|
||||
http,
|
||||
|
@ -113,16 +103,11 @@ describe('loadRuleAggregations', () => {
|
|||
unknown: 0,
|
||||
},
|
||||
});
|
||||
expect(http.get.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
expect(http.post.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/internal/alerting/rules/_aggregate",
|
||||
Object {
|
||||
"query": Object {
|
||||
"default_search_operator": "AND",
|
||||
"filter": "(alert.attributes.actions:{ actionTypeId:action } OR alert.attributes.actions:{ actionTypeId:type })",
|
||||
"search": "foo",
|
||||
"search_fields": "[\\"name\\",\\"tags\\"]",
|
||||
},
|
||||
"body": "{\\"search_fields\\":\\"[\\\\\\"name\\\\\\",\\\\\\"tags\\\\\\"]\\",\\"search\\":\\"foo\\",\\"filter\\":\\"(alert.attributes.actions:{ actionTypeId:action } OR alert.attributes.actions:{ actionTypeId:type })\\",\\"default_search_operator\\":\\"AND\\"}",
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
@ -138,7 +123,7 @@ describe('loadRuleAggregations', () => {
|
|||
unknown: 0,
|
||||
},
|
||||
};
|
||||
http.get.mockResolvedValueOnce(resolvedValue);
|
||||
http.post.mockResolvedValueOnce(resolvedValue);
|
||||
|
||||
const result = await loadRuleAggregations({
|
||||
http,
|
||||
|
@ -153,16 +138,11 @@ describe('loadRuleAggregations', () => {
|
|||
unknown: 0,
|
||||
},
|
||||
});
|
||||
expect(http.get.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
expect(http.post.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/internal/alerting/rules/_aggregate",
|
||||
Object {
|
||||
"query": Object {
|
||||
"default_search_operator": "AND",
|
||||
"filter": "alert.attributes.alertTypeId:(foo or bar)",
|
||||
"search": undefined,
|
||||
"search_fields": undefined,
|
||||
},
|
||||
"body": "{\\"filter\\":\\"alert.attributes.alertTypeId:(foo or bar)\\",\\"default_search_operator\\":\\"AND\\"}",
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
@ -178,7 +158,7 @@ describe('loadRuleAggregations', () => {
|
|||
unknown: 0,
|
||||
},
|
||||
};
|
||||
http.get.mockResolvedValueOnce(resolvedValue);
|
||||
http.post.mockResolvedValueOnce(resolvedValue);
|
||||
|
||||
const result = await loadRuleAggregations({
|
||||
http,
|
||||
|
@ -195,16 +175,11 @@ describe('loadRuleAggregations', () => {
|
|||
unknown: 0,
|
||||
},
|
||||
});
|
||||
expect(http.get.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
expect(http.post.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/internal/alerting/rules/_aggregate",
|
||||
Object {
|
||||
"query": Object {
|
||||
"default_search_operator": "AND",
|
||||
"filter": "alert.attributes.alertTypeId:(foo or bar) and (alert.attributes.actions:{ actionTypeId:action } OR alert.attributes.actions:{ actionTypeId:type })",
|
||||
"search": "baz",
|
||||
"search_fields": "[\\"name\\",\\"tags\\"]",
|
||||
},
|
||||
"body": "{\\"search_fields\\":\\"[\\\\\\"name\\\\\\",\\\\\\"tags\\\\\\"]\\",\\"search\\":\\"baz\\",\\"filter\\":\\"alert.attributes.alertTypeId:(foo or bar) and (alert.attributes.actions:{ actionTypeId:action } OR alert.attributes.actions:{ actionTypeId:type })\\",\\"default_search_operator\\":\\"AND\\"}",
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
@ -220,7 +195,7 @@ describe('loadRuleAggregations', () => {
|
|||
unknown: 0,
|
||||
},
|
||||
};
|
||||
http.get.mockResolvedValue(resolvedValue);
|
||||
http.post.mockResolvedValue(resolvedValue);
|
||||
|
||||
let result = await loadRuleAggregations({
|
||||
http,
|
||||
|
@ -237,16 +212,11 @@ describe('loadRuleAggregations', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(http.get.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
expect(http.post.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/internal/alerting/rules/_aggregate",
|
||||
Object {
|
||||
"query": Object {
|
||||
"default_search_operator": "AND",
|
||||
"filter": "alert.attributes.enabled: true",
|
||||
"search": undefined,
|
||||
"search_fields": undefined,
|
||||
},
|
||||
"body": "{\\"filter\\":\\"alert.attributes.enabled: true\\",\\"default_search_operator\\":\\"AND\\"}",
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
@ -256,16 +226,11 @@ describe('loadRuleAggregations', () => {
|
|||
ruleStatusesFilter: ['enabled', 'snoozed'],
|
||||
});
|
||||
|
||||
expect(http.get.mock.calls[1]).toMatchInlineSnapshot(`
|
||||
expect(http.post.mock.calls[1]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/internal/alerting/rules/_aggregate",
|
||||
Object {
|
||||
"query": Object {
|
||||
"default_search_operator": "AND",
|
||||
"filter": "alert.attributes.enabled: true and (alert.attributes.muteAll:true OR alert.attributes.snoozeSchedule: { duration > 0 })",
|
||||
"search": undefined,
|
||||
"search_fields": undefined,
|
||||
},
|
||||
"body": "{\\"filter\\":\\"alert.attributes.enabled: true and (alert.attributes.muteAll:true OR alert.attributes.snoozeSchedule: { duration > 0 })\\",\\"default_search_operator\\":\\"AND\\"}",
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
@ -275,16 +240,11 @@ describe('loadRuleAggregations', () => {
|
|||
ruleStatusesFilter: ['enabled', 'disabled', 'snoozed'],
|
||||
});
|
||||
|
||||
expect(http.get.mock.calls[1]).toMatchInlineSnapshot(`
|
||||
expect(http.post.mock.calls[1]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/internal/alerting/rules/_aggregate",
|
||||
Object {
|
||||
"query": Object {
|
||||
"default_search_operator": "AND",
|
||||
"filter": "alert.attributes.enabled: true and (alert.attributes.muteAll:true OR alert.attributes.snoozeSchedule: { duration > 0 })",
|
||||
"search": undefined,
|
||||
"search_fields": undefined,
|
||||
},
|
||||
"body": "{\\"filter\\":\\"alert.attributes.enabled: true and (alert.attributes.muteAll:true OR alert.attributes.snoozeSchedule: { duration > 0 })\\",\\"default_search_operator\\":\\"AND\\"}",
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
@ -300,7 +260,7 @@ describe('loadRuleAggregations', () => {
|
|||
unknown: 0,
|
||||
},
|
||||
};
|
||||
http.get.mockResolvedValueOnce(resolvedValue);
|
||||
http.post.mockResolvedValueOnce(resolvedValue);
|
||||
|
||||
const result = await loadRuleAggregations({
|
||||
http,
|
||||
|
@ -318,16 +278,11 @@ describe('loadRuleAggregations', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(http.get.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
expect(http.post.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/internal/alerting/rules/_aggregate",
|
||||
Object {
|
||||
"query": Object {
|
||||
"default_search_operator": "AND",
|
||||
"filter": "alert.attributes.tags:(a or b or c)",
|
||||
"search": "baz",
|
||||
"search_fields": "[\\"name\\",\\"tags\\"]",
|
||||
},
|
||||
"body": "{\\"search_fields\\":\\"[\\\\\\"name\\\\\\",\\\\\\"tags\\\\\\"]\\",\\"search\\":\\"baz\\",\\"filter\\":\\"alert.attributes.tags:(a or b or c)\\",\\"default_search_operator\\":\\"AND\\"}",
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
|
|
@ -40,15 +40,15 @@ export async function loadRuleAggregations({
|
|||
ruleStatusesFilter,
|
||||
tagsFilter,
|
||||
});
|
||||
const res = await http.get<AsApiContract<RuleAggregations>>(
|
||||
const res = await http.post<AsApiContract<RuleAggregations>>(
|
||||
`${INTERNAL_BASE_ALERTING_API_PATH}/rules/_aggregate`,
|
||||
{
|
||||
query: {
|
||||
body: JSON.stringify({
|
||||
search_fields: searchText ? JSON.stringify(['name', 'tags']) : undefined,
|
||||
search: searchText,
|
||||
filter: filters.length ? filters.join(' and ') : undefined,
|
||||
default_search_operator: 'AND',
|
||||
},
|
||||
}),
|
||||
}
|
||||
);
|
||||
return rewriteBodyRes(res);
|
||||
|
|
|
@ -28,13 +28,13 @@ export async function loadRuleAggregationsWithKueryFilter({
|
|||
searchText,
|
||||
});
|
||||
|
||||
const res = await http.get<AsApiContract<RuleAggregations>>(
|
||||
const res = await http.post<AsApiContract<RuleAggregations>>(
|
||||
`${INTERNAL_BASE_ALERTING_API_PATH}/rules/_aggregate`,
|
||||
{
|
||||
query: {
|
||||
body: JSON.stringify({
|
||||
...(filtersKueryNode ? { filter: JSON.stringify(filtersKueryNode) } : {}),
|
||||
default_search_operator: 'AND',
|
||||
},
|
||||
}),
|
||||
}
|
||||
);
|
||||
return rewriteBodyRes(res);
|
||||
|
|
|
@ -38,7 +38,7 @@ export async function loadRulesWithKueryFilter({
|
|||
searchText,
|
||||
});
|
||||
|
||||
const res = await http.get<
|
||||
const res = await http.post<
|
||||
AsApiContract<{
|
||||
page: number;
|
||||
perPage: number;
|
||||
|
@ -46,14 +46,15 @@ export async function loadRulesWithKueryFilter({
|
|||
data: Array<AsApiContract<Rule>>;
|
||||
}>
|
||||
>(`${INTERNAL_BASE_ALERTING_API_PATH}/rules/_find`, {
|
||||
query: {
|
||||
body: JSON.stringify({
|
||||
page: page.index + 1,
|
||||
per_page: page.size,
|
||||
...(filtersKueryNode ? { filter: JSON.stringify(filtersKueryNode) } : {}),
|
||||
sort_field: sort.field,
|
||||
sort_order: sort.direction,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
return {
|
||||
page: res.page,
|
||||
perPage: res.per_page,
|
||||
|
|
|
@ -0,0 +1,576 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { SuperTest, Test } from 'supertest';
|
||||
import { chunk, omit } from 'lodash';
|
||||
import uuid from 'uuid';
|
||||
import { UserAtSpaceScenarios } from '../../../scenarios';
|
||||
import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib';
|
||||
import { FtrProviderContext } from '../../../../common/ftr_provider_context';
|
||||
|
||||
const findTestUtils = (
|
||||
describeType: 'internal' | 'public',
|
||||
objectRemover: ObjectRemover,
|
||||
supertest: SuperTest<Test>,
|
||||
supertestWithoutAuth: any
|
||||
) => {
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/148660
|
||||
describe.skip(describeType, () => {
|
||||
afterEach(() => objectRemover.removeAll());
|
||||
|
||||
for (const scenario of UserAtSpaceScenarios) {
|
||||
const { user, space } = scenario;
|
||||
describe(scenario.id, () => {
|
||||
it('should handle find alert request appropriately', async () => {
|
||||
const { body: createdAlert } = await supertest
|
||||
.post(`${getUrlPrefix(space.id)}/api/alerting/rule`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send(getTestRuleData())
|
||||
.expect(200);
|
||||
objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting');
|
||||
|
||||
const response = await supertestWithoutAuth
|
||||
.post(
|
||||
`${getUrlPrefix(space.id)}/${
|
||||
describeType === 'public' ? 'api' : 'internal'
|
||||
}/alerting/rules/_find`
|
||||
)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send({
|
||||
search: 'test.noop',
|
||||
search_fields: 'alertTypeId',
|
||||
});
|
||||
|
||||
switch (scenario.id) {
|
||||
case 'no_kibana_privileges at space1':
|
||||
case 'space_1_all at space2':
|
||||
expect(response.statusCode).to.eql(403);
|
||||
expect(response.body).to.eql({
|
||||
error: 'Forbidden',
|
||||
message: `Unauthorized to find rules for any rule types`,
|
||||
statusCode: 403,
|
||||
});
|
||||
break;
|
||||
case 'global_read at space1':
|
||||
case 'superuser at space1':
|
||||
case 'space_1_all at space1':
|
||||
case 'space_1_all_alerts_none_actions at space1':
|
||||
case 'space_1_all_with_restricted_fixture at space1':
|
||||
expect(response.statusCode).to.eql(200);
|
||||
expect(response.body.page).to.equal(1);
|
||||
expect(response.body.per_page).to.be.greaterThan(0);
|
||||
expect(response.body.total).to.be.greaterThan(0);
|
||||
const match = response.body.data.find((obj: any) => obj.id === createdAlert.id);
|
||||
const activeSnoozes = match.active_snoozes;
|
||||
const hasActiveSnoozes = !!(activeSnoozes || []).filter((obj: any) => obj).length;
|
||||
expect(match).to.eql({
|
||||
id: createdAlert.id,
|
||||
name: 'abc',
|
||||
tags: ['foo'],
|
||||
rule_type_id: 'test.noop',
|
||||
running: false,
|
||||
consumer: 'alertsFixture',
|
||||
schedule: { interval: '1m' },
|
||||
enabled: true,
|
||||
actions: [],
|
||||
params: {},
|
||||
created_by: 'elastic',
|
||||
scheduled_task_id: match.scheduled_task_id,
|
||||
created_at: match.created_at,
|
||||
updated_at: match.updated_at,
|
||||
throttle: '1m',
|
||||
notify_when: 'onThrottleInterval',
|
||||
updated_by: 'elastic',
|
||||
api_key_owner: 'elastic',
|
||||
mute_all: false,
|
||||
muted_alert_ids: [],
|
||||
execution_status: match.execution_status,
|
||||
...(match.next_run ? { next_run: match.next_run } : {}),
|
||||
...(match.last_run ? { last_run: match.last_run } : {}),
|
||||
...(describeType === 'internal'
|
||||
? {
|
||||
monitoring: match.monitoring,
|
||||
snooze_schedule: match.snooze_schedule,
|
||||
...(hasActiveSnoozes && { active_snoozes: activeSnoozes }),
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
expect(Date.parse(match.created_at)).to.be.greaterThan(0);
|
||||
expect(Date.parse(match.updated_at)).to.be.greaterThan(0);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`);
|
||||
}
|
||||
});
|
||||
|
||||
it('should filter out types that the user is not authorized to `get` retaining pagination', async () => {
|
||||
async function createNoOpAlert(overrides = {}) {
|
||||
const alert = getTestRuleData(overrides);
|
||||
const { body: createdAlert } = await supertest
|
||||
.post(`${getUrlPrefix(space.id)}/api/alerting/rule`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send(alert)
|
||||
.expect(200);
|
||||
objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting');
|
||||
return {
|
||||
id: createdAlert.id,
|
||||
rule_type_id: alert.rule_type_id,
|
||||
};
|
||||
}
|
||||
function createRestrictedNoOpAlert() {
|
||||
return createNoOpAlert({
|
||||
rule_type_id: 'test.restricted-noop',
|
||||
consumer: 'alertsRestrictedFixture',
|
||||
});
|
||||
}
|
||||
function createUnrestrictedNoOpAlert() {
|
||||
return createNoOpAlert({
|
||||
rule_type_id: 'test.unrestricted-noop',
|
||||
consumer: 'alertsFixture',
|
||||
});
|
||||
}
|
||||
const allAlerts = [];
|
||||
allAlerts.push(await createNoOpAlert());
|
||||
allAlerts.push(await createNoOpAlert());
|
||||
allAlerts.push(await createRestrictedNoOpAlert());
|
||||
allAlerts.push(await createUnrestrictedNoOpAlert());
|
||||
allAlerts.push(await createUnrestrictedNoOpAlert());
|
||||
allAlerts.push(await createRestrictedNoOpAlert());
|
||||
allAlerts.push(await createNoOpAlert());
|
||||
allAlerts.push(await createNoOpAlert());
|
||||
|
||||
const perPage = 4;
|
||||
|
||||
const response = await supertestWithoutAuth
|
||||
.post(
|
||||
`${getUrlPrefix(space.id)}/${
|
||||
describeType === 'public' ? 'api' : 'internal'
|
||||
}/alerting/rules/_find`
|
||||
)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send({
|
||||
per_page: perPage,
|
||||
sort_field: 'createdAt',
|
||||
});
|
||||
|
||||
switch (scenario.id) {
|
||||
case 'no_kibana_privileges at space1':
|
||||
case 'space_1_all at space2':
|
||||
expect(response.statusCode).to.eql(403);
|
||||
expect(response.body).to.eql({
|
||||
error: 'Forbidden',
|
||||
message: `Unauthorized to find rules for any rule types`,
|
||||
statusCode: 403,
|
||||
});
|
||||
break;
|
||||
case 'space_1_all at space1':
|
||||
case 'space_1_all_alerts_none_actions at space1':
|
||||
expect(response.statusCode).to.eql(200);
|
||||
expect(response.body.page).to.equal(1);
|
||||
expect(response.body.per_page).to.be.equal(perPage);
|
||||
expect(response.body.total).to.be.equal(6);
|
||||
{
|
||||
const [firstPage] = chunk(
|
||||
allAlerts
|
||||
.filter((alert) => alert.rule_type_id !== 'test.restricted-noop')
|
||||
.map((alert) => alert.id),
|
||||
perPage
|
||||
);
|
||||
expect(response.body.data.map((alert: any) => alert.id)).to.eql(firstPage);
|
||||
}
|
||||
break;
|
||||
case 'global_read at space1':
|
||||
case 'superuser at space1':
|
||||
case 'space_1_all_with_restricted_fixture at space1':
|
||||
expect(response.statusCode).to.eql(200);
|
||||
expect(response.body.page).to.equal(1);
|
||||
expect(response.body.per_page).to.be.equal(perPage);
|
||||
expect(response.body.total).to.be.equal(8);
|
||||
|
||||
{
|
||||
const [firstPage, secondPage] = chunk(
|
||||
allAlerts.map((alert) => alert.id),
|
||||
perPage
|
||||
);
|
||||
expect(response.body.data.map((alert: any) => alert.id)).to.eql(firstPage);
|
||||
|
||||
const secondResponse = await supertestWithoutAuth
|
||||
.get(
|
||||
`${getUrlPrefix(space.id)}/${
|
||||
describeType === 'public' ? 'api' : 'internal'
|
||||
}/alerting/rules/_find?per_page=${perPage}&sort_field=createdAt&page=2`
|
||||
)
|
||||
.auth(user.username, user.password);
|
||||
|
||||
expect(secondResponse.body.data.map((alert: any) => alert.id)).to.eql(secondPage);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`);
|
||||
}
|
||||
});
|
||||
|
||||
it('should handle find alert request with filter appropriately', async () => {
|
||||
const { body: createdAction } = await supertest
|
||||
.post(`${getUrlPrefix(space.id)}/api/actions/connector`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send({
|
||||
name: 'My action',
|
||||
connector_type_id: 'test.noop',
|
||||
config: {},
|
||||
secrets: {},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const { body: createdAlert } = await supertest
|
||||
.post(`${getUrlPrefix(space.id)}/api/alerting/rule`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send(
|
||||
getTestRuleData({
|
||||
enabled: false,
|
||||
actions: [
|
||||
{
|
||||
id: createdAction.id,
|
||||
group: 'default',
|
||||
params: {},
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
.expect(200);
|
||||
objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting');
|
||||
|
||||
const response = await supertestWithoutAuth
|
||||
.post(
|
||||
`${getUrlPrefix(space.id)}/${
|
||||
describeType === 'public' ? 'api' : 'internal'
|
||||
}/alerting/rules/_find`
|
||||
)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send({
|
||||
filter: 'alert.attributes.actions:{ actionTypeId: "test.noop" }',
|
||||
});
|
||||
|
||||
switch (scenario.id) {
|
||||
case 'no_kibana_privileges at space1':
|
||||
case 'space_1_all at space2':
|
||||
expect(response.statusCode).to.eql(403);
|
||||
expect(response.body).to.eql({
|
||||
error: 'Forbidden',
|
||||
message: `Unauthorized to find rules for any rule types`,
|
||||
statusCode: 403,
|
||||
});
|
||||
break;
|
||||
case 'global_read at space1':
|
||||
case 'superuser at space1':
|
||||
case 'space_1_all at space1':
|
||||
case 'space_1_all_alerts_none_actions at space1':
|
||||
case 'space_1_all_with_restricted_fixture at space1':
|
||||
expect(response.statusCode).to.eql(200);
|
||||
expect(response.body.page).to.equal(1);
|
||||
expect(response.body.per_page).to.be.greaterThan(0);
|
||||
expect(response.body.total).to.be.greaterThan(0);
|
||||
const match = response.body.data.find((obj: any) => obj.id === createdAlert.id);
|
||||
const activeSnoozes = match.active_snoozes;
|
||||
const hasActiveSnoozes = !!(activeSnoozes || []).filter((obj: any) => obj).length;
|
||||
expect(match).to.eql({
|
||||
id: createdAlert.id,
|
||||
name: 'abc',
|
||||
tags: ['foo'],
|
||||
rule_type_id: 'test.noop',
|
||||
running: false,
|
||||
consumer: 'alertsFixture',
|
||||
schedule: { interval: '1m' },
|
||||
enabled: false,
|
||||
actions: [
|
||||
{
|
||||
id: createdAction.id,
|
||||
group: 'default',
|
||||
connector_type_id: 'test.noop',
|
||||
params: {},
|
||||
},
|
||||
],
|
||||
params: {},
|
||||
created_by: 'elastic',
|
||||
throttle: '1m',
|
||||
updated_by: 'elastic',
|
||||
api_key_owner: null,
|
||||
mute_all: false,
|
||||
muted_alert_ids: [],
|
||||
notify_when: 'onThrottleInterval',
|
||||
created_at: match.created_at,
|
||||
updated_at: match.updated_at,
|
||||
execution_status: match.execution_status,
|
||||
...(match.next_run ? { next_run: match.next_run } : {}),
|
||||
...(match.last_run ? { last_run: match.last_run } : {}),
|
||||
...(describeType === 'internal'
|
||||
? {
|
||||
monitoring: match.monitoring,
|
||||
snooze_schedule: match.snooze_schedule,
|
||||
...(hasActiveSnoozes && { active_snoozes: activeSnoozes }),
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
expect(Date.parse(match.created_at)).to.be.greaterThan(0);
|
||||
expect(Date.parse(match.updated_at)).to.be.greaterThan(0);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`);
|
||||
}
|
||||
});
|
||||
|
||||
it('should handle find alert request with fields appropriately', async () => {
|
||||
const myTag = uuid.v4();
|
||||
const { body: createdAlert } = await supertest
|
||||
.post(`${getUrlPrefix(space.id)}/api/alerting/rule`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send(
|
||||
getTestRuleData({
|
||||
enabled: false,
|
||||
tags: [myTag],
|
||||
rule_type_id: 'test.restricted-noop',
|
||||
consumer: 'alertsRestrictedFixture',
|
||||
})
|
||||
)
|
||||
.expect(200);
|
||||
objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting');
|
||||
|
||||
// create another type with same tag
|
||||
const { body: createdSecondAlert } = await supertest
|
||||
.post(`${getUrlPrefix(space.id)}/api/alerting/rule`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send(
|
||||
getTestRuleData({
|
||||
tags: [myTag],
|
||||
rule_type_id: 'test.restricted-noop',
|
||||
consumer: 'alertsRestrictedFixture',
|
||||
})
|
||||
)
|
||||
.expect(200);
|
||||
objectRemover.add(space.id, createdSecondAlert.id, 'rule', 'alerting');
|
||||
|
||||
const response = await supertestWithoutAuth
|
||||
.post(
|
||||
`${getUrlPrefix(space.id)}/${
|
||||
describeType === 'public' ? 'api' : 'internal'
|
||||
}/alerting/rules/_find`
|
||||
)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send({
|
||||
filter: 'alert.attributes.alertTypeId: "test.restricted - noop"',
|
||||
fields: ['tags'],
|
||||
sort_field: 'createdAt',
|
||||
});
|
||||
|
||||
switch (scenario.id) {
|
||||
case 'no_kibana_privileges at space1':
|
||||
case 'space_1_all at space2':
|
||||
expect(response.statusCode).to.eql(403);
|
||||
expect(response.body).to.eql({
|
||||
error: 'Forbidden',
|
||||
message: `Unauthorized to find rules for any rule types`,
|
||||
statusCode: 403,
|
||||
});
|
||||
break;
|
||||
case 'space_1_all at space1':
|
||||
case 'space_1_all_alerts_none_actions at space1':
|
||||
expect(response.statusCode).to.eql(200);
|
||||
expect(response.body.data).to.eql([]);
|
||||
break;
|
||||
case 'global_read at space1':
|
||||
case 'superuser at space1':
|
||||
case 'space_1_all_with_restricted_fixture at space1':
|
||||
expect(response.statusCode).to.eql(200);
|
||||
expect(response.body.page).to.equal(1);
|
||||
expect(response.body.per_page).to.be.greaterThan(0);
|
||||
expect(response.body.total).to.be.greaterThan(0);
|
||||
const [matchFirst, matchSecond] = response.body.data;
|
||||
expect(omit(matchFirst, 'updatedAt')).to.eql({
|
||||
id: createdAlert.id,
|
||||
actions: [],
|
||||
tags: [myTag],
|
||||
...(describeType === 'internal' && {
|
||||
snooze_schedule: [],
|
||||
}),
|
||||
});
|
||||
expect(omit(matchSecond, 'updatedAt')).to.eql({
|
||||
id: createdSecondAlert.id,
|
||||
actions: [],
|
||||
tags: [myTag],
|
||||
...(describeType === 'internal' && {
|
||||
snooze_schedule: [],
|
||||
}),
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`);
|
||||
}
|
||||
});
|
||||
|
||||
it('should handle find alert request with executionStatus field appropriately', async () => {
|
||||
const myTag = uuid.v4();
|
||||
const { body: createdAlert } = await supertest
|
||||
.post(`${getUrlPrefix(space.id)}/api/alerting/rule`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send(
|
||||
getTestRuleData({
|
||||
enabled: false,
|
||||
tags: [myTag],
|
||||
rule_type_id: 'test.restricted-noop',
|
||||
consumer: 'alertsRestrictedFixture',
|
||||
})
|
||||
)
|
||||
.expect(200);
|
||||
objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting');
|
||||
|
||||
// create another type with same tag
|
||||
const { body: createdSecondAlert } = await supertest
|
||||
.post(`${getUrlPrefix(space.id)}/api/alerting/rule`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send(
|
||||
getTestRuleData({
|
||||
tags: [myTag],
|
||||
rule_type_id: 'test.restricted-noop',
|
||||
consumer: 'alertsRestrictedFixture',
|
||||
})
|
||||
)
|
||||
.expect(200);
|
||||
objectRemover.add(space.id, createdSecondAlert.id, 'rule', 'alerting');
|
||||
|
||||
const response = await supertestWithoutAuth
|
||||
.post(
|
||||
`${getUrlPrefix(space.id)}/${
|
||||
describeType === 'public' ? 'api' : 'internal'
|
||||
}/alerting/rules/_find`
|
||||
)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send({
|
||||
filter: 'alert.attributes.alertTypeId: "test.restricted - noop"',
|
||||
fields: ['tags', 'executionStatus'],
|
||||
sort_field: 'createdAt',
|
||||
});
|
||||
|
||||
switch (scenario.id) {
|
||||
case 'no_kibana_privileges at space1':
|
||||
case 'space_1_all at space2':
|
||||
expect(response.statusCode).to.eql(403);
|
||||
expect(response.body).to.eql({
|
||||
error: 'Forbidden',
|
||||
message: `Unauthorized to find rules for any rule types`,
|
||||
statusCode: 403,
|
||||
});
|
||||
break;
|
||||
case 'space_1_all at space1':
|
||||
case 'space_1_all_alerts_none_actions at space1':
|
||||
expect(response.statusCode).to.eql(200);
|
||||
expect(response.body.data).to.eql([]);
|
||||
break;
|
||||
case 'global_read at space1':
|
||||
case 'superuser at space1':
|
||||
case 'space_1_all_with_restricted_fixture at space1':
|
||||
expect(response.statusCode).to.eql(200);
|
||||
expect(response.body.page).to.equal(1);
|
||||
expect(response.body.per_page).to.be.greaterThan(0);
|
||||
expect(response.body.total).to.be.greaterThan(0);
|
||||
const [matchFirst, matchSecond] = response.body.data;
|
||||
expect(omit(matchFirst, 'updatedAt')).to.eql({
|
||||
id: createdAlert.id,
|
||||
actions: [],
|
||||
tags: [myTag],
|
||||
execution_status: matchFirst.execution_status,
|
||||
...(describeType === 'internal' && {
|
||||
snooze_schedule: [],
|
||||
}),
|
||||
});
|
||||
expect(omit(matchSecond, 'updatedAt')).to.eql({
|
||||
id: createdSecondAlert.id,
|
||||
actions: [],
|
||||
tags: [myTag],
|
||||
execution_status: matchSecond.execution_status,
|
||||
...(describeType === 'internal' && {
|
||||
snooze_schedule: [],
|
||||
}),
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`);
|
||||
}
|
||||
});
|
||||
|
||||
it(`shouldn't find alert from another space`, async () => {
|
||||
const { body: createdAlert } = await supertest
|
||||
.post(`${getUrlPrefix(space.id)}/api/alerting/rule`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send(getTestRuleData())
|
||||
.expect(200);
|
||||
objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting');
|
||||
|
||||
const response = await supertestWithoutAuth
|
||||
.post(
|
||||
`${getUrlPrefix(space.id)}/${
|
||||
describeType === 'public' ? 'api' : 'internal'
|
||||
}/alerting/rules/_find`
|
||||
)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send({
|
||||
search: 'test.noop',
|
||||
search_fields: 'alertTypeId',
|
||||
});
|
||||
|
||||
switch (scenario.id) {
|
||||
case 'no_kibana_privileges at space1':
|
||||
case 'space_1_all at space2':
|
||||
case 'space_1_all at space1':
|
||||
case 'space_1_all_alerts_none_actions at space1':
|
||||
case 'space_1_all_with_restricted_fixture at space1':
|
||||
expect(response.statusCode).to.eql(403);
|
||||
expect(response.body).to.eql({
|
||||
error: 'Forbidden',
|
||||
message: `Unauthorized to find rules for any rule types`,
|
||||
statusCode: 403,
|
||||
});
|
||||
break;
|
||||
case 'global_read at space1':
|
||||
case 'superuser at space1':
|
||||
expect(response.statusCode).to.eql(200);
|
||||
expect(response.body).to.eql({
|
||||
page: 1,
|
||||
per_page: 10,
|
||||
total: 0,
|
||||
data: [],
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function createFindTests({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const supertestWithoutAuth = getService('supertestWithoutAuth');
|
||||
|
||||
describe('find with post', () => {
|
||||
const objectRemover = new ObjectRemover(supertest);
|
||||
|
||||
afterEach(() => objectRemover.removeAll());
|
||||
|
||||
findTestUtils('internal', objectRemover, supertest, supertestWithoutAuth);
|
||||
});
|
||||
}
|
|
@ -21,6 +21,7 @@ export default function alertingTests({ loadTestFile, getService }: FtrProviderC
|
|||
});
|
||||
|
||||
loadTestFile(require.resolve('./find'));
|
||||
loadTestFile(require.resolve('./find_with_post'));
|
||||
loadTestFile(require.resolve('./create'));
|
||||
loadTestFile(require.resolve('./delete'));
|
||||
loadTestFile(require.resolve('./disable'));
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { Spaces } from '../../scenarios';
|
||||
import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../common/lib';
|
||||
import { FtrProviderContext } from '../../../common/ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function createAggregateTests({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
|
||||
describe('aggregate post', () => {
|
||||
const objectRemover = new ObjectRemover(supertest);
|
||||
|
||||
afterEach(() => objectRemover.removeAll());
|
||||
|
||||
it('should aggregate when there are no alerts', async () => {
|
||||
const response = await supertest
|
||||
.post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_aggregate`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send({});
|
||||
|
||||
expect(response.status).to.eql(200);
|
||||
expect(response.body).to.eql({
|
||||
rule_enabled_status: {
|
||||
disabled: 0,
|
||||
enabled: 0,
|
||||
},
|
||||
rule_execution_status: {
|
||||
ok: 0,
|
||||
active: 0,
|
||||
error: 0,
|
||||
pending: 0,
|
||||
unknown: 0,
|
||||
warning: 0,
|
||||
},
|
||||
rule_last_run_outcome: {
|
||||
succeeded: 0,
|
||||
warning: 0,
|
||||
failed: 0,
|
||||
},
|
||||
rule_muted_status: {
|
||||
muted: 0,
|
||||
unmuted: 0,
|
||||
},
|
||||
rule_snoozed_status: {
|
||||
snoozed: 0,
|
||||
},
|
||||
rule_tags: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('should aggregate alert status totals', async () => {
|
||||
const NumOkAlerts = 4;
|
||||
const NumActiveAlerts = 1;
|
||||
const NumErrorAlerts = 2;
|
||||
|
||||
await Promise.all(
|
||||
[...Array(NumOkAlerts)].map(async () => {
|
||||
const okAlertId = await createTestAlert(
|
||||
{
|
||||
rule_type_id: 'test.noop',
|
||||
schedule: { interval: '1s' },
|
||||
},
|
||||
'ok'
|
||||
);
|
||||
objectRemover.add(Spaces.space1.id, okAlertId, 'rule', 'alerting');
|
||||
})
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
[...Array(NumActiveAlerts)].map(async () => {
|
||||
const activeAlertId = await createTestAlert(
|
||||
{
|
||||
rule_type_id: 'test.patternFiring',
|
||||
schedule: { interval: '1s' },
|
||||
params: {
|
||||
pattern: { instance: new Array(100).fill(true) },
|
||||
},
|
||||
},
|
||||
'active'
|
||||
);
|
||||
objectRemover.add(Spaces.space1.id, activeAlertId, 'rule', 'alerting');
|
||||
})
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
[...Array(NumErrorAlerts)].map(async () => {
|
||||
const activeAlertId = await createTestAlert(
|
||||
{
|
||||
rule_type_id: 'test.throw',
|
||||
schedule: { interval: '1s' },
|
||||
},
|
||||
'error'
|
||||
);
|
||||
objectRemover.add(Spaces.space1.id, activeAlertId, 'rule', 'alerting');
|
||||
})
|
||||
);
|
||||
|
||||
// Adding delay to allow ES refresh cycle to run. Even when the waitForStatus
|
||||
// calls are successful, the call to aggregate may return stale totals if called
|
||||
// too early.
|
||||
await delay(1000);
|
||||
const response = await supertest
|
||||
.post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_aggregate`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send({});
|
||||
|
||||
expect(response.status).to.eql(200);
|
||||
expect(response.body).to.eql({
|
||||
rule_enabled_status: {
|
||||
disabled: 0,
|
||||
enabled: 7,
|
||||
},
|
||||
rule_execution_status: {
|
||||
ok: NumOkAlerts,
|
||||
active: NumActiveAlerts,
|
||||
error: NumErrorAlerts,
|
||||
pending: 0,
|
||||
unknown: 0,
|
||||
warning: 0,
|
||||
},
|
||||
rule_last_run_outcome: {
|
||||
succeeded: 5,
|
||||
warning: 0,
|
||||
failed: 2,
|
||||
},
|
||||
rule_muted_status: {
|
||||
muted: 0,
|
||||
unmuted: 7,
|
||||
},
|
||||
rule_snoozed_status: {
|
||||
snoozed: 0,
|
||||
},
|
||||
rule_tags: ['foo'],
|
||||
});
|
||||
});
|
||||
|
||||
describe('tags limit', () => {
|
||||
it('should be 50 be default', async () => {
|
||||
const numOfAlerts = 3;
|
||||
const numOfTagsPerAlert = 30;
|
||||
|
||||
await Promise.all(
|
||||
[...Array(numOfAlerts)].map(async (_, alertIndex) => {
|
||||
const okAlertId = await createTestAlert(
|
||||
{
|
||||
rule_type_id: 'test.noop',
|
||||
schedule: { interval: '1s' },
|
||||
tags: [...Array(numOfTagsPerAlert)].map(
|
||||
(__, i) => `tag-${i + numOfTagsPerAlert * alertIndex}`
|
||||
),
|
||||
},
|
||||
'ok'
|
||||
);
|
||||
objectRemover.add(Spaces.space1.id, okAlertId, 'rule', 'alerting');
|
||||
})
|
||||
);
|
||||
|
||||
const response = await supertest
|
||||
.post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_aggregate`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send({});
|
||||
|
||||
expect(response.body.rule_tags.length).to.eql(50);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const WaitForStatusIncrement = 500;
|
||||
|
||||
async function waitForStatus(
|
||||
id: string,
|
||||
statuses: Set<string>,
|
||||
waitMillis: number = 10000
|
||||
): Promise<Record<string, any>> {
|
||||
if (waitMillis < 0) {
|
||||
expect().fail(`waiting for alert ${id} statuses ${Array.from(statuses)} timed out`);
|
||||
}
|
||||
|
||||
const response = await supertest.get(
|
||||
`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${id}`
|
||||
);
|
||||
expect(response.status).to.eql(200);
|
||||
|
||||
const { execution_status: executionStatus } = response.body || {};
|
||||
const { status } = executionStatus || {};
|
||||
|
||||
const message = `waitForStatus(${Array.from(statuses)}): got ${JSON.stringify(
|
||||
executionStatus
|
||||
)}`;
|
||||
|
||||
if (statuses.has(status)) {
|
||||
return executionStatus;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`${message}, retrying`);
|
||||
|
||||
await delay(WaitForStatusIncrement);
|
||||
return await waitForStatus(id, statuses, waitMillis - WaitForStatusIncrement);
|
||||
}
|
||||
|
||||
async function delay(millis: number): Promise<void> {
|
||||
await new Promise((resolve) => setTimeout(resolve, millis));
|
||||
}
|
||||
|
||||
async function createTestAlert(testAlertOverrides = {}, status: string) {
|
||||
const { body: createdAlert } = await supertest
|
||||
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send(getTestRuleData(testAlertOverrides))
|
||||
.expect(200);
|
||||
|
||||
await waitForStatus(createdAlert.id, new Set([status]));
|
||||
return createdAlert.id;
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ export default function alertingTests({ loadTestFile, getService }: FtrProviderC
|
|||
after(async () => await tearDown(getService));
|
||||
|
||||
loadTestFile(require.resolve('./aggregate'));
|
||||
loadTestFile(require.resolve('./aggregate_post'));
|
||||
loadTestFile(require.resolve('./create'));
|
||||
loadTestFile(require.resolve('./delete'));
|
||||
loadTestFile(require.resolve('./disable'));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue