[ML] Switching to config files for serverless ML features (#166477)

Switches to using the serverless config file to enabled/disable ML
features rather than a function shared from the setup contract.
Storing these flags in a config file means they are already available
when setup runs and so can be used when registering integrations into
other plugins.

Removes the dependency on ML from `security_solution_serverless`,
`serverless_observability` and `serverless_search`
This commit is contained in:
James Gowdy 2023-09-21 14:46:19 +01:00 committed by GitHub
parent c544c52b88
commit e0ae59fa60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 159 additions and 129 deletions

View file

@ -35,3 +35,7 @@ no_data_page.analyticsNoDataPageFlavor: 'serverless_search'
# Disable Dev tools
xpack.grokdebugger.enabled: false
xpack.painless_lab.enabled: false
xpack.ml.ad.enabled: false
xpack.ml.dfa.enabled: false
xpack.ml.nlp.enabled: true

View file

@ -48,3 +48,7 @@ xpack.apm.featureFlags.storageExplorerAvailable: false
# Specify in telemetry the project type
telemetry.labels.serverless: observability
xpack.ml.ad.enabled: true
xpack.ml.dfa.enabled: false
xpack.ml.nlp.enabled: false

View file

@ -35,3 +35,7 @@ xpack.fleet.internal.registry.spec.max: '3.0'
# Serverless security specific options
xpack.securitySolution.enableExperimental:
- discoverInTimeline
xpack.ml.ad.enabled: true
xpack.ml.dfa.enabled: true
xpack.ml.nlp.enabled: false

View 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { schema, type TypeOf } from '@kbn/config-schema';
const enabledSchema = schema.maybe(
schema.object({
enabled: schema.boolean(),
})
);
export const configSchema = schema.object({
ad: enabledSchema,
dfa: enabledSchema,
nlp: enabledSchema,
});
export type ConfigSchema = TypeOf<typeof configSchema>;

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { PluginInitializerContext } from '@kbn/core/server';
import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server';
import { MlServerPlugin } from './plugin';
export type { MlPluginSetup, MlPluginStart } from './plugin';
export type {
@ -26,5 +26,10 @@ export {
InsufficientMLCapabilities,
MLPrivilegesUninitialized,
} from './shared';
import { configSchema, type ConfigSchema } from './config_schema';
export const plugin = (ctx: PluginInitializerContext) => new MlServerPlugin(ctx);
export const config: PluginConfigDescriptor<ConfigSchema> = {
schema: configSchema,
};
export const plugin = (ctx: PluginInitializerContext<ConfigSchema>) => new MlServerPlugin(ctx);

View file

@ -8,12 +8,12 @@
import Boom from '@hapi/boom';
import { i18n } from '@kbn/i18n';
import rison from '@kbn/rison';
import { Duration } from 'moment/moment';
import type { Duration } from 'moment/moment';
import { memoize } from 'lodash';
import {
FIELD_FORMAT_IDS,
IFieldFormat,
SerializedFieldFormat,
type IFieldFormat,
type SerializedFieldFormat,
} from '@kbn/field-formats-plugin/common';
import { isDefined } from '@kbn/ml-is-defined';
import {
@ -24,12 +24,12 @@ import {
ML_ANOMALY_RESULT_TYPE,
} from '@kbn/ml-anomaly-utils';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import { MlClient } from '../ml_client';
import {
import type { MlClient } from '../ml_client';
import type {
MlAnomalyDetectionAlertParams,
MlAnomalyDetectionAlertPreviewRequest,
} from '../../routes/schemas/alerting_schema';
import {
import type {
AlertExecutionResult,
InfluencerAnomalyAlertDoc,
PreviewResponse,
@ -37,11 +37,11 @@ import {
RecordAnomalyAlertDoc,
TopHitsResultsKeys,
} from '../../../common/types/alerts';
import { AnomalyDetectionAlertContext } from './register_anomaly_detection_alert_type';
import type { AnomalyDetectionAlertContext } from './register_anomaly_detection_alert_type';
import { resolveMaxTimeInterval } from '../../../common/util/job_utils';
import { getTopNBuckets, resolveLookbackInterval } from '../../../common/util/alerts';
import type { DatafeedsService } from '../../models/job_service/datafeeds';
import { FieldFormatsRegistryProvider } from '../../../common/types/kibana';
import type { FieldFormatsRegistryProvider } from '../../../common/types/kibana';
import type { AwaitReturnType } from '../../../common/types/common';
import { getTypicalAndActualValues } from '../../models/results_service/results_service';
import type { GetDataViewsService } from '../data_views_utils';

View file

@ -6,17 +6,17 @@
*/
import { groupBy, keyBy, memoize, partition } from 'lodash';
import { KibanaRequest, Logger, SavedObjectsClientContract } from '@kbn/core/server';
import type { KibanaRequest, Logger, SavedObjectsClientContract } from '@kbn/core/server';
import { i18n } from '@kbn/i18n';
import { MlJob } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import type { MlJob } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { isDefined } from '@kbn/ml-is-defined';
import { MlClient } from '../ml_client';
import { JobSelection } from '../../routes/schemas/alerting_schema';
import { datafeedsProvider, DatafeedsService } from '../../models/job_service/datafeeds';
import type { MlClient } from '../ml_client';
import type { JobSelection } from '../../routes/schemas/alerting_schema';
import { datafeedsProvider, type DatafeedsService } from '../../models/job_service/datafeeds';
import { ALL_JOBS_SELECTION, HEALTH_CHECK_NAMES } from '../../../common/constants/alerts';
import { DatafeedStats } from '../../../common/types/anomaly_detection_jobs';
import { GetGuards } from '../../shared_services/shared_services';
import {
import type { DatafeedStats } from '../../../common/types/anomaly_detection_jobs';
import type { GetGuards } from '../../shared_services/shared_services';
import type {
AnomalyDetectionJobsHealthAlertContext,
DelayedDataResponse,
JobsErrorsResponse,
@ -28,12 +28,12 @@ import {
getResultJobsHealthRuleConfig,
resolveLookbackInterval,
} from '../../../common/util/alerts';
import { AnnotationService } from '../../models/annotation_service/annotation';
import type { AnnotationService } from '../../models/annotation_service/annotation';
import { annotationServiceProvider } from '../../models/annotation_service';
import { parseInterval } from '../../../common/util/parse_interval';
import {
jobAuditMessagesProvider,
JobAuditMessagesService,
type JobAuditMessagesService,
} from '../../models/job_audit_messages/job_audit_messages';
import type { FieldFormatsRegistryProvider } from '../../../common/types/kibana';

View file

@ -6,8 +6,8 @@
*/
import { i18n } from '@kbn/i18n';
import { KibanaRequest } from '@kbn/core/server';
import {
import type { KibanaRequest } from '@kbn/core/server';
import type {
ActionGroup,
AlertInstanceContext,
AlertInstanceState,
@ -17,11 +17,14 @@ import { ML_ALERT_TYPES } from '../../../common/constants/alerts';
import { PLUGIN_ID } from '../../../common/constants/app';
import { MINIMUM_FULL_LICENSE } from '../../../common/license';
import {
MlAnomalyDetectionAlertParams,
type MlAnomalyDetectionAlertParams,
mlAnomalyDetectionAlertParams,
} from '../../routes/schemas/alerting_schema';
import { RegisterAlertParams } from './register_ml_alerts';
import { InfluencerAnomalyAlertDoc, RecordAnomalyAlertDoc } from '../../../common/types/alerts';
import type { RegisterAlertParams } from './register_ml_alerts';
import {
InfluencerAnomalyAlertDoc,
type RecordAnomalyAlertDoc,
} from '../../../common/types/alerts';
/**
* Base Anomaly detection alerting rule context.

View file

@ -6,13 +6,13 @@
*/
import { i18n } from '@kbn/i18n';
import { KibanaRequest } from '@kbn/core/server';
import {
import type { KibanaRequest } from '@kbn/core/server';
import type {
MlDatafeedState,
MlJobState,
MlJobStats,
} from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import {
import type {
ActionGroup,
AlertInstanceContext,
AlertInstanceState,
@ -24,9 +24,9 @@ import { PLUGIN_ID } from '../../../common/constants/app';
import { MINIMUM_FULL_LICENSE } from '../../../common/license';
import {
anomalyDetectionJobsHealthRuleParams,
AnomalyDetectionJobsHealthRuleParams,
type AnomalyDetectionJobsHealthRuleParams,
} from '../../routes/schemas/alerting_schema';
import { RegisterAlertParams } from './register_ml_alerts';
import type { RegisterAlertParams } from './register_ml_alerts';
import type { JobMessage } from '../../../common/types/audit_message';
type ModelSizeStats = MlJobStats['model_size_stats'];

View file

@ -5,12 +5,13 @@
* 2.0.
*/
import { Logger } from '@kbn/core/server';
import { AlertingPlugin } from '@kbn/alerting-plugin/server';
import type { Logger } from '@kbn/core/server';
import type { AlertingPlugin } from '@kbn/alerting-plugin/server';
import { registerAnomalyDetectionAlertType } from './register_anomaly_detection_alert_type';
import { SharedServices } from '../../shared_services';
import type { SharedServices } from '../../shared_services';
import { registerJobsMonitoringRuleType } from './register_jobs_monitoring_rule_type';
import { MlServicesProviders } from '../../shared_services/shared_services';
import type { MlServicesProviders } from '../../shared_services/shared_services';
import type { MlFeatures } from '../../types';
export interface RegisterAlertParams {
alerting: AlertingPlugin['setup'];
@ -19,7 +20,9 @@ export interface RegisterAlertParams {
mlServicesProviders: MlServicesProviders;
}
export function registerMlAlerts(alertParams: RegisterAlertParams) {
registerAnomalyDetectionAlertType(alertParams);
registerJobsMonitoringRuleType(alertParams);
export function registerMlAlerts(alertParams: RegisterAlertParams, enabledFeatures: MlFeatures) {
if (enabledFeatures.ad === true) {
registerAnomalyDetectionAlertType(alertParams);
registerJobsMonitoringRuleType(alertParams);
}
}

View file

@ -10,13 +10,16 @@ import {
CASE_ATTACHMENT_TYPE_ID_ANOMALY_EXPLORER_CHARTS,
CASE_ATTACHMENT_TYPE_ID_ANOMALY_SWIMLANE,
} from '../../common/constants/cases';
import type { MlFeatures } from '../types';
export function registerCasesPersistableState(cases: CasesSetup) {
cases.attachmentFramework.registerPersistableState({
id: CASE_ATTACHMENT_TYPE_ID_ANOMALY_SWIMLANE,
});
export function registerCasesPersistableState(cases: CasesSetup, enabledFeatures: MlFeatures) {
if (enabledFeatures.ad === true) {
cases.attachmentFramework.registerPersistableState({
id: CASE_ATTACHMENT_TYPE_ID_ANOMALY_SWIMLANE,
});
cases.attachmentFramework.registerPersistableState({
id: CASE_ATTACHMENT_TYPE_ID_ANOMALY_EXPLORER_CHARTS,
});
cases.attachmentFramework.registerPersistableState({
id: CASE_ATTACHMENT_TYPE_ID_ANOMALY_EXPLORER_CHARTS,
});
}
}

View file

@ -10,8 +10,8 @@ import type { HomeServerPluginSetup } from '@kbn/home-plugin/server';
import type { MlFeatures } from '../types';
export function registerSampleDataSetLinks(
enabledFeatures: MlFeatures,
home: HomeServerPluginSetup
home: HomeServerPluginSetup,
enabledFeatures: MlFeatures
) {
if (enabledFeatures.ad === true) {
const sampleDataLinkLabel = i18n.translate('xpack.ml.sampleDataLinkLabel', {

View file

@ -18,17 +18,19 @@ import type {
SavedObjectsServiceStart,
UiSettingsServiceStart,
} from '@kbn/core/server';
import type { SecurityPluginSetup } from '@kbn/security-plugin/server';
import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server';
import type { SecurityPluginSetup } from '@kbn/security-plugin/server';
import type { PluginStart as DataViewsPluginStart } from '@kbn/data-views-plugin/server';
import type { SpacesPluginSetup } from '@kbn/spaces-plugin/server';
import { FieldFormatsStart } from '@kbn/field-formats-plugin/server';
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/server';
import type { HomeServerPluginSetup } from '@kbn/home-plugin/server';
import type { CasesSetup } from '@kbn/cases-plugin/server';
import type { MlFeatures, PluginsSetup, PluginsStart, RouteInitialization } from './types';
import type { MlCapabilities } from '../common/types/capabilities';
import type { ConfigSchema } from './config_schema';
import { jsonSchemaRoutes } from './routes/json_schema';
import { notificationsRoutes } from './routes/notifications';
import type { MlFeatures, PluginsSetup, PluginsStart, RouteInitialization } from './types';
import { PLUGIN_ID } from '../common/constants/app';
import type { MlCapabilities } from '../common/types/capabilities';
import { initMlServerLog } from './lib/log';
import { annotationRoutes } from './routes/annotations';
import { calendars } from './routes/calendars';
@ -66,15 +68,9 @@ import { alertingRoutes } from './routes/alerting';
import { registerCollector } from './usage';
import { SavedObjectsSyncService } from './saved_objects/sync_task';
import { registerCasesPersistableState } from './lib/register_cases';
import { registerSampleDataSetLinks } from './lib/register_sameple_data_set_links';
import { registerSampleDataSetLinks } from './lib/register_sample_data_set_links';
type SetFeaturesEnabled = (features: MlFeatures) => void;
interface MlSetup {
setFeaturesEnabled: SetFeaturesEnabled;
}
export type MlPluginSetup = SharedServices & MlSetup;
export type MlPluginSetup = SharedServices;
export type MlPluginStart = void;
export class MlServerPlugin
@ -90,6 +86,7 @@ export class MlServerPlugin
private spacesPlugin: SpacesPluginSetup | undefined;
private security: SecurityPluginSetup | undefined;
private home: HomeServerPluginSetup | null = null;
private cases: CasesSetup | null | undefined = null;
private dataViews: DataViewsPluginStart | null = null;
private isMlReady: Promise<void>;
private setMlReady: () => void = () => {};
@ -99,22 +96,20 @@ export class MlServerPlugin
dfa: true,
nlp: true,
};
private isServerless: boolean = false;
private registerCases: () => void = () => {};
private registerSampleDatasetsIntegration: () => void = () => {};
constructor(ctx: PluginInitializerContext) {
constructor(ctx: PluginInitializerContext<ConfigSchema>) {
this.log = ctx.logger.get();
this.mlLicense = new MlLicense();
this.isMlReady = new Promise((resolve) => (this.setMlReady = resolve));
this.savedObjectsSyncService = new SavedObjectsSyncService(this.log);
this.isServerless = ctx.env.packageInfo.buildFlavor === 'serverless';
this.initEnabledFeatures(ctx.config.get());
}
public setup(coreSetup: CoreSetup<PluginsStart>, plugins: PluginsSetup): MlPluginSetup {
this.spacesPlugin = plugins.spaces;
this.security = plugins.security;
this.home = plugins.home;
this.cases = plugins.cases;
const { admin, user, apmUser } = getPluginPrivileges();
plugins.features.registerKibanaFeature({
@ -222,25 +217,38 @@ export class MlServerPlugin
),
mlLicense: this.mlLicense,
getEnabledFeatures: () => Object.assign({}, this.enabledFeatures),
isServerless: this.isServerless,
};
annotationRoutes(routeInit, plugins.security);
calendars(routeInit);
dataFeedRoutes(routeInit);
dataFrameAnalyticsRoutes(routeInit);
dataRecognizer(routeInit);
// Register Anomaly Detection routes
if (this.enabledFeatures.ad) {
annotationRoutes(routeInit, plugins.security);
calendars(routeInit);
dataFeedRoutes(routeInit);
dataRecognizer(routeInit);
filtersRoutes(routeInit);
jobAuditMessagesRoutes(routeInit);
jobRoutes(routeInit);
jobServiceRoutes(routeInit);
resultsServiceRoutes(routeInit);
jobValidationRoutes(routeInit);
}
// Register Data Frame Analytics routes
if (this.enabledFeatures.dfa) {
dataFrameAnalyticsRoutes(routeInit);
}
// Register Trained Model Management routes
if (this.enabledFeatures.dfa || this.enabledFeatures.nlp) {
modelManagementRoutes(routeInit);
trainedModelsRoutes(routeInit);
}
// Register Miscellaneous routes
dataVisualizerRoutes(routeInit);
fieldsService(routeInit);
filtersRoutes(routeInit);
indicesRoutes(routeInit);
jobAuditMessagesRoutes(routeInit);
jobRoutes(routeInit);
jobServiceRoutes(routeInit);
managementRoutes(routeInit);
modelManagementRoutes(routeInit);
resultsServiceRoutes(routeInit);
jobValidationRoutes(routeInit);
savedObjectsRoutes(routeInit, {
getSpaces,
resolveMlCapabilities,
@ -250,7 +258,6 @@ export class MlServerPlugin
cloud: plugins.cloud,
resolveMlCapabilities,
});
trainedModelsRoutes(routeInit);
notificationsRoutes(routeInit);
jsonSchemaRoutes(routeInit);
alertingRoutes(routeInit, sharedServicesProviders);
@ -258,27 +265,17 @@ export class MlServerPlugin
initMlServerLog({ log: this.log });
if (plugins.alerting) {
registerMlAlerts({
alerting: plugins.alerting,
logger: this.log,
mlSharedServices: sharedServicesProviders,
mlServicesProviders: internalServicesProviders,
});
registerMlAlerts(
{
alerting: plugins.alerting,
logger: this.log,
mlSharedServices: sharedServicesProviders,
mlServicesProviders: internalServicesProviders,
},
this.enabledFeatures
);
}
this.registerCases = () => {
if (plugins.cases) {
registerCasesPersistableState(plugins.cases);
}
};
this.registerSampleDatasetsIntegration = () => {
// called in start once enabledFeatures is available
if (this.home) {
registerSampleDataSetLinks(this.enabledFeatures, this.home);
}
};
registerKibanaSettings(coreSetup);
if (plugins.usageCollection) {
@ -289,19 +286,7 @@ export class MlServerPlugin
registerCollector(plugins.usageCollection, getIndexForType);
}
const setFeaturesEnabled = (features: MlFeatures) => {
if (features.ad !== undefined) {
this.enabledFeatures.ad = features.ad;
}
if (features.dfa !== undefined) {
this.enabledFeatures.dfa = features.dfa;
}
if (features.nlp !== undefined) {
this.enabledFeatures.nlp = features.nlp;
}
};
return { ...sharedServicesProviders, setFeaturesEnabled };
return { ...sharedServicesProviders };
}
public start(coreStart: CoreStart, plugins: PluginsStart): MlPluginStart {
@ -323,8 +308,12 @@ export class MlServerPlugin
}
if (mlLicense.isMlEnabled() && mlLicense.isFullLicense()) {
this.registerCases();
this.registerSampleDatasetsIntegration();
if (this.cases) {
registerCasesPersistableState(this.cases, this.enabledFeatures);
}
if (this.home) {
registerSampleDataSetLinks(this.home, this.enabledFeatures);
}
}
// check whether the job saved objects exist
// and create them if needed.
@ -343,4 +332,16 @@ export class MlServerPlugin
public stop() {
this.mlLicense.unsubscribe();
}
private initEnabledFeatures(config: ConfigSchema) {
if (config.ad?.enabled !== undefined) {
this.enabledFeatures.ad = config.ad.enabled;
}
if (config.dfa?.enabled !== undefined) {
this.enabledFeatures.dfa = config.dfa.enabled;
}
if (config.nlp?.enabled !== undefined) {
this.enabledFeatures.nlp = config.nlp.enabled;
}
}
}

View file

@ -81,7 +81,6 @@ export interface RouteInitialization {
mlLicense: MlLicense;
routeGuard: RouteGuard;
getEnabledFeatures: () => MlFeatures;
isServerless: boolean;
}
export type MlFeatures = Record<'ad' | 'dfa' | 'nlp', boolean>;

View file

@ -14,7 +14,6 @@
"requiredPlugins": [
"kibanaReact",
"management",
"ml",
"security",
"securitySolution",
"serverless",

View file

@ -65,8 +65,6 @@ export class SecuritySolutionServerlessPlugin
pluginsSetup.securitySolution.setAppFeaturesConfigurator(appFeaturesConfigurator);
}
pluginsSetup.ml.setFeaturesEnabled({ ad: true, dfa: true, nlp: false });
this.cloudSecurityUsageReportingTask = new SecurityUsageReportingTask({
core: coreSetup,
logFactory: this.initializerContext.logger,

View file

@ -17,7 +17,6 @@ import type {
} from '@kbn/task-manager-plugin/server';
import type { CloudSetup } from '@kbn/cloud-plugin/server';
import type { SecuritySolutionEssPluginSetup } from '@kbn/security-solution-ess/server';
import type { MlPluginSetup } from '@kbn/ml-plugin/server';
import type { FleetStartContract } from '@kbn/fleet-plugin/server';
import type { ServerlessPluginSetup } from '@kbn/serverless/server';
@ -36,7 +35,6 @@ export interface SecuritySolutionServerlessPluginSetupDeps {
securitySolutionEss: SecuritySolutionEssPluginSetup;
serverless: ServerlessPluginSetup;
features: PluginSetupContract;
ml: MlPluginSetup;
taskManager: TaskManagerSetupContract;
cloud: CloudSetup;
}

View file

@ -32,7 +32,6 @@
"@kbn/i18n",
"@kbn/shared-ux-page-kibana-template",
"@kbn/features-plugin",
"@kbn/ml-plugin",
"@kbn/kibana-utils-plugin",
"@kbn/task-manager-plugin",
"@kbn/cloud-plugin",

View file

@ -22,7 +22,6 @@
"observabilityShared",
"kibanaReact",
"management",
"ml",
"cloud"
],
"optionalPlugins": [],

View file

@ -27,8 +27,6 @@ export class ServerlessObservabilityPlugin
constructor(_initializerContext: PluginInitializerContext) {}
public setup(_coreSetup: CoreSetup, pluginsSetup: SetupDependencies) {
pluginsSetup.ml.setFeaturesEnabled({ ad: true, dfa: false, nlp: false });
pluginsSetup.serverless.setupProjectSettings(OBSERVABILITY_PROJECT_SETTINGS);
return {};
}

View file

@ -5,7 +5,6 @@
* 2.0.
*/
import type { MlPluginSetup } from '@kbn/ml-plugin/server';
import { ServerlessPluginSetup } from '@kbn/serverless/server';
// eslint-disable-next-line @typescript-eslint/no-empty-interface
@ -17,6 +16,5 @@ export interface ServerlessObservabilityPluginStart {}
export interface StartDependencies {}
export interface SetupDependencies {
ml: MlPluginSetup;
serverless: ServerlessPluginSetup;
}

View file

@ -22,7 +22,6 @@
"@kbn/observability-shared-plugin",
"@kbn/kibana-react-plugin",
"@kbn/shared-ux-chrome-navigation",
"@kbn/ml-plugin",
"@kbn/i18n",
"@kbn/management-cards-navigation",
"@kbn/cloud-plugin",

View file

@ -19,7 +19,6 @@
"devTools",
"discover",
"management",
"ml",
"searchprofiler",
"security",
"serverless",

View file

@ -71,7 +71,6 @@ export class ServerlessSearchPlugin
registerIndicesRoutes(dependencies);
});
pluginsSetup.ml.setFeaturesEnabled({ ad: false, dfa: false, nlp: true });
pluginsSetup.serverless.setupProjectSettings(SEARCH_PROJECT_SETTINGS);
return {};
}

View file

@ -6,7 +6,6 @@
*/
import type { SecurityPluginStart } from '@kbn/security-plugin/server';
import type { MlPluginSetup } from '@kbn/ml-plugin/server';
import type { ServerlessPluginSetup } from '@kbn/serverless/server';
// eslint-disable-next-line @typescript-eslint/no-empty-interface
@ -18,6 +17,5 @@ export interface StartDependencies {
security: SecurityPluginStart;
}
export interface SetupDependencies {
ml: MlPluginSetup;
serverless: ServerlessPluginSetup;
}

View file

@ -27,7 +27,6 @@
"@kbn/security-plugin",
"@kbn/cloud-plugin",
"@kbn/share-plugin",
"@kbn/ml-plugin",
"@kbn/management-cards-navigation",
"@kbn/core-elasticsearch-server",
"@kbn/search-api-panels",