diff --git a/x-pack/test_serverless/api_integration/services/alerting_api.ts b/x-pack/test_serverless/api_integration/services/alerting_api.ts new file mode 100644 index 0000000000000..33d8b224561cc --- /dev/null +++ b/x-pack/test_serverless/api_integration/services/alerting_api.ts @@ -0,0 +1,90 @@ +/* + * 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 type { + AggregationsAggregate, + SearchResponse, +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import { FtrProviderContext } from '../ftr_provider_context'; + +export function AlertingApiProvider({ getService }: FtrProviderContext) { + const retry = getService('retry'); + const supertest = getService('supertest'); + const es = getService('es'); + const requestTimeout = 30 * 1000; + const retryTimeout = 120 * 1000; + + return { + async waitForRuleStatus({ + ruleId, + expectedStatus, + }: { + ruleId: string; + expectedStatus: string; + }) { + if (!ruleId) { + throw new Error(`'ruleId' is undefined`); + } + return await retry.tryForTime(retryTimeout, async () => { + const response = await supertest + .get(`/api/alerting/rule/${ruleId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .timeout(requestTimeout); + const { execution_status: executionStatus } = response.body || {}; + const { status } = executionStatus || {}; + if (status !== expectedStatus) { + throw new Error(`waitForStatus(${expectedStatus}): got ${status}`); + } + return executionStatus?.status; + }); + }, + + async waitForDocumentInIndex({ + indexName, + }: { + indexName: string; + }): Promise>> { + return await retry.tryForTime(retryTimeout, async () => { + const response = await es.search({ index: indexName }); + if (response.hits.hits.length === 0) { + throw new Error('No hits found'); + } + return response; + }); + }, + + async waitForAlertInIndex({ + indexName, + ruleId, + }: { + indexName: string; + ruleId: string; + }): Promise>> { + if (!ruleId) { + throw new Error(`'ruleId' is undefined`); + } + return await retry.tryForTime(retryTimeout, async () => { + const response = await es.search({ + index: indexName, + body: { + query: { + term: { + 'kibana.alert.rule.uuid': ruleId, + }, + }, + }, + }); + if (response.hits.hits.length === 0) { + throw new Error('No hits found'); + } + return response; + }); + }, + }; +} diff --git a/x-pack/test_serverless/api_integration/services/index.ts b/x-pack/test_serverless/api_integration/services/index.ts index 7c66bc38a24f7..bab7b001b5982 100644 --- a/x-pack/test_serverless/api_integration/services/index.ts +++ b/x-pack/test_serverless/api_integration/services/index.ts @@ -11,12 +11,14 @@ import { services as xpackApiIntegrationServices } from '../../../test/api_integ import { services as svlSharedServices } from '../../shared/services'; import { SvlCommonApiServiceProvider } from './svl_common_api'; +import { AlertingApiProvider } from './alerting_api'; export const services = { ...xpackApiIntegrationServices, ...svlSharedServices, svlCommonApi: SvlCommonApiServiceProvider, + alertingApi: AlertingApiProvider, }; export type InheritedFtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/avg_pct_fired.ts b/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/avg_pct_fired.ts index e03f1f05ad287..eaf12f3c69e5f 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/avg_pct_fired.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/avg_pct_fired.ts @@ -13,12 +13,12 @@ import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/observability-plugin/ import { FtrProviderContext } from '../../../ftr_provider_context'; import { createIndexConnector, createRule } from '../helpers/alerting_api_helper'; import { createDataView, deleteDataView } from '../helpers/data_view'; -import { waitForAlertInIndex, waitForRuleStatus } from '../helpers/alerting_wait_for_helpers'; export default function ({ getService }: FtrProviderContext) { const esClient = getService('es'); const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); + const alertingApi = getService('alertingApi'); const logger = getService('log'); describe('Threshold rule - AVG - PCT - FIRED', () => { @@ -125,17 +125,15 @@ export default function ({ getService }: FtrProviderContext) { }); it('should be active', async () => { - const executionStatus = await waitForRuleStatus({ - id: ruleId, + const executionStatus = await alertingApi.waitForRuleStatus({ + ruleId, expectedStatus: 'active', - supertest, }); - expect(executionStatus.status).to.be('active'); + expect(executionStatus).to.be('active'); }); it('should set correct information in the alert document', async () => { - const resp = await waitForAlertInIndex({ - esClient, + const resp = await alertingApi.waitForAlertInIndex({ indexName: THRESHOLD_RULE_ALERT_INDEX, ruleId, }); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/avg_pct_no_data.ts b/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/avg_pct_no_data.ts index 7ed52de44810e..c101af3bc9aa8 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/avg_pct_no_data.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/avg_pct_no_data.ts @@ -12,11 +12,11 @@ import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/observability-plugin/ import { FtrProviderContext } from '../../../ftr_provider_context'; import { createIndexConnector, createRule } from '../helpers/alerting_api_helper'; import { createDataView, deleteDataView } from '../helpers/data_view'; -import { waitForAlertInIndex, waitForRuleStatus } from '../helpers/alerting_wait_for_helpers'; export default function ({ getService }: FtrProviderContext) { const esClient = getService('es'); const supertest = getService('supertest'); + const alertingApi = getService('alertingApi'); describe('Threshold rule - AVG - PCT - NoData', () => { const THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default'; @@ -118,17 +118,15 @@ export default function ({ getService }: FtrProviderContext) { }); it('should be active', async () => { - const executionStatus = await waitForRuleStatus({ - id: ruleId, + const executionStatus = await alertingApi.waitForRuleStatus({ + ruleId, expectedStatus: 'active', - supertest, }); - expect(executionStatus.status).to.be('active'); + expect(executionStatus).to.be('active'); }); it('should set correct information in the alert document', async () => { - const resp = await waitForAlertInIndex({ - esClient, + const resp = await alertingApi.waitForAlertInIndex({ indexName: THRESHOLD_RULE_ALERT_INDEX, ruleId, }); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/custom_eq_avg_bytes_fired.ts b/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/custom_eq_avg_bytes_fired.ts index faa9604e762cb..a963245651d7a 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/custom_eq_avg_bytes_fired.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/custom_eq_avg_bytes_fired.ts @@ -19,13 +19,13 @@ import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/observability-plugin/ import { FtrProviderContext } from '../../../ftr_provider_context'; import { createIndexConnector, createRule } from '../helpers/alerting_api_helper'; import { createDataView, deleteDataView } from '../helpers/data_view'; -import { waitForAlertInIndex, waitForRuleStatus } from '../helpers/alerting_wait_for_helpers'; export default function ({ getService }: FtrProviderContext) { const esClient = getService('es'); const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); const logger = getService('log'); + const alertingApi = getService('alertingApi'); describe('Threshold rule - CUSTOM_EQ - AVG - BYTES - FIRED', () => { const THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default'; @@ -133,17 +133,15 @@ export default function ({ getService }: FtrProviderContext) { }); it('should be active', async () => { - const executionStatus = await waitForRuleStatus({ - id: ruleId, + const executionStatus = await alertingApi.waitForRuleStatus({ + ruleId, expectedStatus: 'active', - supertest, }); - expect(executionStatus.status).to.be('active'); + expect(executionStatus).to.be('active'); }); it('should set correct information in the alert document', async () => { - const resp = await waitForAlertInIndex({ - esClient, + const resp = await alertingApi.waitForAlertInIndex({ indexName: THRESHOLD_RULE_ALERT_INDEX, ruleId, }); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/documents_count_fired.ts b/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/documents_count_fired.ts index 27c5bc17c7cfc..eacdf7b34fa4f 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/documents_count_fired.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/documents_count_fired.ts @@ -13,13 +13,13 @@ import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/observability-plugin/ import { FtrProviderContext } from '../../../ftr_provider_context'; import { createIndexConnector, createRule } from '../helpers/alerting_api_helper'; import { createDataView, deleteDataView } from '../helpers/data_view'; -import { waitForAlertInIndex, waitForRuleStatus } from '../helpers/alerting_wait_for_helpers'; export default function ({ getService }: FtrProviderContext) { const esClient = getService('es'); const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); const logger = getService('log'); + const alertingApi = getService('alertingApi'); describe('Threshold rule - DOCUMENTS_COUNT - FIRED', () => { const THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default'; @@ -123,17 +123,15 @@ export default function ({ getService }: FtrProviderContext) { }); it('should be active', async () => { - const executionStatus = await waitForRuleStatus({ - id: ruleId, + const executionStatus = await alertingApi.waitForRuleStatus({ + ruleId, expectedStatus: 'active', - supertest, }); - expect(executionStatus.status).to.be('active'); + expect(executionStatus).to.be('active'); }); it('should set correct information in the alert document', async () => { - const resp = await waitForAlertInIndex({ - esClient, + const resp = await alertingApi.waitForAlertInIndex({ indexName: THRESHOLD_RULE_ALERT_INDEX, ruleId, }); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/group_by_fired.ts b/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/group_by_fired.ts index 29d2e64a41874..a78a008f93e61 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/group_by_fired.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/threshold_rule/group_by_fired.ts @@ -20,17 +20,13 @@ import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/observability-plugin/ import { FtrProviderContext } from '../../../ftr_provider_context'; import { createIndexConnector, createRule } from '../helpers/alerting_api_helper'; import { createDataView, deleteDataView } from '../helpers/data_view'; -import { - waitForAlertInIndex, - waitForDocumentInIndex, - waitForRuleStatus, -} from '../helpers/alerting_wait_for_helpers'; export default function ({ getService }: FtrProviderContext) { const esClient = getService('es'); const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); const logger = getService('log'); + const alertingApi = getService('alertingApi'); let alertId: string; let startedAt: string; @@ -143,17 +139,15 @@ export default function ({ getService }: FtrProviderContext) { }); it('should be active', async () => { - const executionStatus = await waitForRuleStatus({ - id: ruleId, + const executionStatus = await alertingApi.waitForRuleStatus({ + ruleId, expectedStatus: 'active', - supertest, }); - expect(executionStatus.status).to.be('active'); + expect(executionStatus).to.be('active'); }); it('should set correct information in the alert document', async () => { - const resp = await waitForAlertInIndex({ - esClient, + const resp = await alertingApi.waitForAlertInIndex({ indexName: THRESHOLD_RULE_ALERT_INDEX, ruleId, }); @@ -214,14 +208,13 @@ export default function ({ getService }: FtrProviderContext) { it('should set correct action variables', async () => { const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString(); - const resp = await waitForDocumentInIndex<{ + const resp = await alertingApi.waitForDocumentInIndex<{ ruleType: string; alertDetailsUrl: string; reason: string; value: string; host: string; }>({ - esClient, indexName: ALERT_ACTION_INDEX, });