Skip to content

Commit

Permalink
[8.x] [ResponseOps][Alerting] Add deprecation object to legacy rule e…
Browse files Browse the repository at this point in the history
…ndpoints (#201550) (#202165)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[ResponseOps][Alerting] Add deprecation object to legacy rule
endpoints (#201550)](#201550)

<!--- Backport version: 8.9.8 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Julian
Gernun","email":"17549662+jcger@users.noreply.github.com"},"sourceCommit":{"committedDate":"2024-11-28T07:45:11Z","message":"[ResponseOps][Alerting]
Add deprecation object to legacy rule endpoints (#201550)\n\n##
Summary\r\n\r\nAdds deprecation object in deprecated alerting
routes\r\n\r\nCloses
https://github.com/elastic/kibana/issues/196556\r\n\r\n---------\r\n\r\nCo-authored-by:
lcawl
<lcawley@elastic.co>","sha":"93b67fb1a37b397284c92309e3ca864580b9fcfc","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Feature:Alerting","release_note:skip","Team:ResponseOps","v9.0.0","backport:prev-minor","v8.18.0"],"number":201550,"url":"https://github.com/elastic/kibana/pull/201550","mergeCommit":{"message":"[ResponseOps][Alerting]
Add deprecation object to legacy rule endpoints (#201550)\n\n##
Summary\r\n\r\nAdds deprecation object in deprecated alerting
routes\r\n\r\nCloses
https://github.com/elastic/kibana/issues/196556\r\n\r\n---------\r\n\r\nCo-authored-by:
lcawl
<lcawley@elastic.co>","sha":"93b67fb1a37b397284c92309e3ca864580b9fcfc"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/201550","number":201550,"mergeCommit":{"message":"[ResponseOps][Alerting]
Add deprecation object to legacy rule endpoints (#201550)\n\n##
Summary\r\n\r\nAdds deprecation object in deprecated alerting
routes\r\n\r\nCloses
https://github.com/elastic/kibana/issues/196556\r\n\r\n---------\r\n\r\nCo-authored-by:
lcawl
<lcawley@elastic.co>","sha":"93b67fb1a37b397284c92309e3ca864580b9fcfc"}},{"branch":"8.x","label":"v8.18.0","labelRegex":"^v8.18.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->
  • Loading branch information
jcger authored Nov 28, 2024
1 parent 4a19426 commit 09ae9ad
Show file tree
Hide file tree
Showing 40 changed files with 795 additions and 139 deletions.
2 changes: 1 addition & 1 deletion docs/CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -9043,4 +9043,4 @@ Use the `xpack.monitoring.clusterAlertsEmail` in kibana.yml.
The 8.0.0-alpha1 release includes the following bug fix.

Operations::
* Moves systemd service to /usr/lib/systemd/system {kibana-pull}83571[#83571]
* Moves systemd service to /usr/lib/systemd/system {kibana-pull}83571[#83571]
45 changes: 39 additions & 6 deletions docs/upgrade-notes.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,51 @@ For Elastic Security release information, refer to {security-guide}/release-note
==== Kibana APIs

[discrete]
[[breaking-201004]]
.[Cases] Legacy deprecations (9.0.0)
[[breaking-201550]]
.Removed legacy alerting endpoints (9.0.0)
[%collapsible]
====
*Details* +
`GET /api/cases/status` has been deprecated with no replacement. Deleted in v9.0.0
--
* `POST /api/alerts/alert/{id?}` has been replaced by `POST /api/alerting/rule/{id?}`
* `GET /api/alerts/alert/{id}` has been replaced by `GET /api/alerting/rule/{id}`
* `PUT /api/alerts/alert/{id}` has been replaced by `PUT /api/alerting/rule/rule/{id}`
* `DELETE: /api/alerts/alert/{id}` has been replaced by `DELETE /api/alerting/rule/{id}`
* `POST /api/alerts/alert/{id}/_disable` has been replaced by `POST /api/alerting/rule/{id}/_disable`
* `POST /api/alerts/alert/{id}/_enable` has been replaced by `POST /api/alerting/rule/{id}/_enable`
* `GET /api/alerts/_find` has been replaced by `GET /api/alerting/rules/_find`
* `GET /api/alerts/_health` has been replaced by `GET /api/alerting/rule/_health`
* `GET /api/alerts/list_alert_types` has been replaced by `GET /api/alerting/rule_types`
* `POST /api/alerts/alert/{alert_id}/alert_instance/{alert_instance_id}/_mute` has been replaced by `POST /api/alerting/rule/{rule_id}/alert/{alert_id}/_mute`
* `POST /api/alerts/alert/{alert_id}/alert_instance/{alert_instance_id}/_unmute` has been replaced by `POST /api/alerting/rule/{rule_id}/alert/{alert_id}/_unmute`
* `POST /api/alerts/alert/{id}/_mute_all` has been replaced by `POST /api/alerting/rule/{id}/_mute_all`
* `POST /api/alerts/alert/{id}/_unmute_all` has been replaced by `POST /api/alerting/rule/{id}/_unmute_all`
* `POST /api/alerts/alert/{id}/_update_api_key` has been replaced by `POST /api/alerting/rule/{id}/_update_api_key`
* `GET /api/alerts/{id}/_instance_summary` has been deprecated without replacement. Will be removed in v9.0.0
* `GET /api/alerts/{id}/state` has been deprecated without replacement. Will be removed in v9.0.0
--
`GET /api/cases/{case_id}/comments` has been replaced by `GET /api/cases/{case_id}/comments/_find` released in v7.13
*Impact* +
Deprecated endpoints will fail with a 404 status code starting from version 9.0.0
`GET /api/cases/<case_id>/user_actions` has been replaced by `GET /api/cases/<case_id>/user_actions/_find` released in v8.7
*Action* +
Remove references to `GET /api/alerts/{id}/_instance_summary` endpoint.
Remove references to `GET /api/alerts/{id}/state` endpoint.
Replace references to endpoints listed as deprecated by it's replacement. See `Details` section.
The updated APIs can be found here https://www.elastic.co/docs/api/doc/kibana/v8/group/endpoint-alerting
====

`includeComments` parameter in `GET /api/cases/{case_id}` has been deprecated. Use `GET /api/cases/{case_id}/comments/_find` instead, released in v7.13
[[breaking-201004]]
.Removed legacy cases endpoints (9.0.0)
[%collapsible]
====
*Details* +
--
* `GET /api/cases/status` has been deprecated with no replacement. Deleted in v9.0.0
* `GET /api/cases/{case_id}/comments` has been replaced by `GET /api/cases/{case_id}/comments/_find` released in v7.13
* `GET /api/cases/<case_id>/user_actions` has been replaced by `GET /api/cases/<case_id>/user_actions/_find` released in v8.7
* `includeComments` parameter in `GET /api/cases/{case_id}` has been deprecated. Use `GET /api/cases/{case_id}/comments/_find` instead, released in v7.13
--
*Impact* +
Deprecated endpoints will fail with a 404 status code starting from version 9.0.0
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-doc-links/src/get_doc_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D
slackApiAction: `${KIBANA_DOCS}slack-action-type.html#configuring-slack-web-api`,
teamsAction: `${KIBANA_DOCS}teams-action-type.html#configuring-teams`,
connectors: `${KIBANA_DOCS}action-types.html`,
legacyRuleApiDeprecations: `${KIBANA_DOCS}breaking-changes-summary.html#breaking-201550`,
},
taskManager: {
healthMonitoring: `${KIBANA_DOCS}task-manager-health-monitoring.html`,
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-doc-links/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ export interface DocLinks {
slackApiAction: string;
teamsAction: string;
connectors: string;
legacyRuleApiDeprecations: string;
}>;
readonly taskManager: Readonly<{
healthMonitoring: string;
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/alerting/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ export class AlertingPlugin {
encryptedSavedObjects: plugins.encryptedSavedObjects,
config$: plugins.unifiedSearch.autocomplete.getInitializerContextConfig().create(),
isServerless: !!plugins.serverless,
docLinks: core.docLinks,
});

return {
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/alerting/server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { IRouter } from '@kbn/core/server';
import { DocLinksServiceSetup, IRouter } from '@kbn/core/server';
import { UsageCounter } from '@kbn/usage-collection-plugin/server';
import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server';
import type { ConfigSchema } from '@kbn/unified-search-plugin/server/config';
Expand Down Expand Up @@ -81,6 +81,7 @@ export interface RouteOptions {
usageCounter?: UsageCounter;
config$?: Observable<ConfigSchema>;
isServerless?: boolean;
docLinks: DocLinksServiceSetup;
}

export function defineRoutes(opts: RouteOptions) {
Expand Down
50 changes: 47 additions & 3 deletions x-pack/plugins/alerting/server/routes/legacy/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ 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();

Expand All @@ -32,6 +33,7 @@ beforeEach(() => {
});

describe('createAlertRoute', () => {
const docLinks = docLinksServiceMock.createSetupContract();
const createdAt = new Date();
const updatedAt = new Date();

Expand Down Expand Up @@ -104,6 +106,7 @@ describe('createAlertRoute', () => {
licenseState,
encryptedSavedObjects,
usageCounter: mockUsageCounter,
docLinks,
});

const [config, handler] = router.post.mock.calls[0];
Expand Down Expand Up @@ -179,6 +182,7 @@ describe('createAlertRoute', () => {
encryptedSavedObjects,
usageCounter: mockUsageCounter,
isServerless: true,
docLinks,
});

const [config] = router.post.mock.calls[0];
Expand All @@ -204,6 +208,7 @@ describe('createAlertRoute', () => {
licenseState,
encryptedSavedObjects,
usageCounter: mockUsageCounter,
docLinks,
});

const [config, handler] = router.post.mock.calls[0];
Expand Down Expand Up @@ -281,6 +286,7 @@ describe('createAlertRoute', () => {
licenseState,
encryptedSavedObjects,
usageCounter: mockUsageCounter,
docLinks,
});

const [config, handler] = router.post.mock.calls[0];
Expand Down Expand Up @@ -359,6 +365,7 @@ describe('createAlertRoute', () => {
licenseState,
encryptedSavedObjects,
usageCounter: mockUsageCounter,
docLinks,
});

const [config, handler] = router.post.mock.calls[0];
Expand Down Expand Up @@ -426,7 +433,7 @@ describe('createAlertRoute', () => {
const router = httpServiceMock.createRouter();
const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true });

createAlertRoute({ router, licenseState, encryptedSavedObjects });
createAlertRoute({ router, licenseState, encryptedSavedObjects, docLinks });

const [, handler] = router.post.mock.calls[0];

Expand All @@ -448,7 +455,7 @@ describe('createAlertRoute', () => {
throw new Error('OMG');
});

createAlertRoute({ router, licenseState, encryptedSavedObjects });
createAlertRoute({ router, licenseState, encryptedSavedObjects, docLinks });

const [, handler] = router.post.mock.calls[0];

Expand All @@ -466,7 +473,7 @@ describe('createAlertRoute', () => {
const router = httpServiceMock.createRouter();
const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true });

createAlertRoute({ router, licenseState, encryptedSavedObjects });
createAlertRoute({ router, licenseState, encryptedSavedObjects, docLinks });

const [, handler] = router.post.mock.calls[0];

Expand All @@ -491,6 +498,7 @@ describe('createAlertRoute', () => {
licenseState,
encryptedSavedObjects,
usageCounter: mockUsageCounter,
docLinks,
});
const [, handler] = router.post.mock.calls[0];
rulesClient.create.mockResolvedValueOnce(createResult);
Expand All @@ -511,6 +519,7 @@ describe('createAlertRoute', () => {
licenseState,
encryptedSavedObjects,
usageCounter: mockUsageCounter,
docLinks,
});

const [config, handler] = router.post.mock.calls[0];
Expand Down Expand Up @@ -570,4 +579,39 @@ describe('createAlertRoute', () => {
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",
}
`
);
});
});
12 changes: 10 additions & 2 deletions x-pack/plugins/alerting/server/routes/legacy/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const createAlertRoute = ({
licenseState,
usageCounter,
isServerless,
docLinks,
}: RouteOptions) => {
router.post(
{
Expand All @@ -65,8 +66,15 @@ export const createAlertRoute = ({
access: isServerless ? 'internal' : 'public',
summary: 'Create an alert',
tags: ['oas-tag:alerting'],
// @ts-expect-error TODO(https://github.com/elastic/kibana/issues/196095): Replace {RouteDeprecationInfo}
deprecated: true,
deprecated: {
documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations,
severity: 'warning',
reason: {
type: 'migrate',
newApiMethod: 'POST',
newApiPath: '/api/alerting/rule/{id?}',
},
},
},
},
handleDisabledApiKeysError(
Expand Down
39 changes: 34 additions & 5 deletions x-pack/plugins/alerting/server/routes/legacy/delete.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ 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();

Expand All @@ -29,11 +30,13 @@ beforeEach(() => {
});

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);
deleteAlertRoute(router, licenseState, docLinks);

const [config, handler] = router.delete.mock.calls[0];

Expand Down Expand Up @@ -70,7 +73,7 @@ describe('deleteAlertRoute', () => {
const licenseState = licenseStateMock.create();
const router = httpServiceMock.createRouter();

deleteAlertRoute(router, licenseState, undefined, true);
deleteAlertRoute(router, licenseState, docLinks, undefined, true);

const [config] = router.delete.mock.calls[0];

Expand All @@ -82,7 +85,7 @@ describe('deleteAlertRoute', () => {
const licenseState = licenseStateMock.create();
const router = httpServiceMock.createRouter();

deleteAlertRoute(router, licenseState);
deleteAlertRoute(router, licenseState, docLinks);

const [, handler] = router.delete.mock.calls[0];

Expand All @@ -108,7 +111,7 @@ describe('deleteAlertRoute', () => {
throw new Error('OMG');
});

deleteAlertRoute(router, licenseState);
deleteAlertRoute(router, licenseState, docLinks);

const [, handler] = router.delete.mock.calls[0];

Expand All @@ -132,12 +135,38 @@ describe('deleteAlertRoute', () => {
const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract();
const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test');

deleteAlertRoute(router, licenseState, mockUsageCounter);
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",
}
`
);
});
});
13 changes: 11 additions & 2 deletions x-pack/plugins/alerting/server/routes/legacy/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

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';
Expand All @@ -20,6 +21,7 @@ const paramSchema = schema.object({
export const deleteAlertRoute = (
router: AlertingRouter,
licenseState: ILicenseState,
docLinks: DocLinksServiceSetup,
usageCounter?: UsageCounter,
isServerless?: boolean
) => {
Expand All @@ -33,8 +35,15 @@ export const deleteAlertRoute = (
access: isServerless ? 'internal' : 'public',
summary: 'Delete an alert',
tags: ['oas-tag:alerting'],
// @ts-expect-error TODO(https://github.com/elastic/kibana/issues/196095): Replace {RouteDeprecationInfo}
deprecated: true,
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) {
Expand Down
Loading

0 comments on commit 09ae9ad

Please sign in to comment.