kibana/x-pack/platform/plugins/shared/ml/server/plugin.ts
Julia Rechkunova db1c118fa1
[8.x] [Discover] Rename Saved Search to Discover Session (#202217) (#204818)
# Backport

This will backport the following commits from `main` to `8.x`:
- [[Discover] Rename Saved Search to Discover Session
(#202217)](https://github.com/elastic/kibana/pull/202217)

<!--- Backport version: 8.9.8 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Julia
Rechkunova","email":"julia.rechkunova@elastic.co"},"sourceCommit":{"committedDate":"2024-12-18T12:45:32Z","message":"[Discover]
Rename Saved Search to Discover Session (#202217)\n\n- Closes
https://github.com/elastic/kibana/issues/174144\r\n\r\n##
Summary\r\n\r\nThis PR renames Saved Search into Discover Session in
UI.\r\n\r\n- [x] Discover\r\n- [x] Saved Objects page and modal\r\n- [x]
Docs\r\n- [x] Other occurrences \r\n\r\n<img width=\"810\"
alt=\"Screenshot 2024-12-16 at 15 20
10\"\r\nsrc=\"https://github.com/user-attachments/assets/e39083da-f496-4ed5-bbdc-8e184897fc41\"\r\n/>\r\n<img
width=\"1220\" alt=\"Screenshot 2024-12-11 at 14 40
15\"\r\nsrc=\"https://github.com/user-attachments/assets/a6dc3e29-e1a5-4304-8148-0108231cc9de\"\r\n/>\r\n<img
width=\"1476\" alt=\"Screenshot 2024-12-16 at 14 57
39\"\r\nsrc=\"https://github.com/user-attachments/assets/4b34c70e-e21a-4d82-85f2-f5a3cb7a3826\"\r\n/>\r\n\r\n\r\n###
Checklist\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[x]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [x] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] The PR
description includes the appropriate Release Notes section,\r\nand the
correct `release_note:*` label is applied per
the\r\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
wajihaparvez <wajiha.parvez@elastic.co>\r\nCo-authored-by: Davis McPhee
<davismcphee@hotmail.com>\r\nCo-authored-by: Julia Bardi
<90178898+juliaElastic@users.noreply.github.com>","sha":"40c90550f12f99f23e6b7d545c7427e30d648dab","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:enhancement","Team:Fleet","v9.0.0","Team:DataDiscovery","backport:prev-minor","ci:project-deploy-observability"],"number":202217,"url":"https://github.com/elastic/kibana/pull/202217","mergeCommit":{"message":"[Discover]
Rename Saved Search to Discover Session (#202217)\n\n- Closes
https://github.com/elastic/kibana/issues/174144\r\n\r\n##
Summary\r\n\r\nThis PR renames Saved Search into Discover Session in
UI.\r\n\r\n- [x] Discover\r\n- [x] Saved Objects page and modal\r\n- [x]
Docs\r\n- [x] Other occurrences \r\n\r\n<img width=\"810\"
alt=\"Screenshot 2024-12-16 at 15 20
10\"\r\nsrc=\"https://github.com/user-attachments/assets/e39083da-f496-4ed5-bbdc-8e184897fc41\"\r\n/>\r\n<img
width=\"1220\" alt=\"Screenshot 2024-12-11 at 14 40
15\"\r\nsrc=\"https://github.com/user-attachments/assets/a6dc3e29-e1a5-4304-8148-0108231cc9de\"\r\n/>\r\n<img
width=\"1476\" alt=\"Screenshot 2024-12-16 at 14 57
39\"\r\nsrc=\"https://github.com/user-attachments/assets/4b34c70e-e21a-4d82-85f2-f5a3cb7a3826\"\r\n/>\r\n\r\n\r\n###
Checklist\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[x]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [x] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] The PR
description includes the appropriate Release Notes section,\r\nand the
correct `release_note:*` label is applied per
the\r\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
wajihaparvez <wajiha.parvez@elastic.co>\r\nCo-authored-by: Davis McPhee
<davismcphee@hotmail.com>\r\nCo-authored-by: Julia Bardi
<90178898+juliaElastic@users.noreply.github.com>","sha":"40c90550f12f99f23e6b7d545c7427e30d648dab"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/202217","number":202217,"mergeCommit":{"message":"[Discover]
Rename Saved Search to Discover Session (#202217)\n\n- Closes
https://github.com/elastic/kibana/issues/174144\r\n\r\n##
Summary\r\n\r\nThis PR renames Saved Search into Discover Session in
UI.\r\n\r\n- [x] Discover\r\n- [x] Saved Objects page and modal\r\n- [x]
Docs\r\n- [x] Other occurrences \r\n\r\n<img width=\"810\"
alt=\"Screenshot 2024-12-16 at 15 20
10\"\r\nsrc=\"https://github.com/user-attachments/assets/e39083da-f496-4ed5-bbdc-8e184897fc41\"\r\n/>\r\n<img
width=\"1220\" alt=\"Screenshot 2024-12-11 at 14 40
15\"\r\nsrc=\"https://github.com/user-attachments/assets/a6dc3e29-e1a5-4304-8148-0108231cc9de\"\r\n/>\r\n<img
width=\"1476\" alt=\"Screenshot 2024-12-16 at 14 57
39\"\r\nsrc=\"https://github.com/user-attachments/assets/4b34c70e-e21a-4d82-85f2-f5a3cb7a3826\"\r\n/>\r\n\r\n\r\n###
Checklist\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[x]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [x] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] The PR
description includes the appropriate Release Notes section,\r\nand the
correct `release_note:*` label is applied per
the\r\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
wajihaparvez <wajiha.parvez@elastic.co>\r\nCo-authored-by: Davis McPhee
<davismcphee@hotmail.com>\r\nCo-authored-by: Julia Bardi
<90178898+juliaElastic@users.noreply.github.com>","sha":"40c90550f12f99f23e6b7d545c7427e30d648dab"}}]}]
BACKPORT-->
2024-12-19 21:38:57 +11:00

368 lines
13 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,
CoreAuditService,
} 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 { CasesServerSetup } from '@kbn/cases-plugin/server';
import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common';
import { KibanaFeatureScope } from '@kbn/features-plugin/common';
import type { PluginsSetup, PluginsStart, RouteInitialization } from './types';
import type { MlCapabilities } from '../common/types/capabilities';
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 { 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 type { SharedServices } from './shared_services';
import { createSharedServices } 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';
import { inferenceModelRoutes } from './routes/inference_models';
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: CasesServerSetup | null | undefined = null;
private dataViews: DataViewsPluginStart | null = null;
private auditService: CoreAuditService | 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,
scope: [KibanaFeatureScope.Spaces, KibanaFeatureScope.Security],
app: [PLUGIN_ID, 'kibana'],
catalogue: [PLUGIN_ID, `${PLUGIN_ID}_file_data_visualizer`],
privilegesTooltip: i18n.translate('xpack.ml.featureRegistry.privilegesTooltip', {
defaultMessage:
'Granting All or Read feature privilege for Machine Learning will also grant the equivalent feature privileges to certain types of Kibana saved objects, namely index patterns, dashboards, saved Discover sessions and visualizations as well as machine learning job, trained model and module saved objects.',
}),
management: {
insightsAndAlerting: ['jobsListLink', 'triggersActions'],
},
alerting: Object.values(ML_ALERT_TYPES).map((ruleTypeId) => ({
ruleTypeId,
consumers: [PLUGIN_ID, ALERTING_FEATURE_ID],
})),
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.auditService,
() => this.isMlReady,
this.compatibleModuleType,
this.enabledFeatures
);
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
inferenceModelRoutes(routeInit, plugins.cloud);
modelManagementRoutes(routeInit);
dataVisualizerRoutes(routeInit);
fieldsService(routeInit);
managementRoutes(routeInit);
savedObjectsRoutes(routeInit, {
getSpaces,
resolveMlCapabilities,
});
systemRoutes(routeInit, {
getSpaces,
cloud: plugins.cloud,
resolveMlCapabilities,
});
notificationsRoutes(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.auditService = coreStart.security.audit;
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()
.catch((err) => {
this.log.debug(`Error initializing jobs`, err);
})
.finally(() => {
this.setMlReady();
});
this.savedObjectsSyncService.scheduleSyncTask(plugins.taskManager, coreStart).catch((err) => {
this.log.debug(`Error scheduling saved objects sync task`, err);
});
});
}
public stop() {
this.mlLicense.unsubscribe();
}
}