Add ability to name alerts (#49035)
* Ability to name alerts * Fix RawAlert TypeScript interface * Update docs
This commit is contained in:
parent
568b8d3992
commit
bfdf61714e
|
@ -198,6 +198,7 @@ Payload:
|
|||
|Property|Description|Type|
|
||||
|---|---|---|
|
||||
|enabled|Indicate if you want the alert to start executing on an interval basis after it has been created.|boolean|
|
||||
|name|A name to reference and search in the future.|string|
|
||||
|alertTypeId|The id value of the alert type you want to call when the alert is scheduled to execute.|string|
|
||||
|interval|The interval in seconds, minutes, hours or days the alert should execute. Example: `10s`, `5m`, `1h`, `1d`.|string|
|
||||
|alertTypeParams|The parameters to pass in to the alert type executor `params` value. This will also validate against the alert type params validator if defined.|object|
|
||||
|
@ -242,6 +243,7 @@ Payload:
|
|||
|Property|Description|Type|
|
||||
|---|---|---|
|
||||
|interval|The interval in seconds, minutes, hours or days the alert should execute. Example: `10s`, `5m`, `1h`, `1d`.|string|
|
||||
|name|A name to reference and search in the future.|string|
|
||||
|alertTypeParams|The parameters to pass in to the alert type executor `params` value. This will also validate against the alert type params validator if defined.|object|
|
||||
|actions|Array of the following:<br> - `group` (string): We support grouping actions in the scenario of escalations or different types of alert instances. If you don't need this, feel free to use `default` as a value.<br>- `id` (string): The id of the action saved object to execute.<br>- `params` (object): There map to the `params` the action type will receive. In order to help apply context to strings, we handle them as mustache templates and pass in a default set of context. (see templating actions).|array|
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"name": {
|
||||
"type": "text"
|
||||
},
|
||||
"alertTypeId": {
|
||||
"type": "keyword"
|
||||
},
|
||||
|
|
|
@ -43,6 +43,7 @@ const mockedDate = new Date('2019-02-12T21:01:22.479Z');
|
|||
function getMockData(overwrites: Record<string, any> = {}) {
|
||||
return {
|
||||
enabled: true,
|
||||
name: 'abc',
|
||||
alertTypeId: '123',
|
||||
interval: '10s',
|
||||
throttle: null,
|
||||
|
@ -172,6 +173,7 @@ describe('create()', () => {
|
|||
"interval": "10s",
|
||||
"muteAll": false,
|
||||
"mutedInstanceIds": Array [],
|
||||
"name": "abc",
|
||||
"throttle": null,
|
||||
"updatedBy": "elastic",
|
||||
}
|
||||
|
@ -504,6 +506,7 @@ describe('create()', () => {
|
|||
},
|
||||
],
|
||||
alertTypeId: '123',
|
||||
name: 'abc',
|
||||
alertTypeParams: { bar: true },
|
||||
apiKey: Buffer.from('123:abc').toString('base64'),
|
||||
apiKeyOwner: 'elastic',
|
||||
|
@ -1173,6 +1176,7 @@ describe('update()', () => {
|
|||
id: '1',
|
||||
data: {
|
||||
interval: '10s',
|
||||
name: 'abc',
|
||||
alertTypeParams: {
|
||||
bar: true,
|
||||
},
|
||||
|
@ -1230,6 +1234,7 @@ describe('update()', () => {
|
|||
"apiKeyOwner": null,
|
||||
"enabled": true,
|
||||
"interval": "10s",
|
||||
"name": "abc",
|
||||
"scheduledTaskId": "task-123",
|
||||
"updatedBy": "elastic",
|
||||
}
|
||||
|
@ -1304,6 +1309,7 @@ describe('update()', () => {
|
|||
id: '1',
|
||||
data: {
|
||||
interval: '10s',
|
||||
name: 'abc',
|
||||
alertTypeParams: {
|
||||
bar: true,
|
||||
},
|
||||
|
@ -1362,6 +1368,7 @@ describe('update()', () => {
|
|||
"apiKeyOwner": "elastic",
|
||||
"enabled": true,
|
||||
"interval": "10s",
|
||||
"name": "abc",
|
||||
"scheduledTaskId": "task-123",
|
||||
"updatedBy": "elastic",
|
||||
}
|
||||
|
@ -1406,6 +1413,7 @@ describe('update()', () => {
|
|||
id: '1',
|
||||
data: {
|
||||
interval: '10s',
|
||||
name: 'abc',
|
||||
alertTypeParams: {
|
||||
bar: true,
|
||||
},
|
||||
|
|
|
@ -72,6 +72,7 @@ interface CreateOptions {
|
|||
interface UpdateOptions {
|
||||
id: string;
|
||||
data: {
|
||||
name: string;
|
||||
interval: string;
|
||||
actions: AlertAction[];
|
||||
alertTypeParams: Record<string, any>;
|
||||
|
|
|
@ -12,6 +12,7 @@ server.route(createAlertRoute);
|
|||
|
||||
const mockedAlert = {
|
||||
alertTypeId: '1',
|
||||
name: 'abc',
|
||||
interval: '10s',
|
||||
alertTypeParams: {
|
||||
bar: true,
|
||||
|
@ -44,24 +45,25 @@ test('creates an alert with proper parameters', async () => {
|
|||
expect(statusCode).toBe(200);
|
||||
const response = JSON.parse(payload);
|
||||
expect(response).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"actions": Array [
|
||||
Object {
|
||||
"actions": Array [
|
||||
Object {
|
||||
"group": "default",
|
||||
"id": "2",
|
||||
"params": Object {
|
||||
"foo": true,
|
||||
},
|
||||
},
|
||||
],
|
||||
"alertTypeId": "1",
|
||||
"alertTypeParams": Object {
|
||||
"bar": true,
|
||||
"group": "default",
|
||||
"id": "2",
|
||||
"params": Object {
|
||||
"foo": true,
|
||||
},
|
||||
"id": "123",
|
||||
"interval": "10s",
|
||||
}
|
||||
`);
|
||||
},
|
||||
],
|
||||
"alertTypeId": "1",
|
||||
"alertTypeParams": Object {
|
||||
"bar": true,
|
||||
},
|
||||
"id": "123",
|
||||
"interval": "10s",
|
||||
"name": "abc",
|
||||
}
|
||||
`);
|
||||
expect(alertsClient.create).toHaveBeenCalledTimes(1);
|
||||
expect(alertsClient.create.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
|
@ -82,6 +84,7 @@ test('creates an alert with proper parameters', async () => {
|
|||
},
|
||||
"enabled": true,
|
||||
"interval": "10s",
|
||||
"name": "abc",
|
||||
"throttle": null,
|
||||
},
|
||||
},
|
||||
|
@ -107,6 +110,7 @@ test('creates an alert with proper parameters', async () => {
|
|||
},
|
||||
"enabled": true,
|
||||
"interval": "10s",
|
||||
"name": "abc",
|
||||
"throttle": null,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -12,6 +12,7 @@ import { getDurationSchema } from '../lib';
|
|||
interface ScheduleRequest extends Hapi.Request {
|
||||
payload: {
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
alertTypeId: string;
|
||||
interval: string;
|
||||
actions: AlertAction[];
|
||||
|
@ -32,6 +33,7 @@ export const createAlertRoute = {
|
|||
payload: Joi.object()
|
||||
.keys({
|
||||
enabled: Joi.boolean().default(true),
|
||||
name: Joi.string().required(),
|
||||
alertTypeId: Joi.string().required(),
|
||||
throttle: getDurationSchema().default(null),
|
||||
interval: getDurationSchema().required(),
|
||||
|
|
|
@ -36,6 +36,7 @@ test('calls the update function with proper parameters', async () => {
|
|||
url: '/api/alert/1',
|
||||
payload: {
|
||||
throttle: null,
|
||||
name: 'abc',
|
||||
interval: '12s',
|
||||
alertTypeParams: {
|
||||
otherField: false,
|
||||
|
@ -75,6 +76,7 @@ test('calls the update function with proper parameters', async () => {
|
|||
"otherField": false,
|
||||
},
|
||||
"interval": "12s",
|
||||
"name": "abc",
|
||||
"throttle": null,
|
||||
},
|
||||
"id": "1",
|
||||
|
|
|
@ -15,6 +15,7 @@ interface UpdateRequest extends Hapi.Request {
|
|||
};
|
||||
payload: {
|
||||
alertTypeId: string;
|
||||
name: string;
|
||||
interval: string;
|
||||
actions: AlertAction[];
|
||||
alertTypeParams: Record<string, any>;
|
||||
|
@ -36,6 +37,7 @@ export const updateAlertRoute = {
|
|||
throttle: getDurationSchema()
|
||||
.required()
|
||||
.allow(null),
|
||||
name: Joi.string().required(),
|
||||
interval: getDurationSchema().required(),
|
||||
alertTypeParams: Joi.object().required(),
|
||||
actions: Joi.array()
|
||||
|
|
|
@ -60,6 +60,7 @@ export interface RawAlertAction extends SavedObjectAttributes {
|
|||
|
||||
export interface Alert {
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
alertTypeId: string;
|
||||
interval: string;
|
||||
actions: AlertAction[];
|
||||
|
@ -76,6 +77,7 @@ export interface Alert {
|
|||
|
||||
export interface RawAlert extends SavedObjectAttributes {
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
alertTypeId: string;
|
||||
interval: string;
|
||||
actions: RawAlertAction[];
|
||||
|
|
|
@ -124,6 +124,7 @@ export const createSignals = async ({
|
|||
|
||||
return alertsClient.create({
|
||||
data: {
|
||||
name: 'SIEM Alert',
|
||||
alertTypeId: SIGNALS_ID,
|
||||
alertTypeParams: {
|
||||
description,
|
||||
|
|
|
@ -84,6 +84,7 @@ export const updateSignal = async ({
|
|||
return alertsClient.update({
|
||||
id: signal.id,
|
||||
data: {
|
||||
name: 'SIEM Alert',
|
||||
interval: calculateInterval(interval, signal.interval),
|
||||
actions,
|
||||
alertTypeParams: nextAlertTypeParams,
|
||||
|
|
|
@ -178,6 +178,7 @@ export class AlertUtils {
|
|||
}
|
||||
const response = await request.send({
|
||||
enabled: true,
|
||||
name: 'abc',
|
||||
interval: '1m',
|
||||
throttle: '1m',
|
||||
alertTypeId: 'test.always-firing',
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
export function getTestAlertData(overwrites = {}) {
|
||||
return {
|
||||
enabled: true,
|
||||
name: 'abc',
|
||||
alertTypeId: 'test.noop',
|
||||
interval: '10s',
|
||||
throttle: '1m',
|
||||
|
|
|
@ -54,6 +54,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) {
|
|||
objectRemover.add(space.id, response.body.id, 'alert');
|
||||
expect(response.body).to.eql({
|
||||
id: response.body.id,
|
||||
name: 'abc',
|
||||
actions: [],
|
||||
enabled: true,
|
||||
alertTypeId: 'test.noop',
|
||||
|
@ -171,10 +172,10 @@ export default function createAlertTests({ getService }: FtrProviderContext) {
|
|||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message:
|
||||
'child "alertTypeId" fails because ["alertTypeId" is required]. child "interval" fails because ["interval" is required]. child "alertTypeParams" fails because ["alertTypeParams" is required]. child "actions" fails because ["actions" is required]',
|
||||
'child "name" fails because ["name" is required]. child "alertTypeId" fails because ["alertTypeId" is required]. child "interval" fails because ["interval" is required]. child "alertTypeParams" fails because ["alertTypeParams" is required]. child "actions" fails because ["actions" is required]',
|
||||
validation: {
|
||||
source: 'payload',
|
||||
keys: ['alertTypeId', 'interval', 'alertTypeParams', 'actions'],
|
||||
keys: ['name', 'alertTypeId', 'interval', 'alertTypeParams', 'actions'],
|
||||
},
|
||||
});
|
||||
break;
|
||||
|
|
|
@ -56,6 +56,7 @@ export default function createFindTests({ getService }: FtrProviderContext) {
|
|||
const match = response.body.data.find((obj: any) => obj.id === createdAlert.id);
|
||||
expect(match).to.eql({
|
||||
id: createdAlert.id,
|
||||
name: 'abc',
|
||||
alertTypeId: 'test.noop',
|
||||
interval: '10s',
|
||||
enabled: true,
|
||||
|
@ -111,6 +112,7 @@ export default function createFindTests({ getService }: FtrProviderContext) {
|
|||
const match = response.body.data.find((obj: any) => obj.id === createdAlert.id);
|
||||
expect(match).to.eql({
|
||||
id: createdAlert.id,
|
||||
name: 'abc',
|
||||
alertTypeId: 'test.noop',
|
||||
interval: '10s',
|
||||
enabled: true,
|
||||
|
|
|
@ -50,6 +50,7 @@ export default function createGetTests({ getService }: FtrProviderContext) {
|
|||
expect(response.statusCode).to.eql(200);
|
||||
expect(response.body).to.eql({
|
||||
id: createdAlert.id,
|
||||
name: 'abc',
|
||||
alertTypeId: 'test.noop',
|
||||
interval: '10s',
|
||||
enabled: true,
|
||||
|
|
|
@ -31,6 +31,7 @@ export default function createUpdateTests({ getService }: FtrProviderContext) {
|
|||
objectRemover.add(space.id, createdAlert.id, 'alert');
|
||||
|
||||
const updatedData = {
|
||||
name: 'bcd',
|
||||
alertTypeParams: {
|
||||
foo: true,
|
||||
},
|
||||
|
@ -89,6 +90,7 @@ export default function createUpdateTests({ getService }: FtrProviderContext) {
|
|||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send({
|
||||
name: 'bcd',
|
||||
alertTypeParams: {
|
||||
foo: true,
|
||||
},
|
||||
|
@ -134,6 +136,7 @@ export default function createUpdateTests({ getService }: FtrProviderContext) {
|
|||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send({
|
||||
name: 'bcd',
|
||||
throttle: '1m',
|
||||
alertTypeId: '1',
|
||||
alertTypeParams: {
|
||||
|
@ -197,10 +200,10 @@ export default function createUpdateTests({ getService }: FtrProviderContext) {
|
|||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message:
|
||||
'child "throttle" fails because ["throttle" is required]. child "interval" fails because ["interval" is required]. child "alertTypeParams" fails because ["alertTypeParams" is required]. child "actions" fails because ["actions" is required]',
|
||||
'child "throttle" fails because ["throttle" is required]. child "name" fails because ["name" is required]. child "interval" fails because ["interval" is required]. child "alertTypeParams" fails because ["alertTypeParams" is required]. child "actions" fails because ["actions" is required]',
|
||||
validation: {
|
||||
source: 'payload',
|
||||
keys: ['throttle', 'interval', 'alertTypeParams', 'actions'],
|
||||
keys: ['throttle', 'name', 'interval', 'alertTypeParams', 'actions'],
|
||||
},
|
||||
});
|
||||
break;
|
||||
|
@ -229,6 +232,7 @@ export default function createUpdateTests({ getService }: FtrProviderContext) {
|
|||
.set('kbn-xsrf', 'foo')
|
||||
.auth(user.username, user.password)
|
||||
.send({
|
||||
name: 'bcd',
|
||||
interval: '10s',
|
||||
throttle: '1m',
|
||||
alertTypeParams: {},
|
||||
|
|
|
@ -36,6 +36,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) {
|
|||
objectRemover.add(Spaces.space1.id, response.body.id, 'alert');
|
||||
expect(response.body).to.eql({
|
||||
id: response.body.id,
|
||||
name: 'abc',
|
||||
actions: [],
|
||||
enabled: true,
|
||||
alertTypeId: 'test.noop',
|
||||
|
|
|
@ -39,6 +39,7 @@ export default function createFindTests({ getService }: FtrProviderContext) {
|
|||
const match = response.body.data.find((obj: any) => obj.id === createdAlert.id);
|
||||
expect(match).to.eql({
|
||||
id: createdAlert.id,
|
||||
name: 'abc',
|
||||
alertTypeId: 'test.noop',
|
||||
interval: '10s',
|
||||
enabled: true,
|
||||
|
|
|
@ -33,6 +33,7 @@ export default function createGetTests({ getService }: FtrProviderContext) {
|
|||
expect(response.statusCode).to.eql(200);
|
||||
expect(response.body).to.eql({
|
||||
id: createdAlert.id,
|
||||
name: 'abc',
|
||||
alertTypeId: 'test.noop',
|
||||
interval: '10s',
|
||||
enabled: true,
|
||||
|
|
|
@ -26,6 +26,7 @@ export default function createUpdateTests({ getService }: FtrProviderContext) {
|
|||
objectRemover.add(Spaces.space1.id, createdAlert.id, 'alert');
|
||||
|
||||
const updatedData = {
|
||||
name: 'bcd',
|
||||
alertTypeParams: {
|
||||
foo: true,
|
||||
},
|
||||
|
@ -63,6 +64,7 @@ export default function createUpdateTests({ getService }: FtrProviderContext) {
|
|||
.put(`${getUrlPrefix(Spaces.other.id)}/api/alert/${createdAlert.id}`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send({
|
||||
name: 'bcd',
|
||||
alertTypeParams: {
|
||||
foo: true,
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue