From 4540c5591664d77b330a7588d7c33d1e7dc55476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?= Date: Wed, 21 Aug 2019 15:57:23 -0400 Subject: [PATCH] Add spaces only tests for alerting and actions (#43616) (#43702) * Add spaces only tests * Rename some tests to make more sense in spaces only context * Modify test suite titles * Apply changes from master * Loop only one scenario for now * Reduce amount of tests spaces_only runs * Fix failing test * Remove looping in spaces only tests --- x-pack/scripts/functional_tests.js | 1 + .../security_and_spaces/tests/index.ts | 2 +- .../spaces_only/config.ts | 10 + .../spaces_only/scenarios.ts | 17 + .../actions/builtin_action_types/es_index.ts | 133 ++++++++ .../spaces_only/tests/actions/create.ts | 49 +++ .../spaces_only/tests/actions/delete.ts | 53 +++ .../spaces_only/tests/actions/execute.ts | 175 ++++++++++ .../spaces_only/tests/actions/find.ts | 60 ++++ .../spaces_only/tests/actions/get.ts | 49 +++ .../spaces_only/tests/actions/index.ts | 21 ++ .../tests/actions/list_action_types.ts | 34 ++ .../spaces_only/tests/actions/update.ts | 59 ++++ .../spaces_only/tests/alerting/alerts.ts | 309 ++++++++++++++++++ .../spaces_only/tests/alerting/create.ts | 70 ++++ .../spaces_only/tests/alerting/delete.ts | 50 +++ .../spaces_only/tests/alerting/disable.ts | 51 +++ .../spaces_only/tests/alerting/enable.ts | 57 ++++ .../spaces_only/tests/alerting/find.ts | 54 +++ .../spaces_only/tests/alerting/get.ts | 56 ++++ .../spaces_only/tests/alerting/index.ts | 22 ++ .../tests/alerting/list_alert_types.ts | 28 ++ .../spaces_only/tests/alerting/update.ts | 47 +++ .../spaces_only/tests/alerting/utils.ts | 55 ++++ .../spaces_only/tests/index.ts | 33 ++ 25 files changed, 1494 insertions(+), 1 deletion(-) create mode 100644 x-pack/test/alerting_api_integration/spaces_only/config.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/scenarios.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/actions/create.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/actions/delete.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/actions/find.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/actions/get.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/actions/index.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/actions/list_action_types.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/actions/update.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/alerting/find.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/alerting/index.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/alerting/update.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/alerting/utils.ts create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/index.ts diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js index 002701269e3ed..222647e000672 100644 --- a/x-pack/scripts/functional_tests.js +++ b/x-pack/scripts/functional_tests.js @@ -12,6 +12,7 @@ require('@kbn/test').runTestsCli([ require.resolve('../test/functional/config.js'), require.resolve('../test/api_integration/config_security_basic.js'), require.resolve('../test/api_integration/config.js'), + require.resolve('../test/alerting_api_integration/spaces_only/config.ts'), require.resolve('../test/alerting_api_integration/security_and_spaces/config.ts'), require.resolve('../test/plugin_api_integration/config.js'), require.resolve('../test/kerberos_api_integration/config'), diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/index.ts index 7b7be170d9ff4..4c2dc3cbdf11f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/index.ts @@ -18,7 +18,7 @@ export default function alertingApiIntegrationTests({ const spacesService: SpacesService = getService('spaces'); const esArchiver = getService('esArchiver'); - describe('alerting api integration', function() { + describe('alerting api integration security and spaces enabled', function() { this.tags('ciGroup8'); before(async () => { diff --git a/x-pack/test/alerting_api_integration/spaces_only/config.ts b/x-pack/test/alerting_api_integration/spaces_only/config.ts new file mode 100644 index 0000000000000..44603cc95e5e0 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/config.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { createTestConfig } from '../common/config'; + +// eslint-disable-next-line import/no-default-export +export default createTestConfig('spaces_only', { disabledPlugins: ['security'], license: 'basic' }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/scenarios.ts b/x-pack/test/alerting_api_integration/spaces_only/scenarios.ts new file mode 100644 index 0000000000000..7e9569037a4cd --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/scenarios.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Space } from '../common/types'; + +const Space1: Space = { + id: 'space1', + name: 'Space 1', + disabledFeatures: [], +}; + +export const Spaces = { + space1: Space1, +}; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts new file mode 100644 index 0000000000000..74a1255dacfe5 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts @@ -0,0 +1,133 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; + +const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; + +// eslint-disable-next-line import/no-default-export +export default function indexTest({ getService }: FtrProviderContext) { + const es = getService('es'); + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('index action', () => { + after(() => esArchiver.unload('empty_kibana')); + beforeEach(() => clearTestIndex(es)); + + let createdActionID: string; + let createdActionIDWithIndex: string; + + it('should be created successfully', async () => { + // create action with no config + const { body: createdAction } = await supertest + .post('/api/action') + .set('kbn-xsrf', 'foo') + .send({ + description: 'An index action', + actionTypeId: '.index', + config: {}, + secrets: {}, + }) + .expect(200); + + expect(createdAction).to.eql({ + id: createdAction.id, + description: 'An index action', + actionTypeId: '.index', + config: { + index: null, + }, + }); + createdActionID = createdAction.id; + expect(typeof createdActionID).to.be('string'); + + const { body: fetchedAction } = await supertest + .get(`/api/action/${createdActionID}`) + .expect(200); + + expect(fetchedAction).to.eql({ + id: fetchedAction.id, + description: 'An index action', + actionTypeId: '.index', + config: { index: null }, + }); + + // create action with index config + const { body: createdActionWithIndex } = await supertest + .post('/api/action') + .set('kbn-xsrf', 'foo') + .send({ + description: 'An index action with index config', + actionTypeId: '.index', + config: { + index: ES_TEST_INDEX_NAME, + }, + }) + .expect(200); + + expect(createdActionWithIndex).to.eql({ + id: createdActionWithIndex.id, + description: 'An index action with index config', + actionTypeId: '.index', + config: { + index: ES_TEST_INDEX_NAME, + }, + }); + createdActionIDWithIndex = createdActionWithIndex.id; + expect(typeof createdActionIDWithIndex).to.be('string'); + + const { body: fetchedActionWithIndex } = await supertest + .get(`/api/action/${createdActionIDWithIndex}`) + .expect(200); + + expect(fetchedActionWithIndex).to.eql({ + id: fetchedActionWithIndex.id, + description: 'An index action with index config', + actionTypeId: '.index', + config: { + index: ES_TEST_INDEX_NAME, + }, + }); + }); + + it('should execute successly when expected for a single body', async () => { + const { body: result } = await supertest + .post(`/api/action/${createdActionID}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + index: ES_TEST_INDEX_NAME, + documents: [{ testing: [1, 2, 3] }], + refresh: true, + }, + }) + .expect(200); + expect(result.status).to.eql('ok'); + + const items = await getTestIndexItems(es); + expect(items.length).to.eql(1); + expect(items[0]._source).to.eql({ testing: [1, 2, 3] }); + }); + }); +} + +async function clearTestIndex(es: any) { + return await es.indices.delete({ + index: ES_TEST_INDEX_NAME, + ignoreUnavailable: true, + }); +} + +async function getTestIndexItems(es: any) { + const result = await es.search({ + index: ES_TEST_INDEX_NAME, + }); + + return result.hits.hits; +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/create.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/create.ts new file mode 100644 index 0000000000000..bf648890c591b --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/create.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function createActionTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('create', () => { + const objectRemover = new ObjectRemover(supertest); + + after(() => objectRemover.removeAll()); + + it('should handle create action request appropriately', async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action`) + .set('kbn-xsrf', 'foo') + .send({ + description: 'My action', + actionTypeId: 'test.index-record', + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + secrets: { + encrypted: 'This value should be encrypted', + }, + }); + + expect(response.statusCode).to.eql(200); + expect(response.body).to.eql({ + id: response.body.id, + description: 'My action', + actionTypeId: 'test.index-record', + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + }); + expect(typeof response.body.id).to.be('string'); + objectRemover.add(Spaces.space1.id, response.body.id, 'action'); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/delete.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/delete.ts new file mode 100644 index 0000000000000..e5b533334385a --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/delete.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function deleteActionTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('delete', () => { + const objectRemover = new ObjectRemover(supertest); + + after(() => objectRemover.removeAll()); + + it('should handle delete action request appropriately', async () => { + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action`) + .set('kbn-xsrf', 'foo') + .send({ + description: 'My action', + actionTypeId: 'test.index-record', + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + secrets: { + encrypted: 'This value should be encrypted', + }, + }) + .expect(200); + + await supertest + .delete(`${getUrlPrefix(Spaces.space1.id)}/api/action/${createdAction.id}`) + .set('kbn-xsrf', 'foo') + .expect(204, ''); + }); + + it(`should handle delete request appropriately when action doesn't exist`, async () => { + await supertest + .delete(`${getUrlPrefix(Spaces.space1.id)}/api/action/2`) + .set('kbn-xsrf', 'foo') + .expect(404, { + statusCode: 404, + error: 'Not Found', + message: 'Saved object [action/2] not found', + }); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts new file mode 100644 index 0000000000000..d810187499f39 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts @@ -0,0 +1,175 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const es = getService('es'); + + const esTestIndexName = '.kibaka-alerting-test-data'; + const authorizationIndex = '.kibana-test-authorization'; + + describe('execute', () => { + const objectRemover = new ObjectRemover(supertest); + + before(async () => { + await es.indices.delete({ index: esTestIndexName, ignore: [404] }); + await es.indices.create({ + index: esTestIndexName, + body: { + mappings: { + properties: { + source: { + type: 'keyword', + }, + reference: { + type: 'keyword', + }, + params: { + enabled: false, + type: 'object', + }, + config: { + enabled: false, + type: 'object', + }, + state: { + enabled: false, + type: 'object', + }, + }, + }, + }, + }); + await es.indices.create({ index: authorizationIndex }); + }); + after(async () => { + await es.indices.delete({ index: esTestIndexName }); + await es.indices.delete({ index: authorizationIndex }); + await objectRemover.removeAll(); + }); + + async function getTestIndexDoc(source: string, reference: string) { + const searchResult = await es.search({ + index: esTestIndexName, + body: { + query: { + bool: { + must: [ + { + term: { + source, + }, + }, + { + term: { + reference, + }, + }, + ], + }, + }, + }, + }); + expect(searchResult.hits.total.value).to.eql(1); + return searchResult.hits.hits[0]; + } + + it('should handle execute request appropriately', async () => { + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action`) + .set('kbn-xsrf', 'foo') + .send({ + description: 'My action', + actionTypeId: 'test.index-record', + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + secrets: { + encrypted: 'This value should be encrypted', + }, + }) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAction.id, 'action'); + + const reference = `actions-execute-1:${Spaces.space1.id}`; + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action/${createdAction.id}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + reference, + index: esTestIndexName, + message: 'Testing 123', + }, + }); + + expect(response.statusCode).to.eql(200); + expect(response.body).to.be.an('object'); + const indexedRecord = await getTestIndexDoc('action:test.index-record', reference); + expect(indexedRecord._source).to.eql({ + params: { + reference, + index: esTestIndexName, + message: 'Testing 123', + }, + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + secrets: { + encrypted: 'This value should be encrypted', + }, + reference, + source: 'action:test.index-record', + }); + }); + + it('should handle execute request appropriately and have proper callCluster and savedObjectsClient authorization', async () => { + const reference = `actions-execute-3:${Spaces.space1.id}`; + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action`) + .set('kbn-xsrf', 'foo') + .send({ + description: 'My action', + actionTypeId: 'test.authorization', + }) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAction.id, 'action'); + + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action/${createdAction.id}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + callClusterAuthorizationIndex: authorizationIndex, + savedObjectsClientType: 'dashboard', + savedObjectsClientId: '1', + index: esTestIndexName, + reference, + }, + }); + + expect(response.statusCode).to.eql(200); + const indexedRecord = await getTestIndexDoc('action:test.authorization', reference); + expect(indexedRecord._source.state).to.eql({ + callClusterSuccess: true, + savedObjectsClientSuccess: false, + savedObjectsClientError: { + ...indexedRecord._source.state.savedObjectsClientError, + output: { + ...indexedRecord._source.state.savedObjectsClientError.output, + statusCode: 404, + }, + }, + }); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/find.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/find.ts new file mode 100644 index 0000000000000..e955a38daa42a --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/find.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function findActionTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('find', () => { + const objectRemover = new ObjectRemover(supertest); + + afterEach(() => objectRemover.removeAll()); + + it('should handle find action request appropriately', async () => { + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action`) + .set('kbn-xsrf', 'foo') + .send({ + description: 'My action', + actionTypeId: 'test.index-record', + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + secrets: { + encrypted: 'This value should be encrypted', + }, + }) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAction.id, 'action'); + + await supertest + .get( + `${getUrlPrefix( + Spaces.space1.id + )}/api/action/_find?search=test.index-record&search_fields=actionTypeId` + ) + .expect(200, { + page: 1, + perPage: 20, + total: 1, + data: [ + { + id: createdAction.id, + description: 'My action', + actionTypeId: 'test.index-record', + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + }, + ], + }); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/get.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/get.ts new file mode 100644 index 0000000000000..a5a321eb6d0c6 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/get.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function getActionTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('get', () => { + const objectRemover = new ObjectRemover(supertest); + + afterEach(() => objectRemover.removeAll()); + + it('should handle get action request appropriately', async () => { + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action`) + .set('kbn-xsrf', 'foo') + .send({ + description: 'My action', + actionTypeId: 'test.index-record', + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + secrets: { + encrypted: 'This value should be encrypted', + }, + }) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAction.id, 'action'); + + await supertest + .get(`${getUrlPrefix(Spaces.space1.id)}/api/action/${createdAction.id}`) + .expect(200, { + id: createdAction.id, + actionTypeId: 'test.index-record', + description: 'My action', + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + }); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/index.ts new file mode 100644 index 0000000000000..a3447e730c28d --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function actionsTests({ loadTestFile }: FtrProviderContext) { + describe('Actions', () => { + loadTestFile(require.resolve('./create')); + loadTestFile(require.resolve('./delete')); + loadTestFile(require.resolve('./find')); + loadTestFile(require.resolve('./get')); + loadTestFile(require.resolve('./list_action_types')); + loadTestFile(require.resolve('./update')); + loadTestFile(require.resolve('./execute')); + loadTestFile(require.resolve('./builtin_action_types/es_index')); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/list_action_types.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/list_action_types.ts new file mode 100644 index 0000000000000..fa3941dad3795 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/list_action_types.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { Spaces } from '../../scenarios'; +import { getUrlPrefix } from '../../../common/lib/space_test_utils'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function listActionTypesTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('list_action_types', () => { + it('should return 200 with list of action types containing defaults', async () => { + const response = await supertest.get(`${getUrlPrefix(Spaces.space1.id)}/api/action/types`); + + function createActionTypeMatcher(id: string, name: string) { + return (actionType: { id: string; name: string }) => { + return actionType.id === id && actionType.name === name; + }; + } + + expect(response.statusCode).to.eql(200); + // Check for values explicitly in order to avoid this test failing each time plugins register + // a new action type + expect( + response.body.some(createActionTypeMatcher('test.index-record', 'Test: Index Record')) + ).to.be(true); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/update.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/update.ts new file mode 100644 index 0000000000000..76a997e369fe1 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/update.ts @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function updateActionTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('update', () => { + const objectRemover = new ObjectRemover(supertest); + + after(() => objectRemover.removeAll()); + + it('should handle update action request appropriately', async () => { + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action`) + .set('kbn-xsrf', 'foo') + .send({ + description: 'My action', + actionTypeId: 'test.index-record', + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + secrets: { + encrypted: 'This value should be encrypted', + }, + }) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAction.id, 'action'); + + await supertest + .put(`${getUrlPrefix(Spaces.space1.id)}/api/action/${createdAction.id}`) + .set('kbn-xsrf', 'foo') + .send({ + description: 'My action updated', + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + secrets: { + encrypted: 'This value should be encrypted', + }, + }) + .expect(200, { + id: createdAction.id, + actionTypeId: 'test.index-record', + description: 'My action updated', + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + }); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts.ts new file mode 100644 index 0000000000000..dfdaecb8d4593 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts.ts @@ -0,0 +1,309 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { getTestAlertData, setupEsTestIndex, destroyEsTestIndex } from './utils'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function alertTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const es = getService('es'); + const retry = getService('retry'); + + describe('alerts', () => { + let esTestIndexName: string; + const authorizationIndex = '.kibana-test-authorization'; + const objectRemover = new ObjectRemover(supertest); + + before(async () => { + await destroyEsTestIndex(es); + ({ name: esTestIndexName } = await setupEsTestIndex(es)); + await es.indices.create({ index: authorizationIndex }); + }); + afterEach(() => objectRemover.removeAll()); + after(async () => { + await destroyEsTestIndex(es); + await es.indices.delete({ index: authorizationIndex }); + }); + + async function waitForTestIndexDoc(source: string, reference: string) { + return await retry.try(async () => { + const searchResult = await es.search({ + index: esTestIndexName, + body: { + query: { + bool: { + must: [ + { + term: { + source, + }, + }, + { + term: { + reference, + }, + }, + ], + }, + }, + }, + }); + expect(searchResult.hits.total.value).to.eql(1); + return searchResult.hits.hits[0]; + }); + } + + it('should schedule task, run alert and fire actions', async () => { + const reference = `create-test-1:${Spaces.space1.id}`; + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action`) + .set('kbn-xsrf', 'foo') + .send({ + description: 'My action', + actionTypeId: 'test.index-record', + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + secrets: { + encrypted: 'This value should be encrypted', + }, + }) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAction.id, 'action'); + + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert`) + .set('kbn-xsrf', 'foo') + .send( + getTestAlertData({ + interval: '1m', + alertTypeId: 'test.always-firing', + alertTypeParams: { + index: esTestIndexName, + reference, + }, + actions: [ + { + group: 'default', + id: createdAction.id, + params: { + index: esTestIndexName, + reference, + message: + 'instanceContextValue: {{context.instanceContextValue}}, instanceStateValue: {{state.instanceStateValue}}', + }, + }, + ], + }) + ); + + expect(response.statusCode).to.eql(200); + objectRemover.add(Spaces.space1.id, response.body.id, 'alert'); + const alertTestRecord = await waitForTestIndexDoc('alert:test.always-firing', reference); + expect(alertTestRecord._source).to.eql({ + source: 'alert:test.always-firing', + reference, + state: {}, + params: { + index: esTestIndexName, + reference, + }, + }); + const actionTestRecord = await waitForTestIndexDoc('action:test.index-record', reference); + expect(actionTestRecord._source).to.eql({ + config: { + unencrypted: `This value shouldn't get encrypted`, + }, + secrets: { + encrypted: 'This value should be encrypted', + }, + params: { + index: esTestIndexName, + reference, + message: 'instanceContextValue: true, instanceStateValue: true', + }, + reference, + source: 'action:test.index-record', + }); + }); + + it('should handle custom retry logic', async () => { + // We'll use this start time to query tasks created after this point + const testStart = new Date(); + // We have to provide the test.rate-limit the next runAt, for testing purposes + const retryDate = new Date(Date.now() + 60000); + + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action`) + .set('kbn-xsrf', 'foo') + .send({ + description: 'Test rate limit', + actionTypeId: 'test.rate-limit', + config: {}, + }) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAction.id, 'action'); + + const reference = `create-test-2:${Spaces.space1.id}`; + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert`) + .set('kbn-xsrf', 'foo') + .send( + getTestAlertData({ + interval: '1m', + alertTypeId: 'test.always-firing', + alertTypeParams: { + index: esTestIndexName, + reference: 'create-test-2', + }, + actions: [ + { + group: 'default', + id: createdAction.id, + params: { + reference, + index: esTestIndexName, + retryAt: retryDate.getTime(), + }, + }, + ], + }) + ); + + expect(response.statusCode).to.eql(200); + objectRemover.add(Spaces.space1.id, response.body.id, 'alert'); + const scheduledActionTask = await retry.try(async () => { + const searchResult = await es.search({ + index: '.kibana_task_manager', + body: { + query: { + bool: { + must: [ + { + term: { + 'task.status': 'idle', + }, + }, + { + term: { + 'task.attempts': 1, + }, + }, + { + term: { + 'task.taskType': 'actions:test.rate-limit', + }, + }, + { + range: { + 'task.scheduledAt': { + gte: testStart, + }, + }, + }, + ], + }, + }, + }, + }); + expect(searchResult.hits.total.value).to.eql(1); + return searchResult.hits.hits[0]; + }); + expect(scheduledActionTask._source.task.runAt).to.eql(retryDate.toISOString()); + }); + + it('should have proper callCluster and savedObjectsClient authorization for alert type executor', async () => { + const reference = `create-test-3:${Spaces.space1.id}`; + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert`) + .set('kbn-xsrf', 'foo') + .send( + getTestAlertData({ + alertTypeId: 'test.authorization', + alertTypeParams: { + callClusterAuthorizationIndex: authorizationIndex, + savedObjectsClientType: 'dashboard', + savedObjectsClientId: '1', + index: esTestIndexName, + reference, + }, + }) + ); + + expect(response.statusCode).to.eql(200); + objectRemover.add(Spaces.space1.id, response.body.id, 'alert'); + const alertTestRecord = await waitForTestIndexDoc('alert:test.authorization', reference); + expect(alertTestRecord._source.state).to.eql({ + callClusterSuccess: true, + savedObjectsClientSuccess: false, + savedObjectsClientError: { + ...alertTestRecord._source.state.savedObjectsClientError, + output: { + ...alertTestRecord._source.state.savedObjectsClientError.output, + statusCode: 404, + }, + }, + }); + }); + + it('should have proper callCluster and savedObjectsClient authorization for action type executor', async () => { + const reference = `create-test-4:${Spaces.space1.id}`; + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action`) + .set('kbn-xsrf', 'foo') + .send({ + description: 'My action', + actionTypeId: 'test.authorization', + }) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAction.id, 'action'); + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert`) + .set('kbn-xsrf', 'foo') + .send( + getTestAlertData({ + alertTypeId: 'test.always-firing', + alertTypeParams: { + index: esTestIndexName, + reference, + }, + actions: [ + { + group: 'default', + id: createdAction.id, + params: { + callClusterAuthorizationIndex: authorizationIndex, + savedObjectsClientType: 'dashboard', + savedObjectsClientId: '1', + index: esTestIndexName, + reference, + }, + }, + ], + }) + ); + + expect(response.statusCode).to.eql(200); + objectRemover.add(Spaces.space1.id, response.body.id, 'alert'); + const actionTestRecord = await waitForTestIndexDoc('action:test.authorization', reference); + expect(actionTestRecord._source.state).to.eql({ + callClusterSuccess: true, + savedObjectsClientSuccess: false, + savedObjectsClientError: { + ...actionTestRecord._source.state.savedObjectsClientError, + output: { + ...actionTestRecord._source.state.savedObjectsClientError.output, + statusCode: 404, + }, + }, + }); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts new file mode 100644 index 0000000000000..6d23e6f6817a1 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { getTestAlertData } from './utils'; +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function createAlertTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('create', () => { + const objectRemover = new ObjectRemover(supertest); + + after(() => objectRemover.removeAll()); + + async function getScheduledTask(id: string) { + return await es.get({ + id: `task:${id}`, + index: '.kibana_task_manager', + }); + } + + it('should handle create alert request appropriately', async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert`) + .set('kbn-xsrf', 'foo') + .send(getTestAlertData()); + + expect(response.statusCode).to.eql(200); + objectRemover.add(Spaces.space1.id, response.body.id, 'alert'); + expect(response.body).to.eql({ + id: response.body.id, + actions: [], + enabled: true, + alertTypeId: 'test.noop', + alertTypeParams: {}, + createdBy: null, + interval: '10s', + scheduledTaskId: response.body.scheduledTaskId, + updatedBy: null, + }); + expect(typeof response.body.scheduledTaskId).to.be('string'); + const { _source: taskRecord } = await getScheduledTask(response.body.scheduledTaskId); + expect(taskRecord.type).to.eql('task'); + expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); + expect(JSON.parse(taskRecord.task.params)).to.eql({ + alertId: response.body.id, + spaceId: Spaces.space1.id, + }); + }); + + it('should handle create alert request appropriately when an alert is disabled ', async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert`) + .set('kbn-xsrf', 'foo') + .send(getTestAlertData({ enabled: false })); + + expect(response.statusCode).to.eql(200); + objectRemover.add(Spaces.space1.id, response.body.id, 'alert'); + expect(response.body.scheduledTaskId).to.eql(undefined); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts new file mode 100644 index 0000000000000..798b5ff5b319f --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { getTestAlertData } from './utils'; +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function createDeleteTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('delete', () => { + const objectRemover = new ObjectRemover(supertest); + + after(() => objectRemover.removeAll()); + + async function getScheduledTask(id: string) { + return await es.get({ + id: `task:${id}`, + index: '.kibana_task_manager', + }); + } + + it('should handle delete alert request appropriately', async () => { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert`) + .set('kbn-xsrf', 'foo') + .send(getTestAlertData()) + .expect(200); + + await supertest + .delete(`${getUrlPrefix(Spaces.space1.id)}/api/alert/${createdAlert.id}`) + .set('kbn-xsrf', 'foo') + .expect(204, ''); + + try { + await getScheduledTask(createdAlert.scheduledTaskId); + throw new Error('Should have removed scheduled task'); + } catch (e) { + expect(e.status).to.eql(404); + } + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts new file mode 100644 index 0000000000000..7da8f71139ad4 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { getTestAlertData } from './utils'; +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function createDisableAlertTests({ getService }: FtrProviderContext) { + const es = getService('es'); + const supertest = getService('supertest'); + + describe('disable', () => { + const objectRemover = new ObjectRemover(supertest); + + after(() => objectRemover.removeAll()); + + async function getScheduledTask(id: string) { + return await es.get({ + id: `task:${id}`, + index: '.kibana_task_manager', + }); + } + + it('should handle disable alert request appropriately', async () => { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert`) + .set('kbn-xsrf', 'foo') + .send(getTestAlertData({ enabled: true })) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAlert.id, 'alert'); + + await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert/${createdAlert.id}/_disable`) + .set('kbn-xsrf', 'foo') + .expect(204, ''); + + try { + await getScheduledTask(createdAlert.scheduledTaskId); + throw new Error('Should have removed scheduled task'); + } catch (e) { + expect(e.status).to.eql(404); + } + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts new file mode 100644 index 0000000000000..4ffb6d3637b32 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { getTestAlertData } from './utils'; +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function createEnableAlertTests({ getService }: FtrProviderContext) { + const es = getService('es'); + const supertest = getService('supertest'); + + describe('enable', () => { + const objectRemover = new ObjectRemover(supertest); + + after(() => objectRemover.removeAll()); + + async function getScheduledTask(id: string) { + return await es.get({ + id: `task:${id}`, + index: '.kibana_task_manager', + }); + } + + it('should handle enable alert request appropriately', async () => { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert`) + .set('kbn-xsrf', 'foo') + .send(getTestAlertData({ enabled: false })) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAlert.id, 'alert'); + + await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert/${createdAlert.id}/_enable`) + .set('kbn-xsrf', 'foo') + .expect(204, ''); + + const { body: updatedAlert } = await supertest + .get(`${getUrlPrefix(Spaces.space1.id)}/api/alert/${createdAlert.id}`) + .set('kbn-xsrf', 'foo') + .expect(200); + expect(typeof updatedAlert.scheduledTaskId).to.eql('string'); + const { _source: taskRecord } = await getScheduledTask(updatedAlert.scheduledTaskId); + expect(taskRecord.type).to.eql('task'); + expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); + expect(JSON.parse(taskRecord.task.params)).to.eql({ + alertId: createdAlert.id, + spaceId: Spaces.space1.id, + }); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/find.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/find.ts new file mode 100644 index 0000000000000..308b3467536da --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/find.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { getTestAlertData } from './utils'; +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function createFindTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('find', () => { + const objectRemover = new ObjectRemover(supertest); + + afterEach(() => objectRemover.removeAll()); + + it('should handle find alert request appropriately', async () => { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert`) + .set('kbn-xsrf', 'foo') + .send(getTestAlertData()) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAlert.id, 'alert'); + + const response = await supertest.get( + `${getUrlPrefix( + Spaces.space1.id + )}/api/alert/_find?search=test.noop&search_fields=alertTypeId` + ); + + expect(response.statusCode).to.eql(200); + expect(response.body.page).to.equal(1); + expect(response.body.perPage).to.be.greaterThan(0); + expect(response.body.total).to.be.greaterThan(0); + const match = response.body.data.find((obj: any) => obj.id === createdAlert.id); + expect(match).to.eql({ + id: createdAlert.id, + alertTypeId: 'test.noop', + interval: '10s', + enabled: true, + actions: [], + alertTypeParams: {}, + createdBy: null, + scheduledTaskId: match.scheduledTaskId, + updatedBy: null, + }); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get.ts new file mode 100644 index 0000000000000..101bcf728da44 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { getTestAlertData } from './utils'; +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function createGetTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('get', () => { + const objectRemover = new ObjectRemover(supertest); + + afterEach(() => objectRemover.removeAll()); + + it('should handle get alert request appropriately', async () => { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert`) + .set('kbn-xsrf', 'foo') + .send(getTestAlertData()) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAlert.id, 'alert'); + + const response = await supertest.get( + `${getUrlPrefix(Spaces.space1.id)}/api/alert/${createdAlert.id}` + ); + + expect(response.statusCode).to.eql(200); + expect(response.body).to.eql({ + id: createdAlert.id, + alertTypeId: 'test.noop', + interval: '10s', + enabled: true, + actions: [], + alertTypeParams: {}, + createdBy: null, + scheduledTaskId: response.body.scheduledTaskId, + updatedBy: null, + }); + }); + + it(`should handle get alert request appropriately when alert doesn't exist`, async () => { + await supertest.get(`${getUrlPrefix(Spaces.space1.id)}/api/alert/1`).expect(404, { + statusCode: 404, + error: 'Not Found', + message: 'Saved object [alert/1] not found', + }); + }); + }); +} 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 new file mode 100644 index 0000000000000..8db614feda937 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function alertingTests({ loadTestFile }: FtrProviderContext) { + describe('Alerting', () => { + loadTestFile(require.resolve('./create')); + loadTestFile(require.resolve('./delete')); + loadTestFile(require.resolve('./disable')); + loadTestFile(require.resolve('./enable')); + loadTestFile(require.resolve('./find')); + loadTestFile(require.resolve('./get')); + loadTestFile(require.resolve('./list_alert_types')); + loadTestFile(require.resolve('./update')); + loadTestFile(require.resolve('./alerts')); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts new file mode 100644 index 0000000000000..479b6621d3fcd --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { Spaces } from '../../scenarios'; +import { getUrlPrefix } from '../../../common/lib/space_test_utils'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function listAlertTypes({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('list_alert_types', () => { + it('should return 200 with list of alert types', async () => { + const response = await supertest.get(`${getUrlPrefix(Spaces.space1.id)}/api/alert/types`); + + expect(response.statusCode).to.eql(200); + const fixtureAlertType = response.body.find((alertType: any) => alertType.id === 'test.noop'); + expect(fixtureAlertType).to.eql({ + id: 'test.noop', + name: 'Test: Noop', + }); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/update.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/update.ts new file mode 100644 index 0000000000000..24fbab8d45b84 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/update.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getTestAlertData } from './utils'; +import { Spaces } from '../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function createUpdateTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('update', () => { + const objectRemover = new ObjectRemover(supertest); + + after(() => objectRemover.removeAll()); + + it('should handle update alert request appropriately', async () => { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alert`) + .set('kbn-xsrf', 'foo') + .send(getTestAlertData()) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAlert.id, 'alert'); + + const updatedData = { + alertTypeParams: { + foo: true, + }, + interval: '12s', + actions: [], + }; + await supertest + .put(`${getUrlPrefix(Spaces.space1.id)}/api/alert/${createdAlert.id}`) + .set('kbn-xsrf', 'foo') + .send(updatedData) + .expect(200, { + ...updatedData, + id: createdAlert.id, + updatedBy: null, + }); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/utils.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/utils.ts new file mode 100644 index 0000000000000..b91f4651c0851 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/utils.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +const esTestIndexName = '.kibaka-alerting-test-data'; + +export function getTestAlertData(attributeOverwrites = {}) { + return { + enabled: true, + alertTypeId: 'test.noop', + interval: '10s', + actions: [], + alertTypeParams: {}, + ...attributeOverwrites, + }; +} + +export async function setupEsTestIndex(es: any) { + await es.indices.create({ + index: esTestIndexName, + body: { + mappings: { + properties: { + source: { + type: 'keyword', + }, + reference: { + type: 'keyword', + }, + params: { + enabled: false, + type: 'object', + }, + config: { + enabled: false, + type: 'object', + }, + state: { + enabled: false, + type: 'object', + }, + }, + }, + }, + }); + return { + name: esTestIndexName, + }; +} + +export async function destroyEsTestIndex(es: any) { + await es.indices.delete({ index: esTestIndexName, ignore: [404] }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/index.ts new file mode 100644 index 0000000000000..dfbb2cca81a49 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/index.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SpacesService } from '../../../common/services'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { Spaces } from '../scenarios'; + +// eslint-disable-next-line import/no-default-export +export default function alertingApiIntegrationTests({ + loadTestFile, + getService, +}: FtrProviderContext) { + const spacesService: SpacesService = getService('spaces'); + const esArchiver = getService('esArchiver'); + + describe('alerting api integration spaces only', function() { + this.tags('ciGroup8'); + + before(async () => { + for (const space of Object.values(Spaces)) { + await spacesService.create(space); + } + }); + + after(() => esArchiver.unload('empty_kibana')); + + loadTestFile(require.resolve('./actions')); + loadTestFile(require.resolve('./alerting')); + }); +}