Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Api Deprecations #193668

Closed
wants to merge 13 commits into from
16 changes: 14 additions & 2 deletions packages/core/deprecations/core-deprecations-common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export interface BaseDeprecationDetails {
* Predefined types are necessary to reduce having similar definitions with different keywords
* across kibana deprecations.
*/
deprecationType?: 'config' | 'feature';
deprecationType?: 'config' | 'feature' | 'api';
/** (optional) link to the documentation for more details on the deprecation. */
documentationUrl?: string;
/** (optional) specify the fix for this deprecation requires a full kibana restart. */
Expand Down Expand Up @@ -91,7 +91,19 @@ export interface FeatureDeprecationDetails extends BaseDeprecationDetails {
/**
* @public
*/
export type DeprecationsDetails = ConfigDeprecationDetails | FeatureDeprecationDetails;
export interface ApiDeprecationDetails extends BaseDeprecationDetails {
routePath: string;
routeMethod: string;
deprecationType: 'api';
}

/**
* @public
*/
export type DeprecationsDetails =
| ConfigDeprecationDetails
| FeatureDeprecationDetails
| ApiDeprecationDetails;

/**
* @public
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,90 @@
# @kbn/core-deprecations-server-internal

This package contains the internal types and implementation of Core's server-side `deprecations` service.


/** Router:
* register Usage counters side core setup
* DOMIANID: CORE.ROUTER
* At router definition
* Call deprecations.registerDeprecation
* - group all renamed etc

* GroupId: Method / path
* when route is called
if deprecation is triggered based on rename/ path/ remove
- increment counter: GroupId, domainId, type: 'count'


set: ['body.a'],
unset: ['body.a'],

{
"deprecations": [
{
"configPath": "xpack.reporting.roles.enabled",
"title": "The \"xpack.reporting.roles\" setting is deprecated",
"level": "warning",
"message": "The default mechanism for Reporting privileges will work differently in future versions, which will affect the behavior of this cluster. Set \"xpack.reporting.roles.enabled\" to \"false\" to adopt the future behavior before upgrading.",
"correctiveActions": {
"manualSteps": [
"Set \"xpack.reporting.roles.enabled\" to \"false\" in kibana.yml.",
"Remove \"xpack.reporting.roles.allow\" in kibana.yml, if present.",
"Go to Management > Security > Roles to create one or more roles that grant the Kibana application privilege for Reporting.",
"Grant Reporting privileges to users by assigning one of the new roles."
],
api: {
path: 'some-path',
method: 'POST',
body: {
extra_param: 123,
},
},
},
"deprecationType": "config",
"requireRestart": true,
"domainId": "xpack.reporting"
}
]
}


domainId: 'routesDeprecations'
counterName: '{RouteAPIGroupingID}',
counterType: 'count',

RouteAPIGroupingID
If Route level: method, route

For fixed:
counterType: 'count:fixed',

We count all deprecations

{
'RouteAPIGroupingID': {
message: '',
deprecationDetails
}
}


Approach 1:
In memory:
1. Store in memory the deprecation details defined at routes setup

3. enrich some text (last called etc) filter out diff 0
4. send result

SO and get rid of Usage counter

interface UsageCountersParams {
/** The domainId used to create the Counter API */
domainId: string;
/** The name of the counter. Optional, will return all counters in the same domainId that match the rest of filters if omitted */
counterName?: string;
/** The 2. on UA api call we do matching between usage counters and the deprecation details in memorytype of counter. Optional, will return all counters in the same domainId that match the rest of filters if omitted */
counterType?: string;
/** Namespace of the counter. Optional, counters of the 'default' namespace will be returned if omitted */
namespace?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ export class DeprecationsFactory {
})
);

return deprecationsInfo.flat();
return [
...deprecationsInfo.flat(),
// ...apiDeprecations,
];
};

private createDeprecationInfo = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@ import type {
DeprecationRegistryProvider,
DeprecationsClient,
} from '@kbn/core-deprecations-server';
import { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal';
import { DeprecationsFactory } from './deprecations_factory';
import { registerRoutes } from './routes';
import { config as deprecationConfig, DeprecationConfigType } from './deprecation_config';
import {
registerApiDeprecationsInfo,
registerConfigDeprecationsInfo,
} from './register_core_deprecations';

export interface InternalDeprecationsServiceStart {
/**
Expand All @@ -40,6 +45,7 @@ export type InternalDeprecationsServiceSetup = DeprecationRegistryProvider;
/** @internal */
export interface DeprecationsSetupDeps {
http: InternalHttpServiceSetup;
coreUsageData: InternalCoreUsageDataSetup;
}

/** @internal */
Expand All @@ -55,7 +61,10 @@ export class DeprecationsService
this.configService = coreContext.configService;
}

public async setup({ http }: DeprecationsSetupDeps): Promise<InternalDeprecationsServiceSetup> {
public async setup({
http,
coreUsageData,
}: DeprecationsSetupDeps): Promise<InternalDeprecationsServiceSetup> {
this.logger.debug('Setting up Deprecations service');

const config = await firstValueFrom(
Expand All @@ -70,7 +79,18 @@ export class DeprecationsService
});

registerRoutes({ http });
this.registerConfigDeprecationsInfo(this.deprecationsFactory);

registerConfigDeprecationsInfo({
deprecationsFactory: this.deprecationsFactory,
configService: this.configService,
});

registerApiDeprecationsInfo({
deprecationsFactory: this.deprecationsFactory,
logger: this.logger,
http,
coreUsageData,
});

const deprecationsFactory = this.deprecationsFactory;
return {
Expand All @@ -87,6 +107,7 @@ export class DeprecationsService
if (!this.deprecationsFactory) {
throw new Error('`setup` must be called before `start`');
}

return {
asScopedToClient: this.createScopedDeprecations(),
};
Expand All @@ -107,35 +128,4 @@ export class DeprecationsService
};
};
}

private registerConfigDeprecationsInfo(deprecationsFactory: DeprecationsFactory) {
const handledDeprecatedConfigs = this.configService.getHandledDeprecatedConfigs();

for (const [domainId, deprecationsContexts] of handledDeprecatedConfigs) {
const deprecationsRegistry = deprecationsFactory.getRegistry(domainId);
deprecationsRegistry.registerDeprecations({
getDeprecations: () => {
return deprecationsContexts.map(
({
configPath,
title = `${domainId} has a deprecated setting`,
level,
message,
correctiveActions,
documentationUrl,
}) => ({
configPath,
title,
level,
message,
correctiveActions,
documentationUrl,
deprecationType: 'config',
requireRestart: true,
})
);
},
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* 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 { IConfigService } from '@kbn/config';
import type { Logger } from '@kbn/logging';
import { InternalHttpServiceSetup } from '@kbn/core-http-server-internal';
import { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal';
import { DeprecationsFactory } from './deprecations_factory';

interface RegisterConfigDeprecationsInfo {
deprecationsFactory: DeprecationsFactory;
configService: IConfigService;
}

export const registerConfigDeprecationsInfo = ({
deprecationsFactory,
configService,
}: RegisterConfigDeprecationsInfo) => {
const handledDeprecatedConfigs = configService.getHandledDeprecatedConfigs();

for (const [domainId, deprecationsContexts] of handledDeprecatedConfigs) {
const deprecationsRegistry = deprecationsFactory.getRegistry(domainId);
deprecationsRegistry.registerDeprecations({
getDeprecations: () => {
return deprecationsContexts.map(
({
configPath,
title = `${domainId} has a deprecated setting`,
level,
message,
correctiveActions,
documentationUrl,
}) => ({
configPath,
title,
level,
message,
correctiveActions,
documentationUrl,
deprecationType: 'config',
requireRestart: true,
})
);
},
});
}
};

export interface ApiDeprecationsServiceDeps {
logger: Logger;
deprecationsFactory: DeprecationsFactory;
http: InternalHttpServiceSetup;
coreUsageData: InternalCoreUsageDataSetup;
}

export const registerApiDeprecationsInfo = ({
deprecationsFactory,
http,
coreUsageData,
}: ApiDeprecationsServiceDeps): void => {
const deprecationsRegistery = deprecationsFactory.getRegistry('core.api_deprecations');

deprecationsRegistery.registerDeprecations({
getDeprecations: async () => {
console.log('calling get!!');

const usageClient = coreUsageData.getClient();
const deprecatedRoutes = http.getDeprecatedRoutes();
const deprecatedStats = await usageClient.getDeprecatedApisStats();

console.log('deprecatedRoutes::', deprecatedRoutes);
console.log('deprecatedStats::', deprecatedStats);

// Do the matching here
// Do the diff here
// write the messages here

return [
{
routePath: '/api/chocolate_love',
routeMethod: 'GET',
title: `The Route "[GET] /api/chocolate_love" has deprected params`,
level: 'warning',
message: `Deprecated route [GET] /api/chocolate_love was called 34 times with deprecated params.\n
The last time the deprecation was triggered was on Fri Sep 20 2024 14:28:22.\n
This deprecation was previously marked as resolved but was called 3 times since it was marked on Fri Sep 13 2024 10:28:22.`,
documentationUrl: 'https://google.com',
correctiveActions: {
manualSteps: [
'The following query params are deprecated: dont_use,my_old_query_param',
'Make sure you are not using any of these parameters when calling the API',
],
api: {
path: 'some-path',
method: 'POST',
body: {
extra_param: 123,
},
},
},
deprecationType: 'api',
requireRestart: false,
domainId: 'core.router',
},
];
},
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ export const registerGetRoute = (router: InternalDeprecationRouter) => {
{
path: '/',
validate: false,
options: {
deprecated: {
guideLink: 'https://google.com',
severity: 'warning',
reason: {
type: 'migrated-api',
apiMethod: 'GET',
apiPath: '/api/core/deprecations',
},
},
},
},
async (context, req, res) => {
const deprecationsClient = (await context.core).deprecations.client;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ export class CoreKibanaRequest<
xsrfRequired:
((request.route?.settings as RouteOptions)?.app as KibanaRouteOptions)?.xsrfRequired ??
true, // some places in LP call KibanaRequest.from(request) manually. remove fallback to true before v8
deprecated: ((request.route?.settings as RouteOptions)?.app as KibanaRouteOptions)
?.deprecated,
access: this.getAccess(request),
tags: request.route?.settings?.tags || [],
timeout: {
Expand Down
Loading