From dc0c75294e6f19094ce1a91a5b6f56d29f7abb7f Mon Sep 17 00:00:00 2001 From: Janki Salvi Date: Thu, 5 Dec 2024 16:57:04 +0000 Subject: [PATCH] remove legacy routes --- .../plugins/alerting/server/routes/index.ts | 2 - .../server/routes/legacy/create.test.ts | 617 ------------------ .../alerting/server/routes/legacy/create.ts | 120 ---- .../server/routes/legacy/delete.test.ts | 172 ----- .../alerting/server/routes/legacy/delete.ts | 62 -- .../server/routes/legacy/disable.test.ts | 143 ---- .../alerting/server/routes/legacy/disable.ts | 70 -- .../server/routes/legacy/enable.test.ts | 143 ---- .../alerting/server/routes/legacy/enable.ts | 73 --- .../server/routes/legacy/find.test.ts | 439 ------------- .../alerting/server/routes/legacy/find.ts | 148 ----- .../alerting/server/routes/legacy/get.test.ts | 243 ------- .../alerting/server/routes/legacy/get.ts | 64 -- .../legacy/get_alert_instance_summary.test.ts | 177 ----- .../legacy/get_alert_instance_summary.ts | 73 --- .../routes/legacy/get_alert_state.test.ts | 212 ------ .../server/routes/legacy/get_alert_state.ts | 60 -- .../server/routes/legacy/health.test.ts | 473 -------------- .../alerting/server/routes/legacy/health.ts | 91 --- .../alerting/server/routes/legacy/index.ts | 46 -- .../routes/legacy/list_alert_types.test.ts | 287 -------- .../server/routes/legacy/list_alert_types.ts | 55 -- .../server/routes/legacy/mute_all.test.ts | 143 ---- .../alerting/server/routes/legacy/mute_all.ts | 70 -- .../routes/legacy/mute_instance.test.ts | 151 ----- .../server/routes/legacy/mute_instance.ts | 81 --- .../server/routes/legacy/unmute_all.test.ts | 143 ---- .../server/routes/legacy/unmute_all.ts | 70 -- .../routes/legacy/unmute_instance.test.ts | 151 ----- .../server/routes/legacy/unmute_instance.ts | 71 -- .../server/routes/legacy/update.test.ts | 390 ----------- .../alerting/server/routes/legacy/update.ts | 113 ---- .../routes/legacy/update_api_key.test.ts | 144 ---- .../server/routes/legacy/update_api_key.ts | 73 --- .../preconfigured_alert_history_connector.ts | 2 +- .../tests/alerting/group1/delete.ts | 22 - .../tests/alerting/group1/disable.ts | 45 -- .../tests/alerting/group1/enable.ts | 43 -- .../spaces_only/tests/alerting/group1/get.ts | 50 -- .../tests/alerting/group1/get_alert_state.ts | 2 +- .../alerting/group1/get_alert_summary.ts | 72 -- .../tests/alerting/group2/mute_all.ts | 30 - .../tests/alerting/group2/mute_instance.ts | 34 - .../tests/alerting/group2/unmute_all.ts | 34 - .../tests/alerting/group2/unmute_instance.ts | 42 -- .../tests/alerting/group2/update.ts | 70 -- .../tests/alerting/group2/update_api_key.ts | 36 - .../functional/services/monitoring/alerts.js | 2 +- .../discover_ml_uptime/uptime/alert_flyout.ts | 4 +- .../test_suites/task_manager/metrics_route.ts | 2 +- .../common/lib/helpers/delete_alert.ts | 2 +- .../lib/helpers/wait_until_next_execution.ts | 2 +- .../alerts/wait_for_alert_to_complete.ts | 4 +- .../test_suites/task_manager/metrics_route.ts | 2 +- 54 files changed, 12 insertions(+), 5858 deletions(-) delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/create.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/create.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/delete.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/delete.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/disable.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/disable.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/enable.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/enable.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/find.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/find.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/get.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/get.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/get_alert_state.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/health.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/health.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/index.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/mute_all.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/mute_all.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/mute_instance.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/unmute_all.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/unmute_instance.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/update.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/update.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/update_api_key.test.ts delete mode 100644 x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts diff --git a/x-pack/plugins/alerting/server/routes/index.ts b/x-pack/plugins/alerting/server/routes/index.ts index d1fc9989be5e7..ec8f2b659a1f5 100644 --- a/x-pack/plugins/alerting/server/routes/index.ts +++ b/x-pack/plugins/alerting/server/routes/index.ts @@ -11,7 +11,6 @@ import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-p import type { ConfigSchema } from '@kbn/unified-search-plugin/server/config'; import { Observable } from 'rxjs'; import { GetAlertIndicesAlias, ILicenseState } from '../lib'; -import { defineLegacyRoutes } from './legacy'; import { AlertingRequestHandlerContext } from '../types'; import { createRuleRoute } from './rule/apis/create'; import { getRuleRoute, getInternalRuleRoute } from './rule/apis/get/get_rule_route'; @@ -94,7 +93,6 @@ export function defineRoutes(opts: RouteOptions) { getAlertIndicesAlias, } = opts; - defineLegacyRoutes(opts); createRuleRoute(opts); getRuleRoute(router, licenseState); getInternalRuleRoute(router, licenseState); diff --git a/x-pack/plugins/alerting/server/routes/legacy/create.test.ts b/x-pack/plugins/alerting/server/routes/legacy/create.test.ts deleted file mode 100644 index f3df843899f22..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/create.test.ts +++ /dev/null @@ -1,617 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { createAlertRoute } from './create'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { Rule, RuleSystemAction } from '../../../common/rule'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('createAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - const createdAt = new Date(); - const updatedAt = new Date(); - - const mockedAlert = { - alertTypeId: '1', - consumer: 'bar', - name: 'abc', - schedule: { interval: '10s' }, - tags: ['foo'], - params: { - bar: true, - }, - throttle: '30s', - notifyWhen: 'onActionGroupChange', - actions: [ - { - group: 'default', - id: '2', - params: { - foo: true, - }, - }, - ], - }; - - const systemAction: RuleSystemAction = { - actionTypeId: 'test-2', - id: 'system_action-id', - params: { - foo: true, - }, - uuid: '123-456', - }; - - const createResult: Rule<{ bar: boolean }> = { - ...mockedAlert, - enabled: true, - muteAll: false, - createdBy: '', - updatedBy: '', - apiKey: '', - apiKeyOwner: '', - mutedInstanceIds: [], - notifyWhen: 'onActionGroupChange', - createdAt, - updatedAt, - id: '123', - actions: [ - { - ...mockedAlert.actions[0], - actionTypeId: 'test', - }, - ], - executionStatus: { - status: 'unknown', - lastExecutionDate: new Date('2020-08-20T19:23:38Z'), - }, - revision: 0, - }; - - it('creates an alert with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id?}"`); - - expect(config.options?.access).toBe('public'); - - rulesClient.create.mockResolvedValueOnce(createResult); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - body: mockedAlert, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: createResult }); - - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - expect(rulesClient.create).toHaveBeenCalledTimes(1); - expect(rulesClient.create.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "foo": true, - }, - }, - ], - "alertTypeId": "1", - "consumer": "bar", - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "bar": true, - }, - "schedule": Object { - "interval": "10s", - }, - "tags": Array [ - "foo", - ], - "throttle": "30s", - }, - "options": Object { - "id": undefined, - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: createResult, - }); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - isServerless: true, - docLinks, - }); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id?}"`); - - expect(config.options?.access).toBe('internal'); - }); - - it('allows providing a custom id when space is undefined', async () => { - const expectedResult = { - ...createResult, - id: 'custom-id', - }; - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id?}"`); - - rulesClient.create.mockResolvedValueOnce(expectedResult); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: 'custom-id' }, - body: mockedAlert, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: expectedResult }); - - expect(mockUsageCounter.incrementCounter).toHaveBeenCalledTimes(1); - expect(rulesClient.create).toHaveBeenCalledTimes(1); - expect(rulesClient.create.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "foo": true, - }, - }, - ], - "alertTypeId": "1", - "consumer": "bar", - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "bar": true, - }, - "schedule": Object { - "interval": "10s", - }, - "tags": Array [ - "foo", - ], - "throttle": "30s", - }, - "options": Object { - "id": "custom-id", - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: expectedResult, - }); - }); - - it('allows providing a custom id in default space', async () => { - const expectedResult = { - ...createResult, - id: 'custom-id', - }; - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id?}"`); - - rulesClient.create.mockResolvedValueOnce(expectedResult); - rulesClient.getSpaceId.mockReturnValueOnce('default'); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: 'custom-id' }, - body: mockedAlert, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: expectedResult }); - - expect(mockUsageCounter.incrementCounter).toHaveBeenCalledTimes(1); - expect(rulesClient.create).toHaveBeenCalledTimes(1); - expect(rulesClient.create.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "foo": true, - }, - }, - ], - "alertTypeId": "1", - "consumer": "bar", - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "bar": true, - }, - "schedule": Object { - "interval": "10s", - }, - "tags": Array [ - "foo", - ], - "throttle": "30s", - }, - "options": Object { - "id": "custom-id", - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: expectedResult, - }); - }); - - it('allows providing a custom id in non-default space', async () => { - const expectedResult = { - ...createResult, - id: 'custom-id', - }; - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id?}"`); - - rulesClient.create.mockResolvedValueOnce(expectedResult); - rulesClient.getSpaceId.mockReturnValueOnce('another-space'); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: 'custom-id' }, - body: mockedAlert, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: expectedResult }); - - expect(mockUsageCounter.incrementCounter).toHaveBeenCalledTimes(2); - expect(rulesClient.create).toHaveBeenCalledTimes(1); - expect(rulesClient.create.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "foo": true, - }, - }, - ], - "alertTypeId": "1", - "consumer": "bar", - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "bar": true, - }, - "schedule": Object { - "interval": "10s", - }, - "tags": Array [ - "foo", - ], - "throttle": "30s", - }, - "options": Object { - "id": "custom-id", - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: expectedResult, - }); - }); - - it('ensures the license allows creating alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - - createAlertRoute({ router, licenseState, encryptedSavedObjects, docLinks }); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.create.mockResolvedValueOnce(createResult); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, {}); - - await handler(context, req, res); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the license check prevents creating alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); - }); - - createAlertRoute({ router, licenseState, encryptedSavedObjects, docLinks }); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.create.mockResolvedValueOnce(createResult); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, {}); - - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - - createAlertRoute({ router, licenseState, encryptedSavedObjects, docLinks }); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.create.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid')); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, {}, ['ok', 'forbidden']); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - const [, handler] = router.post.mock.calls[0]; - rulesClient.create.mockResolvedValueOnce(createResult); - const [context, req, res] = mockHandlerArguments({ rulesClient }, {}, ['ok']); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('create', mockUsageCounter); - }); - - it('does not return system actions', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id?}"`); - - rulesClient.create.mockResolvedValueOnce({ ...createResult, systemActions: [systemAction] }); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - body: mockedAlert, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: createResult }); - - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - expect(rulesClient.create).toHaveBeenCalledTimes(1); - expect(rulesClient.create.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "foo": true, - }, - }, - ], - "alertTypeId": "1", - "consumer": "bar", - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "bar": true, - }, - "schedule": Object { - "interval": "10s", - }, - "tags": Array [ - "foo", - ], - "throttle": "30s", - }, - "options": Object { - "id": undefined, - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: createResult, - }); - }); - - it('should be deprecated', () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{id?}", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/create.ts b/x-pack/plugins/alerting/server/routes/legacy/create.ts deleted file mode 100644 index 8346ec37edf9c..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/create.ts +++ /dev/null @@ -1,120 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { validateDurationSchema } from '../../lib'; -import { handleDisabledApiKeysError } from '../lib/error_handler'; -import { - SanitizedRule, - RuleNotifyWhenType, - RuleTypeParams, - LEGACY_BASE_ALERT_API_PATH, - validateNotifyWhenType, -} from '../../types'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { RouteOptions } from '..'; -import { countUsageOfPredefinedIds } from '../lib'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -export const bodySchema = schema.object({ - name: schema.string(), - alertTypeId: schema.string(), - enabled: schema.boolean({ defaultValue: true }), - consumer: schema.string(), - tags: schema.arrayOf(schema.string(), { defaultValue: [] }), - throttle: schema.nullable(schema.string({ validate: validateDurationSchema })), - params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), - schedule: schema.object({ - interval: schema.string({ validate: validateDurationSchema }), - }), - actions: schema.arrayOf( - schema.object({ - group: schema.string(), - id: schema.string(), - actionTypeId: schema.maybe(schema.string()), - params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), - }), - { defaultValue: [] } - ), - notifyWhen: schema.nullable(schema.string({ validate: validateNotifyWhenType })), -}); - -export const createAlertRoute = ({ - router, - licenseState, - usageCounter, - isServerless, - docLinks, -}: RouteOptions) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id?}`, - validate: { - params: schema.maybe( - schema.object({ - id: schema.maybe(schema.string()), - }) - ), - body: bodySchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Create an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{id?}', - }, - }, - }, - }, - handleDisabledApiKeysError( - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const alert = req.body; - const params = req.params; - const notifyWhen = alert?.notifyWhen ? (alert.notifyWhen as RuleNotifyWhenType) : null; - - trackLegacyRouteUsage('create', usageCounter); - - countUsageOfPredefinedIds({ - predefinedId: params?.id, - spaceId: rulesClient.getSpaceId(), - usageCounter, - }); - - try { - const { systemActions, ...alertRes }: SanitizedRule = - await rulesClient.create({ - data: { ...alert, notifyWhen }, - options: { id: params?.id }, - }); - return res.ok({ - body: alertRes, - }); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/delete.test.ts b/x-pack/plugins/alerting/server/routes/legacy/delete.test.ts deleted file mode 100644 index d8fd0effc50e4..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/delete.test.ts +++ /dev/null @@ -1,172 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { deleteAlertRoute } from './delete'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('deleteAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('deletes an alert with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - deleteAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.delete.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - expect(config.options?.access).toBe('public'); - - rulesClient.delete.mockResolvedValueOnce({}); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.delete).toHaveBeenCalledTimes(1); - expect(rulesClient.delete.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - deleteAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.delete.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the license allows deleting alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - deleteAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.delete.mock.calls[0]; - - rulesClient.delete.mockResolvedValueOnce({}); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - } - ); - - await handler(context, req, res); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the license check prevents deleting alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); - }); - - deleteAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.delete.mock.calls[0]; - - rulesClient.delete.mockResolvedValueOnce({}); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - id: '1', - } - ); - - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - deleteAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.delete.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: { id: '1' } }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('delete', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - deleteAlertRoute(router, licenseState, docLinks); - - const [config] = router.delete.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "DELETE", - "newApiPath": "/api/alerting/rule/{id}", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/delete.ts b/x-pack/plugins/alerting/server/routes/legacy/delete.ts deleted file mode 100644 index 738633c61f745..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/delete.ts +++ /dev/null @@ -1,62 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const deleteAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.delete( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}`, - validate: { - params: paramSchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Delete an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'DELETE', - newApiPath: '/api/alerting/rule/{id}', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('delete', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - await rulesClient.delete({ id }); - return res.noContent(); - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/disable.test.ts b/x-pack/plugins/alerting/server/routes/legacy/disable.test.ts deleted file mode 100644 index 13fec185429ed..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/disable.test.ts +++ /dev/null @@ -1,143 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { disableAlertRoute } from './disable'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('disableAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('disables an alert', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - disableAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_disable"`); - expect(config.options?.access).toBe('public'); - - rulesClient.disableRule.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.disableRule).toHaveBeenCalledTimes(1); - expect(rulesClient.disableRule.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - disableAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_disable"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - disableAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.disableRule.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid')); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - disableAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: { id: '1' } }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('disable', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - disableAlertRoute(router, licenseState, docLinks); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{id}/_disable", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/disable.ts b/x-pack/plugins/alerting/server/routes/legacy/disable.ts deleted file mode 100644 index e69a176776e0c..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/disable.ts +++ /dev/null @@ -1,70 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const disableAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_disable`, - validate: { - params: paramSchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Disable an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{id}/_disable', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('disable', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - try { - await rulesClient.disableRule({ id }); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/enable.test.ts b/x-pack/plugins/alerting/server/routes/legacy/enable.test.ts deleted file mode 100644 index 88df304ea07c0..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/enable.test.ts +++ /dev/null @@ -1,143 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { enableAlertRoute } from './enable'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('enableAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('enables an alert', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - enableAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_enable"`); - expect(config.options?.access).toBe('public'); - - rulesClient.enableRule.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.enableRule).toHaveBeenCalledTimes(1); - expect(rulesClient.enableRule.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - enableAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_enable"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - enableAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.enableRule.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid')); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - enableAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: { id: '1' } }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('enable', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - enableAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{id}/_enable", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/enable.ts b/x-pack/plugins/alerting/server/routes/legacy/enable.ts deleted file mode 100644 index 289b4050e059b..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/enable.ts +++ /dev/null @@ -1,73 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { handleDisabledApiKeysError } from '../lib/error_handler'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const enableAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_enable`, - validate: { - params: paramSchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Enable an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{id}/_enable', - }, - }, - }, - }, - handleDisabledApiKeysError( - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('enable', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - try { - await rulesClient.enableRule({ id }); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/find.test.ts b/x-pack/plugins/alerting/server/routes/legacy/find.test.ts deleted file mode 100644 index 646f18fa072ea..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/find.test.ts +++ /dev/null @@ -1,439 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { omit } from 'lodash'; -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { findAlertRoute } from './find'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { trackLegacyTerminology } from '../lib/track_legacy_terminology'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -jest.mock('../lib/track_legacy_terminology', () => ({ - trackLegacyTerminology: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('findAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('finds alerts with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - findAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/_find"`); - expect(config.options?.access).toBe('public'); - - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [], - }; - rulesClient.find.mockResolvedValueOnce(findResult); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - query: { - per_page: 1, - page: 1, - default_search_operator: 'OR', - }, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toMatchInlineSnapshot(` - Object { - "body": Object { - "data": Array [], - "page": 1, - "perPage": 1, - "total": 0, - }, - } - `); - - expect(rulesClient.find).toHaveBeenCalledTimes(1); - expect(rulesClient.find.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "excludeFromPublicApi": true, - "options": Object { - "defaultSearchOperator": "OR", - "page": 1, - "perPage": 1, - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: findResult, - }); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - findAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/_find"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the license allows finding alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - findAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.get.mock.calls[0]; - - rulesClient.find.mockResolvedValueOnce({ - page: 1, - perPage: 1, - total: 0, - data: [], - }); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - query: { - per_page: 1, - page: 1, - default_search_operator: 'OR', - }, - } - ); - - await handler(context, req, res); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the license check prevents finding alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); - }); - - findAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - {}, - { - query: { - per_page: 1, - page: 1, - default_search_operator: 'OR', - }, - }, - ['ok'] - ); - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - findAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [], - }; - rulesClient.find.mockResolvedValueOnce(findResult); - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, query: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('find', mockUsageCounter); - }); - - it('should track calls with deprecated param values', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - findAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [], - }; - rulesClient.find.mockResolvedValueOnce(findResult); - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: {}, - query: { - search_fields: ['alertTypeId:1', 'message:foo'], - search: 'alertTypeId:2', - sort_field: 'alertTypeId', - }, - }, - ['ok'] - ); - await handler(context, req, res); - expect(trackLegacyTerminology).toHaveBeenCalledTimes(1); - expect((trackLegacyTerminology as jest.Mock).mock.calls[0][0]).toStrictEqual([ - 'alertTypeId:2', - ['alertTypeId:1', 'message:foo'], - 'alertTypeId', - ]); - }); - - it('should track calls to deprecated functionality', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - findAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [], - }; - rulesClient.find.mockResolvedValueOnce(findResult); - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: {}, - query: { - fields: ['foo', 'bar'], - }, - }, - ['ok'] - ); - await handler(context, req, res); - expect(mockUsageCounter.incrementCounter).toHaveBeenCalledWith({ - counterName: `legacyAlertingFieldsUsage`, - counterType: 'alertingFieldsUsage', - incrementBy: 1, - }); - }); - - it('does not return system actions', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - findAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/_find"`); - - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [ - { - id: '3d534c70-582b-11ec-8995-2b1578a3bc5d', - notifyWhen: 'onActiveAlert' as const, - alertTypeId: '.index-threshold', - name: 'stressing index-threshold 37/200', - consumer: 'alerts', - tags: [], - enabled: true, - throttle: null, - apiKey: null, - apiKeyOwner: '2889684073', - createdBy: 'elastic', - updatedBy: '2889684073', - muteAll: false, - mutedInstanceIds: [], - schedule: { - interval: '1s', - }, - actions: [ - { - actionTypeId: '.server-log', - params: { - message: 'alert 37: {{context.message}}', - }, - group: 'threshold met', - id: '3619a0d0-582b-11ec-8995-2b1578a3bc5d', - uuid: '123-456', - }, - ], - systemActions: [ - { actionTypeId: '.test', id: 'system_action-id', params: {}, uuid: '789' }, - ], - params: { x: 42 }, - updatedAt: '2024-03-21T13:15:00.498Z', - createdAt: '2024-03-21T13:15:00.498Z', - scheduledTaskId: '52125fb0-5895-11ec-ae69-bb65d1a71b72', - executionStatus: { - status: 'ok' as const, - lastExecutionDate: '2024-03-21T13:15:00.498Z', - lastDuration: 1194, - }, - revision: 0, - }, - ], - }; - - // @ts-expect-error: TS complains about dates being string and not a Date object - rulesClient.find.mockResolvedValueOnce(findResult); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - query: { - per_page: 1, - page: 1, - default_search_operator: 'OR', - }, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toMatchInlineSnapshot(` - Object { - "body": Object { - "data": Array [ - Object { - "actions": Array [ - Object { - "actionTypeId": ".server-log", - "group": "threshold met", - "id": "3619a0d0-582b-11ec-8995-2b1578a3bc5d", - "params": Object { - "message": "alert 37: {{context.message}}", - }, - "uuid": "123-456", - }, - ], - "alertTypeId": ".index-threshold", - "apiKey": null, - "apiKeyOwner": "2889684073", - "consumer": "alerts", - "createdAt": "2024-03-21T13:15:00.498Z", - "createdBy": "elastic", - "enabled": true, - "executionStatus": Object { - "lastDuration": 1194, - "lastExecutionDate": "2024-03-21T13:15:00.498Z", - "status": "ok", - }, - "id": "3d534c70-582b-11ec-8995-2b1578a3bc5d", - "muteAll": false, - "mutedInstanceIds": Array [], - "name": "stressing index-threshold 37/200", - "notifyWhen": "onActiveAlert", - "params": Object { - "x": 42, - }, - "revision": 0, - "schedule": Object { - "interval": "1s", - }, - "scheduledTaskId": "52125fb0-5895-11ec-ae69-bb65d1a71b72", - "tags": Array [], - "throttle": null, - "updatedAt": "2024-03-21T13:15:00.498Z", - "updatedBy": "2889684073", - }, - ], - "page": 1, - "perPage": 1, - "total": 0, - }, - } - `); - - expect(rulesClient.find).toHaveBeenCalledTimes(1); - expect(rulesClient.find.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "excludeFromPublicApi": true, - "options": Object { - "defaultSearchOperator": "OR", - "page": 1, - "perPage": 1, - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: omit(findResult, 'data[0].systemActions'), - }); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - findAlertRoute(router, licenseState, docLinks); - - const [config] = router.get.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "GET", - "newApiPath": "/api/alerting/rules/_find", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/find.ts b/x-pack/plugins/alerting/server/routes/legacy/find.ts deleted file mode 100644 index de1e5f8c226a1..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/find.ts +++ /dev/null @@ -1,148 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { estypes } from '@elastic/elasticsearch'; -import { KueryNode } from '@kbn/es-query'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; - -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { renameKeys } from '../lib/rename_keys'; -import { IndexType } from '../../rules_client'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { trackLegacyTerminology } from '../lib/track_legacy_terminology'; - -export interface FindOptions extends IndexType { - perPage?: number; - page?: number; - search?: string; - defaultSearchOperator?: 'AND' | 'OR'; - searchFields?: string[]; - sortField?: string; - sortOrder?: estypes.SortOrder; - hasReference?: { - type: string; - id: string; - }; - fields?: string[]; - filter?: string | KueryNode; - filterConsumers?: string[]; -} - -// config definition -const querySchema = schema.object({ - per_page: schema.number({ defaultValue: 10, min: 0 }), - page: schema.number({ defaultValue: 1, min: 1 }), - search: schema.maybe(schema.string()), - default_search_operator: schema.oneOf([schema.literal('OR'), schema.literal('AND')], { - defaultValue: 'OR', - }), - search_fields: schema.maybe(schema.oneOf([schema.arrayOf(schema.string()), schema.string()])), - sort_field: schema.maybe(schema.string()), - sort_order: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])), - has_reference: schema.maybe( - // use nullable as maybe is currently broken - // in config-schema - schema.nullable( - schema.object({ - type: schema.string(), - id: schema.string(), - }) - ) - ), - fields: schema.maybe(schema.arrayOf(schema.string())), - filter: schema.maybe(schema.string()), -}); - -export const findAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.get( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/_find`, - validate: { - query: querySchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Find alerts', - tags: ['oas-tag:alerting'], - description: - 'Gets a paginated set of alerts. Alert `params` are stored as a flattened field type and analyzed as keywords. As alerts change in Kibana, the results on each page of the response also change. Use the find API for traditional paginated results, but avoid using it to export large amounts of data.', - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'GET', - newApiPath: '/api/alerting/rules/_find', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('find', usageCounter); - trackLegacyTerminology( - [req.query.search, req.query.search_fields, req.query.sort_field].filter( - Boolean - ) as string[], - usageCounter - ); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - - const query = req.query; - const renameMap = { - default_search_operator: 'defaultSearchOperator', - fields: 'fields', - has_reference: 'hasReference', - page: 'page', - per_page: 'perPage', - search: 'search', - sort_field: 'sortField', - sort_order: 'sortOrder', - filter: 'filter', - }; - - const options = renameKeys>(renameMap, query); - - if (query.search_fields) { - options.searchFields = Array.isArray(query.search_fields) - ? query.search_fields - : [query.search_fields]; - } - - if (query.fields) { - usageCounter?.incrementCounter({ - counterName: `legacyAlertingFieldsUsage`, - counterType: 'alertingFieldsUsage', - incrementBy: 1, - }); - } - - const findResult = await rulesClient.find({ options, excludeFromPublicApi: true }); - return res.ok({ - body: { - ...findResult, - data: findResult.data.map(({ systemActions, ...rule }) => rule), - }, - }); - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/get.test.ts b/x-pack/plugins/alerting/server/routes/legacy/get.test.ts deleted file mode 100644 index ca8154fc7adae..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/get.test.ts +++ /dev/null @@ -1,243 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { getAlertRoute } from './get'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { Rule, RuleSystemAction } from '../../../common'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('getAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - const mockedAlert: Rule<{ - bar: true; - }> = { - id: '1', - alertTypeId: '1', - schedule: { interval: '10s' }, - params: { - bar: true, - }, - createdAt: new Date(), - updatedAt: new Date(), - actions: [ - { - group: 'default', - id: '2', - actionTypeId: 'test', - params: { - foo: true, - }, - }, - ], - consumer: 'bar', - name: 'abc', - tags: ['foo'], - enabled: true, - muteAll: false, - notifyWhen: 'onActionGroupChange', - createdBy: '', - updatedBy: '', - apiKey: '', - apiKeyOwner: '', - throttle: '30s', - mutedInstanceIds: [], - executionStatus: { - status: 'unknown', - lastExecutionDate: new Date('2020-08-20T19:23:38Z'), - }, - revision: 0, - }; - - const systemAction: RuleSystemAction = { - actionTypeId: 'test-2', - id: 'system_action-id', - params: { - foo: true, - }, - uuid: '123-456', - }; - - it('gets an alert with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertRoute(router, licenseState, docLinks); - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - expect(config.options?.access).toBe('public'); - - rulesClient.get.mockResolvedValueOnce(mockedAlert); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - await handler(context, req, res); - - expect(rulesClient.get).toHaveBeenCalledTimes(1); - expect(rulesClient.get.mock.calls[0][0].id).toEqual('1'); - - expect(res.ok).toHaveBeenCalledWith({ - body: mockedAlert, - }); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertRoute(router, licenseState, docLinks, undefined, true); - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the license allows getting alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.get.mock.calls[0]; - - rulesClient.get.mockResolvedValueOnce(mockedAlert); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - - await handler(context, req, res); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the license check prevents getting alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); - }); - - getAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.get.mock.calls[0]; - - rulesClient.get.mockResolvedValueOnce(mockedAlert); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - getAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - - rulesClient.get.mockResolvedValueOnce(mockedAlert); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: { id: '1' } }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('get', mockUsageCounter); - }); - - it('does not return system actions', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertRoute(router, licenseState, docLinks); - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - - rulesClient.get.mockResolvedValueOnce({ ...mockedAlert, systemActions: [systemAction] }); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - await handler(context, req, res); - - expect(rulesClient.get).toHaveBeenCalledTimes(1); - expect(rulesClient.get.mock.calls[0][0].id).toEqual('1'); - - expect(res.ok).toHaveBeenCalledWith({ - body: mockedAlert, - }); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertRoute(router, licenseState, docLinks); - const [config] = router.get.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "GET", - "newApiPath": "/api/alerting/rule/{id}", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/get.ts b/x-pack/plugins/alerting/server/routes/legacy/get.ts deleted file mode 100644 index 19fc0f7ff49e6..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/get.ts +++ /dev/null @@ -1,64 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import type { AlertingRouter } from '../../types'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const getAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.get( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}`, - validate: { - params: paramSchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Get an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'GET', - newApiPath: '/api/alerting/rule/{id}', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('get', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - const { systemActions, ...rule } = await rulesClient.get({ id, excludeFromPublicApi: true }); - return res.ok({ - body: rule, - }); - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.test.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.test.ts deleted file mode 100644 index cc3deaad9af99..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.test.ts +++ /dev/null @@ -1,177 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { getAlertInstanceSummaryRoute } from './get_alert_instance_summary'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { SavedObjectsErrorHelpers } from '@kbn/core/server'; -import { rulesClientMock } from '../../rules_client.mock'; -import { AlertSummary } from '../../types'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { RULE_SAVED_OBJECT_TYPE } from '../../saved_objects'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('getAlertInstanceSummaryRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - const dateString = new Date().toISOString(); - const mockedAlertInstanceSummary: AlertSummary = { - id: '', - name: '', - tags: [], - ruleTypeId: '', - consumer: '', - muteAll: false, - throttle: null, - enabled: false, - statusStartDate: dateString, - statusEndDate: dateString, - status: 'OK', - errorMessages: [], - alerts: {}, - executionDuration: { - average: 0, - valuesWithTimestamp: {}, - }, - revision: 0, - }; - - it('gets alert instance summary', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertInstanceSummaryRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_instance_summary"`); - expect(config.options?.access).toBe('public'); - - rulesClient.getAlertSummary.mockResolvedValueOnce(mockedAlertInstanceSummary); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - query: {}, - }, - ['ok'] - ); - - await handler(context, req, res); - - expect(rulesClient.getAlertSummary).toHaveBeenCalledTimes(1); - expect(rulesClient.getAlertSummary.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "dateStart": undefined, - "id": "1", - }, - ] - `); - - expect(res.ok).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertInstanceSummaryRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_instance_summary"`); - expect(config.options?.access).toBe('internal'); - }); - - it('returns NOT-FOUND when alert is not found', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertInstanceSummaryRoute(router, licenseState, docLinks); - - const [, handler] = router.get.mock.calls[0]; - - rulesClient.getAlertSummary = jest - .fn() - .mockResolvedValueOnce( - SavedObjectsErrorHelpers.createGenericNotFoundError(RULE_SAVED_OBJECT_TYPE, '1') - ); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - query: {}, - }, - ['notFound'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - getAlertInstanceSummaryRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - - rulesClient.getAlertSummary.mockResolvedValueOnce(mockedAlertInstanceSummary); - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { params: { id: '1' }, query: {} }, - ['ok'] - ); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('instanceSummary', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertInstanceSummaryRoute(router, licenseState, docLinks); - - const [config] = router.get.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "type": "remove", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts deleted file mode 100644 index 0e50601a1fd4d..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts +++ /dev/null @@ -1,73 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { AlertSummary, LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -const querySchema = schema.object({ - dateStart: schema.maybe(schema.string()), -}); - -const rewriteBodyRes = ({ ruleTypeId, alerts, ...rest }: AlertSummary) => ({ - ...rest, - alertTypeId: ruleTypeId, - instances: alerts, -}); - -export const getAlertInstanceSummaryRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.get( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_instance_summary`, - validate: { - params: paramSchema, - query: querySchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Get an alert summary', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'remove', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('instanceSummary', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - const { dateStart } = req.query; - const summary = await rulesClient.getAlertSummary({ id, dateStart }); - - return res.ok({ body: rewriteBodyRes(summary) }); - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.test.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.test.ts deleted file mode 100644 index ca79291b23dbc..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.test.ts +++ /dev/null @@ -1,212 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { getAlertStateRoute } from './get_alert_state'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { SavedObjectsErrorHelpers } from '@kbn/core/server'; -import { rulesClientMock } from '../../rules_client.mock'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { RULE_SAVED_OBJECT_TYPE } from '../../saved_objects'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('getAlertStateRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - const mockedAlertState = { - alertTypeState: { - some: 'value', - }, - alertInstances: { - first_instance: { - state: {}, - meta: { - lastScheduledActions: { - group: 'first_group', - date: new Date().toISOString(), - }, - }, - }, - second_instance: {}, - }, - }; - - it('gets alert state', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertStateRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/state"`); - expect(config.options?.access).toBe('public'); - - rulesClient.getAlertState.mockResolvedValueOnce(mockedAlertState); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['ok'] - ); - - await handler(context, req, res); - - expect(rulesClient.getAlertState).toHaveBeenCalledTimes(1); - expect(rulesClient.getAlertState.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.ok).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertStateRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/state"`); - expect(config.options?.access).toBe('internal'); - }); - - it('returns NO-CONTENT when alert exists but has no task state yet', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertStateRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/state"`); - - rulesClient.getAlertState.mockResolvedValueOnce(undefined); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.getAlertState).toHaveBeenCalledTimes(1); - expect(rulesClient.getAlertState.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('returns NOT-FOUND when alert is not found', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertStateRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/state"`); - - rulesClient.getAlertState = jest - .fn() - .mockResolvedValueOnce( - SavedObjectsErrorHelpers.createGenericNotFoundError(RULE_SAVED_OBJECT_TYPE, '1') - ); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['notFound'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.getAlertState).toHaveBeenCalledTimes(1); - expect(rulesClient.getAlertState.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - getAlertStateRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: { id: '1' } }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('state', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertStateRoute(router, licenseState, docLinks); - - const [config] = router.get.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "type": "remove", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts deleted file mode 100644 index f9db44c1e9a0c..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts +++ /dev/null @@ -1,60 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const getAlertStateRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.get( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/state`, - validate: { - params: paramSchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Get the state of an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'remove', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('state', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - const state = await rulesClient.getAlertState({ id }); - return state ? res.ok({ body: state }) : res.noContent(); - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/health.test.ts b/x-pack/plugins/alerting/server/routes/legacy/health.test.ts deleted file mode 100644 index fea24b831e97d..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/health.test.ts +++ /dev/null @@ -1,473 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { HealthStatus } from '@kbn/alerting-types'; -import { healthRoute } from './health'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RecoveredActionGroup } from '../../types'; -import { alertsMock } from '../../mocks'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { RegistryAlertTypeWithAuth } from '../../authorization'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -const alerting = alertsMock.createStart(); - -const currentDate = new Date().toISOString(); - -const ruleTypes = [ - { - id: '1', - name: 'name', - actionGroups: [ - { - id: 'default', - name: 'Default', - }, - ], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - ruleTaskTimeout: '10m', - recoveryActionGroup: RecoveredActionGroup, - authorizedConsumers: {}, - actionVariables: { - context: [], - state: [], - }, - category: 'test', - producer: 'test', - enabledInLicense: true, - defaultScheduleInterval: '10m', - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - } as RegistryAlertTypeWithAuth, -]; - -beforeEach(() => { - jest.resetAllMocks(); - alerting.getFrameworkHealth.mockResolvedValue({ - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }); -}); - -describe('healthRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('registers the route', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/_health"`); - expect(config.options?.access).toBe('public'); - }); - - it('should have internal access for serverless', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - healthRoute(router, licenseState, encryptedSavedObjects, docLinks, undefined, true); - - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/_health"`); - expect(config.options?.access).toBe('internal'); - }); - - it('throws error when user does not have any access to any rule types', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce([]); - const router = httpServiceMock.createRouter(); - - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: false }); - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - { - rulesClient, - getFrameworkHealth: alerting.getFrameworkHealth, - areApiKeysEnabled: () => Promise.resolve(true), - }, - {}, - ['ok'] - ); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ - body: { message: `Unauthorized to access alerting framework health` }, - }); - }); - - it('evaluates whether Encrypted Saved Objects is missing encryption key', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: false }); - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - { - rulesClient, - getFrameworkHealth: alerting.getFrameworkHealth, - areApiKeysEnabled: () => Promise.resolve(true), - }, - {}, - ['ok'] - ); - - expect(await handler(context, req, res)).toStrictEqual({ - body: { - alertingFrameworkHeath: { - // Legacy: pre-v8.0 typo - _deprecated: 'This state property has a typo, use "alertingFrameworkHealth" instead.', - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - alertingFrameworkHealth: { - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - hasPermanentEncryptionKey: false, - isSufficientlySecure: true, - }, - }); - }); - - test('when ES security status cannot be determined from license state, isSufficientlySecure should return false', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - licenseState.getIsSecurityEnabled.mockReturnValueOnce(null); - - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - { - rulesClient, - getFrameworkHealth: alerting.getFrameworkHealth, - areApiKeysEnabled: () => Promise.resolve(true), - }, - {}, - ['ok'] - ); - - expect(await handler(context, req, res)).toStrictEqual({ - body: { - alertingFrameworkHeath: { - // Legacy: pre-v8.0 typo - _deprecated: 'This state property has a typo, use "alertingFrameworkHealth" instead.', - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - alertingFrameworkHealth: { - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - hasPermanentEncryptionKey: true, - isSufficientlySecure: false, - }, - }); - }); - - test('when ES security is disabled, isSufficientlySecure should return true', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - licenseState.getIsSecurityEnabled.mockReturnValueOnce(false); - - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - { - rulesClient, - getFrameworkHealth: alerting.getFrameworkHealth, - areApiKeysEnabled: () => Promise.resolve(false), - }, - {}, - ['ok'] - ); - - expect(await handler(context, req, res)).toStrictEqual({ - body: { - alertingFrameworkHeath: { - // Legacy: pre-v8.0 typo - _deprecated: 'This state property has a typo, use "alertingFrameworkHealth" instead.', - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - alertingFrameworkHealth: { - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - hasPermanentEncryptionKey: true, - isSufficientlySecure: true, - }, - }); - }); - - test('when ES security is enabled but user cannot generate api keys, isSufficientlySecure should return false', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - licenseState.getIsSecurityEnabled.mockReturnValueOnce(true); - - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - { - rulesClient, - getFrameworkHealth: alerting.getFrameworkHealth, - areApiKeysEnabled: () => Promise.resolve(false), - }, - {}, - ['ok'] - ); - - expect(await handler(context, req, res)).toStrictEqual({ - body: { - alertingFrameworkHeath: { - // Legacy: pre-v8.0 typo - _deprecated: 'This state property has a typo, use "alertingFrameworkHealth" instead.', - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - alertingFrameworkHealth: { - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - hasPermanentEncryptionKey: true, - isSufficientlySecure: false, - }, - }); - }); - - test('when ES security is enabled and user can generate api keys, isSufficientlySecure should return true', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - licenseState.getIsSecurityEnabled.mockReturnValueOnce(true); - - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - { - rulesClient, - getFrameworkHealth: alerting.getFrameworkHealth, - areApiKeysEnabled: () => Promise.resolve(true), - }, - {}, - ['ok'] - ); - - expect(await handler(context, req, res)).toStrictEqual({ - body: { - alertingFrameworkHeath: { - // Legacy: pre-v8.0 typo - _deprecated: 'This state property has a typo, use "alertingFrameworkHealth" instead.', - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - alertingFrameworkHealth: { - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - hasPermanentEncryptionKey: true, - isSufficientlySecure: true, - }, - }); - }); - - it('should track every call', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - healthRoute(router, licenseState, encryptedSavedObjects, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: { id: '1' } }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('health', mockUsageCounter); - }); - - it('should be deprecated', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - - const [config] = router.get.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "GET", - "newApiPath": "/api/alerting/rule/_health", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/health.ts b/x-pack/plugins/alerting/server/routes/legacy/health.ts deleted file mode 100644 index b463298837f4e..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/health.ts +++ /dev/null @@ -1,91 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { AlertingFrameworkHealth } from '../../types'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { getSecurityHealth } from '../../lib/get_security_health'; - -export function healthRoute( - router: AlertingRouter, - licenseState: ILicenseState, - encryptedSavedObjects: EncryptedSavedObjectsPluginSetup, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) { - router.get( - { - path: '/api/alerts/_health', - validate: false, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Get the alerting framework health', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'GET', - newApiPath: '/api/alerting/rule/_health', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('health', usageCounter); - try { - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - // Verify that user has access to at least one rule type - const ruleTypes = Array.from(await rulesClient.listRuleTypes()); - if (ruleTypes.length > 0) { - const alertingFrameworkHealth = await alertingContext.getFrameworkHealth(); - - const securityHealth = await getSecurityHealth( - async () => (licenseState ? licenseState.getIsSecurityEnabled() : null), - async () => encryptedSavedObjects.canEncrypt, - alertingContext.areApiKeysEnabled - ); - - const frameworkHealth: AlertingFrameworkHealth = { - ...securityHealth, - alertingFrameworkHealth, - }; - - return res.ok({ - body: { - ...frameworkHealth, - alertingFrameworkHeath: { - // Legacy: pre-v8.0 typo - ...alertingFrameworkHealth, - _deprecated: - 'This state property has a typo, use "alertingFrameworkHealth" instead.', - }, - }, - }); - } else { - return res.forbidden({ - body: { message: `Unauthorized to access alerting framework health` }, - }); - } - } catch (error) { - return res.badRequest({ body: error }); - } - }) - ); -} diff --git a/x-pack/plugins/alerting/server/routes/legacy/index.ts b/x-pack/plugins/alerting/server/routes/legacy/index.ts deleted file mode 100644 index e9551d938e6c1..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/index.ts +++ /dev/null @@ -1,46 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { createAlertRoute } from './create'; -import { deleteAlertRoute } from './delete'; -import { findAlertRoute } from './find'; -import { getAlertRoute } from './get'; -import { getAlertStateRoute } from './get_alert_state'; -import { getAlertInstanceSummaryRoute } from './get_alert_instance_summary'; -import { listAlertTypesRoute } from './list_alert_types'; -import { updateAlertRoute } from './update'; -import { enableAlertRoute } from './enable'; -import { disableAlertRoute } from './disable'; -import { updateApiKeyRoute } from './update_api_key'; -import { muteAlertInstanceRoute } from './mute_instance'; -import { unmuteAlertInstanceRoute } from './unmute_instance'; -import { muteAllAlertRoute } from './mute_all'; -import { unmuteAllAlertRoute } from './unmute_all'; -import { healthRoute } from './health'; -import { RouteOptions } from '..'; - -export function defineLegacyRoutes(opts: RouteOptions) { - const { router, licenseState, encryptedSavedObjects, usageCounter, isServerless, docLinks } = - opts; - - createAlertRoute(opts); - deleteAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - findAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - getAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - getAlertStateRoute(router, licenseState, docLinks, usageCounter, isServerless); - getAlertInstanceSummaryRoute(router, licenseState, docLinks, usageCounter, isServerless); - listAlertTypesRoute(router, licenseState, docLinks, usageCounter, isServerless); - updateAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - enableAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - disableAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - updateApiKeyRoute(router, licenseState, docLinks, usageCounter, isServerless); - muteAllAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - unmuteAllAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - muteAlertInstanceRoute(router, licenseState, docLinks, usageCounter, isServerless); - unmuteAlertInstanceRoute(router, licenseState, docLinks, usageCounter, isServerless); - healthRoute(router, licenseState, encryptedSavedObjects, docLinks, usageCounter, isServerless); -} diff --git a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts b/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts deleted file mode 100644 index 27e9d7ce44865..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts +++ /dev/null @@ -1,287 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { listAlertTypesRoute } from './list_alert_types'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RecoveredActionGroup } from '../../../common'; -import { RegistryAlertTypeWithAuth } from '../../authorization'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('listAlertTypesRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - it('lists alert types with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - listAlertTypesRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/list_alert_types"`); - expect(config.options?.access).toBe('public'); - - const listTypes: RegistryAlertTypeWithAuth[] = [ - { - id: '1', - name: 'name', - actionGroups: [ - { - id: 'default', - name: 'Default', - }, - ], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - authorizedConsumers: {}, - actionVariables: { - context: [], - state: [], - }, - category: 'test', - producer: 'test', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, - ]; - - rulesClient.listRuleTypes.mockResolvedValueOnce(listTypes); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, {}, ['ok']); - - expect(await handler(context, req, res)).toMatchInlineSnapshot(` - Object { - "body": Array [ - Object { - "actionGroups": Array [ - Object { - "id": "default", - "name": "Default", - }, - ], - "actionVariables": Object { - "context": Array [], - "state": Array [], - }, - "authorizedConsumers": Object {}, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "1", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "name", - "producer": "test", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, - ], - } - `); - - expect(rulesClient.listRuleTypes).toHaveBeenCalledTimes(1); - - expect(res.ok).toHaveBeenCalledWith({ - body: listTypes, - }); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - listAlertTypesRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/list_alert_types"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the license allows listing alert types', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - listAlertTypesRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/list_alert_types"`); - - const listTypes = [ - { - id: '1', - name: 'name', - actionGroups: [ - { - id: 'default', - name: 'Default', - }, - ], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - authorizedConsumers: {}, - actionVariables: { - context: [], - state: [], - }, - category: 'test', - producer: 'alerts', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - } as RegistryAlertTypeWithAuth, - ]; - - rulesClient.listRuleTypes.mockResolvedValueOnce(listTypes); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - - await handler(context, req, res); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the license check prevents listing alert types', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); - }); - - listAlertTypesRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/list_alert_types"`); - - const listTypes = [ - { - id: '1', - name: 'name', - actionGroups: [ - { - id: 'default', - name: 'Default', - }, - ], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - authorizedConsumers: {}, - actionVariables: { - context: [], - state: [], - }, - category: 'test', - producer: 'alerts', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - } as RegistryAlertTypeWithAuth, - ]; - - rulesClient.listRuleTypes.mockResolvedValueOnce(listTypes); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - rulesClient.listRuleTypes.mockResolvedValueOnce([]); - - listAlertTypesRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { params: { id: '1' }, body: {} }, - ['ok'] - ); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('listAlertTypes', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - listAlertTypesRoute(router, licenseState, docLinks); - - const [config] = router.get.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "GET", - "newApiPath": "/api/alerting/rule_types", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts b/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts deleted file mode 100644 index f4f2bc7936b3d..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts +++ /dev/null @@ -1,55 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -export const listAlertTypesRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.get( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/list_alert_types`, - validate: {}, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Get the alert types', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'GET', - newApiPath: '/api/alerting/rule_types', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('listAlertTypes', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - - return res.ok({ - body: Array.from(await rulesClient.listRuleTypes()), - }); - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_all.test.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_all.test.ts deleted file mode 100644 index d80cf415283d0..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/mute_all.test.ts +++ /dev/null @@ -1,143 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { muteAllAlertRoute } from './mute_all'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('muteAllAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('mute an alert', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAllAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_mute_all"`); - expect(config.options?.access).toBe('public'); - - rulesClient.muteAll.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.muteAll).toHaveBeenCalledTimes(1); - expect(rulesClient.muteAll.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAllAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_mute_all"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAllAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.muteAll.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid')); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - muteAllAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('muteAll', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAllAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{id}/_mute_all", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts deleted file mode 100644 index 75c860167f21c..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts +++ /dev/null @@ -1,70 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const muteAllAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_mute_all`, - validate: { - params: paramSchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Mute all alert instances', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{id}/_mute_all', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('muteAll', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - try { - await rulesClient.muteAll({ id }); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.test.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_instance.test.ts deleted file mode 100644 index 08e03a6d053ef..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.test.ts +++ /dev/null @@ -1,151 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { muteAlertInstanceRoute } from './mute_instance'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('muteAlertInstanceRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('mutes an alert instance', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAlertInstanceRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot( - `"/api/alerts/alert/{alert_id}/alert_instance/{alert_instance_id}/_mute"` - ); - expect(config.options?.access).toBe('public'); - - rulesClient.muteInstance.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - alert_id: '1', - alert_instance_id: '2', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.muteInstance).toHaveBeenCalledTimes(1); - expect(rulesClient.muteInstance.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "alertId": "1", - "alertInstanceId": "2", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAlertInstanceRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot( - `"/api/alerts/alert/{alert_id}/alert_instance/{alert_instance_id}/_mute"` - ); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAlertInstanceRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.muteInstance.mockRejectedValue( - new RuleTypeDisabledError('Fail', 'license_invalid') - ); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - muteAlertInstanceRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('muteInstance', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAlertInstanceRoute(router, licenseState, docLinks); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{rule_id}/alert/{alert_id}/_mute", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts deleted file mode 100644 index 23225c387ccaa..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts +++ /dev/null @@ -1,81 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { renameKeys } from '../lib/rename_keys'; -import { MuteOptions } from '../../rules_client'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -const paramSchema = schema.object({ - alert_id: schema.string(), - alert_instance_id: schema.string(), -}); - -export const muteAlertInstanceRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{alert_id}/alert_instance/{alert_instance_id}/_mute`, - validate: { - params: paramSchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Mute an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{rule_id}/alert/{alert_id}/_mute', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - - trackLegacyRouteUsage('muteInstance', usageCounter); - - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - - const renameMap = { - alert_id: 'alertId', - alert_instance_id: 'alertInstanceId', - }; - - const renamedQuery = renameKeys>(renameMap, req.params); - try { - await rulesClient.muteInstance(renamedQuery); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.test.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_all.test.ts deleted file mode 100644 index 5ae337e6a3f51..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.test.ts +++ /dev/null @@ -1,143 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { unmuteAllAlertRoute } from './unmute_all'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('unmuteAllAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('unmutes an alert', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAllAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_unmute_all"`); - expect(config.options?.access).toBe('public'); - - rulesClient.unmuteAll.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.unmuteAll).toHaveBeenCalledTimes(1); - expect(rulesClient.unmuteAll.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAllAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_unmute_all"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAllAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.unmuteAll.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid')); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - unmuteAllAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('unmuteAll', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAllAlertRoute(router, licenseState, docLinks); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{id}/_unmute_all", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts deleted file mode 100644 index 2684ea60d7336..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts +++ /dev/null @@ -1,70 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const unmuteAllAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_unmute_all`, - validate: { - params: paramSchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Unmute all alert instances', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{id}/_unmute_all', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('unmuteAll', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - try { - await rulesClient.unmuteAll({ id }); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.test.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.test.ts deleted file mode 100644 index b6fba61aaff8a..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.test.ts +++ /dev/null @@ -1,151 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { unmuteAlertInstanceRoute } from './unmute_instance'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('unmuteAlertInstanceRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('unmutes an alert instance', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAlertInstanceRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot( - `"/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute"` - ); - expect(config.options?.access).toBe('public'); - - rulesClient.unmuteInstance.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - alertId: '1', - alertInstanceId: '2', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.unmuteInstance).toHaveBeenCalledTimes(1); - expect(rulesClient.unmuteInstance.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "alertId": "1", - "alertInstanceId": "2", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAlertInstanceRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot( - `"/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute"` - ); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAlertInstanceRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.unmuteInstance.mockRejectedValue( - new RuleTypeDisabledError('Fail', 'license_invalid') - ); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - unmuteAlertInstanceRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('unmuteInstance', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAlertInstanceRoute(router, licenseState, docLinks); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{rule_id}/alert/{alert_id}/_unmute", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts deleted file mode 100644 index e6122a92509b0..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts +++ /dev/null @@ -1,71 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -const paramSchema = schema.object({ - alertId: schema.string(), - alertInstanceId: schema.string(), -}); - -export const unmuteAlertInstanceRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute`, - validate: { - params: paramSchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Unmute an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{rule_id}/alert/{alert_id}/_unmute', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('unmuteInstance', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { alertId, alertInstanceId } = req.params; - try { - await rulesClient.unmuteInstance({ alertId, alertInstanceId }); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/update.test.ts b/x-pack/plugins/alerting/server/routes/legacy/update.test.ts deleted file mode 100644 index 7aaee90b805c5..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/update.test.ts +++ /dev/null @@ -1,390 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { updateAlertRoute } from './update'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { RuleNotifyWhen, SanitizedRule, RuleSystemAction } from '../../../common'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('updateAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - const mockedResponse = { - id: '1', - alertTypeId: '1', - tags: ['foo'], - schedule: { interval: '12s' }, - params: { - otherField: false, - }, - createdAt: new Date(), - updatedAt: new Date(), - actions: [ - { - group: 'default', - id: '2', - actionTypeId: 'test', - params: { - baz: true, - }, - }, - ], - notifyWhen: RuleNotifyWhen.CHANGE, - }; - - const systemAction: RuleSystemAction = { - actionTypeId: 'test-2', - id: 'system_action-id', - params: { - foo: true, - }, - uuid: '123-456', - }; - - it('updates an alert with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.put.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - expect(config.options?.access).toBe('public'); - - rulesClient.update.mockResolvedValueOnce(mockedResponse as unknown as SanitizedRule); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - body: { - throttle: null, - name: 'abc', - tags: ['bar'], - schedule: { interval: '12s' }, - params: { - otherField: false, - }, - actions: [ - { - group: 'default', - id: '2', - params: { - baz: true, - }, - }, - ], - notifyWhen: 'onActionGroupChange', - }, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: mockedResponse }); - - expect(rulesClient.update).toHaveBeenCalledTimes(1); - expect(rulesClient.update.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "baz": true, - }, - }, - ], - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "otherField": false, - }, - "schedule": Object { - "interval": "12s", - }, - "tags": Array [ - "bar", - ], - "throttle": null, - }, - "id": "1", - }, - ] - `); - - expect(res.ok).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.put.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the license allows updating alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.put.mock.calls[0]; - - rulesClient.update.mockResolvedValueOnce(mockedResponse as unknown as SanitizedRule); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - body: { - throttle: null, - name: 'abc', - tags: ['bar'], - schedule: { interval: '12s' }, - params: { - otherField: false, - }, - actions: [ - { - group: 'default', - id: '2', - params: { - baz: true, - }, - }, - ], - }, - }, - ['ok'] - ); - - await handler(context, req, res); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the license check prevents updating alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); - }); - - updateAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.put.mock.calls[0]; - - rulesClient.update.mockResolvedValueOnce(mockedResponse as unknown as SanitizedRule); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - body: { - throttle: null, - name: 'abc', - tags: ['bar'], - schedule: { interval: '12s' }, - params: { - otherField: false, - }, - actions: [ - { - group: 'default', - id: '2', - params: { - baz: true, - }, - }, - ], - }, - }, - ['ok'] - ); - - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.put.mock.calls[0]; - - rulesClient.update.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid')); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - updateAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.put.mock.calls[0]; - rulesClient.update.mockResolvedValueOnce(mockedResponse as unknown as SanitizedRule); - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('update', mockUsageCounter); - }); - - it('does not return system actions', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.put.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - - rulesClient.update.mockResolvedValueOnce({ - ...mockedResponse, - systemActions: [systemAction], - } as unknown as SanitizedRule); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - body: { - throttle: null, - name: 'abc', - tags: ['bar'], - schedule: { interval: '12s' }, - params: { - otherField: false, - }, - actions: [ - { - group: 'default', - id: '2', - params: { - baz: true, - }, - }, - ], - notifyWhen: 'onActionGroupChange', - }, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: mockedResponse }); - - expect(rulesClient.update).toHaveBeenCalledTimes(1); - expect(rulesClient.update.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "baz": true, - }, - }, - ], - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "otherField": false, - }, - "schedule": Object { - "interval": "12s", - }, - "tags": Array [ - "bar", - ], - "throttle": null, - }, - "id": "1", - }, - ] - `); - - expect(res.ok).toHaveBeenCalled(); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateAlertRoute(router, licenseState, docLinks); - - const [config] = router.put.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "PUT", - "newApiPath": "/api/alerting/rule/rule/{id}", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/update.ts b/x-pack/plugins/alerting/server/routes/legacy/update.ts deleted file mode 100644 index 3e3d3b5a480f0..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/update.ts +++ /dev/null @@ -1,113 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { validateDurationSchema } from '../../lib'; -import { handleDisabledApiKeysError } from '../lib/error_handler'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { - RuleNotifyWhenType, - LEGACY_BASE_ALERT_API_PATH, - validateNotifyWhenType, -} from '../../../common'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -const bodySchema = schema.object({ - name: schema.string(), - tags: schema.arrayOf(schema.string(), { defaultValue: [] }), - schedule: schema.object({ - interval: schema.string({ validate: validateDurationSchema }), - }), - throttle: schema.nullable(schema.string({ validate: validateDurationSchema })), - params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), - actions: schema.arrayOf( - schema.object({ - group: schema.string(), - id: schema.string(), - params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), - actionTypeId: schema.maybe(schema.string()), - }), - { defaultValue: [] } - ), - notifyWhen: schema.nullable(schema.string({ validate: validateNotifyWhenType })), -}); - -export const updateAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.put( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}`, - validate: { - body: bodySchema, - params: paramSchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Update an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'PUT', - newApiPath: '/api/alerting/rule/rule/{id}', - }, - }, - }, - }, - handleDisabledApiKeysError( - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('update', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - const { name, actions, params, schedule, tags, throttle, notifyWhen } = req.body; - try { - const { systemActions, ...alertRes } = await rulesClient.update({ - id, - data: { - name, - actions, - params, - schedule, - tags, - throttle, - notifyWhen: notifyWhen as RuleNotifyWhenType, - }, - }); - return res.ok({ - body: alertRes, - }); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.test.ts b/x-pack/plugins/alerting/server/routes/legacy/update_api_key.test.ts deleted file mode 100644 index cb2817af2ed58..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.test.ts +++ /dev/null @@ -1,144 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { updateApiKeyRoute } from './update_api_key'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('updateApiKeyRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('updates api key for an alert', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateApiKeyRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_update_api_key"`); - expect(config.options?.access).toBe('public'); - - rulesClient.updateRuleApiKey.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.updateRuleApiKey).toHaveBeenCalledTimes(1); - expect(rulesClient.updateRuleApiKey.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateApiKeyRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_update_api_key"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateApiKeyRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.updateRuleApiKey.mockRejectedValue( - new RuleTypeDisabledError('Fail', 'license_invalid') - ); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - updateApiKeyRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('updateApiKey', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateApiKeyRoute(router, licenseState, docLinks); - - const [config] = router.post.mock.calls[0]; - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{id}/_update_api_key", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts b/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts deleted file mode 100644 index 603a321768573..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts +++ /dev/null @@ -1,73 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { handleDisabledApiKeysError } from '../lib/error_handler'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const updateApiKeyRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_update_api_key`, - validate: { - params: paramSchema, - }, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Update the API key for an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{id}/_update_api_key', - }, - }, - }, - }, - handleDisabledApiKeysError( - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('updateApiKey', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - try { - await rulesClient.updateRuleApiKey({ id }); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ) - ); -}; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/connector_types/stack/preconfigured_alert_history_connector.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/connector_types/stack/preconfigured_alert_history_connector.ts index 22f81d7bb7e96..b6197c268947e 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/connector_types/stack/preconfigured_alert_history_connector.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/connector_types/stack/preconfigured_alert_history_connector.ts @@ -137,7 +137,7 @@ export default function preconfiguredAlertHistoryConnectorTests({ expect().fail(`waiting for alert ${id} statuses ${Array.from(statuses)} timed out`); } - const response = await supertest.get(`/api/alerts/alert/${id}`); + const response = await supertest.get(`/api/alerting/rule/${id}`); expect(response.status).to.eql(200); const { executionStatus } = response.body || {}; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/delete.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/delete.ts index 811fbbf2b1732..37f482a5d512e 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/delete.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/delete.ts @@ -65,27 +65,5 @@ export default function createDeleteTests({ getService }: FtrProviderContext) { message: `Saved object [alert/${createdAlert.id}] not found`, }); }); - - describe('legacy', () => { - it('should handle delete alert request appropriately', async () => { - const { body: createdAlert } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) - .expect(200); - - await supertest - .delete(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(204, ''); - - try { - await getScheduledTask(createdAlert.scheduledTaskId); - throw new Error('Should have removed scheduled task'); - } catch (e) { - expect(e.meta.statusCode).to.eql(404); - } - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/disable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/disable.ts index 01fa746b65f2a..846c4a719522f 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/disable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/disable.ts @@ -266,50 +266,5 @@ export default function createDisableRuleTests({ getService }: FtrProviderContex id: createdRule.id, }); }); - - describe('legacy', function () { - it('should handle disable rule request appropriately', async () => { - const { body: createdRule } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ enabled: true })) - .expect(200); - objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdRule.id}/_disable`) - .set('kbn-xsrf', 'foo') - .expect(204); - - // task doc should still exist but be disabled - await retry.try(async () => { - const taskRecord = await getScheduledTask(createdRule.scheduled_task_id); - expect(taskRecord.type).to.eql('task'); - expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); - expect(JSON.parse(taskRecord.task.params)).to.eql({ - alertId: createdRule.id, - spaceId: Spaces.space1.id, - consumer: 'alertsFixture', - }); - expect(taskRecord.task.enabled).to.eql(false); - }); - - const { body: disabledRule } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdRule.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - - // Ensure revision was not updated - expect(disabledRule.revision).to.eql(0); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdRule.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/enable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/enable.ts index 74b8fd0307a86..8eae2dfe7022b 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/enable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/enable.ts @@ -94,48 +94,5 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex }); }); }); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('should handle enable alert request appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ enabled: false })) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/_enable`) - .set('kbn-xsrf', 'foo') - .expect(204); - - const { body: updatedAlert } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - expect(typeof updatedAlert.scheduled_task_id).to.eql('string'); - const taskRecord = await getScheduledTask(updatedAlert.scheduled_task_id); - expect(taskRecord.type).to.eql('task'); - expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); - expect(JSON.parse(taskRecord.task.params)).to.eql({ - alertId: createdAlert.id, - spaceId: Spaces.space1.id, - consumer: 'alertsFixture', - }); - expect(taskRecord.task.enabled).to.eql(true); - - // Ensure revision was not updated - expect(updatedAlert.revision).to.eql(0); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get.ts index e559b1d17f196..58fdbf377ecf1 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get.ts @@ -124,55 +124,5 @@ export default function createGetTests({ getService }: FtrProviderContext) { getTestUtils('public', objectRemover, supertest); getTestUtils('internal', objectRemover, supertest); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('should handle get alert request appropriately', async () => { - const { body: createdAlert } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}` - ); - - expect(response.status).to.eql(200); - expect(response.body).to.eql({ - id: createdAlert.id, - name: 'abc', - tags: ['foo'], - alertTypeId: 'test.noop', - consumer: 'alertsFixture', - schedule: { interval: '1m' }, - enabled: true, - actions: [], - params: {}, - createdBy: null, - scheduledTaskId: response.body.scheduledTaskId, - updatedBy: null, - apiKeyOwner: null, - apiKeyCreatedByUser: null, - throttle: '1m', - notifyWhen: 'onThrottleInterval', - muteAll: false, - mutedInstanceIds: [], - createdAt: response.body.createdAt, - updatedAt: response.body.updatedAt, - executionStatus: response.body.executionStatus, - revision: 0, - running: false, - ...(response.body.nextRun ? { nextRun: response.body.nextRun } : {}), - ...(response.body.lastRun ? { lastRun: response.body.lastRun } : {}), - }); - expect(Date.parse(response.body.createdAt)).to.be.greaterThan(0); - expect(Date.parse(response.body.updatedAt)).to.be.greaterThan(0); - if (response.body.nextRun) { - expect(Date.parse(response.body.nextRun)).to.be.greaterThan(0); - } - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_state.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_state.ts index 6082e6ff69eb8..986b48443d6c4 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_state.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_state.ts @@ -115,7 +115,7 @@ export default function createGetAlertStateTests({ getService }: FtrProviderCont // wait for alert to actually execute await retry.try(async () => { const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/state` + `${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}/state` ); expect(response.status).to.eql(200); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_summary.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_summary.ts index 86444543bde73..cee5e44afcc8d 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_summary.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_summary.ts @@ -384,78 +384,6 @@ export default function createGetAlertSummaryTests({ getService }: FtrProviderCo expect(actualAlerts).to.eql(expectedAlerts); }); }); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('handles multi-alert status', async () => { - // wait so cache expires - await setTimeoutAsync(TEST_CACHE_EXPIRATION_TIME); - - // pattern of when the alert should fire - const pattern = { - alertA: [true, true, true, true], - alertB: [true, true, false, false], - alertC: [true, true, true, true], - }; - - const { body: createdRule } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send( - getTestRuleData({ - rule_type_id: 'test.patternFiring', - params: { pattern }, - schedule: { interval: '1s' }, - }) - ) - .expect(200); - objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting'); - - await alertUtils.muteInstance(createdRule.id, 'alertC'); - await alertUtils.muteInstance(createdRule.id, 'alertD'); - await waitForEvents(createdRule.id, ['new-instance', 'recovered-instance']); - const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdRule.id}/_instance_summary` - ); - - const actualAlerts = checkAndCleanActualAlerts(response.body.instances, [ - 'alertA', - 'alertB', - 'alertC', - ]); - const expectedAlerts = { - alertA: { - status: 'Active', - muted: false, - actionGroupId: 'default', - activeStartDate: actualAlerts.alertA.activeStartDate, - flapping: false, - tracked: true, - }, - alertB: { - status: 'OK', - muted: false, - flapping: false, - tracked: true, - }, - alertC: { - status: 'Active', - muted: true, - actionGroupId: 'default', - activeStartDate: actualAlerts.alertC.activeStartDate, - flapping: false, - tracked: true, - }, - alertD: { - status: 'OK', - muted: true, - flapping: false, - tracked: true, - }, - }; - expect(actualAlerts).to.eql(expectedAlerts); - }); - }); }); async function waitForEvents(id: string, actions: string[]) { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_all.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_all.ts index e4cbec75460b0..09a12a1371454 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_all.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_all.ts @@ -51,35 +51,5 @@ export default function createMuteTests({ getService }: FtrProviderContext) { id: createdAlert.id, }); }); - - describe('legacy', () => { - it('should handle mute alert request appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ enabled: false })) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/_mute_all`) - .set('kbn-xsrf', 'foo') - .expect(204); - - const { body: updatedAlert } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - expect(updatedAlert.mute_all).to.eql(true); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_instance.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_instance.ts index ac580ad335c51..65791c86e833b 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_instance.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_instance.ts @@ -52,39 +52,5 @@ export default function createMuteInstanceTests({ getService }: FtrProviderConte id: createdAlert.id, }); }); - - describe('legacy', () => { - it('should handle mute alert instance request appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ enabled: false })) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${ - createdAlert.id - }/alert_instance/1/_mute` - ) - .set('kbn-xsrf', 'foo') - .expect(204); - - const { body: updatedAlert } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - expect(updatedAlert.muted_alert_ids).to.eql(['1']); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_all.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_all.ts index 363086e1549fe..42bca18c07bfc 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_all.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_all.ts @@ -53,39 +53,5 @@ export default function createUnmuteTests({ getService }: FtrProviderContext) { id: createdAlert.id, }); }); - - describe('legacy', () => { - it('should handle unmute alert request appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ enabled: false })) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/_mute_all`) - .set('kbn-xsrf', 'foo') - .expect(204); - await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/_unmute_all`) - .set('kbn-xsrf', 'foo') - .expect(204); - - const { body: updatedAlert } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - expect(updatedAlert.mute_all).to.eql(false); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_instance.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_instance.ts index 5655e52aa4d09..4b54c6c0c134f 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_instance.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_instance.ts @@ -53,47 +53,5 @@ export default function createUnmuteInstanceTests({ getService }: FtrProviderCon id: createdAlert.id, }); }); - - describe('legacy', () => { - it('should handle unmute alert instance request appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ enabled: false })) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${ - createdAlert.id - }/alert_instance/1/_mute` - ) - .set('kbn-xsrf', 'foo') - .expect(204); - await supertestWithoutAuth - .post( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${ - createdAlert.id - }/alert_instance/1/_unmute` - ) - .set('kbn-xsrf', 'foo') - .expect(204); - - const { body: updatedAlert } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - expect(updatedAlert.muted_alert_ids).to.eql([]); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update.ts index 025fa3b693dce..24fdf571f070d 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update.ts @@ -408,75 +408,5 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { .expect(400); }); }); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('should handle update alert request appropriately', async () => { - const { body: createdAlert } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - const updatedData = { - name: 'bcd', - tags: ['bar'], - params: { - foo: true, - }, - schedule: { interval: '12s' }, - actions: [], - throttle: '1m', - notifyWhen: 'onThrottleInterval', - }; - - const response = await supertest - .put(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .send(updatedData) - .expect(200); - - expect(response.body).to.eql({ - ...updatedData, - id: createdAlert.id, - tags: ['bar'], - alertTypeId: 'test.noop', - consumer: 'alertsFixture', - createdBy: null, - enabled: true, - updatedBy: null, - apiKeyOwner: null, - apiKeyCreatedByUser: null, - muteAll: false, - mutedInstanceIds: [], - notifyWhen: 'onThrottleInterval', - scheduledTaskId: createdAlert.scheduled_task_id, - createdAt: response.body.createdAt, - updatedAt: response.body.updatedAt, - executionStatus: response.body.executionStatus, - revision: 1, - running: false, - ...(response.body.nextRun ? { nextRun: response.body.nextRun } : {}), - ...(response.body.lastRun ? { lastRun: response.body.lastRun } : {}), - }); - expect(Date.parse(response.body.createdAt)).to.be.greaterThan(0); - expect(Date.parse(response.body.updatedAt)).to.be.greaterThan(0); - expect(Date.parse(response.body.updatedAt)).to.be.greaterThan( - Date.parse(response.body.createdAt) - ); - if (response.body.nextRun) { - expect(Date.parse(response.body.nextRun)).to.be.greaterThan(0); - } - - // Ensure AAD isn't broken - await checkAAD({ - supertest, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update_api_key.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update_api_key.ts index 0aa9ec3354acd..e588d0e606543 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update_api_key.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update_api_key.ts @@ -79,41 +79,5 @@ export default function createUpdateApiKeyTests({ getService }: FtrProviderConte }); }); }); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('should handle update alert api key appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/_update_api_key` - ) - .set('kbn-xsrf', 'foo') - .expect(204); - - const { body: updatedAlert } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - expect(updatedAlert.api_key_owner).to.eql(null); - - // Ensure revision is not incremented when API key is updated - expect(updatedAlert.revision).to.eql(0); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/functional/services/monitoring/alerts.js b/x-pack/test/functional/services/monitoring/alerts.js index c480cc0c45c03..b17cf142005bf 100644 --- a/x-pack/test/functional/services/monitoring/alerts.js +++ b/x-pack/test/functional/services/monitoring/alerts.js @@ -15,7 +15,7 @@ export function MonitoringAlertsProvider({ getService }) { return await Promise.all( alerts.map(async (alert) => - supertest.delete(`/api/alerts/alert/${alert.id}`).set('kbn-xsrf', 'true').expect(204) + supertest.delete(`/api/alerting/rule/${alert.id}`).set('kbn-xsrf', 'true').expect(204) ) ); } diff --git a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/alert_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/alert_flyout.ts index 25f77cb8d41ef..a24f19ddcb07c 100644 --- a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/alert_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/alert_flyout.ts @@ -134,7 +134,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { `{"tags":[],"url.port":["5678"],"observer.geo.name":["mpls"],"monitor.type":["http"]}` ); } finally { - await supertest.delete(`/api/alerts/alert/${id}`).set('kbn-xsrf', 'true').expect(204); + await supertest.delete(`/api/alerting/rule/${id}`).set('kbn-xsrf', 'true').expect(204); } }); }); @@ -206,7 +206,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(params).to.eql({}); expect(interval).to.eql('11m'); } finally { - await supertest.delete(`/api/alerts/alert/${id}`).set('kbn-xsrf', 'true').expect(204); + await supertest.delete(`/api/alerting/rule/${id}`).set('kbn-xsrf', 'true').expect(204); } }); }); diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/metrics_route.ts b/x-pack/test/plugin_api_integration/test_suites/task_manager/metrics_route.ts index 50568fe1c206c..b456e35d5d673 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/metrics_route.ts +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/metrics_route.ts @@ -301,7 +301,7 @@ export default function ({ getService }: FtrProviderContext) { // update apiKey to fix decryption error await request - .post(`/api/alerts/alert/${ruleId}/_update_api_key`) + .post(`/api/alerting/rule/${ruleId}/_update_api_key`) .set('kbn-xsrf', 'xxx') .expect(204); diff --git a/x-pack/test/rule_registry/common/lib/helpers/delete_alert.ts b/x-pack/test/rule_registry/common/lib/helpers/delete_alert.ts index 209b182a958c5..b373d0ffe8667 100644 --- a/x-pack/test/rule_registry/common/lib/helpers/delete_alert.ts +++ b/x-pack/test/rule_registry/common/lib/helpers/delete_alert.ts @@ -22,7 +22,7 @@ export const deleteAlert = async ( const { body: targetIndices } = await getAlertsTargetIndices(getService, user, spaceId); if (id) { const { body, status } = await supertest - .delete(`${getSpaceUrlPrefix(spaceId)}/api/alerts/alert/${id}`) + .delete(`${getSpaceUrlPrefix(spaceId)}/api/alerting/rule/${id}`) .auth(user.username, user.password) .set('kbn-xsrf', 'foo'); diff --git a/x-pack/test/rule_registry/common/lib/helpers/wait_until_next_execution.ts b/x-pack/test/rule_registry/common/lib/helpers/wait_until_next_execution.ts index 73e15c6cdbaeb..08613ba2c143d 100644 --- a/x-pack/test/rule_registry/common/lib/helpers/wait_until_next_execution.ts +++ b/x-pack/test/rule_registry/common/lib/helpers/wait_until_next_execution.ts @@ -27,7 +27,7 @@ export async function waitUntilNextExecution( }); const { body, status } = await supertest - .get(`${getSpaceUrlPrefix(spaceId)}/api/alerts/alert/${alert.id}`) + .get(`${getSpaceUrlPrefix(spaceId)}/api/alerting/rule/${alert.id}`) .auth(user.username, user.password) .set('kbn-xsrf', 'foo'); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/wait_for_alert_to_complete.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/wait_for_alert_to_complete.ts index d6799e6be611c..f70ead2781626 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/wait_for_alert_to_complete.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/wait_for_alert_to_complete.ts @@ -17,7 +17,9 @@ export const waitForAlertToComplete = async ( ): Promise => { await waitFor( async () => { - const response = await supertest.get(`/api/alerts/alert/${id}/state`).set('kbn-xsrf', 'true'); + const response = await supertest + .get(`/api/alerting/rule/${id}/state`) + .set('kbn-xsrf', 'true'); if (response.status !== 200) { log.debug( `Did not get an expected 200 "ok" when waiting for an alert to complete (waitForAlertToComplete). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( diff --git a/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/metrics_route.ts b/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/metrics_route.ts index 3e37c488e5190..2bab3cf0dc577 100644 --- a/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/metrics_route.ts +++ b/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/metrics_route.ts @@ -296,7 +296,7 @@ export default function ({ getService }: FtrProviderContext) { // update apiKey to fix decryption error await request - .post(`/api/alerts/alert/${ruleId}/_update_api_key`) + .post(`/api/alerting/rule/${ruleId}/_update_api_key`) .set('kbn-xsrf', 'xxx') .expect(204);