mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Allow registered alert types to be non-editable (#65606)
* Allow registered alert types to be non-editable * Fixed isUiEditEnabled values * Fixed due to comments * fixed failing tests * Enable alert type selection per alert consumer, only 'alerting' consumer can display other consumers alert types, but in case if it isEditable * fixed tests * Removed consumer property from the client side alert type registry and added server side property producer which purpose is to manage a feature logic * fixed type check * Fixed tests and type checks * Removed error message for non registered plugins * Fixed failing tests * Fixed due to comments * fixed test * - * revert logic for requiresAppContext * Added close toast after saving alert
This commit is contained in:
parent
fd4074f2cd
commit
5ed5fda832
58 changed files with 332 additions and 22 deletions
|
@ -51,6 +51,7 @@ export function getAlertType(): AlertTypeModel {
|
|||
}
|
||||
return validationResult;
|
||||
},
|
||||
requiresAppContext: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -99,6 +99,7 @@ export function getAlertType(): AlertTypeModel {
|
|||
|
||||
return validationResult;
|
||||
},
|
||||
requiresAppContext: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
import uuid from 'uuid';
|
||||
import { range } from 'lodash';
|
||||
import { AlertType } from '../../../../x-pack/plugins/alerting/server';
|
||||
import { DEFAULT_INSTANCES_TO_GENERATE } from '../../common/constants';
|
||||
import { DEFAULT_INSTANCES_TO_GENERATE, ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
|
||||
|
||||
export const alertType: AlertType = {
|
||||
id: 'example.always-firing',
|
||||
|
@ -43,4 +43,5 @@ export const alertType: AlertType = {
|
|||
count,
|
||||
};
|
||||
},
|
||||
producer: ALERTING_EXAMPLE_APP_ID,
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import axios from 'axios';
|
||||
import { AlertType } from '../../../../x-pack/plugins/alerting/server';
|
||||
import { Operator, Craft } from '../../common/constants';
|
||||
import { Operator, Craft, ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
|
||||
|
||||
interface PeopleInSpace {
|
||||
people: Array<{
|
||||
|
@ -79,4 +79,5 @@ export const alertType: AlertType = {
|
|||
peopleInSpace,
|
||||
};
|
||||
},
|
||||
producer: ALERTING_EXAMPLE_APP_ID,
|
||||
};
|
||||
|
|
|
@ -91,6 +91,7 @@ The following table describes the properties of the `options` object.
|
|||
|actionVariables|An explicit list of action variables the alert type makes available via context and state in action parameter templates, and a short human readable description. Alert UI will use this to display prompts for the users for these variables, in action parameter editors. We highly encourage using `kbn-i18n` to translate the descriptions. |{ context: Array<{name:string, description:string}, state: Array<{name:string, description:string}>|
|
||||
|validate.params|When developing an alert type, you can choose to accept a series of parameters. You may also have the parameters validated before they are passed to the `executor` function or created as an alert saved object. In order to do this, provide a `@kbn/config-schema` schema that we will use to validate the `params` attribute.|@kbn/config-schema|
|
||||
|executor|This is where the code of the alert type lives. This is a function to be called when executing an alert on an interval basis. For full details, see executor section below.|Function|
|
||||
|producer|The id of the application producing this alert type.|string|
|
||||
|
||||
### Executor
|
||||
|
||||
|
@ -212,6 +213,7 @@ server.newPlatform.setup.plugins.alerting.registerType({
|
|||
lastChecked: new Date(),
|
||||
};
|
||||
},
|
||||
producer: 'alerting',
|
||||
});
|
||||
```
|
||||
|
||||
|
@ -287,6 +289,7 @@ server.newPlatform.setup.plugins.alerting.registerType({
|
|||
lastChecked: new Date(),
|
||||
};
|
||||
},
|
||||
producer: 'alerting',
|
||||
});
|
||||
```
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ export interface AlertType {
|
|||
actionGroups: ActionGroup[];
|
||||
actionVariables: string[];
|
||||
defaultActionGroupId: ActionGroup['id'];
|
||||
producer: string;
|
||||
}
|
||||
|
||||
export interface ActionGroup {
|
||||
|
|
|
@ -22,6 +22,7 @@ describe('loadAlertTypes', () => {
|
|||
actionVariables: ['var1'],
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
},
|
||||
];
|
||||
http.get.mockResolvedValueOnce(resolvedValue);
|
||||
|
@ -44,6 +45,7 @@ describe('loadAlertType', () => {
|
|||
actionVariables: ['var1'],
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
http.get.mockResolvedValueOnce([alertType]);
|
||||
|
||||
|
@ -63,6 +65,7 @@ describe('loadAlertType', () => {
|
|||
actionVariables: [],
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
http.get.mockResolvedValueOnce([alertType]);
|
||||
|
||||
|
@ -77,6 +80,7 @@ describe('loadAlertType', () => {
|
|||
actionVariables: [],
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
},
|
||||
]);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ const mockAlertType = (id: string): AlertType => ({
|
|||
actionGroups: [],
|
||||
actionVariables: [],
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
});
|
||||
|
||||
describe('AlertNavigationRegistry', () => {
|
||||
|
|
|
@ -36,6 +36,7 @@ describe('has()', () => {
|
|||
],
|
||||
defaultActionGroupId: 'default',
|
||||
executor: jest.fn(),
|
||||
producer: 'alerting',
|
||||
});
|
||||
expect(registry.has('foo')).toEqual(true);
|
||||
});
|
||||
|
@ -54,6 +55,7 @@ describe('register()', () => {
|
|||
],
|
||||
defaultActionGroupId: 'default',
|
||||
executor: jest.fn(),
|
||||
producer: 'alerting',
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const registry = new AlertTypeRegistry(alertTypeRegistryParams);
|
||||
|
@ -84,6 +86,7 @@ describe('register()', () => {
|
|||
],
|
||||
defaultActionGroupId: 'default',
|
||||
executor: jest.fn(),
|
||||
producer: 'alerting',
|
||||
};
|
||||
const registry = new AlertTypeRegistry(alertTypeRegistryParams);
|
||||
registry.register(alertType);
|
||||
|
@ -104,6 +107,7 @@ describe('register()', () => {
|
|||
],
|
||||
defaultActionGroupId: 'default',
|
||||
executor: jest.fn(),
|
||||
producer: 'alerting',
|
||||
});
|
||||
expect(() =>
|
||||
registry.register({
|
||||
|
@ -117,6 +121,7 @@ describe('register()', () => {
|
|||
],
|
||||
defaultActionGroupId: 'default',
|
||||
executor: jest.fn(),
|
||||
producer: 'alerting',
|
||||
})
|
||||
).toThrowErrorMatchingInlineSnapshot(`"Alert type \\"test\\" is already registered."`);
|
||||
});
|
||||
|
@ -136,6 +141,7 @@ describe('get()', () => {
|
|||
],
|
||||
defaultActionGroupId: 'default',
|
||||
executor: jest.fn(),
|
||||
producer: 'alerting',
|
||||
});
|
||||
const alertType = registry.get('test');
|
||||
expect(alertType).toMatchInlineSnapshot(`
|
||||
|
@ -154,6 +160,7 @@ describe('get()', () => {
|
|||
"executor": [MockFunction],
|
||||
"id": "test",
|
||||
"name": "Test",
|
||||
"producer": "alerting",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -186,6 +193,7 @@ describe('list()', () => {
|
|||
],
|
||||
defaultActionGroupId: 'testActionGroup',
|
||||
executor: jest.fn(),
|
||||
producer: 'alerting',
|
||||
});
|
||||
const result = registry.list();
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
|
@ -204,6 +212,7 @@ describe('list()', () => {
|
|||
"defaultActionGroupId": "testActionGroup",
|
||||
"id": "test",
|
||||
"name": "Test",
|
||||
"producer": "alerting",
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
@ -251,6 +260,7 @@ function alertTypeWithVariables(id: string, context: string, state: string): Ale
|
|||
actionGroups: [],
|
||||
defaultActionGroupId: id,
|
||||
async executor() {},
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
if (!context && !state) {
|
||||
|
|
|
@ -73,6 +73,7 @@ export class AlertTypeRegistry {
|
|||
actionGroups: alertType.actionGroups,
|
||||
defaultActionGroupId: alertType.defaultActionGroupId,
|
||||
actionVariables: alertType.actionVariables,
|
||||
producer: alertType.producer,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@ describe('create()', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
async executor() {},
|
||||
producer: 'alerting',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -539,6 +540,7 @@ describe('create()', () => {
|
|||
}),
|
||||
},
|
||||
async executor() {},
|
||||
producer: 'alerting',
|
||||
});
|
||||
await expect(alertsClient.create({ data })).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"params invalid: [param1]: expected value of type [string] but got [undefined]"`
|
||||
|
@ -1896,6 +1898,7 @@ describe('update()', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
async executor() {},
|
||||
producer: 'alerting',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -2438,6 +2441,7 @@ describe('update()', () => {
|
|||
}),
|
||||
},
|
||||
async executor() {},
|
||||
producer: 'alerting',
|
||||
});
|
||||
await expect(
|
||||
alertsClient.update({
|
||||
|
@ -2669,6 +2673,7 @@ describe('update()', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
async executor() {},
|
||||
producer: 'alerting',
|
||||
});
|
||||
savedObjectsClient.bulkGet.mockResolvedValueOnce({
|
||||
saved_objects: [
|
||||
|
|
|
@ -20,6 +20,7 @@ test('should return passed in params when validation not defined', () => {
|
|||
],
|
||||
defaultActionGroupId: 'default',
|
||||
async executor() {},
|
||||
producer: 'alerting',
|
||||
},
|
||||
{
|
||||
foo: true,
|
||||
|
@ -47,6 +48,7 @@ test('should validate and apply defaults when params is valid', () => {
|
|||
}),
|
||||
},
|
||||
async executor() {},
|
||||
producer: 'alerting',
|
||||
},
|
||||
{ param1: 'value' }
|
||||
);
|
||||
|
@ -75,6 +77,7 @@ test('should validate and throw error when params is invalid', () => {
|
|||
}),
|
||||
},
|
||||
async executor() {},
|
||||
producer: 'alerting',
|
||||
},
|
||||
{}
|
||||
)
|
||||
|
|
|
@ -48,6 +48,7 @@ describe('listAlertTypesRoute', () => {
|
|||
],
|
||||
defaultActionGroupId: 'default',
|
||||
actionVariables: [],
|
||||
producer: 'test',
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -67,6 +68,7 @@ describe('listAlertTypesRoute', () => {
|
|||
"defaultActionGroupId": "default",
|
||||
"id": "1",
|
||||
"name": "name",
|
||||
"producer": "test",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
@ -109,6 +111,7 @@ describe('listAlertTypesRoute', () => {
|
|||
],
|
||||
defaultActionGroupId: 'default',
|
||||
actionVariables: [],
|
||||
producer: 'alerting',
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -158,6 +161,7 @@ describe('listAlertTypesRoute', () => {
|
|||
],
|
||||
defaultActionGroupId: 'default',
|
||||
actionVariables: [],
|
||||
producer: 'alerting',
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ const alertType: AlertType = {
|
|||
],
|
||||
defaultActionGroupId: 'default',
|
||||
executor: jest.fn(),
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
const createExecutionHandlerParams = {
|
||||
|
|
|
@ -25,6 +25,7 @@ const alertType = {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
executor: jest.fn(),
|
||||
producer: 'alerting',
|
||||
};
|
||||
let fakeTimer: sinon.SinonFakeTimers;
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ const alertType = {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
executor: jest.fn(),
|
||||
producer: 'alerting',
|
||||
};
|
||||
let fakeTimer: sinon.SinonFakeTimers;
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ export interface AlertType {
|
|||
actionGroups: ActionGroup[];
|
||||
defaultActionGroupId: ActionGroup['id'];
|
||||
executor: ({ services, params, state }: AlertExecutorOptions) => Promise<State | void>;
|
||||
producer: string;
|
||||
actionVariables?: {
|
||||
context?: ActionVariable[];
|
||||
state?: ActionVariable[];
|
||||
|
|
|
@ -85,6 +85,7 @@ export function getAlertType(service: Service): AlertType {
|
|||
],
|
||||
},
|
||||
executor,
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
async function executor(options: AlertExecutorOptions) {
|
||||
|
|
|
@ -24,7 +24,8 @@ export const ALERT_TYPES_CONFIG = {
|
|||
})
|
||||
}
|
||||
],
|
||||
defaultActionGroupId: 'threshold_met'
|
||||
defaultActionGroupId: 'threshold_met',
|
||||
producer: 'apm'
|
||||
},
|
||||
[AlertType.TransactionDuration]: {
|
||||
name: i18n.translate('xpack.apm.transactionDurationAlert.name', {
|
||||
|
@ -41,7 +42,8 @@ export const ALERT_TYPES_CONFIG = {
|
|||
)
|
||||
}
|
||||
],
|
||||
defaultActionGroupId: 'threshold_met'
|
||||
defaultActionGroupId: 'threshold_met',
|
||||
producer: 'apm'
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -115,7 +115,8 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
|
|||
alertParamsExpression: ErrorRateAlertTrigger,
|
||||
validate: () => ({
|
||||
errors: []
|
||||
})
|
||||
}),
|
||||
requiresAppContext: true
|
||||
});
|
||||
|
||||
plugins.triggers_actions_ui.alertTypeRegistry.register({
|
||||
|
@ -127,7 +128,8 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
|
|||
alertParamsExpression: TransactionDurationAlertTrigger,
|
||||
validate: () => ({
|
||||
errors: []
|
||||
})
|
||||
}),
|
||||
requiresAppContext: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ export function registerErrorRateAlertType({
|
|||
}
|
||||
]
|
||||
},
|
||||
producer: 'apm',
|
||||
executor: async ({ services, params }) => {
|
||||
const config = await config$.pipe(take(1)).toPromise();
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ export function registerTransactionDurationAlertType({
|
|||
}
|
||||
]
|
||||
},
|
||||
producer: 'apm',
|
||||
executor: async ({ services, params }) => {
|
||||
const config = await config$.pipe(take(1)).toPromise();
|
||||
|
||||
|
|
|
@ -30,5 +30,6 @@ Reason:
|
|||
`,
|
||||
}
|
||||
),
|
||||
requiresAppContext: false,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -30,5 +30,6 @@ Current value is \\{\\{context.valueOf.condition0\\}\\}
|
|||
`,
|
||||
}
|
||||
),
|
||||
requiresAppContext: false,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -25,5 +25,6 @@ export function getAlertType(): AlertTypeModel {
|
|||
defaultMessage: `\\{\\{context.matchingDocuments\\}\\} log entries have matched the following conditions: \\{\\{context.conditions\\}\\}`,
|
||||
}
|
||||
),
|
||||
requiresAppContext: false,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ export const registerMetricInventoryThresholdAlertType = (libs: InfraBackendLibs
|
|||
},
|
||||
defaultActionGroupId: FIRED_ACTIONS.id,
|
||||
actionGroups: [FIRED_ACTIONS],
|
||||
producer: 'metrics',
|
||||
executor: curry(createInventoryMetricThresholdExecutor)(libs, uuid.v4()),
|
||||
actionVariables: {
|
||||
context: [
|
||||
|
|
|
@ -86,5 +86,6 @@ export async function registerLogThresholdAlertType(
|
|||
{ name: 'conditions', description: conditionsActionVariableDescription },
|
||||
],
|
||||
},
|
||||
producer: 'logs',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -84,5 +84,6 @@ export function registerMetricThresholdAlertType(libs: InfraBackendLibs) {
|
|||
{ name: 'reason', description: reasonActionVariableDescription },
|
||||
],
|
||||
},
|
||||
producer: 'metrics',
|
||||
};
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ export const getClusterState = (
|
|||
}),
|
||||
},
|
||||
],
|
||||
producer: 'monitoring',
|
||||
defaultActionGroupId: 'default',
|
||||
async executor({
|
||||
services,
|
||||
|
|
|
@ -41,6 +41,7 @@ export const getLicenseExpiration = (
|
|||
},
|
||||
],
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'monitoring',
|
||||
async executor({ services, params, state }: AlertCommonExecutorOptions): Promise<any> {
|
||||
logger.debug(
|
||||
`Firing alert with params: ${JSON.stringify(params)} and state: ${JSON.stringify(state)}`
|
||||
|
|
|
@ -25,6 +25,7 @@ export const rulesNotificationAlertType = ({
|
|||
name: 'SIEM notification',
|
||||
actionGroups: siemRuleActionGroups,
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'siem',
|
||||
validate: {
|
||||
params: schema.object({
|
||||
ruleAlertId: schema.string(),
|
||||
|
|
|
@ -50,6 +50,7 @@ export const signalRulesAlertType = ({
|
|||
validate: {
|
||||
params: signalParamsSchema(),
|
||||
},
|
||||
producer: 'siem',
|
||||
async executor({ previousStartedAt, alertId, services, params }) {
|
||||
const {
|
||||
anomalyThreshold,
|
||||
|
|
|
@ -71,6 +71,7 @@ export function getAlertType(): AlertTypeModel {
|
|||
iconClass: 'alert',
|
||||
alertParamsExpression: lazy(() => import('./index_threshold_expression')),
|
||||
validate: validateAlertType,
|
||||
requiresAppContext: false,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
@ -254,6 +255,7 @@ Each alert type should be defined as `AlertTypeModel` object with the these prop
|
|||
|validate|Validation function for the alert params.|
|
||||
|alertParamsExpression| A lazy loaded React component for building UI of the current alert type params.|
|
||||
|defaultActionMessage|Optional property for providing default message for all added actions with `message` property.|
|
||||
|requiresAppContext|Define if alert type is enabled for create and edit in the alerting management UI.|
|
||||
|
||||
IMPORTANT: The current UI supports a single action group only.
|
||||
Action groups are mapped from the server API result for [GET /api/alert/types: List alert types](https://github.com/elastic/kibana/tree/master/x-pack/legacy/plugins/alerting#get-apialerttypes-list-alert-types).
|
||||
|
@ -267,6 +269,7 @@ export interface AlertType {
|
|||
};
|
||||
actionGroups: string[];
|
||||
executor: ({ services, params, state }: AlertExecutorOptions) => Promise<State | void>;
|
||||
requiresAppContext: boolean;
|
||||
}
|
||||
```
|
||||
Only the default (which means first item of the array) action group is displayed in the current UI.
|
||||
|
@ -313,6 +316,7 @@ export function getAlertType(): AlertTypeModel {
|
|||
alertParamsExpression: lazy(() => import('./expression')),
|
||||
validate: validateExampleAlertType,
|
||||
defaultActionMessage: 'Alert [{{ctx.metadata.name}}] has exceeded the threshold',
|
||||
requiresAppContext: false,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -17,5 +17,6 @@ export function getAlertType(): AlertTypeModel<IndexThresholdAlertParams, Alerts
|
|||
iconClass: 'alert',
|
||||
alertParamsExpression: lazy(() => import('./expression')),
|
||||
validate: validateExpression,
|
||||
requiresAppContext: false,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -183,5 +183,6 @@ function getAlertType(actionVariables: ActionVariables): AlertType {
|
|||
actionVariables,
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ describe('loadAlertTypes', () => {
|
|||
context: [{ name: 'var1', description: 'val1' }],
|
||||
state: [{ name: 'var2', description: 'val2' }],
|
||||
},
|
||||
producer: 'alerting',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
},
|
||||
|
|
|
@ -26,6 +26,7 @@ describe('action_form', () => {
|
|||
return { errors: {} };
|
||||
},
|
||||
alertParamsExpression: () => <Fragment />,
|
||||
requiresAppContext: false,
|
||||
};
|
||||
|
||||
const actionType = {
|
||||
|
|
|
@ -7,7 +7,7 @@ import * as React from 'react';
|
|||
import uuid from 'uuid';
|
||||
import { shallow } from 'enzyme';
|
||||
import { AlertDetails } from './alert_details';
|
||||
import { Alert, ActionType, AlertTypeRegistryContract } from '../../../../types';
|
||||
import { Alert, ActionType, ValidationResult } from '../../../../types';
|
||||
import {
|
||||
EuiTitle,
|
||||
EuiBadge,
|
||||
|
@ -27,17 +27,27 @@ jest.mock('../../../app_context', () => ({
|
|||
http: jest.fn(),
|
||||
capabilities: {
|
||||
get: jest.fn(() => ({})),
|
||||
siem: {
|
||||
'alerting:show': true,
|
||||
'alerting:save': true,
|
||||
'alerting:delete': true,
|
||||
},
|
||||
},
|
||||
actionTypeRegistry: jest.fn(),
|
||||
alertTypeRegistry: jest.fn(() => {
|
||||
const mocked: jest.Mocked<AlertTypeRegistryContract> = {
|
||||
has: jest.fn(),
|
||||
register: jest.fn(),
|
||||
get: jest.fn(),
|
||||
list: jest.fn(),
|
||||
};
|
||||
return mocked;
|
||||
}),
|
||||
alertTypeRegistry: {
|
||||
has: jest.fn().mockReturnValue(true),
|
||||
register: jest.fn(),
|
||||
get: jest.fn().mockReturnValue({
|
||||
id: 'my-alert-type',
|
||||
iconClass: 'test',
|
||||
name: 'test-alert',
|
||||
validate: (): ValidationResult => {
|
||||
return { errors: {} };
|
||||
},
|
||||
requiresAppContext: false,
|
||||
}),
|
||||
list: jest.fn(),
|
||||
},
|
||||
toastNotifications: mockes.notifications.toasts,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
uiSettings: mockes.uiSettings,
|
||||
|
@ -79,6 +89,7 @@ describe('alert_details', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
expect(
|
||||
|
@ -116,6 +127,7 @@ describe('alert_details', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
expect(
|
||||
|
@ -144,6 +156,7 @@ describe('alert_details', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
const actionTypes: ActionType[] = [
|
||||
|
@ -196,6 +209,7 @@ describe('alert_details', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
const actionTypes: ActionType[] = [
|
||||
{
|
||||
|
@ -253,6 +267,7 @@ describe('alert_details', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
expect(
|
||||
|
@ -271,6 +286,7 @@ describe('alert_details', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
expect(
|
||||
|
@ -298,6 +314,7 @@ describe('disable button', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
const enableButton = shallow(
|
||||
|
@ -324,6 +341,7 @@ describe('disable button', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
const enableButton = shallow(
|
||||
|
@ -350,6 +368,7 @@ describe('disable button', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
const disableAlert = jest.fn();
|
||||
|
@ -385,6 +404,7 @@ describe('disable button', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
const enableAlert = jest.fn();
|
||||
|
@ -423,6 +443,7 @@ describe('mute button', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
const enableButton = shallow(
|
||||
|
@ -450,6 +471,7 @@ describe('mute button', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
const enableButton = shallow(
|
||||
|
@ -477,6 +499,7 @@ describe('mute button', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
const muteAlert = jest.fn();
|
||||
|
@ -513,6 +536,7 @@ describe('mute button', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
const unmuteAlert = jest.fn();
|
||||
|
@ -549,6 +573,7 @@ describe('mute button', () => {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
actionVariables: { context: [], state: [] },
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
};
|
||||
|
||||
const enableButton = shallow(
|
||||
|
|
|
@ -72,8 +72,11 @@ export const AlertDetails: React.FunctionComponent<AlertDetailsProps> = ({
|
|||
} = useAppDependencies();
|
||||
|
||||
const canSave = hasSaveAlertsCapability(capabilities);
|
||||
|
||||
const actionTypesByTypeId = indexBy(actionTypes, 'id');
|
||||
const hasEditButton =
|
||||
canSave && alertTypeRegistry.has(alert.alertTypeId)
|
||||
? !alertTypeRegistry.get(alert.alertTypeId).requiresAppContext
|
||||
: false;
|
||||
|
||||
const alertActions = alert.actions;
|
||||
const uniqueActions = Array.from(new Set(alertActions.map((item: any) => item.actionTypeId)));
|
||||
|
@ -113,7 +116,7 @@ export const AlertDetails: React.FunctionComponent<AlertDetailsProps> = ({
|
|||
</EuiPageContentHeaderSection>
|
||||
<EuiPageContentHeaderSection>
|
||||
<EuiFlexGroup responsive={false} gutterSize="xs">
|
||||
{canSave ? (
|
||||
{hasEditButton ? (
|
||||
<EuiFlexItem grow={false}>
|
||||
<Fragment>
|
||||
{' '}
|
||||
|
|
|
@ -71,6 +71,7 @@ describe('alert_add', () => {
|
|||
return { errors: {} };
|
||||
},
|
||||
alertParamsExpression: TestExpression,
|
||||
requiresAppContext: false,
|
||||
};
|
||||
|
||||
const actionTypeModel = {
|
||||
|
|
|
@ -55,6 +55,7 @@ describe('alert_edit', () => {
|
|||
return { errors: {} };
|
||||
},
|
||||
alertParamsExpression: () => <React.Fragment />,
|
||||
requiresAppContext: false,
|
||||
};
|
||||
|
||||
const actionTypeModel = {
|
||||
|
|
|
@ -15,6 +15,10 @@ import { AlertsContextProvider } from '../../context/alerts_context';
|
|||
import { coreMock } from 'src/core/public/mocks';
|
||||
const actionTypeRegistry = actionTypeRegistryMock.create();
|
||||
const alertTypeRegistry = alertTypeRegistryMock.create();
|
||||
jest.mock('../../lib/alert_api', () => ({
|
||||
loadAlertTypes: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('alert_form', () => {
|
||||
let deps: any;
|
||||
const alertType = {
|
||||
|
@ -25,6 +29,7 @@ describe('alert_form', () => {
|
|||
return { errors: {} };
|
||||
},
|
||||
alertParamsExpression: () => <Fragment />,
|
||||
requiresAppContext: false,
|
||||
};
|
||||
|
||||
const actionType = {
|
||||
|
@ -42,6 +47,17 @@ describe('alert_form', () => {
|
|||
actionParamsFields: null,
|
||||
};
|
||||
|
||||
const alertTypeNonEditable = {
|
||||
id: 'non-edit-alert-type',
|
||||
iconClass: 'test',
|
||||
name: 'non edit alert',
|
||||
validate: (): ValidationResult => {
|
||||
return { errors: {} };
|
||||
},
|
||||
alertParamsExpression: () => <Fragment />,
|
||||
requiresAppContext: true,
|
||||
};
|
||||
|
||||
describe('alert_form create alert', () => {
|
||||
let wrapper: ReactWrapper<any>;
|
||||
|
||||
|
@ -61,7 +77,7 @@ describe('alert_form', () => {
|
|||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
capabilities,
|
||||
};
|
||||
alertTypeRegistry.list.mockReturnValue([alertType]);
|
||||
alertTypeRegistry.list.mockReturnValue([alertType, alertTypeNonEditable]);
|
||||
alertTypeRegistry.has.mockReturnValue(true);
|
||||
actionTypeRegistry.list.mockReturnValue([actionType]);
|
||||
actionTypeRegistry.has.mockReturnValue(true);
|
||||
|
@ -118,6 +134,14 @@ describe('alert_form', () => {
|
|||
expect(alertTypeSelectOptions.exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('does not render registered alert type which non editable', async () => {
|
||||
await setup();
|
||||
const alertTypeSelectOptions = wrapper.find(
|
||||
'[data-test-subj="non-edit-alert-type-SelectOption"]'
|
||||
);
|
||||
expect(alertTypeSelectOptions.exists()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('renders registered action types', async () => {
|
||||
await setup();
|
||||
const alertTypeSelectOptions = wrapper.find(
|
||||
|
@ -127,6 +151,134 @@ describe('alert_form', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('alert_form create alert non alerting consumer and producer', () => {
|
||||
let wrapper: ReactWrapper<any>;
|
||||
|
||||
async function setup() {
|
||||
const { loadAlertTypes } = jest.requireMock('../../lib/alert_api');
|
||||
loadAlertTypes.mockResolvedValue([
|
||||
{
|
||||
id: 'other-consumer-producer-alert-type',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
{
|
||||
id: 'testActionGroup',
|
||||
name: 'Test Action Group',
|
||||
},
|
||||
],
|
||||
defaultActionGroupId: 'testActionGroup',
|
||||
producer: 'alerting',
|
||||
},
|
||||
{
|
||||
id: 'same-consumer-producer-alert-type',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
{
|
||||
id: 'testActionGroup',
|
||||
name: 'Test Action Group',
|
||||
},
|
||||
],
|
||||
defaultActionGroupId: 'testActionGroup',
|
||||
producer: 'test',
|
||||
},
|
||||
]);
|
||||
const mocks = coreMock.createSetup();
|
||||
const [
|
||||
{
|
||||
application: { capabilities },
|
||||
},
|
||||
] = await mocks.getStartServices();
|
||||
deps = {
|
||||
toastNotifications: mocks.notifications.toasts,
|
||||
http: mocks.http,
|
||||
uiSettings: mocks.uiSettings,
|
||||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
alertTypeRegistry: alertTypeRegistry as any,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
capabilities,
|
||||
};
|
||||
alertTypeRegistry.list.mockReturnValue([
|
||||
{
|
||||
id: 'same-consumer-producer-alert-type',
|
||||
iconClass: 'test',
|
||||
name: 'test-alert',
|
||||
validate: (): ValidationResult => {
|
||||
return { errors: {} };
|
||||
},
|
||||
alertParamsExpression: () => <Fragment />,
|
||||
requiresAppContext: true,
|
||||
},
|
||||
{
|
||||
id: 'other-consumer-producer-alert-type',
|
||||
iconClass: 'test',
|
||||
name: 'test-alert',
|
||||
validate: (): ValidationResult => {
|
||||
return { errors: {} };
|
||||
},
|
||||
alertParamsExpression: () => <Fragment />,
|
||||
requiresAppContext: false,
|
||||
},
|
||||
]);
|
||||
alertTypeRegistry.has.mockReturnValue(true);
|
||||
|
||||
const initialAlert = ({
|
||||
name: 'non alerting consumer test',
|
||||
params: {},
|
||||
consumer: 'test',
|
||||
schedule: {
|
||||
interval: '1m',
|
||||
},
|
||||
actions: [],
|
||||
tags: [],
|
||||
muteAll: false,
|
||||
enabled: false,
|
||||
mutedInstanceIds: [],
|
||||
} as unknown) as Alert;
|
||||
|
||||
wrapper = mountWithIntl(
|
||||
<AlertsContextProvider
|
||||
value={{
|
||||
reloadAlerts: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
http: deps!.http,
|
||||
docLinks: deps.docLinks,
|
||||
actionTypeRegistry: deps!.actionTypeRegistry,
|
||||
alertTypeRegistry: deps!.alertTypeRegistry,
|
||||
toastNotifications: deps!.toastNotifications,
|
||||
uiSettings: deps!.uiSettings,
|
||||
capabilities: deps!.capabilities,
|
||||
}}
|
||||
>
|
||||
<AlertForm alert={initialAlert} dispatch={() => {}} errors={{ name: [], interval: [] }} />
|
||||
</AlertsContextProvider>
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await nextTick();
|
||||
wrapper.update();
|
||||
});
|
||||
|
||||
expect(loadAlertTypes).toHaveBeenCalled();
|
||||
}
|
||||
|
||||
it('renders alert type options which producer correspond to the alert consumer', async () => {
|
||||
await setup();
|
||||
const alertTypeSelectOptions = wrapper.find(
|
||||
'[data-test-subj="same-consumer-producer-alert-type-SelectOption"]'
|
||||
);
|
||||
expect(alertTypeSelectOptions.exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('does not render alert type options which producer does not correspond to the alert consumer', async () => {
|
||||
await setup();
|
||||
const alertTypeSelectOptions = wrapper.find(
|
||||
'[data-test-subj="other-consumer-producer-alert-type-SelectOption"]'
|
||||
);
|
||||
expect(alertTypeSelectOptions.exists()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('alert_form edit alert', () => {
|
||||
let wrapper: ReactWrapper<any>;
|
||||
|
||||
|
|
|
@ -167,7 +167,21 @@ export const AlertForm = ({
|
|||
? alertTypeModel.alertParamsExpression
|
||||
: null;
|
||||
|
||||
const alertTypeNodes = alertTypeRegistry.list().map(function(item, index) {
|
||||
const alertTypeRegistryList =
|
||||
alert.consumer === 'alerting'
|
||||
? alertTypeRegistry
|
||||
.list()
|
||||
.filter(
|
||||
(alertTypeRegistryItem: AlertTypeModel) => !alertTypeRegistryItem.requiresAppContext
|
||||
)
|
||||
: alertTypeRegistry
|
||||
.list()
|
||||
.filter(
|
||||
(alertTypeRegistryItem: AlertTypeModel) =>
|
||||
alertTypesIndex &&
|
||||
alertTypesIndex[alertTypeRegistryItem.id].producer === alert.consumer
|
||||
);
|
||||
const alertTypeNodes = alertTypeRegistryList.map(function(item, index) {
|
||||
return (
|
||||
<EuiKeyPadMenuItem
|
||||
key={index}
|
||||
|
|
|
@ -44,6 +44,7 @@ const alertType = {
|
|||
return { errors: {} };
|
||||
},
|
||||
alertParamsExpression: () => null,
|
||||
requiresAppContext: false,
|
||||
};
|
||||
alertTypeRegistry.list.mockReturnValue([alertType]);
|
||||
actionTypeRegistry.list.mockReturnValue([]);
|
||||
|
|
|
@ -20,6 +20,7 @@ const getTestAlertType = (id?: string, name?: string, iconClass?: string) => {
|
|||
return { errors: {} };
|
||||
},
|
||||
alertParamsExpression: ExpressionComponent,
|
||||
requiresAppContext: false,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -99,6 +99,7 @@ export interface AlertType {
|
|||
actionGroups: ActionGroup[];
|
||||
actionVariables: ActionVariables;
|
||||
defaultActionGroupId: ActionGroup['id'];
|
||||
producer: string;
|
||||
}
|
||||
|
||||
export type SanitizedAlertType = Omit<AlertType, 'apiKey'>;
|
||||
|
@ -132,6 +133,7 @@ export interface AlertTypeModel<AlertParamsType = any, AlertsContextValue = any>
|
|||
| React.LazyExoticComponent<
|
||||
ComponentType<AlertTypeParamsExpressionProps<AlertParamsType, AlertsContextValue>>
|
||||
>;
|
||||
requiresAppContext: boolean;
|
||||
defaultActionMessage?: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,6 +175,7 @@ describe('monitor status alert type', () => {
|
|||
"iconClass": "uptimeApp",
|
||||
"id": "xpack.uptime.alerts.monitorStatus",
|
||||
"name": <MonitorStatusTitle />,
|
||||
"requiresAppContext": true,
|
||||
"validate": [Function],
|
||||
}
|
||||
`);
|
||||
|
|
|
@ -68,4 +68,5 @@ export const initMonitorStatusAlertType: AlertTypeInitializer = ({
|
|||
),
|
||||
validate,
|
||||
defaultActionMessage,
|
||||
requiresAppContext: true,
|
||||
});
|
||||
|
|
|
@ -20,4 +20,5 @@ export const initTlsAlertType: AlertTypeInitializer = (): AlertTypeModel => ({
|
|||
name,
|
||||
validate: () => ({ errors: {} }),
|
||||
defaultActionMessage,
|
||||
requiresAppContext: true,
|
||||
});
|
||||
|
|
|
@ -171,6 +171,7 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = (_server, libs) =
|
|||
],
|
||||
state: [...commonStateTranslations],
|
||||
},
|
||||
producer: 'uptime',
|
||||
async executor(options: AlertExecutorOptions) {
|
||||
const { params: rawParams } = options;
|
||||
const decoded = StatusCheckExecutorParamsType.decode(rawParams);
|
||||
|
|
|
@ -100,6 +100,7 @@ export const tlsAlertFactory: UptimeAlertTypeFactory = (_server, libs) => ({
|
|||
context: [],
|
||||
state: [...tlsTranslations.actionVariables, ...commonStateTranslations],
|
||||
},
|
||||
producer: 'uptime',
|
||||
async executor(options) {
|
||||
const {
|
||||
services: { alertInstanceFactory, callCluster, savedObjectsClient },
|
||||
|
|
|
@ -245,6 +245,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
{ id: 'default', name: 'Default' },
|
||||
{ id: 'other', name: 'Other' },
|
||||
],
|
||||
producer: 'alerting',
|
||||
defaultActionGroupId: 'default',
|
||||
actionVariables: {
|
||||
state: [{ name: 'instanceStateValue', description: 'the instance state value' }],
|
||||
|
@ -304,6 +305,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
{ id: 'default', name: 'Default' },
|
||||
{ id: 'other', name: 'Other' },
|
||||
],
|
||||
producer: 'alerting',
|
||||
defaultActionGroupId: 'default',
|
||||
async executor(alertExecutorOptions: AlertExecutorOptions) {
|
||||
const { services, state } = alertExecutorOptions;
|
||||
|
@ -332,6 +334,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
name: 'Default',
|
||||
},
|
||||
],
|
||||
producer: 'alerting',
|
||||
defaultActionGroupId: 'default',
|
||||
async executor({ services, params, state }: AlertExecutorOptions) {
|
||||
await services.callCluster('index', {
|
||||
|
@ -358,6 +361,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
name: 'Default',
|
||||
},
|
||||
],
|
||||
producer: 'alerting',
|
||||
defaultActionGroupId: 'default',
|
||||
async executor({ services, params, state }: AlertExecutorOptions) {
|
||||
await services.callCluster('index', {
|
||||
|
@ -383,6 +387,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
},
|
||||
],
|
||||
defaultActionGroupId: 'default',
|
||||
producer: 'alerting',
|
||||
validate: {
|
||||
params: schema.object({
|
||||
callClusterAuthorizationIndex: schema.string(),
|
||||
|
@ -465,6 +470,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
name: 'Default',
|
||||
},
|
||||
],
|
||||
producer: 'alerting',
|
||||
defaultActionGroupId: 'default',
|
||||
validate: {
|
||||
params: schema.object({
|
||||
|
@ -477,6 +483,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
id: 'test.noop',
|
||||
name: 'Test: Noop',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
producer: 'alerting',
|
||||
defaultActionGroupId: 'default',
|
||||
async executor({ services, params, state }: AlertExecutorOptions) {},
|
||||
};
|
||||
|
@ -484,6 +491,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
id: 'test.onlyContextVariables',
|
||||
name: 'Test: Only Context Variables',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
producer: 'alerting',
|
||||
defaultActionGroupId: 'default',
|
||||
actionVariables: {
|
||||
context: [{ name: 'aContextVariable', description: 'this is a context variable' }],
|
||||
|
@ -494,6 +502,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
id: 'test.onlyStateVariables',
|
||||
name: 'Test: Only State Variables',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
producer: 'alerting',
|
||||
defaultActionGroupId: 'default',
|
||||
actionVariables: {
|
||||
state: [{ name: 'aStateVariable', description: 'this is a state variable' }],
|
||||
|
|
|
@ -48,6 +48,7 @@ export default function listAlertTypes({ getService }: FtrProviderContext) {
|
|||
state: [],
|
||||
context: [],
|
||||
},
|
||||
producer: 'alerting',
|
||||
});
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -27,6 +27,7 @@ export default function listAlertTypes({ getService }: FtrProviderContext) {
|
|||
state: [],
|
||||
context: [],
|
||||
},
|
||||
producer: 'alerting',
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
|
||||
it('can save alert', async () => {
|
||||
await alerts.clickSaveAlertButton();
|
||||
await pageObjects.common.closeToast();
|
||||
});
|
||||
|
||||
it('posts an alert, verifies its presence, and deletes the alert', async () => {
|
||||
|
@ -171,6 +172,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
|
||||
it('can save alert', async () => {
|
||||
await alerts.clickSaveAlertButton();
|
||||
await pageObjects.common.closeToast();
|
||||
});
|
||||
|
||||
it('has created a valid alert with expected parameters', async () => {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"version": "1.0.0",
|
||||
"kibanaVersion": "kibana",
|
||||
"configPath": ["xpack"],
|
||||
"requiredPlugins": ["alerting"],
|
||||
"requiredPlugins": ["alerting", "triggers_actions_ui"],
|
||||
"server": true,
|
||||
"ui": true
|
||||
}
|
||||
|
|
|
@ -4,25 +4,50 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public';
|
||||
import { PluginSetupContract as AlertingSetup } from '../../../../../../plugins/alerting/public';
|
||||
import { AlertType, SanitizedAlert } from '../../../../../../plugins/alerting/common';
|
||||
import { TriggersAndActionsUIPublicPluginSetup } from '../../../../../../plugins/triggers_actions_ui/public';
|
||||
|
||||
export type Setup = void;
|
||||
export type Start = void;
|
||||
|
||||
export interface AlertingExamplePublicSetupDeps {
|
||||
alerting: AlertingSetup;
|
||||
triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup;
|
||||
}
|
||||
|
||||
export class AlertingFixturePlugin implements Plugin<Setup, Start, AlertingExamplePublicSetupDeps> {
|
||||
public setup(core: CoreSetup, { alerting }: AlertingExamplePublicSetupDeps) {
|
||||
public setup(core: CoreSetup, { alerting, triggers_actions_ui }: AlertingExamplePublicSetupDeps) {
|
||||
alerting.registerNavigation(
|
||||
'consumer-noop',
|
||||
'test.noop',
|
||||
(alert: SanitizedAlert, alertType: AlertType) => `/alert/${alert.id}`
|
||||
);
|
||||
|
||||
triggers_actions_ui.alertTypeRegistry.register({
|
||||
id: 'test.always-firing',
|
||||
name: 'Test Always Firing',
|
||||
iconClass: 'alert',
|
||||
alertParamsExpression: () => React.createElement('div', null, 'Test Always Firing'),
|
||||
validate: () => {
|
||||
return { errors: {} };
|
||||
},
|
||||
requiresAppContext: false,
|
||||
});
|
||||
|
||||
triggers_actions_ui.alertTypeRegistry.register({
|
||||
id: 'test.noop',
|
||||
name: 'Test Noop',
|
||||
iconClass: 'alert',
|
||||
alertParamsExpression: () => React.createElement('div', null, 'Test Noop'),
|
||||
validate: () => {
|
||||
return { errors: {} };
|
||||
},
|
||||
requiresAppContext: false,
|
||||
});
|
||||
|
||||
core.application.register({
|
||||
id: 'consumer-noop',
|
||||
title: 'No Op App',
|
||||
|
|
|
@ -32,6 +32,7 @@ function createNoopAlertType(alerting: AlertingSetup) {
|
|||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
async executor() {},
|
||||
producer: 'alerting',
|
||||
};
|
||||
alerting.registerType(noopAlertType);
|
||||
}
|
||||
|
@ -45,6 +46,7 @@ function createAlwaysFiringAlertType(alerting: AlertingSetup) {
|
|||
{ id: 'default', name: 'Default' },
|
||||
{ id: 'other', name: 'Other' },
|
||||
],
|
||||
producer: 'alerting',
|
||||
async executor(alertExecutorOptions: any) {
|
||||
const { services, state, params } = alertExecutorOptions;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue