diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.test.ts index d0f1a39f7cede..f6b3d23c2e289 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.test.ts @@ -37,7 +37,28 @@ describe('getMutedAlerts', () => { Array [ "/internal/alerting/rules/_find", Object { - "body": "{\\"rule_type_ids\\":[\\"foo\\"],\\"fields\\":[\\"id\\",\\"mutedInstanceIds\\"],\\"page\\":1,\\"per_page\\":1}", + "body": "{\\"filter\\":\\"{\\\\\\"type\\\\\\":\\\\\\"function\\\\\\",\\\\\\"function\\\\\\":\\\\\\"is\\\\\\",\\\\\\"arguments\\\\\\":[{\\\\\\"type\\\\\\":\\\\\\"literal\\\\\\",\\\\\\"value\\\\\\":\\\\\\"alert.id\\\\\\",\\\\\\"isQuoted\\\\\\":false},{\\\\\\"type\\\\\\":\\\\\\"literal\\\\\\",\\\\\\"value\\\\\\":\\\\\\"alert:foo\\\\\\",\\\\\\"isQuoted\\\\\\":false}]}\\",\\"fields\\":[\\"id\\",\\"mutedInstanceIds\\"],\\"page\\":1,\\"per_page\\":1}", + "signal": undefined, + }, + ] + `); + }); + + test('should call find API with multiple ruleIds', async () => { + const result = await getMutedAlerts(http, { ruleIds: ['foo', 'bar'] }); + + expect(result).toEqual({ + page: 1, + per_page: 10, + total: 0, + data: [], + }); + + expect(http.post.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_find", + Object { + "body": "{\\"filter\\":\\"{\\\\\\"type\\\\\\":\\\\\\"function\\\\\\",\\\\\\"function\\\\\\":\\\\\\"or\\\\\\",\\\\\\"arguments\\\\\\":[{\\\\\\"type\\\\\\":\\\\\\"function\\\\\\",\\\\\\"function\\\\\\":\\\\\\"is\\\\\\",\\\\\\"arguments\\\\\\":[{\\\\\\"type\\\\\\":\\\\\\"literal\\\\\\",\\\\\\"value\\\\\\":\\\\\\"alert.id\\\\\\",\\\\\\"isQuoted\\\\\\":false},{\\\\\\"type\\\\\\":\\\\\\"literal\\\\\\",\\\\\\"value\\\\\\":\\\\\\"alert:foo\\\\\\",\\\\\\"isQuoted\\\\\\":false}]},{\\\\\\"type\\\\\\":\\\\\\"function\\\\\\",\\\\\\"function\\\\\\":\\\\\\"is\\\\\\",\\\\\\"arguments\\\\\\":[{\\\\\\"type\\\\\\":\\\\\\"literal\\\\\\",\\\\\\"value\\\\\\":\\\\\\"alert.id\\\\\\",\\\\\\"isQuoted\\\\\\":false},{\\\\\\"type\\\\\\":\\\\\\"literal\\\\\\",\\\\\\"value\\\\\\":\\\\\\"alert:bar\\\\\\",\\\\\\"isQuoted\\\\\\":false}]}]}\\",\\"fields\\":[\\"id\\",\\"mutedInstanceIds\\"],\\"page\\":1,\\"per_page\\":2}", "signal": undefined, }, ] diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.ts index d9baef548dafc..4c13c0c7b5ef6 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.ts @@ -6,6 +6,7 @@ */ import { HttpStart } from '@kbn/core-http-browser'; +import { nodeBuilder } from '@kbn/es-query'; const INTERNAL_FIND_RULES_URL = '/internal/alerting/rules/_find'; @@ -23,9 +24,12 @@ export const getMutedAlerts = async ( params: { ruleIds: string[] }, signal?: AbortSignal ) => { + const filterNode = nodeBuilder.or( + params.ruleIds.map((id) => nodeBuilder.is('alert.id', `alert:${id}`)) + ); return http.post(INTERNAL_FIND_RULES_URL, { body: JSON.stringify({ - rule_type_ids: params.ruleIds, + filter: JSON.stringify(filterNode), fields: ['id', 'mutedInstanceIds'], page: 1, per_page: params.ruleIds.length, diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/index.ts index 1da03fbbcc54c..b2753cb17245d 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/index.ts @@ -18,6 +18,7 @@ export default function alertingTests({ loadTestFile, getService }: FtrProviderC loadTestFile(require.resolve('./builtin_alert_types')); loadTestFile(require.resolve('./mustache_templates.ts')); loadTestFile(require.resolve('./notify_when')); + loadTestFile(require.resolve('./muted_alerts')); loadTestFile(require.resolve('./event_log_alerts')); loadTestFile(require.resolve('./snooze')); loadTestFile(require.resolve('./unsnooze')); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/muted_alerts.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/muted_alerts.ts new file mode 100644 index 0000000000000..475a36872e8c7 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/muted_alerts.ts @@ -0,0 +1,122 @@ +/* + * 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 { ES_TEST_INDEX_NAME } from '@kbn/alerting-api-integration-helpers'; +import { ALERT_INSTANCE_ID, ALERT_RULE_UUID, ALERT_STATUS } from '@kbn/rule-data-utils'; +import { nodeBuilder } from '@kbn/es-query'; +import { Spaces } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; + +const alertAsDataIndex = '.internal.alerts-observability.test.alerts.alerts-default-000001'; + +// eslint-disable-next-line import/no-default-export +export default function createDisableRuleTests({ getService }: FtrProviderContext) { + const es = getService('es'); + const retry = getService('retry'); + const supertest = getService('supertest'); + + describe('mutedAlerts', () => { + const objectRemover = new ObjectRemover(supertest); + + const createRule = async () => { + const { body: createdRule } = await supertest + .post(`${getUrlPrefix(Spaces.space1.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', + }, + }) + ) + .expect(200); + + objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting'); + return createdRule.id; + }; + + const getAlerts = async () => { + const { + hits: { hits: alerts }, + } = await es.search({ + index: alertAsDataIndex, + body: { query: { match_all: {} } }, + }); + + return alerts; + }; + + afterEach(async () => { + await es.deleteByQuery({ + index: alertAsDataIndex, + query: { + match_all: {}, + }, + conflicts: 'proceed', + ignore_unavailable: true, + }); + await objectRemover.removeAll(); + }); + + it('should reflect muted alert instance ids in rule', async () => { + const createdRule1 = await createRule(); + const createdRule2 = await createRule(); + + let alerts: any[] = []; + + await retry.try(async () => { + alerts = await getAlerts(); + + expect(alerts.length).greaterThan(2); + alerts.forEach((activeAlert: any) => { + expect(activeAlert._source[ALERT_STATUS]).eql('active'); + }); + }); + + const alertFromRule1 = alerts.find( + (alert: any) => + alert._source[ALERT_STATUS] === 'active' && + alert._source[ALERT_RULE_UUID] === createdRule1 + ); + + await supertest + .post( + `${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${encodeURIComponent( + createdRule1 + )}/alert/${encodeURIComponent(alertFromRule1._source['kibana.alert.instance.id'])}/_mute` + ) + .set('kbn-xsrf', 'foo') + .expect(204); + + const ruleUuids = [createdRule1, createdRule2]; + + const filterNode = nodeBuilder.or( + ruleUuids.map((id) => nodeBuilder.is('alert.id', `alert:${id}`)) + ); + const { body: rules } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ + filter: JSON.stringify(filterNode), + fields: ['id', 'mutedInstanceIds'], + page: 1, + per_page: ruleUuids.length, + }); + + expect(rules.data.length).to.be(2); + const mutedRule = rules.data.find((rule: { id: string }) => rule.id === createdRule1); + expect(mutedRule.muted_alert_ids).to.contain(alertFromRule1._source[ALERT_INSTANCE_ID]); + }); + }); +}