mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
# Backport This will backport the following commits from `main` to `8.12`: - [[RAM] Stack management rules available with only ml feature (#174791)](https://github.com/elastic/kibana/pull/174791) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Xavier Mouligneau","email":"xavier.mouligneau@elastic.co"},"sourceCommit":{"committedDate":"2024-01-16T16:13:02Z","message":"[RAM] Stack management rules available with only ml feature (#174791)\n\n## Summary\r\n\r\nFix => https://github.com/elastic/kibana/issues/173573","sha":"5d5f0d10739647ea7a963327c72dcda5b845ade1","branchLabelMapping":{"^v8.13.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","Team:ResponseOps","Team:ML","v8.12.1","v8.13.0"],"title":"[RAM] Stack management rules available with only ml feature","number":174791,"url":"https://github.com/elastic/kibana/pull/174791","mergeCommit":{"message":"[RAM] Stack management rules available with only ml feature (#174791)\n\n## Summary\r\n\r\nFix => https://github.com/elastic/kibana/issues/173573","sha":"5d5f0d10739647ea7a963327c72dcda5b845ade1"}},"sourceBranch":"main","suggestedTargetBranches":["8.12"],"targetPullRequestStates":[{"branch":"8.12","label":"v8.12.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.13.0","branchLabelMappingKey":"^v8.13.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/174791","number":174791,"mergeCommit":{"message":"[RAM] Stack management rules available with only ml feature (#174791)\n\n## Summary\r\n\r\nFix => https://github.com/elastic/kibana/issues/173573","sha":"5d5f0d10739647ea7a963327c72dcda5b845ade1"}}]}] BACKPORT--> Co-authored-by: Xavier Mouligneau <xavier.mouligneau@elastic.co>
348 lines
12 KiB
TypeScript
348 lines
12 KiB
TypeScript
/*
|
|
* 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 { i18n } from '@kbn/i18n';
|
|
import type {
|
|
CoreSetup,
|
|
CoreStart,
|
|
Plugin,
|
|
KibanaRequest,
|
|
Logger,
|
|
PluginInitializerContext,
|
|
CapabilitiesStart,
|
|
IClusterClient,
|
|
SavedObjectsServiceStart,
|
|
UiSettingsServiceStart,
|
|
} from '@kbn/core/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 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 { PluginsSetup, PluginsStart, RouteInitialization } from './types';
|
|
import type { MlCapabilities } from '../common/types/capabilities';
|
|
import { jsonSchemaRoutes } from './routes/json_schema';
|
|
import { notificationsRoutes } from './routes/notifications';
|
|
import {
|
|
type MlFeatures,
|
|
PLUGIN_ID,
|
|
type ConfigSchema,
|
|
initEnabledFeatures,
|
|
type CompatibleModule,
|
|
} from '../common/constants/app';
|
|
import { initMlServerLog } from './lib/log';
|
|
import { annotationRoutes } from './routes/annotations';
|
|
import { calendars } from './routes/calendars';
|
|
import { dataFeedRoutes } from './routes/datafeeds';
|
|
import { dataFrameAnalyticsRoutes } from './routes/data_frame_analytics';
|
|
import { dataRecognizer } from './routes/modules';
|
|
import { dataVisualizerRoutes } from './routes/data_visualizer';
|
|
import { fieldsService } from './routes/fields_service';
|
|
import { filtersRoutes } from './routes/filters';
|
|
import { indicesRoutes } from './routes/indices';
|
|
import { jobAuditMessagesRoutes } from './routes/job_audit_messages';
|
|
import { jobRoutes } from './routes/anomaly_detectors';
|
|
import { jobServiceRoutes } from './routes/job_service';
|
|
import { savedObjectsRoutes } from './routes/saved_objects';
|
|
import { jobValidationRoutes } from './routes/job_validation';
|
|
import { resultsServiceRoutes } from './routes/results_service';
|
|
import { modelManagementRoutes } from './routes/model_management';
|
|
import { systemRoutes } from './routes/system';
|
|
import { MlLicense } from '../common/license';
|
|
import { createSharedServices, SharedServices } from './shared_services';
|
|
import { getPluginPrivileges } from '../common/types/capabilities';
|
|
import { setupCapabilitiesSwitcher } from './lib/capabilities';
|
|
import { registerKibanaSettings } from './lib/register_settings';
|
|
import { trainedModelsRoutes } from './routes/trained_models';
|
|
import { managementRoutes } from './routes/management';
|
|
import {
|
|
setupSavedObjects,
|
|
jobSavedObjectsInitializationFactory,
|
|
savedObjectClientsFactory,
|
|
} from './saved_objects';
|
|
import { RouteGuard } from './lib/route_guard';
|
|
import { registerMlAlerts } from './lib/alerts/register_ml_alerts';
|
|
import { ML_ALERT_TYPES } from '../common/constants/alerts';
|
|
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_sample_data_set_links';
|
|
|
|
export type MlPluginSetup = SharedServices;
|
|
export type MlPluginStart = void;
|
|
|
|
export class MlServerPlugin
|
|
implements Plugin<MlPluginSetup, MlPluginStart, PluginsSetup, PluginsStart>
|
|
{
|
|
private log: Logger;
|
|
private mlLicense: MlLicense;
|
|
private capabilities: CapabilitiesStart | null = null;
|
|
private clusterClient: IClusterClient | null = null;
|
|
private fieldsFormat: FieldFormatsStart | null = null;
|
|
private uiSettings: UiSettingsServiceStart | null = null;
|
|
private savedObjectsStart: SavedObjectsServiceStart | null = null;
|
|
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 = () => {};
|
|
private savedObjectsSyncService: SavedObjectsSyncService;
|
|
private enabledFeatures: MlFeatures = {
|
|
ad: true,
|
|
dfa: true,
|
|
nlp: true,
|
|
};
|
|
private compatibleModuleType: CompatibleModule | null = null;
|
|
|
|
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);
|
|
|
|
const config = ctx.config.get();
|
|
initEnabledFeatures(this.enabledFeatures, config);
|
|
this.compatibleModuleType = config.compatibleModuleType ?? null;
|
|
this.enabledFeatures = Object.freeze(this.enabledFeatures);
|
|
}
|
|
|
|
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({
|
|
id: PLUGIN_ID,
|
|
name: i18n.translate('xpack.ml.featureRegistry.mlFeatureName', {
|
|
defaultMessage: 'Machine Learning',
|
|
}),
|
|
order: 500,
|
|
category: DEFAULT_APP_CATEGORIES.kibana,
|
|
app: [PLUGIN_ID, 'kibana'],
|
|
catalogue: [PLUGIN_ID, `${PLUGIN_ID}_file_data_visualizer`],
|
|
management: {
|
|
insightsAndAlerting: ['jobsListLink', 'triggersActions'],
|
|
},
|
|
alerting: Object.values(ML_ALERT_TYPES),
|
|
privileges: {
|
|
all: admin,
|
|
read: user,
|
|
},
|
|
reserved: {
|
|
description: i18n.translate('xpack.ml.feature.reserved.description', {
|
|
defaultMessage:
|
|
'To grant users access, you should also assign either the machine_learning_user or machine_learning_admin role.',
|
|
}),
|
|
privileges: [
|
|
{
|
|
id: 'ml_user',
|
|
privilege: user,
|
|
},
|
|
{
|
|
id: 'ml_admin',
|
|
privilege: admin,
|
|
},
|
|
{
|
|
id: 'ml_apm_user',
|
|
privilege: apmUser,
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
// initialize capabilities switcher to add license filter to ml capabilities
|
|
setupCapabilitiesSwitcher(
|
|
coreSetup,
|
|
plugins.licensing.license$,
|
|
this.enabledFeatures,
|
|
this.log
|
|
);
|
|
setupSavedObjects(coreSetup.savedObjects);
|
|
this.savedObjectsSyncService.registerSyncTask(
|
|
plugins.taskManager,
|
|
plugins.security,
|
|
this.spacesPlugin !== undefined,
|
|
() => this.isMlReady
|
|
);
|
|
|
|
const { getInternalSavedObjectsClient, getMlSavedObjectsClient } = savedObjectClientsFactory(
|
|
() => this.savedObjectsStart
|
|
);
|
|
|
|
const getSpaces = plugins.spaces
|
|
? () => coreSetup.getStartServices().then(([, { spaces }]) => spaces!)
|
|
: undefined;
|
|
|
|
const getDataViews = () => {
|
|
if (this.dataViews === null) {
|
|
throw Error('Data views plugin not initialized');
|
|
}
|
|
return this.dataViews;
|
|
};
|
|
|
|
const resolveMlCapabilities = async (request: KibanaRequest) => {
|
|
if (this.capabilities === null) {
|
|
return null;
|
|
}
|
|
const capabilities = await this.capabilities.resolveCapabilities(request, {
|
|
capabilityPath: 'ml.*',
|
|
});
|
|
return capabilities.ml as MlCapabilities;
|
|
};
|
|
|
|
const { internalServicesProviders, sharedServicesProviders } = createSharedServices(
|
|
this.mlLicense,
|
|
getSpaces,
|
|
plugins.cloud,
|
|
plugins.security?.authz,
|
|
resolveMlCapabilities,
|
|
() => this.clusterClient,
|
|
() => getInternalSavedObjectsClient(),
|
|
() => this.uiSettings,
|
|
() => this.fieldsFormat,
|
|
getDataViews,
|
|
() => this.isMlReady,
|
|
this.compatibleModuleType
|
|
);
|
|
|
|
const routeInit: RouteInitialization = {
|
|
router: coreSetup.http.createRouter(),
|
|
routeGuard: new RouteGuard(
|
|
this.mlLicense,
|
|
getMlSavedObjectsClient,
|
|
getInternalSavedObjectsClient,
|
|
plugins.spaces,
|
|
plugins.security?.authz,
|
|
() => this.isMlReady,
|
|
() => this.dataViews,
|
|
coreSetup.getStartServices
|
|
),
|
|
mlLicense: this.mlLicense,
|
|
getEnabledFeatures: () => this.enabledFeatures,
|
|
};
|
|
|
|
// Register Anomaly Detection routes
|
|
if (this.enabledFeatures.ad) {
|
|
annotationRoutes(routeInit, plugins.security);
|
|
calendars(routeInit);
|
|
dataFeedRoutes(routeInit);
|
|
dataRecognizer(routeInit, this.compatibleModuleType);
|
|
filtersRoutes(routeInit);
|
|
jobAuditMessagesRoutes(routeInit);
|
|
jobRoutes(routeInit);
|
|
jobServiceRoutes(routeInit);
|
|
resultsServiceRoutes(routeInit);
|
|
jobValidationRoutes(routeInit);
|
|
}
|
|
|
|
// Register Data Frame Analytics routes
|
|
if (this.enabledFeatures.dfa) {
|
|
dataFrameAnalyticsRoutes(routeInit, plugins.cloud);
|
|
}
|
|
|
|
// Register Trained Model Management routes
|
|
if (this.enabledFeatures.dfa || this.enabledFeatures.nlp) {
|
|
trainedModelsRoutes(routeInit, plugins.cloud);
|
|
}
|
|
|
|
// Register Miscellaneous routes
|
|
modelManagementRoutes(routeInit);
|
|
dataVisualizerRoutes(routeInit);
|
|
fieldsService(routeInit);
|
|
indicesRoutes(routeInit);
|
|
managementRoutes(routeInit);
|
|
savedObjectsRoutes(routeInit, {
|
|
getSpaces,
|
|
resolveMlCapabilities,
|
|
});
|
|
systemRoutes(routeInit, {
|
|
getSpaces,
|
|
cloud: plugins.cloud,
|
|
resolveMlCapabilities,
|
|
});
|
|
notificationsRoutes(routeInit);
|
|
jsonSchemaRoutes(routeInit);
|
|
alertingRoutes(routeInit, sharedServicesProviders);
|
|
|
|
initMlServerLog({ log: this.log });
|
|
|
|
if (plugins.alerting) {
|
|
registerMlAlerts(
|
|
{
|
|
alerting: plugins.alerting,
|
|
logger: this.log,
|
|
mlSharedServices: sharedServicesProviders,
|
|
mlServicesProviders: internalServicesProviders,
|
|
},
|
|
this.enabledFeatures
|
|
);
|
|
}
|
|
|
|
registerKibanaSettings(coreSetup);
|
|
|
|
if (plugins.usageCollection) {
|
|
const getIndexForType = (type: string) =>
|
|
coreSetup
|
|
.getStartServices()
|
|
.then(([coreStart]) => coreStart.savedObjects.getIndexForType(type));
|
|
registerCollector(plugins.usageCollection, getIndexForType);
|
|
}
|
|
|
|
return { ...sharedServicesProviders };
|
|
}
|
|
|
|
public start(coreStart: CoreStart, plugins: PluginsStart): MlPluginStart {
|
|
this.uiSettings = coreStart.uiSettings;
|
|
this.fieldsFormat = plugins.fieldFormats;
|
|
this.capabilities = coreStart.capabilities;
|
|
this.clusterClient = coreStart.elasticsearch.client;
|
|
this.savedObjectsStart = coreStart.savedObjects;
|
|
this.dataViews = plugins.dataViews;
|
|
|
|
this.mlLicense.setup(plugins.licensing.license$, async (mlLicense: MlLicense) => {
|
|
if (mlLicense.isMlEnabled() === false || mlLicense.isFullLicense() === false) {
|
|
try {
|
|
await this.savedObjectsSyncService.unscheduleSyncTask(plugins.taskManager);
|
|
} catch (e) {
|
|
this.log.debug(`Error unscheduling saved objects sync task`, e);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (mlLicense.isMlEnabled() && mlLicense.isFullLicense()) {
|
|
if (this.cases) {
|
|
registerCasesPersistableState(this.cases, this.enabledFeatures, this.log);
|
|
}
|
|
if (this.home) {
|
|
registerSampleDataSetLinks(this.home, this.enabledFeatures, this.log);
|
|
}
|
|
}
|
|
// check whether the job saved objects exist
|
|
// and create them if needed.
|
|
const { initializeJobs } = jobSavedObjectsInitializationFactory(
|
|
coreStart,
|
|
this.security,
|
|
this.spacesPlugin !== undefined
|
|
);
|
|
initializeJobs().finally(() => {
|
|
this.setMlReady();
|
|
});
|
|
this.savedObjectsSyncService.scheduleSyncTask(plugins.taskManager, coreStart);
|
|
});
|
|
}
|
|
|
|
public stop() {
|
|
this.mlLicense.unsubscribe();
|
|
}
|
|
}
|