Skip to content

Commit

Permalink
Add functional tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mikecote committed Apr 20, 2021
1 parent 25a5e6b commit 6e9ec56
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],
"requiredPlugins": ["taskManager", "features", "actions", "alerting", "encryptedSavedObjects"],
"requiredPlugins": ["taskManager", "features", "actions", "alerting", "encryptedSavedObjects", "actions"],
"optionalPlugins": ["security", "spaces"],
"server": true,
"ui": false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { defineActionTypes } from './action_types';
import { defineRoutes } from './routes';
import { SpacesPluginStart } from '../../../../../../../plugins/spaces/server';
import { SecurityPluginStart } from '../../../../../../../plugins/security/server';
import { PluginStartContract as ActionsPluginStart } from '../../../../../../../plugins/actions/server';

export interface FixtureSetupDeps {
features: FeaturesPluginSetup;
Expand All @@ -26,6 +27,7 @@ export interface FixtureStartDeps {
encryptedSavedObjects: EncryptedSavedObjectsPluginStart;
security?: SecurityPluginStart;
spaces?: SpacesPluginStart;
actions: ActionsPluginStart;
}

export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, FixtureStartDeps> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import uuid from 'uuid';
import {
CoreSetup,
RequestHandlerContext,
Expand Down Expand Up @@ -174,10 +175,10 @@ export function defineRoutes(core: CoreSetup<FixtureStartDeps>, { logger }: { lo

router.put(
{
path: '/api/alerts_fixture/{id}/reschedule_task',
path: '/api/alerts_fixture/{taskId}/reschedule_task',
validate: {
params: schema.object({
id: schema.string(),
taskId: schema.string(),
}),
body: schema.object({
runAt: schema.string(),
Expand All @@ -189,23 +190,20 @@ export function defineRoutes(core: CoreSetup<FixtureStartDeps>, { logger }: { lo
req: KibanaRequest<any, any, any, any>,
res: KibanaResponseFactory
): Promise<IKibanaResponse<any>> => {
const { id } = req.params;
const { taskId } = req.params;
const { runAt } = req.body;

const [{ savedObjects }] = await core.getStartServices();
const savedObjectsWithTasksAndAlerts = await savedObjects.getScopedClient(req, {
includedHiddenTypes: ['task', 'alert'],
});
const alert = await savedObjectsWithTasksAndAlerts.get<RawAlert>('alert', id);
const result = await retryIfConflicts(
logger,
`/api/alerts_fixture/${id}/reschedule_task`,
`/api/alerts_fixture/${taskId}/reschedule_task`,
async () => {
return await savedObjectsWithTasksAndAlerts.update<TaskInstance>(
'task',
alert.attributes.scheduledTaskId!,
{ runAt }
);
return await savedObjectsWithTasksAndAlerts.update<TaskInstance>('task', taskId, {
runAt,
});
}
);
return res.ok({ body: result });
Expand Down Expand Up @@ -278,4 +276,53 @@ export function defineRoutes(core: CoreSetup<FixtureStartDeps>, { logger }: { lo
}
}
);

router.post(
{
path: '/api/alerts_fixture/{id}/enqueue_action',
validate: {
params: schema.object({
id: schema.string(),
}),
body: schema.object({
params: schema.recordOf(schema.string(), schema.any()),
}),
},
},
async (
context: RequestHandlerContext,
req: KibanaRequest<any, any, any, any>,
res: KibanaResponseFactory
): Promise<IKibanaResponse<any>> => {
try {
const [, { actions, security, spaces }] = await core.getStartServices();
const actionsClient = await actions.getActionsClientWithRequest(req);

const createAPIKeyResult =
security &&
(await security.authc.apiKeys.grantAsInternalUser(req, {
name: `alerts_fixture:enqueue_action:${uuid.v4()}`,
role_descriptors: {},
}));

await actionsClient.enqueueExecution({
id: req.params.id,
spaceId: spaces ? spaces.spacesService.getSpaceId(req) : 'default',
apiKey: createAPIKeyResult
? Buffer.from(`${createAPIKeyResult.id}:${createAPIKeyResult.api_key}`).toString(
'base64'
)
: null,
params: req.body.params,
source: {
type: 'HTTP_REQUEST' as any,
source: req,
},
});
return res.noContent();
} catch (err) {
return res.badRequest({ body: err });
}
}
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,22 @@ export default function alertTests({ getService }: FtrProviderContext) {
'pre-7.10.0'
);

// Get scheduled task id
const getResponse = await supertestWithoutAuth
.get(`${getUrlPrefix(space.id)}/api/alerting/rule/${alertId}`)
.auth(user.username, user.password)
.expect(200);

// loading the archive likely caused the task to fail so ensure it's rescheduled to run in 2 seconds,
// otherwise this test will stall for 5 minutes
// no other attributes are touched, only runAt, so unless it would have ran when runAt expired, it
// won't run now
await supertest
.put(`${getUrlPrefix(space.id)}/api/alerts_fixture/${alertId}/reschedule_task`)
.put(
`${getUrlPrefix(space.id)}/api/alerts_fixture/${
getResponse.body.scheduled_task_id
}/reschedule_task`
)
.set('kbn-xsrf', 'foo')
.send({
runAt: getRunAt(2000),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* 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 {
ESTestIndexTool,
ES_TEST_INDEX_NAME,
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('legacyEs');
const retry = getService('retry');
const esTestIndexTool = new ESTestIndexTool(es, retry);

describe('enqueue', () => {
const objectRemover = new ObjectRemover(supertest);

before(async () => {
await esTestIndexTool.destroy();
await esTestIndexTool.setup();
});
after(async () => {
await esTestIndexTool.destroy();
await objectRemover.removeAll();
});

it('should handle enqueue request appropriately', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'My action',
connector_type_id: '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', 'actions');

const reference = `actions-enqueue-1:${Spaces.space1.id}:${createdAction.id}`;
const response = await supertest
.post(
`${getUrlPrefix(Spaces.space1.id)}/api/alerts_fixture/${createdAction.id}/enqueue_action`
)
.set('kbn-xsrf', 'foo')
.send({
params: {
reference,
index: ES_TEST_INDEX_NAME,
message: 'Testing 123',
},
});

expect(response.status).to.eql(204);
await esTestIndexTool.waitForDocs('action:test.index-record', reference, 1);
});

it('should cleanup task after a failure', async () => {
const testStart = new Date();
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'My action',
connector_type_id: 'test.failing',
config: {},
secrets: {},
})
.expect(200);
objectRemover.add(Spaces.space1.id, createdAction.id, 'action', 'actions');

const reference = `actions-enqueue-2:${Spaces.space1.id}:${createdAction.id}`;
await supertest
.post(
`${getUrlPrefix(Spaces.space1.id)}/api/alerts_fixture/${createdAction.id}/enqueue_action`
)
.set('kbn-xsrf', 'foo')
.send({
params: {
reference,
index: ES_TEST_INDEX_NAME,
},
})
.expect(204);

await esTestIndexTool.waitForDocs('action:test.failing', reference, 1);

await supertest
.put(
`${getUrlPrefix(
Spaces.space1.id
)}/api/alerts_fixture/Actions-cleanup_failed_action_executions/reschedule_task`
)
.set('kbn-xsrf', 'foo')
.send({
runAt: new Date().toISOString(),
})
.expect(200);

await retry.try(async () => {
const searchResult = await es.search({
index: '.kibana_task_manager',
body: {
query: {
bool: {
must: [
{
term: {
'task.taskType': 'actions:test.failing',
},
},
{
range: {
'task.scheduledAt': {
gte: testStart,
},
},
},
],
},
},
},
});
expect(searchResult.hits.total.value).to.eql(0);
});
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default function actionsTests({ loadTestFile, getService }: FtrProviderCo
loadTestFile(require.resolve('./connector_types'));
loadTestFile(require.resolve('./update'));
loadTestFile(require.resolve('./execute'));
loadTestFile(require.resolve('./enqueue'));
loadTestFile(require.resolve('./builtin_action_types/es_index'));
loadTestFile(require.resolve('./builtin_action_types/webhook'));
loadTestFile(require.resolve('./builtin_action_types/preconfigured_alert_history_connector'));
Expand Down

0 comments on commit 6e9ec56

Please sign in to comment.