mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Ingest Pipelines] Add license checks for processors (#154525)
This commit is contained in:
parent
dd083a351a
commit
aefc949911
8 changed files with 89 additions and 16 deletions
|
@ -11,6 +11,7 @@
|
|||
"ingest_pipelines"
|
||||
],
|
||||
"requiredPlugins": [
|
||||
"licensing",
|
||||
"management",
|
||||
"features",
|
||||
"share",
|
||||
|
|
|
@ -6,8 +6,14 @@
|
|||
*/
|
||||
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { licensingMock } from '@kbn/licensing-plugin/server/mocks';
|
||||
import { setup, SetupResult } from './pipeline_processors_editor.helpers';
|
||||
import { Pipeline } from '../../../../../common/types';
|
||||
import {
|
||||
extractProcessorDetails,
|
||||
getProcessorTypesAndLabels,
|
||||
} from '../components/processor_form/processors/common_fields/processor_type_field';
|
||||
import { mapProcessorTypeToDescriptor } from '../components/shared/map_processor_type_to_form';
|
||||
|
||||
const testProcessors: Pick<Pipeline, 'processors'> = {
|
||||
processors: [
|
||||
|
@ -96,6 +102,28 @@ describe('Pipeline Editor', () => {
|
|||
expect(d).toEqual({ test: { if: '1 == 1' } });
|
||||
});
|
||||
|
||||
it('Shows inference and redact processors for licenses > platinum', async () => {
|
||||
const basicLicense = licensingMock.createLicense({
|
||||
license: { status: 'active', type: 'basic' },
|
||||
});
|
||||
const platinumLicense = licensingMock.createLicense({
|
||||
license: { status: 'active', type: 'platinum' },
|
||||
});
|
||||
|
||||
// Get the list of processors that are only available for platinum licenses
|
||||
const processorsForPlatinumLicense = extractProcessorDetails(mapProcessorTypeToDescriptor)
|
||||
.filter((processor) => processor.forLicenseAtLeast === 'platinum')
|
||||
.map(({ value, label }) => ({ label, value }));
|
||||
|
||||
// Check that the list of processors for platinum licenses is not included in the list of processors for basic licenses
|
||||
expect(getProcessorTypesAndLabels(basicLicense)).toEqual(
|
||||
expect.not.arrayContaining(processorsForPlatinumLicense)
|
||||
);
|
||||
expect(getProcessorTypesAndLabels(platinumLicense)).toEqual(
|
||||
expect.arrayContaining(processorsForPlatinumLicense)
|
||||
);
|
||||
});
|
||||
|
||||
it('edits a processor without removing unknown processor.options', async () => {
|
||||
const { actions, exists, form } = testBed;
|
||||
// Open the edit processor form for the set processor
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { FunctionComponent, ReactNode } from 'react';
|
||||
import React, { FunctionComponent, ReactNode, useMemo } from 'react';
|
||||
import { flow } from 'fp-ts/lib/function';
|
||||
import { map } from 'fp-ts/lib/Array';
|
||||
|
||||
|
@ -15,6 +15,7 @@ import {
|
|||
FieldValidateResponse,
|
||||
VALIDATION_TYPES,
|
||||
} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
|
||||
import { ILicense } from '../../../../../../../types';
|
||||
import {
|
||||
FIELD_TYPES,
|
||||
FieldConfig,
|
||||
|
@ -25,11 +26,12 @@ import {
|
|||
|
||||
import { getProcessorDescriptor, mapProcessorTypeToDescriptor } from '../../../shared';
|
||||
|
||||
const extractProcessorTypesAndLabels = flow(
|
||||
export const extractProcessorDetails = flow(
|
||||
Object.entries,
|
||||
map(([type, { label }]) => ({
|
||||
map(([type, { label, forLicenseAtLeast }]) => ({
|
||||
label,
|
||||
value: type,
|
||||
...(forLicenseAtLeast ? { forLicenseAtLeast } : {}),
|
||||
})),
|
||||
(arr) => arr.sort((a, b) => a.label.localeCompare(b.label))
|
||||
);
|
||||
|
@ -39,9 +41,17 @@ interface ProcessorTypeAndLabel {
|
|||
label: string;
|
||||
}
|
||||
|
||||
const processorTypesAndLabels: ProcessorTypeAndLabel[] = extractProcessorTypesAndLabels(
|
||||
mapProcessorTypeToDescriptor
|
||||
);
|
||||
export const getProcessorTypesAndLabels = (license: ILicense | null) => {
|
||||
return (
|
||||
extractProcessorDetails(mapProcessorTypeToDescriptor)
|
||||
// Filter out any processors that are not available for the current license type
|
||||
.filter((option) => {
|
||||
return option.forLicenseAtLeast ? license?.hasAtLeast(option.forLicenseAtLeast) : true;
|
||||
})
|
||||
// Convert to EuiComboBox options
|
||||
.map(({ value, label }) => ({ label, value }))
|
||||
);
|
||||
};
|
||||
|
||||
interface Props {
|
||||
initialType?: string;
|
||||
|
@ -68,9 +78,12 @@ const typeConfig: FieldConfig<string> = {
|
|||
|
||||
export const ProcessorTypeField: FunctionComponent<Props> = ({ initialType }) => {
|
||||
const {
|
||||
services: { documentation },
|
||||
services: { documentation, license },
|
||||
} = useKibana();
|
||||
const esDocUrl = documentation.getEsDocsBasePath();
|
||||
// Some processors are only available for certain license types
|
||||
const processorOptions = useMemo(() => getProcessorTypesAndLabels(license), [license]);
|
||||
|
||||
return (
|
||||
<UseField<string> config={typeConfig} defaultValue={initialType} path="type">
|
||||
{(typeField) => {
|
||||
|
@ -128,7 +141,7 @@ export const ProcessorTypeField: FunctionComponent<Props> = ({ initialType }) =>
|
|||
defaultMessage: 'Type and then hit "ENTER"',
|
||||
}
|
||||
)}
|
||||
options={processorTypesAndLabels}
|
||||
options={processorOptions}
|
||||
selectedOptions={selectedOptions}
|
||||
onCreateOption={onCreateComboOption}
|
||||
onChange={(options: Array<EuiComboBoxOptionOption<string>>) => {
|
||||
|
|
|
@ -10,6 +10,8 @@ import React, { ReactNode } from 'react';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiCode, EuiLink } from '@elastic/eui';
|
||||
|
||||
import { LicenseType } from '../../../../../types';
|
||||
|
||||
import {
|
||||
Append,
|
||||
Bytes,
|
||||
|
@ -69,6 +71,10 @@ interface FieldDescriptor {
|
|||
* Default
|
||||
*/
|
||||
getDefaultDescription: (processorOptions: Record<string, any>) => string | undefined;
|
||||
/**
|
||||
* Some processors are only available for certain license types
|
||||
*/
|
||||
forLicenseAtLeast?: LicenseType;
|
||||
}
|
||||
|
||||
type MapProcessorTypeToDescriptor = Record<string, FieldDescriptor>;
|
||||
|
@ -453,6 +459,7 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = {
|
|||
},
|
||||
inference: {
|
||||
FieldsComponent: Inference,
|
||||
forLicenseAtLeast: 'platinum',
|
||||
docLinkPath: '/inference-processor.html',
|
||||
label: i18n.translate('xpack.ingestPipelines.processors.label.inference', {
|
||||
defaultMessage: 'Inference',
|
||||
|
@ -580,6 +587,7 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = {
|
|||
},
|
||||
redact: {
|
||||
FieldsComponent: Redact,
|
||||
forLicenseAtLeast: 'platinum',
|
||||
docLinkPath: '/redact-processor.html',
|
||||
label: i18n.translate('xpack.ingestPipelines.processors.label.redact', {
|
||||
defaultMessage: 'Redact',
|
||||
|
|
|
@ -16,6 +16,7 @@ import { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
|||
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import type { FileUploadPluginStart } from '@kbn/file-upload-plugin/public';
|
||||
import { KibanaContextProvider, KibanaThemeProvider } from '../shared_imports';
|
||||
import { ILicense } from '../types';
|
||||
|
||||
import { API_BASE_PATH } from '../../common/constants';
|
||||
|
||||
|
@ -42,6 +43,7 @@ export interface AppServices {
|
|||
share: SharePluginStart;
|
||||
fileUpload: FileUploadPluginStart;
|
||||
application: ApplicationStart;
|
||||
license: ILicense | null;
|
||||
}
|
||||
|
||||
export interface CoreServices {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { CoreSetup } from '@kbn/core/public';
|
||||
import { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
||||
|
||||
import { StartDependencies } from '../types';
|
||||
import { StartDependencies, ILicense } from '../types';
|
||||
import {
|
||||
documentationService,
|
||||
uiMetricService,
|
||||
|
@ -18,11 +18,15 @@ import {
|
|||
} from './services';
|
||||
import { renderApp } from '.';
|
||||
|
||||
export interface AppParams extends ManagementAppMountParams {
|
||||
license: ILicense | null;
|
||||
}
|
||||
|
||||
export async function mountManagementSection(
|
||||
{ http, getStartServices, notifications }: CoreSetup<StartDependencies>,
|
||||
params: ManagementAppMountParams
|
||||
params: AppParams
|
||||
) {
|
||||
const { element, setBreadcrumbs, history, theme$ } = params;
|
||||
const { element, setBreadcrumbs, history, theme$, license } = params;
|
||||
const [coreStart, depsStart] = await getStartServices();
|
||||
const {
|
||||
docLinks,
|
||||
|
@ -47,6 +51,7 @@ export async function mountManagementSection(
|
|||
fileUpload: depsStart.fileUpload,
|
||||
application,
|
||||
executionContext,
|
||||
license,
|
||||
};
|
||||
|
||||
return renderApp(element, I18nContext, services, { http }, { theme$ });
|
||||
|
|
|
@ -6,16 +6,20 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { CoreSetup, Plugin } from '@kbn/core/public';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { CoreStart, CoreSetup, Plugin } from '@kbn/core/public';
|
||||
|
||||
import { PLUGIN_ID } from '../common/constants';
|
||||
import { uiMetricService, apiService } from './application/services';
|
||||
import { SetupDependencies, StartDependencies } from './types';
|
||||
import { SetupDependencies, StartDependencies, ILicense } from './types';
|
||||
import { IngestPipelinesLocatorDefinition } from './locator';
|
||||
|
||||
export class IngestPipelinesPlugin
|
||||
implements Plugin<void, void, SetupDependencies, StartDependencies>
|
||||
{
|
||||
private license: ILicense | null = null;
|
||||
private licensingSubscription?: Subscription;
|
||||
|
||||
public setup(coreSetup: CoreSetup<StartDependencies>, plugins: SetupDependencies): void {
|
||||
const { management, usageCollection, share } = plugins;
|
||||
const { http, getStartServices } = coreSetup;
|
||||
|
@ -42,7 +46,10 @@ export class IngestPipelinesPlugin
|
|||
docTitle.change(pluginName);
|
||||
|
||||
const { mountManagementSection } = await import('./application/mount_management_section');
|
||||
const unmountAppCallback = await mountManagementSection(coreSetup, params);
|
||||
const unmountAppCallback = await mountManagementSection(coreSetup, {
|
||||
...params,
|
||||
license: this.license,
|
||||
});
|
||||
|
||||
return () => {
|
||||
docTitle.reset();
|
||||
|
@ -58,7 +65,13 @@ export class IngestPipelinesPlugin
|
|||
);
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public start(core: CoreStart, { licensing }: StartDependencies) {
|
||||
this.licensingSubscription = licensing?.license$.subscribe((license) => {
|
||||
this.license = license;
|
||||
});
|
||||
}
|
||||
|
||||
public stop() {}
|
||||
public stop() {
|
||||
this.licensingSubscription?.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import { ManagementSetup } from '@kbn/management-plugin/public';
|
|||
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||
import { SharePluginStart, SharePluginSetup } from '@kbn/share-plugin/public';
|
||||
import type { FileUploadPluginStart } from '@kbn/file-upload-plugin/public';
|
||||
import { LicensingPluginStart } from '@kbn/licensing-plugin/public';
|
||||
export type { LicenseType, ILicense } from '@kbn/licensing-plugin/public';
|
||||
|
||||
export interface SetupDependencies {
|
||||
management: ManagementSetup;
|
||||
|
@ -19,4 +21,5 @@ export interface SetupDependencies {
|
|||
export interface StartDependencies {
|
||||
share: SharePluginStart;
|
||||
fileUpload: FileUploadPluginStart;
|
||||
licensing?: LicensingPluginStart;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue