From f426a70a3d67252c246e7a6414b446b00b07cec8 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Thu, 3 Dec 2020 22:50:03 -0800 Subject: [PATCH 1/8] Define minimum license required for each alert type --- .../server/alert_types/always_firing.ts | 1 + .../server/alert_types/astros.ts | 1 + x-pack/plugins/alerts/README.md | 2 + x-pack/plugins/alerts/common/alert_type.ts | 3 + .../plugins/alerts/public/alert_api.test.ts | 4 ++ .../alert_navigation_registry.test.ts | 1 + .../alerts/server/alert_type_registry.test.ts | 12 ++++ .../alerts_client/tests/aggregate.test.ts | 2 + .../server/alerts_client/tests/create.test.ts | 1 + .../server/alerts_client/tests/find.test.ts | 2 + .../alerts/server/alerts_client/tests/lib.ts | 1 + .../tests/list_alert_types.test.ts | 5 ++ .../server/alerts_client/tests/update.test.ts | 3 + .../alerts_client_conflict_retries.test.ts | 2 + .../alerts_authorization.test.ts | 6 ++ .../alerts_authorization_kuery.test.ts | 5 ++ .../lib/validate_alert_type_params.test.ts | 3 + x-pack/plugins/alerts/server/plugin.test.ts | 68 ++++++++++++++++++- x-pack/plugins/alerts/server/plugin.ts | 13 ++-- .../server/routes/list_alert_types.test.ts | 3 + .../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/alerts/server/types.ts | 2 + x-pack/plugins/apm/common/alert_types.ts | 4 ++ .../alerts/register_error_count_alert_type.ts | 1 + ...egister_transaction_duration_alert_type.ts | 1 + ...transaction_duration_anomaly_alert_type.ts | 1 + ...ister_transaction_error_rate_alert_type.ts | 1 + ...r_inventory_metric_threshold_alert_type.ts | 4 +- .../register_log_threshold_alert_type.ts | 1 + .../register_metric_threshold_alert_type.ts | 4 +- .../monitoring/server/alerts/base_alert.ts | 1 + .../rules_notification_alert_type.ts | 1 + .../signals/signal_rule_alert_type.ts | 1 + .../alert_types/geo_threshold/alert_type.ts | 3 + .../alert_types/index_threshold/alert_type.ts | 1 + .../components/alert_details.test.tsx | 20 ++++++ .../components/alert_instances.test.tsx | 1 + .../components/alert_instances_route.test.tsx | 1 + .../sections/alert_form/alert_add.test.tsx | 1 + .../sections/alert_form/alert_form.test.tsx | 3 + .../components/alerts_list.test.tsx | 1 + .../triggers_actions_ui/public/types.ts | 8 +-- .../server/lib/alerts/duration_anomaly.ts | 1 + .../uptime/server/lib/alerts/status_check.ts | 1 + .../plugins/uptime/server/lib/alerts/tls.ts | 1 + .../plugins/alerts/server/alert_types.ts | 13 ++++ .../alerts_restricted/server/alert_types.ts | 2 + .../tests/alerting/list_alert_types.ts | 2 + .../tests/alerting/list_alert_types.ts | 1 + .../fixtures/plugins/alerts/server/plugin.ts | 7 +- 52 files changed, 213 insertions(+), 17 deletions(-) diff --git a/x-pack/examples/alerting_example/server/alert_types/always_firing.ts b/x-pack/examples/alerting_example/server/alert_types/always_firing.ts index 1900f55a51a55..a0abf01e53937 100644 --- a/x-pack/examples/alerting_example/server/alert_types/always_firing.ts +++ b/x-pack/examples/alerting_example/server/alert_types/always_firing.ts @@ -41,6 +41,7 @@ export const alertType: AlertType = { name: 'Always firing', actionGroups: ACTION_GROUPS, defaultActionGroupId: DEFAULT_ACTION_GROUP, + minimumLicenseRequired: 'basic', async executor({ services, params: { instances = DEFAULT_INSTANCES_TO_GENERATE, thresholds }, diff --git a/x-pack/examples/alerting_example/server/alert_types/astros.ts b/x-pack/examples/alerting_example/server/alert_types/astros.ts index 852e6f57d1106..0a2c3f26fe47a 100644 --- a/x-pack/examples/alerting_example/server/alert_types/astros.ts +++ b/x-pack/examples/alerting_example/server/alert_types/astros.ts @@ -42,6 +42,7 @@ export const alertType: AlertType = { id: 'example.people-in-space', name: 'People In Space Right Now', actionGroups: [{ id: 'default', name: 'default' }], + minimumLicenseRequired: 'basic', defaultActionGroupId: 'default', async executor({ services, params }) { const { outerSpaceCapacity, craft: craftToTriggerBy, op } = params; diff --git a/x-pack/plugins/alerts/README.md b/x-pack/plugins/alerts/README.md index 62058d47cbd44..5b0c39985652f 100644 --- a/x-pack/plugins/alerts/README.md +++ b/x-pack/plugins/alerts/README.md @@ -171,6 +171,7 @@ server.newPlatform.setup.plugins.alerts.registerType({ { name: 'cpuUsage', description: 'CPU usage' }, ], }, + minimumLicenseRequired: 'basic', async executor({ alertId, startedAt, @@ -238,6 +239,7 @@ server.newPlatform.setup.plugins.alerts.registerType({ }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', actionVariables: { context: [ { name: 'server', description: 'the server' }, diff --git a/x-pack/plugins/alerts/common/alert_type.ts b/x-pack/plugins/alerts/common/alert_type.ts index f07555c334074..364c07edfa408 100644 --- a/x-pack/plugins/alerts/common/alert_type.ts +++ b/x-pack/plugins/alerts/common/alert_type.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { LicenseType } from '../../licensing/common/types'; + export interface AlertType { id: string; name: string; @@ -11,6 +13,7 @@ export interface AlertType { actionVariables: string[]; defaultActionGroupId: ActionGroup['id']; producer: string; + minimumLicenseRequired: LicenseType; } export interface ActionGroup { diff --git a/x-pack/plugins/alerts/public/alert_api.test.ts b/x-pack/plugins/alerts/public/alert_api.test.ts index 0fa2e7f25323b..cd3280aa8f76b 100644 --- a/x-pack/plugins/alerts/public/alert_api.test.ts +++ b/x-pack/plugins/alerts/public/alert_api.test.ts @@ -22,6 +22,7 @@ describe('loadAlertTypes', () => { actionVariables: ['var1'], actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: 'alerts', }, ]; @@ -45,6 +46,7 @@ describe('loadAlertType', () => { actionVariables: ['var1'], actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: 'alerts', }; http.get.mockResolvedValueOnce([alertType]); @@ -65,6 +67,7 @@ describe('loadAlertType', () => { actionVariables: [], actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: 'alerts', }; http.get.mockResolvedValueOnce([alertType]); @@ -80,6 +83,7 @@ describe('loadAlertType', () => { actionVariables: [], actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: 'alerts', }, ]); diff --git a/x-pack/plugins/alerts/public/alert_navigation_registry/alert_navigation_registry.test.ts b/x-pack/plugins/alerts/public/alert_navigation_registry/alert_navigation_registry.test.ts index 72c955923a0cc..3ba2063f66460 100644 --- a/x-pack/plugins/alerts/public/alert_navigation_registry/alert_navigation_registry.test.ts +++ b/x-pack/plugins/alerts/public/alert_navigation_registry/alert_navigation_registry.test.ts @@ -17,6 +17,7 @@ const mockAlertType = (id: string): AlertType => ({ actionVariables: [], defaultActionGroupId: 'default', producer: 'alerts', + minimumLicenseRequired: 'basic', }); describe('AlertNavigationRegistry', () => { diff --git a/x-pack/plugins/alerts/server/alert_type_registry.test.ts b/x-pack/plugins/alerts/server/alert_type_registry.test.ts index b04871a047e4b..a12aea53e0cf9 100644 --- a/x-pack/plugins/alerts/server/alert_type_registry.test.ts +++ b/x-pack/plugins/alerts/server/alert_type_registry.test.ts @@ -8,6 +8,7 @@ import { TaskRunnerFactory } from './task_runner'; import { AlertTypeRegistry } from './alert_type_registry'; import { AlertType } from './types'; import { taskManagerMock } from '../../task_manager/server/mocks'; +import { LicenseType } from '../../licensing/server'; const taskManager = taskManagerMock.createSetup(); const alertTypeRegistryParams = { @@ -35,6 +36,7 @@ describe('has()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }); @@ -54,6 +56,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic' as LicenseType, executor: jest.fn(), producer: 'alerts', }; @@ -85,6 +88,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic' as LicenseType, executor: jest.fn(), producer: 'alerts', }; @@ -110,6 +114,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic' as LicenseType, executor: jest.fn(), producer: 'alerts', }; @@ -133,6 +138,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic' as LicenseType, executor: jest.fn(), producer: 'alerts', }; @@ -162,6 +168,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic' as LicenseType, executor: jest.fn(), producer: 'alerts', }; @@ -183,6 +190,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }); @@ -197,6 +205,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }) @@ -217,6 +226,7 @@ describe('get()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }); @@ -274,6 +284,7 @@ describe('list()', () => { }, ], defaultActionGroupId: 'testActionGroup', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }); @@ -346,6 +357,7 @@ function alertTypeWithVariables(id: string, context: string, state: string): Ale name: `${id}-name`, actionGroups: [], defaultActionGroupId: id, + minimumLicenseRequired: 'basic' as LicenseType, async executor() {}, producer: 'alerts', }; diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/aggregate.test.ts b/x-pack/plugins/alerts/server/alerts_client/tests/aggregate.test.ts index cc5d10c3346e8..f666c890f12d5 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/aggregate.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/aggregate.test.ts @@ -53,6 +53,7 @@ describe('aggregate()', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'myType', name: 'myType', producer: 'myApp', @@ -102,6 +103,7 @@ describe('aggregate()', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: 'alerts', authorizedConsumers: { myApp: { read: true, all: true }, diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/create.test.ts b/x-pack/plugins/alerts/server/alerts_client/tests/create.test.ts index 171ed13763c46..061c20e809fea 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/create.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/create.test.ts @@ -689,6 +689,7 @@ describe('create()', () => { threshold: schema.number({ min: 0, max: 1 }), }), }, + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', }); diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/find.test.ts b/x-pack/plugins/alerts/server/alerts_client/tests/find.test.ts index 3d7473a746986..f3bf1588f9038 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/find.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/find.test.ts @@ -54,6 +54,7 @@ describe('find()', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'myType', name: 'myType', producer: 'myApp', @@ -109,6 +110,7 @@ describe('find()', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: 'alerts', authorizedConsumers: { myApp: { read: true, all: true }, diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/lib.ts b/x-pack/plugins/alerts/server/alerts_client/tests/lib.ts index 028a7c6737474..b7b77fb6512d4 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/lib.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/lib.ts @@ -83,6 +83,7 @@ export function getBeforeSetup( name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', })); diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/list_alert_types.test.ts b/x-pack/plugins/alerts/server/alerts_client/tests/list_alert_types.test.ts index 8cbe47655ef68..ec1f620102b37 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/list_alert_types.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/list_alert_types.test.ts @@ -50,6 +50,7 @@ describe('listAlertTypes', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'alertingAlertType', name: 'alertingAlertType', producer: 'alerts', @@ -58,6 +59,7 @@ describe('listAlertTypes', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'myAppAlertType', name: 'myAppAlertType', producer: 'myApp', @@ -96,6 +98,7 @@ describe('listAlertTypes', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'myType', name: 'myType', producer: 'myApp', @@ -105,6 +108,7 @@ describe('listAlertTypes', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: 'alerts', }, ]); @@ -119,6 +123,7 @@ describe('listAlertTypes', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: 'alerts', authorizedConsumers: { myApp: { read: true, all: true }, diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/update.test.ts b/x-pack/plugins/alerts/server/alerts_client/tests/update.test.ts index 046d7ec63c048..73ed3a879ec36 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/update.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/update.test.ts @@ -97,6 +97,7 @@ describe('update()', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', }); @@ -676,6 +677,7 @@ describe('update()', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', validate: { params: schema.object({ param1: schema.string(), @@ -1021,6 +1023,7 @@ describe('update()', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', }); diff --git a/x-pack/plugins/alerts/server/alerts_client_conflict_retries.test.ts b/x-pack/plugins/alerts/server/alerts_client_conflict_retries.test.ts index ca9389ece310c..0fa2e6e08ed2a 100644 --- a/x-pack/plugins/alerts/server/alerts_client_conflict_retries.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client_conflict_retries.test.ts @@ -331,6 +331,7 @@ beforeEach(() => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', })); @@ -340,6 +341,7 @@ beforeEach(() => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', }); diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts index eb116b9e208dc..68ae7bc8d5f88 100644 --- a/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts @@ -172,6 +172,7 @@ beforeEach(() => { name: 'My Alert Type', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, producer: 'myApp', })); @@ -534,6 +535,7 @@ describe('AlertsAuthorization', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'myOtherAppAlertType', name: 'myOtherAppAlertType', producer: 'alerts', @@ -542,6 +544,7 @@ describe('AlertsAuthorization', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'myAppAlertType', name: 'myAppAlertType', producer: 'myApp', @@ -550,6 +553,7 @@ describe('AlertsAuthorization', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'mySecondAppAlertType', name: 'mySecondAppAlertType', producer: 'myApp', @@ -824,6 +828,7 @@ describe('AlertsAuthorization', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'myOtherAppAlertType', name: 'myOtherAppAlertType', producer: 'myOtherApp', @@ -832,6 +837,7 @@ describe('AlertsAuthorization', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'myAppAlertType', name: 'myAppAlertType', producer: 'myApp', diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts index e4b9f8c54c38d..5113f0dd11d6a 100644 --- a/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts @@ -20,6 +20,7 @@ describe('asFiltersByAlertTypeAndConsumer', () => { id: 'myAppAlertType', name: 'myAppAlertType', producer: 'myApp', + minimumLicenseRequired: 'basic', authorizedConsumers: { myApp: { read: true, all: true }, }, @@ -40,6 +41,7 @@ describe('asFiltersByAlertTypeAndConsumer', () => { { actionGroups: [], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'myAppAlertType', name: 'myAppAlertType', producer: 'myApp', @@ -65,6 +67,7 @@ describe('asFiltersByAlertTypeAndConsumer', () => { { actionGroups: [], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'myAppAlertType', name: 'myAppAlertType', producer: 'myApp', @@ -78,6 +81,7 @@ describe('asFiltersByAlertTypeAndConsumer', () => { { actionGroups: [], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'myOtherAppAlertType', name: 'myOtherAppAlertType', producer: 'alerts', @@ -91,6 +95,7 @@ describe('asFiltersByAlertTypeAndConsumer', () => { { actionGroups: [], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'mySecondAppAlertType', name: 'mySecondAppAlertType', producer: 'myApp', diff --git a/x-pack/plugins/alerts/server/lib/validate_alert_type_params.test.ts b/x-pack/plugins/alerts/server/lib/validate_alert_type_params.test.ts index 1e6c26c02e65b..2814eaef3e02a 100644 --- a/x-pack/plugins/alerts/server/lib/validate_alert_type_params.test.ts +++ b/x-pack/plugins/alerts/server/lib/validate_alert_type_params.test.ts @@ -19,6 +19,7 @@ test('should return passed in params when validation not defined', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', }, @@ -41,6 +42,7 @@ test('should validate and apply defaults when params is valid', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', validate: { params: schema.object({ param1: schema.string(), @@ -71,6 +73,7 @@ test('should validate and throw error when params is invalid', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', validate: { params: schema.object({ param1: schema.string(), diff --git a/x-pack/plugins/alerts/server/plugin.test.ts b/x-pack/plugins/alerts/server/plugin.test.ts index fee7901c4ea55..6706be75e92bf 100644 --- a/x-pack/plugins/alerts/server/plugin.test.ts +++ b/x-pack/plugins/alerts/server/plugin.test.ts @@ -4,7 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AlertingPlugin, AlertingPluginsSetup, AlertingPluginsStart } from './plugin'; +import { + AlertingPlugin, + AlertingPluginsSetup, + AlertingPluginsStart, + PluginSetupContract, +} from './plugin'; import { coreMock, statusServiceMock } from '../../../../src/core/server/mocks'; import { licensingMock } from '../../licensing/server/mocks'; import { encryptedSavedObjectsMock } from '../../encrypted_saved_objects/server/mocks'; @@ -14,9 +19,16 @@ import { KibanaRequest, CoreSetup } from 'kibana/server'; import { featuresPluginMock } from '../../features/server/mocks'; import { KibanaFeature } from '../../features/server'; import { AlertsConfig } from './config'; +import { AlertType } from './types'; +import { eventLogMock } from '../../event_log/server/mocks'; +import { actionsMock } from '../../actions/server/mocks'; describe('Alerting Plugin', () => { describe('setup()', () => { + let plugin: AlertingPlugin; + let coreSetup: ReturnType; + let pluginsSetup: jest.Mocked; + it('should log warning when Encrypted Saved Objects plugin is using an ephemeral encryption key', async () => { const context = coreMock.createPluginInitializerContext({ healthCheck: { @@ -27,9 +39,9 @@ describe('Alerting Plugin', () => { removalDelay: '5m', }, }); - const plugin = new AlertingPlugin(context); + plugin = new AlertingPlugin(context); - const coreSetup = coreMock.createSetup(); + coreSetup = coreMock.createSetup(); const encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup(); const statusMock = statusServiceMock.createSetupContract(); await plugin.setup( @@ -55,6 +67,56 @@ describe('Alerting Plugin', () => { 'APIs are disabled because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' ); }); + + describe('registerType()', () => { + let setup: PluginSetupContract; + const sampleAlertType: AlertType = { + id: 'test', + name: 'test', + minimumLicenseRequired: 'basic', + actionGroups: [], + defaultActionGroupId: 'default', + producer: 'test', + async executor() {}, + }; + + beforeEach(async () => { + setup = await plugin.setup(coreSetup, pluginsSetup); + coreSetup = coreMock.createSetup(); + pluginsSetup = { + taskManager: taskManagerMock.createSetup(), + encryptedSavedObjects: encryptedSavedObjectsMock.createSetup(), + licensing: licensingMock.createSetup(), + eventLog: eventLogMock.createSetup(), + actions: actionsMock.createSetup(), + statusService: statusServiceMock.createSetupContract(), + }; + }); + + it('should throw error when license type is invalid', async () => { + expect(() => + setup.registerType({ + ...sampleAlertType, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + minimumLicenseRequired: 'foo' as any, + }) + ).toThrowErrorMatchingInlineSnapshot(`"\\"foo\\" is not a valid license type"`); + }); + + it('should not throw when license type is gold', async () => { + setup.registerType({ + ...sampleAlertType, + minimumLicenseRequired: 'gold', + }); + }); + + it('should not throw when license type is basic', async () => { + setup.registerType({ + ...sampleAlertType, + minimumLicenseRequired: 'basic', + }); + }); + }); }); describe('start()', () => { diff --git a/x-pack/plugins/alerts/server/plugin.ts b/x-pack/plugins/alerts/server/plugin.ts index bafb89c64076b..e4ddf44b8808c 100644 --- a/x-pack/plugins/alerts/server/plugin.ts +++ b/x-pack/plugins/alerts/server/plugin.ts @@ -54,12 +54,12 @@ import { unmuteAlertInstanceRoute, healthRoute, } from './routes'; -import { LicensingPluginSetup } from '../../licensing/server'; +import { LICENSE_TYPE, LicensingPluginSetup } from '../../licensing/server'; import { PluginSetupContract as ActionsPluginSetupContract, PluginStartContract as ActionsPluginStartContract, } from '../../actions/server'; -import { AlertsHealth, Services } from './types'; +import { AlertsHealth, AlertType, Services } from './types'; import { registerAlertsUsageCollector } from './usage'; import { initializeAlertingTelemetry, scheduleAlertingTelemetry } from './usage/task'; import { IEventLogger, IEventLogService, IEventLogClientService } from '../../event_log/server'; @@ -90,7 +90,7 @@ export const LEGACY_EVENT_LOG_ACTIONS = { }; export interface PluginSetupContract { - registerType: AlertTypeRegistry['register']; + registerType: (alertType: AlertType) => void; } export interface PluginStartContract { listTypes: AlertTypeRegistry['list']; @@ -250,7 +250,12 @@ export class AlertingPlugin { healthRoute(router, this.licenseState, plugins.encryptedSavedObjects); return { - registerType: alertTypeRegistry.register.bind(alertTypeRegistry), + registerType: (alertType: AlertType) => { + if (!(alertType.minimumLicenseRequired in LICENSE_TYPE)) { + throw new Error(`"${alertType.minimumLicenseRequired}" is not a valid license type`); + } + alertTypeRegistry.register(alertType); + }, }; } diff --git a/x-pack/plugins/alerts/server/routes/list_alert_types.test.ts b/x-pack/plugins/alerts/server/routes/list_alert_types.test.ts index af20dd6e202ba..be1fad5403556 100644 --- a/x-pack/plugins/alerts/server/routes/list_alert_types.test.ts +++ b/x-pack/plugins/alerts/server/routes/list_alert_types.test.ts @@ -43,6 +43,7 @@ describe('listAlertTypesRoute', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', authorizedConsumers: {}, actionVariables: { context: [], @@ -107,6 +108,7 @@ describe('listAlertTypesRoute', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', authorizedConsumers: {}, actionVariables: { context: [], @@ -156,6 +158,7 @@ describe('listAlertTypesRoute', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', authorizedConsumers: {}, actionVariables: { context: [], diff --git a/x-pack/plugins/alerts/server/task_runner/create_execution_handler.test.ts b/x-pack/plugins/alerts/server/task_runner/create_execution_handler.test.ts index ed73fec24db26..f97c71750047c 100644 --- a/x-pack/plugins/alerts/server/task_runner/create_execution_handler.test.ts +++ b/x-pack/plugins/alerts/server/task_runner/create_execution_handler.test.ts @@ -20,6 +20,7 @@ const alertType: AlertType = { { id: 'other-group', name: 'Other Group' }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts index d4c4f746392c3..2e286a7dfa529 100644 --- a/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts @@ -33,6 +33,7 @@ const alertType = { name: 'My test alert', actionGroups: [{ id: 'default', name: 'Default' }, RecoveredActionGroup], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts b/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts index 1c10a997d8cdd..e622f1d5d2cbc 100644 --- a/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts +++ b/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts @@ -22,6 +22,7 @@ const alertType = { name: 'My test alert', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; diff --git a/x-pack/plugins/alerts/server/types.ts b/x-pack/plugins/alerts/server/types.ts index 500c681a1d2b9..57498be36f7f1 100644 --- a/x-pack/plugins/alerts/server/types.ts +++ b/x-pack/plugins/alerts/server/types.ts @@ -29,6 +29,7 @@ import { AlertExecutionStatusErrorReasons, AlertsHealth, } from '../common'; +import { LicenseType } from '../../licensing/server'; export type WithoutQueryAndParams = Pick>; export type GetServicesFunction = (request: KibanaRequest) => Services; @@ -107,6 +108,7 @@ export interface AlertType< state?: ActionVariable[]; params?: ActionVariable[]; }; + minimumLicenseRequired: LicenseType; } export interface RawAlertAction extends SavedObjectAttributes { diff --git a/x-pack/plugins/apm/common/alert_types.ts b/x-pack/plugins/apm/common/alert_types.ts index a234226d18034..7cc36253ef581 100644 --- a/x-pack/plugins/apm/common/alert_types.ts +++ b/x-pack/plugins/apm/common/alert_types.ts @@ -29,6 +29,7 @@ export const ALERT_TYPES_CONFIG = { }), actionGroups: [THRESHOLD_MET_GROUP], defaultActionGroupId: 'threshold_met', + minimumLicenseRequired: 'basic', producer: 'apm', }, [AlertType.TransactionDuration]: { @@ -37,6 +38,7 @@ export const ALERT_TYPES_CONFIG = { }), actionGroups: [THRESHOLD_MET_GROUP], defaultActionGroupId: 'threshold_met', + minimumLicenseRequired: 'basic', producer: 'apm', }, [AlertType.TransactionDurationAnomaly]: { @@ -45,6 +47,7 @@ export const ALERT_TYPES_CONFIG = { }), actionGroups: [THRESHOLD_MET_GROUP], defaultActionGroupId: 'threshold_met', + minimumLicenseRequired: 'basic', producer: 'apm', }, [AlertType.TransactionErrorRate]: { @@ -53,6 +56,7 @@ export const ALERT_TYPES_CONFIG = { }), actionGroups: [THRESHOLD_MET_GROUP], defaultActionGroupId: 'threshold_met', + minimumLicenseRequired: 'basic', producer: 'apm', }, }; diff --git a/x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.ts index 464a737c50ea2..2b33f8a35d50e 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.ts @@ -59,6 +59,7 @@ export function registerErrorCountAlertType({ ], }, producer: 'apm', + minimumLicenseRequired: 'basic', executor: async ({ services, params }) => { const config = await config$.pipe(take(1)).toPromise(); const alertParams = params; 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 602ee99970f8a..ac51a151bb207 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 @@ -68,6 +68,7 @@ export function registerTransactionDurationAlertType({ ], }, producer: 'apm', + minimumLicenseRequired: 'basic', executor: async ({ services, params }) => { const config = await config$.pipe(take(1)).toPromise(); const alertParams = params; diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts index b9e970ace869d..f3df0092dbbbd 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts @@ -67,6 +67,7 @@ export function registerTransactionDurationAnomalyAlertType({ ], }, producer: 'apm', + minimumLicenseRequired: 'basic', executor: async ({ services, params, state }) => { if (!ml) { return; diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts index 0506e1b4c3aed..96ab854e5ea39 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts @@ -65,6 +65,7 @@ export function registerTransactionErrorRateAlertType({ ], }, producer: 'apm', + minimumLicenseRequired: 'basic', executor: async ({ services, params: alertParams }) => { const config = await config$.pipe(take(1)).toPromise(); const indices = await getApmIndices({ 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 14d1acf0e4a9f..6ec6210ecb344 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 @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; +import { AlertType } from '../../../../../alerts/server'; import { createInventoryMetricThresholdExecutor, FIRED_ACTIONS, @@ -38,7 +39,7 @@ const condition = schema.object({ ), }); -export const registerMetricInventoryThresholdAlertType = (libs: InfraBackendLibs) => ({ +export const registerMetricInventoryThresholdAlertType = (libs: InfraBackendLibs): AlertType => ({ id: METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, name: 'Inventory', validate: { @@ -58,6 +59,7 @@ export const registerMetricInventoryThresholdAlertType = (libs: InfraBackendLibs defaultActionGroupId: FIRED_ACTIONS.id, actionGroups: [FIRED_ACTIONS], producer: 'infrastructure', + minimumLicenseRequired: 'basic', executor: createInventoryMetricThresholdExecutor(libs), 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 34afddc2a4d48..64bfad92a8458 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 @@ -89,6 +89,7 @@ export async function registerLogThresholdAlertType( }, defaultActionGroupId: FIRED_ACTIONS.id, actionGroups: [FIRED_ACTIONS], + minimumLicenseRequired: 'basic', executor: createLogThresholdExecutor(libs), actionVariables: { context: [ 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 45b1df2f03ea1..1a10765eaf734 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 @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; +import { AlertType } from '../../../../../alerts/server'; import { METRIC_EXPLORER_AGGREGATIONS } from '../../../../common/http_api/metrics_explorer'; import { createMetricThresholdExecutor, FIRED_ACTIONS } from './metric_threshold_executor'; import { METRIC_THRESHOLD_ALERT_TYPE_ID, Comparator } from './types'; @@ -19,7 +20,7 @@ import { thresholdActionVariableDescription, } from '../common/messages'; -export function registerMetricThresholdAlertType(libs: InfraBackendLibs) { +export function registerMetricThresholdAlertType(libs: InfraBackendLibs): AlertType { const baseCriterion = { threshold: schema.arrayOf(schema.number()), comparator: oneOfLiterals(Object.values(Comparator)), @@ -60,6 +61,7 @@ export function registerMetricThresholdAlertType(libs: InfraBackendLibs) { }, defaultActionGroupId: FIRED_ACTIONS.id, actionGroups: [FIRED_ACTIONS], + minimumLicenseRequired: 'basic', executor: createMetricThresholdExecutor(libs), actionVariables: { context: [ diff --git a/x-pack/plugins/monitoring/server/alerts/base_alert.ts b/x-pack/plugins/monitoring/server/alerts/base_alert.ts index 4c1a4d8df2ab5..255a3a19d38a8 100644 --- a/x-pack/plugins/monitoring/server/alerts/base_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/base_alert.ts @@ -113,6 +113,7 @@ export class BaseAlert { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: (options: AlertExecutorOptions): Promise => this.execute(options), producer: 'monitoring', actionVariables: { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts index 802b9472a4487..088cc417cf28e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts @@ -31,6 +31,7 @@ export const rulesNotificationAlertType = ({ ruleAlertId: schema.string(), }), }, + minimumLicenseRequired: 'basic', async executor({ startedAt, previousStartedAt, alertId, services, params }) { const ruleAlertSavedObject = await services.savedObjectsClient.get( 'alert', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts index d6bdc14a92b40..91c5a8c3ecf6c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -90,6 +90,7 @@ export const signalRulesAlertType = ({ params: signalParamsSchema(), }, producer: SERVER_APP_ID, + minimumLicenseRequired: 'basic', async executor({ previousStartedAt, startedAt, diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/alert_type.ts index 0c40f5b5f3866..f485f53e2be62 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/alert_type.ts @@ -7,6 +7,7 @@ import { i18n } from '@kbn/i18n'; import { schema } from '@kbn/config-schema'; import { Logger } from 'src/core/server'; +import { LicenseType } from '../../../../licensing/server'; import { STACK_ALERTS_FEATURE_ID } from '../../../common'; import { getGeoThresholdExecutor } from './geo_threshold'; import { @@ -182,6 +183,7 @@ export function getAlertType( ): { defaultActionGroupId: string; actionGroups: ActionGroup[]; + minimumLicenseRequired: LicenseType; executor: ({ previousStartedAt: currIntervalStartTime, startedAt: currIntervalEndTime, @@ -233,5 +235,6 @@ export function getAlertType( params: ParamsSchema, }, actionVariables, + minimumLicenseRequired: 'gold', }; } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts index 9de0940771525..9600395c78218 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts @@ -143,6 +143,7 @@ export function getAlertType( ...alertParamsVariables, ], }, + minimumLicenseRequired: 'basic', executor, producer: STACK_ALERTS_FEATURE_ID, }; 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 2f7a31721fa07..040c1e0cc85d6 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 @@ -16,6 +16,7 @@ import { } from '../../../../../../alerts/common'; import { useKibana } from '../../../../common/lib/kibana'; import { alertTypeRegistryMock } from '../../../alert_type_registry.mock'; +import { LicenseType } from '../../../../../../licensing/public'; jest.mock('../../../../common/lib/kibana'); @@ -60,6 +61,7 @@ describe('alert_details', () => { actionGroups: [{ id: 'default', name: 'Default' }], actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic' as LicenseType, producer: ALERTS_FEATURE_ID, authorizedConsumers, }; @@ -85,6 +87,7 @@ describe('alert_details', () => { actionGroups: [{ id: 'default', name: 'Default' }], actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic' as LicenseType, producer: ALERTS_FEATURE_ID, authorizedConsumers, }; @@ -113,6 +116,7 @@ describe('alert_details', () => { actionGroups: [{ id: 'default', name: 'Default' }], actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic' as LicenseType, producer: ALERTS_FEATURE_ID, authorizedConsumers, }; @@ -147,6 +151,7 @@ describe('alert_details', () => { actionGroups: [{ id: 'default', name: 'Default' }], actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic' as LicenseType, producer: ALERTS_FEATURE_ID, authorizedConsumers, }; @@ -202,6 +207,7 @@ describe('alert_details', () => { actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, + minimumLicenseRequired: 'basic' as LicenseType, authorizedConsumers, }; const actionTypes: ActionType[] = [ @@ -262,6 +268,7 @@ describe('alert_details', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; expect( @@ -282,6 +289,7 @@ describe('alert_details', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; expect( @@ -311,6 +319,7 @@ describe('disable button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; const enableButton = shallow( @@ -339,6 +348,7 @@ describe('disable button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; const enableButton = shallow( @@ -367,6 +377,7 @@ describe('disable button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; const disableAlert = jest.fn(); @@ -404,6 +415,7 @@ describe('disable button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; const enableAlert = jest.fn(); @@ -444,6 +456,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; const enableButton = shallow( @@ -473,6 +486,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; const enableButton = shallow( @@ -502,6 +516,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; const muteAlert = jest.fn(); @@ -540,6 +555,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; const unmuteAlert = jest.fn(); @@ -578,6 +594,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; const enableButton = shallow( @@ -643,6 +660,7 @@ describe('edit button', () => { defaultActionGroupId: 'default', producer: 'alerting', authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; expect( @@ -685,6 +703,7 @@ describe('edit button', () => { defaultActionGroupId: 'default', producer: 'alerting', authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; expect( @@ -720,6 +739,7 @@ describe('edit button', () => { defaultActionGroupId: 'default', producer: 'alerting', authorizedConsumers, + minimumLicenseRequired: 'basic' as LicenseType, }; expect( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.test.tsx index 52a85e8bc57bd..18858f12483db 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.test.tsx @@ -309,6 +309,7 @@ function mockAlertType(overloads: Partial = {}): AlertType { defaultActionGroupId: 'default', authorizedConsumers: {}, producer: 'alerts', + minimumLicenseRequired: 'basic', ...overloads, }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances_route.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances_route.test.tsx index 2256efe30831b..14ad638546f3e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances_route.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances_route.test.tsx @@ -149,6 +149,7 @@ function mockAlertType(overloads: Partial = {}): AlertType { defaultActionGroupId: 'default', authorizedConsumers: {}, producer: 'alerts', + minimumLicenseRequired: 'basic', ...overloads, }; } 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 084da8905663e..9980f0256d7be 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 @@ -61,6 +61,7 @@ describe('alert_add', () => { }, ], defaultActionGroupId: 'testActionGroup', + minimumLicenseRequired: 'basic', producer: ALERTS_FEATURE_ID, authorizedConsumers: { [ALERTS_FEATURE_ID]: { read: true, all: true }, 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 6b5f0a31d345c..a0625f0cbcf47 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 @@ -85,6 +85,7 @@ describe('alert_form', () => { }, ], defaultActionGroupId: 'testActionGroup', + minimumLicenseRequired: 'basic', producer: ALERTS_FEATURE_ID, authorizedConsumers: { [ALERTS_FEATURE_ID]: { read: true, all: true }, @@ -218,6 +219,7 @@ describe('alert_form', () => { }, ], defaultActionGroupId: 'testActionGroup', + minimumLicenseRequired: 'basic', producer: ALERTS_FEATURE_ID, authorizedConsumers: { [ALERTS_FEATURE_ID]: { read: true, all: true }, @@ -234,6 +236,7 @@ describe('alert_form', () => { }, ], defaultActionGroupId: 'testActionGroup', + minimumLicenseRequired: 'basic', producer: 'test', authorizedConsumers: { [ALERTS_FEATURE_ID]: { read: true, all: true }, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx index 351eccf2934be..cb187655c77a2 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx @@ -59,6 +59,7 @@ const alertTypeFromApi = { actionVariables: { context: [], state: [] }, defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, + minimumLicenseRequired: 'basic', authorizedConsumers: { [ALERTS_FEATURE_ID]: { read: true, all: true }, }, diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index a4eac1ab1da21..f488f2eb6ed59 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -9,6 +9,7 @@ import { ComponentType } from 'react'; import { ActionGroup, AlertActionParam } from '../../alerts/common'; import { ActionType } from '../../actions/common'; import { TypeRegistry } from './application/type_registry'; +import { AlertType as AlertTypeApi } from '../../alerts/common'; import { SanitizedAlert as Alert, AlertAction, @@ -133,14 +134,9 @@ export interface ActionVariables { params: ActionVariable[]; } -export interface AlertType { - id: string; - name: string; - actionGroups: ActionGroup[]; +export interface AlertType extends Omit { actionVariables: ActionVariables; - defaultActionGroupId: ActionGroup['id']; authorizedConsumers: Record; - producer: string; } export type SanitizedAlertType = Omit; diff --git a/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts b/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts index 022ec48bad1d9..f5e79ad43336b 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts @@ -82,6 +82,7 @@ export const durationAnomalyAlertFactory: UptimeAlertTypeFactory = (_server, _li context: [], state: [...durationAnomalyTranslations.actionVariables, ...commonStateTranslations], }, + minimumLicenseRequired: 'basic', async executor({ options, uptimeEsClient, savedObjectsClient, dynamicSettings }) { const { services: { alertInstanceFactory }, 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 3e45ce302bf87..56ca7a85784c5 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts @@ -255,6 +255,7 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = (_server, libs) = ], state: [...commonMonitorStateI18, ...commonStateTranslations], }, + minimumLicenseRequired: 'basic', async executor({ options: { params: rawParams, diff --git a/x-pack/plugins/uptime/server/lib/alerts/tls.ts b/x-pack/plugins/uptime/server/lib/alerts/tls.ts index 41a5101716122..b6501f7d92059 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], }, + minimumLicenseRequired: 'basic', async executor({ options, dynamicSettings, uptimeEsClient }) { const { services: { alertInstanceFactory }, diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts index 998ec6ab2ed0e..ff28aea660036 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts @@ -7,6 +7,7 @@ import { CoreSetup } from 'src/core/server'; import { schema, TypeOf } from '@kbn/config-schema'; import { times } from 'lodash'; +import { LicenseType } from '../../../../../../../plugins/licensing/public'; import { ES_TEST_INDEX_NAME } from '../../../../lib'; import { FixtureStartDeps, FixtureSetupDeps } from './plugin'; import { @@ -43,6 +44,7 @@ function getAlwaysFiringAlertType() { }, producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic' as LicenseType, actionVariables: { state: [{ name: 'instanceStateValue', description: 'the instance state value' }], params: [{ name: 'instanceParamsValue', description: 'the instance params value' }], @@ -113,6 +115,7 @@ function getCumulativeFiringAlertType() { ], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor(alertExecutorOptions) { const { services, state } = alertExecutorOptions; const group = 'default'; @@ -157,6 +160,7 @@ function getNeverFiringAlertType() { }, producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor({ services, params, state }) { await services.callCluster('index', { index: params.index, @@ -196,6 +200,7 @@ function getFailingAlertType() { ], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor({ services, params, state }) { await services.callCluster('index', { index: params.index, @@ -234,6 +239,7 @@ function getAuthorizationAlertType(core: CoreSetup) { ], defaultActionGroupId: 'default', producer: 'alertsFixture', + minimumLicenseRequired: 'basic', validate: { params: paramsSchema, }, @@ -319,6 +325,7 @@ function getValidationAlertType() { }, ], producer: 'alertsFixture', + minimumLicenseRequired: 'basic', defaultActionGroupId: 'default', validate: { params: paramsSchema, @@ -343,6 +350,7 @@ function getPatternFiringAlertType() { actionGroups: [{ id: 'default', name: 'Default' }], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor(alertExecutorOptions) { const { services, state, params } = alertExecutorOptions; const pattern = params.pattern; @@ -398,6 +406,7 @@ export function defineAlertTypes( actionGroups: [{ id: 'default', name: 'Default' }], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, }; const onlyContextVariablesAlertType: AlertType = { @@ -406,6 +415,7 @@ export function defineAlertTypes( actionGroups: [{ id: 'default', name: 'Default' }], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', actionVariables: { context: [{ name: 'aContextVariable', description: 'this is a context variable' }], }, @@ -420,6 +430,7 @@ export function defineAlertTypes( actionVariables: { state: [{ name: 'aStateVariable', description: 'this is a state variable' }], }, + minimumLicenseRequired: 'basic', async executor() {}, }; const throwAlertType: AlertType = { @@ -433,6 +444,7 @@ export function defineAlertTypes( ], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() { throw new Error('this alert is intended to fail'); }, @@ -448,6 +460,7 @@ export function defineAlertTypes( ], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() { await new Promise((resolve) => setTimeout(resolve, 5000)); }, diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts_restricted/server/alert_types.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts_restricted/server/alert_types.ts index 00d06c30aa910..976efa9c62102 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts_restricted/server/alert_types.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts_restricted/server/alert_types.ts @@ -18,6 +18,7 @@ export function defineAlertTypes( actionGroups: [{ id: 'default', name: 'Default' }], producer: 'alertsRestrictedFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor({ services, params, state }: AlertExecutorOptions) {}, }; const noopUnrestrictedAlertType: AlertType = { @@ -26,6 +27,7 @@ export function defineAlertTypes( actionGroups: [{ id: 'default', name: 'Default' }], producer: 'alertsRestrictedFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor({ services, params, state }: AlertExecutorOptions) {}, }; alerts.registerType(noopRestrictedAlertType); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/list_alert_types.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/list_alert_types.ts index bfaf8a2a4788e..2a1d1baaf230c 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/list_alert_types.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/list_alert_types.ts @@ -28,6 +28,7 @@ export default function listAlertTypes({ getService }: FtrProviderContext) { params: [], }, producer: 'alertsFixture', + minimumLicenseRequired: 'basic', }; const expectedRestrictedNoOpType = { @@ -44,6 +45,7 @@ export default function listAlertTypes({ getService }: FtrProviderContext) { params: [], }, producer: 'alertsRestrictedFixture', + minimumLicenseRequired: 'basic', }; describe('list_alert_types', () => { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts index 9d38f4abb7f3f..a9ea8a82c6493 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts @@ -36,6 +36,7 @@ export default function listAlertTypes({ getService }: FtrProviderContext) { context: [], }, producer: 'alertsFixture', + minimumLicenseRequired: 'basic', }); expect(Object.keys(authorizedConsumers)).to.contain('alertsFixture'); }); 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 6584c5891a8b9..f6cbc52e7a421 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 @@ -22,11 +22,12 @@ export const noopAlertType: AlertType = { name: 'Test: Noop', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', }; -export const alwaysFiringAlertType: any = { +export const alwaysFiringAlertType: AlertType = { id: 'test.always-firing', name: 'Always Firing', actionGroups: [ @@ -35,6 +36,7 @@ export const alwaysFiringAlertType: any = { ], defaultActionGroupId: 'default', producer: 'alerts', + minimumLicenseRequired: 'basic', async executor(alertExecutorOptions: any) { const { services, state, params } = alertExecutorOptions; @@ -52,7 +54,7 @@ export const alwaysFiringAlertType: any = { }, }; -export const failingAlertType: any = { +export const failingAlertType: AlertType = { id: 'test.failing', name: 'Test: Failing', actionGroups: [ @@ -63,6 +65,7 @@ export const failingAlertType: any = { ], producer: 'alerts', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() { throw new Error('Failed to execute alert type'); }, From a260f51e39667ca20c631041a3c2ef206473bea6 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Fri, 4 Dec 2020 17:14:39 -0800 Subject: [PATCH 2/8] fixed typechecks --- .../alerts/server/alert_type_registry.test.ts | 3 + .../alerts_authorization.test.ts | 8 ++ x-pack/plugins/alerts/server/plugin.test.ts | 2 +- .../server/routes/list_alert_types.test.ts | 1 + .../server/task_runner/task_runner.test.ts | 3 +- .../task_runner/task_runner_factory.test.ts | 3 +- x-pack/plugins/alerts/server/types.ts | 16 ++- x-pack/plugins/stack_alerts/kibana.json | 2 +- .../alert_types/geo_containment/alert_type.ts | 43 +------- .../alert_types/geo_containment/index.ts | 4 +- .../alert_types/geo_threshold/alert_type.ts | 44 +------- .../server/alert_types/geo_threshold/index.ts | 4 +- .../alert_types/index_threshold/index.ts | 4 +- .../application/lib/action_variables.test.ts | 1 + .../public/application/lib/alert_api.test.ts | 1 + .../plugins/alerts/server/alert_types.ts | 100 +++++++++--------- 16 files changed, 93 insertions(+), 146 deletions(-) diff --git a/x-pack/plugins/alerts/server/alert_type_registry.test.ts b/x-pack/plugins/alerts/server/alert_type_registry.test.ts index cc720522aebe7..59ba3c865e0c1 100644 --- a/x-pack/plugins/alerts/server/alert_type_registry.test.ts +++ b/x-pack/plugins/alerts/server/alert_type_registry.test.ts @@ -144,6 +144,7 @@ describe('register()', () => { }, executor: jest.fn(), producer: 'alerts', + minimumLicenseRequired: 'basic' as LicenseType, }; const registry = new AlertTypeRegistry(alertTypeRegistryParams); registry.register(alertType); @@ -180,6 +181,7 @@ describe('register()', () => { name: 'Back To Awesome', }, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic' as LicenseType, executor: jest.fn(), producer: 'alerts', }; @@ -316,6 +318,7 @@ describe('get()', () => { "defaultActionGroupId": "default", "executor": [MockFunction], "id": "test", + "minimumLicenseRequired": "basic", "name": "Test", "producer": "alerts", "recoveryActionGroup": Object { diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts index f93754c99991f..1914bbcb0acba 100644 --- a/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts @@ -891,6 +891,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myAppAlertType", + "minimumLicenseRequired": "basic", "name": "myAppAlertType", "producer": "myApp", "recoveryActionGroup": Object { @@ -921,6 +922,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myOtherAppAlertType", + "minimumLicenseRequired": "basic", "name": "myOtherAppAlertType", "producer": "myOtherApp", "recoveryActionGroup": Object { @@ -991,6 +993,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myOtherAppAlertType", + "minimumLicenseRequired": "basic", "name": "myOtherAppAlertType", "producer": "myOtherApp", "recoveryActionGroup": Object { @@ -1017,6 +1020,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myAppAlertType", + "minimumLicenseRequired": "basic", "name": "myAppAlertType", "producer": "myApp", "recoveryActionGroup": Object { @@ -1082,6 +1086,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myAppAlertType", + "minimumLicenseRequired": "basic", "name": "myAppAlertType", "producer": "myApp", "recoveryActionGroup": Object { @@ -1176,6 +1181,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myOtherAppAlertType", + "minimumLicenseRequired": "basic", "name": "myOtherAppAlertType", "producer": "myOtherApp", "recoveryActionGroup": Object { @@ -1202,6 +1208,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myAppAlertType", + "minimumLicenseRequired": "basic", "name": "myAppAlertType", "producer": "myApp", "recoveryActionGroup": Object { @@ -1280,6 +1287,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myOtherAppAlertType", + "minimumLicenseRequired": "basic", "name": "myOtherAppAlertType", "producer": "myOtherApp", "recoveryActionGroup": Object { diff --git a/x-pack/plugins/alerts/server/plugin.test.ts b/x-pack/plugins/alerts/server/plugin.test.ts index 6706be75e92bf..b41e70b9d6a5a 100644 --- a/x-pack/plugins/alerts/server/plugin.test.ts +++ b/x-pack/plugins/alerts/server/plugin.test.ts @@ -81,7 +81,6 @@ describe('Alerting Plugin', () => { }; beforeEach(async () => { - setup = await plugin.setup(coreSetup, pluginsSetup); coreSetup = coreMock.createSetup(); pluginsSetup = { taskManager: taskManagerMock.createSetup(), @@ -91,6 +90,7 @@ describe('Alerting Plugin', () => { actions: actionsMock.createSetup(), statusService: statusServiceMock.createSetupContract(), }; + setup = await plugin.setup(coreSetup, pluginsSetup); }); it('should throw error when license type is invalid', async () => { diff --git a/x-pack/plugins/alerts/server/routes/list_alert_types.test.ts b/x-pack/plugins/alerts/server/routes/list_alert_types.test.ts index 63008ed4923d7..33c6a1d81139c 100644 --- a/x-pack/plugins/alerts/server/routes/list_alert_types.test.ts +++ b/x-pack/plugins/alerts/server/routes/list_alert_types.test.ts @@ -75,6 +75,7 @@ describe('listAlertTypesRoute', () => { "authorizedConsumers": Object {}, "defaultActionGroupId": "default", "id": "1", + "minimumLicenseRequired": "basic", "name": "name", "producer": "test", "recoveryActionGroup": Object { diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts index 11b02a59abf72..5a25f5cd2c6eb 100644 --- a/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts @@ -28,12 +28,13 @@ import { IEventLogger } from '../../../event_log/server'; import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; import { Alert, RecoveredActionGroup } from '../../common'; import { omit } from 'lodash'; +import { LicenseType } from '../../../licensing/server'; const alertType = { id: 'test', name: 'My test alert', actionGroups: [{ id: 'default', name: 'Default' }, RecoveredActionGroup], defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', + minimumLicenseRequired: 'basic' as LicenseType, recoveryActionGroup: RecoveredActionGroup, executor: jest.fn(), producer: 'alerts', diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts b/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts index 593415d02d3f7..4c83ccb7dad91 100644 --- a/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts +++ b/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts @@ -16,13 +16,14 @@ import { import { actionsMock } from '../../../actions/server/mocks'; import { alertsMock, alertsClientMock } from '../mocks'; import { eventLoggerMock } from '../../../event_log/server/event_logger.mock'; +import { LicenseType } from '../../../licensing/server'; const alertType = { id: 'test', name: 'My test alert', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', + minimumLicenseRequired: 'basic' as LicenseType, recoveryActionGroup: { id: 'recovered', name: 'Recovered', diff --git a/x-pack/plugins/alerts/server/types.ts b/x-pack/plugins/alerts/server/types.ts index 625c2f3f997ce..b11352e2e3b7a 100644 --- a/x-pack/plugins/alerts/server/types.ts +++ b/x-pack/plugins/alerts/server/types.ts @@ -84,6 +84,16 @@ export interface ActionVariable { description: string; } +// signature of the alert type executor function +export type ExecutorType< + Params, + State, + InstanceState extends AlertInstanceState = AlertInstanceState, + InstanceContext extends AlertInstanceContext = AlertInstanceContext +> = ( + options: AlertExecutorOptions +) => Promise; + export interface AlertType< Params extends AlertTypeParams = AlertTypeParams, State extends AlertTypeState = AlertTypeState, @@ -98,11 +108,7 @@ export interface AlertType< actionGroups: ActionGroup[]; defaultActionGroupId: ActionGroup['id']; recoveryActionGroup?: ActionGroup; - executor: ({ - services, - params, - state, - }: AlertExecutorOptions) => Promise; + executor: ExecutorType; producer: string; actionVariables?: { context?: ActionVariable[]; diff --git a/x-pack/plugins/stack_alerts/kibana.json b/x-pack/plugins/stack_alerts/kibana.json index 884d33ef669e5..c4d054b4da45d 100644 --- a/x-pack/plugins/stack_alerts/kibana.json +++ b/x-pack/plugins/stack_alerts/kibana.json @@ -3,7 +3,7 @@ "server": true, "version": "8.0.0", "kibanaVersion": "kibana", - "requiredPlugins": ["alerts", "features", "triggersActionsUi", "kibanaReact", "savedObjects", "data"], + "requiredPlugins": ["alerts", "features", "triggersActionsUi", "kibanaReact", "savedObjects", "data", "licensing"], "configPath": ["xpack", "stack_alerts"], "ui": true } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts index a873cab69f23b..164ce993eebac 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts @@ -9,12 +9,7 @@ import { schema } from '@kbn/config-schema'; import { Logger } from 'src/core/server'; import { STACK_ALERTS_FEATURE_ID } from '../../../common'; import { getGeoContainmentExecutor } from './geo_containment'; -import { - ActionGroup, - AlertServices, - ActionVariable, - AlertTypeState, -} from '../../../../alerts/server'; +import { AlertType } from '../../../../alerts/server'; import { Query } from '../../../../../../src/plugins/data/common/query'; export const GEO_CONTAINMENT_ID = '.geo-containment'; @@ -117,40 +112,7 @@ export interface GeoContainmentParams { boundaryIndexQuery?: Query; } -export function getAlertType( - logger: Logger -): { - defaultActionGroupId: string; - actionGroups: ActionGroup[]; - executor: ({ - previousStartedAt: currIntervalStartTime, - startedAt: currIntervalEndTime, - services, - params, - alertId, - state, - }: { - previousStartedAt: Date | null; - startedAt: Date; - services: AlertServices; - params: GeoContainmentParams; - alertId: string; - state: AlertTypeState; - }) => Promise; - validate?: { - params?: { - validate: (object: unknown) => GeoContainmentParams; - }; - }; - name: string; - producer: string; - id: string; - actionVariables?: { - context?: ActionVariable[]; - state?: ActionVariable[]; - params?: ActionVariable[]; - }; -} { +export function getAlertType(logger: Logger): AlertType { const alertTypeName = i18n.translate('xpack.stackAlerts.geoContainment.alertTypeTitle', { defaultMessage: 'Geo tracking containment', }); @@ -173,5 +135,6 @@ export function getAlertType( params: ParamsSchema, }, actionVariables, + minimumLicenseRequired: 'gold', }; } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts index 2fa2bed9d8419..16e2155ef37fc 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts @@ -5,7 +5,7 @@ */ import { Logger } from 'src/core/server'; -import { AlertingSetup } from '../../types'; +import { AlertingSetup, AlertType } from '../../types'; import { getAlertType } from './alert_type'; interface RegisterParams { @@ -15,5 +15,5 @@ interface RegisterParams { export function register(params: RegisterParams) { const { logger, alerts } = params; - alerts.registerType(getAlertType(logger)); + alerts.registerType((getAlertType(logger) as unknown) as AlertType); } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/alert_type.ts index f485f53e2be62..93a6c0d29cf3c 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/alert_type.ts @@ -7,15 +7,9 @@ import { i18n } from '@kbn/i18n'; import { schema } from '@kbn/config-schema'; import { Logger } from 'src/core/server'; -import { LicenseType } from '../../../../licensing/server'; import { STACK_ALERTS_FEATURE_ID } from '../../../common'; import { getGeoThresholdExecutor } from './geo_threshold'; -import { - ActionGroup, - AlertServices, - ActionVariable, - AlertTypeState, -} from '../../../../alerts/server'; +import { AlertType } from '../../../../alerts/server'; import { Query } from '../../../../../../src/plugins/data/common/query'; export const GEO_THRESHOLD_ID = '.geo-threshold'; @@ -178,41 +172,7 @@ export interface GeoThresholdParams { boundaryIndexQuery?: Query; } -export function getAlertType( - logger: Logger -): { - defaultActionGroupId: string; - actionGroups: ActionGroup[]; - minimumLicenseRequired: LicenseType; - executor: ({ - previousStartedAt: currIntervalStartTime, - startedAt: currIntervalEndTime, - services, - params, - alertId, - state, - }: { - previousStartedAt: Date | null; - startedAt: Date; - services: AlertServices; - params: GeoThresholdParams; - alertId: string; - state: AlertTypeState; - }) => Promise; - validate?: { - params?: { - validate: (object: unknown) => GeoThresholdParams; - }; - }; - name: string; - producer: string; - id: string; - actionVariables?: { - context?: ActionVariable[]; - state?: ActionVariable[]; - params?: ActionVariable[]; - }; -} { +export function getAlertType(logger: Logger): AlertType { const alertTypeName = i18n.translate('xpack.stackAlerts.geoThreshold.alertTypeTitle', { defaultMessage: 'Geo tracking threshold', }); diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/index.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/index.ts index 2fa2bed9d8419..16e2155ef37fc 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/index.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/index.ts @@ -5,7 +5,7 @@ */ import { Logger } from 'src/core/server'; -import { AlertingSetup } from '../../types'; +import { AlertingSetup, AlertType } from '../../types'; import { getAlertType } from './alert_type'; interface RegisterParams { @@ -15,5 +15,5 @@ interface RegisterParams { export function register(params: RegisterParams) { const { logger, alerts } = params; - alerts.registerType(getAlertType(logger)); + alerts.registerType((getAlertType(logger) as unknown) as AlertType); } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/index.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/index.ts index a075b0d614cbb..90abc2fcbe6c2 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/index.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/index.ts @@ -5,7 +5,7 @@ */ import { Logger } from 'src/core/server'; -import { AlertingSetup, StackAlertsStartDeps } from '../../types'; +import { AlertingSetup, AlertType, StackAlertsStartDeps } from '../../types'; import { getAlertType } from './alert_type'; // future enhancement: make these configurable? @@ -21,5 +21,5 @@ interface RegisterParams { export function register(params: RegisterParams) { const { logger, data, alerts } = params; - alerts.registerType(getAlertType(logger, data)); + alerts.registerType((getAlertType(logger, data) as unknown) as AlertType); } 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 80e94f8a80f0e..e8f13bf65fea8 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 @@ -242,5 +242,6 @@ function getAlertType(actionVariables: ActionVariables): AlertType { recoveryActionGroup: { id: 'recovered', name: 'Recovered' }, authorizedConsumers: {}, producer: ALERTS_FEATURE_ID, + minimumLicenseRequired: 'basic', }; } 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 e1011e2fe69b9..ed452a77e5ab1 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 @@ -51,6 +51,7 @@ describe('loadAlertTypes', () => { recoveryActionGroup: { id: 'recovered', name: 'Recovered' }, defaultActionGroupId: 'default', authorizedConsumers: {}, + minimumLicenseRequired: 'basic', }, ]; http.get.mockResolvedValueOnce(resolvedValue); diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts index ff28aea660036..1c42db9772910 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts @@ -6,7 +6,7 @@ import { CoreSetup } from 'src/core/server'; import { schema, TypeOf } from '@kbn/config-schema'; -import { times } from 'lodash'; +import { curry, times } from 'lodash'; import { LicenseType } from '../../../../../../../plugins/licensing/public'; import { ES_TEST_INDEX_NAME } from '../../../../lib'; import { FixtureStartDeps, FixtureSetupDeps } from './plugin'; @@ -50,53 +50,55 @@ function getAlwaysFiringAlertType() { params: [{ name: 'instanceParamsValue', description: 'the instance params value' }], context: [{ name: 'instanceContextValue', description: 'the instance context value' }], }, - async executor(alertExecutorOptions) { - const { - services, - params, - state, - alertId, - spaceId, - namespace, - name, - tags, - createdBy, - updatedBy, - } = alertExecutorOptions; - let group: string | null = 'default'; - const alertInfo = { alertId, spaceId, namespace, name, tags, createdBy, updatedBy }; + executor: curry(alwaysFiringExecutor)(), + }; + return (result as unknown) as AlertType; +} - if (params.groupsToScheduleActionsInSeries) { - const index = state.groupInSeriesIndex || 0; - group = params.groupsToScheduleActionsInSeries[index]; - } +async function alwaysFiringExecutor(alertExecutorOptions: any) { + const { + services, + params, + state, + alertId, + spaceId, + namespace, + name, + tags, + createdBy, + updatedBy, + } = alertExecutorOptions; + let group: string | null = 'default'; + const alertInfo = { alertId, spaceId, namespace, name, tags, createdBy, updatedBy }; - if (group) { - services - .alertInstanceFactory('1') - .replaceState({ instanceStateValue: true }) - .scheduleActions(group, { - instanceContextValue: true, - }); - } - await services.scopedClusterClient.index({ - index: params.index, - refresh: 'wait_for', - body: { - state, - params, - reference: params.reference, - source: 'alert:test.always-firing', - alertInfo, - }, + if (params.groupsToScheduleActionsInSeries) { + const index = state.groupInSeriesIndex || 0; + group = params.groupsToScheduleActionsInSeries[index]; + } + + if (group) { + services + .alertInstanceFactory('1') + .replaceState({ instanceStateValue: true }) + .scheduleActions(group, { + instanceContextValue: true, }); - return { - globalStateValue: true, - groupInSeriesIndex: (state.groupInSeriesIndex || 0) + 1, - }; + } + await services.scopedClusterClient.index({ + index: params.index, + refresh: 'wait_for', + body: { + state, + params, + reference: params.reference, + source: 'alert:test.always-firing', + alertInfo, }, + }); + return { + globalStateValue: true, + groupInSeriesIndex: (state.groupInSeriesIndex || 0) + 1, }; - return result; } function getCumulativeFiringAlertType() { @@ -134,7 +136,7 @@ function getCumulativeFiringAlertType() { }; }, }; - return result; + return result as AlertType; } function getNeverFiringAlertType() { @@ -177,7 +179,7 @@ function getNeverFiringAlertType() { }; }, }; - return result; + return (result as unknown) as AlertType; } function getFailingAlertType() { @@ -215,7 +217,7 @@ function getFailingAlertType() { throw new Error('Failed to execute alert type'); }, }; - return result; + return (result as unknown) as AlertType; } function getAuthorizationAlertType(core: CoreSetup) { @@ -307,7 +309,7 @@ function getAuthorizationAlertType(core: CoreSetup) { }); }, }; - return result; + return (result as unknown) as AlertType; } function getValidationAlertType() { @@ -332,7 +334,7 @@ function getValidationAlertType() { }, async executor() {}, }; - return result; + return (result as unknown) as AlertType; } function getPatternFiringAlertType() { @@ -393,7 +395,7 @@ function getPatternFiringAlertType() { }; }, }; - return result; + return (result as unknown) as AlertType; } export function defineAlertTypes( From 9ef4ff067aea001bc153df68433dc7debbcf872b Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Fri, 4 Dec 2020 21:52:12 -0800 Subject: [PATCH 3/8] fixed tests --- x-pack/plugins/alerts/server/alert_type_registry.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugins/alerts/server/alert_type_registry.ts b/x-pack/plugins/alerts/server/alert_type_registry.ts index a3e80fbd6c11a..e7571a71eb321 100644 --- a/x-pack/plugins/alerts/server/alert_type_registry.ts +++ b/x-pack/plugins/alerts/server/alert_type_registry.ts @@ -146,6 +146,7 @@ export class AlertTypeRegistry { defaultActionGroupId, actionVariables, producer, + minimumLicenseRequired, }, ]: [string, NormalizedAlertType]) => ({ id, @@ -155,6 +156,7 @@ export class AlertTypeRegistry { defaultActionGroupId, actionVariables, producer, + minimumLicenseRequired, }) ) ); From 956a15fb0ba3c1214fcd216dad9f1035eb242495 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Sun, 6 Dec 2020 08:13:55 -0800 Subject: [PATCH 4/8] fixed tests --- x-pack/plugins/alerts/server/alert_type_registry.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/alerts/server/alert_type_registry.test.ts b/x-pack/plugins/alerts/server/alert_type_registry.test.ts index 59ba3c865e0c1..700134bb5cb07 100644 --- a/x-pack/plugins/alerts/server/alert_type_registry.test.ts +++ b/x-pack/plugins/alerts/server/alert_type_registry.test.ts @@ -381,6 +381,7 @@ describe('list()', () => { }, "defaultActionGroupId": "testActionGroup", "id": "test", + "minimumLicenseRequired": "basic", "name": "Test", "producer": "alerts", "recoveryActionGroup": Object { From a6b5b0759064db894c22c8b84b5be63222e4d5c3 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Tue, 8 Dec 2020 09:49:04 -0800 Subject: [PATCH 5/8] fixed due to comments --- .../alerts/server/alert_type_registry.test.ts | 31 ++++---- .../task_runner/task_runner_factory.test.ts | 6 +- x-pack/plugins/stack_alerts/kibana.json | 2 +- .../components/alert_details.test.tsx | 78 +++++++++---------- .../triggers_actions_ui/public/types.ts | 15 +++- .../plugins/alerts/server/alert_types.ts | 3 +- 6 files changed, 71 insertions(+), 64 deletions(-) diff --git a/x-pack/plugins/alerts/server/alert_type_registry.test.ts b/x-pack/plugins/alerts/server/alert_type_registry.test.ts index 700134bb5cb07..ef481788d836f 100644 --- a/x-pack/plugins/alerts/server/alert_type_registry.test.ts +++ b/x-pack/plugins/alerts/server/alert_type_registry.test.ts @@ -8,7 +8,6 @@ import { TaskRunnerFactory } from './task_runner'; import { AlertTypeRegistry } from './alert_type_registry'; import { AlertType } from './types'; import { taskManagerMock } from '../../task_manager/server/mocks'; -import { LicenseType } from '../../licensing/server'; const taskManager = taskManagerMock.createSetup(); const alertTypeRegistryParams = { @@ -46,7 +45,7 @@ describe('has()', () => { describe('register()', () => { test('throws if AlertType Id contains invalid characters', () => { - const alertType = { + const alertType: AlertType = { id: 'test', name: 'Test', actionGroups: [ @@ -56,7 +55,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; @@ -78,7 +77,7 @@ describe('register()', () => { }); test('throws if AlertType Id isnt a string', () => { - const alertType = { + const alertType: AlertType = { id: (123 as unknown) as string, name: 'Test', actionGroups: [ @@ -88,7 +87,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; @@ -100,7 +99,7 @@ describe('register()', () => { }); test('throws if AlertType action groups contains reserved group id', () => { - const alertType = { + const alertType: AlertType = { id: 'test', name: 'Test', actionGroups: [ @@ -114,7 +113,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; @@ -128,7 +127,7 @@ describe('register()', () => { }); test('allows an AlertType to specify a custom recovery group', () => { - const alertType = { + const alertType: AlertType = { id: 'test', name: 'Test', actionGroups: [ @@ -144,7 +143,7 @@ describe('register()', () => { }, executor: jest.fn(), producer: 'alerts', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; const registry = new AlertTypeRegistry(alertTypeRegistryParams); registry.register(alertType); @@ -163,7 +162,7 @@ describe('register()', () => { }); test('throws if the custom recovery group is contained in the AlertType action groups', () => { - const alertType = { + const alertType: AlertType = { id: 'test', name: 'Test', actionGroups: [ @@ -181,7 +180,7 @@ describe('register()', () => { name: 'Back To Awesome', }, defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; @@ -195,7 +194,7 @@ describe('register()', () => { }); test('registers the executor with the task manager', () => { - const alertType = { + const alertType: AlertType = { id: 'test', name: 'Test', actionGroups: [ @@ -205,7 +204,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; @@ -235,7 +234,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; @@ -429,12 +428,12 @@ describe('list()', () => { }); function alertTypeWithVariables(id: string, context: string, state: string): AlertType { - const baseAlert = { + const baseAlert: AlertType = { id, name: `${id}-name`, actionGroups: [], defaultActionGroupId: id, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', }; diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts b/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts index 4c83ccb7dad91..f58939440212e 100644 --- a/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts +++ b/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts @@ -16,14 +16,14 @@ import { import { actionsMock } from '../../../actions/server/mocks'; import { alertsMock, alertsClientMock } from '../mocks'; import { eventLoggerMock } from '../../../event_log/server/event_logger.mock'; -import { LicenseType } from '../../../licensing/server'; +import { NormalizedAlertType } from '../alert_type_registry'; -const alertType = { +const alertType: NormalizedAlertType = { id: 'test', name: 'My test alert', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', recoveryActionGroup: { id: 'recovered', name: 'Recovered', diff --git a/x-pack/plugins/stack_alerts/kibana.json b/x-pack/plugins/stack_alerts/kibana.json index c4d054b4da45d..884d33ef669e5 100644 --- a/x-pack/plugins/stack_alerts/kibana.json +++ b/x-pack/plugins/stack_alerts/kibana.json @@ -3,7 +3,7 @@ "server": true, "version": "8.0.0", "kibanaVersion": "kibana", - "requiredPlugins": ["alerts", "features", "triggersActionsUi", "kibanaReact", "savedObjects", "data", "licensing"], + "requiredPlugins": ["alerts", "features", "triggersActionsUi", "kibanaReact", "savedObjects", "data"], "configPath": ["xpack", "stack_alerts"], "ui": true } 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 1454ee9aa9d8e..27a0368b34c6f 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, AlertTypeModel } from '../../../../types'; +import { Alert, ActionType, AlertTypeModel, AlertType } from '../../../../types'; import { EuiTitle, EuiBadge, EuiFlexItem, EuiSwitch, EuiButtonEmpty, EuiText } from '@elastic/eui'; import { ViewInApp } from './view_in_app'; import { @@ -55,14 +55,14 @@ describe('alert_details', () => { it('renders the alert name as a title', () => { const alert = mockAlert(); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], recoveryActionGroup, actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', producer: ALERTS_FEATURE_ID, authorizedConsumers, }; @@ -82,14 +82,14 @@ describe('alert_details', () => { it('renders the alert type badge', () => { const alert = mockAlert(); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], recoveryActionGroup, actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', producer: ALERTS_FEATURE_ID, authorizedConsumers, }; @@ -112,14 +112,14 @@ describe('alert_details', () => { }, }, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], recoveryActionGroup, actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', producer: ALERTS_FEATURE_ID, authorizedConsumers, }; @@ -148,14 +148,14 @@ describe('alert_details', () => { ], }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], recoveryActionGroup, actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', producer: ALERTS_FEATURE_ID, authorizedConsumers, }; @@ -204,7 +204,7 @@ describe('alert_details', () => { }, ], }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -212,7 +212,7 @@ describe('alert_details', () => { actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', authorizedConsumers, }; const actionTypes: ActionType[] = [ @@ -265,7 +265,7 @@ describe('alert_details', () => { it('links to the app that created the alert', () => { const alert = mockAlert(); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -274,7 +274,7 @@ describe('alert_details', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; expect( @@ -287,7 +287,7 @@ describe('alert_details', () => { it('links to the Edit flyout', () => { const alert = mockAlert(); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -296,7 +296,7 @@ describe('alert_details', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; expect( @@ -318,7 +318,7 @@ describe('disable button', () => { enabled: true, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -327,7 +327,7 @@ describe('disable button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; const enableButton = shallow( @@ -348,7 +348,7 @@ describe('disable button', () => { enabled: false, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -357,7 +357,7 @@ describe('disable button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; const enableButton = shallow( @@ -378,7 +378,7 @@ describe('disable button', () => { enabled: true, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -387,7 +387,7 @@ describe('disable button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; const disableAlert = jest.fn(); @@ -417,7 +417,7 @@ describe('disable button', () => { enabled: false, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -426,7 +426,7 @@ describe('disable button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; const enableAlert = jest.fn(); @@ -459,7 +459,7 @@ describe('mute button', () => { muteAll: false, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -468,7 +468,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; const enableButton = shallow( @@ -490,7 +490,7 @@ describe('mute button', () => { muteAll: true, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -499,7 +499,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; const enableButton = shallow( @@ -521,7 +521,7 @@ describe('mute button', () => { muteAll: false, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -530,7 +530,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; const muteAlert = jest.fn(); @@ -561,7 +561,7 @@ describe('mute button', () => { muteAll: true, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -570,7 +570,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; const unmuteAlert = jest.fn(); @@ -601,7 +601,7 @@ describe('mute button', () => { muteAll: false, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -610,7 +610,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; const enableButton = shallow( @@ -668,7 +668,7 @@ describe('edit button', () => { ], }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -677,7 +677,7 @@ describe('edit button', () => { defaultActionGroupId: 'default', producer: 'alerting', authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; expect( @@ -712,7 +712,7 @@ describe('edit button', () => { ], }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -721,7 +721,7 @@ describe('edit button', () => { defaultActionGroupId: 'default', producer: 'alerting', authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; expect( @@ -749,7 +749,7 @@ describe('edit button', () => { actions: [], }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -758,7 +758,7 @@ describe('edit button', () => { defaultActionGroupId: 'default', producer: 'alerting', authorizedConsumers, - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', }; expect( diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index d53918b24d505..b54d5c9e8f9b7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -9,7 +9,7 @@ import { ComponentType } from 'react'; import { ActionGroup, AlertActionParam } from '../../alerts/common'; import { ActionType } from '../../actions/common'; import { TypeRegistry } from './application/type_registry'; -import { AlertType as AlertTypeApi } from '../../alerts/common'; +import { AlertType as CommonAlertType } from '../../alerts/common'; import { SanitizedAlert as Alert, AlertAction, @@ -136,8 +136,17 @@ export const OPTIONAL_ACTION_VARIABLES = ['context'] as const; export type ActionVariables = AsActionVariables & Partial>; -export interface AlertType extends Omit { - recoveryActionGroup: ActionGroup; +export interface AlertType + extends Pick< + CommonAlertType, + | 'id' + | 'name' + | 'actionGroups' + | 'producer' + | 'minimumLicenseRequired' + | 'recoveryActionGroup' + | 'defaultActionGroupId' + > { actionVariables: ActionVariables; authorizedConsumers: Record; } diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts index 1c42db9772910..4a37b76573af4 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts @@ -7,7 +7,6 @@ import { CoreSetup } from 'src/core/server'; import { schema, TypeOf } from '@kbn/config-schema'; import { curry, times } from 'lodash'; -import { LicenseType } from '../../../../../../../plugins/licensing/public'; import { ES_TEST_INDEX_NAME } from '../../../../lib'; import { FixtureStartDeps, FixtureSetupDeps } from './plugin'; import { @@ -44,7 +43,7 @@ function getAlwaysFiringAlertType() { }, producer: 'alertsFixture', defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', actionVariables: { state: [{ name: 'instanceStateValue', description: 'the instance state value' }], params: [{ name: 'instanceParamsValue', description: 'the instance params value' }], From 6503ba8d7dec22210df16f459da04b42c4119598 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Tue, 8 Dec 2020 10:30:49 -0800 Subject: [PATCH 6/8] fixed due to comments --- x-pack/plugins/alerts/server/plugin.ts | 27 +- .../server/alerts/base_alert.ts.orig | 452 ++++++++++++++++++ .../alert_types/geo_containment/index.ts | 6 +- .../server/alert_types/geo_threshold/index.ts | 4 +- .../alert_types/index_threshold/index.ts | 4 +- .../components/alert_details.test.tsx | 7 +- .../plugins/alerts/server/alert_types.ts | 12 +- 7 files changed, 492 insertions(+), 20 deletions(-) create mode 100644 x-pack/plugins/monitoring/server/alerts/base_alert.ts.orig diff --git a/x-pack/plugins/alerts/server/plugin.ts b/x-pack/plugins/alerts/server/plugin.ts index e4ddf44b8808c..9122ca405e03e 100644 --- a/x-pack/plugins/alerts/server/plugin.ts +++ b/x-pack/plugins/alerts/server/plugin.ts @@ -59,7 +59,15 @@ import { PluginSetupContract as ActionsPluginSetupContract, PluginStartContract as ActionsPluginStartContract, } from '../../actions/server'; -import { AlertsHealth, AlertType, Services } from './types'; +import { + AlertInstanceContext, + AlertInstanceState, + AlertsHealth, + AlertType, + AlertTypeParams, + AlertTypeState, + Services, +} from './types'; import { registerAlertsUsageCollector } from './usage'; import { initializeAlertingTelemetry, scheduleAlertingTelemetry } from './usage/task'; import { IEventLogger, IEventLogService, IEventLogClientService } from '../../event_log/server'; @@ -90,8 +98,16 @@ export const LEGACY_EVENT_LOG_ACTIONS = { }; export interface PluginSetupContract { - registerType: (alertType: AlertType) => void; + registerType< + Params extends AlertTypeParams = AlertTypeParams, + State extends AlertTypeState = AlertTypeState, + InstanceState extends AlertInstanceState = AlertInstanceState, + InstanceContext extends AlertInstanceContext = AlertInstanceContext + >( + alertType: AlertType + ): void; } + export interface PluginStartContract { listTypes: AlertTypeRegistry['list']; getAlertsClientWithRequest(request: KibanaRequest): PublicMethodsOf; @@ -250,7 +266,12 @@ export class AlertingPlugin { healthRoute(router, this.licenseState, plugins.encryptedSavedObjects); return { - registerType: (alertType: AlertType) => { + registerType< + Params extends AlertTypeParams = AlertTypeParams, + State extends AlertTypeState = AlertTypeState, + InstanceState extends AlertInstanceState = AlertInstanceState, + InstanceContext extends AlertInstanceContext = AlertInstanceContext + >(alertType: AlertType) { if (!(alertType.minimumLicenseRequired in LICENSE_TYPE)) { throw new Error(`"${alertType.minimumLicenseRequired}" is not a valid license type`); } diff --git a/x-pack/plugins/monitoring/server/alerts/base_alert.ts.orig b/x-pack/plugins/monitoring/server/alerts/base_alert.ts.orig new file mode 100644 index 0000000000000..cd21d834a438b --- /dev/null +++ b/x-pack/plugins/monitoring/server/alerts/base_alert.ts.orig @@ -0,0 +1,452 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Logger, LegacyCallAPIOptions } from 'kibana/server'; +import { i18n } from '@kbn/i18n'; +import { + AlertType, + AlertExecutorOptions, + AlertInstance, + AlertsClient, + AlertServices, +} from '../../../alerts/server'; +import { Alert, RawAlertInstance, SanitizedAlert } from '../../../alerts/common'; +import { ActionsClient } from '../../../actions/server'; +import { + AlertState, + AlertNodeState, + AlertCluster, + AlertMessage, + AlertData, + AlertInstanceState, + AlertEnableAction, + CommonAlertFilter, + CommonAlertParams, + LegacyAlert, +} from '../../common/types/alerts'; +import { fetchAvailableCcs } from '../lib/alerts/fetch_available_ccs'; +import { fetchClusters } from '../lib/alerts/fetch_clusters'; +import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; +import { INDEX_PATTERN_ELASTICSEARCH, INDEX_ALERTS } from '../../common/constants'; +import { AlertSeverity } from '../../common/enums'; +import { MonitoringLicenseService } from '../types'; +import { mbSafeQuery } from '../lib/mb_safe_query'; +import { appendMetricbeatIndex } from '../lib/alerts/append_mb_index'; +import { parseDuration } from '../../../alerts/common/parse_duration'; +import { Globals } from '../static_globals'; +import { fetchLegacyAlerts } from '../lib/alerts/fetch_legacy_alerts'; +import { mapLegacySeverity } from '../lib/alerts/map_legacy_severity'; + +interface LegacyOptions { + watchName: string; + changeDataValues?: Partial; +} + +type ExecutedState = + | { + lastChecked: number; + lastExecutedAction: number; + [key: string]: unknown; + } + | Record; + +interface AlertOptions { + id: string; + name: string; + throttle?: string | null; + interval?: string; + legacy?: LegacyOptions; + defaultParams?: CommonAlertParams; + actionVariables: Array<{ name: string; description: string }>; + fetchClustersRange?: number; + accessorKey?: string; +} + +type CallCluster = ( + endpoint: string, + clientParams?: Record | undefined, + options?: LegacyCallAPIOptions | undefined +) => Promise; + +const defaultAlertOptions = (): AlertOptions => { + return { + id: '', + name: '', + throttle: '1d', + interval: '1m', + defaultParams: { threshold: 85, duration: '1h' }, + actionVariables: [], + }; +}; +export class BaseAlert { + protected scopedLogger: Logger; + + constructor( + public rawAlert?: SanitizedAlert, + public alertOptions: AlertOptions = defaultAlertOptions() + ) { + this.alertOptions = { ...defaultAlertOptions(), ...this.alertOptions }; + this.scopedLogger = Globals.app.getLogger(alertOptions.id!); + } + + public getAlertType(): AlertType { + const { id, name, actionVariables } = this.alertOptions; + return { + id, + name, + actionGroups: [ + { + id: 'default', + name: i18n.translate('xpack.monitoring.alerts.actionGroups.default', { + defaultMessage: 'Default', + }), + }, + ], + defaultActionGroupId: 'default', +<<<<<<< HEAD + minimumLicenseRequired: 'basic', + executor: (options: AlertExecutorOptions): Promise => this.execute(options), +======= + executor: (options: AlertExecutorOptions & { state: ExecutedState }): Promise => + this.execute(options), +>>>>>>> upstream/alerts/license-checks + producer: 'monitoring', + actionVariables: { + context: actionVariables, + }, + }; + } + + public isEnabled(licenseService: MonitoringLicenseService) { + if (this.alertOptions.legacy) { + const watcherFeature = licenseService.getWatcherFeature(); + if (!watcherFeature.isAvailable || !watcherFeature.isEnabled) { + return false; + } + } + return true; + } + + public getId() { + return this.rawAlert?.id; + } + + public async createIfDoesNotExist( + alertsClient: AlertsClient, + actionsClient: ActionsClient, + actions: AlertEnableAction[] + ): Promise { + const existingAlertData = await alertsClient.find({ + options: { + search: this.alertOptions.id, + }, + }); + + if (existingAlertData.total > 0) { + const existingAlert = existingAlertData.data[0] as Alert; + return existingAlert; + } + + const alertActions = []; + for (const actionData of actions) { + const action = await actionsClient.get({ id: actionData.id }); + if (!action) { + continue; + } + alertActions.push({ + group: 'default', + id: actionData.id, + params: { + message: '{{context.internalShortMessage}}', + ...actionData.config, + }, + }); + } + + const { + defaultParams: params = {}, + name, + id: alertTypeId, + throttle = '1d', + interval = '1m', + } = this.alertOptions; + return await alertsClient.create({ + data: { + enabled: true, + tags: [], + params, + consumer: 'monitoring', + name, + alertTypeId, + throttle, + schedule: { interval }, + actions: alertActions, + }, + }); + } + + public async getStates( + alertsClient: AlertsClient, + id: string, + filters: CommonAlertFilter[] + ): Promise<{ [instanceId: string]: RawAlertInstance }> { + const states = await alertsClient.getAlertState({ id }); + if (!states || !states.alertInstances) { + return {}; + } + + return Object.keys(states.alertInstances).reduce( + (accum: { [instanceId: string]: RawAlertInstance }, instanceId) => { + if (!states.alertInstances) { + return accum; + } + const alertInstance: RawAlertInstance = states.alertInstances[instanceId]; + if (alertInstance && this.filterAlertInstance(alertInstance, filters)) { + accum[instanceId] = alertInstance; + if (alertInstance.state) { + accum[instanceId].state = { + alertStates: (alertInstance.state as AlertInstanceState).alertStates, + }; + } + } + return accum; + }, + {} + ); + } + + protected filterAlertInstance( + alertInstance: RawAlertInstance, + filters: CommonAlertFilter[], + filterOnNodes: boolean = false + ) { + if (!filterOnNodes) { + return true; + } + const alertInstanceStates = alertInstance.state?.alertStates as AlertNodeState[]; + const nodeFilter = filters?.find((filter) => filter.nodeUuid); + if (!filters || !filters.length || !alertInstanceStates?.length || !nodeFilter?.nodeUuid) { + return true; + } + const nodeAlerts = alertInstanceStates.filter(({ nodeId }) => nodeId === nodeFilter.nodeUuid); + return Boolean(nodeAlerts.length); + } + + protected async execute({ + services, + params, + state, + }: AlertExecutorOptions & { state: ExecutedState }): Promise { + this.scopedLogger.debug( + `Executing alert with params: ${JSON.stringify(params)} and state: ${JSON.stringify(state)}` + ); + + const useCallCluster = + Globals.app.monitoringCluster?.callAsInternalUser || services.callCluster; + const callCluster = async ( + endpoint: string, + clientParams?: Record, + options?: LegacyCallAPIOptions + ) => { + return await mbSafeQuery(async () => useCallCluster(endpoint, clientParams, options)); + }; + const availableCcs = Globals.app.config.ui.ccs.enabled + ? await fetchAvailableCcs(callCluster) + : []; + const clusters = await this.fetchClusters( + callCluster, + params as CommonAlertParams, + availableCcs + ); + if (this.alertOptions.legacy) { + const data = await this.fetchLegacyData(callCluster, clusters, availableCcs); + return await this.processLegacyData(data, clusters, services, state); + } + const data = await this.fetchData(params, callCluster, clusters, availableCcs); + return await this.processData(data, clusters, services, state); + } + + protected async fetchClusters( + callCluster: CallCluster, + params: CommonAlertParams, + ccs?: string[] + ) { + let esIndexPattern = appendMetricbeatIndex(Globals.app.config, INDEX_PATTERN_ELASTICSEARCH); + if (ccs?.length) { + esIndexPattern = getCcsIndexPattern(esIndexPattern, ccs); + } + if (!params.limit) { + return await fetchClusters(callCluster, esIndexPattern); + } + const limit = parseDuration(params.limit); + const rangeFilter = this.alertOptions.fetchClustersRange + ? { + timestamp: { + format: 'epoch_millis', + gte: limit - this.alertOptions.fetchClustersRange, + }, + } + : undefined; + return await fetchClusters(callCluster, esIndexPattern, rangeFilter); + } + + protected async fetchData( + params: CommonAlertParams | unknown, + callCluster: CallCluster, + clusters: AlertCluster[], + availableCcs: string[] + ): Promise> { + throw new Error('Child classes must implement `fetchData`'); + } + + protected async fetchLegacyData( + callCluster: CallCluster, + clusters: AlertCluster[], + availableCcs: string[] + ): Promise { + let alertIndexPattern = INDEX_ALERTS; + if (availableCcs) { + alertIndexPattern = getCcsIndexPattern(alertIndexPattern, availableCcs); + } + const legacyAlerts = await fetchLegacyAlerts( + callCluster, + clusters, + alertIndexPattern, + this.alertOptions.legacy!.watchName, + Globals.app.config.ui.max_bucket_size + ); + + return legacyAlerts.map((legacyAlert) => { + return { + clusterUuid: legacyAlert.metadata.cluster_uuid, + shouldFire: !legacyAlert.resolved_timestamp, + severity: mapLegacySeverity(legacyAlert.metadata.severity), + meta: legacyAlert, + ...this.alertOptions.legacy!.changeDataValues, + }; + }); + } + + protected async processData( + data: AlertData[], + clusters: AlertCluster[], + services: AlertServices, + state: ExecutedState + ) { + const currentUTC = +new Date(); + for (const cluster of clusters) { + const nodes = data.filter((node) => node.clusterUuid === cluster.clusterUuid); + if (!nodes.length) { + continue; + } + + const firingNodeUuids = nodes + .filter((node) => node.shouldFire) + .map((node) => node.meta.nodeId) + .join(','); + const instanceId = `${this.alertOptions.id}:${cluster.clusterUuid}:${firingNodeUuids}`; + const instance = services.alertInstanceFactory(instanceId); + const newAlertStates: AlertNodeState[] = []; + const key = this.alertOptions.accessorKey; + for (const node of nodes) { + if (!node.shouldFire) { + continue; + } + const stat = node.meta as AlertNodeState; + const nodeState = this.getDefaultAlertState(cluster, node) as AlertNodeState; + if (key) { + nodeState[key] = stat[key]; + } + nodeState.nodeId = stat.nodeId || node.nodeId!; + nodeState.nodeName = stat.nodeName || node.nodeName || nodeState.nodeId; + nodeState.ui.triggeredMS = currentUTC; + nodeState.ui.isFiring = true; + nodeState.ui.severity = node.severity; + nodeState.ui.message = this.getUiMessage(nodeState, node); + newAlertStates.push(nodeState); + } + + const alertInstanceState = { alertStates: newAlertStates }; + instance.replaceState(alertInstanceState); + if (newAlertStates.length) { + this.executeActions(instance, alertInstanceState, null, cluster); + state.lastExecutedAction = currentUTC; + } + } + + state.lastChecked = currentUTC; + return state; + } + + protected async processLegacyData( + data: AlertData[], + clusters: AlertCluster[], + services: AlertServices, + state: ExecutedState + ) { + const currentUTC = +new Date(); + for (const item of data) { + const instanceId = `${this.alertOptions.id}:${item.clusterUuid}`; + const instance = services.alertInstanceFactory(instanceId); + if (!item.shouldFire) { + instance.replaceState({ alertStates: [] }); + continue; + } + const cluster = clusters.find((c: AlertCluster) => c.clusterUuid === item.clusterUuid); + const alertState: AlertState = this.getDefaultAlertState(cluster!, item); + alertState.ui.triggeredMS = currentUTC; + alertState.ui.isFiring = true; + alertState.ui.severity = item.severity; + alertState.ui.message = this.getUiMessage(alertState, item); + instance.replaceState({ alertStates: [alertState] }); + this.executeActions(instance, alertState, item, cluster); + } + state.lastChecked = currentUTC; + return state; + } + + protected getDefaultAlertState(cluster: AlertCluster, item: AlertData): AlertState { + return { + cluster, + ccs: item.ccs, + ui: { + isFiring: false, + message: null, + severity: AlertSeverity.Success, + triggeredMS: 0, + lastCheckedMS: 0, + }, + }; + } + + protected getVersions(legacyAlert: LegacyAlert) { + return `[${legacyAlert.message.match(/(?<=Versions: \[).+?(?=\])/)}]`; + } + + protected getUiMessage( + alertState: AlertState | unknown, + item: AlertData | unknown + ): AlertMessage { + throw new Error('Child classes must implement `getUiMessage`'); + } + + protected executeActions( + instance: AlertInstance, + instanceState: AlertInstanceState | AlertState | unknown, + item: AlertData | unknown, + cluster?: AlertCluster | unknown + ) { + throw new Error('Child classes must implement `executeActions`'); + } + + protected createGlobalStateLink(link: string, clusterUuid: string, ccs?: string) { + const globalState = [`cluster_uuid:${clusterUuid}`]; + if (ccs) { + globalState.push(`ccs:${ccs}`); + } + return `${Globals.app.url}/app/monitoring#/${link}?_g=(${globalState.toString()})`; + } +} diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts index 16e2155ef37fc..02116d0701bfa 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts @@ -5,8 +5,8 @@ */ import { Logger } from 'src/core/server'; -import { AlertingSetup, AlertType } from '../../types'; -import { getAlertType } from './alert_type'; +import { AlertingSetup } from '../../types'; +import { GeoContainmentParams, getAlertType } from './alert_type'; interface RegisterParams { logger: Logger; @@ -15,5 +15,5 @@ interface RegisterParams { export function register(params: RegisterParams) { const { logger, alerts } = params; - alerts.registerType((getAlertType(logger) as unknown) as AlertType); + alerts.registerType(getAlertType(logger)); } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/index.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/index.ts index 16e2155ef37fc..2fa2bed9d8419 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/index.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/index.ts @@ -5,7 +5,7 @@ */ import { Logger } from 'src/core/server'; -import { AlertingSetup, AlertType } from '../../types'; +import { AlertingSetup } from '../../types'; import { getAlertType } from './alert_type'; interface RegisterParams { @@ -15,5 +15,5 @@ interface RegisterParams { export function register(params: RegisterParams) { const { logger, alerts } = params; - alerts.registerType((getAlertType(logger) as unknown) as AlertType); + alerts.registerType(getAlertType(logger)); } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/index.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/index.ts index 90abc2fcbe6c2..a075b0d614cbb 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/index.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/index.ts @@ -5,7 +5,7 @@ */ import { Logger } from 'src/core/server'; -import { AlertingSetup, AlertType, StackAlertsStartDeps } from '../../types'; +import { AlertingSetup, StackAlertsStartDeps } from '../../types'; import { getAlertType } from './alert_type'; // future enhancement: make these configurable? @@ -21,5 +21,5 @@ interface RegisterParams { export function register(params: RegisterParams) { const { logger, data, alerts } = params; - alerts.registerType((getAlertType(logger, data) as unknown) as AlertType); + alerts.registerType(getAlertType(logger, data)); } 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 27a0368b34c6f..d2d4efc5973c0 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 @@ -16,7 +16,6 @@ import { } from '../../../../../../alerts/common'; import { useKibana } from '../../../../common/lib/kibana'; import { alertTypeRegistryMock } from '../../../alert_type_registry.mock'; -import { LicenseType } from '../../../../../../licensing/public'; jest.mock('../../../../common/lib/kibana'); @@ -639,7 +638,7 @@ describe('edit button', () => { }, ]; alertTypeRegistry.has.mockReturnValue(true); - const alertTypeR = ({ + const alertTypeR: AlertTypeModel = { id: 'my-alert-type', iconClass: 'test', name: 'test-alert', @@ -648,9 +647,9 @@ describe('edit button', () => { validate: () => { return { errors: {} }; }, - alertParamsExpression: () => {}, + alertParamsExpression: jest.fn(), requiresAppContext: false, - } as unknown) as AlertTypeModel; + }; alertTypeRegistry.get.mockReturnValue(alertTypeR); useKibanaMock().services.alertTypeRegistry = alertTypeRegistry; diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts index 4a37b76573af4..f4928d5fc60d3 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts @@ -51,7 +51,7 @@ function getAlwaysFiringAlertType() { }, executor: curry(alwaysFiringExecutor)(), }; - return (result as unknown) as AlertType; + return result; } async function alwaysFiringExecutor(alertExecutorOptions: any) { @@ -178,7 +178,7 @@ function getNeverFiringAlertType() { }; }, }; - return (result as unknown) as AlertType; + return result; } function getFailingAlertType() { @@ -216,7 +216,7 @@ function getFailingAlertType() { throw new Error('Failed to execute alert type'); }, }; - return (result as unknown) as AlertType; + return result; } function getAuthorizationAlertType(core: CoreSetup) { @@ -308,7 +308,7 @@ function getAuthorizationAlertType(core: CoreSetup) { }); }, }; - return (result as unknown) as AlertType; + return result; } function getValidationAlertType() { @@ -333,7 +333,7 @@ function getValidationAlertType() { }, async executor() {}, }; - return (result as unknown) as AlertType; + return result; } function getPatternFiringAlertType() { @@ -394,7 +394,7 @@ function getPatternFiringAlertType() { }; }, }; - return (result as unknown) as AlertType; + return result; } export function defineAlertTypes( From 5f3fa51206c01b7c5443393c84c84b469848d2c1 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Tue, 8 Dec 2020 10:43:15 -0800 Subject: [PATCH 7/8] removed file --- .../server/alerts/base_alert.ts.orig | 452 ------------------ 1 file changed, 452 deletions(-) delete mode 100644 x-pack/plugins/monitoring/server/alerts/base_alert.ts.orig diff --git a/x-pack/plugins/monitoring/server/alerts/base_alert.ts.orig b/x-pack/plugins/monitoring/server/alerts/base_alert.ts.orig deleted file mode 100644 index cd21d834a438b..0000000000000 --- a/x-pack/plugins/monitoring/server/alerts/base_alert.ts.orig +++ /dev/null @@ -1,452 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Logger, LegacyCallAPIOptions } from 'kibana/server'; -import { i18n } from '@kbn/i18n'; -import { - AlertType, - AlertExecutorOptions, - AlertInstance, - AlertsClient, - AlertServices, -} from '../../../alerts/server'; -import { Alert, RawAlertInstance, SanitizedAlert } from '../../../alerts/common'; -import { ActionsClient } from '../../../actions/server'; -import { - AlertState, - AlertNodeState, - AlertCluster, - AlertMessage, - AlertData, - AlertInstanceState, - AlertEnableAction, - CommonAlertFilter, - CommonAlertParams, - LegacyAlert, -} from '../../common/types/alerts'; -import { fetchAvailableCcs } from '../lib/alerts/fetch_available_ccs'; -import { fetchClusters } from '../lib/alerts/fetch_clusters'; -import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; -import { INDEX_PATTERN_ELASTICSEARCH, INDEX_ALERTS } from '../../common/constants'; -import { AlertSeverity } from '../../common/enums'; -import { MonitoringLicenseService } from '../types'; -import { mbSafeQuery } from '../lib/mb_safe_query'; -import { appendMetricbeatIndex } from '../lib/alerts/append_mb_index'; -import { parseDuration } from '../../../alerts/common/parse_duration'; -import { Globals } from '../static_globals'; -import { fetchLegacyAlerts } from '../lib/alerts/fetch_legacy_alerts'; -import { mapLegacySeverity } from '../lib/alerts/map_legacy_severity'; - -interface LegacyOptions { - watchName: string; - changeDataValues?: Partial; -} - -type ExecutedState = - | { - lastChecked: number; - lastExecutedAction: number; - [key: string]: unknown; - } - | Record; - -interface AlertOptions { - id: string; - name: string; - throttle?: string | null; - interval?: string; - legacy?: LegacyOptions; - defaultParams?: CommonAlertParams; - actionVariables: Array<{ name: string; description: string }>; - fetchClustersRange?: number; - accessorKey?: string; -} - -type CallCluster = ( - endpoint: string, - clientParams?: Record | undefined, - options?: LegacyCallAPIOptions | undefined -) => Promise; - -const defaultAlertOptions = (): AlertOptions => { - return { - id: '', - name: '', - throttle: '1d', - interval: '1m', - defaultParams: { threshold: 85, duration: '1h' }, - actionVariables: [], - }; -}; -export class BaseAlert { - protected scopedLogger: Logger; - - constructor( - public rawAlert?: SanitizedAlert, - public alertOptions: AlertOptions = defaultAlertOptions() - ) { - this.alertOptions = { ...defaultAlertOptions(), ...this.alertOptions }; - this.scopedLogger = Globals.app.getLogger(alertOptions.id!); - } - - public getAlertType(): AlertType { - const { id, name, actionVariables } = this.alertOptions; - return { - id, - name, - actionGroups: [ - { - id: 'default', - name: i18n.translate('xpack.monitoring.alerts.actionGroups.default', { - defaultMessage: 'Default', - }), - }, - ], - defaultActionGroupId: 'default', -<<<<<<< HEAD - minimumLicenseRequired: 'basic', - executor: (options: AlertExecutorOptions): Promise => this.execute(options), -======= - executor: (options: AlertExecutorOptions & { state: ExecutedState }): Promise => - this.execute(options), ->>>>>>> upstream/alerts/license-checks - producer: 'monitoring', - actionVariables: { - context: actionVariables, - }, - }; - } - - public isEnabled(licenseService: MonitoringLicenseService) { - if (this.alertOptions.legacy) { - const watcherFeature = licenseService.getWatcherFeature(); - if (!watcherFeature.isAvailable || !watcherFeature.isEnabled) { - return false; - } - } - return true; - } - - public getId() { - return this.rawAlert?.id; - } - - public async createIfDoesNotExist( - alertsClient: AlertsClient, - actionsClient: ActionsClient, - actions: AlertEnableAction[] - ): Promise { - const existingAlertData = await alertsClient.find({ - options: { - search: this.alertOptions.id, - }, - }); - - if (existingAlertData.total > 0) { - const existingAlert = existingAlertData.data[0] as Alert; - return existingAlert; - } - - const alertActions = []; - for (const actionData of actions) { - const action = await actionsClient.get({ id: actionData.id }); - if (!action) { - continue; - } - alertActions.push({ - group: 'default', - id: actionData.id, - params: { - message: '{{context.internalShortMessage}}', - ...actionData.config, - }, - }); - } - - const { - defaultParams: params = {}, - name, - id: alertTypeId, - throttle = '1d', - interval = '1m', - } = this.alertOptions; - return await alertsClient.create({ - data: { - enabled: true, - tags: [], - params, - consumer: 'monitoring', - name, - alertTypeId, - throttle, - schedule: { interval }, - actions: alertActions, - }, - }); - } - - public async getStates( - alertsClient: AlertsClient, - id: string, - filters: CommonAlertFilter[] - ): Promise<{ [instanceId: string]: RawAlertInstance }> { - const states = await alertsClient.getAlertState({ id }); - if (!states || !states.alertInstances) { - return {}; - } - - return Object.keys(states.alertInstances).reduce( - (accum: { [instanceId: string]: RawAlertInstance }, instanceId) => { - if (!states.alertInstances) { - return accum; - } - const alertInstance: RawAlertInstance = states.alertInstances[instanceId]; - if (alertInstance && this.filterAlertInstance(alertInstance, filters)) { - accum[instanceId] = alertInstance; - if (alertInstance.state) { - accum[instanceId].state = { - alertStates: (alertInstance.state as AlertInstanceState).alertStates, - }; - } - } - return accum; - }, - {} - ); - } - - protected filterAlertInstance( - alertInstance: RawAlertInstance, - filters: CommonAlertFilter[], - filterOnNodes: boolean = false - ) { - if (!filterOnNodes) { - return true; - } - const alertInstanceStates = alertInstance.state?.alertStates as AlertNodeState[]; - const nodeFilter = filters?.find((filter) => filter.nodeUuid); - if (!filters || !filters.length || !alertInstanceStates?.length || !nodeFilter?.nodeUuid) { - return true; - } - const nodeAlerts = alertInstanceStates.filter(({ nodeId }) => nodeId === nodeFilter.nodeUuid); - return Boolean(nodeAlerts.length); - } - - protected async execute({ - services, - params, - state, - }: AlertExecutorOptions & { state: ExecutedState }): Promise { - this.scopedLogger.debug( - `Executing alert with params: ${JSON.stringify(params)} and state: ${JSON.stringify(state)}` - ); - - const useCallCluster = - Globals.app.monitoringCluster?.callAsInternalUser || services.callCluster; - const callCluster = async ( - endpoint: string, - clientParams?: Record, - options?: LegacyCallAPIOptions - ) => { - return await mbSafeQuery(async () => useCallCluster(endpoint, clientParams, options)); - }; - const availableCcs = Globals.app.config.ui.ccs.enabled - ? await fetchAvailableCcs(callCluster) - : []; - const clusters = await this.fetchClusters( - callCluster, - params as CommonAlertParams, - availableCcs - ); - if (this.alertOptions.legacy) { - const data = await this.fetchLegacyData(callCluster, clusters, availableCcs); - return await this.processLegacyData(data, clusters, services, state); - } - const data = await this.fetchData(params, callCluster, clusters, availableCcs); - return await this.processData(data, clusters, services, state); - } - - protected async fetchClusters( - callCluster: CallCluster, - params: CommonAlertParams, - ccs?: string[] - ) { - let esIndexPattern = appendMetricbeatIndex(Globals.app.config, INDEX_PATTERN_ELASTICSEARCH); - if (ccs?.length) { - esIndexPattern = getCcsIndexPattern(esIndexPattern, ccs); - } - if (!params.limit) { - return await fetchClusters(callCluster, esIndexPattern); - } - const limit = parseDuration(params.limit); - const rangeFilter = this.alertOptions.fetchClustersRange - ? { - timestamp: { - format: 'epoch_millis', - gte: limit - this.alertOptions.fetchClustersRange, - }, - } - : undefined; - return await fetchClusters(callCluster, esIndexPattern, rangeFilter); - } - - protected async fetchData( - params: CommonAlertParams | unknown, - callCluster: CallCluster, - clusters: AlertCluster[], - availableCcs: string[] - ): Promise> { - throw new Error('Child classes must implement `fetchData`'); - } - - protected async fetchLegacyData( - callCluster: CallCluster, - clusters: AlertCluster[], - availableCcs: string[] - ): Promise { - let alertIndexPattern = INDEX_ALERTS; - if (availableCcs) { - alertIndexPattern = getCcsIndexPattern(alertIndexPattern, availableCcs); - } - const legacyAlerts = await fetchLegacyAlerts( - callCluster, - clusters, - alertIndexPattern, - this.alertOptions.legacy!.watchName, - Globals.app.config.ui.max_bucket_size - ); - - return legacyAlerts.map((legacyAlert) => { - return { - clusterUuid: legacyAlert.metadata.cluster_uuid, - shouldFire: !legacyAlert.resolved_timestamp, - severity: mapLegacySeverity(legacyAlert.metadata.severity), - meta: legacyAlert, - ...this.alertOptions.legacy!.changeDataValues, - }; - }); - } - - protected async processData( - data: AlertData[], - clusters: AlertCluster[], - services: AlertServices, - state: ExecutedState - ) { - const currentUTC = +new Date(); - for (const cluster of clusters) { - const nodes = data.filter((node) => node.clusterUuid === cluster.clusterUuid); - if (!nodes.length) { - continue; - } - - const firingNodeUuids = nodes - .filter((node) => node.shouldFire) - .map((node) => node.meta.nodeId) - .join(','); - const instanceId = `${this.alertOptions.id}:${cluster.clusterUuid}:${firingNodeUuids}`; - const instance = services.alertInstanceFactory(instanceId); - const newAlertStates: AlertNodeState[] = []; - const key = this.alertOptions.accessorKey; - for (const node of nodes) { - if (!node.shouldFire) { - continue; - } - const stat = node.meta as AlertNodeState; - const nodeState = this.getDefaultAlertState(cluster, node) as AlertNodeState; - if (key) { - nodeState[key] = stat[key]; - } - nodeState.nodeId = stat.nodeId || node.nodeId!; - nodeState.nodeName = stat.nodeName || node.nodeName || nodeState.nodeId; - nodeState.ui.triggeredMS = currentUTC; - nodeState.ui.isFiring = true; - nodeState.ui.severity = node.severity; - nodeState.ui.message = this.getUiMessage(nodeState, node); - newAlertStates.push(nodeState); - } - - const alertInstanceState = { alertStates: newAlertStates }; - instance.replaceState(alertInstanceState); - if (newAlertStates.length) { - this.executeActions(instance, alertInstanceState, null, cluster); - state.lastExecutedAction = currentUTC; - } - } - - state.lastChecked = currentUTC; - return state; - } - - protected async processLegacyData( - data: AlertData[], - clusters: AlertCluster[], - services: AlertServices, - state: ExecutedState - ) { - const currentUTC = +new Date(); - for (const item of data) { - const instanceId = `${this.alertOptions.id}:${item.clusterUuid}`; - const instance = services.alertInstanceFactory(instanceId); - if (!item.shouldFire) { - instance.replaceState({ alertStates: [] }); - continue; - } - const cluster = clusters.find((c: AlertCluster) => c.clusterUuid === item.clusterUuid); - const alertState: AlertState = this.getDefaultAlertState(cluster!, item); - alertState.ui.triggeredMS = currentUTC; - alertState.ui.isFiring = true; - alertState.ui.severity = item.severity; - alertState.ui.message = this.getUiMessage(alertState, item); - instance.replaceState({ alertStates: [alertState] }); - this.executeActions(instance, alertState, item, cluster); - } - state.lastChecked = currentUTC; - return state; - } - - protected getDefaultAlertState(cluster: AlertCluster, item: AlertData): AlertState { - return { - cluster, - ccs: item.ccs, - ui: { - isFiring: false, - message: null, - severity: AlertSeverity.Success, - triggeredMS: 0, - lastCheckedMS: 0, - }, - }; - } - - protected getVersions(legacyAlert: LegacyAlert) { - return `[${legacyAlert.message.match(/(?<=Versions: \[).+?(?=\])/)}]`; - } - - protected getUiMessage( - alertState: AlertState | unknown, - item: AlertData | unknown - ): AlertMessage { - throw new Error('Child classes must implement `getUiMessage`'); - } - - protected executeActions( - instance: AlertInstance, - instanceState: AlertInstanceState | AlertState | unknown, - item: AlertData | unknown, - cluster?: AlertCluster | unknown - ) { - throw new Error('Child classes must implement `executeActions`'); - } - - protected createGlobalStateLink(link: string, clusterUuid: string, ccs?: string) { - const globalState = [`cluster_uuid:${clusterUuid}`]; - if (ccs) { - globalState.push(`ccs:${ccs}`); - } - return `${Globals.app.url}/app/monitoring#/${link}?_g=(${globalState.toString()})`; - } -} From 3d264d920c2b1071133ecfb2bb6360d31075d271 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Tue, 8 Dec 2020 10:52:48 -0800 Subject: [PATCH 8/8] removed casting to LicenseType --- .../server/task_runner/task_runner.test.ts | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts index 5a25f5cd2c6eb..e1dee712a1985 100644 --- a/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts @@ -28,17 +28,18 @@ import { IEventLogger } from '../../../event_log/server'; import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; import { Alert, RecoveredActionGroup } from '../../common'; import { omit } from 'lodash'; -import { LicenseType } from '../../../licensing/server'; +import { NormalizedAlertType } from '../alert_type_registry'; const alertType = { id: 'test', name: 'My test alert', actionGroups: [{ id: 'default', name: 'Default' }, RecoveredActionGroup], defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, executor: jest.fn(), producer: 'alerts', }; + let fakeTimer: sinon.SinonFakeTimers; describe('Task Runner', () => { @@ -142,7 +143,7 @@ describe('Task Runner', () => { test('successfully executes the task', async () => { const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, { ...mockedTaskInstance, state: { @@ -228,7 +229,7 @@ describe('Task Runner', () => { } ); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -363,7 +364,7 @@ describe('Task Runner', () => { } ); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -530,7 +531,7 @@ describe('Task Runner', () => { } ); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, { ...mockedTaskInstance, state: { @@ -613,7 +614,7 @@ describe('Task Runner', () => { } ); const taskRunner = new TaskRunner( - alertTypeWithCustomRecovery, + alertTypeWithCustomRecovery as NormalizedAlertType, { ...mockedTaskInstance, state: { @@ -704,7 +705,7 @@ describe('Task Runner', () => { ); const date = new Date().toISOString(); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, { ...mockedTaskInstance, state: { @@ -833,7 +834,7 @@ describe('Task Runner', () => { param1: schema.string(), }), }, - }, + } as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -861,7 +862,7 @@ describe('Task Runner', () => { test('uses API key when provided', async () => { const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -894,7 +895,7 @@ describe('Task Runner', () => { test(`doesn't use API key when not provided`, async () => { const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -924,7 +925,7 @@ describe('Task Runner', () => { test('rescheduled the Alert if the schedule has update during a task run', async () => { const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -965,7 +966,7 @@ describe('Task Runner', () => { ); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -1032,7 +1033,7 @@ describe('Task Runner', () => { }); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -1091,7 +1092,7 @@ describe('Task Runner', () => { }); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -1158,7 +1159,7 @@ describe('Task Runner', () => { }); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -1228,7 +1229,7 @@ describe('Task Runner', () => { const legacyTaskInstance = omit(mockedTaskInstance, 'schedule'); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, legacyTaskInstance, taskRunnerFactoryInitializerParams ); @@ -1266,7 +1267,7 @@ describe('Task Runner', () => { ); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, { ...mockedTaskInstance, state: originalAlertSate, @@ -1297,7 +1298,7 @@ describe('Task Runner', () => { }); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams );