mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Core] create deprecations service (#94845)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
ceb4c9a160
commit
a67aa97989
102 changed files with 3263 additions and 348 deletions
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [CoreStart](./kibana-plugin-core-public.corestart.md) > [deprecations](./kibana-plugin-core-public.corestart.deprecations.md)
|
||||
|
||||
## CoreStart.deprecations property
|
||||
|
||||
[DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md)
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
deprecations: DeprecationsServiceStart;
|
||||
```
|
|
@ -18,6 +18,7 @@ export interface CoreStart
|
|||
| --- | --- | --- |
|
||||
| [application](./kibana-plugin-core-public.corestart.application.md) | <code>ApplicationStart</code> | [ApplicationStart](./kibana-plugin-core-public.applicationstart.md) |
|
||||
| [chrome](./kibana-plugin-core-public.corestart.chrome.md) | <code>ChromeStart</code> | [ChromeStart](./kibana-plugin-core-public.chromestart.md) |
|
||||
| [deprecations](./kibana-plugin-core-public.corestart.deprecations.md) | <code>DeprecationsServiceStart</code> | [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) |
|
||||
| [docLinks](./kibana-plugin-core-public.corestart.doclinks.md) | <code>DocLinksStart</code> | [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) |
|
||||
| [fatalErrors](./kibana-plugin-core-public.corestart.fatalerrors.md) | <code>FatalErrorsStart</code> | [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) |
|
||||
| [http](./kibana-plugin-core-public.corestart.http.md) | <code>HttpStart</code> | [HttpStart](./kibana-plugin-core-public.httpstart.md) |
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) > [getAllDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getalldeprecations.md)
|
||||
|
||||
## DeprecationsServiceStart.getAllDeprecations property
|
||||
|
||||
Grabs deprecations details for all domains.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getAllDeprecations: () => Promise<DomainDeprecationDetails[]>;
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) > [getDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getdeprecations.md)
|
||||
|
||||
## DeprecationsServiceStart.getDeprecations property
|
||||
|
||||
Grabs deprecations for a specific domain.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getDeprecations: (domainId: string) => Promise<DomainDeprecationDetails[]>;
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) > [isDeprecationResolvable](./kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md)
|
||||
|
||||
## DeprecationsServiceStart.isDeprecationResolvable property
|
||||
|
||||
Returns a boolean if the provided deprecation can be automatically resolvable.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
isDeprecationResolvable: (details: DomainDeprecationDetails) => boolean;
|
||||
```
|
|
@ -0,0 +1,23 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md)
|
||||
|
||||
## DeprecationsServiceStart interface
|
||||
|
||||
DeprecationsService provides methods to fetch domain deprecation details from the Kibana server.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface DeprecationsServiceStart
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [getAllDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getalldeprecations.md) | <code>() => Promise<DomainDeprecationDetails[]></code> | Grabs deprecations details for all domains. |
|
||||
| [getDeprecations](./kibana-plugin-core-public.deprecationsservicestart.getdeprecations.md) | <code>(domainId: string) => Promise<DomainDeprecationDetails[]></code> | Grabs deprecations for a specific domain. |
|
||||
| [isDeprecationResolvable](./kibana-plugin-core-public.deprecationsservicestart.isdeprecationresolvable.md) | <code>(details: DomainDeprecationDetails) => boolean</code> | Returns a boolean if the provided deprecation can be automatically resolvable. |
|
||||
| [resolveDeprecation](./kibana-plugin-core-public.deprecationsservicestart.resolvedeprecation.md) | <code>(details: DomainDeprecationDetails) => Promise<ResolveDeprecationResponse></code> | Calls the correctiveActions.api to automatically resolve the depprecation. |
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) > [resolveDeprecation](./kibana-plugin-core-public.deprecationsservicestart.resolvedeprecation.md)
|
||||
|
||||
## DeprecationsServiceStart.resolveDeprecation property
|
||||
|
||||
Calls the correctiveActions.api to automatically resolve the depprecation.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
resolveDeprecation: (details: DomainDeprecationDetails) => Promise<ResolveDeprecationResponse>;
|
||||
```
|
|
@ -59,6 +59,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [ChromeUserBanner](./kibana-plugin-core-public.chromeuserbanner.md) | |
|
||||
| [CoreSetup](./kibana-plugin-core-public.coresetup.md) | Core services exposed to the <code>Plugin</code> setup lifecycle |
|
||||
| [CoreStart](./kibana-plugin-core-public.corestart.md) | Core services exposed to the <code>Plugin</code> start lifecycle |
|
||||
| [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) | DeprecationsService provides methods to fetch domain deprecation details from the Kibana server. |
|
||||
| [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) | |
|
||||
| [ErrorToastOptions](./kibana-plugin-core-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) error APIs. |
|
||||
| [FatalErrorInfo](./kibana-plugin-core-public.fatalerrorinfo.md) | Represents the <code>message</code> and <code>stack</code> of a fatal Error |
|
||||
|
@ -164,6 +165,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [PublicAppMetaInfo](./kibana-plugin-core-public.publicappmetainfo.md) | Public information about a registered app's [keywords](./kibana-plugin-core-public.appmeta.md) |
|
||||
| [PublicAppSearchDeepLinkInfo](./kibana-plugin-core-public.publicappsearchdeeplinkinfo.md) | Public information about a registered app's [searchDeepLinks](./kibana-plugin-core-public.appsearchdeeplink.md) |
|
||||
| [PublicUiSettingsParams](./kibana-plugin-core-public.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) exposed to the client-side. |
|
||||
| [ResolveDeprecationResponse](./kibana-plugin-core-public.resolvedeprecationresponse.md) | |
|
||||
| [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value |
|
||||
| [SavedObjectAttributeSingle](./kibana-plugin-core-public.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) |
|
||||
| [SavedObjectsClientContract](./kibana-plugin-core-public.savedobjectsclientcontract.md) | SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-core-public.savedobjectsclient.md) |
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ResolveDeprecationResponse](./kibana-plugin-core-public.resolvedeprecationresponse.md)
|
||||
|
||||
## ResolveDeprecationResponse type
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type ResolveDeprecationResponse = {
|
||||
status: 'ok';
|
||||
} | {
|
||||
status: 'fail';
|
||||
reason: string;
|
||||
};
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CoreSetup](./kibana-plugin-core-server.coresetup.md) > [deprecations](./kibana-plugin-core-server.coresetup.deprecations.md)
|
||||
|
||||
## CoreSetup.deprecations property
|
||||
|
||||
[DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md)
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
deprecations: DeprecationsServiceSetup;
|
||||
```
|
|
@ -18,6 +18,7 @@ export interface CoreSetup<TPluginsStart extends object = object, TStart = unkno
|
|||
| --- | --- | --- |
|
||||
| [capabilities](./kibana-plugin-core-server.coresetup.capabilities.md) | <code>CapabilitiesSetup</code> | [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) |
|
||||
| [context](./kibana-plugin-core-server.coresetup.context.md) | <code>ContextSetup</code> | [ContextSetup](./kibana-plugin-core-server.contextsetup.md) |
|
||||
| [deprecations](./kibana-plugin-core-server.coresetup.deprecations.md) | <code>DeprecationsServiceSetup</code> | [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) |
|
||||
| [elasticsearch](./kibana-plugin-core-server.coresetup.elasticsearch.md) | <code>ElasticsearchServiceSetup</code> | [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) |
|
||||
| [getStartServices](./kibana-plugin-core-server.coresetup.getstartservices.md) | <code>StartServicesAccessor<TPluginsStart, TStart></code> | [StartServicesAccessor](./kibana-plugin-core-server.startservicesaccessor.md) |
|
||||
| [http](./kibana-plugin-core-server.coresetup.http.md) | <code>HttpServiceSetup & {</code><br/><code> resources: HttpResources;</code><br/><code> }</code> | [HttpServiceSetup](./kibana-plugin-core-server.httpservicesetup.md) |
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) > [correctiveActions](./kibana-plugin-core-server.deprecationsdetails.correctiveactions.md)
|
||||
|
||||
## DeprecationsDetails.correctiveActions property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
correctiveActions: {
|
||||
api?: {
|
||||
path: string;
|
||||
method: 'POST' | 'PUT';
|
||||
body?: {
|
||||
[key: string]: any;
|
||||
};
|
||||
};
|
||||
manualSteps?: string[];
|
||||
};
|
||||
```
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) > [documentationUrl](./kibana-plugin-core-server.deprecationsdetails.documentationurl.md)
|
||||
|
||||
## DeprecationsDetails.documentationUrl property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
documentationUrl?: string;
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) > [level](./kibana-plugin-core-server.deprecationsdetails.level.md)
|
||||
|
||||
## DeprecationsDetails.level property
|
||||
|
||||
levels: - warning: will not break deployment upon upgrade - critical: needs to be addressed before upgrade. - fetch\_error: Deprecations service failed to grab the deprecation details for the domain.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
level: 'warning' | 'critical' | 'fetch_error';
|
||||
```
|
|
@ -0,0 +1,21 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md)
|
||||
|
||||
## DeprecationsDetails interface
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface DeprecationsDetails
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [correctiveActions](./kibana-plugin-core-server.deprecationsdetails.correctiveactions.md) | <code>{</code><br/><code> api?: {</code><br/><code> path: string;</code><br/><code> method: 'POST' | 'PUT';</code><br/><code> body?: {</code><br/><code> [key: string]: any;</code><br/><code> };</code><br/><code> };</code><br/><code> manualSteps?: string[];</code><br/><code> }</code> | |
|
||||
| [documentationUrl](./kibana-plugin-core-server.deprecationsdetails.documentationurl.md) | <code>string</code> | |
|
||||
| [level](./kibana-plugin-core-server.deprecationsdetails.level.md) | <code>'warning' | 'critical' | 'fetch_error'</code> | levels: - warning: will not break deployment upon upgrade - critical: needs to be addressed before upgrade. - fetch\_error: Deprecations service failed to grab the deprecation details for the domain. |
|
||||
| [message](./kibana-plugin-core-server.deprecationsdetails.message.md) | <code>string</code> | |
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) > [message](./kibana-plugin-core-server.deprecationsdetails.message.md)
|
||||
|
||||
## DeprecationsDetails.message property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
message: string;
|
||||
```
|
|
@ -0,0 +1,95 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md)
|
||||
|
||||
## DeprecationsServiceSetup interface
|
||||
|
||||
The deprecations service provides a way for the Kibana platform to communicate deprecated features and configs with its users. These deprecations are only communicated if the deployment is using these features. Allowing for a user tailored experience for upgrading the stack version.
|
||||
|
||||
The Deprecation service is consumed by the upgrade assistant to assist with the upgrade experience.
|
||||
|
||||
If a deprecated feature can be resolved without manual user intervention. Using correctiveActions.api allows the Upgrade Assistant to use this api to correct the deprecation upon a user trigger.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface DeprecationsServiceSetup
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
```ts
|
||||
import { DeprecationsDetails, GetDeprecationsContext, CoreSetup } from 'src/core/server';
|
||||
|
||||
async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecationsContext): Promise<DeprecationsDetails[]> {
|
||||
const deprecations: DeprecationsDetails[] = [];
|
||||
const count = await getTimelionSheetsCount(savedObjectsClient);
|
||||
|
||||
if (count > 0) {
|
||||
// Example of a manual correctiveAction
|
||||
deprecations.push({
|
||||
message: `You have ${count} Timelion worksheets. The Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard.`,
|
||||
documentationUrl:
|
||||
'https://www.elastic.co/guide/en/kibana/current/create-panels-with-timelion.html',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
manualSteps: [
|
||||
'Navigate to the Kibana Dashboard and click "Create dashboard".',
|
||||
'Select Timelion from the "New Visualization" window.',
|
||||
'Open a new tab, open the Timelion app, select the chart you want to copy, then copy the chart expression.',
|
||||
'Go to Timelion, paste the chart expression in the Timelion expression field, then click Update.',
|
||||
'In the toolbar, click Save.',
|
||||
'On the Save visualization window, enter the visualization Title, then click Save and return.',
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Example of an api correctiveAction
|
||||
deprecations.push({
|
||||
"message": "User 'test_dashboard_user' is using a deprecated role: 'kibana_user'",
|
||||
"documentationUrl": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-user.html",
|
||||
"level": "critical",
|
||||
"correctiveActions": {
|
||||
"api": {
|
||||
"path": "/internal/security/users/test_dashboard_user",
|
||||
"method": "POST",
|
||||
"body": {
|
||||
"username": "test_dashboard_user",
|
||||
"roles": [
|
||||
"machine_learning_user",
|
||||
"enrich_user",
|
||||
"kibana_admin"
|
||||
],
|
||||
"full_name": "Alison Goryachev",
|
||||
"email": "alisongoryachev@gmail.com",
|
||||
"metadata": {},
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"manualSteps": [
|
||||
"Using Kibana user management, change all users using the kibana_user role to the kibana_admin role.",
|
||||
"Using Kibana role-mapping management, change all role-mappings which assing the kibana_user role to the kibana_admin role."
|
||||
]
|
||||
},
|
||||
});
|
||||
|
||||
return deprecations;
|
||||
}
|
||||
|
||||
|
||||
export class Plugin() {
|
||||
setup: (core: CoreSetup) => {
|
||||
core.deprecations.registerDeprecations({ getDeprecations });
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [registerDeprecations](./kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md) | <code>(deprecationContext: RegisterDeprecationsConfig) => void</code> | |
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) > [registerDeprecations](./kibana-plugin-core-server.deprecationsservicesetup.registerdeprecations.md)
|
||||
|
||||
## DeprecationsServiceSetup.registerDeprecations property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
registerDeprecations: (deprecationContext: RegisterDeprecationsConfig) => void;
|
||||
```
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [GetDeprecationsContext](./kibana-plugin-core-server.getdeprecationscontext.md) > [esClient](./kibana-plugin-core-server.getdeprecationscontext.esclient.md)
|
||||
|
||||
## GetDeprecationsContext.esClient property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
esClient: IScopedClusterClient;
|
||||
```
|
|
@ -0,0 +1,19 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [GetDeprecationsContext](./kibana-plugin-core-server.getdeprecationscontext.md)
|
||||
|
||||
## GetDeprecationsContext interface
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface GetDeprecationsContext
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [esClient](./kibana-plugin-core-server.getdeprecationscontext.esclient.md) | <code>IScopedClusterClient</code> | |
|
||||
| [savedObjectsClient](./kibana-plugin-core-server.getdeprecationscontext.savedobjectsclient.md) | <code>SavedObjectsClientContract</code> | |
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [GetDeprecationsContext](./kibana-plugin-core-server.getdeprecationscontext.md) > [savedObjectsClient](./kibana-plugin-core-server.getdeprecationscontext.savedobjectsclient.md)
|
||||
|
||||
## GetDeprecationsContext.savedObjectsClient property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
```
|
|
@ -69,13 +69,16 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [DeprecationAPIClientParams](./kibana-plugin-core-server.deprecationapiclientparams.md) | |
|
||||
| [DeprecationAPIResponse](./kibana-plugin-core-server.deprecationapiresponse.md) | |
|
||||
| [DeprecationInfo](./kibana-plugin-core-server.deprecationinfo.md) | |
|
||||
| [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) | |
|
||||
| [DeprecationSettings](./kibana-plugin-core-server.deprecationsettings.md) | UiSettings deprecation field options. |
|
||||
| [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) | The deprecations service provides a way for the Kibana platform to communicate deprecated features and configs with its users. These deprecations are only communicated if the deployment is using these features. Allowing for a user tailored experience for upgrading the stack version.<!-- -->The Deprecation service is consumed by the upgrade assistant to assist with the upgrade experience.<!-- -->If a deprecated feature can be resolved without manual user intervention. Using correctiveActions.api allows the Upgrade Assistant to use this api to correct the deprecation upon a user trigger. |
|
||||
| [DiscoveredPlugin](./kibana-plugin-core-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. |
|
||||
| [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) | |
|
||||
| [ElasticsearchServiceStart](./kibana-plugin-core-server.elasticsearchservicestart.md) | |
|
||||
| [ElasticsearchStatusMeta](./kibana-plugin-core-server.elasticsearchstatusmeta.md) | |
|
||||
| [ErrorHttpResponseOptions](./kibana-plugin-core-server.errorhttpresponseoptions.md) | HTTP response parameters |
|
||||
| [FakeRequest](./kibana-plugin-core-server.fakerequest.md) | Fake request object created manually by Kibana plugins. |
|
||||
| [GetDeprecationsContext](./kibana-plugin-core-server.getdeprecationscontext.md) | |
|
||||
| [GetResponse](./kibana-plugin-core-server.getresponse.md) | |
|
||||
| [HttpAuth](./kibana-plugin-core-server.httpauth.md) | |
|
||||
| [HttpResources](./kibana-plugin-core-server.httpresources.md) | HttpResources service is responsible for serving static & dynamic assets for Kibana application via HTTP. Provides API allowing plug-ins to respond with: - a pre-configured HTML page bootstrapping Kibana client app - custom HTML page - custom JS script file. |
|
||||
|
@ -128,6 +131,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [PluginConfigDescriptor](./kibana-plugin-core-server.pluginconfigdescriptor.md) | Describes a plugin configuration properties. |
|
||||
| [PluginInitializerContext](./kibana-plugin-core-server.plugininitializercontext.md) | Context that's available to plugins during initialization stage. |
|
||||
| [PluginManifest](./kibana-plugin-core-server.pluginmanifest.md) | Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. |
|
||||
| [RegisterDeprecationsConfig](./kibana-plugin-core-server.registerdeprecationsconfig.md) | |
|
||||
| [RequestHandlerContext](./kibana-plugin-core-server.requesthandlercontext.md) | Plugin specific context passed to a route handler.<!-- -->Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.client](./kibana-plugin-core-server.iscopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [elasticsearch.legacy.client](./kibana-plugin-core-server.legacyscopedclusterclient.md) - The legacy Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request |
|
||||
| [ResolveCapabilitiesOptions](./kibana-plugin-core-server.resolvecapabilitiesoptions.md) | Defines a set of additional options for the <code>resolveCapabilities</code> method of [CapabilitiesStart](./kibana-plugin-core-server.capabilitiesstart.md)<!-- -->. |
|
||||
| [RouteConfig](./kibana-plugin-core-server.routeconfig.md) | Route specific configuration. |
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [RegisterDeprecationsConfig](./kibana-plugin-core-server.registerdeprecationsconfig.md) > [getDeprecations](./kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md)
|
||||
|
||||
## RegisterDeprecationsConfig.getDeprecations property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getDeprecations: (context: GetDeprecationsContext) => MaybePromise<DeprecationsDetails[]>;
|
||||
```
|
|
@ -0,0 +1,18 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [RegisterDeprecationsConfig](./kibana-plugin-core-server.registerdeprecationsconfig.md)
|
||||
|
||||
## RegisterDeprecationsConfig interface
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface RegisterDeprecationsConfig
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [getDeprecations](./kibana-plugin-core-server.registerdeprecationsconfig.getdeprecations.md) | <code>(context: GetDeprecationsContext) => MaybePromise<DeprecationsDetails[]></code> | |
|
||||
|
|
@ -25,13 +25,16 @@ const createConfigServiceMock = ({
|
|||
setSchema: jest.fn(),
|
||||
addDeprecationProvider: jest.fn(),
|
||||
validate: jest.fn(),
|
||||
getHandledDeprecatedConfigs: jest.fn(),
|
||||
};
|
||||
|
||||
mocked.atPath.mockReturnValue(new BehaviorSubject(atPath));
|
||||
mocked.atPathSync.mockReturnValue(atPath);
|
||||
mocked.getConfig$.mockReturnValue(new BehaviorSubject(new ObjectToConfigAdapter(getConfig$)));
|
||||
mocked.getUsedPaths.mockResolvedValue([]);
|
||||
mocked.getUnusedPaths.mockResolvedValue([]);
|
||||
mocked.isEnabledAtPath.mockResolvedValue(true);
|
||||
mocked.getHandledDeprecatedConfigs.mockReturnValue([]);
|
||||
return mocked;
|
||||
};
|
||||
|
||||
|
|
|
@ -7,9 +7,15 @@
|
|||
*/
|
||||
|
||||
export const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] });
|
||||
import type { applyDeprecations } from './deprecation/apply_deprecations';
|
||||
|
||||
jest.mock('../../../package.json', () => mockPackage);
|
||||
|
||||
export const mockApplyDeprecations = jest.fn((config, deprecations, log) => config);
|
||||
export const mockApplyDeprecations = jest.fn<
|
||||
Record<string, any>,
|
||||
Parameters<typeof applyDeprecations>
|
||||
>((config, deprecations, createAddDeprecation) => config);
|
||||
|
||||
jest.mock('./deprecation/apply_deprecations', () => ({
|
||||
applyDeprecations: mockApplyDeprecations,
|
||||
}));
|
||||
|
|
|
@ -72,10 +72,10 @@ test('throws if config at path does not match schema', async () => {
|
|||
);
|
||||
|
||||
await expect(valuesReceived).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
[Error: [config validation of [key]]: expected value of type [string] but got [number]],
|
||||
]
|
||||
`);
|
||||
Array [
|
||||
[Error: [config validation of [key]]: expected value of type [string] but got [number]],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('re-validate config when updated', async () => {
|
||||
|
@ -97,11 +97,11 @@ test('re-validate config when updated', async () => {
|
|||
|
||||
rawConfig$.next({ key: 123 });
|
||||
|
||||
await expect(valuesReceived).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"value",
|
||||
[Error: [config validation of [key]]: expected value of type [string] but got [number]],
|
||||
]
|
||||
expect(valuesReceived).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"value",
|
||||
[Error: [config validation of [key]]: expected value of type [string] but got [number]],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
|
@ -416,10 +416,10 @@ test('throws during validation is any schema is invalid', async () => {
|
|||
test('logs deprecation warning during validation', async () => {
|
||||
const rawConfig = getRawConfigProvider({});
|
||||
const configService = new ConfigService(rawConfig, defaultEnv, logger);
|
||||
|
||||
mockApplyDeprecations.mockImplementationOnce((config, deprecations, log) => {
|
||||
log('some deprecation message');
|
||||
log('another deprecation message');
|
||||
mockApplyDeprecations.mockImplementationOnce((config, deprecations, createAddDeprecation) => {
|
||||
const addDeprecation = createAddDeprecation!('');
|
||||
addDeprecation({ message: 'some deprecation message' });
|
||||
addDeprecation({ message: 'another deprecation message' });
|
||||
return config;
|
||||
});
|
||||
|
||||
|
@ -437,6 +437,37 @@ test('logs deprecation warning during validation', async () => {
|
|||
`);
|
||||
});
|
||||
|
||||
test('does not log warnings for silent deprecations during validation', async () => {
|
||||
const rawConfig = getRawConfigProvider({});
|
||||
const configService = new ConfigService(rawConfig, defaultEnv, logger);
|
||||
|
||||
mockApplyDeprecations
|
||||
.mockImplementationOnce((config, deprecations, createAddDeprecation) => {
|
||||
const addDeprecation = createAddDeprecation!('');
|
||||
addDeprecation({ message: 'some deprecation message', silent: true });
|
||||
addDeprecation({ message: 'another deprecation message' });
|
||||
return config;
|
||||
})
|
||||
.mockImplementationOnce((config, deprecations, createAddDeprecation) => {
|
||||
const addDeprecation = createAddDeprecation!('');
|
||||
addDeprecation({ message: 'I am silent', silent: true });
|
||||
return config;
|
||||
});
|
||||
|
||||
loggerMock.clear(logger);
|
||||
await configService.validate();
|
||||
expect(loggerMock.collect(logger).warn).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Array [
|
||||
"another deprecation message",
|
||||
],
|
||||
]
|
||||
`);
|
||||
loggerMock.clear(logger);
|
||||
await configService.validate();
|
||||
expect(loggerMock.collect(logger).warn).toMatchInlineSnapshot(`Array []`);
|
||||
});
|
||||
|
||||
describe('atPathSync', () => {
|
||||
test('returns the value at path', async () => {
|
||||
const rawConfig = getRawConfigProvider({ key: 'foo' });
|
||||
|
@ -477,3 +508,36 @@ describe('atPathSync', () => {
|
|||
expect(configService.atPathSync('key')).toEqual('new-value');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getHandledDeprecatedConfigs', () => {
|
||||
it('returns all handled deprecated configs', async () => {
|
||||
const rawConfig = getRawConfigProvider({ base: { unused: 'unusedConfig' } });
|
||||
const configService = new ConfigService(rawConfig, defaultEnv, logger);
|
||||
|
||||
configService.addDeprecationProvider('base', ({ unused }) => [unused('unused')]);
|
||||
|
||||
mockApplyDeprecations.mockImplementationOnce((config, deprecations, createAddDeprecation) => {
|
||||
deprecations.forEach((deprecation) => {
|
||||
const addDeprecation = createAddDeprecation!(deprecation.path);
|
||||
addDeprecation({ message: `some deprecation message`, documentationUrl: 'some-url' });
|
||||
});
|
||||
return config;
|
||||
});
|
||||
|
||||
await configService.validate();
|
||||
|
||||
expect(configService.getHandledDeprecatedConfigs()).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Array [
|
||||
"base",
|
||||
Array [
|
||||
Object {
|
||||
"documentationUrl": "some-url",
|
||||
"message": "some deprecation message",
|
||||
},
|
||||
],
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
ConfigDeprecationWithContext,
|
||||
ConfigDeprecationProvider,
|
||||
configDeprecationFactory,
|
||||
DeprecatedConfigDetails,
|
||||
} from './deprecation';
|
||||
import { LegacyObjectToConfigAdapter } from './legacy';
|
||||
|
||||
|
@ -43,6 +44,7 @@ export class ConfigService {
|
|||
private readonly handledPaths: Set<ConfigPath> = new Set();
|
||||
private readonly schemas = new Map<string, Type<unknown>>();
|
||||
private readonly deprecations = new BehaviorSubject<ConfigDeprecationWithContext[]>([]);
|
||||
private readonly handledDeprecatedConfigs = new Map<string, DeprecatedConfigDetails[]>();
|
||||
|
||||
constructor(
|
||||
private readonly rawConfigProvider: RawConfigurationProvider,
|
||||
|
@ -91,6 +93,13 @@ export class ConfigService {
|
|||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns all handled deprecated configs
|
||||
*/
|
||||
public getHandledDeprecatedConfigs() {
|
||||
return [...this.handledDeprecatedConfigs.entries()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the whole configuration and log the deprecation warnings.
|
||||
*
|
||||
|
@ -186,8 +195,16 @@ export class ConfigService {
|
|||
const rawConfig = await this.rawConfigProvider.getConfig$().pipe(take(1)).toPromise();
|
||||
const deprecations = await this.deprecations.pipe(take(1)).toPromise();
|
||||
const deprecationMessages: string[] = [];
|
||||
const logger = (msg: string) => deprecationMessages.push(msg);
|
||||
applyDeprecations(rawConfig, deprecations, logger);
|
||||
const createAddDeprecation = (domainId: string) => (context: DeprecatedConfigDetails) => {
|
||||
if (!context.silent) {
|
||||
deprecationMessages.push(context.message);
|
||||
}
|
||||
const handledDeprecatedConfig = this.handledDeprecatedConfigs.get(domainId) || [];
|
||||
handledDeprecatedConfig.push(context);
|
||||
this.handledDeprecatedConfigs.set(domainId, handledDeprecatedConfig);
|
||||
};
|
||||
|
||||
applyDeprecations(rawConfig, deprecations, createAddDeprecation);
|
||||
deprecationMessages.forEach((msg) => {
|
||||
this.deprecationLog.warn(msg);
|
||||
});
|
||||
|
|
|
@ -32,8 +32,9 @@ describe('applyDeprecations', () => {
|
|||
expect(handlerC).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('calls handlers with correct arguments', () => {
|
||||
const logger = () => undefined;
|
||||
it('passes path to addDeprecation factory', () => {
|
||||
const addDeprecation = jest.fn();
|
||||
const createAddDeprecation = jest.fn().mockReturnValue(addDeprecation);
|
||||
const initialConfig = { foo: 'bar', deprecated: 'deprecated' };
|
||||
const alteredConfig = { foo: 'bar' };
|
||||
|
||||
|
@ -43,11 +44,33 @@ describe('applyDeprecations', () => {
|
|||
applyDeprecations(
|
||||
initialConfig,
|
||||
[wrapHandler(handlerA, 'pathA'), wrapHandler(handlerB, 'pathB')],
|
||||
logger
|
||||
createAddDeprecation
|
||||
);
|
||||
|
||||
expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', logger);
|
||||
expect(handlerB).toHaveBeenCalledWith(alteredConfig, 'pathB', logger);
|
||||
expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', addDeprecation);
|
||||
expect(handlerB).toHaveBeenCalledWith(alteredConfig, 'pathB', addDeprecation);
|
||||
expect(createAddDeprecation).toBeCalledTimes(2);
|
||||
expect(createAddDeprecation).toHaveBeenNthCalledWith(1, 'pathA');
|
||||
expect(createAddDeprecation).toHaveBeenNthCalledWith(2, 'pathB');
|
||||
});
|
||||
|
||||
it('calls handlers with correct arguments', () => {
|
||||
const addDeprecation = jest.fn();
|
||||
const createAddDeprecation = jest.fn().mockReturnValue(addDeprecation);
|
||||
const initialConfig = { foo: 'bar', deprecated: 'deprecated' };
|
||||
const alteredConfig = { foo: 'bar' };
|
||||
|
||||
const handlerA = jest.fn().mockReturnValue(alteredConfig);
|
||||
const handlerB = jest.fn().mockImplementation((conf) => conf);
|
||||
|
||||
applyDeprecations(
|
||||
initialConfig,
|
||||
[wrapHandler(handlerA, 'pathA'), wrapHandler(handlerB, 'pathB')],
|
||||
createAddDeprecation
|
||||
);
|
||||
|
||||
expect(handlerA).toHaveBeenCalledWith(initialConfig, 'pathA', addDeprecation);
|
||||
expect(handlerB).toHaveBeenCalledWith(alteredConfig, 'pathB', addDeprecation);
|
||||
});
|
||||
|
||||
it('returns the migrated config', () => {
|
||||
|
|
|
@ -7,23 +7,24 @@
|
|||
*/
|
||||
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { ConfigDeprecationWithContext, ConfigDeprecationLogger } from './types';
|
||||
|
||||
const noopLogger = (msg: string) => undefined;
|
||||
import { ConfigDeprecationWithContext, AddConfigDeprecation } from './types';
|
||||
|
||||
const noopAddDeprecationFactory: () => AddConfigDeprecation = () => () => undefined;
|
||||
/**
|
||||
* Applies deprecations on given configuration and logs any deprecation warning using provided logger.
|
||||
* Applies deprecations on given configuration and passes addDeprecation hook.
|
||||
* This hook is used for logging any deprecation warning using provided logger.
|
||||
* This hook is used for exposing deprecated configs that must be handled by the user before upgrading to next major.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export const applyDeprecations = (
|
||||
config: Record<string, any>,
|
||||
deprecations: ConfigDeprecationWithContext[],
|
||||
logger: ConfigDeprecationLogger = noopLogger
|
||||
createAddDeprecation: (pluginId: string) => AddConfigDeprecation = noopAddDeprecationFactory
|
||||
) => {
|
||||
let processed = cloneDeep(config);
|
||||
deprecations.forEach(({ deprecation, path }) => {
|
||||
processed = deprecation(processed, path, logger);
|
||||
processed = deprecation(processed, path, createAddDeprecation(path));
|
||||
});
|
||||
return processed;
|
||||
};
|
||||
|
|
|
@ -6,17 +6,16 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { ConfigDeprecationLogger } from './types';
|
||||
import { DeprecatedConfigDetails } from './types';
|
||||
import { configDeprecationFactory } from './deprecation_factory';
|
||||
|
||||
describe('DeprecationFactory', () => {
|
||||
const { rename, unused, renameFromRoot, unusedFromRoot } = configDeprecationFactory;
|
||||
|
||||
let deprecationMessages: string[];
|
||||
const logger: ConfigDeprecationLogger = (msg) => deprecationMessages.push(msg);
|
||||
const addDeprecation = jest.fn<void, [DeprecatedConfigDetails]>();
|
||||
|
||||
beforeEach(() => {
|
||||
deprecationMessages = [];
|
||||
addDeprecation.mockClear();
|
||||
});
|
||||
|
||||
describe('rename', () => {
|
||||
|
@ -30,7 +29,7 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
};
|
||||
const processed = rename('deprecated', 'renamed')(rawConfig, 'myplugin', logger);
|
||||
const processed = rename('deprecated', 'renamed')(rawConfig, 'myplugin', addDeprecation);
|
||||
expect(processed).toEqual({
|
||||
myplugin: {
|
||||
renamed: 'toberenamed',
|
||||
|
@ -40,9 +39,18 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages).toMatchInlineSnapshot(`
|
||||
expect(addDeprecation.mock.calls).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\"",
|
||||
Array [
|
||||
Object {
|
||||
"correctiveActions": Object {
|
||||
"manualSteps": Array [
|
||||
"Replace \\"myplugin.deprecated\\" with \\"myplugin.renamed\\" in the Kibana config file, CLI flag, or environment variable (in Docker only).",
|
||||
],
|
||||
},
|
||||
"message": "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\"",
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -56,7 +64,7 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
};
|
||||
const processed = rename('deprecated', 'new')(rawConfig, 'myplugin', logger);
|
||||
const processed = rename('deprecated', 'new')(rawConfig, 'myplugin', addDeprecation);
|
||||
expect(processed).toEqual({
|
||||
myplugin: {
|
||||
new: 'new',
|
||||
|
@ -66,7 +74,7 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages.length).toEqual(0);
|
||||
expect(addDeprecation).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
it('handles nested keys', () => {
|
||||
const rawConfig = {
|
||||
|
@ -83,7 +91,7 @@ describe('DeprecationFactory', () => {
|
|||
const processed = rename('oldsection.deprecated', 'newsection.renamed')(
|
||||
rawConfig,
|
||||
'myplugin',
|
||||
logger
|
||||
addDeprecation
|
||||
);
|
||||
expect(processed).toEqual({
|
||||
myplugin: {
|
||||
|
@ -97,9 +105,18 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages).toMatchInlineSnapshot(`
|
||||
expect(addDeprecation.mock.calls).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"myplugin.oldsection.deprecated\\" is deprecated and has been replaced by \\"myplugin.newsection.renamed\\"",
|
||||
Array [
|
||||
Object {
|
||||
"correctiveActions": Object {
|
||||
"manualSteps": Array [
|
||||
"Replace \\"myplugin.oldsection.deprecated\\" with \\"myplugin.newsection.renamed\\" in the Kibana config file, CLI flag, or environment variable (in Docker only).",
|
||||
],
|
||||
},
|
||||
"message": "\\"myplugin.oldsection.deprecated\\" is deprecated and has been replaced by \\"myplugin.newsection.renamed\\"",
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -110,15 +127,25 @@ describe('DeprecationFactory', () => {
|
|||
renamed: 'renamed',
|
||||
},
|
||||
};
|
||||
const processed = rename('deprecated', 'renamed')(rawConfig, 'myplugin', logger);
|
||||
const processed = rename('deprecated', 'renamed')(rawConfig, 'myplugin', addDeprecation);
|
||||
expect(processed).toEqual({
|
||||
myplugin: {
|
||||
renamed: 'renamed',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages).toMatchInlineSnapshot(`
|
||||
expect(addDeprecation.mock.calls).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\". However both key are present, ignoring \\"myplugin.deprecated\\"",
|
||||
Array [
|
||||
Object {
|
||||
"correctiveActions": Object {
|
||||
"manualSteps": Array [
|
||||
"Make sure \\"myplugin.renamed\\" contains the correct value in the config file, CLI flag, or environment variable (in Docker only).",
|
||||
"Remove \\"myplugin.deprecated\\" from the config.",
|
||||
],
|
||||
},
|
||||
"message": "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\". However both key are present, ignoring \\"myplugin.deprecated\\"",
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -138,7 +165,7 @@ describe('DeprecationFactory', () => {
|
|||
const processed = renameFromRoot('myplugin.deprecated', 'myplugin.renamed')(
|
||||
rawConfig,
|
||||
'does-not-matter',
|
||||
logger
|
||||
addDeprecation
|
||||
);
|
||||
expect(processed).toEqual({
|
||||
myplugin: {
|
||||
|
@ -149,9 +176,18 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages).toMatchInlineSnapshot(`
|
||||
expect(addDeprecation.mock.calls).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\"",
|
||||
Array [
|
||||
Object {
|
||||
"correctiveActions": Object {
|
||||
"manualSteps": Array [
|
||||
"Replace \\"myplugin.deprecated\\" with \\"myplugin.renamed\\" in the Kibana config file, CLI flag, or environment variable (in Docker only).",
|
||||
],
|
||||
},
|
||||
"message": "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\"",
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -169,7 +205,7 @@ describe('DeprecationFactory', () => {
|
|||
const processed = renameFromRoot('oldplugin.deprecated', 'newplugin.renamed')(
|
||||
rawConfig,
|
||||
'does-not-matter',
|
||||
logger
|
||||
addDeprecation
|
||||
);
|
||||
expect(processed).toEqual({
|
||||
oldplugin: {
|
||||
|
@ -180,9 +216,18 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages).toMatchInlineSnapshot(`
|
||||
expect(addDeprecation.mock.calls).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"oldplugin.deprecated\\" is deprecated and has been replaced by \\"newplugin.renamed\\"",
|
||||
Array [
|
||||
Object {
|
||||
"correctiveActions": Object {
|
||||
"manualSteps": Array [
|
||||
"Replace \\"oldplugin.deprecated\\" with \\"newplugin.renamed\\" in the Kibana config file, CLI flag, or environment variable (in Docker only).",
|
||||
],
|
||||
},
|
||||
"message": "\\"oldplugin.deprecated\\" is deprecated and has been replaced by \\"newplugin.renamed\\"",
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -200,7 +245,7 @@ describe('DeprecationFactory', () => {
|
|||
const processed = renameFromRoot('myplugin.deprecated', 'myplugin.new')(
|
||||
rawConfig,
|
||||
'does-not-matter',
|
||||
logger
|
||||
addDeprecation
|
||||
);
|
||||
expect(processed).toEqual({
|
||||
myplugin: {
|
||||
|
@ -211,7 +256,7 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages.length).toEqual(0);
|
||||
expect(addDeprecation).toBeCalledTimes(0);
|
||||
});
|
||||
|
||||
it('remove the old property but does not overrides the new one if they both exist, and logs a specific message', () => {
|
||||
|
@ -224,16 +269,27 @@ describe('DeprecationFactory', () => {
|
|||
const processed = renameFromRoot('myplugin.deprecated', 'myplugin.renamed')(
|
||||
rawConfig,
|
||||
'does-not-matter',
|
||||
logger
|
||||
addDeprecation
|
||||
);
|
||||
expect(processed).toEqual({
|
||||
myplugin: {
|
||||
renamed: 'renamed',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages).toMatchInlineSnapshot(`
|
||||
|
||||
expect(addDeprecation.mock.calls).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\". However both key are present, ignoring \\"myplugin.deprecated\\"",
|
||||
Array [
|
||||
Object {
|
||||
"correctiveActions": Object {
|
||||
"manualSteps": Array [
|
||||
"Make sure \\"myplugin.renamed\\" contains the correct value in the config file, CLI flag, or environment variable (in Docker only).",
|
||||
"Remove \\"myplugin.deprecated\\" from the config.",
|
||||
],
|
||||
},
|
||||
"message": "\\"myplugin.deprecated\\" is deprecated and has been replaced by \\"myplugin.renamed\\". However both key are present, ignoring \\"myplugin.deprecated\\"",
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -250,7 +306,7 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
};
|
||||
const processed = unused('deprecated')(rawConfig, 'myplugin', logger);
|
||||
const processed = unused('deprecated')(rawConfig, 'myplugin', addDeprecation);
|
||||
expect(processed).toEqual({
|
||||
myplugin: {
|
||||
valid: 'valid',
|
||||
|
@ -259,9 +315,18 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages).toMatchInlineSnapshot(`
|
||||
expect(addDeprecation.mock.calls).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"myplugin.deprecated is deprecated and is no longer used",
|
||||
Array [
|
||||
Object {
|
||||
"correctiveActions": Object {
|
||||
"manualSteps": Array [
|
||||
"Remove \\"myplugin.deprecated\\" from the Kibana config file, CLI flag, or environment variable (in Docker only)",
|
||||
],
|
||||
},
|
||||
"message": "myplugin.deprecated is deprecated and is no longer used",
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -278,7 +343,7 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
};
|
||||
const processed = unused('section.deprecated')(rawConfig, 'myplugin', logger);
|
||||
const processed = unused('section.deprecated')(rawConfig, 'myplugin', addDeprecation);
|
||||
expect(processed).toEqual({
|
||||
myplugin: {
|
||||
valid: 'valid',
|
||||
|
@ -288,9 +353,19 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages).toMatchInlineSnapshot(`
|
||||
|
||||
expect(addDeprecation.mock.calls).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"myplugin.section.deprecated is deprecated and is no longer used",
|
||||
Array [
|
||||
Object {
|
||||
"correctiveActions": Object {
|
||||
"manualSteps": Array [
|
||||
"Remove \\"myplugin.section.deprecated\\" from the Kibana config file, CLI flag, or environment variable (in Docker only)",
|
||||
],
|
||||
},
|
||||
"message": "myplugin.section.deprecated is deprecated and is no longer used",
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -304,7 +379,7 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
};
|
||||
const processed = unused('deprecated')(rawConfig, 'myplugin', logger);
|
||||
const processed = unused('deprecated')(rawConfig, 'myplugin', addDeprecation);
|
||||
expect(processed).toEqual({
|
||||
myplugin: {
|
||||
valid: 'valid',
|
||||
|
@ -313,7 +388,7 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages.length).toEqual(0);
|
||||
expect(addDeprecation).toBeCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -328,7 +403,11 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
};
|
||||
const processed = unusedFromRoot('myplugin.deprecated')(rawConfig, 'does-not-matter', logger);
|
||||
const processed = unusedFromRoot('myplugin.deprecated')(
|
||||
rawConfig,
|
||||
'does-not-matter',
|
||||
addDeprecation
|
||||
);
|
||||
expect(processed).toEqual({
|
||||
myplugin: {
|
||||
valid: 'valid',
|
||||
|
@ -337,9 +416,19 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages).toMatchInlineSnapshot(`
|
||||
|
||||
expect(addDeprecation.mock.calls).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"myplugin.deprecated is deprecated and is no longer used",
|
||||
Array [
|
||||
Object {
|
||||
"correctiveActions": Object {
|
||||
"manualSteps": Array [
|
||||
"Remove \\"myplugin.deprecated\\" from the Kibana config file, CLI flag, or environment variable (in Docker only)",
|
||||
],
|
||||
},
|
||||
"message": "myplugin.deprecated is deprecated and is no longer used",
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -353,7 +442,11 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
};
|
||||
const processed = unusedFromRoot('myplugin.deprecated')(rawConfig, 'does-not-matter', logger);
|
||||
const processed = unusedFromRoot('myplugin.deprecated')(
|
||||
rawConfig,
|
||||
'does-not-matter',
|
||||
addDeprecation
|
||||
);
|
||||
expect(processed).toEqual({
|
||||
myplugin: {
|
||||
valid: 'valid',
|
||||
|
@ -362,7 +455,7 @@ describe('DeprecationFactory', () => {
|
|||
property: 'value',
|
||||
},
|
||||
});
|
||||
expect(deprecationMessages.length).toEqual(0);
|
||||
expect(addDeprecation).toBeCalledTimes(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,15 +9,20 @@
|
|||
import { get } from 'lodash';
|
||||
import { set } from '@elastic/safer-lodash-set';
|
||||
import { unset } from '@kbn/std';
|
||||
import { ConfigDeprecation, ConfigDeprecationLogger, ConfigDeprecationFactory } from './types';
|
||||
import {
|
||||
ConfigDeprecation,
|
||||
AddConfigDeprecation,
|
||||
ConfigDeprecationFactory,
|
||||
DeprecatedConfigDetails,
|
||||
} from './types';
|
||||
|
||||
const _rename = (
|
||||
config: Record<string, any>,
|
||||
rootPath: string,
|
||||
log: ConfigDeprecationLogger,
|
||||
addDeprecation: AddConfigDeprecation,
|
||||
oldKey: string,
|
||||
newKey: string,
|
||||
silent?: boolean
|
||||
details?: Partial<DeprecatedConfigDetails>
|
||||
) => {
|
||||
const fullOldPath = getPath(rootPath, oldKey);
|
||||
const oldValue = get(config, fullOldPath);
|
||||
|
@ -32,48 +37,80 @@ const _rename = (
|
|||
if (newValue === undefined) {
|
||||
set(config, fullNewPath, oldValue);
|
||||
|
||||
if (!silent) {
|
||||
log(`"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}"`);
|
||||
}
|
||||
addDeprecation({
|
||||
message: `"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}"`,
|
||||
correctiveActions: {
|
||||
manualSteps: [
|
||||
`Replace "${fullOldPath}" with "${fullNewPath}" in the Kibana config file, CLI flag, or environment variable (in Docker only).`,
|
||||
],
|
||||
},
|
||||
...details,
|
||||
});
|
||||
} else {
|
||||
if (!silent) {
|
||||
log(
|
||||
`"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}". However both key are present, ignoring "${fullOldPath}"`
|
||||
);
|
||||
}
|
||||
addDeprecation({
|
||||
message: `"${fullOldPath}" is deprecated and has been replaced by "${fullNewPath}". However both key are present, ignoring "${fullOldPath}"`,
|
||||
correctiveActions: {
|
||||
manualSteps: [
|
||||
`Make sure "${fullNewPath}" contains the correct value in the config file, CLI flag, or environment variable (in Docker only).`,
|
||||
`Remove "${fullOldPath}" from the config.`,
|
||||
],
|
||||
},
|
||||
...details,
|
||||
});
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
const _unused = (
|
||||
config: Record<string, any>,
|
||||
rootPath: string,
|
||||
log: ConfigDeprecationLogger,
|
||||
unusedKey: string
|
||||
addDeprecation: AddConfigDeprecation,
|
||||
unusedKey: string,
|
||||
details?: Partial<DeprecatedConfigDetails>
|
||||
) => {
|
||||
const fullPath = getPath(rootPath, unusedKey);
|
||||
if (get(config, fullPath) === undefined) {
|
||||
return config;
|
||||
}
|
||||
unset(config, fullPath);
|
||||
log(`${fullPath} is deprecated and is no longer used`);
|
||||
addDeprecation({
|
||||
message: `${fullPath} is deprecated and is no longer used`,
|
||||
correctiveActions: {
|
||||
manualSteps: [
|
||||
`Remove "${fullPath}" from the Kibana config file, CLI flag, or environment variable (in Docker only)`,
|
||||
],
|
||||
},
|
||||
...details,
|
||||
});
|
||||
return config;
|
||||
};
|
||||
|
||||
const rename = (oldKey: string, newKey: string): ConfigDeprecation => (config, rootPath, log) =>
|
||||
_rename(config, rootPath, log, oldKey, newKey);
|
||||
const rename = (
|
||||
oldKey: string,
|
||||
newKey: string,
|
||||
details?: Partial<DeprecatedConfigDetails>
|
||||
): ConfigDeprecation => (config, rootPath, addDeprecation) =>
|
||||
_rename(config, rootPath, addDeprecation, oldKey, newKey, details);
|
||||
|
||||
const renameFromRoot = (oldKey: string, newKey: string, silent?: boolean): ConfigDeprecation => (
|
||||
config,
|
||||
rootPath,
|
||||
log
|
||||
) => _rename(config, '', log, oldKey, newKey, silent);
|
||||
const renameFromRoot = (
|
||||
oldKey: string,
|
||||
newKey: string,
|
||||
details?: Partial<DeprecatedConfigDetails>
|
||||
): ConfigDeprecation => (config, rootPath, addDeprecation) =>
|
||||
_rename(config, '', addDeprecation, oldKey, newKey, details);
|
||||
|
||||
const unused = (unusedKey: string): ConfigDeprecation => (config, rootPath, log) =>
|
||||
_unused(config, rootPath, log, unusedKey);
|
||||
const unused = (
|
||||
unusedKey: string,
|
||||
details?: Partial<DeprecatedConfigDetails>
|
||||
): ConfigDeprecation => (config, rootPath, addDeprecation) =>
|
||||
_unused(config, rootPath, addDeprecation, unusedKey, details);
|
||||
|
||||
const unusedFromRoot = (unusedKey: string): ConfigDeprecation => (config, rootPath, log) =>
|
||||
_unused(config, '', log, unusedKey);
|
||||
const unusedFromRoot = (
|
||||
unusedKey: string,
|
||||
details?: Partial<DeprecatedConfigDetails>
|
||||
): ConfigDeprecation => (config, rootPath, addDeprecation) =>
|
||||
_unused(config, '', addDeprecation, unusedKey, details);
|
||||
|
||||
const getPath = (rootPath: string, subPath: string) =>
|
||||
rootPath !== '' ? `${rootPath}.${subPath}` : subPath;
|
||||
|
|
|
@ -6,12 +6,13 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export {
|
||||
export type {
|
||||
ConfigDeprecation,
|
||||
ConfigDeprecationWithContext,
|
||||
ConfigDeprecationLogger,
|
||||
ConfigDeprecationFactory,
|
||||
AddConfigDeprecation,
|
||||
ConfigDeprecationProvider,
|
||||
DeprecatedConfigDetails,
|
||||
} from './types';
|
||||
export { configDeprecationFactory } from './deprecation_factory';
|
||||
export { applyDeprecations } from './apply_deprecations';
|
||||
|
|
|
@ -7,11 +7,33 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Logger interface used when invoking a {@link ConfigDeprecation}
|
||||
* Config deprecation hook used when invoking a {@link ConfigDeprecation}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type ConfigDeprecationLogger = (message: string) => void;
|
||||
export type AddConfigDeprecation = (details: DeprecatedConfigDetails) => void;
|
||||
|
||||
/**
|
||||
* Deprecated Config Details
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface DeprecatedConfigDetails {
|
||||
/* The message to be displayed for the deprecation. */
|
||||
message: string;
|
||||
/* (optional) set false to prevent the config service from logging the deprecation message. */
|
||||
silent?: boolean;
|
||||
/* (optional) link to the documentation for more details on the deprecation. */
|
||||
documentationUrl?: string;
|
||||
/* (optional) corrective action needed to fix this deprecation. */
|
||||
correctiveActions?: {
|
||||
/**
|
||||
* Specify a list of manual steps our users need to follow
|
||||
* to fix the deprecation before upgrade.
|
||||
*/
|
||||
manualSteps: string[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration deprecation returned from {@link ConfigDeprecationProvider} that handles a single deprecation from the configuration.
|
||||
|
@ -25,7 +47,7 @@ export type ConfigDeprecationLogger = (message: string) => void;
|
|||
export type ConfigDeprecation = (
|
||||
config: Record<string, any>,
|
||||
fromPath: string,
|
||||
logger: ConfigDeprecationLogger
|
||||
addDeprecation: AddConfigDeprecation
|
||||
) => Record<string, any>;
|
||||
|
||||
/**
|
||||
|
@ -62,6 +84,7 @@ export type ConfigDeprecationProvider = (factory: ConfigDeprecationFactory) => C
|
|||
*
|
||||
* @public
|
||||
*/
|
||||
|
||||
export interface ConfigDeprecationFactory {
|
||||
/**
|
||||
* Rename a configuration property from inside a plugin's configuration path.
|
||||
|
@ -75,7 +98,11 @@ export interface ConfigDeprecationFactory {
|
|||
* ]
|
||||
* ```
|
||||
*/
|
||||
rename(oldKey: string, newKey: string): ConfigDeprecation;
|
||||
rename(
|
||||
oldKey: string,
|
||||
newKey: string,
|
||||
details?: Partial<DeprecatedConfigDetails>
|
||||
): ConfigDeprecation;
|
||||
/**
|
||||
* Rename a configuration property from the root configuration.
|
||||
* Will log a deprecation warning if the oldKey was found and deprecation applied.
|
||||
|
@ -91,7 +118,11 @@ export interface ConfigDeprecationFactory {
|
|||
* ]
|
||||
* ```
|
||||
*/
|
||||
renameFromRoot(oldKey: string, newKey: string, silent?: boolean): ConfigDeprecation;
|
||||
renameFromRoot(
|
||||
oldKey: string,
|
||||
newKey: string,
|
||||
details?: Partial<DeprecatedConfigDetails>
|
||||
): ConfigDeprecation;
|
||||
/**
|
||||
* Remove a configuration property from inside a plugin's configuration path.
|
||||
* Will log a deprecation warning if the unused key was found and deprecation applied.
|
||||
|
@ -104,7 +135,7 @@ export interface ConfigDeprecationFactory {
|
|||
* ]
|
||||
* ```
|
||||
*/
|
||||
unused(unusedKey: string): ConfigDeprecation;
|
||||
unused(unusedKey: string, details?: Partial<DeprecatedConfigDetails>): ConfigDeprecation;
|
||||
/**
|
||||
* Remove a configuration property from the root configuration.
|
||||
* Will log a deprecation warning if the unused key was found and deprecation applied.
|
||||
|
@ -120,7 +151,7 @@ export interface ConfigDeprecationFactory {
|
|||
* ]
|
||||
* ```
|
||||
*/
|
||||
unusedFromRoot(unusedKey: string): ConfigDeprecation;
|
||||
unusedFromRoot(unusedKey: string, details?: Partial<DeprecatedConfigDetails>): ConfigDeprecation;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export {
|
||||
applyDeprecations,
|
||||
ConfigDeprecation,
|
||||
export type {
|
||||
ConfigDeprecationFactory,
|
||||
configDeprecationFactory,
|
||||
ConfigDeprecationLogger,
|
||||
AddConfigDeprecation,
|
||||
ConfigDeprecationProvider,
|
||||
ConfigDeprecationWithContext,
|
||||
ConfigDeprecation,
|
||||
} from './deprecation';
|
||||
|
||||
export { applyDeprecations, configDeprecationFactory } from './deprecation';
|
||||
|
||||
export {
|
||||
RawConfigurationProvider,
|
||||
RawConfigService,
|
||||
|
|
|
@ -28,6 +28,7 @@ import { DocLinksService } from './doc_links';
|
|||
import { RenderingService } from './rendering';
|
||||
import { SavedObjectsService } from './saved_objects';
|
||||
import { IntegrationsService } from './integrations';
|
||||
import { DeprecationsService } from './deprecations';
|
||||
import { CoreApp } from './core_app';
|
||||
import type { InternalApplicationSetup, InternalApplicationStart } from './application/types';
|
||||
|
||||
|
@ -82,7 +83,7 @@ export class CoreSystem {
|
|||
private readonly rendering: RenderingService;
|
||||
private readonly integrations: IntegrationsService;
|
||||
private readonly coreApp: CoreApp;
|
||||
|
||||
private readonly deprecations: DeprecationsService;
|
||||
private readonly rootDomElement: HTMLElement;
|
||||
private readonly coreContext: CoreContext;
|
||||
private fatalErrorsSetup: FatalErrorsSetup | null = null;
|
||||
|
@ -113,6 +114,7 @@ export class CoreSystem {
|
|||
this.rendering = new RenderingService();
|
||||
this.application = new ApplicationService();
|
||||
this.integrations = new IntegrationsService();
|
||||
this.deprecations = new DeprecationsService();
|
||||
|
||||
this.coreContext = { coreId: Symbol('core'), env: injectedMetadata.env };
|
||||
this.plugins = new PluginsService(this.coreContext, injectedMetadata.uiPlugins);
|
||||
|
@ -195,6 +197,7 @@ export class CoreSystem {
|
|||
injectedMetadata,
|
||||
notifications,
|
||||
});
|
||||
const deprecations = this.deprecations.start({ http });
|
||||
|
||||
this.coreApp.start({ application, http, notifications, uiSettings });
|
||||
|
||||
|
@ -210,6 +213,7 @@ export class CoreSystem {
|
|||
overlays,
|
||||
uiSettings,
|
||||
fatalErrors,
|
||||
deprecations,
|
||||
};
|
||||
|
||||
await this.plugins.start(core);
|
||||
|
@ -252,6 +256,7 @@ export class CoreSystem {
|
|||
this.chrome.stop();
|
||||
this.i18n.stop();
|
||||
this.application.stop();
|
||||
this.deprecations.stop();
|
||||
this.rootDomElement.textContent = '';
|
||||
}
|
||||
}
|
||||
|
|
187
src/core/public/deprecations/deprecations_client.test.ts
Normal file
187
src/core/public/deprecations/deprecations_client.test.ts
Normal file
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { httpServiceMock } from '../http/http_service.mock';
|
||||
import { DeprecationsClient } from './deprecations_client';
|
||||
import type { DomainDeprecationDetails } from '../../server/types';
|
||||
|
||||
describe('DeprecationsClient', () => {
|
||||
const http = httpServiceMock.createSetupContract();
|
||||
const mockDeprecations = [
|
||||
{ domainId: 'testPluginId-1' },
|
||||
{ domainId: 'testPluginId-1' },
|
||||
{ domainId: 'testPluginId-2' },
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
http.fetch.mockReset();
|
||||
http.fetch.mockResolvedValue({ deprecations: mockDeprecations });
|
||||
});
|
||||
|
||||
describe('getAllDeprecations', () => {
|
||||
it('returns a list of deprecations', async () => {
|
||||
const deprecationsClient = new DeprecationsClient({ http });
|
||||
const deprecations = await deprecationsClient.getAllDeprecations();
|
||||
expect(http.fetch).toBeCalledTimes(1);
|
||||
expect(http.fetch).toBeCalledWith('/api/deprecations/', {
|
||||
asSystemRequest: true,
|
||||
});
|
||||
|
||||
expect(deprecations).toEqual(mockDeprecations);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDeprecations', () => {
|
||||
it('returns deprecations for a single domainId', async () => {
|
||||
const deprecationsClient = new DeprecationsClient({ http });
|
||||
const deprecations = await deprecationsClient.getDeprecations('testPluginId-1');
|
||||
|
||||
expect(deprecations.length).toBe(2);
|
||||
expect(deprecations).toEqual([
|
||||
{ domainId: 'testPluginId-1' },
|
||||
{ domainId: 'testPluginId-1' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns [] if the domainId does not have any deprecations', async () => {
|
||||
const deprecationsClient = new DeprecationsClient({ http });
|
||||
const deprecations = await deprecationsClient.getDeprecations('testPluginId-4');
|
||||
|
||||
expect(deprecations).toEqual([]);
|
||||
});
|
||||
|
||||
it('calls the fetch api', async () => {
|
||||
const deprecationsClient = new DeprecationsClient({ http });
|
||||
http.fetch.mockResolvedValueOnce({
|
||||
deprecations: [{ domainId: 'testPluginId-1' }, { domainId: 'testPluginId-1' }],
|
||||
});
|
||||
http.fetch.mockResolvedValueOnce({
|
||||
deprecations: [{ domainId: 'testPluginId-2' }, { domainId: 'testPluginId-2' }],
|
||||
});
|
||||
const results = [
|
||||
...(await deprecationsClient.getDeprecations('testPluginId-1')),
|
||||
...(await deprecationsClient.getDeprecations('testPluginId-2')),
|
||||
];
|
||||
|
||||
expect(http.fetch).toBeCalledTimes(2);
|
||||
expect(results).toEqual([
|
||||
{ domainId: 'testPluginId-1' },
|
||||
{ domainId: 'testPluginId-1' },
|
||||
{ domainId: 'testPluginId-2' },
|
||||
{ domainId: 'testPluginId-2' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isDeprecationResolvable', () => {
|
||||
it('returns true if deprecation has correctiveActions.api', async () => {
|
||||
const deprecationsClient = new DeprecationsClient({ http });
|
||||
const mockDeprecationDetails: DomainDeprecationDetails = {
|
||||
domainId: 'testPluginId-1',
|
||||
message: 'some-message',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
api: {
|
||||
path: 'some-path',
|
||||
method: 'POST',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const isResolvable = deprecationsClient.isDeprecationResolvable(mockDeprecationDetails);
|
||||
|
||||
expect(isResolvable).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false if deprecation is missing correctiveActions.api', async () => {
|
||||
const deprecationsClient = new DeprecationsClient({ http });
|
||||
const mockDeprecationDetails: DomainDeprecationDetails = {
|
||||
domainId: 'testPluginId-1',
|
||||
message: 'some-message',
|
||||
level: 'warning',
|
||||
correctiveActions: {},
|
||||
};
|
||||
|
||||
const isResolvable = deprecationsClient.isDeprecationResolvable(mockDeprecationDetails);
|
||||
|
||||
expect(isResolvable).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveDeprecation', () => {
|
||||
it('fails if deprecation is not resolvable', async () => {
|
||||
const deprecationsClient = new DeprecationsClient({ http });
|
||||
const mockDeprecationDetails: DomainDeprecationDetails = {
|
||||
domainId: 'testPluginId-1',
|
||||
message: 'some-message',
|
||||
level: 'warning',
|
||||
correctiveActions: {},
|
||||
};
|
||||
const result = await deprecationsClient.resolveDeprecation(mockDeprecationDetails);
|
||||
|
||||
expect(result).toEqual({
|
||||
status: 'fail',
|
||||
reason: 'deprecation has no correctiveAction via api.',
|
||||
});
|
||||
});
|
||||
|
||||
it('fetches the deprecation api', async () => {
|
||||
const deprecationsClient = new DeprecationsClient({ http });
|
||||
const mockDeprecationDetails: DomainDeprecationDetails = {
|
||||
domainId: 'testPluginId-1',
|
||||
message: 'some-message',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
api: {
|
||||
path: 'some-path',
|
||||
method: 'POST',
|
||||
body: {
|
||||
extra_param: 123,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = await deprecationsClient.resolveDeprecation(mockDeprecationDetails);
|
||||
|
||||
expect(http.fetch).toBeCalledTimes(1);
|
||||
expect(http.fetch).toBeCalledWith({
|
||||
path: 'some-path',
|
||||
method: 'POST',
|
||||
asSystemRequest: true,
|
||||
body: JSON.stringify({
|
||||
extra_param: 123,
|
||||
deprecationDetails: { domainId: 'testPluginId-1' },
|
||||
}),
|
||||
});
|
||||
expect(result).toEqual({ status: 'ok' });
|
||||
});
|
||||
|
||||
it('fails when fetch fails', async () => {
|
||||
const deprecationsClient = new DeprecationsClient({ http });
|
||||
const mockResponse = 'Failed to fetch';
|
||||
const mockDeprecationDetails: DomainDeprecationDetails = {
|
||||
domainId: 'testPluginId-1',
|
||||
message: 'some-message',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
api: {
|
||||
path: 'some-path',
|
||||
method: 'POST',
|
||||
body: {
|
||||
extra_param: 123,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
http.fetch.mockRejectedValue({ body: { message: mockResponse } });
|
||||
const result = await deprecationsClient.resolveDeprecation(mockDeprecationDetails);
|
||||
|
||||
expect(result).toEqual({ status: 'fail', reason: mockResponse });
|
||||
});
|
||||
});
|
||||
});
|
78
src/core/public/deprecations/deprecations_client.ts
Normal file
78
src/core/public/deprecations/deprecations_client.ts
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { HttpStart } from '../http';
|
||||
import type { DomainDeprecationDetails, DeprecationsGetResponse } from '../../server/types';
|
||||
|
||||
/* @internal */
|
||||
export interface DeprecationsClientDeps {
|
||||
http: Pick<HttpStart, 'fetch'>;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export type ResolveDeprecationResponse = { status: 'ok' } | { status: 'fail'; reason: string };
|
||||
|
||||
export class DeprecationsClient {
|
||||
private readonly http: Pick<HttpStart, 'fetch'>;
|
||||
constructor({ http }: DeprecationsClientDeps) {
|
||||
this.http = http;
|
||||
}
|
||||
|
||||
private fetchDeprecations = async (): Promise<DomainDeprecationDetails[]> => {
|
||||
const { deprecations } = await this.http.fetch<DeprecationsGetResponse>('/api/deprecations/', {
|
||||
asSystemRequest: true,
|
||||
});
|
||||
|
||||
return deprecations;
|
||||
};
|
||||
|
||||
public getAllDeprecations = async () => {
|
||||
return await this.fetchDeprecations();
|
||||
};
|
||||
|
||||
public getDeprecations = async (domainId: string) => {
|
||||
const deprecations = await this.fetchDeprecations();
|
||||
return deprecations.filter((deprecation) => deprecation.domainId === domainId);
|
||||
};
|
||||
|
||||
public isDeprecationResolvable = (details: DomainDeprecationDetails) => {
|
||||
return typeof details.correctiveActions.api === 'object';
|
||||
};
|
||||
|
||||
public resolveDeprecation = async (
|
||||
details: DomainDeprecationDetails
|
||||
): Promise<ResolveDeprecationResponse> => {
|
||||
const { domainId, correctiveActions } = details;
|
||||
// explicit check required for TS type guard
|
||||
if (typeof correctiveActions.api !== 'object') {
|
||||
return {
|
||||
status: 'fail',
|
||||
reason: 'deprecation has no correctiveAction via api.',
|
||||
};
|
||||
}
|
||||
|
||||
const { body, method, path } = correctiveActions.api;
|
||||
try {
|
||||
await this.http.fetch<void>({
|
||||
path,
|
||||
method,
|
||||
asSystemRequest: true,
|
||||
body: JSON.stringify({
|
||||
...body,
|
||||
deprecationDetails: { domainId },
|
||||
}),
|
||||
});
|
||||
return { status: 'ok' };
|
||||
} catch (err) {
|
||||
return {
|
||||
status: 'fail',
|
||||
reason: err.body.message,
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
36
src/core/public/deprecations/deprecations_service.mock.ts
Normal file
36
src/core/public/deprecations/deprecations_service.mock.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { PublicMethodsOf } from '@kbn/utility-types';
|
||||
import { DeprecationsService } from './deprecations_service';
|
||||
import type { DeprecationsServiceStart } from './deprecations_service';
|
||||
|
||||
const createServiceMock = (): jest.Mocked<DeprecationsServiceStart> => ({
|
||||
getAllDeprecations: jest.fn().mockResolvedValue([]),
|
||||
getDeprecations: jest.fn().mockResolvedValue([]),
|
||||
isDeprecationResolvable: jest.fn().mockReturnValue(false),
|
||||
resolveDeprecation: jest.fn().mockResolvedValue({ status: 'ok', payload: {} }),
|
||||
});
|
||||
|
||||
const createMock = () => {
|
||||
const mocked: jest.Mocked<PublicMethodsOf<DeprecationsService>> = {
|
||||
setup: jest.fn(),
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
};
|
||||
|
||||
mocked.setup.mockReturnValue(void 0);
|
||||
mocked.start.mockReturnValue(createServiceMock());
|
||||
return mocked;
|
||||
};
|
||||
|
||||
export const deprecationsServiceMock = {
|
||||
create: createMock,
|
||||
createSetupContract: () => void 0,
|
||||
createStartContract: createServiceMock,
|
||||
};
|
60
src/core/public/deprecations/deprecations_service.ts
Normal file
60
src/core/public/deprecations/deprecations_service.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { CoreService } from '../../types';
|
||||
import type { HttpStart } from '../http';
|
||||
import { DeprecationsClient, ResolveDeprecationResponse } from './deprecations_client';
|
||||
import type { DomainDeprecationDetails } from '../../server/types';
|
||||
|
||||
/**
|
||||
* DeprecationsService provides methods to fetch domain deprecation details from
|
||||
* the Kibana server.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface DeprecationsServiceStart {
|
||||
/**
|
||||
* Grabs deprecations details for all domains.
|
||||
*/
|
||||
getAllDeprecations: () => Promise<DomainDeprecationDetails[]>;
|
||||
/**
|
||||
* Grabs deprecations for a specific domain.
|
||||
*
|
||||
* @param {string} domainId
|
||||
*/
|
||||
getDeprecations: (domainId: string) => Promise<DomainDeprecationDetails[]>;
|
||||
/**
|
||||
* Returns a boolean if the provided deprecation can be automatically resolvable.
|
||||
*
|
||||
* @param {DomainDeprecationDetails} details
|
||||
*/
|
||||
isDeprecationResolvable: (details: DomainDeprecationDetails) => boolean;
|
||||
/**
|
||||
* Calls the correctiveActions.api to automatically resolve the depprecation.
|
||||
*
|
||||
* @param {DomainDeprecationDetails} details
|
||||
*/
|
||||
resolveDeprecation: (details: DomainDeprecationDetails) => Promise<ResolveDeprecationResponse>;
|
||||
}
|
||||
|
||||
export class DeprecationsService implements CoreService<void, DeprecationsServiceStart> {
|
||||
public setup(): void {}
|
||||
|
||||
public start({ http }: { http: HttpStart }): DeprecationsServiceStart {
|
||||
const deprecationsClient = new DeprecationsClient({ http });
|
||||
|
||||
return {
|
||||
getAllDeprecations: deprecationsClient.getAllDeprecations,
|
||||
getDeprecations: deprecationsClient.getDeprecations,
|
||||
isDeprecationResolvable: deprecationsClient.isDeprecationResolvable,
|
||||
resolveDeprecation: deprecationsClient.resolveDeprecation,
|
||||
};
|
||||
}
|
||||
|
||||
public stop(): void {}
|
||||
}
|
11
src/core/public/deprecations/index.ts
Normal file
11
src/core/public/deprecations/index.ts
Normal file
|
@ -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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export { DeprecationsService } from './deprecations_service';
|
||||
export type { DeprecationsServiceStart } from './deprecations_service';
|
||||
export type { ResolveDeprecationResponse } from './deprecations_client';
|
|
@ -65,6 +65,7 @@ import { UiSettingsState, IUiSettingsClient } from './ui_settings';
|
|||
import { ApplicationSetup, Capabilities, ApplicationStart } from './application';
|
||||
import { DocLinksStart } from './doc_links';
|
||||
import { SavedObjectsStart } from './saved_objects';
|
||||
import { DeprecationsServiceStart } from './deprecations';
|
||||
|
||||
export type { PackageInfo, EnvironmentMode, IExternalUrlPolicy } from '../server/types';
|
||||
export type { CoreContext, CoreSystem } from './core_system';
|
||||
|
@ -184,6 +185,8 @@ export type {
|
|||
ErrorToastOptions,
|
||||
} from './notifications';
|
||||
|
||||
export type { DeprecationsServiceStart, ResolveDeprecationResponse } from './deprecations';
|
||||
|
||||
export type { MountPoint, UnmountCallback, PublicUiSettingsParams } from './types';
|
||||
|
||||
export { URL_MAX_LENGTH } from './core_app';
|
||||
|
@ -268,6 +271,8 @@ export interface CoreStart {
|
|||
uiSettings: IUiSettingsClient;
|
||||
/** {@link FatalErrorsStart} */
|
||||
fatalErrors: FatalErrorsStart;
|
||||
/** {@link DeprecationsServiceStart} */
|
||||
deprecations: DeprecationsServiceStart;
|
||||
/**
|
||||
* exposed temporarily until https://github.com/elastic/kibana/issues/41990 done
|
||||
* use *only* to retrieve config values. There is no way to set injected values
|
||||
|
|
|
@ -24,6 +24,7 @@ import { overlayServiceMock } from './overlays/overlay_service.mock';
|
|||
import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock';
|
||||
import { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock';
|
||||
import { injectedMetadataServiceMock } from './injected_metadata/injected_metadata_service.mock';
|
||||
import { deprecationsServiceMock } from './deprecations/deprecations_service.mock';
|
||||
|
||||
export { chromeServiceMock } from './chrome/chrome_service.mock';
|
||||
export { docLinksServiceMock } from './doc_links/doc_links_service.mock';
|
||||
|
@ -37,6 +38,7 @@ export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock';
|
|||
export { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock';
|
||||
export { scopedHistoryMock } from './application/scoped_history.mock';
|
||||
export { applicationServiceMock } from './application/application_service.mock';
|
||||
export { deprecationsServiceMock } from './deprecations/deprecations_service.mock';
|
||||
|
||||
function createCoreSetupMock({
|
||||
basePath = '',
|
||||
|
@ -57,6 +59,7 @@ function createCoreSetupMock({
|
|||
http: httpServiceMock.createSetupContract({ basePath }),
|
||||
notifications: notificationServiceMock.createSetupContract(),
|
||||
uiSettings: uiSettingsServiceMock.createSetupContract(),
|
||||
deprecations: deprecationsServiceMock.createSetupContract(),
|
||||
injectedMetadata: {
|
||||
getInjectedVar: injectedMetadataServiceMock.createSetupContract().getInjectedVar,
|
||||
},
|
||||
|
@ -76,6 +79,7 @@ function createCoreStartMock({ basePath = '' } = {}) {
|
|||
overlays: overlayServiceMock.createStartContract(),
|
||||
uiSettings: uiSettingsServiceMock.createStartContract(),
|
||||
savedObjects: savedObjectsServiceMock.createStartContract(),
|
||||
deprecations: deprecationsServiceMock.createStartContract(),
|
||||
injectedMetadata: {
|
||||
getInjectedVar: injectedMetadataServiceMock.createStartContract().getInjectedVar,
|
||||
},
|
||||
|
|
|
@ -139,5 +139,6 @@ export function createPluginStartContext<
|
|||
getInjectedVar: deps.injectedMetadata.getInjectedVar,
|
||||
},
|
||||
fatalErrors: deps.fatalErrors,
|
||||
deprecations: deps.deprecations,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import { httpServiceMock } from '../http/http_service.mock';
|
|||
import { CoreSetup, CoreStart, PluginInitializerContext } from '..';
|
||||
import { docLinksServiceMock } from '../doc_links/doc_links_service.mock';
|
||||
import { savedObjectsServiceMock } from '../saved_objects/saved_objects_service.mock';
|
||||
import { deprecationsServiceMock } from '../deprecations/deprecations_service.mock';
|
||||
|
||||
export let mockPluginInitializers: Map<PluginName, MockedPluginInitializer>;
|
||||
|
||||
|
@ -101,6 +102,7 @@ describe('PluginsService', () => {
|
|||
uiSettings: uiSettingsServiceMock.createStartContract(),
|
||||
savedObjects: savedObjectsServiceMock.createStartContract(),
|
||||
fatalErrors: fatalErrorsServiceMock.createStartContract(),
|
||||
deprecations: deprecationsServiceMock.createStartContract(),
|
||||
};
|
||||
mockStartContext = {
|
||||
...mockStartDeps,
|
||||
|
|
|
@ -432,6 +432,8 @@ export interface CoreStart {
|
|||
// (undocumented)
|
||||
chrome: ChromeStart;
|
||||
// (undocumented)
|
||||
deprecations: DeprecationsServiceStart;
|
||||
// (undocumented)
|
||||
docLinks: DocLinksStart;
|
||||
// (undocumented)
|
||||
fatalErrors: FatalErrorsStart;
|
||||
|
@ -472,6 +474,15 @@ export class CoreSystem {
|
|||
// @internal (undocumented)
|
||||
export const DEFAULT_APP_CATEGORIES: Record<string, AppCategory>;
|
||||
|
||||
// @public
|
||||
export interface DeprecationsServiceStart {
|
||||
// Warning: (ae-forgotten-export) The symbol "DomainDeprecationDetails" needs to be exported by the entry point index.d.ts
|
||||
getAllDeprecations: () => Promise<DomainDeprecationDetails[]>;
|
||||
getDeprecations: (domainId: string) => Promise<DomainDeprecationDetails[]>;
|
||||
isDeprecationResolvable: (details: DomainDeprecationDetails) => boolean;
|
||||
resolveDeprecation: (details: DomainDeprecationDetails) => Promise<ResolveDeprecationResponse>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocLinksStart {
|
||||
// (undocumented)
|
||||
|
@ -1075,6 +1086,16 @@ export type PublicAppSearchDeepLinkInfo = Omit<AppSearchDeepLink, 'searchDeepLin
|
|||
// @public
|
||||
export type PublicUiSettingsParams = Omit<UiSettingsParams, 'schema'>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ResolveDeprecationResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type ResolveDeprecationResponse = {
|
||||
status: 'ok';
|
||||
} | {
|
||||
status: 'fail';
|
||||
reason: string;
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "SavedObject" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
|
@ -1586,6 +1607,6 @@ export interface UserProvidedValues<T = any> {
|
|||
|
||||
// Warnings were encountered during analysis:
|
||||
//
|
||||
// src/core/public/core_system.ts:164:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts
|
||||
// src/core/public/core_system.ts:166:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts
|
||||
|
||||
```
|
||||
|
|
|
@ -20,7 +20,7 @@ const applyCoreDeprecations = (settings: Record<string, any> = {}) => {
|
|||
deprecation,
|
||||
path: '',
|
||||
})),
|
||||
(msg) => deprecationMessages.push(msg)
|
||||
() => ({ message }) => deprecationMessages.push(message)
|
||||
);
|
||||
return {
|
||||
messages: deprecationMessages,
|
||||
|
@ -305,7 +305,7 @@ describe('core deprecations', () => {
|
|||
});
|
||||
expect(messages).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"logging.dest\\" has been deprecated and will be removed in 8.0. To set the destination moving forward, you can use the \\"console\\" appender in your logging configuration or define a custom one. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx.",
|
||||
"\\"logging.dest\\" has been deprecated and will be removed in 8.0. To set the destination moving forward, you can use the \\"console\\" appender in your logging configuration or define a custom one. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -315,7 +315,7 @@ describe('core deprecations', () => {
|
|||
});
|
||||
expect(messages).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"logging.dest\\" has been deprecated and will be removed in 8.0. To set the destination moving forward, you can use the \\"console\\" appender in your logging configuration or define a custom one. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx.",
|
||||
"\\"logging.dest\\" has been deprecated and will be removed in 8.0. To set the destination moving forward, you can use the \\"console\\" appender in your logging configuration or define a custom one. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -361,7 +361,7 @@ describe('core deprecations', () => {
|
|||
});
|
||||
expect(messages).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"logging.json\\" has been deprecated and will be removed in 8.0. To specify log message format moving forward, you can configure the \\"appender.layout\\" property for every custom appender in your logging configuration. There is currently no default layout for custom appenders and each one must be declared explicitly. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx.",
|
||||
"\\"logging.json\\" has been deprecated and will be removed in 8.0. To specify log message format moving forward, you can configure the \\"appender.layout\\" property for every custom appender in your logging configuration. There is currently no default layout for custom appenders and each one must be declared explicitly. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -446,7 +446,7 @@ describe('core deprecations', () => {
|
|||
});
|
||||
expect(messages).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"logging.filter\\" has been deprecated and will be removed in 8.0. ",
|
||||
"\\"logging.filter\\" has been deprecated and will be removed in 8.0.",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -457,7 +457,7 @@ describe('core deprecations', () => {
|
|||
});
|
||||
expect(messages).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"logging.filter\\" has been deprecated and will be removed in 8.0. ",
|
||||
"\\"logging.filter\\" has been deprecated and will be removed in 8.0.",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
|
|
@ -9,40 +9,43 @@
|
|||
import { has, get } from 'lodash';
|
||||
import { ConfigDeprecationProvider, ConfigDeprecation } from '@kbn/config';
|
||||
|
||||
const configPathDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const configPathDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(process.env, 'CONFIG_PATH')) {
|
||||
log(
|
||||
`Environment variable CONFIG_PATH is deprecated. It has been replaced with KBN_PATH_CONF pointing to a config folder`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Environment variable CONFIG_PATH is deprecated. It has been replaced with KBN_PATH_CONF pointing to a config folder`,
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const dataPathDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const dataPathDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(process.env, 'DATA_PATH')) {
|
||||
log(
|
||||
`Environment variable "DATA_PATH" will be removed. It has been replaced with kibana.yml setting "path.data"`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Environment variable "DATA_PATH" will be removed. It has been replaced with kibana.yml setting "path.data"`,
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const rewriteBasePathDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const rewriteBasePathDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(settings, 'server.basePath') && !has(settings, 'server.rewriteBasePath')) {
|
||||
log(
|
||||
'You should set server.basePath along with server.rewriteBasePath. Starting in 7.0, Kibana ' +
|
||||
addDeprecation({
|
||||
message:
|
||||
'You should set server.basePath along with server.rewriteBasePath. Starting in 7.0, Kibana ' +
|
||||
'will expect that all requests start with server.basePath rather than expecting you to rewrite ' +
|
||||
'the requests in your reverse proxy. Set server.rewriteBasePath to false to preserve the ' +
|
||||
'current behavior and silence this warning.'
|
||||
);
|
||||
'current behavior and silence this warning.',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const rewriteCorsSettings: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const rewriteCorsSettings: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
const corsSettings = get(settings, 'server.cors');
|
||||
if (typeof get(settings, 'server.cors') === 'boolean') {
|
||||
log('"server.cors" is deprecated and has been replaced by "server.cors.enabled"');
|
||||
addDeprecation({
|
||||
message: '"server.cors" is deprecated and has been replaced by "server.cors.enabled"',
|
||||
});
|
||||
settings.server.cors = {
|
||||
enabled: corsSettings,
|
||||
};
|
||||
|
@ -50,7 +53,7 @@ const rewriteCorsSettings: ConfigDeprecation = (settings, fromPath, log) => {
|
|||
return settings;
|
||||
};
|
||||
|
||||
const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
const NONCE_STRING = `{nonce}`;
|
||||
// Policies that should include the 'self' source
|
||||
const SELF_POLICIES = Object.freeze(['script-src', 'style-src']);
|
||||
|
@ -67,7 +70,9 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
|||
|
||||
settings.csp.rules = [...parsed].map(([policy, sourceList]) => {
|
||||
if (sourceList.find((source) => source.includes(NONCE_STRING))) {
|
||||
log(`csp.rules no longer supports the {nonce} syntax. Replacing with 'self' in ${policy}`);
|
||||
addDeprecation({
|
||||
message: `csp.rules no longer supports the {nonce} syntax. Replacing with 'self' in ${policy}`,
|
||||
});
|
||||
sourceList = sourceList.filter((source) => !source.includes(NONCE_STRING));
|
||||
|
||||
// Add 'self' if not present
|
||||
|
@ -80,7 +85,9 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
|||
SELF_POLICIES.includes(policy) &&
|
||||
!sourceList.find((source) => source.includes(SELF_STRING))
|
||||
) {
|
||||
log(`csp.rules must contain the 'self' source. Automatically adding to ${policy}.`);
|
||||
addDeprecation({
|
||||
message: `csp.rules must contain the 'self' source. Automatically adding to ${policy}.`,
|
||||
});
|
||||
sourceList.push(SELF_STRING);
|
||||
}
|
||||
|
||||
|
@ -91,149 +98,191 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
|||
return settings;
|
||||
};
|
||||
|
||||
const mapManifestServiceUrlDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const mapManifestServiceUrlDeprecation: ConfigDeprecation = (
|
||||
settings,
|
||||
fromPath,
|
||||
addDeprecation
|
||||
) => {
|
||||
if (has(settings, 'map.manifestServiceUrl')) {
|
||||
log(
|
||||
'You should no longer use the map.manifestServiceUrl setting in kibana.yml to configure the location ' +
|
||||
addDeprecation({
|
||||
message:
|
||||
'You should no longer use the map.manifestServiceUrl setting in kibana.yml to configure the location ' +
|
||||
'of the Elastic Maps Service settings. These settings have moved to the "map.emsTileApiUrl" and ' +
|
||||
'"map.emsFileApiUrl" settings instead. These settings are for development use only and should not be ' +
|
||||
'modified for use in production environments.'
|
||||
);
|
||||
'modified for use in production environments.',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const opsLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const opsLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(settings, 'logging.events.ops')) {
|
||||
log(
|
||||
'"logging.events.ops" has been deprecated and will be removed ' +
|
||||
addDeprecation({
|
||||
documentationUrl:
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents',
|
||||
message:
|
||||
'"logging.events.ops" has been deprecated and will be removed ' +
|
||||
'in 8.0. To access ops data moving forward, please enable debug logs for the ' +
|
||||
'"metrics.ops" context in your logging configuration. For more details, see ' +
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx'
|
||||
);
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const requestLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const requestLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(settings, 'logging.events.request') || has(settings, 'logging.events.response')) {
|
||||
log(
|
||||
'"logging.events.request" and "logging.events.response" have been deprecated and will be removed ' +
|
||||
addDeprecation({
|
||||
documentationUrl:
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents',
|
||||
message:
|
||||
'"logging.events.request" and "logging.events.response" have been deprecated and will be removed ' +
|
||||
'in 8.0. To access request and/or response data moving forward, please enable debug logs for the ' +
|
||||
'"http.server.response" context in your logging configuration. For more details, see ' +
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx'
|
||||
);
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const timezoneLoggingDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const timezoneLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(settings, 'logging.timezone')) {
|
||||
log(
|
||||
'"logging.timezone" has been deprecated and will be removed ' +
|
||||
addDeprecation({
|
||||
documentationUrl:
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingtimezone',
|
||||
message:
|
||||
'"logging.timezone" has been deprecated and will be removed ' +
|
||||
'in 8.0. To set the timezone moving forward, please add a timezone date modifier to the log pattern ' +
|
||||
'in your logging configuration. For more details, see ' +
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx'
|
||||
);
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const destLoggingDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const destLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(settings, 'logging.dest')) {
|
||||
log(
|
||||
'"logging.dest" has been deprecated and will be removed ' +
|
||||
addDeprecation({
|
||||
documentationUrl:
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingdest',
|
||||
message:
|
||||
'"logging.dest" has been deprecated and will be removed ' +
|
||||
'in 8.0. To set the destination moving forward, you can use the "console" appender ' +
|
||||
'in your logging configuration or define a custom one. For more details, see ' +
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx.'
|
||||
);
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const quietLoggingDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const quietLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(settings, 'logging.quiet')) {
|
||||
log(
|
||||
'"logging.quiet" has been deprecated and will be removed ' +
|
||||
'in 8.0. Moving forward, you can use "logging.root.level:error" in your logging configuration. '
|
||||
);
|
||||
addDeprecation({
|
||||
documentationUrl:
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingquiet',
|
||||
message:
|
||||
'"logging.quiet" has been deprecated and will be removed ' +
|
||||
'in 8.0. Moving forward, you can use "logging.root.level:error" in your logging configuration. ',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const silentLoggingDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const silentLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(settings, 'logging.silent')) {
|
||||
log(
|
||||
'"logging.silent" has been deprecated and will be removed ' +
|
||||
'in 8.0. Moving forward, you can use "logging.root.level:off" in your logging configuration. '
|
||||
);
|
||||
addDeprecation({
|
||||
documentationUrl:
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingsilent',
|
||||
message:
|
||||
'"logging.silent" has been deprecated and will be removed ' +
|
||||
'in 8.0. Moving forward, you can use "logging.root.level:off" in your logging configuration. ',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const verboseLoggingDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const verboseLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(settings, 'logging.verbose')) {
|
||||
log(
|
||||
'"logging.verbose" has been deprecated and will be removed ' +
|
||||
'in 8.0. Moving forward, you can use "logging.root.level:all" in your logging configuration. '
|
||||
);
|
||||
addDeprecation({
|
||||
documentationUrl:
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingverbose',
|
||||
message:
|
||||
'"logging.verbose" has been deprecated and will be removed ' +
|
||||
'in 8.0. Moving forward, you can use "logging.root.level:all" in your logging configuration. ',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const jsonLoggingDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const jsonLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
// We silence the deprecation warning when running in development mode because
|
||||
// the dev CLI code in src/dev/cli_dev_mode/using_server_process.ts manually
|
||||
// specifies `--logging.json=false`. Since it's executed in a child process, the
|
||||
// ` legacyLoggingConfigSchema` returns `true` for the TTY check on `process.stdout.isTTY`
|
||||
if (has(settings, 'logging.json') && settings.env !== 'development') {
|
||||
log(
|
||||
'"logging.json" has been deprecated and will be removed ' +
|
||||
addDeprecation({
|
||||
documentationUrl:
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx',
|
||||
message:
|
||||
'"logging.json" has been deprecated and will be removed ' +
|
||||
'in 8.0. To specify log message format moving forward, ' +
|
||||
'you can configure the "appender.layout" property for every custom appender in your logging configuration. ' +
|
||||
'There is currently no default layout for custom appenders and each one must be declared explicitly. ' +
|
||||
'For more details, see ' +
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx.'
|
||||
);
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const logRotateDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const logRotateDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(settings, 'logging.rotate')) {
|
||||
log(
|
||||
'"logging.rotate" and sub-options have been deprecated and will be removed in 8.0. ' +
|
||||
addDeprecation({
|
||||
documentationUrl:
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#rolling-file-appender',
|
||||
message:
|
||||
'"logging.rotate" and sub-options have been deprecated and will be removed in 8.0. ' +
|
||||
'Moving forward, you can enable log rotation using the "rolling-file" appender for a logger ' +
|
||||
'in your logging configuration. For more details, see ' +
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#rolling-file-appender'
|
||||
);
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#rolling-file-appender',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const logEventsLogDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const logEventsLogDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(settings, 'logging.events.log')) {
|
||||
log(
|
||||
'"logging.events.log" has been deprecated and will be removed ' +
|
||||
'in 8.0. Moving forward, log levels can be customized on a per-logger basis using the new logging configuration. '
|
||||
);
|
||||
addDeprecation({
|
||||
documentationUrl:
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents',
|
||||
message:
|
||||
'"logging.events.log" has been deprecated and will be removed ' +
|
||||
'in 8.0. Moving forward, log levels can be customized on a per-logger basis using the new logging configuration. ',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const logEventsErrorDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const logEventsErrorDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(settings, 'logging.events.error')) {
|
||||
log(
|
||||
'"logging.events.error" has been deprecated and will be removed ' +
|
||||
'in 8.0. Moving forward, you can use "logging.root.level: error" in your logging configuration. '
|
||||
);
|
||||
addDeprecation({
|
||||
documentationUrl:
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents',
|
||||
message:
|
||||
'"logging.events.error" has been deprecated and will be removed ' +
|
||||
'in 8.0. Moving forward, you can use "logging.root.level: error" in your logging configuration. ',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
const logFilterDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
|
||||
const logFilterDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (has(settings, 'logging.filter')) {
|
||||
log('"logging.filter" has been deprecated and will be removed ' + 'in 8.0. ');
|
||||
addDeprecation({
|
||||
documentationUrl:
|
||||
'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingfilter',
|
||||
message: '"logging.filter" has been deprecated and will be removed in 8.0.',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
|
|
@ -24,7 +24,7 @@ export type {
|
|||
ConfigPath,
|
||||
CliArgs,
|
||||
ConfigDeprecation,
|
||||
ConfigDeprecationLogger,
|
||||
AddConfigDeprecation,
|
||||
ConfigDeprecationProvider,
|
||||
ConfigDeprecationFactory,
|
||||
EnvironmentMode,
|
||||
|
|
248
src/core/server/deprecations/deprecations_factory.test.ts
Normal file
248
src/core/server/deprecations/deprecations_factory.test.ts
Normal file
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { GetDeprecationsContext } from './types';
|
||||
import { DeprecationsFactory } from './deprecations_factory';
|
||||
import { loggerMock } from '../logging/logger.mock';
|
||||
|
||||
describe('DeprecationsFactory', () => {
|
||||
const logger = loggerMock.create();
|
||||
beforeEach(() => {
|
||||
loggerMock.clear(logger);
|
||||
});
|
||||
|
||||
describe('getRegistry', () => {
|
||||
const domainId = 'test-plugin';
|
||||
|
||||
it('creates a registry for a domainId', async () => {
|
||||
const deprecationsFactory = new DeprecationsFactory({ logger });
|
||||
const registry = deprecationsFactory.getRegistry(domainId);
|
||||
|
||||
expect(registry).toHaveProperty('registerDeprecations');
|
||||
expect(registry).toHaveProperty('getDeprecations');
|
||||
});
|
||||
|
||||
it('creates one registry for a domainId', async () => {
|
||||
const deprecationsFactory = new DeprecationsFactory({ logger });
|
||||
const registry = deprecationsFactory.getRegistry(domainId);
|
||||
const sameRegistry = deprecationsFactory.getRegistry(domainId);
|
||||
|
||||
expect(registry).toStrictEqual(sameRegistry);
|
||||
});
|
||||
|
||||
it('returns a registered registry', () => {
|
||||
const deprecationsFactory = new DeprecationsFactory({ logger });
|
||||
const mockRegistry = 'mock-reg';
|
||||
const mockRegistries = {
|
||||
set: jest.fn(),
|
||||
get: jest.fn().mockReturnValue(mockRegistry),
|
||||
};
|
||||
|
||||
// @ts-expect-error
|
||||
deprecationsFactory.registries = mockRegistries;
|
||||
const result = deprecationsFactory.getRegistry(domainId);
|
||||
|
||||
expect(mockRegistries.get).toBeCalledTimes(1);
|
||||
expect(mockRegistries.get).toBeCalledWith(domainId);
|
||||
expect(mockRegistries.set).toBeCalledTimes(0);
|
||||
expect(result).toStrictEqual(mockRegistry);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAllDeprecations', () => {
|
||||
const mockDependencies = ({
|
||||
esClient: jest.fn(),
|
||||
savedObjectsClient: jest.fn(),
|
||||
} as unknown) as GetDeprecationsContext;
|
||||
|
||||
it('returns a flattened array of deprecations', async () => {
|
||||
const deprecationsFactory = new DeprecationsFactory({ logger });
|
||||
const mockPluginDeprecationsInfo = [
|
||||
{
|
||||
message: 'mockPlugin message',
|
||||
level: 'critical',
|
||||
correctiveActions: {
|
||||
manualSteps: ['mockPlugin step 1', 'mockPlugin step 2'],
|
||||
},
|
||||
},
|
||||
{
|
||||
message: 'hello there!',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
manualSteps: ['mockPlugin step a', 'mockPlugin step b'],
|
||||
},
|
||||
},
|
||||
];
|
||||
const anotherMockPluginDeprecationsInfo = [
|
||||
{
|
||||
message: 'anotherMockPlugin message',
|
||||
level: 'critical',
|
||||
correctiveActions: {
|
||||
manualSteps: ['anotherMockPlugin step 1', 'anotherMockPlugin step 2'],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const mockPluginRegistry = deprecationsFactory.getRegistry('mockPlugin');
|
||||
const anotherMockPluginRegistry = deprecationsFactory.getRegistry('anotherMockPlugin');
|
||||
mockPluginRegistry.registerDeprecations({
|
||||
getDeprecations: jest.fn().mockResolvedValue(mockPluginDeprecationsInfo),
|
||||
});
|
||||
anotherMockPluginRegistry.registerDeprecations({
|
||||
getDeprecations: jest.fn().mockResolvedValue(anotherMockPluginDeprecationsInfo),
|
||||
});
|
||||
|
||||
const derpecations = await deprecationsFactory.getAllDeprecations(mockDependencies);
|
||||
expect(derpecations).toStrictEqual(
|
||||
[
|
||||
mockPluginDeprecationsInfo.map((info) => ({ ...info, domainId: 'mockPlugin' })),
|
||||
anotherMockPluginDeprecationsInfo.map((info) => ({
|
||||
...info,
|
||||
domainId: 'anotherMockPlugin',
|
||||
})),
|
||||
].flat()
|
||||
);
|
||||
});
|
||||
|
||||
it(`returns a failure message for failed getDeprecations functions`, async () => {
|
||||
const deprecationsFactory = new DeprecationsFactory({ logger });
|
||||
const domainId = 'mockPlugin';
|
||||
const mockError = new Error();
|
||||
|
||||
const deprecationsRegistry = deprecationsFactory.getRegistry(domainId);
|
||||
deprecationsRegistry.registerDeprecations({
|
||||
getDeprecations: jest.fn().mockRejectedValue(mockError),
|
||||
});
|
||||
const derpecations = await deprecationsFactory.getAllDeprecations(mockDependencies);
|
||||
expect(logger.warn).toBeCalledTimes(1);
|
||||
expect(logger.warn).toBeCalledWith(
|
||||
`Failed to get deprecations info for plugin "${domainId}".`,
|
||||
mockError
|
||||
);
|
||||
expect(derpecations).toStrictEqual([
|
||||
{
|
||||
domainId,
|
||||
message: `Failed to get deprecations info for plugin "${domainId}".`,
|
||||
level: 'fetch_error',
|
||||
correctiveActions: {
|
||||
manualSteps: ['Check Kibana server logs for error message.'],
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it(`returns successful results even when some getDeprecations fail`, async () => {
|
||||
const deprecationsFactory = new DeprecationsFactory({ logger });
|
||||
const mockPluginRegistry = deprecationsFactory.getRegistry('mockPlugin');
|
||||
const anotherMockPluginRegistry = deprecationsFactory.getRegistry('anotherMockPlugin');
|
||||
const mockError = new Error();
|
||||
const mockPluginDeprecationsInfo = [
|
||||
{
|
||||
message: 'mockPlugin message',
|
||||
level: 'critical',
|
||||
correctiveActions: {
|
||||
manualSteps: ['mockPlugin step 1', 'mockPlugin step 2'],
|
||||
},
|
||||
},
|
||||
];
|
||||
mockPluginRegistry.registerDeprecations({
|
||||
getDeprecations: jest.fn().mockResolvedValue(mockPluginDeprecationsInfo),
|
||||
});
|
||||
anotherMockPluginRegistry.registerDeprecations({
|
||||
getDeprecations: jest.fn().mockRejectedValue(mockError),
|
||||
});
|
||||
const derpecations = await deprecationsFactory.getAllDeprecations(mockDependencies);
|
||||
|
||||
expect(logger.warn).toBeCalledTimes(1);
|
||||
expect(logger.warn).toBeCalledWith(
|
||||
`Failed to get deprecations info for plugin "anotherMockPlugin".`,
|
||||
mockError
|
||||
);
|
||||
expect(derpecations).toStrictEqual([
|
||||
...mockPluginDeprecationsInfo.map((info) => ({ ...info, domainId: 'mockPlugin' })),
|
||||
{
|
||||
domainId: 'anotherMockPlugin',
|
||||
message: `Failed to get deprecations info for plugin "anotherMockPlugin".`,
|
||||
level: 'fetch_error',
|
||||
correctiveActions: {
|
||||
manualSteps: ['Check Kibana server logs for error message.'],
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDeprecations', () => {
|
||||
const mockDependencies = ({
|
||||
esClient: jest.fn(),
|
||||
savedObjectsClient: jest.fn(),
|
||||
} as unknown) as GetDeprecationsContext;
|
||||
|
||||
it('returns a flattened array of DeprecationInfo', async () => {
|
||||
const deprecationsFactory = new DeprecationsFactory({ logger });
|
||||
const deprecationsRegistry = deprecationsFactory.getRegistry('mockPlugin');
|
||||
const deprecationsBody = [
|
||||
{
|
||||
message: 'mockPlugin message',
|
||||
level: 'critical',
|
||||
correctiveActions: {
|
||||
manualSteps: ['mockPlugin step 1', 'mockPlugin step 2'],
|
||||
},
|
||||
},
|
||||
[
|
||||
{
|
||||
message: 'hello there!',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
manualSteps: ['mockPlugin step a', 'mockPlugin step b'],
|
||||
},
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
deprecationsRegistry.registerDeprecations({
|
||||
getDeprecations: jest.fn().mockResolvedValue(deprecationsBody),
|
||||
});
|
||||
|
||||
const derpecations = await deprecationsFactory.getDeprecations(
|
||||
'mockPlugin',
|
||||
mockDependencies
|
||||
);
|
||||
expect(derpecations).toStrictEqual(
|
||||
deprecationsBody.flat().map((body) => ({ ...body, domainId: 'mockPlugin' }))
|
||||
);
|
||||
});
|
||||
|
||||
it('removes empty entries from the returned array', async () => {
|
||||
const deprecationsFactory = new DeprecationsFactory({ logger });
|
||||
const deprecationsRegistry = deprecationsFactory.getRegistry('mockPlugin');
|
||||
const deprecationsBody = [
|
||||
{
|
||||
message: 'mockPlugin message',
|
||||
level: 'critical',
|
||||
correctiveActions: {
|
||||
manualSteps: ['mockPlugin step 1', 'mockPlugin step 2'],
|
||||
},
|
||||
},
|
||||
[undefined],
|
||||
undefined,
|
||||
];
|
||||
|
||||
deprecationsRegistry.registerDeprecations({
|
||||
getDeprecations: jest.fn().mockResolvedValue(deprecationsBody),
|
||||
});
|
||||
|
||||
const derpecations = await deprecationsFactory.getDeprecations(
|
||||
'mockPlugin',
|
||||
mockDependencies
|
||||
);
|
||||
expect(derpecations).toHaveLength(1);
|
||||
expect(derpecations).toStrictEqual([{ ...deprecationsBody[0], domainId: 'mockPlugin' }]);
|
||||
});
|
||||
});
|
||||
});
|
108
src/core/server/deprecations/deprecations_factory.ts
Normal file
108
src/core/server/deprecations/deprecations_factory.ts
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { DeprecationsRegistry } from './deprecations_registry';
|
||||
import type { Logger } from '../logging';
|
||||
import type {
|
||||
DomainDeprecationDetails,
|
||||
DeprecationsDetails,
|
||||
GetDeprecationsContext,
|
||||
} from './types';
|
||||
|
||||
export interface DeprecationsFactoryDeps {
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
export class DeprecationsFactory {
|
||||
private readonly registries: Map<string, DeprecationsRegistry> = new Map();
|
||||
private readonly logger: Logger;
|
||||
constructor({ logger }: DeprecationsFactoryDeps) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public getRegistry = (domainId: string): DeprecationsRegistry => {
|
||||
const existing = this.registries.get(domainId);
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
const registry = new DeprecationsRegistry();
|
||||
this.registries.set(domainId, registry);
|
||||
return registry;
|
||||
};
|
||||
|
||||
public getDeprecations = async (
|
||||
domainId: string,
|
||||
dependencies: GetDeprecationsContext
|
||||
): Promise<DomainDeprecationDetails[]> => {
|
||||
const infoBody = await this.getDeprecationsBody(domainId, dependencies);
|
||||
return this.createDeprecationInfo(domainId, infoBody).flat();
|
||||
};
|
||||
|
||||
public getAllDeprecations = async (
|
||||
dependencies: GetDeprecationsContext
|
||||
): Promise<DomainDeprecationDetails[]> => {
|
||||
const domainIds = [...this.registries.keys()];
|
||||
|
||||
const deprecationsInfo = await Promise.all(
|
||||
domainIds.map(async (domainId) => {
|
||||
const infoBody = await this.getDeprecationsBody(domainId, dependencies);
|
||||
return this.createDeprecationInfo(domainId, infoBody);
|
||||
})
|
||||
);
|
||||
|
||||
return deprecationsInfo.flat();
|
||||
};
|
||||
|
||||
private createDeprecationInfo = (
|
||||
domainId: string,
|
||||
deprecationInfoBody: DeprecationsDetails[]
|
||||
): DomainDeprecationDetails[] => {
|
||||
return deprecationInfoBody
|
||||
.flat()
|
||||
.filter(Boolean)
|
||||
.map((pluginDeprecation) => ({
|
||||
...pluginDeprecation,
|
||||
domainId,
|
||||
}));
|
||||
};
|
||||
|
||||
private getDeprecationsBody = async (
|
||||
domainId: string,
|
||||
dependencies: GetDeprecationsContext
|
||||
): Promise<DeprecationsDetails[]> => {
|
||||
const deprecationsRegistry = this.registries.get(domainId);
|
||||
if (!deprecationsRegistry) {
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const settledResults = await deprecationsRegistry.getDeprecations(dependencies);
|
||||
return settledResults.flatMap((settledResult) => {
|
||||
if (settledResult.status === 'rejected') {
|
||||
this.logger.warn(
|
||||
`Failed to get deprecations info for plugin "${domainId}".`,
|
||||
settledResult.reason
|
||||
);
|
||||
return [
|
||||
{
|
||||
message: `Failed to get deprecations info for plugin "${domainId}".`,
|
||||
level: 'fetch_error',
|
||||
correctiveActions: {
|
||||
manualSteps: ['Check Kibana server logs for error message.'],
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return settledResult.value;
|
||||
});
|
||||
} catch (err) {
|
||||
this.logger.warn(`Failed to get deprecations info for plugin "${domainId}".`, err);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
}
|
78
src/core/server/deprecations/deprecations_registry.test.ts
Normal file
78
src/core/server/deprecations/deprecations_registry.test.ts
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
/* eslint-disable dot-notation */
|
||||
import { RegisterDeprecationsConfig, GetDeprecationsContext } from './types';
|
||||
import { DeprecationsRegistry } from './deprecations_registry';
|
||||
|
||||
describe('DeprecationsRegistry', () => {
|
||||
describe('registerDeprecations', () => {
|
||||
it('throws if getDeprecations is not a function', async () => {
|
||||
const deprecationsRegistry = new DeprecationsRegistry();
|
||||
const deprecationsConfig = ({
|
||||
getDeprecations: null,
|
||||
} as unknown) as RegisterDeprecationsConfig;
|
||||
expect(() => deprecationsRegistry.registerDeprecations(deprecationsConfig)).toThrowError(
|
||||
/getDeprecations must be a function/
|
||||
);
|
||||
});
|
||||
|
||||
it('registers deprecation context', () => {
|
||||
const deprecationsRegistry = new DeprecationsRegistry();
|
||||
const getDeprecations = jest.fn();
|
||||
const deprecationsConfig = { getDeprecations };
|
||||
deprecationsRegistry.registerDeprecations(deprecationsConfig);
|
||||
expect(deprecationsRegistry['deprecationContexts']).toStrictEqual([deprecationsConfig]);
|
||||
});
|
||||
|
||||
it('allows registering multiple contexts', async () => {
|
||||
const deprecationsRegistry = new DeprecationsRegistry();
|
||||
const deprecationsConfigA = { getDeprecations: jest.fn() };
|
||||
const deprecationsConfigB = { getDeprecations: jest.fn() };
|
||||
deprecationsRegistry.registerDeprecations(deprecationsConfigA);
|
||||
deprecationsRegistry.registerDeprecations(deprecationsConfigB);
|
||||
expect(deprecationsRegistry['deprecationContexts']).toStrictEqual([
|
||||
deprecationsConfigA,
|
||||
deprecationsConfigB,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDeprecations', () => {
|
||||
it('returns all settled deprecations', async () => {
|
||||
const deprecationsRegistry = new DeprecationsRegistry();
|
||||
const mockContext = ({} as unknown) as GetDeprecationsContext;
|
||||
const mockError = new Error();
|
||||
const deprecationsConfigA = { getDeprecations: jest.fn().mockResolvedValue('hi') };
|
||||
const deprecationsConfigB = { getDeprecations: jest.fn().mockRejectedValue(mockError) };
|
||||
deprecationsRegistry.registerDeprecations(deprecationsConfigA);
|
||||
deprecationsRegistry.registerDeprecations(deprecationsConfigB);
|
||||
const deprecations = await deprecationsRegistry.getDeprecations(mockContext);
|
||||
expect(deprecations).toStrictEqual([
|
||||
{
|
||||
status: 'fulfilled',
|
||||
value: 'hi',
|
||||
},
|
||||
{
|
||||
status: 'rejected',
|
||||
reason: mockError,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('passes dependencies to registered getDeprecations function', async () => {
|
||||
const deprecationsRegistry = new DeprecationsRegistry();
|
||||
const mockContext = ({} as unknown) as GetDeprecationsContext;
|
||||
const deprecationsConfig = { getDeprecations: jest.fn().mockResolvedValue('hi') };
|
||||
deprecationsRegistry.registerDeprecations(deprecationsConfig);
|
||||
const deprecations = await deprecationsRegistry.getDeprecations(mockContext);
|
||||
expect(deprecations).toHaveLength(1);
|
||||
expect(deprecationsConfig.getDeprecations).toBeCalledWith(mockContext);
|
||||
});
|
||||
});
|
||||
});
|
31
src/core/server/deprecations/deprecations_registry.ts
Normal file
31
src/core/server/deprecations/deprecations_registry.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { DeprecationsDetails, RegisterDeprecationsConfig, GetDeprecationsContext } from './types';
|
||||
|
||||
export class DeprecationsRegistry {
|
||||
private readonly deprecationContexts: RegisterDeprecationsConfig[] = [];
|
||||
|
||||
public registerDeprecations = (deprecationContext: RegisterDeprecationsConfig) => {
|
||||
if (typeof deprecationContext.getDeprecations !== 'function') {
|
||||
throw new Error(`getDeprecations must be a function in registerDeprecations(context)`);
|
||||
}
|
||||
|
||||
this.deprecationContexts.push(deprecationContext);
|
||||
};
|
||||
|
||||
public getDeprecations = async (
|
||||
dependencies: GetDeprecationsContext
|
||||
): Promise<Array<PromiseSettledResult<DeprecationsDetails[]>>> => {
|
||||
return await Promise.allSettled(
|
||||
this.deprecationContexts.map(
|
||||
async (deprecationContext) => await deprecationContext.getDeprecations(dependencies)
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
49
src/core/server/deprecations/deprecations_service.mock.ts
Normal file
49
src/core/server/deprecations/deprecations_service.mock.ts
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { PublicMethodsOf } from '@kbn/utility-types';
|
||||
import {
|
||||
DeprecationsService,
|
||||
InternalDeprecationsServiceSetup,
|
||||
DeprecationsServiceSetup,
|
||||
} from './deprecations_service';
|
||||
type DeprecationsServiceContract = PublicMethodsOf<DeprecationsService>;
|
||||
|
||||
const createSetupContractMock = () => {
|
||||
const setupContract: jest.Mocked<DeprecationsServiceSetup> = {
|
||||
registerDeprecations: jest.fn(),
|
||||
};
|
||||
|
||||
return setupContract;
|
||||
};
|
||||
|
||||
const createInternalSetupContractMock = () => {
|
||||
const internalSetupContract: jest.Mocked<InternalDeprecationsServiceSetup> = {
|
||||
getRegistry: jest.fn(),
|
||||
};
|
||||
|
||||
internalSetupContract.getRegistry.mockReturnValue(createSetupContractMock());
|
||||
return internalSetupContract;
|
||||
};
|
||||
|
||||
const createDeprecationsServiceMock = () => {
|
||||
const mocked: jest.Mocked<DeprecationsServiceContract> = {
|
||||
setup: jest.fn(),
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
};
|
||||
|
||||
mocked.setup.mockReturnValue(createInternalSetupContractMock());
|
||||
return mocked;
|
||||
};
|
||||
|
||||
export const deprecationsServiceMock = {
|
||||
create: createDeprecationsServiceMock,
|
||||
createInternalSetupContract: createInternalSetupContractMock,
|
||||
createSetupContract: createSetupContractMock,
|
||||
};
|
168
src/core/server/deprecations/deprecations_service.ts
Normal file
168
src/core/server/deprecations/deprecations_service.ts
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { DeprecationsFactory } from './deprecations_factory';
|
||||
import { RegisterDeprecationsConfig } from './types';
|
||||
import { registerRoutes } from './routes';
|
||||
|
||||
import { CoreContext } from '../core_context';
|
||||
import { CoreUsageDataSetup } from '../core_usage_data';
|
||||
import { InternalElasticsearchServiceSetup } from '../elasticsearch';
|
||||
import { CoreService } from '../../types';
|
||||
import { InternalHttpServiceSetup } from '../http';
|
||||
import { Logger } from '../logging';
|
||||
|
||||
/**
|
||||
* The deprecations service provides a way for the Kibana platform to communicate deprecated
|
||||
* features and configs with its users. These deprecations are only communicated
|
||||
* if the deployment is using these features. Allowing for a user tailored experience
|
||||
* for upgrading the stack version.
|
||||
*
|
||||
* The Deprecation service is consumed by the upgrade assistant to assist with the upgrade
|
||||
* experience.
|
||||
*
|
||||
* If a deprecated feature can be resolved without manual user intervention.
|
||||
* Using correctiveActions.api allows the Upgrade Assistant to use this api to correct the
|
||||
* deprecation upon a user trigger.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { DeprecationsDetails, GetDeprecationsContext, CoreSetup } from 'src/core/server';
|
||||
*
|
||||
* async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecationsContext): Promise<DeprecationsDetails[]> {
|
||||
* const deprecations: DeprecationsDetails[] = [];
|
||||
* const count = await getTimelionSheetsCount(savedObjectsClient);
|
||||
*
|
||||
* if (count > 0) {
|
||||
* // Example of a manual correctiveAction
|
||||
* deprecations.push({
|
||||
* message: `You have ${count} Timelion worksheets. The Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard.`,
|
||||
* documentationUrl:
|
||||
* 'https://www.elastic.co/guide/en/kibana/current/create-panels-with-timelion.html',
|
||||
* level: 'warning',
|
||||
* correctiveActions: {
|
||||
* manualSteps: [
|
||||
* 'Navigate to the Kibana Dashboard and click "Create dashboard".',
|
||||
* 'Select Timelion from the "New Visualization" window.',
|
||||
* 'Open a new tab, open the Timelion app, select the chart you want to copy, then copy the chart expression.',
|
||||
* 'Go to Timelion, paste the chart expression in the Timelion expression field, then click Update.',
|
||||
* 'In the toolbar, click Save.',
|
||||
* 'On the Save visualization window, enter the visualization Title, then click Save and return.',
|
||||
* ],
|
||||
* },
|
||||
* });
|
||||
* }
|
||||
*
|
||||
* // Example of an api correctiveAction
|
||||
* deprecations.push({
|
||||
* "message": "User 'test_dashboard_user' is using a deprecated role: 'kibana_user'",
|
||||
* "documentationUrl": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-user.html",
|
||||
* "level": "critical",
|
||||
* "correctiveActions": {
|
||||
* "api": {
|
||||
* "path": "/internal/security/users/test_dashboard_user",
|
||||
* "method": "POST",
|
||||
* "body": {
|
||||
* "username": "test_dashboard_user",
|
||||
* "roles": [
|
||||
* "machine_learning_user",
|
||||
* "enrich_user",
|
||||
* "kibana_admin"
|
||||
* ],
|
||||
* "full_name": "Alison Goryachev",
|
||||
* "email": "alisongoryachev@gmail.com",
|
||||
* "metadata": {},
|
||||
* "enabled": true
|
||||
* }
|
||||
* },
|
||||
* "manualSteps": [
|
||||
* "Using Kibana user management, change all users using the kibana_user role to the kibana_admin role.",
|
||||
* "Using Kibana role-mapping management, change all role-mappings which assing the kibana_user role to the kibana_admin role."
|
||||
* ]
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* return deprecations;
|
||||
* }
|
||||
*
|
||||
*
|
||||
* export class Plugin() {
|
||||
* setup: (core: CoreSetup) => {
|
||||
* core.deprecations.registerDeprecations({ getDeprecations });
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface DeprecationsServiceSetup {
|
||||
registerDeprecations: (deprecationContext: RegisterDeprecationsConfig) => void;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface InternalDeprecationsServiceSetup {
|
||||
getRegistry: (domainId: string) => DeprecationsServiceSetup;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface DeprecationsSetupDeps {
|
||||
http: InternalHttpServiceSetup;
|
||||
elasticsearch: InternalElasticsearchServiceSetup;
|
||||
coreUsageData: CoreUsageDataSetup;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export class DeprecationsService implements CoreService<InternalDeprecationsServiceSetup> {
|
||||
private readonly logger: Logger;
|
||||
|
||||
constructor(private readonly coreContext: CoreContext) {
|
||||
this.logger = coreContext.logger.get('deprecations-service');
|
||||
}
|
||||
|
||||
public setup({ http }: DeprecationsSetupDeps): InternalDeprecationsServiceSetup {
|
||||
this.logger.debug('Setting up Deprecations service');
|
||||
const deprecationsFactory = new DeprecationsFactory({
|
||||
logger: this.logger,
|
||||
});
|
||||
|
||||
registerRoutes({ http, deprecationsFactory });
|
||||
this.registerConfigDeprecationsInfo(deprecationsFactory);
|
||||
|
||||
return {
|
||||
getRegistry: (domainId: string): DeprecationsServiceSetup => {
|
||||
const registry = deprecationsFactory.getRegistry(domainId);
|
||||
return {
|
||||
registerDeprecations: registry.registerDeprecations,
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public stop() {}
|
||||
|
||||
private registerConfigDeprecationsInfo(deprecationsFactory: DeprecationsFactory) {
|
||||
const handledDeprecatedConfigs = this.coreContext.configService.getHandledDeprecatedConfigs();
|
||||
|
||||
for (const [domainId, deprecationsContexts] of handledDeprecatedConfigs) {
|
||||
const deprecationsRegistry = deprecationsFactory.getRegistry(domainId);
|
||||
deprecationsRegistry.registerDeprecations({
|
||||
getDeprecations: () => {
|
||||
return deprecationsContexts.map(({ message, correctiveActions, documentationUrl }) => {
|
||||
return {
|
||||
level: 'critical',
|
||||
message,
|
||||
correctiveActions: correctiveActions ?? {},
|
||||
documentationUrl,
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
21
src/core/server/deprecations/index.ts
Normal file
21
src/core/server/deprecations/index.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export type {
|
||||
DeprecationsDetails,
|
||||
GetDeprecationsContext,
|
||||
RegisterDeprecationsConfig,
|
||||
DeprecationsGetResponse,
|
||||
} from './types';
|
||||
|
||||
export type {
|
||||
DeprecationsServiceSetup,
|
||||
InternalDeprecationsServiceSetup,
|
||||
} from './deprecations_service';
|
||||
|
||||
export { DeprecationsService } from './deprecations_service';
|
35
src/core/server/deprecations/routes/get.ts
Normal file
35
src/core/server/deprecations/routes/get.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { IRouter } from '../../http';
|
||||
import { GetDeprecationsContext, DeprecationsGetResponse } from '../types';
|
||||
import { DeprecationsFactory } from '../deprecations_factory';
|
||||
|
||||
interface RouteDependencies {
|
||||
deprecationsFactory: DeprecationsFactory;
|
||||
}
|
||||
|
||||
export const registerGetRoute = (router: IRouter, { deprecationsFactory }: RouteDependencies) => {
|
||||
router.get(
|
||||
{
|
||||
path: '/',
|
||||
validate: false,
|
||||
},
|
||||
async (context, req, res) => {
|
||||
const dependencies: GetDeprecationsContext = {
|
||||
esClient: context.core.elasticsearch.client,
|
||||
savedObjectsClient: context.core.savedObjects.client,
|
||||
};
|
||||
|
||||
const body: DeprecationsGetResponse = {
|
||||
deprecations: await deprecationsFactory.getAllDeprecations(dependencies),
|
||||
};
|
||||
|
||||
return res.ok({ body });
|
||||
}
|
||||
);
|
||||
};
|
22
src/core/server/deprecations/routes/index.ts
Normal file
22
src/core/server/deprecations/routes/index.ts
Normal file
|
@ -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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { InternalHttpServiceSetup } from '../../http';
|
||||
import { registerGetRoute } from './get';
|
||||
import { DeprecationsFactory } from '../deprecations_factory';
|
||||
|
||||
export function registerRoutes({
|
||||
http,
|
||||
deprecationsFactory,
|
||||
}: {
|
||||
http: InternalHttpServiceSetup;
|
||||
deprecationsFactory: DeprecationsFactory;
|
||||
}) {
|
||||
const router = http.createRouter('/api/deprecations');
|
||||
registerGetRoute(router, { deprecationsFactory });
|
||||
}
|
67
src/core/server/deprecations/types.ts
Normal file
67
src/core/server/deprecations/types.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { SavedObjectsClientContract } from '../saved_objects/types';
|
||||
import type { IScopedClusterClient } from '../elasticsearch';
|
||||
|
||||
type MaybePromise<T> = T | Promise<T>;
|
||||
|
||||
export interface DomainDeprecationDetails extends DeprecationsDetails {
|
||||
domainId: string;
|
||||
}
|
||||
|
||||
export interface DeprecationsDetails {
|
||||
/* The message to be displayed for the deprecation. */
|
||||
message: string;
|
||||
/**
|
||||
* levels:
|
||||
* - warning: will not break deployment upon upgrade
|
||||
* - critical: needs to be addressed before upgrade.
|
||||
* - fetch_error: Deprecations service failed to grab the deprecation details for the domain.
|
||||
*/
|
||||
level: 'warning' | 'critical' | 'fetch_error';
|
||||
/* (optional) link to the documentation for more details on the deprecation. */
|
||||
documentationUrl?: string;
|
||||
/* corrective action needed to fix this deprecation. */
|
||||
correctiveActions: {
|
||||
/**
|
||||
* (optional) The api to be called to automatically fix the deprecation
|
||||
* Each domain should implement a POST/PUT route for their plugin to
|
||||
* handle their deprecations.
|
||||
*/
|
||||
api?: {
|
||||
/* Kibana route path. Passing a query string is allowed */
|
||||
path: string;
|
||||
/* Kibana route method: 'POST' or 'PUT'. */
|
||||
method: 'POST' | 'PUT';
|
||||
/* Additional details to be passed to the route. */
|
||||
body?: {
|
||||
[key: string]: any;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* (optional) If this deprecation cannot be automtically fixed
|
||||
* via an API corrective action. Specify a list of manual steps
|
||||
* users need to follow to fix the deprecation before upgrade.
|
||||
*/
|
||||
manualSteps?: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface RegisterDeprecationsConfig {
|
||||
getDeprecations: (context: GetDeprecationsContext) => MaybePromise<DeprecationsDetails[]>;
|
||||
}
|
||||
|
||||
export interface GetDeprecationsContext {
|
||||
esClient: IScopedClusterClient;
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
}
|
||||
|
||||
export interface DeprecationsGetResponse {
|
||||
deprecations: DomainDeprecationDetails[];
|
||||
}
|
|
@ -28,7 +28,7 @@ const applyElasticsearchDeprecations = (settings: Record<string, any> = {}) => {
|
|||
deprecation,
|
||||
path: CONFIG_PATH,
|
||||
})),
|
||||
(msg) => deprecationMessages.push(msg)
|
||||
() => ({ message }) => deprecationMessages.push(message)
|
||||
);
|
||||
return {
|
||||
messages: deprecationMessages,
|
||||
|
|
|
@ -144,32 +144,32 @@ export const configSchema = schema.object({
|
|||
});
|
||||
|
||||
const deprecations: ConfigDeprecationProvider = () => [
|
||||
(settings, fromPath, log) => {
|
||||
(settings, fromPath, addDeprecation) => {
|
||||
const es = settings[fromPath];
|
||||
if (!es) {
|
||||
return settings;
|
||||
}
|
||||
if (es.username === 'elastic') {
|
||||
log(
|
||||
`Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.`,
|
||||
});
|
||||
} else if (es.username === 'kibana') {
|
||||
log(
|
||||
`Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.`,
|
||||
});
|
||||
}
|
||||
if (es.ssl?.key !== undefined && es.ssl?.certificate === undefined) {
|
||||
log(
|
||||
`Setting [${fromPath}.ssl.key] without [${fromPath}.ssl.certificate] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Setting [${fromPath}.ssl.key] without [${fromPath}.ssl.certificate] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`,
|
||||
});
|
||||
} else if (es.ssl?.certificate !== undefined && es.ssl?.key === undefined) {
|
||||
log(
|
||||
`Setting [${fromPath}.ssl.certificate] without [${fromPath}.ssl.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Setting [${fromPath}.ssl.certificate] without [${fromPath}.ssl.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`,
|
||||
});
|
||||
} else if (es.logQueries === true) {
|
||||
log(
|
||||
`Setting [${fromPath}.logQueries] is deprecated and no longer used. You should set the log level to "debug" for the "elasticsearch.queries" context in "logging.loggers" or use "logging.verbose: true".`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Setting [${fromPath}.logQueries] is deprecated and no longer used. You should set the log level to "debug" for the "elasticsearch.queries" context in "logging.loggers" or use "logging.verbose: true".`,
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
},
|
||||
|
|
|
@ -57,7 +57,7 @@ import { StatusServiceSetup } from './status';
|
|||
import { AppenderConfigType, appendersSchema, LoggingServiceSetup } from './logging';
|
||||
import { CoreUsageDataStart } from './core_usage_data';
|
||||
import { I18nServiceSetup } from './i18n';
|
||||
|
||||
import { DeprecationsServiceSetup } from './deprecations';
|
||||
// Because of #79265 we need to explicity import, then export these types for
|
||||
// scripts/telemetry_check.js to work as expected
|
||||
import {
|
||||
|
@ -88,8 +88,8 @@ export type {
|
|||
ConfigService,
|
||||
ConfigDeprecation,
|
||||
ConfigDeprecationProvider,
|
||||
ConfigDeprecationLogger,
|
||||
ConfigDeprecationFactory,
|
||||
AddConfigDeprecation,
|
||||
EnvironmentMode,
|
||||
PackageInfo,
|
||||
} from './config';
|
||||
|
@ -381,6 +381,12 @@ export type {
|
|||
} from './metrics';
|
||||
|
||||
export type { I18nServiceSetup } from './i18n';
|
||||
export type {
|
||||
DeprecationsDetails,
|
||||
RegisterDeprecationsConfig,
|
||||
GetDeprecationsContext,
|
||||
DeprecationsServiceSetup,
|
||||
} from './deprecations';
|
||||
|
||||
export type { AppCategory } from '../types';
|
||||
export { DEFAULT_APP_CATEGORIES } from '../utils';
|
||||
|
@ -481,6 +487,8 @@ export interface CoreSetup<TPluginsStart extends object = object, TStart = unkno
|
|||
status: StatusServiceSetup;
|
||||
/** {@link UiSettingsServiceSetup} */
|
||||
uiSettings: UiSettingsServiceSetup;
|
||||
/** {@link DeprecationsServiceSetup} */
|
||||
deprecations: DeprecationsServiceSetup;
|
||||
/** {@link StartServicesAccessor} */
|
||||
getStartServices: StartServicesAccessor<TPluginsStart, TStart>;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import { InternalStatusServiceSetup } from './status';
|
|||
import { InternalLoggingServiceSetup } from './logging';
|
||||
import { CoreUsageDataStart } from './core_usage_data';
|
||||
import { I18nServiceSetup } from './i18n';
|
||||
import { InternalDeprecationsServiceSetup } from './deprecations';
|
||||
|
||||
/** @internal */
|
||||
export interface InternalCoreSetup {
|
||||
|
@ -45,6 +46,7 @@ export interface InternalCoreSetup {
|
|||
httpResources: InternalHttpResourcesSetup;
|
||||
logging: InternalLoggingServiceSetup;
|
||||
metrics: InternalMetricsServiceSetup;
|
||||
deprecations: InternalDeprecationsServiceSetup;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,7 @@ const applyKibanaDeprecations = (settings: Record<string, any> = {}) => {
|
|||
deprecation,
|
||||
path: CONFIG_PATH,
|
||||
})),
|
||||
(msg) => deprecationMessages.push(msg)
|
||||
() => ({ message }) => deprecationMessages.push(message)
|
||||
);
|
||||
return {
|
||||
messages: deprecationMessages,
|
||||
|
|
|
@ -12,12 +12,13 @@ import { ConfigDeprecationProvider } from '@kbn/config';
|
|||
export type KibanaConfigType = TypeOf<typeof config.schema>;
|
||||
|
||||
const deprecations: ConfigDeprecationProvider = () => [
|
||||
(settings, fromPath, log) => {
|
||||
(settings, fromPath, addDeprecation) => {
|
||||
const kibana = settings[fromPath];
|
||||
if (kibana?.index) {
|
||||
log(
|
||||
`"kibana.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `"kibana.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details`,
|
||||
documentationUrl: 'https://ela.st/kbn-remove-legacy-multitenancy',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
},
|
||||
|
|
|
@ -32,6 +32,7 @@ import { statusServiceMock } from '../status/status_service.mock';
|
|||
import { loggingServiceMock } from '../logging/logging_service.mock';
|
||||
import { metricsServiceMock } from '../metrics/metrics_service.mock';
|
||||
import { i18nServiceMock } from '../i18n/i18n_service.mock';
|
||||
import { deprecationsServiceMock } from '../deprecations/deprecations_service.mock';
|
||||
|
||||
const MockKbnServer: jest.Mock<KbnServer> = KbnServer as any;
|
||||
|
||||
|
@ -80,6 +81,7 @@ beforeEach(() => {
|
|||
status: statusServiceMock.createInternalSetupContract(),
|
||||
logging: loggingServiceMock.createInternalSetupContract(),
|
||||
metrics: metricsServiceMock.createInternalSetupContract(),
|
||||
deprecations: deprecationsServiceMock.createInternalSetupContract(),
|
||||
},
|
||||
plugins: { 'plugin-id': 'plugin-value' },
|
||||
uiPlugins: {
|
||||
|
|
|
@ -257,6 +257,11 @@ export class LegacyService implements CoreService {
|
|||
uiSettings: {
|
||||
register: setupDeps.core.uiSettings.register,
|
||||
},
|
||||
deprecations: {
|
||||
registerDeprecations: () => {
|
||||
throw new Error('core.setup.deprecations.registerDeprecations is unsupported in legacy');
|
||||
},
|
||||
},
|
||||
getStartServices: () => Promise.resolve([coreStart, startDeps.plugins, {}]),
|
||||
};
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import { environmentServiceMock } from './environment/environment_service.mock';
|
|||
import { statusServiceMock } from './status/status_service.mock';
|
||||
import { coreUsageDataServiceMock } from './core_usage_data/core_usage_data_service.mock';
|
||||
import { i18nServiceMock } from './i18n/i18n_service.mock';
|
||||
import { deprecationsServiceMock } from './deprecations/deprecations_service.mock';
|
||||
|
||||
export { configServiceMock } from './config/mocks';
|
||||
export { httpServerMock } from './http/http_server.mocks';
|
||||
|
@ -49,6 +50,7 @@ export { contextServiceMock } from './context/context_service.mock';
|
|||
export { capabilitiesServiceMock } from './capabilities/capabilities_service.mock';
|
||||
export { coreUsageDataServiceMock } from './core_usage_data/core_usage_data_service.mock';
|
||||
export { i18nServiceMock } from './i18n/i18n_service.mock';
|
||||
export { deprecationsServiceMock } from './deprecations/deprecations_service.mock';
|
||||
|
||||
export function pluginInitializerContextConfigMock<T>(config: T) {
|
||||
const globalConfig: SharedGlobalConfig = {
|
||||
|
@ -137,6 +139,7 @@ function createCoreSetupMock({
|
|||
uiSettings: uiSettingsMock,
|
||||
logging: loggingServiceMock.createSetupContract(),
|
||||
metrics: metricsServiceMock.createSetupContract(),
|
||||
deprecations: deprecationsServiceMock.createSetupContract(),
|
||||
getStartServices: jest
|
||||
.fn<Promise<[ReturnType<typeof createCoreStartMock>, object, any]>, []>()
|
||||
.mockResolvedValue([createCoreStartMock(), pluginStartDeps, pluginStartContract]),
|
||||
|
@ -174,6 +177,7 @@ function createInternalCoreSetupMock() {
|
|||
uiSettings: uiSettingsServiceMock.createSetupContract(),
|
||||
logging: loggingServiceMock.createInternalSetupContract(),
|
||||
metrics: metricsServiceMock.createInternalSetupContract(),
|
||||
deprecations: deprecationsServiceMock.createInternalSetupContract(),
|
||||
};
|
||||
return setupDeps;
|
||||
}
|
||||
|
|
|
@ -165,6 +165,7 @@ export function createPluginSetupContext<TPlugin, TPluginDependencies>(
|
|||
register: deps.uiSettings.register,
|
||||
},
|
||||
getStartServices: () => plugin.startDependencies,
|
||||
deprecations: deps.deprecations.getRegistry(plugin.name),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
```ts
|
||||
|
||||
import { AddConfigDeprecation } from '@kbn/config';
|
||||
import { ApiResponse } from '@elastic/elasticsearch/lib/Transport';
|
||||
import Boom from '@hapi/boom';
|
||||
import { BulkIndexDocumentsParams } from 'elasticsearch';
|
||||
|
@ -35,7 +36,6 @@ import { ClusterStateParams } from 'elasticsearch';
|
|||
import { ClusterStatsParams } from 'elasticsearch';
|
||||
import { ConfigDeprecation } from '@kbn/config';
|
||||
import { ConfigDeprecationFactory } from '@kbn/config';
|
||||
import { ConfigDeprecationLogger } from '@kbn/config';
|
||||
import { ConfigDeprecationProvider } from '@kbn/config';
|
||||
import { ConfigOptions } from 'elasticsearch';
|
||||
import { ConfigPath } from '@kbn/config';
|
||||
|
@ -169,6 +169,8 @@ import { UpdateDocumentByQueryParams } from 'elasticsearch';
|
|||
import { UpdateDocumentParams } from 'elasticsearch';
|
||||
import { URL } from 'url';
|
||||
|
||||
export { AddConfigDeprecation }
|
||||
|
||||
// @public
|
||||
export interface AppCategory {
|
||||
ariaLabel?: string;
|
||||
|
@ -374,8 +376,6 @@ export { ConfigDeprecation }
|
|||
|
||||
export { ConfigDeprecationFactory }
|
||||
|
||||
export { ConfigDeprecationLogger }
|
||||
|
||||
export { ConfigDeprecationProvider }
|
||||
|
||||
export { ConfigPath }
|
||||
|
@ -491,6 +491,8 @@ export interface CoreSetup<TPluginsStart extends object = object, TStart = unkno
|
|||
// (undocumented)
|
||||
context: ContextSetup;
|
||||
// (undocumented)
|
||||
deprecations: DeprecationsServiceSetup;
|
||||
// (undocumented)
|
||||
elasticsearch: ElasticsearchServiceSetup;
|
||||
// (undocumented)
|
||||
getStartServices: StartServicesAccessor<TPluginsStart, TStart>;
|
||||
|
@ -830,12 +832,40 @@ export interface DeprecationInfo {
|
|||
url: string;
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "DeprecationsDetails" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface DeprecationsDetails {
|
||||
// (undocumented)
|
||||
correctiveActions: {
|
||||
api?: {
|
||||
path: string;
|
||||
method: 'POST' | 'PUT';
|
||||
body?: {
|
||||
[key: string]: any;
|
||||
};
|
||||
};
|
||||
manualSteps?: string[];
|
||||
};
|
||||
// (undocumented)
|
||||
documentationUrl?: string;
|
||||
level: 'warning' | 'critical' | 'fetch_error';
|
||||
// (undocumented)
|
||||
message: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface DeprecationSettings {
|
||||
docLinksKey: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface DeprecationsServiceSetup {
|
||||
// (undocumented)
|
||||
registerDeprecations: (deprecationContext: RegisterDeprecationsConfig) => void;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type DestructiveRouteMethod = 'post' | 'put' | 'delete' | 'patch';
|
||||
|
||||
|
@ -939,6 +969,16 @@ export type GetAuthState = <T = unknown>(request: KibanaRequest | LegacyRequest)
|
|||
state: T;
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "GetDeprecationsContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface GetDeprecationsContext {
|
||||
// (undocumented)
|
||||
esClient: IScopedClusterClient;
|
||||
// (undocumented)
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetResponse<T> {
|
||||
// (undocumented)
|
||||
|
@ -1912,6 +1952,16 @@ export type RedirectResponseOptions = HttpResponseOptions & {
|
|||
};
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "RegisterDeprecationsConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface RegisterDeprecationsConfig {
|
||||
// Warning: (ae-forgotten-export) The symbol "MaybePromise" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
getDeprecations: (context: GetDeprecationsContext) => MaybePromise<DeprecationsDetails[]>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type RequestHandler<P = unknown, Q = unknown, B = unknown, Context extends RequestHandlerContext = RequestHandlerContext, Method extends RouteMethod = any, ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory> = (context: Context, request: KibanaRequest<P, Q, B, Method>, response: ResponseFactory) => IKibanaResponse<any> | Promise<IKibanaResponse<any>>;
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ import { ContextService } from './context';
|
|||
import { RequestHandlerContext } from '.';
|
||||
import { InternalCoreSetup, InternalCoreStart, ServiceConfigDescriptor } from './internal_types';
|
||||
import { CoreUsageDataService } from './core_usage_data';
|
||||
import { DeprecationsService } from './deprecations';
|
||||
import { CoreRouteHandlerContext } from './core_route_handler_context';
|
||||
import { config as externalUrlConfig } from './external_url';
|
||||
|
||||
|
@ -67,6 +68,7 @@ export class Server {
|
|||
private readonly coreApp: CoreApp;
|
||||
private readonly coreUsageData: CoreUsageDataService;
|
||||
private readonly i18n: I18nService;
|
||||
private readonly deprecations: DeprecationsService;
|
||||
|
||||
private readonly savedObjectsStartPromise: Promise<SavedObjectsServiceStart>;
|
||||
private resolveSavedObjectsStartPromise?: (value: SavedObjectsServiceStart) => void;
|
||||
|
@ -102,6 +104,7 @@ export class Server {
|
|||
this.logging = new LoggingService(core);
|
||||
this.coreUsageData = new CoreUsageDataService(core);
|
||||
this.i18n = new I18nService(core);
|
||||
this.deprecations = new DeprecationsService(core);
|
||||
|
||||
this.savedObjectsStartPromise = new Promise((resolve) => {
|
||||
this.resolveSavedObjectsStartPromise = resolve;
|
||||
|
@ -192,6 +195,12 @@ export class Server {
|
|||
loggingSystem: this.loggingSystem,
|
||||
});
|
||||
|
||||
const deprecationsSetup = this.deprecations.setup({
|
||||
http: httpSetup,
|
||||
elasticsearch: elasticsearchServiceSetup,
|
||||
coreUsageData: coreUsageDataSetup,
|
||||
});
|
||||
|
||||
const coreSetup: InternalCoreSetup = {
|
||||
capabilities: capabilitiesSetup,
|
||||
context: contextServiceSetup,
|
||||
|
@ -206,6 +215,7 @@ export class Server {
|
|||
httpResources: httpResourcesSetup,
|
||||
logging: loggingSetup,
|
||||
metrics: metricsSetup,
|
||||
deprecations: deprecationsSetup,
|
||||
};
|
||||
|
||||
const pluginsSetup = await this.plugins.setup(coreSetup);
|
||||
|
@ -285,6 +295,7 @@ export class Server {
|
|||
await this.metrics.stop();
|
||||
await this.status.stop();
|
||||
await this.logging.stop();
|
||||
this.deprecations.stop();
|
||||
}
|
||||
|
||||
private registerCoreContext(coreSetup: InternalCoreSetup) {
|
||||
|
|
|
@ -37,6 +37,7 @@ export type {
|
|||
SavedObjectsClientContract,
|
||||
SavedObjectsNamespaceType,
|
||||
} from './saved_objects/types';
|
||||
export type { DomainDeprecationDetails, DeprecationsGetResponse } from './deprecations/types';
|
||||
export * from './ui_settings/types';
|
||||
export * from './legacy/types';
|
||||
export type { EnvironmentMode, PackageInfo } from '@kbn/config';
|
||||
|
|
|
@ -6,12 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
ConfigDeprecationLogger,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
PluginConfigDescriptor,
|
||||
} from 'kibana/server';
|
||||
import { AddConfigDeprecation, CoreSetup, CoreStart, PluginConfigDescriptor } from 'kibana/server';
|
||||
import { get } from 'lodash';
|
||||
|
||||
import { configSchema, ConfigSchema } from '../config';
|
||||
|
@ -23,17 +18,28 @@ export const config: PluginConfigDescriptor<ConfigSchema> = {
|
|||
schema: configSchema,
|
||||
deprecations: ({ renameFromRoot }) => [
|
||||
// TODO: Remove deprecation once defaultAppId is deleted
|
||||
renameFromRoot('kibana.defaultAppId', 'kibana_legacy.defaultAppId', true),
|
||||
(completeConfig: Record<string, any>, rootPath: string, log: ConfigDeprecationLogger) => {
|
||||
renameFromRoot('kibana.defaultAppId', 'kibana_legacy.defaultAppId', { silent: true }),
|
||||
(
|
||||
completeConfig: Record<string, any>,
|
||||
rootPath: string,
|
||||
addDeprecation: AddConfigDeprecation
|
||||
) => {
|
||||
if (
|
||||
get(completeConfig, 'kibana.defaultAppId') === undefined &&
|
||||
get(completeConfig, 'kibana_legacy.defaultAppId') === undefined
|
||||
) {
|
||||
return completeConfig;
|
||||
}
|
||||
log(
|
||||
`kibana.defaultAppId is deprecated and will be removed in 8.0. Please use the \`defaultRoute\` advanced setting instead`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `kibana.defaultAppId is deprecated and will be removed in 8.0. Please use the \`defaultRoute\` advanced setting instead`,
|
||||
correctiveActions: {
|
||||
manualSteps: [
|
||||
'Go to Stack Management > Advanced Settings',
|
||||
'Update the "defaultRoute" setting under the General section',
|
||||
'Remove "kibana.defaultAppId" from the kibana.yml config file',
|
||||
],
|
||||
},
|
||||
});
|
||||
return completeConfig;
|
||||
},
|
||||
],
|
||||
|
|
70
src/plugins/timelion/server/deprecations.ts
Normal file
70
src/plugins/timelion/server/deprecations.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
CoreStart,
|
||||
SavedObjectsClient,
|
||||
Logger,
|
||||
GetDeprecationsContext,
|
||||
DeprecationsDetails,
|
||||
} from 'src/core/server';
|
||||
|
||||
export const getTimelionSheetsCount = async (
|
||||
savedObjectsClient: Pick<SavedObjectsClient, 'find'>
|
||||
) => {
|
||||
const { total } = await savedObjectsClient.find({ type: 'timelion-sheet', perPage: 1 });
|
||||
return total;
|
||||
};
|
||||
|
||||
export const showWarningMessageIfTimelionSheetWasFound = async (
|
||||
core: CoreStart,
|
||||
logger: Logger
|
||||
) => {
|
||||
const { savedObjects } = core;
|
||||
const savedObjectsClient = savedObjects.createInternalRepository();
|
||||
const count = await getTimelionSheetsCount(savedObjectsClient);
|
||||
if (count > 0) {
|
||||
logger.warn(
|
||||
'Deprecated since 7.0, the Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard. See https://www.elastic.co/guide/en/kibana/current/create-panels-with-timelion.html.'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deprecated since 7.0, the Timelion app will be removed in 8.0.
|
||||
* To continue using your Timelion worksheets, migrate them to a dashboard.
|
||||
*
|
||||
* @link https://www.elastic.co/guide/en/kibana/master/timelion.html#timelion-deprecation
|
||||
**/
|
||||
export async function getDeprecations({
|
||||
savedObjectsClient,
|
||||
}: GetDeprecationsContext): Promise<DeprecationsDetails[]> {
|
||||
const deprecations: DeprecationsDetails[] = [];
|
||||
const count = await getTimelionSheetsCount(savedObjectsClient);
|
||||
|
||||
if (count > 0) {
|
||||
deprecations.push({
|
||||
message: `You have ${count} Timelion worksheets. The Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard.`,
|
||||
documentationUrl:
|
||||
'https://www.elastic.co/guide/en/kibana/current/create-panels-with-timelion.html',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
manualSteps: [
|
||||
'Navigate to the Kibana Dashboard and click "Create dashboard".',
|
||||
'Select Timelion from the "New Visualization" window.',
|
||||
'Open a new tab, open the Timelion app, select the chart you want to copy, then copy the chart expression.',
|
||||
'Go to Timelion, paste the chart expression in the Timelion expression field, then click Update.',
|
||||
'In the toolbar, click Save.',
|
||||
'On the Save visualization window, enter the visualization Title, then click Save and return.',
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return deprecations;
|
||||
}
|
|
@ -11,30 +11,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { schema } from '@kbn/config-schema';
|
||||
import { TimelionConfigType } from './config';
|
||||
import { timelionSheetSavedObjectType } from './saved_objects';
|
||||
|
||||
/**
|
||||
* Deprecated since 7.0, the Timelion app will be removed in 8.0.
|
||||
* To continue using your Timelion worksheets, migrate them to a dashboard.
|
||||
*
|
||||
* @link https://www.elastic.co/guide/en/kibana/master/timelion.html#timelion-deprecation
|
||||
**/
|
||||
const showWarningMessageIfTimelionSheetWasFound = (core: CoreStart, logger: Logger) => {
|
||||
const { savedObjects } = core;
|
||||
const savedObjectsClient = savedObjects.createInternalRepository();
|
||||
|
||||
savedObjectsClient
|
||||
.find({
|
||||
type: 'timelion-sheet',
|
||||
perPage: 1,
|
||||
})
|
||||
.then(
|
||||
({ total }) =>
|
||||
total &&
|
||||
logger.warn(
|
||||
'Deprecated since 7.0, the Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard. See https://www.elastic.co/guide/en/kibana/current/create-panels-with-timelion.html.'
|
||||
)
|
||||
);
|
||||
};
|
||||
import { getDeprecations, showWarningMessageIfTimelionSheetWasFound } from './deprecations';
|
||||
|
||||
export class TimelionPlugin implements Plugin {
|
||||
private logger: Logger;
|
||||
|
@ -87,6 +64,8 @@ export class TimelionPlugin implements Plugin {
|
|||
schema: schema.number(),
|
||||
},
|
||||
});
|
||||
|
||||
core.deprecations.registerDeprecations({ getDeprecations });
|
||||
}
|
||||
start(core: CoreStart) {
|
||||
showWarningMessageIfTimelionSheetWasFound(core, this.logger);
|
||||
|
|
|
@ -21,7 +21,7 @@ export const config: PluginConfigDescriptor<ConfigSchema> = {
|
|||
renameFromRoot('timelion_vis.enabled', 'vis_type_timelion.enabled'),
|
||||
renameFromRoot('timelion.enabled', 'vis_type_timelion.enabled'),
|
||||
renameFromRoot('timelion.graphiteUrls', 'vis_type_timelion.graphiteUrls'),
|
||||
renameFromRoot('timelion.ui.enabled', 'vis_type_timelion.ui.enabled', true),
|
||||
renameFromRoot('timelion.ui.enabled', 'vis_type_timelion.ui.enabled', { silent: true }),
|
||||
],
|
||||
};
|
||||
export const plugin = (initializerContext: PluginInitializerContext) =>
|
||||
|
|
|
@ -15,9 +15,13 @@ export { VisTypeTimeseriesSetup } from './plugin';
|
|||
export const config: PluginConfigDescriptor<VisTypeTimeseriesConfig> = {
|
||||
deprecations: ({ unused, renameFromRoot }) => [
|
||||
// In Kibana v7.8 plugin id was renamed from 'metrics' to 'vis_type_timeseries':
|
||||
renameFromRoot('metrics.enabled', 'vis_type_timeseries.enabled', true),
|
||||
renameFromRoot('metrics.chartResolution', 'vis_type_timeseries.chartResolution', true),
|
||||
renameFromRoot('metrics.minimumBucketSize', 'vis_type_timeseries.minimumBucketSize', true),
|
||||
renameFromRoot('metrics.enabled', 'vis_type_timeseries.enabled', { silent: true }),
|
||||
renameFromRoot('metrics.chartResolution', 'vis_type_timeseries.chartResolution', {
|
||||
silent: true,
|
||||
}),
|
||||
renameFromRoot('metrics.minimumBucketSize', 'vis_type_timeseries.minimumBucketSize', {
|
||||
silent: true,
|
||||
}),
|
||||
|
||||
// Unused properties which should be removed after releasing Kibana v8.0:
|
||||
unused('chartResolution'),
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana",
|
||||
"id": "test-deprecations-plugin:ff3733a0-9fty-11e7-ahb3-3dcb94193fab",
|
||||
"source": {
|
||||
"type": "test-deprecations-plugin",
|
||||
"updated_at": "2021-02-11T18:51:23.794Z",
|
||||
"test-deprecations-plugin": {
|
||||
"title": "Test saved object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,289 @@
|
|||
{
|
||||
"type": "index",
|
||||
"value": {
|
||||
"index": ".kibana",
|
||||
"mappings": {
|
||||
"properties": {
|
||||
"config": {
|
||||
"dynamic": "true",
|
||||
"properties": {
|
||||
"buildNum": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"dateFormat:tz": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"hits": {
|
||||
"type": "integer"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"optionsJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"panelsJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"refreshInterval": {
|
||||
"properties": {
|
||||
"display": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"pause": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"section": {
|
||||
"type": "integer"
|
||||
},
|
||||
"value": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeFrom": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"timeRestore": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"timeTo": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"uiStateJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"index-pattern": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"fieldFormatMap": {
|
||||
"type": "text"
|
||||
},
|
||||
"fields": {
|
||||
"type": "text"
|
||||
},
|
||||
"intervalName": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"notExpandable": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sourceFilters": {
|
||||
"type": "text"
|
||||
},
|
||||
"timeFieldName": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"search": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"columns": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"hits": {
|
||||
"type": "integer"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sort": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"server": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"uuid": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timelion-sheet": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"hits": {
|
||||
"type": "integer"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timelion_chart_height": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timelion_columns": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timelion_interval": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"timelion_other_interval": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"timelion_rows": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timelion_sheet": {
|
||||
"type": "text"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"url": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"accessCount": {
|
||||
"type": "long"
|
||||
},
|
||||
"accessDate": {
|
||||
"type": "date"
|
||||
},
|
||||
"createDate": {
|
||||
"type": "date"
|
||||
},
|
||||
"url": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 2048,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"visualization": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"savedSearchId": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"uiStateJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
},
|
||||
"visState": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"query": {
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"query": {
|
||||
"properties": {
|
||||
"language": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"query": {
|
||||
"type": "keyword",
|
||||
"index": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"filters": {
|
||||
"type": "object",
|
||||
"enabled": false
|
||||
},
|
||||
"timefilter": {
|
||||
"type": "object",
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"test-deprecations-plugin": {
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"index": {
|
||||
"number_of_replicas": "0",
|
||||
"number_of_shards": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,6 +56,9 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
|
||||
// Required to load new platform plugins via `--plugin-path` flag.
|
||||
'--env.name=development',
|
||||
'--corePluginDeprecations.oldProperty=hello',
|
||||
'--corePluginDeprecations.secret=100',
|
||||
'--corePluginDeprecations.noLongerUsed=still_using',
|
||||
...plugins.map(
|
||||
(pluginDir) => `--plugin-path=${path.resolve(__dirname, 'plugins', pluginDir)}`
|
||||
),
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"id": "corePluginDeprecations",
|
||||
"version": "0.0.1",
|
||||
"kibanaVersion": "kibana",
|
||||
"configPath": ["corePluginDeprecations"],
|
||||
"server": true,
|
||||
"ui": false
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "core_plugin_deprecations",
|
||||
"version": "1.0.0",
|
||||
"main": "target/test/plugin_functional/plugins/core_plugin_deprecations",
|
||||
"kibana": {
|
||||
"version": "kibana",
|
||||
"templateVersion": "1.0.0"
|
||||
},
|
||||
"license": "SSPL-1.0 OR Elastic License 2.0",
|
||||
"scripts": {
|
||||
"kbn": "node ../../../../scripts/kbn.js",
|
||||
"build": "rm -rf './target' && ../../../../node_modules/.bin/tsc"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { AppMountParameters } from 'kibana/public';
|
||||
|
||||
const DeprecationsApp = () => <div>Deprcations App</div>;
|
||||
|
||||
export const renderApp = ({ element }: AppMountParameters) => {
|
||||
ReactDOM.render(<DeprecationsApp />, element);
|
||||
|
||||
return () => ReactDOM.unmountComponentAtNode(element);
|
||||
};
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { PluginInitializer, PluginInitializerContext } from 'kibana/public';
|
||||
import {
|
||||
CorePluginDeprecationsPlugin,
|
||||
CorePluginDeprecationsPluginSetup,
|
||||
CorePluginDeprecationsPluginStart,
|
||||
} from './plugin';
|
||||
|
||||
export const plugin: PluginInitializer<
|
||||
CorePluginDeprecationsPluginSetup,
|
||||
CorePluginDeprecationsPluginStart
|
||||
> = (context: PluginInitializerContext) => new CorePluginDeprecationsPlugin(context);
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { CoreSetup, Plugin, PluginInitializerContext } from 'kibana/public';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
env?: PluginInitializerContext['env'];
|
||||
}
|
||||
}
|
||||
|
||||
export class CorePluginDeprecationsPlugin
|
||||
implements Plugin<CorePluginDeprecationsPluginSetup, CorePluginDeprecationsPluginStart> {
|
||||
constructor(pluginContext: PluginInitializerContext) {
|
||||
window.env = pluginContext.env;
|
||||
}
|
||||
public setup(core: CoreSetup) {
|
||||
core.application.register({
|
||||
id: 'core-plugin-deprecations',
|
||||
title: 'Core Plugin Deprecations',
|
||||
async mount(params) {
|
||||
const { renderApp } = await import('./application');
|
||||
await core.getStartServices();
|
||||
return renderApp(params);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public start() {}
|
||||
|
||||
public stop() {}
|
||||
}
|
||||
|
||||
export type CorePluginDeprecationsPluginSetup = ReturnType<CorePluginDeprecationsPlugin['setup']>;
|
||||
export type CorePluginDeprecationsPluginStart = ReturnType<CorePluginDeprecationsPlugin['start']>;
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import { get } from 'lodash';
|
||||
import type { PluginConfigDescriptor } from 'kibana/server';
|
||||
import type { ConfigDeprecation } from '@kbn/config';
|
||||
|
||||
const configSchema = schema.object({
|
||||
newProperty: schema.maybe(schema.string({ defaultValue: 'Some string' })),
|
||||
noLongerUsed: schema.maybe(schema.string()),
|
||||
secret: schema.maybe(schema.number({ defaultValue: 42 })),
|
||||
});
|
||||
|
||||
type ConfigType = TypeOf<typeof configSchema>;
|
||||
|
||||
const configSecretDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => {
|
||||
if (get(settings, 'corePluginDeprecations.secret') !== 42) {
|
||||
addDeprecation({
|
||||
documentationUrl: 'config-secret-doc-url',
|
||||
message:
|
||||
'Kibana plugin funcitonal tests will no longer allow corePluginDeprecations.secret ' +
|
||||
'config to be set to anything except 42.',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
export const config: PluginConfigDescriptor<ConfigType> = {
|
||||
schema: configSchema,
|
||||
deprecations: ({ rename, unused }) => [
|
||||
rename('oldProperty', 'newProperty'),
|
||||
unused('noLongerUsed'),
|
||||
configSecretDeprecation,
|
||||
],
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { CorePluginDeprecationsPlugin } from './plugin';
|
||||
|
||||
export { config } from './config';
|
||||
export const plugin = () => new CorePluginDeprecationsPlugin();
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { Plugin, CoreSetup, GetDeprecationsContext, DeprecationsDetails } from 'kibana/server';
|
||||
import { registerRoutes } from './routes';
|
||||
async function getDeprecations({
|
||||
savedObjectsClient,
|
||||
}: GetDeprecationsContext): Promise<DeprecationsDetails[]> {
|
||||
const deprecations: DeprecationsDetails[] = [];
|
||||
const { total } = await savedObjectsClient.find({ type: 'test-deprecations-plugin', perPage: 1 });
|
||||
|
||||
deprecations.push({
|
||||
message: `CorePluginDeprecationsPlugin is a deprecated feature for testing.`,
|
||||
documentationUrl: 'test-url',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
manualSteps: ['Step a', 'Step b'],
|
||||
},
|
||||
});
|
||||
|
||||
if (total > 0) {
|
||||
deprecations.push({
|
||||
message: `SavedObject test-deprecations-plugin is still being used.`,
|
||||
documentationUrl: 'another-test-url',
|
||||
level: 'critical',
|
||||
correctiveActions: {},
|
||||
});
|
||||
}
|
||||
|
||||
return deprecations;
|
||||
}
|
||||
|
||||
export class CorePluginDeprecationsPlugin implements Plugin {
|
||||
public setup(core: CoreSetup, deps: {}) {
|
||||
registerRoutes(core.http);
|
||||
core.savedObjects.registerType({
|
||||
name: 'test-deprecations-plugin',
|
||||
hidden: false,
|
||||
namespaceType: 'single',
|
||||
mappings: {
|
||||
properties: {
|
||||
title: { type: 'text' },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
core.deprecations.registerDeprecations({ getDeprecations });
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public stop() {}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { HttpServiceSetup } from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
export function registerRoutes(http: HttpServiceSetup) {
|
||||
const router = http.createRouter();
|
||||
router.post(
|
||||
{
|
||||
path: '/api/core_deprecations_resolve/',
|
||||
validate: {
|
||||
body: schema.object({
|
||||
mockFail: schema.maybe(schema.boolean()),
|
||||
keyId: schema.maybe(schema.string()),
|
||||
deprecationDetails: schema.object({
|
||||
domainId: schema.string(),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async (context, req, res) => {
|
||||
const { mockFail, keyId } = req.body;
|
||||
if (mockFail === true) {
|
||||
return res.badRequest({
|
||||
body: new Error('Mocking api failure'),
|
||||
});
|
||||
}
|
||||
|
||||
if (keyId) {
|
||||
const client = context.core.savedObjects.getClient();
|
||||
await client.delete('test-deprecations-plugin', keyId, {
|
||||
refresh: true,
|
||||
});
|
||||
}
|
||||
|
||||
return res.ok();
|
||||
}
|
||||
);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"extends": "../../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./target",
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"index.ts",
|
||||
"public/**/*.ts",
|
||||
"public/**/*.tsx",
|
||||
"server/**/*.ts",
|
||||
"../../../../typings/**/*",
|
||||
],
|
||||
"exclude": [],
|
||||
"references": [
|
||||
{ "path": "../../../../src/core/tsconfig.json" }
|
||||
]
|
||||
}
|
247
test/plugin_functional/test_suites/core/deprecations.ts
Normal file
247
test/plugin_functional/test_suites/core/deprecations.ts
Normal file
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import type { DomainDeprecationDetails, DeprecationsGetResponse } from 'src/core/server/types';
|
||||
import type { ResolveDeprecationResponse } from 'src/core/public';
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const PageObjects = getPageObjects(['common']);
|
||||
const browser = getService('browser');
|
||||
|
||||
const CorePluginDeprecationsPluginDeprecations = [
|
||||
{
|
||||
level: 'critical',
|
||||
message:
|
||||
'"corePluginDeprecations.oldProperty" is deprecated and has been replaced by "corePluginDeprecations.newProperty"',
|
||||
correctiveActions: {
|
||||
manualSteps: [
|
||||
'Replace "corePluginDeprecations.oldProperty" with "corePluginDeprecations.newProperty" in the Kibana config file, CLI flag, or environment variable (in Docker only).',
|
||||
],
|
||||
},
|
||||
domainId: 'corePluginDeprecations',
|
||||
},
|
||||
{
|
||||
level: 'critical',
|
||||
message: 'corePluginDeprecations.noLongerUsed is deprecated and is no longer used',
|
||||
correctiveActions: {
|
||||
manualSteps: [
|
||||
'Remove "corePluginDeprecations.noLongerUsed" from the Kibana config file, CLI flag, or environment variable (in Docker only)',
|
||||
],
|
||||
},
|
||||
domainId: 'corePluginDeprecations',
|
||||
},
|
||||
{
|
||||
level: 'critical',
|
||||
message:
|
||||
'Kibana plugin funcitonal tests will no longer allow corePluginDeprecations.secret config to be set to anything except 42.',
|
||||
correctiveActions: {},
|
||||
documentationUrl: 'config-secret-doc-url',
|
||||
domainId: 'corePluginDeprecations',
|
||||
},
|
||||
{
|
||||
message: 'CorePluginDeprecationsPlugin is a deprecated feature for testing.',
|
||||
documentationUrl: 'test-url',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
manualSteps: ['Step a', 'Step b'],
|
||||
},
|
||||
domainId: 'corePluginDeprecations',
|
||||
},
|
||||
{
|
||||
message: 'SavedObject test-deprecations-plugin is still being used.',
|
||||
documentationUrl: 'another-test-url',
|
||||
level: 'critical',
|
||||
correctiveActions: {},
|
||||
domainId: 'corePluginDeprecations',
|
||||
},
|
||||
];
|
||||
|
||||
describe('deprecations service', () => {
|
||||
before(() => esArchiver.load('../functional/fixtures/es_archiver/deprecations_service'));
|
||||
after(() => esArchiver.unload('../functional/fixtures/es_archiver/deprecations_service'));
|
||||
|
||||
describe('GET /api/deprecations/', async () => {
|
||||
it('returns registered config deprecations and feature deprecations', async () => {
|
||||
const { body } = await supertest.get('/api/deprecations/').set('kbn-xsrf', 'true');
|
||||
|
||||
const { deprecations } = body as DeprecationsGetResponse;
|
||||
expect(Array.isArray(deprecations)).to.be(true);
|
||||
const corePluginDeprecations = deprecations.filter(
|
||||
({ domainId }) => domainId === 'corePluginDeprecations'
|
||||
);
|
||||
|
||||
expect(corePluginDeprecations).to.eql(CorePluginDeprecationsPluginDeprecations);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Public API', () => {
|
||||
before(async () => await PageObjects.common.navigateToApp('home'));
|
||||
|
||||
it('#getAllDeprecations returns all deprecations plugin deprecations', async () => {
|
||||
const result = await browser.executeAsync<DomainDeprecationDetails[]>((cb) => {
|
||||
return window._coreProvider.start.core.deprecations.getAllDeprecations().then(cb);
|
||||
});
|
||||
|
||||
const corePluginDeprecations = result.filter(
|
||||
({ domainId }) => domainId === 'corePluginDeprecations'
|
||||
);
|
||||
|
||||
expect(corePluginDeprecations).to.eql(CorePluginDeprecationsPluginDeprecations);
|
||||
});
|
||||
|
||||
it('#getDeprecations returns domain deprecations', async () => {
|
||||
const corePluginDeprecations = await browser.executeAsync<DomainDeprecationDetails[]>(
|
||||
(cb) => {
|
||||
return window._coreProvider.start.core.deprecations
|
||||
.getDeprecations('corePluginDeprecations')
|
||||
.then(cb);
|
||||
}
|
||||
);
|
||||
|
||||
expect(corePluginDeprecations).to.eql(CorePluginDeprecationsPluginDeprecations);
|
||||
});
|
||||
|
||||
describe('resolveDeprecation', () => {
|
||||
it('fails on missing correctiveActions.api', async () => {
|
||||
const resolveResult = await browser.executeAsync<ResolveDeprecationResponse>((cb) => {
|
||||
return window._coreProvider.start.core.deprecations
|
||||
.resolveDeprecation({
|
||||
message: 'CorePluginDeprecationsPlugin is a deprecated feature for testing.',
|
||||
documentationUrl: 'test-url',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
manualSteps: ['Step a', 'Step b'],
|
||||
},
|
||||
domainId: 'corePluginDeprecations',
|
||||
})
|
||||
.then(cb);
|
||||
});
|
||||
|
||||
expect(resolveResult).to.eql({
|
||||
reason: 'deprecation has no correctiveAction via api.',
|
||||
status: 'fail',
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on bad request from correctiveActions.api', async () => {
|
||||
const resolveResult = await browser.executeAsync<ResolveDeprecationResponse>((cb) => {
|
||||
return window._coreProvider.start.core.deprecations
|
||||
.resolveDeprecation({
|
||||
message: 'CorePluginDeprecationsPlugin is a deprecated feature for testing.',
|
||||
documentationUrl: 'test-url',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
api: {
|
||||
method: 'POST',
|
||||
path: '/api/core_deprecations_resolve/',
|
||||
body: {
|
||||
mockFail: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
domainId: 'corePluginDeprecations',
|
||||
})
|
||||
.then(cb);
|
||||
});
|
||||
|
||||
expect(resolveResult).to.eql({
|
||||
reason: 'Mocking api failure',
|
||||
status: 'fail',
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on 404 request from correctiveActions.api', async () => {
|
||||
const resolveResult = await browser.executeAsync<ResolveDeprecationResponse>((cb) => {
|
||||
return window._coreProvider.start.core.deprecations
|
||||
.resolveDeprecation({
|
||||
message: 'CorePluginDeprecationsPlugin is a deprecated feature for testing.',
|
||||
documentationUrl: 'test-url',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
api: {
|
||||
method: 'POST',
|
||||
path: '/api/invalid_route_not_registered/',
|
||||
body: {
|
||||
mockFail: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
domainId: 'corePluginDeprecations',
|
||||
})
|
||||
.then(cb);
|
||||
});
|
||||
|
||||
expect(resolveResult).to.eql({
|
||||
reason: 'Not Found',
|
||||
status: 'fail',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns { status: ok } on successful correctiveActions.api', async () => {
|
||||
const savedObjectId = await supertest
|
||||
.get('/api/saved_objects/_find?type=test-deprecations-plugin')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200)
|
||||
.then(({ body }) => {
|
||||
expect(body.total).to.be(1);
|
||||
return body.saved_objects[0].id;
|
||||
});
|
||||
|
||||
const resolveResult = await browser.executeAsync<ResolveDeprecationResponse>(
|
||||
(keyId, cb) => {
|
||||
return window._coreProvider.start.core.deprecations
|
||||
.resolveDeprecation({
|
||||
message: 'CorePluginDeprecationsPlugin is a deprecated feature for testing.',
|
||||
documentationUrl: 'test-url',
|
||||
level: 'warning',
|
||||
correctiveActions: {
|
||||
api: {
|
||||
method: 'POST',
|
||||
path: '/api/core_deprecations_resolve/',
|
||||
body: { keyId },
|
||||
},
|
||||
},
|
||||
domainId: 'corePluginDeprecations',
|
||||
})
|
||||
.then(cb);
|
||||
},
|
||||
savedObjectId
|
||||
);
|
||||
|
||||
expect(resolveResult).to.eql({ status: 'ok' });
|
||||
await supertest
|
||||
.get('/api/saved_objects/_find?type=test-deprecations-plugin')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200)
|
||||
.then(({ body }) => {
|
||||
expect(body.total).to.be(0);
|
||||
});
|
||||
|
||||
const { deprecations } = await supertest
|
||||
.get('/api/deprecations/')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.then(
|
||||
({ body }): Promise<DeprecationsGetResponse> => {
|
||||
return body;
|
||||
}
|
||||
);
|
||||
|
||||
const deprecation = deprecations.find(
|
||||
({ message }) => message === 'SavedObject test-deprecations-plugin is still being used.'
|
||||
);
|
||||
|
||||
expect(deprecation).to.eql(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -10,6 +10,7 @@ import { PluginFunctionalProviderContext } from '../../services';
|
|||
|
||||
export default function ({ loadTestFile }: PluginFunctionalProviderContext) {
|
||||
describe('core', function () {
|
||||
loadTestFile(require.resolve('./deprecations'));
|
||||
loadTestFile(require.resolve('./route'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@ describe('monitoring plugin deprecations', function () {
|
|||
|
||||
beforeAll(function () {
|
||||
const deprecations = deprecationsModule({ rename, renameFromRoot });
|
||||
transformDeprecations = (settings, fromPath, log = noop) => {
|
||||
deprecations.forEach((deprecation) => deprecation(settings, fromPath, log));
|
||||
transformDeprecations = (settings, fromPath, addDeprecation = noop) => {
|
||||
deprecations.forEach((deprecation) => deprecation(settings, fromPath, addDeprecation));
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -31,9 +31,9 @@ describe('monitoring plugin deprecations', function () {
|
|||
},
|
||||
};
|
||||
|
||||
const log = jest.fn();
|
||||
transformDeprecations(settings, fromPath, log);
|
||||
expect(log).not.toHaveBeenCalled();
|
||||
const addDeprecation = jest.fn();
|
||||
transformDeprecations(settings, fromPath, addDeprecation);
|
||||
expect(addDeprecation).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`shouldn't log when email_address is specified`, function () {
|
||||
|
@ -46,9 +46,9 @@ describe('monitoring plugin deprecations', function () {
|
|||
},
|
||||
};
|
||||
|
||||
const log = jest.fn();
|
||||
transformDeprecations(settings, fromPath, log);
|
||||
expect(log).not.toHaveBeenCalled();
|
||||
const addDeprecation = jest.fn();
|
||||
transformDeprecations(settings, fromPath, addDeprecation);
|
||||
expect(addDeprecation).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`should log when email_address is missing, but alerts/notifications are both enabled`, function () {
|
||||
|
@ -60,9 +60,9 @@ describe('monitoring plugin deprecations', function () {
|
|||
},
|
||||
};
|
||||
|
||||
const log = jest.fn();
|
||||
transformDeprecations(settings, fromPath, log);
|
||||
expect(log).toHaveBeenCalled();
|
||||
const addDeprecation = jest.fn();
|
||||
transformDeprecations(settings, fromPath, addDeprecation);
|
||||
expect(addDeprecation).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -70,65 +70,65 @@ describe('monitoring plugin deprecations', function () {
|
|||
it('logs a warning if elasticsearch.username is set to "elastic"', () => {
|
||||
const settings = { elasticsearch: { username: 'elastic' } };
|
||||
|
||||
const log = jest.fn();
|
||||
transformDeprecations(settings, fromPath, log);
|
||||
expect(log).toHaveBeenCalled();
|
||||
const addDeprecation = jest.fn();
|
||||
transformDeprecations(settings, fromPath, addDeprecation);
|
||||
expect(addDeprecation).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('logs a warning if elasticsearch.username is set to "kibana"', () => {
|
||||
const settings = { elasticsearch: { username: 'kibana' } };
|
||||
|
||||
const log = jest.fn();
|
||||
transformDeprecations(settings, fromPath, log);
|
||||
expect(log).toHaveBeenCalled();
|
||||
const addDeprecation = jest.fn();
|
||||
transformDeprecations(settings, fromPath, addDeprecation);
|
||||
expect(addDeprecation).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not log a warning if elasticsearch.username is set to something besides "elastic" or "kibana"', () => {
|
||||
const settings = { elasticsearch: { username: 'otheruser' } };
|
||||
|
||||
const log = jest.fn();
|
||||
transformDeprecations(settings, fromPath, log);
|
||||
expect(log).not.toHaveBeenCalled();
|
||||
const addDeprecation = jest.fn();
|
||||
transformDeprecations(settings, fromPath, addDeprecation);
|
||||
expect(addDeprecation).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not log a warning if elasticsearch.username is unset', () => {
|
||||
const settings = { elasticsearch: { username: undefined } };
|
||||
|
||||
const log = jest.fn();
|
||||
transformDeprecations(settings, fromPath, log);
|
||||
expect(log).not.toHaveBeenCalled();
|
||||
const addDeprecation = jest.fn();
|
||||
transformDeprecations(settings, fromPath, addDeprecation);
|
||||
expect(addDeprecation).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('logs a warning if ssl.key is set and ssl.certificate is not', () => {
|
||||
const settings = { elasticsearch: { ssl: { key: '' } } };
|
||||
|
||||
const log = jest.fn();
|
||||
transformDeprecations(settings, fromPath, log);
|
||||
expect(log).toHaveBeenCalled();
|
||||
const addDeprecation = jest.fn();
|
||||
transformDeprecations(settings, fromPath, addDeprecation);
|
||||
expect(addDeprecation).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('logs a warning if ssl.certificate is set and ssl.key is not', () => {
|
||||
const settings = { elasticsearch: { ssl: { certificate: '' } } };
|
||||
|
||||
const log = jest.fn();
|
||||
transformDeprecations(settings, fromPath, log);
|
||||
expect(log).toHaveBeenCalled();
|
||||
const addDeprecation = jest.fn();
|
||||
transformDeprecations(settings, fromPath, addDeprecation);
|
||||
expect(addDeprecation).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not log a warning if both ssl.key and ssl.certificate are set', () => {
|
||||
const settings = { elasticsearch: { ssl: { key: '', certificate: '' } } };
|
||||
|
||||
const log = jest.fn();
|
||||
transformDeprecations(settings, fromPath, log);
|
||||
expect(log).not.toHaveBeenCalled();
|
||||
const addDeprecation = jest.fn();
|
||||
transformDeprecations(settings, fromPath, addDeprecation);
|
||||
expect(addDeprecation).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('xpack_api_polling_frequency_millis', () => {
|
||||
it('should call rename for this renamed config key', () => {
|
||||
const settings = { xpack_api_polling_frequency_millis: 30000 };
|
||||
const log = jest.fn();
|
||||
transformDeprecations(settings, fromPath, log);
|
||||
const addDeprecation = jest.fn();
|
||||
transformDeprecations(settings, fromPath, addDeprecation);
|
||||
expect(rename).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -44,41 +44,41 @@ export const deprecations = ({
|
|||
'monitoring.ui.elasticsearch.logFetchCount'
|
||||
),
|
||||
renameFromRoot('xpack.monitoring', 'monitoring'),
|
||||
(config, fromPath, logger) => {
|
||||
(config, fromPath, addDeprecation) => {
|
||||
const emailNotificationsEnabled = get(config, 'cluster_alerts.email_notifications.enabled');
|
||||
if (emailNotificationsEnabled && !get(config, CLUSTER_ALERTS_ADDRESS_CONFIG_KEY)) {
|
||||
logger(
|
||||
`Config key [${fromPath}.${CLUSTER_ALERTS_ADDRESS_CONFIG_KEY}] will be required for email notifications to work in 7.0."`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Config key [${fromPath}.${CLUSTER_ALERTS_ADDRESS_CONFIG_KEY}] will be required for email notifications to work in 7.0."`,
|
||||
});
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(config, fromPath, logger) => {
|
||||
(config, fromPath, addDeprecation) => {
|
||||
const es: Record<string, any> = get(config, 'elasticsearch');
|
||||
if (es) {
|
||||
if (es.username === 'elastic') {
|
||||
logger(
|
||||
`Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.`,
|
||||
});
|
||||
} else if (es.username === 'kibana') {
|
||||
logger(
|
||||
`Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.`,
|
||||
});
|
||||
}
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(config, fromPath, logger) => {
|
||||
(config, fromPath, addDeprecation) => {
|
||||
const ssl: Record<string, any> = get(config, 'elasticsearch.ssl');
|
||||
if (ssl) {
|
||||
if (ssl.key !== undefined && ssl.certificate === undefined) {
|
||||
logger(
|
||||
`Setting [${fromPath}.key] without [${fromPath}.certificate] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Setting [${fromPath}.key] without [${fromPath}.certificate] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`,
|
||||
});
|
||||
} else if (ssl.certificate !== undefined && ssl.key === undefined) {
|
||||
logger(
|
||||
`Setting [${fromPath}.certificate] without [${fromPath}.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Setting [${fromPath}.certificate] without [${fromPath}.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`,
|
||||
});
|
||||
}
|
||||
}
|
||||
return config;
|
||||
|
|
|
@ -21,7 +21,7 @@ const applyReportingDeprecations = (settings: Record<string, any> = {}) => {
|
|||
deprecation,
|
||||
path: CONFIG_PATH,
|
||||
})),
|
||||
(msg) => deprecationMessages.push(msg)
|
||||
() => ({ message }) => deprecationMessages.push(message)
|
||||
);
|
||||
return {
|
||||
messages: deprecationMessages,
|
||||
|
|
|
@ -24,12 +24,12 @@ export const config: PluginConfigDescriptor<ReportingConfigType> = {
|
|||
unused('poll.jobCompletionNotifier.intervalErrorMultiplier'),
|
||||
unused('poll.jobsRefresh.intervalErrorMultiplier'),
|
||||
unused('kibanaApp'),
|
||||
(settings, fromPath, log) => {
|
||||
(settings, fromPath, addDeprecation) => {
|
||||
const reporting = get(settings, fromPath);
|
||||
if (reporting?.index) {
|
||||
log(
|
||||
`"${fromPath}.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `"${fromPath}.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details`,
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
},
|
||||
|
|
|
@ -20,7 +20,7 @@ const applyConfigDeprecations = (settings: Record<string, any> = {}) => {
|
|||
deprecation,
|
||||
path: 'xpack.security',
|
||||
})),
|
||||
(msg) => deprecationMessages.push(msg)
|
||||
() => ({ message }) => deprecationMessages.push(message)
|
||||
);
|
||||
return {
|
||||
messages: deprecationMessages,
|
||||
|
|
|
@ -22,16 +22,17 @@ export const securityConfigDeprecationProvider: ConfigDeprecationProvider = ({
|
|||
unused('authorization.legacyFallback.enabled'),
|
||||
unused('authc.saml.maxRedirectURLSize'),
|
||||
// Deprecation warning for the old array-based format of `xpack.security.authc.providers`.
|
||||
(settings, fromPath, log) => {
|
||||
(settings, fromPath, addDeprecation) => {
|
||||
if (Array.isArray(settings?.xpack?.security?.authc?.providers)) {
|
||||
log(
|
||||
'Defining `xpack.security.authc.providers` as an array of provider types is deprecated. Use extended `object` format instead.'
|
||||
);
|
||||
addDeprecation({
|
||||
message:
|
||||
'Defining `xpack.security.authc.providers` as an array of provider types is deprecated. Use extended `object` format instead.',
|
||||
});
|
||||
}
|
||||
|
||||
return settings;
|
||||
},
|
||||
(settings, fromPath, log) => {
|
||||
(settings, fromPath, addDeprecation) => {
|
||||
const hasProviderType = (providerType: string) => {
|
||||
const providers = settings?.xpack?.security?.authc?.providers;
|
||||
if (Array.isArray(providers)) {
|
||||
|
@ -44,31 +45,34 @@ export const securityConfigDeprecationProvider: ConfigDeprecationProvider = ({
|
|||
};
|
||||
|
||||
if (hasProviderType('basic') && hasProviderType('token')) {
|
||||
log(
|
||||
'Enabling both `basic` and `token` authentication providers in `xpack.security.authc.providers` is deprecated. Login page will only use `token` provider.'
|
||||
);
|
||||
addDeprecation({
|
||||
message:
|
||||
'Enabling both `basic` and `token` authentication providers in `xpack.security.authc.providers` is deprecated. Login page will only use `token` provider.',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
},
|
||||
(settings, fromPath, log) => {
|
||||
(settings, fromPath, addDeprecation) => {
|
||||
const samlProviders = (settings?.xpack?.security?.authc?.providers?.saml ?? {}) as Record<
|
||||
string,
|
||||
any
|
||||
>;
|
||||
if (Object.values(samlProviders).find((provider) => !!provider.maxRedirectURLSize)) {
|
||||
log(
|
||||
'`xpack.security.authc.providers.saml.<provider-name>.maxRedirectURLSize` is deprecated and is no longer used'
|
||||
);
|
||||
addDeprecation({
|
||||
message:
|
||||
'`xpack.security.authc.providers.saml.<provider-name>.maxRedirectURLSize` is deprecated and is no longer used',
|
||||
});
|
||||
}
|
||||
|
||||
return settings;
|
||||
},
|
||||
(settings, fromPath, log) => {
|
||||
(settings, fromPath, addDeprecation) => {
|
||||
if (settings?.xpack?.security?.enabled === false) {
|
||||
log(
|
||||
'Disabling the security plugin (`xpack.security.enabled`) will not be supported in the next major version (8.0). ' +
|
||||
'To turn off security features, disable them in Elasticsearch instead.'
|
||||
);
|
||||
addDeprecation({
|
||||
message:
|
||||
'Disabling the security plugin (`xpack.security.enabled`) will not be supported in the next major version (8.0). ' +
|
||||
'To turn off security features, disable them in Elasticsearch instead.',
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
},
|
||||
|
|
|
@ -19,7 +19,7 @@ const applyConfigDeprecations = (settings: Record<string, any> = {}) => {
|
|||
deprecation,
|
||||
path: '',
|
||||
})),
|
||||
(msg) => deprecationMessages.push(msg)
|
||||
() => ({ message }) => deprecationMessages.push(message)
|
||||
);
|
||||
return {
|
||||
messages: deprecationMessages,
|
||||
|
|
|
@ -24,11 +24,11 @@ export function createConfig$(context: PluginInitializerContext) {
|
|||
return context.config.create<TypeOf<typeof ConfigSchema>>();
|
||||
}
|
||||
|
||||
const disabledDeprecation: ConfigDeprecation = (config, fromPath, log) => {
|
||||
const disabledDeprecation: ConfigDeprecation = (config, fromPath, addDeprecation) => {
|
||||
if (config.xpack?.spaces?.enabled === false) {
|
||||
log(
|
||||
`Disabling the spaces plugin (xpack.spaces.enabled) will not be supported in the next major version (8.0)`
|
||||
);
|
||||
addDeprecation({
|
||||
message: `Disabling the spaces plugin (xpack.spaces.enabled) will not be supported in the next major version (8.0)`,
|
||||
});
|
||||
}
|
||||
return config;
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue