From 0e10cb424170287c9c67688eb804f65ec9453ca3 Mon Sep 17 00:00:00 2001 From: Bamieh Date: Tue, 5 Nov 2024 19:39:40 +0300 Subject: [PATCH 01/11] internal access deprecations --- .../server/routes/message_routes.ts | 3 + .../core-deprecations-common/index.ts | 1 + .../core-deprecations-common/src/types.ts | 2 +- .../src/deprecations/api_deprecations.ts | 96 ------------------- .../api_deprecations/access_deprecations.ts | 54 +++++++++++ .../api_deprecation_id.test.ts | 51 ++++++++++ .../api_deprecations/api_deprecation_id.ts | 22 +++++ .../{ => api_deprecations}/i18n_texts.ts | 8 +- .../deprecations/api_deprecations/index.ts | 11 +++ .../register_api_depercation_info.test.ts} | 63 +++--------- .../register_api_depercation_info.ts | 64 +++++++++++++ .../api_deprecations/route_deprecations.ts | 55 +++++++++++ .../deprecations/api_deprecations/types.ts | 25 +++++ .../src/http_server.ts | 21 ++-- .../core-http-server-internal/src/types.ts | 4 +- packages/core/http/core-http-server/index.ts | 2 +- .../core-http-server/src/http_contract.ts | 8 +- .../http/core-http-server/src/router/index.ts | 2 +- .../core-http-server/src/router/router.ts | 5 +- .../upgrade_assistant/api_deprecations.ts | 12 +-- 20 files changed, 332 insertions(+), 177 deletions(-) delete mode 100644 packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations.ts create mode 100644 packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access_deprecations.ts create mode 100644 packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/api_deprecation_id.test.ts create mode 100644 packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/api_deprecation_id.ts rename packages/core/deprecations/core-deprecations-server-internal/src/deprecations/{ => api_deprecations}/i18n_texts.ts (96%) create mode 100644 packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/index.ts rename packages/core/deprecations/core-deprecations-server-internal/src/deprecations/{api_deprecations.test.ts => api_deprecations/register_api_depercation_info.test.ts} (88%) create mode 100644 packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts create mode 100644 packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route_deprecations.ts create mode 100644 packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/types.ts diff --git a/examples/routing_example/server/routes/message_routes.ts b/examples/routing_example/server/routes/message_routes.ts index c4f4aea1cf3e3..ccf200e811ffa 100644 --- a/examples/routing_example/server/routes/message_routes.ts +++ b/examples/routing_example/server/routes/message_routes.ts @@ -63,6 +63,9 @@ export function registerGetMessageByIdRoute(router: IRouter) { router.get( { path: `${INTERNAL_GET_MESSAGE_BY_ID_ROUTE}/{id}`, + options: { + access: 'internal', + }, validate: { params: schema.object({ id: schema.string(), diff --git a/packages/core/deprecations/core-deprecations-common/index.ts b/packages/core/deprecations/core-deprecations-common/index.ts index 005e84d7d57f1..de8122a18c551 100644 --- a/packages/core/deprecations/core-deprecations-common/index.ts +++ b/packages/core/deprecations/core-deprecations-common/index.ts @@ -11,6 +11,7 @@ export type { BaseDeprecationDetails, ConfigDeprecationDetails, FeatureDeprecationDetails, + ApiDeprecationDetails, DeprecationsDetails, DomainDeprecationDetails, DeprecationsGetResponse, diff --git a/packages/core/deprecations/core-deprecations-common/src/types.ts b/packages/core/deprecations/core-deprecations-common/src/types.ts index 85da30b2c1287..9a08be7808452 100644 --- a/packages/core/deprecations/core-deprecations-common/src/types.ts +++ b/packages/core/deprecations/core-deprecations-common/src/types.ts @@ -121,7 +121,7 @@ export type DeprecationsDetails = /** * @public */ -export type DomainDeprecationDetails = DeprecationsDetails & { +export type DomainDeprecationDetails = ExtendedDetails & { domainId: string; }; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations.ts deleted file mode 100644 index 45893987ddf92..0000000000000 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations.ts +++ /dev/null @@ -1,96 +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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { InternalHttpServiceSetup } from '@kbn/core-http-server-internal'; -import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; -import type { RouterDeprecatedRouteDetails } from '@kbn/core-http-server'; -import { DeprecationsDetails } from '@kbn/core-deprecations-common'; -import type { DeprecationsFactory } from '../deprecations_factory'; -import { - getApiDeprecationMessage, - getApiDeprecationsManualSteps, - getApiDeprecationTitle, -} from './i18n_texts'; - -interface ApiDeprecationsServiceDeps { - deprecationsFactory: DeprecationsFactory; - http: InternalHttpServiceSetup; - coreUsageData: InternalCoreUsageDataSetup; -} - -export const buildApiDeprecationId = ({ - routePath, - routeMethod, - routeVersion, -}: Pick): string => { - return [ - routeVersion || 'unversioned', - routeMethod.toLocaleLowerCase(), - routePath.replace(/\/$/, ''), - ].join('|'); -}; - -export const createGetApiDeprecations = - ({ http, coreUsageData }: Pick) => - async (): Promise => { - const deprecatedRoutes = http.getRegisteredDeprecatedApis(); - const usageClient = coreUsageData.getClient(); - const deprecatedApiUsageStats = await usageClient.getDeprecatedApiUsageStats(); - - return deprecatedApiUsageStats - .filter(({ apiTotalCalls, totalMarkedAsResolved }) => { - return apiTotalCalls > totalMarkedAsResolved; - }) - .filter(({ apiId }) => - deprecatedRoutes.some((routeDetails) => buildApiDeprecationId(routeDetails) === apiId) - ) - .map((apiUsageStats) => { - const { apiId, apiTotalCalls, totalMarkedAsResolved } = apiUsageStats; - const routeDeprecationDetails = deprecatedRoutes.find( - (routeDetails) => buildApiDeprecationId(routeDetails) === apiId - )!; - const { routeVersion, routePath, routeDeprecationOptions, routeMethod } = - routeDeprecationDetails; - - const deprecationLevel = routeDeprecationOptions.severity || 'warning'; - - return { - apiId, - title: getApiDeprecationTitle(routeDeprecationDetails), - level: deprecationLevel, - message: getApiDeprecationMessage(routeDeprecationDetails, apiUsageStats), - documentationUrl: routeDeprecationOptions.documentationUrl, - correctiveActions: { - manualSteps: getApiDeprecationsManualSteps(routeDeprecationDetails), - mark_as_resolved_api: { - routePath, - routeMethod, - routeVersion, - apiTotalCalls, - totalMarkedAsResolved, - timestamp: new Date(), - }, - }, - deprecationType: 'api', - domainId: 'core.routes-deprecations', - }; - }); - }; - -export const registerApiDeprecationsInfo = ({ - deprecationsFactory, - http, - coreUsageData, -}: ApiDeprecationsServiceDeps): void => { - const deprecationsRegistery = deprecationsFactory.getRegistry('core.api_deprecations'); - - deprecationsRegistery.registerDeprecations({ - getDeprecations: createGetApiDeprecations({ http, coreUsageData }), - }); -}; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access_deprecations.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access_deprecations.ts new file mode 100644 index 0000000000000..5cd574cf9f702 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access_deprecations.ts @@ -0,0 +1,54 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { + ApiDeprecationDetails, + DomainDeprecationDetails, +} from '@kbn/core-deprecations-common'; +import type { BuildApiDeprecationDetailsParams } from './types'; +import { + getApiDeprecationMessage, + getApiDeprecationsManualSteps, + getApiDeprecationTitle, +} from './i18n_texts'; +import { buildApiDeprecationId } from './api_deprecation_id'; + +export const buildApiAccessDeprecationDetails = ({ + apiUsageStats, + deprecatedApis, +}: BuildApiDeprecationDetailsParams): DomainDeprecationDetails => { + const { apiId, apiTotalCalls, totalMarkedAsResolved } = apiUsageStats; + const routeDeprecationDetails = deprecatedApis.find( + (routeDetails) => buildApiDeprecationId(routeDetails) === apiId + )!; + const { routeVersion, routePath, routeDeprecationOptions, routeMethod } = routeDeprecationDetails; + + const deprecationLevel = routeDeprecationOptions.severity || 'warning'; + + return { + apiId, + title: getApiDeprecationTitle(routeDeprecationDetails), + level: deprecationLevel, + message: getApiDeprecationMessage(routeDeprecationDetails, apiUsageStats), + documentationUrl: routeDeprecationOptions.documentationUrl, + correctiveActions: { + manualSteps: getApiDeprecationsManualSteps(routeDeprecationDetails), + mark_as_resolved_api: { + routePath, + routeMethod, + routeVersion, + apiTotalCalls, + totalMarkedAsResolved, + timestamp: new Date(), + }, + }, + deprecationType: 'api', + domainId: 'core.http.access-deprecations', + }; +}; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/api_deprecation_id.test.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/api_deprecation_id.test.ts new file mode 100644 index 0000000000000..151b7bd8d4cec --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/api_deprecation_id.test.ts @@ -0,0 +1,51 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { buildApiDeprecationId } from './api_deprecation_id'; + +describe('#buildApiDeprecationId', () => { + it('returns apiDeprecationId string for versioned routes', () => { + const apiDeprecationId = buildApiDeprecationId({ + routeMethod: 'get', + routePath: '/api/test', + routeVersion: '10-10-2023', + }); + expect(apiDeprecationId).toBe('10-10-2023|get|/api/test'); + }); + + it('returns apiDeprecationId string for unversioned routes', () => { + const apiDeprecationId = buildApiDeprecationId({ + routeMethod: 'get', + routePath: '/api/test', + }); + expect(apiDeprecationId).toBe('unversioned|get|/api/test'); + }); + + it('gives the same ID the route method is capitalized or not', () => { + const apiDeprecationId = buildApiDeprecationId({ + // @ts-expect-error + routeMethod: 'GeT', + routePath: '/api/test', + routeVersion: '10-10-2023', + }); + + expect(apiDeprecationId).toBe('10-10-2023|get|/api/test'); + }); + + it('gives the same ID the route path has a trailing slash or not', () => { + const apiDeprecationId = buildApiDeprecationId({ + // @ts-expect-error + routeMethod: 'GeT', + routePath: '/api/test/', + routeVersion: '10-10-2023', + }); + + expect(apiDeprecationId).toBe('10-10-2023|get|/api/test'); + }); +}); diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/api_deprecation_id.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/api_deprecation_id.ts new file mode 100644 index 0000000000000..0e3b6107a25e5 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/api_deprecation_id.ts @@ -0,0 +1,22 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { RouterDeprecatedApiDetails } from '@kbn/core-http-server'; + +export const buildApiDeprecationId = ({ + routePath, + routeMethod, + routeVersion, +}: Pick): string => { + return [ + routeVersion || 'unversioned', + routeMethod.toLocaleLowerCase(), + routePath.replace(/\/$/, ''), + ].join('|'); +}; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/i18n_texts.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/i18n_texts.ts similarity index 96% rename from packages/core/deprecations/core-deprecations-server-internal/src/deprecations/i18n_texts.ts rename to packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/i18n_texts.ts index cb1dacc97bd91..e5d63953e9f0f 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/i18n_texts.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/i18n_texts.ts @@ -7,12 +7,12 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { RouterDeprecatedRouteDetails } from '@kbn/core-http-server'; +import { RouterDeprecatedApiDetails } from '@kbn/core-http-server'; import { CoreDeprecatedApiUsageStats } from '@kbn/core-usage-data-server'; import { i18n } from '@kbn/i18n'; import moment from 'moment'; -export const getApiDeprecationTitle = (details: RouterDeprecatedRouteDetails) => { +export const getApiDeprecationTitle = (details: RouterDeprecatedApiDetails) => { const { routePath, routeMethod, routeDeprecationOptions } = details; const deprecationType = routeDeprecationOptions.reason.type; const routeWithMethod = `${routeMethod.toUpperCase()} ${routePath}`; @@ -32,7 +32,7 @@ export const getApiDeprecationTitle = (details: RouterDeprecatedRouteDetails) => }; export const getApiDeprecationMessage = ( - details: RouterDeprecatedRouteDetails, + details: RouterDeprecatedApiDetails, apiUsageStats: CoreDeprecatedApiUsageStats ): string[] => { const { routePath, routeMethod } = details; @@ -74,7 +74,7 @@ export const getApiDeprecationMessage = ( return messages; }; -export const getApiDeprecationsManualSteps = (details: RouterDeprecatedRouteDetails): string[] => { +export const getApiDeprecationsManualSteps = (details: RouterDeprecatedApiDetails): string[] => { const { routeDeprecationOptions } = details; const deprecationType = routeDeprecationOptions.reason.type; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/index.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/index.ts new file mode 100644 index 0000000000000..535401178e4c5 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/index.ts @@ -0,0 +1,11 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export { registerApiDeprecationsInfo } from './register_api_depercation_info'; +export { buildApiDeprecationId } from './api_deprecation_id'; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations.test.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.test.ts similarity index 88% rename from packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations.test.ts rename to packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.test.ts index b431088152f3e..0b93ef87e1954 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations.test.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.test.ts @@ -8,13 +8,13 @@ */ import type { DeepPartial } from '@kbn/utility-types'; -import { mockDeprecationsRegistry, mockDeprecationsFactory } from '../mocks'; +import { mockDeprecationsRegistry, mockDeprecationsFactory } from '../../mocks'; import { registerApiDeprecationsInfo, - buildApiDeprecationId, createGetApiDeprecations, -} from './api_deprecations'; -import { RouterDeprecatedRouteDetails } from '@kbn/core-http-server'; +} from './register_api_depercation_info'; +import { buildApiDeprecationId } from './api_deprecation_id'; +import { RouterDeprecatedApiDetails } from '@kbn/core-http-server'; import { httpServiceMock } from '@kbn/core-http-server-mocks'; import { coreUsageDataServiceMock, @@ -58,8 +58,8 @@ describe('#registerApiDeprecationsInfo', () => { describe('#createGetApiDeprecations', () => { const createDeprecatedRouteDetails = ( - overrides?: DeepPartial - ): RouterDeprecatedRouteDetails => + overrides?: DeepPartial + ): RouterDeprecatedApiDetails => _.merge( { routeDeprecationOptions: { @@ -72,7 +72,7 @@ describe('#registerApiDeprecationsInfo', () => { routeMethod: 'get', routePath: '/api/test/', routeVersion: '123', - } as RouterDeprecatedRouteDetails, + } as RouterDeprecatedApiDetails, overrides ); @@ -124,7 +124,7 @@ describe('#registerApiDeprecationsInfo', () => { }, "deprecationType": "api", "documentationUrl": "https://fake-url", - "domainId": "core.routes-deprecations", + "domainId": "core.http.routes-deprecations", "level": "critical", "message": Array [ "The API \\"GET /api/test_removed/\\" has been called 13 times. The last call was on Sunday, September 1, 2024 6:06 AM -04:00.", @@ -171,7 +171,7 @@ describe('#registerApiDeprecationsInfo', () => { }, "deprecationType": "api", "documentationUrl": "https://fake-url", - "domainId": "core.routes-deprecations", + "domainId": "core.http.routes-deprecations", "level": "critical", "message": Array [ "The API \\"GET /api/test_migrated/\\" has been called 13 times. The last call was on Sunday, September 1, 2024 6:06 AM -04:00.", @@ -216,7 +216,7 @@ describe('#registerApiDeprecationsInfo', () => { }, "deprecationType": "api", "documentationUrl": "https://fake-url", - "domainId": "core.routes-deprecations", + "domainId": "core.http.routes-deprecations", "level": "critical", "message": Array [ "The API \\"GET /api/test_bumped/\\" has been called 13 times. The last call was on Sunday, September 1, 2024 6:06 AM -04:00.", @@ -278,7 +278,7 @@ describe('#registerApiDeprecationsInfo', () => { }, "deprecationType": "api", "documentationUrl": "https://fake-url", - "domainId": "core.routes-deprecations", + "domainId": "core.http.routes-deprecations", "level": "critical", "message": Array [ "The API \\"GET /api/test_never_resolved/\\" has been called 13 times. The last call was on Sunday, September 1, 2024 6:06 AM -04:00.", @@ -310,44 +310,3 @@ describe('#registerApiDeprecationsInfo', () => { }); }); }); - -describe('#buildApiDeprecationId', () => { - it('returns apiDeprecationId string for versioned routes', () => { - const apiDeprecationId = buildApiDeprecationId({ - routeMethod: 'get', - routePath: '/api/test', - routeVersion: '10-10-2023', - }); - expect(apiDeprecationId).toBe('10-10-2023|get|/api/test'); - }); - - it('returns apiDeprecationId string for unversioned routes', () => { - const apiDeprecationId = buildApiDeprecationId({ - routeMethod: 'get', - routePath: '/api/test', - }); - expect(apiDeprecationId).toBe('unversioned|get|/api/test'); - }); - - it('gives the same ID the route method is capitalized or not', () => { - const apiDeprecationId = buildApiDeprecationId({ - // @ts-expect-error - routeMethod: 'GeT', - routePath: '/api/test', - routeVersion: '10-10-2023', - }); - - expect(apiDeprecationId).toBe('10-10-2023|get|/api/test'); - }); - - it('gives the same ID the route path has a trailing slash or not', () => { - const apiDeprecationId = buildApiDeprecationId({ - // @ts-expect-error - routeMethod: 'GeT', - routePath: '/api/test/', - routeVersion: '10-10-2023', - }); - - expect(apiDeprecationId).toBe('10-10-2023|get|/api/test'); - }); -}); diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts new file mode 100644 index 0000000000000..53171dc232556 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts @@ -0,0 +1,64 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { DeprecationsDetails } from '@kbn/core-deprecations-common'; + +import _ from 'lodash'; +import { buildApiRouteDeprecationDetails } from './route_deprecations'; +import { buildApiAccessDeprecationDetails } from './access_deprecations'; + +import { ApiDeprecationsServiceDeps } from './types'; +import { buildApiDeprecationId } from './api_deprecation_id'; + +export const createGetApiDeprecations = + ({ http, coreUsageData }: Pick) => + async (): Promise => { + const usageClient = coreUsageData.getClient(); + const deprecatedApis = http.getRegisteredDeprecatedApis(); + const deprecatedApiUsageStats = await usageClient.getDeprecatedApiUsageStats(); + + return deprecatedApiUsageStats + .filter(({ apiTotalCalls, totalMarkedAsResolved }) => { + return apiTotalCalls > totalMarkedAsResolved; + }) + .filter(({ apiId }) => + deprecatedApis.some((routeDetails) => buildApiDeprecationId(routeDetails) === apiId) + ) + .map((apiUsageStats) => { + const { internal: internalApiDeprecationedRoutes, ...deprecatedRoutes } = _.groupBy( + deprecatedApis, + 'routeAccess' + ); + + // buildApiAccessDeprecationDetails + return [ + buildApiRouteDeprecationDetails({ + apiUsageStats, + deprecatedApis: Object.values(deprecatedRoutes).flat(), + }), + buildApiAccessDeprecationDetails({ + apiUsageStats, + deprecatedApis: Object.values(internalApiDeprecationedRoutes), + }), + ]; + }) + .flat(); + }; + +export const registerApiDeprecationsInfo = ({ + deprecationsFactory, + http, + coreUsageData, +}: ApiDeprecationsServiceDeps): void => { + const deprecationsRegistery = deprecationsFactory.getRegistry('core.api_deprecations'); + + deprecationsRegistery.registerDeprecations({ + getDeprecations: createGetApiDeprecations({ http, coreUsageData }), + }); +}; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route_deprecations.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route_deprecations.ts new file mode 100644 index 0000000000000..6d6f59f8a4882 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route_deprecations.ts @@ -0,0 +1,55 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { + ApiDeprecationDetails, + DomainDeprecationDetails, +} from '@kbn/core-deprecations-common'; +import type { BuildApiDeprecationDetailsParams } from './types'; +import { + getApiDeprecationMessage, + getApiDeprecationsManualSteps, + getApiDeprecationTitle, +} from './i18n_texts'; + +import { buildApiDeprecationId } from './api_deprecation_id'; + +export const buildApiRouteDeprecationDetails = ({ + apiUsageStats, + deprecatedApis, +}: BuildApiDeprecationDetailsParams): DomainDeprecationDetails => { + const { apiId, apiTotalCalls, totalMarkedAsResolved } = apiUsageStats; + const routeDeprecationDetails = deprecatedApis.find( + (routeDetails) => buildApiDeprecationId(routeDetails) === apiId + )!; + const { routeVersion, routePath, routeDeprecationOptions, routeMethod } = routeDeprecationDetails; + + const deprecationLevel = routeDeprecationOptions.severity || 'warning'; + + return { + apiId, + title: getApiDeprecationTitle(routeDeprecationDetails), + level: deprecationLevel, + message: getApiDeprecationMessage(routeDeprecationDetails, apiUsageStats), + documentationUrl: routeDeprecationOptions.documentationUrl, + correctiveActions: { + manualSteps: getApiDeprecationsManualSteps(routeDeprecationDetails), + mark_as_resolved_api: { + routePath, + routeMethod, + routeVersion, + apiTotalCalls, + totalMarkedAsResolved, + timestamp: new Date(), + }, + }, + deprecationType: 'api', + domainId: 'core.http.routes-deprecations', + }; +}; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/types.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/types.ts new file mode 100644 index 0000000000000..4b3b34e9ee76d --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/types.ts @@ -0,0 +1,25 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { InternalHttpServiceSetup } from '@kbn/core-http-server-internal'; +import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { RouterDeprecatedApiDetails } from '@kbn/core-http-server'; +import type { CoreDeprecatedApiUsageStats } from '@kbn/core-usage-data-server'; +import type { DeprecationsFactory } from '../../deprecations_factory'; + +export interface ApiDeprecationsServiceDeps { + deprecationsFactory: DeprecationsFactory; + http: InternalHttpServiceSetup; + coreUsageData: InternalCoreUsageDataSetup; +} + +export interface BuildApiDeprecationDetailsParams { + apiUsageStats: CoreDeprecatedApiUsageStats; + deprecatedApis: RouterDeprecatedApiDetails[]; +} diff --git a/packages/core/http/core-http-server-internal/src/http_server.ts b/packages/core/http/core-http-server-internal/src/http_server.ts index 1dee6a3286788..14cc4397ebce0 100644 --- a/packages/core/http/core-http-server-internal/src/http_server.ts +++ b/packages/core/http/core-http-server-internal/src/http_server.ts @@ -35,7 +35,7 @@ import type { HttpServerInfo, HttpAuth, IAuthHeadersStorage, - RouterDeprecatedRouteDetails, + RouterDeprecatedApiDetails, RouteMethod, } from '@kbn/core-http-server'; import { performance } from 'perf_hooks'; @@ -389,8 +389,8 @@ export class HttpServer { } } - private getDeprecatedRoutes(): RouterDeprecatedRouteDetails[] { - const deprecatedRoutes: RouterDeprecatedRouteDetails[] = []; + private getDeprecatedRoutes(): RouterDeprecatedApiDetails[] { + const deprecatedRoutes: RouterDeprecatedApiDetails[] = []; for (const router of this.registeredRouters) { const allRouterRoutes = [ @@ -404,22 +404,29 @@ export class HttpServer { ...allRouterRoutes .flat() .map((route) => { + const access = route.options.access; if (route.isVersioned === true) { return [...route.handlers.entries()].map(([_, { options }]) => { const deprecated = options.options?.deprecated; - return { route, version: `${options.version}`, deprecated }; + return { route, version: `${options.version}`, deprecated, access }; }); } - return { route, version: undefined, deprecated: route.options.deprecated }; + + return { route, version: undefined, deprecated: route.options.deprecated, access }; }) .flat() - .filter(({ deprecated }) => isObject(deprecated)) - .flatMap(({ route, deprecated, version }) => { + .filter(({ deprecated, access }) => { + const isRouteDeprecation = isObject(deprecated); + const isAccessDeprecation = access === 'internal'; + return isRouteDeprecation || isAccessDeprecation; + }) + .flatMap(({ route, deprecated, version, access }) => { return { routeDeprecationOptions: deprecated!, routeMethod: route.method as RouteMethod, routePath: route.path, routeVersion: version, + routeAccess: access, }; }) ); diff --git a/packages/core/http/core-http-server-internal/src/types.ts b/packages/core/http/core-http-server-internal/src/types.ts index 0706af9ad73a2..35cac1f4b15ab 100644 --- a/packages/core/http/core-http-server-internal/src/types.ts +++ b/packages/core/http/core-http-server-internal/src/types.ts @@ -16,7 +16,7 @@ import type { IContextContainer, HttpServiceSetup, HttpServiceStart, - RouterDeprecatedRouteDetails, + RouterDeprecatedApiDetails, } from '@kbn/core-http-server'; import { CoreKibanaRequest } from '@kbn/core-http-router-server-internal'; import { RouteDeprecationInfo } from '@kbn/core-http-server/src/router/route'; @@ -71,7 +71,7 @@ export interface InternalHttpServiceSetup contextName: ContextName, provider: IContextProvider ) => IContextContainer; - getRegisteredDeprecatedApis: () => RouterDeprecatedRouteDetails[]; + getRegisteredDeprecatedApis: () => RouterDeprecatedApiDetails[]; } /** @internal */ diff --git a/packages/core/http/core-http-server/index.ts b/packages/core/http/core-http-server/index.ts index 9c12f6a09ac45..866fdbee29260 100644 --- a/packages/core/http/core-http-server/index.ts +++ b/packages/core/http/core-http-server/index.ts @@ -93,7 +93,7 @@ export type { IRouter, RouteRegistrar, RouterRoute, - RouterDeprecatedRouteDetails, + RouterDeprecatedApiDetails, IKibanaSocket, KibanaErrorResponseFactory, KibanaRedirectionResponseFactory, diff --git a/packages/core/http/core-http-server/src/http_contract.ts b/packages/core/http/core-http-server/src/http_contract.ts index e2f675bd8d0c0..2da699e5ea4a6 100644 --- a/packages/core/http/core-http-server/src/http_contract.ts +++ b/packages/core/http/core-http-server/src/http_contract.ts @@ -12,7 +12,7 @@ import type { IContextProvider, IRouter, RequestHandlerContextBase, - RouterDeprecatedRouteDetails, + RouterDeprecatedApiDetails, } from './router'; import type { AuthenticationHandler, @@ -362,12 +362,12 @@ export interface HttpServiceSetup< getServerInfo: () => HttpServerInfo; /** - * Provides a list of all registered deprecated routes {{@link RouterDeprecatedRouteDetails | information}}. + * Provides a list of all registered deprecated routes {{@link RouterDeprecatedApiDetails | information}}. * The routers will be evaluated everytime this function gets called to * accommodate for any late route registrations - * @returns {RouterDeprecatedRouteDetails[]} + * @returns {RouterDeprecatedApiDetails[]} */ - getDeprecatedRoutes: () => RouterDeprecatedRouteDetails[]; + getDeprecatedRoutes: () => RouterDeprecatedApiDetails[]; } /** @public */ diff --git a/packages/core/http/core-http-server/src/router/index.ts b/packages/core/http/core-http-server/src/router/index.ts index 8e2b9373c43bd..26358a5fcde36 100644 --- a/packages/core/http/core-http-server/src/router/index.ts +++ b/packages/core/http/core-http-server/src/router/index.ts @@ -80,7 +80,7 @@ export type { LazyValidator, } from './route_validator'; export { RouteValidationError } from './route_validator'; -export type { IRouter, RouteRegistrar, RouterRoute, RouterDeprecatedRouteDetails } from './router'; +export type { IRouter, RouteRegistrar, RouterRoute, RouterDeprecatedApiDetails } from './router'; export type { IKibanaSocket } from './socket'; export type { KibanaErrorResponseFactory, diff --git a/packages/core/http/core-http-server/src/router/router.ts b/packages/core/http/core-http-server/src/router/router.ts index d8b79bee13025..b8c03380a500a 100644 --- a/packages/core/http/core-http-server/src/router/router.ts +++ b/packages/core/http/core-http-server/src/router/router.ts @@ -10,7 +10,7 @@ import type { Request, ResponseObject, ResponseToolkit } from '@hapi/hapi'; import type Boom from '@hapi/boom'; import type { VersionedRouter } from '../versioning'; -import type { RouteConfig, RouteDeprecationInfo, RouteMethod } from './route'; +import type { RouteAccess, RouteConfig, RouteDeprecationInfo, RouteMethod } from './route'; import type { RequestHandler, RequestHandlerWrapper } from './request_handler'; import type { RequestHandlerContextBase } from './request_handler_context'; import type { RouteConfigOptions } from './route'; @@ -143,9 +143,10 @@ export interface RouterRoute { } /** @public */ -export interface RouterDeprecatedRouteDetails { +export interface RouterDeprecatedApiDetails { routeDeprecationOptions: RouteDeprecationInfo; routeMethod: RouteMethod; routePath: string; routeVersion?: string; + routeAccess?: RouteAccess; } diff --git a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/api_deprecations.ts b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/api_deprecations.ts index f146bf38f5f26..3ee458e74a9a0 100644 --- a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/api_deprecations.ts +++ b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/api_deprecations.ts @@ -7,21 +7,19 @@ import expect from '@kbn/expect'; import { expect as expectExpect } from 'expect'; -import type { DomainDeprecationDetails } from '@kbn/core-deprecations-common'; -import { ApiDeprecationDetails } from '@kbn/core-deprecations-common/src/types'; import { setTimeout as setTimeoutAsync } from 'timers/promises'; import { UsageCountersSavedObject } from '@kbn/usage-collection-plugin/server'; import _ from 'lodash'; +import type { + ApiDeprecationDetails, + DomainDeprecationDetails, +} from '@kbn/core-deprecations-common'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -interface DomainApiDeprecationDetails extends ApiDeprecationDetails { - domainId: string; -} - const getApiDeprecations = (allDeprecations: DomainDeprecationDetails[]) => { return allDeprecations.filter( (deprecation) => deprecation.deprecationType === 'api' - ) as unknown as DomainApiDeprecationDetails[]; + ) as unknown as Array>; }; export default function ({ getService }: FtrProviderContext) { From 087ca984ba3bbd642aca78ba084f02c4b1f8ae89 Mon Sep 17 00:00:00 2001 From: Bamieh Date: Wed, 6 Nov 2024 21:01:00 +0300 Subject: [PATCH 02/11] add internal routes to post validation --- examples/routing_example/common/index.ts | 2 + .../server/routes/deprecated_routes/index.ts | 2 + .../routes/deprecated_routes/internal.ts | 54 +++++++++++++++++++ .../register_api_depercation_info.ts | 1 - .../src/routes/post_validation_handler.ts | 5 +- 5 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 examples/routing_example/server/routes/deprecated_routes/internal.ts diff --git a/examples/routing_example/common/index.ts b/examples/routing_example/common/index.ts index b83582b66ff08..90f1c5e9a6743 100644 --- a/examples/routing_example/common/index.ts +++ b/examples/routing_example/common/index.ts @@ -20,4 +20,6 @@ export const DEPRECATED_ROUTES = { REMOVED_ROUTE: '/api/routing_example/d/removed_route', MIGRATED_ROUTE: '/api/routing_example/d/migrated_route', VERSIONED_ROUTE: '/api/routing_example/d/versioned', + INTERNAL_DEPRECATED_ROUTE: '/api/routing_example/d/internal_deprecated_route', + INTERNAL_ONLY_ROUTE: '/internal/routing_example/d/internal_only_route', }; diff --git a/examples/routing_example/server/routes/deprecated_routes/index.ts b/examples/routing_example/server/routes/deprecated_routes/index.ts index 75dc0261ed1b9..3fa535b171d9a 100644 --- a/examples/routing_example/server/routes/deprecated_routes/index.ts +++ b/examples/routing_example/server/routes/deprecated_routes/index.ts @@ -10,8 +10,10 @@ import { IRouter } from '@kbn/core/server'; import { registerDeprecatedRoute } from './unversioned'; import { registerVersionedDeprecatedRoute } from './versioned'; +import { registerInternalDeprecatedRoute } from './internal'; export function registerDeprecatedRoutes(router: IRouter) { registerDeprecatedRoute(router); registerVersionedDeprecatedRoute(router); + registerInternalDeprecatedRoute(router); } diff --git a/examples/routing_example/server/routes/deprecated_routes/internal.ts b/examples/routing_example/server/routes/deprecated_routes/internal.ts new file mode 100644 index 0000000000000..983d1ab444979 --- /dev/null +++ b/examples/routing_example/server/routes/deprecated_routes/internal.ts @@ -0,0 +1,54 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { IRouter } from '@kbn/core/server'; +import { DEPRECATED_ROUTES } from '../../../common'; + +export const registerInternalDeprecatedRoute = (router: IRouter) => { + router.get( + { + path: DEPRECATED_ROUTES.INTERNAL_DEPRECATED_ROUTE, + validate: false, + options: { + access: 'internal', + deprecated: { + documentationUrl: 'https://elastic.co/', + severity: 'critical', + reason: { type: 'remove' }, + }, + }, + }, + async (ctx, req, res) => { + return res.ok({ + body: { + result: + 'Called deprecated route with `access: internal`. Check UA to see the deprecation.', + }, + }); + } + ); + + router.get( + { + path: DEPRECATED_ROUTES.INTERNAL_ONLY_ROUTE, + validate: false, + options: { + access: 'internal', + }, + }, + async (ctx, req, res) => { + return res.ok({ + body: { + result: + 'Called route with `access: internal` Although this API is not marked as deprecated it will show in UA. Check UA to see the deprecation.', + }, + }); + } + ); +}; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts index 53171dc232556..47fbd123b5594 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts @@ -36,7 +36,6 @@ export const createGetApiDeprecations = 'routeAccess' ); - // buildApiAccessDeprecationDetails return [ buildApiRouteDeprecationDetails({ apiUsageStats, diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts b/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts index b93c17af2f536..be6ca2d1e482b 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts @@ -36,7 +36,10 @@ export function createRouteDeprecationsHandler({ coreUsageData: InternalCoreUsageDataSetup; }) { return (req: CoreKibanaRequest, { deprecated }: { deprecated?: RouteDeprecationInfo }) => { - if (deprecated && isObject(deprecated) && req.route.routePath) { + const hasRouteDeprecation = deprecated && isObject(deprecated); + const hasAccessDeprecation = req.route.options.access === 'internal'; + const isApiDeprecation = hasAccessDeprecation || hasRouteDeprecation; + if (isApiDeprecation && req.route.routePath) { const counterName = buildApiDeprecationId({ routeMethod: req.route.method, routePath: req.route.routePath, From e31e86b2c3119ecf331ed137dddad0fe025d049c Mon Sep 17 00:00:00 2001 From: Bamieh Date: Sun, 10 Nov 2024 15:42:54 +0100 Subject: [PATCH 03/11] finalize copy --- .../routes/deprecated_routes/internal.ts | 3 +- .../{ => access}/access_deprecations.ts | 20 ++-- .../api_deprecations/access/i18n_texts.ts | 101 ++++++++++++++++++ .../api_deprecations/access/index.ts | 10 ++ .../register_api_depercation_info.test.ts | 2 +- .../register_api_depercation_info.ts | 47 ++++---- .../{ => route}/i18n_texts.ts | 59 +++++----- .../api_deprecations/route/index.ts | 10 ++ .../{ => route}/route_deprecations.ts | 20 ++-- .../deprecations/api_deprecations/types.ts | 2 +- packages/core/http/core-http-server/index.ts | 2 + .../http/core-http-server/src/router/index.ts | 9 +- .../core-http-server/src/router/router.ts | 14 ++- x-pack/plugins/upgrade_assistant/README.md | 18 ++-- 14 files changed, 238 insertions(+), 79 deletions(-) rename packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/{ => access}/access_deprecations.ts (67%) create mode 100644 packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/i18n_texts.ts create mode 100644 packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/index.ts rename packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/{ => route}/i18n_texts.ts (70%) create mode 100644 packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/index.ts rename packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/{ => route}/route_deprecations.ts (73%) diff --git a/examples/routing_example/server/routes/deprecated_routes/internal.ts b/examples/routing_example/server/routes/deprecated_routes/internal.ts index 983d1ab444979..033a6c713292b 100644 --- a/examples/routing_example/server/routes/deprecated_routes/internal.ts +++ b/examples/routing_example/server/routes/deprecated_routes/internal.ts @@ -20,7 +20,8 @@ export const registerInternalDeprecatedRoute = (router: IRouter) => { deprecated: { documentationUrl: 'https://elastic.co/', severity: 'critical', - reason: { type: 'remove' }, + message: 'Additonal message for internal deprecated api', + reason: { type: 'deprecate' }, }, }, }, diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access_deprecations.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/access_deprecations.ts similarity index 67% rename from packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access_deprecations.ts rename to packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/access_deprecations.ts index 5cd574cf9f702..6e264e05e8164 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access_deprecations.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/access_deprecations.ts @@ -11,34 +11,30 @@ import type { ApiDeprecationDetails, DomainDeprecationDetails, } from '@kbn/core-deprecations-common'; -import type { BuildApiDeprecationDetailsParams } from './types'; +import type { BuildApiDeprecationDetailsParams } from '../types'; import { getApiDeprecationMessage, getApiDeprecationsManualSteps, getApiDeprecationTitle, } from './i18n_texts'; -import { buildApiDeprecationId } from './api_deprecation_id'; export const buildApiAccessDeprecationDetails = ({ apiUsageStats, - deprecatedApis, + deprecatedApiDetails, }: BuildApiDeprecationDetailsParams): DomainDeprecationDetails => { const { apiId, apiTotalCalls, totalMarkedAsResolved } = apiUsageStats; - const routeDeprecationDetails = deprecatedApis.find( - (routeDetails) => buildApiDeprecationId(routeDetails) === apiId - )!; - const { routeVersion, routePath, routeDeprecationOptions, routeMethod } = routeDeprecationDetails; + const { routeVersion, routePath, routeDeprecationOptions, routeMethod } = deprecatedApiDetails; - const deprecationLevel = routeDeprecationOptions.severity || 'warning'; + const deprecationLevel = routeDeprecationOptions?.severity || 'warning'; return { apiId, - title: getApiDeprecationTitle(routeDeprecationDetails), + title: getApiDeprecationTitle(deprecatedApiDetails), level: deprecationLevel, - message: getApiDeprecationMessage(routeDeprecationDetails, apiUsageStats), - documentationUrl: routeDeprecationOptions.documentationUrl, + message: getApiDeprecationMessage(deprecatedApiDetails, apiUsageStats), + documentationUrl: routeDeprecationOptions?.documentationUrl, correctiveActions: { - manualSteps: getApiDeprecationsManualSteps(routeDeprecationDetails), + manualSteps: getApiDeprecationsManualSteps(), mark_as_resolved_api: { routePath, routeMethod, diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/i18n_texts.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/i18n_texts.ts new file mode 100644 index 0000000000000..bd1f92cf368fe --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/i18n_texts.ts @@ -0,0 +1,101 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { RouterDeprecatedApiDetails } from '@kbn/core-http-server'; +import { CoreDeprecatedApiUsageStats } from '@kbn/core-usage-data-server'; +import { i18n } from '@kbn/i18n'; +import moment from 'moment'; + +export const getApiDeprecationTitle = ( + details: Pick +) => { + const { routePath, routeMethod } = details; + const routeWithMethod = `${routeMethod.toUpperCase()} ${routePath}`; + + return i18n.translate('core.deprecations.apiAccessDeprecation.infoTitle', { + defaultMessage: 'The "{routeWithMethod}" API is internal to Elastic', + values: { + routeWithMethod, + }, + }); +}; + +export const getApiDeprecationMessage = ( + details: Pick< + RouterDeprecatedApiDetails, + 'routePath' | 'routeMethod' | 'routeDeprecationOptions' + >, + apiUsageStats: CoreDeprecatedApiUsageStats +): string[] => { + const { routePath, routeMethod, routeDeprecationOptions } = details; + const { apiLastCalledAt, apiTotalCalls, markedAsResolvedLastCalledAt, totalMarkedAsResolved } = + apiUsageStats; + + const diff = apiTotalCalls - totalMarkedAsResolved; + const wasResolvedBefore = totalMarkedAsResolved > 0; + const routeWithMethod = `${routeMethod.toUpperCase()} ${routePath}`; + + const messages = [ + i18n.translate('core.deprecations.apiAccessDeprecation.apiCallsDetailsMessage', { + defaultMessage: + 'The API "{routeWithMethod}" has been called {apiTotalCalls} times. The last call was on {apiLastCalledAt}.', + values: { + routeWithMethod, + apiTotalCalls, + apiLastCalledAt: moment(apiLastCalledAt).format('LLLL Z'), + }, + }), + ]; + + if (wasResolvedBefore) { + messages.push( + i18n.translate('core.deprecations.apiAccessDeprecation.previouslyMarkedAsResolvedMessage', { + defaultMessage: + 'This issue has been marked as resolved on {markedAsResolvedLastCalledAt} but the API has been called {timeSinceLastResolved, plural, one {# time} other {# times}} since.', + values: { + timeSinceLastResolved: diff, + markedAsResolvedLastCalledAt: moment(markedAsResolvedLastCalledAt).format('LLLL Z'), + }, + }) + ); + } + + messages.push( + i18n.translate('core.deprecations.apiAccessDeprecation.internalApiExplanationMessage', { + defaultMessage: + 'Internal APIs are meant to be used by Elastic services only. You should not use them. External access to these APIs will be restricted.', + }) + ); + + if (routeDeprecationOptions?.message) { + // Surfaces additional deprecation messages passed into the route in UA + messages.push(routeDeprecationOptions.message); + } + + return messages; +}; + +export const getApiDeprecationsManualSteps = (): string[] => { + return [ + i18n.translate('core.deprecations.apiAccessDeprecation.manualSteps.identifyCallsOriginStep', { + defaultMessage: 'Identify the origin of these API calls.', + }), + i18n.translate('core.deprecations.apiAccessDeprecation.manualSteps.deleteRequestsStep', { + defaultMessage: + 'Delete any requests you have that use this API. Check the learn more link for possible alternatives.', + }), + i18n.translate( + 'core.deprecations.apiAccessDeprecation.manualSteps.accessDepractionMarkAsResolvedStep', + { + defaultMessage: + 'Once you have successfully stopped using this API, mark this issue as resolved. It will no longer appear in the Upgrade Assistant unless another call using this API is detected.', + } + ), + ]; +}; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/index.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/index.ts new file mode 100644 index 0000000000000..8bf195a8360f1 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/index.ts @@ -0,0 +1,10 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export { buildApiAccessDeprecationDetails } from './access_deprecations'; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.test.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.test.ts index 1df0956ce543d..77d6f089ffb40 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.test.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.test.ts @@ -260,7 +260,7 @@ describe('#registerApiDeprecationsInfo', () => { }, "deprecationType": "api", "documentationUrl": "https://fake-url", - "domainId": "core.routes-deprecations", + "domainId": "core.http.routes-deprecations", "level": "critical", "message": Array [ "The API \\"GET /api/test_deprecated/\\" has been called 13 times. The last call was on Sunday, September 1, 2024 6:06 AM -04:00.", diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts index 47fbd123b5594..535db90577106 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts @@ -9,12 +9,10 @@ import { DeprecationsDetails } from '@kbn/core-deprecations-common'; -import _ from 'lodash'; -import { buildApiRouteDeprecationDetails } from './route_deprecations'; -import { buildApiAccessDeprecationDetails } from './access_deprecations'; - -import { ApiDeprecationsServiceDeps } from './types'; +import { buildApiRouteDeprecationDetails } from './route/route_deprecations'; +import { buildApiAccessDeprecationDetails } from './access/access_deprecations'; import { buildApiDeprecationId } from './api_deprecation_id'; +import type { ApiDeprecationsServiceDeps } from './types'; export const createGetApiDeprecations = ({ http, coreUsageData }: Pick) => @@ -31,23 +29,32 @@ export const createGetApiDeprecations = deprecatedApis.some((routeDetails) => buildApiDeprecationId(routeDetails) === apiId) ) .map((apiUsageStats) => { - const { internal: internalApiDeprecationedRoutes, ...deprecatedRoutes } = _.groupBy( - deprecatedApis, - 'routeAccess' + const { apiId } = apiUsageStats; + const deprecatedApiDetails = deprecatedApis.find( + (routeDetails) => buildApiDeprecationId(routeDetails) === apiId ); + if (!deprecatedApiDetails) { + throw new Error(`Unable to find deprecation details for "${apiId}"`); + } - return [ - buildApiRouteDeprecationDetails({ - apiUsageStats, - deprecatedApis: Object.values(deprecatedRoutes).flat(), - }), - buildApiAccessDeprecationDetails({ - apiUsageStats, - deprecatedApis: Object.values(internalApiDeprecationedRoutes), - }), - ]; - }) - .flat(); + const { routeAccess } = deprecatedApiDetails; + + switch (routeAccess) { + case 'internal': { + return buildApiAccessDeprecationDetails({ + apiUsageStats, + deprecatedApiDetails, + }); + } + case 'public': + default: { + return buildApiRouteDeprecationDetails({ + apiUsageStats, + deprecatedApiDetails, + }); + } + } + }); }; export const registerApiDeprecationsInfo = ({ diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/i18n_texts.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/i18n_texts.ts similarity index 70% rename from packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/i18n_texts.ts rename to packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/i18n_texts.ts index 41d35c1f1494c..8cbade658bb2e 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/i18n_texts.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/i18n_texts.ts @@ -14,15 +14,19 @@ import moment from 'moment'; export const getApiDeprecationTitle = (details: RouterDeprecatedApiDetails) => { const { routePath, routeMethod, routeDeprecationOptions } = details; + if (!routeDeprecationOptions) { + throw new Error(`Router "deprecated" param is missing for path "${routePath}".`); + } + const deprecationType = routeDeprecationOptions.reason.type; const routeWithMethod = `${routeMethod.toUpperCase()} ${routePath}`; - const deprecationTypeText = i18n.translate('core.deprecations.deprecations.apiDeprecationType', { + const deprecationTypeText = i18n.translate('core.deprecations.apiRouteDeprecation.type', { defaultMessage: '{deprecationType, select, remove {is removed} bump {has a newer version available} migrate {is migrated to a different API} other {is deprecated}}', values: { deprecationType }, }); - return i18n.translate('core.deprecations.deprecations.apiDeprecationInfoTitle', { + return i18n.translate('core.deprecations.apiRouteDeprecation.infoTitle', { defaultMessage: 'The "{routeWithMethod}" route {deprecationTypeText}', values: { routeWithMethod, @@ -36,6 +40,9 @@ export const getApiDeprecationMessage = ( apiUsageStats: CoreDeprecatedApiUsageStats ): string[] => { const { routePath, routeMethod, routeDeprecationOptions } = details; + if (!routeDeprecationOptions) { + throw new Error(`Router "deprecated" param is missing for path "${routePath}".`); + } const { apiLastCalledAt, apiTotalCalls, markedAsResolvedLastCalledAt, totalMarkedAsResolved } = apiUsageStats; @@ -44,7 +51,7 @@ export const getApiDeprecationMessage = ( const routeWithMethod = `${routeMethod.toUpperCase()} ${routePath}`; const messages = [ - i18n.translate('core.deprecations.deprecations.apiDeprecationApiCallsDetailsMessage', { + i18n.translate('core.deprecations.apiRouteDeprecation.apiCallsDetailsMessage', { defaultMessage: 'The API "{routeWithMethod}" has been called {apiTotalCalls} times. The last call was on {apiLastCalledAt}.', values: { @@ -57,17 +64,14 @@ export const getApiDeprecationMessage = ( if (wasResolvedBefore) { messages.push( - i18n.translate( - 'core.deprecations.deprecations.apiDeprecationPreviouslyMarkedAsResolvedMessage', - { - defaultMessage: - 'This issue has been marked as resolved on {markedAsResolvedLastCalledAt} but the API has been called {timeSinceLastResolved, plural, one {# time} other {# times}} since.', - values: { - timeSinceLastResolved: diff, - markedAsResolvedLastCalledAt: moment(markedAsResolvedLastCalledAt).format('LLLL Z'), - }, - } - ) + i18n.translate('core.deprecations.apiRouteDeprecation.previouslyMarkedAsResolvedMessage', { + defaultMessage: + 'This issue has been marked as resolved on {markedAsResolvedLastCalledAt} but the API has been called {timeSinceLastResolved, plural, one {# time} other {# times}} since.', + values: { + timeSinceLastResolved: diff, + markedAsResolvedLastCalledAt: moment(markedAsResolvedLastCalledAt).format('LLLL Z'), + }, + }) ); } @@ -80,11 +84,15 @@ export const getApiDeprecationMessage = ( }; export const getApiDeprecationsManualSteps = (details: RouterDeprecatedApiDetails): string[] => { - const { routeDeprecationOptions } = details; + const { routePath, routeDeprecationOptions } = details; + if (!routeDeprecationOptions) { + throw new Error(`Router "deprecated" param is missing for path "${routePath}".`); + } + const deprecationType = routeDeprecationOptions.reason.type; const manualSteps = [ - i18n.translate('core.deprecations.deprecations.manualSteps.apiIseprecatedStep', { + i18n.translate('core.deprecations.apiRouteDeprecation.manualSteps.identifyCallsOriginStep', { defaultMessage: 'Identify the origin of these API calls.', }), ]; @@ -93,7 +101,7 @@ export const getApiDeprecationsManualSteps = (details: RouterDeprecatedApiDetail case 'bump': { const { newApiVersion } = routeDeprecationOptions.reason; manualSteps.push( - i18n.translate('core.deprecations.deprecations.manualSteps.bumpDetailsStep', { + i18n.translate('core.deprecations.apiRouteDeprecation.manualSteps.bumpTypeStep', { defaultMessage: 'Update the requests to use the following new version of the API instead: "{newApiVersion}".', values: { newApiVersion }, @@ -104,7 +112,7 @@ export const getApiDeprecationsManualSteps = (details: RouterDeprecatedApiDetail case 'remove': { manualSteps.push( - i18n.translate('core.deprecations.deprecations.manualSteps.removeTypeExplainationStep', { + i18n.translate('core.deprecations.apiRouteDeprecation.manualSteps.removeTypeStep', { defaultMessage: 'This API no longer exists and no replacement is available. Delete any requests you have that use this API.', }) @@ -113,7 +121,7 @@ export const getApiDeprecationsManualSteps = (details: RouterDeprecatedApiDetail } case 'deprecate': { manualSteps.push( - i18n.translate('core.deprecations.deprecations.manualSteps.removeTypeExplainationStep', { + i18n.translate('core.deprecations.apiRouteDeprecation.manualSteps.deprecateTypeStep', { defaultMessage: 'For now, the API will still work, but will be moved or removed in a future version. Check the Learn more link for more information. If you are no longer using the API, you can mark this issue as resolved. It will no longer appear in the Upgrade Assistant unless another call using this API is detected.', }) @@ -125,7 +133,7 @@ export const getApiDeprecationsManualSteps = (details: RouterDeprecatedApiDetail const newRouteWithMethod = `${newApiMethod.toUpperCase()} ${newApiPath}`; manualSteps.push( - i18n.translate('core.deprecations.deprecations.manualSteps.migrateDetailsStep', { + i18n.translate('core.deprecations.apiRouteDeprecation.manualSteps.migrateTypeStep', { defaultMessage: 'Update the requests to use the following new API instead: "{newRouteWithMethod}".', values: { newRouteWithMethod }, @@ -137,10 +145,13 @@ export const getApiDeprecationsManualSteps = (details: RouterDeprecatedApiDetail if (deprecationType !== 'deprecate') { manualSteps.push( - i18n.translate('core.deprecations.deprecations.manualSteps.markAsResolvedStep', { - defaultMessage: - 'Check that you are no longer using the old API in any requests, and mark this issue as resolved. It will no longer appear in the Upgrade Assistant unless another call using this API is detected.', - }) + i18n.translate( + 'core.deprecations.apiRouteDeprecation.manualSteps.routeDepractionMarkAsResolvedStep', + { + defaultMessage: + 'Check that you are no longer using the old API in any requests, and mark this issue as resolved. It will no longer appear in the Upgrade Assistant unless another call using this API is detected.', + } + ) ); } diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/index.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/index.ts new file mode 100644 index 0000000000000..2e28928c9c065 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/index.ts @@ -0,0 +1,10 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export { buildApiRouteDeprecationDetails } from './route_deprecations'; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route_deprecations.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts similarity index 73% rename from packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route_deprecations.ts rename to packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts index 6d6f59f8a4882..cbddb117c1620 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route_deprecations.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts @@ -11,35 +11,33 @@ import type { ApiDeprecationDetails, DomainDeprecationDetails, } from '@kbn/core-deprecations-common'; -import type { BuildApiDeprecationDetailsParams } from './types'; +import type { BuildApiDeprecationDetailsParams } from '../types'; import { getApiDeprecationMessage, getApiDeprecationsManualSteps, getApiDeprecationTitle, } from './i18n_texts'; -import { buildApiDeprecationId } from './api_deprecation_id'; - export const buildApiRouteDeprecationDetails = ({ apiUsageStats, - deprecatedApis, + deprecatedApiDetails, }: BuildApiDeprecationDetailsParams): DomainDeprecationDetails => { const { apiId, apiTotalCalls, totalMarkedAsResolved } = apiUsageStats; - const routeDeprecationDetails = deprecatedApis.find( - (routeDetails) => buildApiDeprecationId(routeDetails) === apiId - )!; - const { routeVersion, routePath, routeDeprecationOptions, routeMethod } = routeDeprecationDetails; + const { routeVersion, routePath, routeDeprecationOptions, routeMethod } = deprecatedApiDetails; + if (!routeDeprecationOptions) { + throw new Error(`Expecing deprecated to be defined for route ${apiId}`); + } const deprecationLevel = routeDeprecationOptions.severity || 'warning'; return { apiId, - title: getApiDeprecationTitle(routeDeprecationDetails), + title: getApiDeprecationTitle(deprecatedApiDetails), level: deprecationLevel, - message: getApiDeprecationMessage(routeDeprecationDetails, apiUsageStats), + message: getApiDeprecationMessage(deprecatedApiDetails, apiUsageStats), documentationUrl: routeDeprecationOptions.documentationUrl, correctiveActions: { - manualSteps: getApiDeprecationsManualSteps(routeDeprecationDetails), + manualSteps: getApiDeprecationsManualSteps(deprecatedApiDetails), mark_as_resolved_api: { routePath, routeMethod, diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/types.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/types.ts index 4b3b34e9ee76d..ad6436b70c55f 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/types.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/types.ts @@ -21,5 +21,5 @@ export interface ApiDeprecationsServiceDeps { export interface BuildApiDeprecationDetailsParams { apiUsageStats: CoreDeprecatedApiUsageStats; - deprecatedApis: RouterDeprecatedApiDetails[]; + deprecatedApiDetails: RouterDeprecatedApiDetails; } diff --git a/packages/core/http/core-http-server/index.ts b/packages/core/http/core-http-server/index.ts index 15c7ff2f7dfe2..af3c566f6a8d2 100644 --- a/packages/core/http/core-http-server/index.ts +++ b/packages/core/http/core-http-server/index.ts @@ -94,6 +94,8 @@ export type { RouteRegistrar, RouterRoute, RouterDeprecatedApiDetails, + RouterAccessDeprecatedApiDetails, + RouterRouteDeprecatedApiDetails, IKibanaSocket, KibanaErrorResponseFactory, KibanaRedirectionResponseFactory, diff --git a/packages/core/http/core-http-server/src/router/index.ts b/packages/core/http/core-http-server/src/router/index.ts index 67423a93f849a..2c7a83469ebb1 100644 --- a/packages/core/http/core-http-server/src/router/index.ts +++ b/packages/core/http/core-http-server/src/router/index.ts @@ -81,7 +81,14 @@ export type { LazyValidator, } from './route_validator'; export { RouteValidationError } from './route_validator'; -export type { IRouter, RouteRegistrar, RouterRoute, RouterDeprecatedApiDetails } from './router'; +export type { + IRouter, + RouteRegistrar, + RouterRoute, + RouterDeprecatedApiDetails, + RouterAccessDeprecatedApiDetails, + RouterRouteDeprecatedApiDetails, +} from './router'; export type { IKibanaSocket } from './socket'; export type { KibanaErrorResponseFactory, diff --git a/packages/core/http/core-http-server/src/router/router.ts b/packages/core/http/core-http-server/src/router/router.ts index b8c03380a500a..f770cfcc45e4b 100644 --- a/packages/core/http/core-http-server/src/router/router.ts +++ b/packages/core/http/core-http-server/src/router/router.ts @@ -144,9 +144,21 @@ export interface RouterRoute { /** @public */ export interface RouterDeprecatedApiDetails { - routeDeprecationOptions: RouteDeprecationInfo; + routeDeprecationOptions?: RouteDeprecationInfo; routeMethod: RouteMethod; routePath: string; routeVersion?: string; routeAccess?: RouteAccess; } + +/** @public */ +export interface RouterRouteDeprecatedApiDetails extends RouterDeprecatedApiDetails { + routeAccess: 'public'; + routeDeprecationOptions: RouteDeprecationInfo; +} + +/** @public */ +export interface RouterAccessDeprecatedApiDetails extends RouterDeprecatedApiDetails { + routeAccess: 'internal'; + routeDeprecationOptions?: RouteDeprecationInfo; +} diff --git a/x-pack/plugins/upgrade_assistant/README.md b/x-pack/plugins/upgrade_assistant/README.md index 9e2cf1b47e60a..e1cadeb0404f9 100644 --- a/x-pack/plugins/upgrade_assistant/README.md +++ b/x-pack/plugins/upgrade_assistant/README.md @@ -21,14 +21,14 @@ When we want to enable ML model snapshot deprecation warnings again we need to c There are three sources of deprecation information: -* [**Elasticsearch Deprecation Info API.**](https://www.elastic.co/guide/en/elasticsearch/reference/master/migration-api-deprecation.html) +* [**Elasticsearch Deprecation Info API.**](https://www.elastic.co/guide/en/elasticsearch/reference/main/migration-api-deprecation.html) This is information about Elasticsearch cluster, node, Machine Learning, and index-level settings that use deprecated features that will be removed or changed in the next major version. ES server engineers are responsible for adding deprecations to the Deprecation Info API. * [**Elasticsearch deprecation logs.**](https://www.elastic.co/guide/en/elasticsearch/reference/current/logging.html#deprecation-logging) These surface runtime deprecations, e.g. a Painless script that uses a deprecated accessor or a request to a deprecated API. These are also generally surfaced as deprecation headers within the response. Even if the cluster state is good, app maintainers need to watch the logs in case deprecations are discovered as data is migrated. Starting in 7.x, deprecation logs can be written to a file or a data stream ([#58924](https://github.com/elastic/elasticsearch/pull/58924)). When the data stream exists, the Upgrade Assistant provides a way to analyze the logs through Observability or Discover ([#106521](https://github.com/elastic/kibana/pull/106521)). -* [**Kibana deprecations API.**](https://github.com/elastic/kibana/blob/master/src/core/server/deprecations/README.mdx) This is information about deprecated features and configs in Kibana. These deprecations are only communicated to the user if the deployment is using these features. Kibana engineers are responsible for adding deprecations to the deprecations API for their respective team. +* [**Kibana deprecations API.**](https://github.com/elastic/kibana/blob/main/src/core/server/deprecations/README.mdx) This is information about deprecated features and configs in Kibana. These deprecations are only communicated to the user if the deployment is using these features. Kibana engineers are responsible for adding deprecations to the deprecations API for their respective team. ### Fixing problems @@ -286,15 +286,19 @@ The following comprehensive deprecated routes examples are registered inside the Run them in the console to trigger the deprecation condition so they show up in the UA: ``` -# Versioned routes: Version 1 is deprecated +# Route deprecations for Versioned routes: Version 1 is deprecated GET kbn:/api/routing_example/d/versioned?apiVersion=1 GET kbn:/api/routing_example/d/versioned?apiVersion=2 -# Non-versioned routes +# Route deprecations for Non-versioned routes GET kbn:/api/routing_example/d/removed_route GET kbn:/api/routing_example/d/deprecated_route POST kbn:/api/routing_example/d/migrated_route {} + +# Access deprecations +GET kbn:/api/routing_example/d/internal_deprecated_route +GET kbn:/internal/routing_example/d/internal_only_route ``` 1. You can also mark as deprecated in the UA to remove the deprecation from the list. @@ -331,7 +335,7 @@ This is a non-exhaustive list of different error scenarios in Upgrade Assistant. ### Telemetry -The Upgrade Assistant tracks several triggered events in the UI, using Kibana Usage Collection service's [UI counters](https://github.com/elastic/kibana/blob/master/src/plugins/usage_collection/README.mdx#ui-counters). +The Upgrade Assistant tracks several triggered events in the UI, using Kibana Usage Collection service's [UI counters](https://github.com/elastic/kibana/blob/main/src/plugins/usage_collection/README.mdx#ui-counters). **Overview page** - Component loaded @@ -350,6 +354,6 @@ The Upgrade Assistant tracks several triggered events in the UI, using Kibana Us - Component loaded - Click event for "Quick resolve" button -In addition to UI counters, the Upgrade Assistant has a [custom usage collector](https://github.com/elastic/kibana/blob/master/src/plugins/usage_collection/README.mdx#custom-collector). It currently is only responsible for tracking whether the user has deprecation logging enabled or not. +In addition to UI counters, the Upgrade Assistant has a [custom usage collector](https://github.com/elastic/kibana/blob/main/src/plugins/usage_collection/README.mdx#custom-collector). It currently is only responsible for tracking whether the user has deprecation logging enabled or not. -For testing instructions, refer to the [Kibana Usage Collection service README](https://github.com/elastic/kibana/blob/master/src/plugins/usage_collection/README.mdx#testing). \ No newline at end of file +For testing instructions, refer to the [Kibana Usage Collection service README](https://github.com/elastic/kibana/blob/main/src/plugins/usage_collection/README.mdx#testing). \ No newline at end of file From 687164ee6963197ac74de0bb4c49a61800dc72b0 Mon Sep 17 00:00:00 2001 From: Bamieh Date: Sun, 10 Nov 2024 20:50:57 +0100 Subject: [PATCH 04/11] integration tests --- examples/routing_example/common/index.ts | 3 +- .../routes/deprecated_routes/internal.ts | 5 +- .../routes/deprecated_routes/versioned.ts | 98 ++++++++----- .../access/access_deprecations.ts | 8 ++ .../api_deprecations/access/index.ts | 2 +- .../deprecations/api_deprecations/index.ts | 2 + .../register_api_depercation_info.ts | 10 +- .../api_deprecations/route/index.ts | 2 +- .../route/route_deprecations.ts | 16 ++- .../src/deprecations/index.ts | 7 +- .../src/routes/get.ts | 3 + .../src/routes/post_validation_handler.ts | 9 +- .../src/routes/resolve_deprecated_api.ts | 3 + src/plugins/telemetry/schema/oss_plugins.json | 12 ++ x-pack/plugins/upgrade_assistant/README.md | 7 +- .../upgrade_assistant/api_deprecations.ts | 133 ++++++++++++++---- 16 files changed, 236 insertions(+), 84 deletions(-) diff --git a/examples/routing_example/common/index.ts b/examples/routing_example/common/index.ts index 134ddd58fec74..205144ad0f872 100644 --- a/examples/routing_example/common/index.ts +++ b/examples/routing_example/common/index.ts @@ -20,7 +20,8 @@ export const DEPRECATED_ROUTES = { DEPRECATED_ROUTE: '/api/routing_example/d/deprecated_route', REMOVED_ROUTE: '/api/routing_example/d/removed_route', MIGRATED_ROUTE: '/api/routing_example/d/migrated_route', - VERSIONED_ROUTE: '/api/routing_example/d/versioned', + VERSIONED_ROUTE: '/api/routing_example/d/versioned_route', INTERNAL_DEPRECATED_ROUTE: '/api/routing_example/d/internal_deprecated_route', INTERNAL_ONLY_ROUTE: '/internal/routing_example/d/internal_only_route', + VERSIONED_INTERNAL_ROUTE: '/internal/routing_example/d/internal_versioned_route', }; diff --git a/examples/routing_example/server/routes/deprecated_routes/internal.ts b/examples/routing_example/server/routes/deprecated_routes/internal.ts index 033a6c713292b..95267cb66dd38 100644 --- a/examples/routing_example/server/routes/deprecated_routes/internal.ts +++ b/examples/routing_example/server/routes/deprecated_routes/internal.ts @@ -16,6 +16,7 @@ export const registerInternalDeprecatedRoute = (router: IRouter) => { path: DEPRECATED_ROUTES.INTERNAL_DEPRECATED_ROUTE, validate: false, options: { + // Explicitly set access is to internal access: 'internal', deprecated: { documentationUrl: 'https://elastic.co/', @@ -39,9 +40,7 @@ export const registerInternalDeprecatedRoute = (router: IRouter) => { { path: DEPRECATED_ROUTES.INTERNAL_ONLY_ROUTE, validate: false, - options: { - access: 'internal', - }, + // If no access is specified then it defaults to internal }, async (ctx, req, res) => { return res.ok({ diff --git a/examples/routing_example/server/routes/deprecated_routes/versioned.ts b/examples/routing_example/server/routes/deprecated_routes/versioned.ts index 060bc64403dba..6261ef6f9cb91 100644 --- a/examples/routing_example/server/routes/deprecated_routes/versioned.ts +++ b/examples/routing_example/server/routes/deprecated_routes/versioned.ts @@ -11,42 +11,72 @@ import type { IRouter } from '@kbn/core/server'; import { DEPRECATED_ROUTES } from '../../../common'; export const registerVersionedDeprecatedRoute = (router: IRouter) => { - const versionedRoute = router.versioned.get({ - path: DEPRECATED_ROUTES.VERSIONED_ROUTE, - description: 'Routing example plugin deprecated versioned route.', - access: 'internal', - options: { - excludeFromOAS: true, - }, - enableQueryVersion: true, - }); - - versionedRoute.addVersion( - { + router.versioned + .get({ + path: DEPRECATED_ROUTES.VERSIONED_ROUTE, + description: 'Routing example plugin deprecated versioned route.', + access: 'public', options: { - deprecated: { - documentationUrl: 'https://elastic.co/', - severity: 'warning', - reason: { type: 'bump', newApiVersion: '2' }, + excludeFromOAS: true, + }, + enableQueryVersion: true, + }) + .addVersion( + { + options: { + deprecated: { + documentationUrl: 'https://elastic.co/', + severity: 'warning', + reason: { type: 'deprecate' }, + }, }, + validate: false, + version: '2023-10-31', }, - validate: false, - version: '1', - }, - (ctx, req, res) => { - return res.ok({ - body: { result: 'Called deprecated version of the API. API version 1 -> 2' }, - }); - } - ); + (ctx, req, res) => { + return res.ok({ + body: { result: 'Called deprecated version of the API "2023-10-31"' }, + }); + } + ); - versionedRoute.addVersion( - { - version: '2', - validate: false, - }, - (ctx, req, res) => { - return res.ok({ body: { result: 'Called API version 2' } }); - } - ); + router.versioned + .get({ + path: DEPRECATED_ROUTES.VERSIONED_INTERNAL_ROUTE, + description: 'Routing example plugin deprecated versioned route.', + access: 'internal', + options: { + excludeFromOAS: true, + }, + enableQueryVersion: true, + }) + .addVersion( + { + options: { + deprecated: { + documentationUrl: 'https://elastic.co/', + severity: 'warning', + reason: { type: 'bump', newApiVersion: '2' }, + }, + }, + validate: false, + version: '1', + }, + (ctx, req, res) => { + return res.ok({ + body: { result: 'Called internal deprecated version of the API 1.' }, + }); + } + ) + .addVersion( + { + validate: false, + version: '2', + }, + (ctx, req, res) => { + return res.ok({ + body: { result: 'Called non-deprecated version of the API.' }, + }); + } + ); }; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/access_deprecations.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/access_deprecations.ts index 6e264e05e8164..bc9b35f235472 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/access_deprecations.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/access_deprecations.ts @@ -11,6 +11,7 @@ import type { ApiDeprecationDetails, DomainDeprecationDetails, } from '@kbn/core-deprecations-common'; +import { CoreKibanaRequest } from '@kbn/core-http-router-server-internal'; import type { BuildApiDeprecationDetailsParams } from '../types'; import { getApiDeprecationMessage, @@ -18,6 +19,13 @@ import { getApiDeprecationTitle, } from './i18n_texts'; +export const getIsAccessApiDeprecation = (req: CoreKibanaRequest): boolean => { + const isNotPublicAccess = req.route.options.access !== 'public'; + const isNotInternalRequest = !req.isInternalApiRequest; + + return !!(isNotPublicAccess && isNotInternalRequest); +}; + export const buildApiAccessDeprecationDetails = ({ apiUsageStats, deprecatedApiDetails, diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/index.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/index.ts index 8bf195a8360f1..b78ddba35d2c2 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/index.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/index.ts @@ -7,4 +7,4 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -export { buildApiAccessDeprecationDetails } from './access_deprecations'; +export { buildApiAccessDeprecationDetails, getIsAccessApiDeprecation } from './access_deprecations'; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/index.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/index.ts index 535401178e4c5..8d823e8ad2118 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/index.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/index.ts @@ -8,4 +8,6 @@ */ export { registerApiDeprecationsInfo } from './register_api_depercation_info'; +export { getIsAccessApiDeprecation } from './access'; +export { getIsRouteApiDeprecation } from './route'; export { buildApiDeprecationId } from './api_deprecation_id'; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts index 535db90577106..f4c9847b09e54 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.ts @@ -38,17 +38,17 @@ export const createGetApiDeprecations = } const { routeAccess } = deprecatedApiDetails; - switch (routeAccess) { - case 'internal': { - return buildApiAccessDeprecationDetails({ + case 'public': { + return buildApiRouteDeprecationDetails({ apiUsageStats, deprecatedApiDetails, }); } - case 'public': + // if no access is specified then internal is the default + case 'internal': default: { - return buildApiRouteDeprecationDetails({ + return buildApiAccessDeprecationDetails({ apiUsageStats, deprecatedApiDetails, }); diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/index.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/index.ts index 2e28928c9c065..9caf06c7def8f 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/index.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/index.ts @@ -7,4 +7,4 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -export { buildApiRouteDeprecationDetails } from './route_deprecations'; +export { buildApiRouteDeprecationDetails, getIsRouteApiDeprecation } from './route_deprecations'; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts index cbddb117c1620..60186c45a3f04 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts @@ -11,12 +11,26 @@ import type { ApiDeprecationDetails, DomainDeprecationDetails, } from '@kbn/core-deprecations-common'; -import type { BuildApiDeprecationDetailsParams } from '../types'; + +import { CoreKibanaRequest } from '@kbn/core-http-router-server-internal'; +import _ from 'lodash'; +import { RouteDeprecationInfo } from '@kbn/core-http-server'; import { getApiDeprecationMessage, getApiDeprecationsManualSteps, getApiDeprecationTitle, } from './i18n_texts'; +import type { BuildApiDeprecationDetailsParams } from '../types'; + +export const getIsRouteApiDeprecation = ( + req: CoreKibanaRequest, + deprecated?: RouteDeprecationInfo +): boolean => { + const hasDeprecatedObject = deprecated && _.isObject(deprecated); + const isNotInternalRequest = !req.isInternalApiRequest; + + return !!(hasDeprecatedObject && isNotInternalRequest); +}; export const buildApiRouteDeprecationDetails = ({ apiUsageStats, diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/index.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/index.ts index aecf3d5b299a2..21e4f801ca987 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/index.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/index.ts @@ -7,5 +7,10 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -export { buildApiDeprecationId, registerApiDeprecationsInfo } from './api_deprecations'; +export { + buildApiDeprecationId, + registerApiDeprecationsInfo, + getIsAccessApiDeprecation, + getIsRouteApiDeprecation, +} from './api_deprecations'; export { registerConfigDeprecationsInfo } from './config_deprecations'; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/routes/get.ts b/packages/core/deprecations/core-deprecations-server-internal/src/routes/get.ts index ed3cd061b633b..42a2af4ff7d1d 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/routes/get.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/routes/get.ts @@ -14,6 +14,9 @@ export const registerGetRoute = (router: InternalDeprecationRouter) => { router.get( { path: '/', + options: { + access: 'public', + }, validate: false, }, async (context, req, res) => { diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts b/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts index 60d42a303d38d..bbcd2216a48e0 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts @@ -10,9 +10,9 @@ import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-server-internal'; import type { CoreKibanaRequest } from '@kbn/core-http-router-server-internal'; import type { InternalHttpServiceSetup } from '@kbn/core-http-server-internal'; -import { isObject } from 'lodash'; -import { RouteDeprecationInfo } from '@kbn/core-http-server/src/router/route'; // shouldn't use deep imports +import { RouteDeprecationInfo } from '@kbn/core-http-server'; import { buildApiDeprecationId } from '../deprecations'; +import { getIsRouteApiDeprecation, getIsAccessApiDeprecation } from '../deprecations'; interface Dependencies { coreUsageData: InternalCoreUsageDataSetup; @@ -36,8 +36,9 @@ export function createRouteDeprecationsHandler({ coreUsageData: InternalCoreUsageDataSetup; }) { return (req: CoreKibanaRequest, { deprecated }: { deprecated?: RouteDeprecationInfo }) => { - const hasRouteDeprecation = deprecated && isObject(deprecated); - const hasAccessDeprecation = req.route.options.access === 'internal'; + const hasRouteDeprecation = getIsRouteApiDeprecation(req, deprecated); + const hasAccessDeprecation = getIsAccessApiDeprecation(req); + const isApiDeprecation = hasAccessDeprecation || hasRouteDeprecation; if (isApiDeprecation && req.route.routePath) { const counterName = buildApiDeprecationId({ diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/routes/resolve_deprecated_api.ts b/packages/core/deprecations/core-deprecations-server-internal/src/routes/resolve_deprecated_api.ts index 840bc5ac22d23..14939188ef0fb 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/routes/resolve_deprecated_api.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/routes/resolve_deprecated_api.ts @@ -19,6 +19,9 @@ export const registerMarkAsResolvedRoute = ( router.post( { path: '/mark_as_resolved', + options: { + access: 'internal', + }, validate: { body: schema.object({ domainId: schema.string(), diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index d54a75b313cd8..7887c7a315bf7 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -9290,6 +9290,18 @@ "_meta": { "description": "How many times a saved object has resolved with any of the four possible outcomes." } + }, + "deprecated_api_calls_resolved.total": { + "type": "integer", + "_meta": { + "description": "How many times deprecated APIs has been marked as resolved" + } + }, + "deprecated_api_calls.total": { + "type": "integer", + "_meta": { + "description": "How many times deprecated APIs has been called." + } } } }, diff --git a/x-pack/plugins/upgrade_assistant/README.md b/x-pack/plugins/upgrade_assistant/README.md index e1cadeb0404f9..0d4f1a74b4f9e 100644 --- a/x-pack/plugins/upgrade_assistant/README.md +++ b/x-pack/plugins/upgrade_assistant/README.md @@ -287,8 +287,7 @@ Run them in the console to trigger the deprecation condition so they show up in ``` # Route deprecations for Versioned routes: Version 1 is deprecated -GET kbn:/api/routing_example/d/versioned?apiVersion=1 -GET kbn:/api/routing_example/d/versioned?apiVersion=2 +GET kbn:/api/routing_example/d/versioned_route?apiVersion=2023-10-31 # Route deprecations for Non-versioned routes GET kbn:/api/routing_example/d/removed_route @@ -299,12 +298,12 @@ POST kbn:/api/routing_example/d/migrated_route # Access deprecations GET kbn:/api/routing_example/d/internal_deprecated_route GET kbn:/internal/routing_example/d/internal_only_route +GET kbn:/internal/routing_example/d/internal_versioned_route?apiVersion=1 ``` 1. You can also mark as deprecated in the UA to remove the deprecation from the list. 2. Check the telemetry response to see the reported data about the deprecated route. -3. Calling version 2 of the API does not do anything since it is not deprecated unlike version `1` (`GET kbn:/api/routing_example/d/versioned?apiVersion=2`) -4. Internally you can see the deprecations counters from the dev console by running the following: +3. Internally you can see the deprecations counters from the dev console by running the following: ``` GET .kibana_usage_counters/_search { diff --git a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/api_deprecations.ts b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/api_deprecations.ts index 3ee458e74a9a0..bbce39e9fb29a 100644 --- a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/api_deprecations.ts +++ b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/api_deprecations.ts @@ -28,7 +28,10 @@ export default function ({ getService }: FtrProviderContext) { const retry = getService('retry'); const es = getService('es'); - describe('Kibana API Deprecations', () => { + describe('Kibana API Deprecations', function () { + // bail on first error in this suite since cases sequentially depend on each other + this.bail(true); + before(async () => { // await kibanaServer.savedObjects.cleanStandardList(); await esArchiver.emptyKibanaIndex(); @@ -40,6 +43,9 @@ export default function ({ getService }: FtrProviderContext) { }); it('returns deprecated APIs when the api is called', async () => { + await supertest + .get(`/internal/routing_example/d/internal_versioned_route?apiVersion=1`) + .expect(200); await supertest.get(`/api/routing_example/d/removed_route`).expect(200); // sleep a little until the usage counter is synced into ES @@ -49,7 +55,7 @@ export default function ({ getService }: FtrProviderContext) { async () => { const { deprecations } = (await supertest.get(`/api/deprecations/`).expect(200)).body; const apiDeprecations = getApiDeprecations(deprecations); - expect(apiDeprecations.length).to.equal(1); + expect(apiDeprecations.length).to.equal(2); expectExpect(apiDeprecations[0].correctiveActions.mark_as_resolved_api).toEqual({ routePath: '/api/routing_example/d/removed_route', @@ -66,6 +72,23 @@ export default function ({ getService }: FtrProviderContext) { expectExpect(apiDeprecations[0].title).toEqual( 'The "GET /api/routing_example/d/removed_route" route is removed' ); + + expectExpect(apiDeprecations[1].correctiveActions.mark_as_resolved_api).toEqual({ + routePath: '/internal/routing_example/d/internal_versioned_route', + routeMethod: 'get', + routeVersion: '1', + apiTotalCalls: 1, + totalMarkedAsResolved: 0, + timestamp: expectExpect.any(String), + }); + + expectExpect(apiDeprecations[1].domainId).toEqual('core.api_deprecations'); + expectExpect(apiDeprecations[1].apiId).toEqual( + '1|get|/internal/routing_example/d/internal_versioned_route' + ); + expectExpect(apiDeprecations[1].title).toEqual( + 'The "GET /internal/routing_example/d/internal_versioned_route" API is internal to Elastic' + ); }, undefined, 2000 @@ -74,7 +97,7 @@ export default function ({ getService }: FtrProviderContext) { it('no longer returns deprecated API when it is marked as resolved', async () => { await supertest - .post(`/api/deprecations/mark_as_resolved`) + .post(`/api/deprecations/mark_as_resolved?elasticInternalOrigin=true`) .set('kbn-xsrf', 'xxx') .send({ domainId: 'core.api_deprecations', @@ -89,7 +112,10 @@ export default function ({ getService }: FtrProviderContext) { await retry.tryForTime(15 * 1000, async () => { const { deprecations } = (await supertest.get(`/api/deprecations/`).expect(200)).body; const apiDeprecations = getApiDeprecations(deprecations); - expect(apiDeprecations.length).to.equal(0); + expect(apiDeprecations.length).to.equal(1); + expectExpect(apiDeprecations[0].apiId).toEqual( + '1|get|/internal/routing_example/d/internal_versioned_route' + ); }); }); @@ -103,7 +129,7 @@ export default function ({ getService }: FtrProviderContext) { async () => { const { deprecations } = (await supertest.get(`/api/deprecations/`).expect(200)).body; const apiDeprecations = getApiDeprecations(deprecations); - expect(apiDeprecations.length).to.equal(1); + expect(apiDeprecations.length).to.equal(2); expectExpect(apiDeprecations[0].correctiveActions.mark_as_resolved_api).toEqual({ routePath: '/api/routing_example/d/removed_route', @@ -130,31 +156,80 @@ export default function ({ getService }: FtrProviderContext) { }, }); - expect(hits.hits.length).to.equal(3); + expect(hits.hits.length).to.equal(4); const counters = hits.hits.map((hit) => hit._source!['usage-counter']).sort(); - expectExpect(_.sortBy(counters, 'counterType')).toEqual([ - { - count: 1, - counterName: 'unversioned|get|/api/routing_example/d/removed_route', - counterType: 'deprecated_api_call:marked_as_resolved', - domainId: 'core', - source: 'server', - }, - { - count: 1, - counterName: 'unversioned|get|/api/routing_example/d/removed_route', - counterType: 'deprecated_api_call:resolved', - domainId: 'core', - source: 'server', - }, - { - count: 2, - counterName: 'unversioned|get|/api/routing_example/d/removed_route', - counterType: 'deprecated_api_call:total', - domainId: 'core', - source: 'server', - }, - ]); + expectExpect(_.sortBy(counters, 'counterType')).toEqual(expectedSuiteUsageCounters); + }); + + it('Does not increment internal origin calls', async () => { + await supertest + .get(`/api/routing_example/d/removed_route?elasticInternalOrigin=true`) + .expect(200); + // call another deprecated api to make sure that we are not verifying stale results + await supertest + .get(`/api/routing_example/d/versioned_route?apiVersion=2023-10-31`) + .expect(200); + + // sleep a little until the usage counter is synced into ES + await setTimeoutAsync(3000); + await retry.tryForTime(15 * 1000, async () => { + const should = ['total', 'resolved', 'marked_as_resolved'].map((type) => ({ + match: { 'usage-counter.counterType': `deprecated_api_call:${type}` }, + })); + + const { hits } = await es.search<{ 'usage-counter': UsageCountersSavedObject }>({ + index: '.kibana_usage_counters', + body: { + query: { bool: { should } }, + }, + }); + + expect(hits.hits.length).to.equal(5); + const counters = hits.hits.map((hit) => hit._source!['usage-counter']).sort(); + expectExpect(_.sortBy(counters, 'counterType')).toEqual( + [ + ...expectedSuiteUsageCounters, + { + domainId: 'core', + counterName: '2023-10-31|get|/api/routing_example/d/versioned_route', + counterType: 'deprecated_api_call:total', + source: 'server', + count: 1, + }, + ].sort() + ); + }); }); }); } + +const expectedSuiteUsageCounters = [ + { + domainId: 'core', + counterName: 'unversioned|get|/api/routing_example/d/removed_route', + counterType: 'deprecated_api_call:marked_as_resolved', + source: 'server', + count: 1, + }, + { + domainId: 'core', + counterName: 'unversioned|get|/api/routing_example/d/removed_route', + counterType: 'deprecated_api_call:resolved', + source: 'server', + count: 1, + }, + { + domainId: 'core', + counterName: '1|get|/internal/routing_example/d/internal_versioned_route', + counterType: 'deprecated_api_call:total', + source: 'server', + count: 1, + }, + { + domainId: 'core', + counterName: 'unversioned|get|/api/routing_example/d/removed_route', + counterType: 'deprecated_api_call:total', + source: 'server', + count: 2, + }, +]; From 003a5b1ef4c31f68b23f94354ee36e1b5225b14a Mon Sep 17 00:00:00 2001 From: Bamieh Date: Sun, 10 Nov 2024 21:29:29 +0100 Subject: [PATCH 05/11] update metadata post validation param --- .../access/access_deprecations.ts | 12 ++++++---- .../route/route_deprecations.ts | 14 +++++------ .../src/routes/post_validation_handler.ts | 8 +++---- .../src/router.ts | 23 ++++++++++++++----- .../versioned_router/core_versioned_route.ts | 12 ++++++++-- .../core-http-server-internal/src/types.ts | 6 ++--- packages/core/http/core-http-server/index.ts | 1 + .../http/core-http-server/src/router/index.ts | 1 + .../http/core-http-server/src/router/route.ts | 9 ++++++++ .../src/core_usage_stats.ts | 3 +++ .../collectors/core/core_usage_collector.ts | 12 ++++++++++ src/plugins/telemetry/schema/oss_plugins.json | 12 +++++----- 12 files changed, 80 insertions(+), 33 deletions(-) diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/access_deprecations.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/access_deprecations.ts index bc9b35f235472..2a0c2a8cae5ff 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/access_deprecations.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/access/access_deprecations.ts @@ -11,7 +11,8 @@ import type { ApiDeprecationDetails, DomainDeprecationDetails, } from '@kbn/core-deprecations-common'; -import { CoreKibanaRequest } from '@kbn/core-http-router-server-internal'; + +import type { PostValidationMetadata } from '@kbn/core-http-server'; import type { BuildApiDeprecationDetailsParams } from '../types'; import { getApiDeprecationMessage, @@ -19,9 +20,12 @@ import { getApiDeprecationTitle, } from './i18n_texts'; -export const getIsAccessApiDeprecation = (req: CoreKibanaRequest): boolean => { - const isNotPublicAccess = req.route.options.access !== 'public'; - const isNotInternalRequest = !req.isInternalApiRequest; +export const getIsAccessApiDeprecation = ({ + isInternalApiRequest, + isPublicAccess, +}: PostValidationMetadata): boolean => { + const isNotPublicAccess = !isPublicAccess; + const isNotInternalRequest = !isInternalApiRequest; return !!(isNotPublicAccess && isNotInternalRequest); }; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts index 60186c45a3f04..ba38fdbcac1b0 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts @@ -11,10 +11,8 @@ import type { ApiDeprecationDetails, DomainDeprecationDetails, } from '@kbn/core-deprecations-common'; - -import { CoreKibanaRequest } from '@kbn/core-http-router-server-internal'; import _ from 'lodash'; -import { RouteDeprecationInfo } from '@kbn/core-http-server'; +import { PostValidationMetadata } from '@kbn/core-http-server'; import { getApiDeprecationMessage, getApiDeprecationsManualSteps, @@ -22,12 +20,12 @@ import { } from './i18n_texts'; import type { BuildApiDeprecationDetailsParams } from '../types'; -export const getIsRouteApiDeprecation = ( - req: CoreKibanaRequest, - deprecated?: RouteDeprecationInfo -): boolean => { +export const getIsRouteApiDeprecation = ({ + isInternalApiRequest, + deprecated, +}: PostValidationMetadata): boolean => { const hasDeprecatedObject = deprecated && _.isObject(deprecated); - const isNotInternalRequest = !req.isInternalApiRequest; + const isNotInternalRequest = !isInternalApiRequest; return !!(hasDeprecatedObject && isNotInternalRequest); }; diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts b/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts index bbcd2216a48e0..95cf1d7c7181a 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts @@ -10,7 +10,7 @@ import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-server-internal'; import type { CoreKibanaRequest } from '@kbn/core-http-router-server-internal'; import type { InternalHttpServiceSetup } from '@kbn/core-http-server-internal'; -import { RouteDeprecationInfo } from '@kbn/core-http-server'; +import type { PostValidationMetadata } from '@kbn/core-http-server'; import { buildApiDeprecationId } from '../deprecations'; import { getIsRouteApiDeprecation, getIsAccessApiDeprecation } from '../deprecations'; @@ -35,9 +35,9 @@ export function createRouteDeprecationsHandler({ }: { coreUsageData: InternalCoreUsageDataSetup; }) { - return (req: CoreKibanaRequest, { deprecated }: { deprecated?: RouteDeprecationInfo }) => { - const hasRouteDeprecation = getIsRouteApiDeprecation(req, deprecated); - const hasAccessDeprecation = getIsAccessApiDeprecation(req); + return (req: CoreKibanaRequest, metadata: PostValidationMetadata) => { + const hasRouteDeprecation = getIsRouteApiDeprecation(metadata); + const hasAccessDeprecation = getIsAccessApiDeprecation(metadata); const isApiDeprecation = hasAccessDeprecation || hasRouteDeprecation; if (isApiDeprecation && req.route.routePath) { diff --git a/packages/core/http/core-http-router-server-internal/src/router.ts b/packages/core/http/core-http-router-server-internal/src/router.ts index e7ad85fcda33a..8880e7f1b61d5 100644 --- a/packages/core/http/core-http-router-server-internal/src/router.ts +++ b/packages/core/http/core-http-router-server-internal/src/router.ts @@ -33,7 +33,7 @@ import { isZod } from '@kbn/zod'; import { validBodyOutput, getRequestValidation } from '@kbn/core-http-server'; import type { RouteSecurityGetter } from '@kbn/core-http-server'; import type { DeepPartial } from '@kbn/utility-types'; -import { RouteDeprecationInfo } from '@kbn/core-http-server/src/router/route'; +import type { PostValidationMetadata } from '@kbn/core-http-server-internal'; import { RouteValidator } from './validator'; import { ALLOWED_PUBLIC_VERSION, CoreVersionedRouter } from './versioned_router'; import { CoreKibanaRequest } from './request'; @@ -287,10 +287,13 @@ export class Router { const postValidate: RouterEvents = 'onPostValidate'; - Router.ee.emit(postValidate, request, routeOptions); + Router.ee.emit(postValidate, request, postValidateConext); }; private async handle({ @@ -304,7 +307,7 @@ export class Router void; + onPostValidation: (req: KibanaRequest, metadata: PostValidationMetadata) => void; }; isPublicUnversionedRoute: boolean; handler: RequestHandlerEnhanced< @@ -337,11 +340,19 @@ export class Router IRouter; registerOnPostValidation( - cb: (req: CoreKibanaRequest, metadata: { deprecated: RouteDeprecationInfo }) => void + cb: (req: CoreKibanaRequest, metadata: PostValidationMetadata) => void ): void; registerRouterAfterListening: (router: IRouter) => void; registerStaticDir: (path: string, dirPath: string) => void; diff --git a/packages/core/http/core-http-server/index.ts b/packages/core/http/core-http-server/index.ts index af3c566f6a8d2..7b79dfe313bd6 100644 --- a/packages/core/http/core-http-server/index.ts +++ b/packages/core/http/core-http-server/index.ts @@ -123,6 +123,7 @@ export type { RouteSecurityGetter, InternalRouteSecurity, RouteDeprecationInfo, + PostValidationMetadata, } from './src/router'; export { validBodyOutput, diff --git a/packages/core/http/core-http-server/src/router/index.ts b/packages/core/http/core-http-server/src/router/index.ts index 2c7a83469ebb1..166fcad324953 100644 --- a/packages/core/http/core-http-server/src/router/index.ts +++ b/packages/core/http/core-http-server/src/router/index.ts @@ -65,6 +65,7 @@ export type { Privilege, PrivilegeSet, RouteDeprecationInfo, + PostValidationMetadata, } from './route'; export { validBodyOutput, ReservedPrivilegesSet } from './route'; diff --git a/packages/core/http/core-http-server/src/router/route.ts b/packages/core/http/core-http-server/src/router/route.ts index eec9a01f60562..da24adcb6802e 100644 --- a/packages/core/http/core-http-server/src/router/route.ts +++ b/packages/core/http/core-http-server/src/router/route.ts @@ -525,3 +525,12 @@ export interface RouteConfig { */ options?: RouteConfigOptions; } + +/** + * Post Validation Route emitter metadata. + */ +export interface PostValidationMetadata { + deprecated?: RouteDeprecationInfo; + isInternalApiRequest: boolean; + isPublicAccess: boolean; +} diff --git a/packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts b/packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts index 39df9d30d19c9..e713e3e905a47 100644 --- a/packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts +++ b/packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts @@ -145,6 +145,9 @@ export interface CoreUsageStats { 'savedObjectsRepository.resolvedOutcome.conflict'?: number; 'savedObjectsRepository.resolvedOutcome.notFound'?: number; 'savedObjectsRepository.resolvedOutcome.total'?: number; + // API Deprecations counters + 'deprecated_api_calls_resolved.total'?: number; + 'deprecated_api_calls.total'?: number; } /** diff --git a/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts index b969215f508df..41e7bf9fd7402 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts @@ -1183,6 +1183,18 @@ export function getCoreUsageCollector( 'How many times a saved object has resolved with any of the four possible outcomes.', }, }, + 'deprecated_api_calls_resolved.total': { + type: 'integer', + _meta: { + description: 'How many times deprecated APIs has been marked as resolved', + }, + }, + 'deprecated_api_calls.total': { + type: 'integer', + _meta: { + description: 'How many times deprecated APIs has been called.', + }, + }, }, fetch() { return getCoreUsageDataService().getCoreUsageData(); diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 7887c7a315bf7..60a4978c4cdfe 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -10905,12 +10905,6 @@ "description": "Non-default value of setting." } }, - "observability:newLogsOverview": { - "type": "boolean", - "_meta": { - "description": "Enable the new logs overview component." - } - }, "observability:searchExcludedDataTiers": { "type": "array", "items": { @@ -10919,6 +10913,12 @@ "description": "Non-default value of setting." } } + }, + "observability:newLogsOverview": { + "type": "boolean", + "_meta": { + "description": "Enable the new logs overview component." + } } } }, From 8adf24771cd33f79b35350f0b5978268256c6286 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Sun, 10 Nov 2024 20:39:04 +0000 Subject: [PATCH 06/11] [CI] Auto-commit changed files from 'node scripts/notice' --- .../core/http/core-http-router-server-internal/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/http/core-http-router-server-internal/tsconfig.json b/packages/core/http/core-http-router-server-internal/tsconfig.json index 5224fd5db16b5..be5f5a7dc7464 100644 --- a/packages/core/http/core-http-router-server-internal/tsconfig.json +++ b/packages/core/http/core-http-router-server-internal/tsconfig.json @@ -19,7 +19,8 @@ "@kbn/core-logging-server-mocks", "@kbn/logging", "@kbn/core-http-common", - "@kbn/logging-mocks" + "@kbn/logging-mocks", + "@kbn/core-http-server-internal" ], "exclude": [ "target/**/*", From 2161b63488020af13e72bba00803f5f016a6e873 Mon Sep 17 00:00:00 2001 From: Bamieh Date: Sun, 10 Nov 2024 21:43:59 +0100 Subject: [PATCH 07/11] import type --- .../deprecations/api_deprecations/route/route_deprecations.ts | 2 +- .../core/http/core-http-router-server-internal/src/router.ts | 2 +- .../src/versioned_router/core_versioned_route.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts index ba38fdbcac1b0..6f9bab78dff9f 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/route/route_deprecations.ts @@ -12,7 +12,7 @@ import type { DomainDeprecationDetails, } from '@kbn/core-deprecations-common'; import _ from 'lodash'; -import { PostValidationMetadata } from '@kbn/core-http-server'; +import type { PostValidationMetadata } from '@kbn/core-http-server'; import { getApiDeprecationMessage, getApiDeprecationsManualSteps, diff --git a/packages/core/http/core-http-router-server-internal/src/router.ts b/packages/core/http/core-http-router-server-internal/src/router.ts index 8880e7f1b61d5..203f7c5ef6d11 100644 --- a/packages/core/http/core-http-router-server-internal/src/router.ts +++ b/packages/core/http/core-http-router-server-internal/src/router.ts @@ -28,12 +28,12 @@ import type { VersionedRouter, RouteRegistrar, RouteSecurity, + PostValidationMetadata, } from '@kbn/core-http-server'; import { isZod } from '@kbn/zod'; import { validBodyOutput, getRequestValidation } from '@kbn/core-http-server'; import type { RouteSecurityGetter } from '@kbn/core-http-server'; import type { DeepPartial } from '@kbn/utility-types'; -import type { PostValidationMetadata } from '@kbn/core-http-server-internal'; import { RouteValidator } from './validator'; import { ALLOWED_PUBLIC_VERSION, CoreVersionedRouter } from './versioned_router'; import { CoreKibanaRequest } from './request'; diff --git a/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.ts b/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.ts index 22cccb8d3905a..fa6a31011b0cd 100644 --- a/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.ts +++ b/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.ts @@ -26,9 +26,9 @@ import type { RouteSecurity, RouteMethod, VersionedRouterRoute, + PostValidationMetadata, } from '@kbn/core-http-server'; import type { Mutable } from 'utility-types'; -import { PostValidationMetadata } from '@kbn/core-http-server-internal'; import type { HandlerResolutionStrategy, Method, Options } from './types'; import { validate } from './validate'; From d2287ac02015ed7ccf8c946536cd62339438041d Mon Sep 17 00:00:00 2001 From: Bamieh Date: Sun, 10 Nov 2024 21:45:43 +0100 Subject: [PATCH 08/11] pull branch --- .../core/http/core-http-router-server-internal/tsconfig.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/core/http/core-http-router-server-internal/tsconfig.json b/packages/core/http/core-http-router-server-internal/tsconfig.json index be5f5a7dc7464..5224fd5db16b5 100644 --- a/packages/core/http/core-http-router-server-internal/tsconfig.json +++ b/packages/core/http/core-http-router-server-internal/tsconfig.json @@ -19,8 +19,7 @@ "@kbn/core-logging-server-mocks", "@kbn/logging", "@kbn/core-http-common", - "@kbn/logging-mocks", - "@kbn/core-http-server-internal" + "@kbn/logging-mocks" ], "exclude": [ "target/**/*", From 457732b858291b05d14e23bc5f826f444a539285 Mon Sep 17 00:00:00 2001 From: Bamieh Date: Mon, 11 Nov 2024 00:13:03 +0100 Subject: [PATCH 09/11] fix tests --- .../api_deprecations/register_api_depercation_info.test.ts | 1 + .../src/deprecations_service.test.ts | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.test.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.test.ts index 77d6f089ffb40..9a7842d8915db 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.test.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations/api_deprecations/register_api_depercation_info.test.ts @@ -62,6 +62,7 @@ describe('#registerApiDeprecationsInfo', () => { ): RouterDeprecatedApiDetails => _.merge( { + routeAccess: 'public', routeDeprecationOptions: { documentationUrl: 'https://fake-url', severity: 'critical', diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations_service.test.ts b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations_service.test.ts index 39c299d980531..0ea283b6eb5d6 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/deprecations_service.test.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/deprecations_service.test.ts @@ -52,7 +52,10 @@ describe('DeprecationsService', () => { expect(http.createRouter).toBeCalledWith('/api/deprecations'); // registers get route '/' expect(router.get).toHaveBeenCalledTimes(1); - expect(router.get).toHaveBeenCalledWith({ path: '/', validate: false }, expect.any(Function)); + expect(router.get).toHaveBeenCalledWith( + { options: { access: 'public' }, path: '/', validate: false }, + expect.any(Function) + ); }); it('calls registerConfigDeprecationsInfo', async () => { From 119d6893cda279fe11b0b60d0dd2912172b88067 Mon Sep 17 00:00:00 2001 From: Bamieh Date: Mon, 11 Nov 2024 04:00:12 +0100 Subject: [PATCH 10/11] add elasticInternalOrigin=false tests and update readme --- .../src/routes/post_validation_handler.ts | 1 - .../src/request.ts | 9 +++++-- .../src/router.ts | 4 +-- .../src/lifecycle_handlers.test.ts | 27 +++++++++++++++++++ x-pack/plugins/upgrade_assistant/README.md | 17 ++++++------ 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts b/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts index 95cf1d7c7181a..20f680d4c313d 100644 --- a/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts +++ b/packages/core/deprecations/core-deprecations-server-internal/src/routes/post_validation_handler.ts @@ -38,7 +38,6 @@ export function createRouteDeprecationsHandler({ return (req: CoreKibanaRequest, metadata: PostValidationMetadata) => { const hasRouteDeprecation = getIsRouteApiDeprecation(metadata); const hasAccessDeprecation = getIsAccessApiDeprecation(metadata); - const isApiDeprecation = hasAccessDeprecation || hasRouteDeprecation; if (isApiDeprecation && req.route.routePath) { const counterName = buildApiDeprecationId({ diff --git a/packages/core/http/core-http-router-server-internal/src/request.ts b/packages/core/http/core-http-router-server-internal/src/request.ts index 9f89f1a70bb47..cbccf31fc0946 100644 --- a/packages/core/http/core-http-router-server-internal/src/request.ts +++ b/packages/core/http/core-http-router-server-internal/src/request.ts @@ -177,9 +177,14 @@ export class CoreKibanaRequest< this.headers = isRealReq ? deepFreeze({ ...request.headers }) : request.headers; this.isSystemRequest = this.headers['kbn-system-request'] === 'true'; this.isFakeRequest = !isRealReq; + // set to false if elasticInternalOrigin is explicitly set to false + // otherwise check for the header or the query param this.isInternalApiRequest = - X_ELASTIC_INTERNAL_ORIGIN_REQUEST in this.headers || - Boolean(this.url?.searchParams?.has(ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM)); + this.url?.searchParams?.get(ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM) === 'false' + ? false + : X_ELASTIC_INTERNAL_ORIGIN_REQUEST in this.headers || + this.url?.searchParams?.has(ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM); + // prevent Symbol exposure via Object.getOwnPropertySymbols() Object.defineProperty(this, requestSymbol, { value: request, diff --git a/packages/core/http/core-http-router-server-internal/src/router.ts b/packages/core/http/core-http-router-server-internal/src/router.ts index 203f7c5ef6d11..c2ea09605c4e0 100644 --- a/packages/core/http/core-http-router-server-internal/src/router.ts +++ b/packages/core/http/core-http-router-server-internal/src/router.ts @@ -343,7 +343,7 @@ export class Router { const request = createForgeRequest('public', { 'x-elastic-internal-origin': 'Kibana' }); createForwardSuccess(handler, request); }); + + it('overrides internal api when elasticInternalOrigin=false is set explicitly', () => { + const handler = createRestrictInternalRoutesPostAuthHandler( + { ...config, restrictInternalApis: true }, + logger + ); + + // Will be treated as external + const request = createForgeRequest( + 'internal', + { 'x-elastic-internal-origin': 'Kibana' }, + { elasticInternalOrigin: 'false' } + ); + + responseFactory.badRequest.mockReturnValue('badRequest' as any); + + const result = handler(request, responseFactory, toolkit); + + expect(toolkit.next).not.toHaveBeenCalled(); + expect(responseFactory.badRequest).toHaveBeenCalledTimes(1); + expect(responseFactory.badRequest.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "body": "uri [/internal/some-path] with method [get] exists but is not available with the current configuration", + } + `); + expect(result).toEqual('badRequest'); + }); }); describe('customHeaders pre-response handler', () => { diff --git a/x-pack/plugins/upgrade_assistant/README.md b/x-pack/plugins/upgrade_assistant/README.md index 0d4f1a74b4f9e..d81e90e75b163 100644 --- a/x-pack/plugins/upgrade_assistant/README.md +++ b/x-pack/plugins/upgrade_assistant/README.md @@ -284,21 +284,22 @@ yarn start --plugin-path=examples/routing_example --plugin-path=examples/develop The following comprehensive deprecated routes examples are registered inside the folder: `examples/routing_example/server/routes/deprecated_routes` Run them in the console to trigger the deprecation condition so they show up in the UA: +We need to explicitly set the query param `elasticInternalOrigin` to `false` to track the request as non-internal origin. ``` # Route deprecations for Versioned routes: Version 1 is deprecated -GET kbn:/api/routing_example/d/versioned_route?apiVersion=2023-10-31 +GET kbn:/api/routing_example/d/versioned_route?apiVersion=2023-10-31&elasticInternalOrigin=false -# Route deprecations for Non-versioned routes -GET kbn:/api/routing_example/d/removed_route -GET kbn:/api/routing_example/d/deprecated_route -POST kbn:/api/routing_example/d/migrated_route +# Route deprecations for Non-versioned routes?elasticInternalOrigin=false +GET kbn:/api/routing_example/d/removed_route?elasticInternalOrigin=false +GET kbn:/api/routing_example/d/deprecated_route?elasticInternalOrigin=false +POST kbn:/api/routing_example/d/migrated_route?elasticInternalOrigin=false {} # Access deprecations -GET kbn:/api/routing_example/d/internal_deprecated_route -GET kbn:/internal/routing_example/d/internal_only_route -GET kbn:/internal/routing_example/d/internal_versioned_route?apiVersion=1 +GET kbn:/api/routing_example/d/internal_deprecated_route?elasticInternalOrigin=false +GET kbn:/internal/routing_example/d/internal_only_route?elasticInternalOrigin=false +GET kbn:/internal/routing_example/d/internal_versioned_route?apiVersion=1&elasticInternalOrigin=false ``` 1. You can also mark as deprecated in the UA to remove the deprecation from the list. From 07262b9852fe33af72a02801c465b7daff562532 Mon Sep 17 00:00:00 2001 From: Bamieh Date: Mon, 11 Nov 2024 04:17:17 +0100 Subject: [PATCH 11/11] update readme --- x-pack/plugins/upgrade_assistant/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/README.md b/x-pack/plugins/upgrade_assistant/README.md index d81e90e75b163..531d4c1702c04 100644 --- a/x-pack/plugins/upgrade_assistant/README.md +++ b/x-pack/plugins/upgrade_assistant/README.md @@ -287,10 +287,10 @@ Run them in the console to trigger the deprecation condition so they show up in We need to explicitly set the query param `elasticInternalOrigin` to `false` to track the request as non-internal origin. ``` -# Route deprecations for Versioned routes: Version 1 is deprecated +# Route deprecations for Versioned routes GET kbn:/api/routing_example/d/versioned_route?apiVersion=2023-10-31&elasticInternalOrigin=false -# Route deprecations for Non-versioned routes?elasticInternalOrigin=false +# Route deprecations for Non-versioned routes GET kbn:/api/routing_example/d/removed_route?elasticInternalOrigin=false GET kbn:/api/routing_example/d/deprecated_route?elasticInternalOrigin=false POST kbn:/api/routing_example/d/migrated_route?elasticInternalOrigin=false