From 5ed5fda8320f9b966645cf9e888c77822315b5f5 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Tue, 12 May 2020 13:38:22 -0700 Subject: [PATCH] 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 --- .../public/alert_types/always_firing.tsx | 1 + .../public/alert_types/astros.tsx | 1 + .../server/alert_types/always_firing.ts | 3 +- .../server/alert_types/astros.ts | 3 +- x-pack/plugins/alerting/README.md | 3 + x-pack/plugins/alerting/common/alert_type.ts | 1 + .../plugins/alerting/public/alert_api.test.ts | 4 + .../alert_navigation_registry.test.ts | 1 + .../server/alert_type_registry.test.ts | 10 ++ .../alerting/server/alert_type_registry.ts | 1 + .../alerting/server/alerts_client.test.ts | 5 + .../lib/validate_alert_type_params.test.ts | 3 + .../server/routes/list_alert_types.test.ts | 4 + .../create_execution_handler.test.ts | 1 + .../server/task_runner/task_runner.test.ts | 1 + .../task_runner/task_runner_factory.test.ts | 1 + x-pack/plugins/alerting/server/types.ts | 1 + .../alert_types/index_threshold/alert_type.ts | 1 + x-pack/plugins/apm/common/alert_types.ts | 6 +- x-pack/plugins/apm/public/plugin.ts | 6 +- .../alerts/register_error_rate_alert_type.ts | 1 + ...egister_transaction_duration_alert_type.ts | 1 + .../public/alerting/metric_threshold/index.ts | 1 + .../metric_inventory_threshold_alert_type.ts | 1 + .../alerting/logs/log_threshold_alert_type.ts | 1 + ...r_inventory_metric_threshold_alert_type.ts | 1 + .../register_log_threshold_alert_type.ts | 1 + .../register_metric_threshold_alert_type.ts | 1 + .../monitoring/server/alerts/cluster_state.ts | 1 + .../server/alerts/license_expiration.ts | 1 + .../rules_notification_alert_type.ts | 1 + .../signals/signal_rule_alert_type.ts | 1 + x-pack/plugins/triggers_actions_ui/README.md | 4 + .../builtin_alert_types/threshold/index.ts | 1 + .../application/lib/action_variables.test.ts | 1 + .../public/application/lib/alert_api.test.ts | 1 + .../action_form.test.tsx | 1 + .../components/alert_details.test.tsx | 45 +++-- .../components/alert_details.tsx | 7 +- .../sections/alert_form/alert_add.test.tsx | 1 + .../sections/alert_form/alert_edit.test.tsx | 1 + .../sections/alert_form/alert_form.test.tsx | 154 +++++++++++++++++- .../sections/alert_form/alert_form.tsx | 16 +- .../components/alerts_list.test.tsx | 1 + .../public/application/type_registry.test.ts | 1 + .../triggers_actions_ui/public/types.ts | 2 + .../__tests__/monitor_status.test.ts | 1 + .../public/lib/alert_types/monitor_status.tsx | 1 + .../uptime/public/lib/alert_types/tls.tsx | 1 + .../uptime/server/lib/alerts/status_check.ts | 1 + .../plugins/uptime/server/lib/alerts/tls.ts | 1 + .../fixtures/plugins/alerts/server/plugin.ts | 9 + .../tests/alerting/list_alert_types.ts | 1 + .../tests/alerting/list_alert_types.ts | 1 + .../apps/uptime/alert_flyout.ts | 2 + .../fixtures/plugins/alerts/kibana.json | 2 +- .../fixtures/plugins/alerts/public/plugin.ts | 27 ++- .../fixtures/plugins/alerts/server/plugin.ts | 2 + 58 files changed, 332 insertions(+), 22 deletions(-) diff --git a/examples/alerting_example/public/alert_types/always_firing.tsx b/examples/alerting_example/public/alert_types/always_firing.tsx index a62a24365ea3..b7add1f6d43c 100644 --- a/examples/alerting_example/public/alert_types/always_firing.tsx +++ b/examples/alerting_example/public/alert_types/always_firing.tsx @@ -51,6 +51,7 @@ export function getAlertType(): AlertTypeModel { } return validationResult; }, + requiresAppContext: false, }; } diff --git a/examples/alerting_example/public/alert_types/astros.tsx b/examples/alerting_example/public/alert_types/astros.tsx index 9bda7da6f140..3411c6722ccd 100644 --- a/examples/alerting_example/public/alert_types/astros.tsx +++ b/examples/alerting_example/public/alert_types/astros.tsx @@ -99,6 +99,7 @@ export function getAlertType(): AlertTypeModel { return validationResult; }, + requiresAppContext: false, }; } diff --git a/examples/alerting_example/server/alert_types/always_firing.ts b/examples/alerting_example/server/alert_types/always_firing.ts index f0553ad5ebeb..dfee379013eb 100644 --- a/examples/alerting_example/server/alert_types/always_firing.ts +++ b/examples/alerting_example/server/alert_types/always_firing.ts @@ -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, }; diff --git a/examples/alerting_example/server/alert_types/astros.ts b/examples/alerting_example/server/alert_types/astros.ts index 3a53f85e6a26..d22bc6164fa5 100644 --- a/examples/alerting_example/server/alert_types/astros.ts +++ b/examples/alerting_example/server/alert_types/astros.ts @@ -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, }; diff --git a/x-pack/plugins/alerting/README.md b/x-pack/plugins/alerting/README.md index d15b5f4ce45c..dfa299189542 100644 --- a/x-pack/plugins/alerting/README.md +++ b/x-pack/plugins/alerting/README.md @@ -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', }); ``` diff --git a/x-pack/plugins/alerting/common/alert_type.ts b/x-pack/plugins/alerting/common/alert_type.ts index b30cf3fa1851..f07555c33407 100644 --- a/x-pack/plugins/alerting/common/alert_type.ts +++ b/x-pack/plugins/alerting/common/alert_type.ts @@ -10,6 +10,7 @@ export interface AlertType { actionGroups: ActionGroup[]; actionVariables: string[]; defaultActionGroupId: ActionGroup['id']; + producer: string; } export interface ActionGroup { diff --git a/x-pack/plugins/alerting/public/alert_api.test.ts b/x-pack/plugins/alerting/public/alert_api.test.ts index a1a90f7c893a..1149e6fc249a 100644 --- a/x-pack/plugins/alerting/public/alert_api.test.ts +++ b/x-pack/plugins/alerting/public/alert_api.test.ts @@ -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', }, ]); diff --git a/x-pack/plugins/alerting/public/alert_navigation_registry/alert_navigation_registry.test.ts b/x-pack/plugins/alerting/public/alert_navigation_registry/alert_navigation_registry.test.ts index 439ee9e818ef..ff8a3a1c311c 100644 --- a/x-pack/plugins/alerting/public/alert_navigation_registry/alert_navigation_registry.test.ts +++ b/x-pack/plugins/alerting/public/alert_navigation_registry/alert_navigation_registry.test.ts @@ -16,6 +16,7 @@ const mockAlertType = (id: string): AlertType => ({ actionGroups: [], actionVariables: [], defaultActionGroupId: 'default', + producer: 'alerting', }); describe('AlertNavigationRegistry', () => { diff --git a/x-pack/plugins/alerting/server/alert_type_registry.test.ts b/x-pack/plugins/alerting/server/alert_type_registry.test.ts index f55628770334..e78e5ab7932c 100644 --- a/x-pack/plugins/alerting/server/alert_type_registry.test.ts +++ b/x-pack/plugins/alerting/server/alert_type_registry.test.ts @@ -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) { diff --git a/x-pack/plugins/alerting/server/alert_type_registry.ts b/x-pack/plugins/alerting/server/alert_type_registry.ts index 8bcb4d838ca1..0163cb71166e 100644 --- a/x-pack/plugins/alerting/server/alert_type_registry.ts +++ b/x-pack/plugins/alerting/server/alert_type_registry.ts @@ -73,6 +73,7 @@ export class AlertTypeRegistry { actionGroups: alertType.actionGroups, defaultActionGroupId: alertType.defaultActionGroupId, actionVariables: alertType.actionVariables, + producer: alertType.producer, })); } } diff --git a/x-pack/plugins/alerting/server/alerts_client.test.ts b/x-pack/plugins/alerting/server/alerts_client.test.ts index 6c7b93aa6400..6601ccc4f5a7 100644 --- a/x-pack/plugins/alerting/server/alerts_client.test.ts +++ b/x-pack/plugins/alerting/server/alerts_client.test.ts @@ -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: [ diff --git a/x-pack/plugins/alerting/server/lib/validate_alert_type_params.test.ts b/x-pack/plugins/alerting/server/lib/validate_alert_type_params.test.ts index 67820e44f567..d31b15030fd3 100644 --- a/x-pack/plugins/alerting/server/lib/validate_alert_type_params.test.ts +++ b/x-pack/plugins/alerting/server/lib/validate_alert_type_params.test.ts @@ -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', }, {} ) diff --git a/x-pack/plugins/alerting/server/routes/list_alert_types.test.ts b/x-pack/plugins/alerting/server/routes/list_alert_types.test.ts index 37b52f1ec792..e940b2d10204 100644 --- a/x-pack/plugins/alerting/server/routes/list_alert_types.test.ts +++ b/x-pack/plugins/alerting/server/routes/list_alert_types.test.ts @@ -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', }, ]; diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts index a564b87f2ca5..ceae9f04fe5a 100644 --- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts @@ -19,6 +19,7 @@ const alertType: AlertType = { ], defaultActionGroupId: 'default', executor: jest.fn(), + producer: 'alerting', }; const createExecutionHandlerParams = { diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index 35a0018049c3..e5ec8f587b9d 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -25,6 +25,7 @@ const alertType = { actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', executor: jest.fn(), + producer: 'alerting', }; let fakeTimer: sinon.SinonFakeTimers; diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts index 563664d3544a..96d89bebcc66 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts @@ -19,6 +19,7 @@ const alertType = { actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', executor: jest.fn(), + producer: 'alerting', }; let fakeTimer: sinon.SinonFakeTimers; diff --git a/x-pack/plugins/alerting/server/types.ts b/x-pack/plugins/alerting/server/types.ts index b733b23dd71e..d0070eb9a299 100644 --- a/x-pack/plugins/alerting/server/types.ts +++ b/x-pack/plugins/alerting/server/types.ts @@ -78,6 +78,7 @@ export interface AlertType { actionGroups: ActionGroup[]; defaultActionGroupId: ActionGroup['id']; executor: ({ services, params, state }: AlertExecutorOptions) => Promise; + producer: string; actionVariables?: { context?: ActionVariable[]; state?: ActionVariable[]; diff --git a/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/alert_type.ts b/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/alert_type.ts index 4d79efc7c947..1a5da8a422b9 100644 --- a/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/alert_type.ts +++ b/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/alert_type.ts @@ -85,6 +85,7 @@ export function getAlertType(service: Service): AlertType { ], }, executor, + producer: 'alerting', }; async function executor(options: AlertExecutorOptions) { diff --git a/x-pack/plugins/apm/common/alert_types.ts b/x-pack/plugins/apm/common/alert_types.ts index 8a342fab71e6..6638c2dd8baf 100644 --- a/x-pack/plugins/apm/common/alert_types.ts +++ b/x-pack/plugins/apm/common/alert_types.ts @@ -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' } }; diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts index 6ac2ecaae2b7..38076c9ee48e 100644 --- a/x-pack/plugins/apm/public/plugin.ts +++ b/x-pack/plugins/apm/public/plugin.ts @@ -115,7 +115,8 @@ export class ApmPlugin implements Plugin { alertParamsExpression: ErrorRateAlertTrigger, validate: () => ({ errors: [] - }) + }), + requiresAppContext: true }); plugins.triggers_actions_ui.alertTypeRegistry.register({ @@ -127,7 +128,8 @@ export class ApmPlugin implements Plugin { alertParamsExpression: TransactionDurationAlertTrigger, validate: () => ({ errors: [] - }) + }), + requiresAppContext: true }); } } diff --git a/x-pack/plugins/apm/server/lib/alerts/register_error_rate_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_error_rate_alert_type.ts index d6242507e401..db5c1fd45546 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_error_rate_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_error_rate_alert_type.ts @@ -60,6 +60,7 @@ export function registerErrorRateAlertType({ } ] }, + producer: 'apm', executor: async ({ services, params }) => { const config = await config$.pipe(take(1)).toPromise(); diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts index 2799da16cf6a..8ef881710b9f 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts @@ -74,6 +74,7 @@ export function registerTransactionDurationAlertType({ } ] }, + producer: 'apm', executor: async ({ services, params }) => { const config = await config$.pipe(take(1)).toPromise(); diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/index.ts b/x-pack/plugins/infra/public/alerting/metric_threshold/index.ts index 91b9bafad501..a40cb1eaec50 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/index.ts +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/index.ts @@ -30,5 +30,6 @@ Reason: `, } ), + requiresAppContext: false, }; } diff --git a/x-pack/plugins/infra/public/components/alerting/inventory/metric_inventory_threshold_alert_type.ts b/x-pack/plugins/infra/public/components/alerting/inventory/metric_inventory_threshold_alert_type.ts index b7abaf5b3637..9ede2d2a4772 100644 --- a/x-pack/plugins/infra/public/components/alerting/inventory/metric_inventory_threshold_alert_type.ts +++ b/x-pack/plugins/infra/public/components/alerting/inventory/metric_inventory_threshold_alert_type.ts @@ -30,5 +30,6 @@ Current value is \\{\\{context.valueOf.condition0\\}\\} `, } ), + requiresAppContext: false, }; } diff --git a/x-pack/plugins/infra/public/components/alerting/logs/log_threshold_alert_type.ts b/x-pack/plugins/infra/public/components/alerting/logs/log_threshold_alert_type.ts index 18126ec58369..9bba8bd804f8 100644 --- a/x-pack/plugins/infra/public/components/alerting/logs/log_threshold_alert_type.ts +++ b/x-pack/plugins/infra/public/components/alerting/logs/log_threshold_alert_type.ts @@ -25,5 +25,6 @@ export function getAlertType(): AlertTypeModel { defaultMessage: `\\{\\{context.matchingDocuments\\}\\} log entries have matched the following conditions: \\{\\{context.conditions\\}\\}`, } ), + requiresAppContext: false, }; } diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts index 71cde0175bef..e23dfed448c5 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts @@ -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: [ diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_alert_type.ts index 04207a4233df..cdb4d2d96847 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_alert_type.ts @@ -86,5 +86,6 @@ export async function registerLogThresholdAlertType( { name: 'conditions', description: conditionsActionVariableDescription }, ], }, + producer: 'logs', }); } diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts index e40cee1b9dda..c1c530131f3a 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts @@ -84,5 +84,6 @@ export function registerMetricThresholdAlertType(libs: InfraBackendLibs) { { name: 'reason', description: reasonActionVariableDescription }, ], }, + producer: 'metrics', }; } diff --git a/x-pack/plugins/monitoring/server/alerts/cluster_state.ts b/x-pack/plugins/monitoring/server/alerts/cluster_state.ts index 9a5805b8af7c..6567d1c6def3 100644 --- a/x-pack/plugins/monitoring/server/alerts/cluster_state.ts +++ b/x-pack/plugins/monitoring/server/alerts/cluster_state.ts @@ -38,6 +38,7 @@ export const getClusterState = ( }), }, ], + producer: 'monitoring', defaultActionGroupId: 'default', async executor({ services, diff --git a/x-pack/plugins/monitoring/server/alerts/license_expiration.ts b/x-pack/plugins/monitoring/server/alerts/license_expiration.ts index 2e5356150086..00402bca57a7 100644 --- a/x-pack/plugins/monitoring/server/alerts/license_expiration.ts +++ b/x-pack/plugins/monitoring/server/alerts/license_expiration.ts @@ -41,6 +41,7 @@ export const getLicenseExpiration = ( }, ], defaultActionGroupId: 'default', + producer: 'monitoring', async executor({ services, params, state }: AlertCommonExecutorOptions): Promise { logger.debug( `Firing alert with params: ${JSON.stringify(params)} and state: ${JSON.stringify(state)}` diff --git a/x-pack/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.ts b/x-pack/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.ts index e4ad53de742d..5a2a950f21bc 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.ts +++ b/x-pack/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.ts @@ -25,6 +25,7 @@ export const rulesNotificationAlertType = ({ name: 'SIEM notification', actionGroups: siemRuleActionGroups, defaultActionGroupId: 'default', + producer: 'siem', validate: { params: schema.object({ ruleAlertId: schema.string(), diff --git a/x-pack/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts index 6160f34faef3..e7d58eaf0c82 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -50,6 +50,7 @@ export const signalRulesAlertType = ({ validate: { params: signalParamsSchema(), }, + producer: 'siem', async executor({ previousStartedAt, alertId, services, params }) { const { anomalyThreshold, diff --git a/x-pack/plugins/triggers_actions_ui/README.md b/x-pack/plugins/triggers_actions_ui/README.md index 0ed6917854dc..b07413ae73ee 100644 --- a/x-pack/plugins/triggers_actions_ui/README.md +++ b/x-pack/plugins/triggers_actions_ui/README.md @@ -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; + 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, }; } ``` diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts index 42747b9e85e2..d7ce73ce0c7d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts @@ -17,5 +17,6 @@ export function getAlertType(): AlertTypeModel import('./expression')), validate: validateExpression, + requiresAppContext: false, }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.test.ts index 3ed8bc7ba625..578c93fc4cba 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.test.ts @@ -183,5 +183,6 @@ function getAlertType(actionVariables: ActionVariables): AlertType { actionVariables, actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + producer: 'alerting', }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api.test.ts index b830ac471c4d..f384a78e2e08 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api.test.ts @@ -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', }, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.test.tsx index 931fde430c60..df7d1e64c8e9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.test.tsx @@ -26,6 +26,7 @@ describe('action_form', () => { return { errors: {} }; }, alertParamsExpression: () => , + requiresAppContext: false, }; const actionType = { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx index 4132ed6ed2a8..99a059e475a9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx @@ -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 = { - 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( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx index 8511ab468ca8..3a25417f7db4 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx @@ -72,8 +72,11 @@ export const AlertDetails: React.FunctionComponent = ({ } = 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 = ({ - {canSave ? ( + {hasEditButton ? ( {' '} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx index bebbcdda10a0..2d0703432097 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx @@ -71,6 +71,7 @@ describe('alert_add', () => { return { errors: {} }; }, alertParamsExpression: TestExpression, + requiresAppContext: false, }; const actionTypeModel = { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.test.tsx index 39112a150958..cab4e022f7d3 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.test.tsx @@ -55,6 +55,7 @@ describe('alert_edit', () => { return { errors: {} }; }, alertParamsExpression: () => , + requiresAppContext: false, }; const actionTypeModel = { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.test.tsx index 02bd65043332..ed36bc6c8d58 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.test.tsx @@ -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: () => , + 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: () => , + requiresAppContext: true, + }; + describe('alert_form create alert', () => { let wrapper: ReactWrapper; @@ -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; + + 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: () => , + requiresAppContext: true, + }, + { + id: 'other-consumer-producer-alert-type', + iconClass: 'test', + name: 'test-alert', + validate: (): ValidationResult => { + return { errors: {} }; + }, + alertParamsExpression: () => , + 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( + { + return new Promise(() => {}); + }, + http: deps!.http, + docLinks: deps.docLinks, + actionTypeRegistry: deps!.actionTypeRegistry, + alertTypeRegistry: deps!.alertTypeRegistry, + toastNotifications: deps!.toastNotifications, + uiSettings: deps!.uiSettings, + capabilities: deps!.capabilities, + }} + > + {}} errors={{ name: [], interval: [] }} /> + + ); + + 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; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.tsx index e956c8ecc4f3..7ffc9e6a79a2 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.tsx @@ -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 ( null, + requiresAppContext: false, }; alertTypeRegistry.list.mockReturnValue([alertType]); actionTypeRegistry.list.mockReturnValue([]); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/type_registry.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/type_registry.test.ts index 62173a6196b9..10195e925611 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/type_registry.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/type_registry.test.ts @@ -20,6 +20,7 @@ const getTestAlertType = (id?: string, name?: string, iconClass?: string) => { return { errors: {} }; }, alertParamsExpression: ExpressionComponent, + requiresAppContext: false, }; }; diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index e9cfd5b33db2..11152c56c49e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -99,6 +99,7 @@ export interface AlertType { actionGroups: ActionGroup[]; actionVariables: ActionVariables; defaultActionGroupId: ActionGroup['id']; + producer: string; } export type SanitizedAlertType = Omit; @@ -132,6 +133,7 @@ export interface AlertTypeModel | React.LazyExoticComponent< ComponentType> >; + requiresAppContext: boolean; defaultActionMessage?: string; } diff --git a/x-pack/plugins/uptime/public/lib/alert_types/__tests__/monitor_status.test.ts b/x-pack/plugins/uptime/public/lib/alert_types/__tests__/monitor_status.test.ts index 0d18facaa5bb..b06a7cc93f62 100644 --- a/x-pack/plugins/uptime/public/lib/alert_types/__tests__/monitor_status.test.ts +++ b/x-pack/plugins/uptime/public/lib/alert_types/__tests__/monitor_status.test.ts @@ -175,6 +175,7 @@ describe('monitor status alert type', () => { "iconClass": "uptimeApp", "id": "xpack.uptime.alerts.monitorStatus", "name": , + "requiresAppContext": true, "validate": [Function], } `); diff --git a/x-pack/plugins/uptime/public/lib/alert_types/monitor_status.tsx b/x-pack/plugins/uptime/public/lib/alert_types/monitor_status.tsx index 65827867da5e..bba7907d79c5 100644 --- a/x-pack/plugins/uptime/public/lib/alert_types/monitor_status.tsx +++ b/x-pack/plugins/uptime/public/lib/alert_types/monitor_status.tsx @@ -68,4 +68,5 @@ export const initMonitorStatusAlertType: AlertTypeInitializer = ({ ), validate, defaultActionMessage, + requiresAppContext: true, }); diff --git a/x-pack/plugins/uptime/public/lib/alert_types/tls.tsx b/x-pack/plugins/uptime/public/lib/alert_types/tls.tsx index 0a5c09acbb69..5e1b8cf233d7 100644 --- a/x-pack/plugins/uptime/public/lib/alert_types/tls.tsx +++ b/x-pack/plugins/uptime/public/lib/alert_types/tls.tsx @@ -20,4 +20,5 @@ export const initTlsAlertType: AlertTypeInitializer = (): AlertTypeModel => ({ name, validate: () => ({ errors: {} }), defaultActionMessage, + requiresAppContext: true, }); diff --git a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts index 0eaa12e8f437..17479bb451b1 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts @@ -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); diff --git a/x-pack/plugins/uptime/server/lib/alerts/tls.ts b/x-pack/plugins/uptime/server/lib/alerts/tls.ts index 5728db8bfcc8..c4464ff57521 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/tls.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/tls.ts @@ -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 }, diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/plugin.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/plugin.ts index 347695dd12be..663e64811904 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/plugin.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/plugin.ts @@ -245,6 +245,7 @@ export class FixturePlugin implements Plugin { 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 () => { diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/kibana.json b/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/kibana.json index f072937c4b12..1715f30b8226 100644 --- a/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/kibana.json +++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/kibana.json @@ -3,7 +3,7 @@ "version": "1.0.0", "kibanaVersion": "kibana", "configPath": ["xpack"], - "requiredPlugins": ["alerting"], + "requiredPlugins": ["alerting", "triggers_actions_ui"], "server": true, "ui": true } diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/public/plugin.ts b/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/public/plugin.ts index 2bf353f79985..4c68a3aa15b3 100644 --- a/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/public/plugin.ts +++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/public/plugin.ts @@ -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 { - 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', diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/server/plugin.ts b/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/server/plugin.ts index d4ae6d3557c3..123c0c550e71 100644 --- a/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/server/plugin.ts +++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/server/plugin.ts @@ -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;