diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/index.ts index 3a4cc62c2550f..531046013263f 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/index.ts @@ -35,6 +35,7 @@ export default function alertingTests({ loadTestFile, getService }: FtrProviderC loadTestFile(require.resolve('./alerts_space1')); loadTestFile(require.resolve('./alerts_default_space')); loadTestFile(require.resolve('./builtin_alert_types')); + loadTestFile(require.resolve('./transform_rule_types')); loadTestFile(require.resolve('./mustache_templates.ts')); loadTestFile(require.resolve('./notify_when')); loadTestFile(require.resolve('./ephemeral')); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/index.ts new file mode 100644 index 0000000000000..072e318da2df9 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/index.ts @@ -0,0 +1,16 @@ +/* + * 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 { FtrProviderContext } from '../../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function alertingTests({ loadTestFile }: FtrProviderContext) { + describe('transform alert rule types', function () { + this.tags('dima'); + loadTestFile(require.resolve('./transform_health')); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/transform_health/alert.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/transform_health/alert.ts new file mode 100644 index 0000000000000..c5fb4ec61aa4f --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/transform_health/alert.ts @@ -0,0 +1,206 @@ +/* + * 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 { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { + ES_TEST_INDEX_NAME, + ESTestIndexTool, + getUrlPrefix, + ObjectRemover, +} from '../../../../../common/lib'; +import { Spaces } from '../../../../scenarios'; +import { PutTransformsRequestSchema } from '../../../../../../../plugins/transform/common/api_schemas/transforms'; + +const ACTION_TYPE_ID = '.index'; +const ALERT_TYPE_ID = 'transform_health'; +const ES_TEST_INDEX_SOURCE = 'transform-alert:transform-health'; +const ES_TEST_INDEX_REFERENCE = '-na-'; +const ES_TEST_OUTPUT_INDEX_NAME = `${ES_TEST_INDEX_NAME}-ts-output`; + +const ALERT_INTERVAL_SECONDS = 3; + +interface CreateAlertParams { + name: string; + includeTransforms: string[]; + excludeTransforms?: string[] | null; + testsConfig?: { + notStarted?: { + enabled: boolean; + } | null; + } | null; +} + +export function generateDestIndex(transformId: string): string { + return `user-${transformId}`; +} + +export function generateTransformConfig(transformId: string): PutTransformsRequestSchema { + const destinationIndex = generateDestIndex(transformId); + + return { + source: { index: ['ft_farequote'] }, + pivot: { + group_by: { airline: { terms: { field: 'airline' } } }, + aggregations: { '@timestamp.value_count': { value_count: { field: '@timestamp' } } }, + }, + dest: { index: destinationIndex }, + sync: { + time: { field: '@timestamp' }, + }, + }; +} + +// eslint-disable-next-line import/no-default-export +export default function alertTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + const retry = getService('retry'); + const es = getService('es'); + const log = getService('log'); + const transform = getService('transform'); + + const esTestIndexTool = new ESTestIndexTool(es, retry); + const esTestIndexToolOutput = new ESTestIndexTool(es, retry, ES_TEST_OUTPUT_INDEX_NAME); + + describe('alert', async () => { + const objectRemover = new ObjectRemover(supertest); + let actionId: string; + const transformId = 'test_transform_01'; + const destinationIndex = generateDestIndex(transformId); + + beforeEach(async () => { + await esTestIndexTool.destroy(); + await esTestIndexTool.setup(); + + await esTestIndexToolOutput.destroy(); + await esTestIndexToolOutput.setup(); + + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/farequote'); + await transform.testResources.setKibanaTimeZoneToUTC(); + + actionId = await createAction(); + + await transform.api.createIndices(destinationIndex); + await createTransform(transformId); + }); + + afterEach(async () => { + await objectRemover.removeAll(); + await esTestIndexTool.destroy(); + await esTestIndexToolOutput.destroy(); + await transform.api.cleanTransformIndices(); + }); + + it('runs correctly', async () => { + await createAlert({ + name: 'Test all transforms', + includeTransforms: ['*'], + }); + + await stopTransform(transformId); + + log.debug('Checking created alert instances...'); + + const docs = await waitForDocs(1); + for (const doc of docs) { + const { name, message } = doc._source.params; + + expect(name).to.be('Test all transforms'); + expect(message).to.be('Transform test_transform_01 is not started.'); + } + }); + + async function waitForDocs(count: number): Promise { + return await esTestIndexToolOutput.waitForDocs( + ES_TEST_INDEX_SOURCE, + ES_TEST_INDEX_REFERENCE, + count + ); + } + + async function createTransform(id: string) { + const config = generateTransformConfig(id); + await transform.api.createAndRunTransform(id, config); + } + + async function createAlert(params: CreateAlertParams): Promise { + log.debug(`Creating an alerting rule "${params.name}"...`); + const action = { + id: actionId, + group: 'transform_issue', + params: { + documents: [ + { + source: ES_TEST_INDEX_SOURCE, + reference: ES_TEST_INDEX_REFERENCE, + params: { + name: '{{{alertName}}}', + message: '{{{context.message}}}', + }, + }, + ], + }, + }; + + const { status, body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send({ + name: params.name, + consumer: 'alerts', + enabled: true, + rule_type_id: ALERT_TYPE_ID, + schedule: { interval: `${ALERT_INTERVAL_SECONDS}s` }, + actions: [action], + notify_when: 'onActiveAlert', + params: { + includeTransforms: params.includeTransforms, + }, + }); + + // will print the error body, if an error occurred + // if (statusCode !== 200) console.log(createdAlert); + + expect(status).to.be(200); + + const alertId = createdAlert.id; + objectRemover.add(Spaces.space1.id, alertId, 'rule', 'alerting'); + + return alertId; + } + + async function stopTransform(id: string) { + await transform.api.stopTransform(id); + } + + async function createAction(): Promise { + log.debug('Creating an action...'); + // @ts-ignore + const { statusCode, body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'index action for transform health FT', + connector_type_id: ACTION_TYPE_ID, + config: { + index: ES_TEST_OUTPUT_INDEX_NAME, + }, + secrets: {}, + }); + + expect(statusCode).to.be(200); + + log.debug(`Action with id "${createdAction.id}" has been created.`); + + const resultId = createdAction.id; + objectRemover.add(Spaces.space1.id, resultId, 'connector', 'actions'); + + return resultId; + } + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/transform_health/index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/transform_health/index.ts new file mode 100644 index 0000000000000..c324745b85813 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/transform_health/index.ts @@ -0,0 +1,15 @@ +/* + * 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 { FtrProviderContext } from '../../../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function alertingTests({ loadTestFile }: FtrProviderContext) { + describe('transform_health', function () { + loadTestFile(require.resolve('./alert')); + }); +} diff --git a/x-pack/test/functional/services/transform/api.ts b/x-pack/test/functional/services/transform/api.ts index 484d794aac879..73dff415832f6 100644 --- a/x-pack/test/functional/services/transform/api.ts +++ b/x-pack/test/functional/services/transform/api.ts @@ -234,6 +234,11 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { await esSupertest.post(`/_transform/${transformId}/_start`).expect(200); }, + async stopTransform(transformId: string) { + log.debug(`Stopping transform '${transformId}' ...`); + await esSupertest.post(`/_transform/${transformId}/_stop`).expect(200); + }, + async createAndRunTransform(transformId: string, transformConfig: PutTransformsRequestSchema) { await this.createTransform(transformId, transformConfig); await this.startTransform(transformId);