mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[ML] Adding shared services to ml setup contract (#59730)
* [ML] Adding shared services to ml setup contract * adding data recognizer * typescripting js client * adding results service * code clean up * adding generic ml index search * making cloud optional
This commit is contained in:
parent
ed68ede2b6
commit
d5c092811b
70 changed files with 511 additions and 173 deletions
32
x-pack/legacy/plugins/ml/common/types/ml_server_info.ts
Normal file
32
x-pack/legacy/plugins/ml/common/types/ml_server_info.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { CategorizationAnalyzer } from './categories';
|
||||
|
||||
export interface MlServerDefaults {
|
||||
anomaly_detectors: {
|
||||
categorization_examples_limit?: number;
|
||||
model_memory_limit?: string;
|
||||
model_snapshot_retention_days?: number;
|
||||
categorization_analyzer?: CategorizationAnalyzer;
|
||||
};
|
||||
datafeeds: { scroll_size?: number };
|
||||
}
|
||||
|
||||
export interface MlServerLimits {
|
||||
max_model_memory_limit?: string;
|
||||
}
|
||||
|
||||
export interface MlInfoResponse {
|
||||
defaults: MlServerDefaults;
|
||||
limits: MlServerLimits;
|
||||
native_code: {
|
||||
build_hash: string;
|
||||
version: string;
|
||||
};
|
||||
upgrade_mode: boolean;
|
||||
cloudId?: string;
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { SavedObjectAttributes } from 'src/core/public';
|
||||
import { SavedObjectAttributes } from 'kibana/public';
|
||||
import { Datafeed, Job } from '../types/anomaly_detection_jobs';
|
||||
|
||||
export interface ModuleJob {
|
||||
|
|
|
@ -10,7 +10,7 @@ import { Server } from 'src/legacy/server/kbn_server';
|
|||
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
|
||||
// @ts-ignore: could not find declaration file for module
|
||||
import { mirrorPluginStatus } from '../../server/lib/mirror_plugin_status';
|
||||
// @ts-ignore: could not find declaration file for module
|
||||
// @ts-ignore: importing JSON file
|
||||
import mappings from './mappings';
|
||||
|
||||
export const ml = (kibana: any) => {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { useReducer } from 'react';
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { SimpleSavedObject } from 'src/core/public';
|
||||
import { SimpleSavedObject } from 'kibana/public';
|
||||
import { ml } from '../../../../../services/ml_api_service';
|
||||
import { useMlContext } from '../../../../../contexts/ml';
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import React, { FC, Fragment } from 'react';
|
||||
import { IUiSettingsClient } from 'src/core/public';
|
||||
import { IUiSettingsClient } from 'kibana/public';
|
||||
|
||||
import { useTimefilter } from '../../contexts/kibana';
|
||||
import { NavigationMenu } from '../../components/navigation_menu';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { IUiSettingsClient } from 'src/core/public';
|
||||
import { IUiSettingsClient } from 'kibana/public';
|
||||
import { esQuery, Query, esKuery } from '../../../../../../../../../src/plugins/data/public';
|
||||
import { IIndexPattern } from '../../../../../../../../../src/plugins/data/common/index_patterns';
|
||||
import { SEARCH_QUERY_LANGUAGE } from '../../../../../common/constants/search';
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ChromeBreadcrumb } from '../../../../../../../src/core/public';
|
||||
import { ChromeBreadcrumb } from 'kibana/public';
|
||||
|
||||
export const ML_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
||||
text: i18n.translate('xpack.ml.machineLearningBreadcrumbLabel', {
|
||||
|
|
|
@ -8,7 +8,7 @@ import React, { FC } from 'react';
|
|||
import { HashRouter, Route, RouteProps } from 'react-router-dom';
|
||||
import { Location } from 'history';
|
||||
|
||||
import { IUiSettingsClient, ChromeStart } from 'src/core/public';
|
||||
import { IUiSettingsClient, ChromeStart } from 'kibana/public';
|
||||
import { ChromeBreadcrumb } from 'kibana/public';
|
||||
import { IndexPatternsContract } from 'src/plugins/data/public';
|
||||
import { MlContext, MlContextValue } from '../contexts/ml';
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { IUiSettingsClient } from 'src/core/public';
|
||||
import { IUiSettingsClient } from 'kibana/public';
|
||||
import {
|
||||
getIndexPatternById,
|
||||
getIndexPatternsContract,
|
||||
|
|
|
@ -11,7 +11,11 @@ import { AggFieldNamePair } from '../../../../common/types/fields';
|
|||
import { Category } from '../../../../common/types/categories';
|
||||
import { ExistingJobsAndGroups } from '../job_service';
|
||||
import { PrivilegesResponse } from '../../../../common/types/privileges';
|
||||
import { MlServerDefaults, MlServerLimits } from '../ml_server_info';
|
||||
import {
|
||||
MlInfoResponse,
|
||||
MlServerDefaults,
|
||||
MlServerLimits,
|
||||
} from '../../../../common/types/ml_server_info';
|
||||
import { ES_AGGREGATION } from '../../../../common/constants/aggregation_types';
|
||||
import { DataFrameAnalyticsStats } from '../../data_frame_analytics/pages/analytics_management/components/analytics_list/common';
|
||||
import { JobMessage } from '../../../../common/types/audit_message';
|
||||
|
@ -69,17 +73,6 @@ export interface BucketSpanEstimatorResponse {
|
|||
message?: { msg: string } | string;
|
||||
}
|
||||
|
||||
export interface MlInfoResponse {
|
||||
defaults: MlServerDefaults;
|
||||
limits: MlServerLimits;
|
||||
native_code: {
|
||||
build_hash: string;
|
||||
version: string;
|
||||
};
|
||||
upgrade_mode: boolean;
|
||||
cloudId?: string;
|
||||
}
|
||||
|
||||
export interface SuccessCardinality {
|
||||
id: 'success_cardinality';
|
||||
}
|
||||
|
|
|
@ -5,21 +5,7 @@
|
|||
*/
|
||||
|
||||
import { ml } from './ml_api_service';
|
||||
import { CategorizationAnalyzer } from '../../../common/types/categories';
|
||||
|
||||
export interface MlServerDefaults {
|
||||
anomaly_detectors: {
|
||||
categorization_examples_limit?: number;
|
||||
model_memory_limit?: string;
|
||||
model_snapshot_retention_days?: number;
|
||||
categorization_analyzer?: CategorizationAnalyzer;
|
||||
};
|
||||
datafeeds: { scroll_size?: number };
|
||||
}
|
||||
|
||||
export interface MlServerLimits {
|
||||
max_model_memory_limit?: string;
|
||||
}
|
||||
import { MlServerDefaults, MlServerLimits } from '../../../common/types/ml_server_info';
|
||||
|
||||
export interface CloudInfo {
|
||||
cloudId: string | null;
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
SavedObjectsClientContract,
|
||||
ApplicationStart,
|
||||
HttpStart,
|
||||
} from 'src/core/public';
|
||||
} from 'kibana/public';
|
||||
import { IndexPatternsContract, DataPublicPluginStart } from 'src/plugins/data/public';
|
||||
import {
|
||||
DocLinksStart,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { PluginInitializer } from '../../../../../src/core/public';
|
||||
import { PluginInitializer } from 'kibana/public';
|
||||
import { MlPlugin, Setup, Start } from './plugin';
|
||||
|
||||
export const plugin: PluginInitializer<Setup, Start> = () => new MlPlugin();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { npSetup, npStart } from 'ui/new_platform';
|
||||
import { PluginInitializerContext } from 'src/core/public';
|
||||
import { PluginInitializerContext } from 'kibana/public';
|
||||
import { SecurityPluginSetup } from '../../../../plugins/security/public';
|
||||
import { LicensingPluginSetup } from '../../../../plugins/licensing/public';
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreStart, CoreSetup } from 'src/core/public';
|
||||
import { Plugin, CoreStart, CoreSetup } from 'kibana/public';
|
||||
import { MlDependencies } from './application/app';
|
||||
|
||||
export class MlPlugin implements Plugin<Setup, Start> {
|
||||
|
|
|
@ -4,14 +4,22 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { elasticsearchJsPlugin } from '../elasticsearch_ml';
|
||||
import { elasticsearchJsPlugin } from './elasticsearch_ml';
|
||||
|
||||
interface Endpoint {
|
||||
fmt: string;
|
||||
}
|
||||
|
||||
interface ClientAction {
|
||||
urls?: Endpoint[];
|
||||
url: Endpoint;
|
||||
}
|
||||
|
||||
describe('ML - Endpoints', () => {
|
||||
// Check all paths in the ML elasticsearchJsPlugin start with a leading forward slash
|
||||
// so they work if Kibana is run behind a reverse proxy
|
||||
const PATH_START = '/';
|
||||
const urls = [];
|
||||
const PATH_START: string = '/';
|
||||
const urls: string[] = [];
|
||||
|
||||
// Stub objects
|
||||
const Client = {
|
||||
|
@ -20,7 +28,7 @@ describe('ML - Endpoints', () => {
|
|||
|
||||
const components = {
|
||||
clientAction: {
|
||||
factory: function(obj) {
|
||||
factory(obj: ClientAction) {
|
||||
// add each endpoint URL to a list
|
||||
if (obj.urls) {
|
||||
obj.urls.forEach(url => {
|
||||
|
@ -45,7 +53,7 @@ describe('ML - Endpoints', () => {
|
|||
describe('paths', () => {
|
||||
it(`should start with ${PATH_START}`, () => {
|
||||
urls.forEach(url => {
|
||||
expect(url[0]).to.eql(PATH_START);
|
||||
expect(url[0]).toEqual(PATH_START);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export const elasticsearchJsPlugin = (Client, config, components) => {
|
||||
export const elasticsearchJsPlugin = (Client: any, config: any, components: any) => {
|
||||
const ca = components.clientAction.factory;
|
||||
|
||||
Client.prototype.ml = components.clientAction.namespaceFactory();
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { boomify, isBoom } from 'boom';
|
||||
import { ResponseError, CustomHttpResponseOptions } from 'src/core/server';
|
||||
import { ResponseError, CustomHttpResponseOptions } from 'kibana/server';
|
||||
|
||||
export function wrapError(error: any): CustomHttpResponseOptions<ResponseError> {
|
||||
const boom = isBoom(error) ? error : boomify(error, { statusCode: error.status });
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Logger } from '../../../../../src/core/server';
|
||||
import { Logger } from 'kibana/server';
|
||||
|
||||
export interface LogInitialization {
|
||||
log: Logger;
|
||||
|
|
|
@ -6,5 +6,6 @@
|
|||
|
||||
import { PluginInitializerContext } from 'kibana/server';
|
||||
import { MlServerPlugin } from './plugin';
|
||||
export { MlStartContract, MlSetupContract } from './plugin';
|
||||
|
||||
export const plugin = (ctx: PluginInitializerContext) => new MlServerPlugin(ctx);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { mlLog } from '../../client/log';
|
||||
|
||||
import {
|
||||
|
|
|
@ -16,7 +16,7 @@ import { mlPrivileges } from './privileges';
|
|||
|
||||
type ClusterPrivilege = Record<string, boolean>;
|
||||
|
||||
interface Response {
|
||||
export interface MlCapabilities {
|
||||
capabilities: Privileges;
|
||||
upgradeInProgress: boolean;
|
||||
isPlatinumOrTrialLicense: boolean;
|
||||
|
@ -30,7 +30,7 @@ export function privilegesProvider(
|
|||
ignoreSpaces: boolean = false
|
||||
) {
|
||||
const { isUpgradeInProgress } = upgradeCheckProvider(callAsCurrentUser);
|
||||
async function getPrivileges(): Promise<Response> {
|
||||
async function getPrivileges(): Promise<MlCapabilities> {
|
||||
// get the default privileges, forced to be false.
|
||||
const privileges = getDefaultPrivileges();
|
||||
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { privilegesProvider } from './check_privileges';
|
||||
export { privilegesProvider, MlCapabilities } from './check_privileges';
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
KibanaResponseFactory,
|
||||
RequestHandler,
|
||||
RequestHandlerContext,
|
||||
} from 'src/core/server';
|
||||
} from 'kibana/server';
|
||||
|
||||
import { MlLicense } from '../../../../../legacy/plugins/ml/common/license';
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
|
||||
import { SavedObjectsServiceStart } from 'src/core/server';
|
||||
import { SavedObjectsServiceStart } from 'kibana/server';
|
||||
import {
|
||||
createMlTelemetry,
|
||||
ML_TELEMETRY_DOC_ID,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { SavedObjectAttributes, SavedObjectsClientContract } from 'src/core/server';
|
||||
import { SavedObjectAttributes, SavedObjectsClientContract } from 'kibana/server';
|
||||
|
||||
export interface MlTelemetry extends SavedObjectAttributes {
|
||||
file_data_visualizer: {
|
||||
|
@ -40,7 +40,10 @@ export async function incrementFileDataVisualizerIndexCreationCount(
|
|||
savedObjectsClient: SavedObjectsClientContract
|
||||
): Promise<void> {
|
||||
try {
|
||||
const { attributes } = await savedObjectsClient.get('telemetry', 'telemetry');
|
||||
const { attributes } = await savedObjectsClient.get<{ enabled: boolean }>(
|
||||
'telemetry',
|
||||
'telemetry'
|
||||
);
|
||||
|
||||
if (attributes.enabled === false) {
|
||||
return;
|
||||
|
|
|
@ -4,15 +4,18 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Request } from 'hapi';
|
||||
import { Legacy } from 'kibana';
|
||||
import { KibanaRequest } from 'kibana/server';
|
||||
import { Space, SpacesPluginSetup } from '../../../spaces/server';
|
||||
|
||||
export type RequestFacade = KibanaRequest | Legacy.Request;
|
||||
|
||||
interface GetActiveSpaceResponse {
|
||||
valid: boolean;
|
||||
space?: Space;
|
||||
}
|
||||
|
||||
export function spacesUtilsProvider(spacesPlugin: SpacesPluginSetup, request: Request) {
|
||||
export function spacesUtilsProvider(spacesPlugin: SpacesPluginSetup, request: RequestFacade) {
|
||||
async function activeSpace(): Promise<GetActiveSpaceResponse> {
|
||||
try {
|
||||
return {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import getAnnotationsRequestMock from './__mocks__/get_annotations_request.json';
|
||||
import getAnnotationsResponseMock from './__mocks__/get_annotations_response.json';
|
||||
import { RequestHandlerContext } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { ANNOTATION_TYPE } from '../../../../../legacy/plugins/ml/common/constants/annotations';
|
||||
import { ML_ANNOTATIONS_INDEX_ALIAS_WRITE } from '../../../../../legacy/plugins/ml/common/constants/index_patterns';
|
||||
|
@ -26,27 +26,21 @@ describe('annotation_service', () => {
|
|||
let callWithRequestSpy: any;
|
||||
|
||||
beforeEach(() => {
|
||||
callWithRequestSpy = ({
|
||||
ml: {
|
||||
mlClient: {
|
||||
callAsCurrentUser: jest.fn((action: string) => {
|
||||
switch (action) {
|
||||
case 'delete':
|
||||
case 'index':
|
||||
return Promise.resolve(acknowledgedResponseMock);
|
||||
case 'search':
|
||||
return Promise.resolve(getAnnotationsResponseMock);
|
||||
}
|
||||
}),
|
||||
},
|
||||
},
|
||||
} as unknown) as RequestHandlerContext;
|
||||
callWithRequestSpy = (jest.fn((action: string) => {
|
||||
switch (action) {
|
||||
case 'delete':
|
||||
case 'index':
|
||||
return Promise.resolve(acknowledgedResponseMock);
|
||||
case 'search':
|
||||
return Promise.resolve(getAnnotationsResponseMock);
|
||||
}
|
||||
}) as unknown) as APICaller;
|
||||
});
|
||||
|
||||
describe('deleteAnnotation()', () => {
|
||||
it('should delete annotation', async done => {
|
||||
const { deleteAnnotation } = annotationServiceProvider(callWithRequestSpy);
|
||||
const mockFunct = callWithRequestSpy.ml.mlClient.callAsCurrentUser;
|
||||
const mockFunct = callWithRequestSpy;
|
||||
|
||||
const annotationMockId = 'mockId';
|
||||
const deleteParamsMock: DeleteParams = {
|
||||
|
@ -67,7 +61,7 @@ describe('annotation_service', () => {
|
|||
describe('getAnnotation()', () => {
|
||||
it('should get annotations for specific job', async done => {
|
||||
const { getAnnotations } = annotationServiceProvider(callWithRequestSpy);
|
||||
const mockFunct = callWithRequestSpy.ml.mlClient.callAsCurrentUser;
|
||||
const mockFunct = callWithRequestSpy;
|
||||
|
||||
const indexAnnotationArgsMock: IndexAnnotationArgs = {
|
||||
jobIds: [jobIdMock],
|
||||
|
@ -93,15 +87,9 @@ describe('annotation_service', () => {
|
|||
message: 'mock error message',
|
||||
};
|
||||
|
||||
const callWithRequestSpyError = ({
|
||||
ml: {
|
||||
mlClient: {
|
||||
callAsCurrentUser: jest.fn(() => {
|
||||
return Promise.resolve(mockEsError);
|
||||
}),
|
||||
},
|
||||
},
|
||||
} as unknown) as RequestHandlerContext;
|
||||
const callWithRequestSpyError = (jest.fn(() => {
|
||||
return Promise.resolve(mockEsError);
|
||||
}) as unknown) as APICaller;
|
||||
|
||||
const { getAnnotations } = annotationServiceProvider(callWithRequestSpyError);
|
||||
|
||||
|
@ -121,7 +109,7 @@ describe('annotation_service', () => {
|
|||
describe('indexAnnotation()', () => {
|
||||
it('should index annotation', async done => {
|
||||
const { indexAnnotation } = annotationServiceProvider(callWithRequestSpy);
|
||||
const mockFunct = callWithRequestSpy.ml.mlClient.callAsCurrentUser;
|
||||
const mockFunct = callWithRequestSpy;
|
||||
|
||||
const annotationMock: Annotation = {
|
||||
annotation: 'Annotation text',
|
||||
|
@ -149,7 +137,7 @@ describe('annotation_service', () => {
|
|||
|
||||
it('should remove ._id and .key before updating annotation', async done => {
|
||||
const { indexAnnotation } = annotationServiceProvider(callWithRequestSpy);
|
||||
const mockFunct = callWithRequestSpy.ml.mlClient.callAsCurrentUser;
|
||||
const mockFunct = callWithRequestSpy;
|
||||
|
||||
const annotationMock: Annotation = {
|
||||
_id: 'mockId',
|
||||
|
@ -181,7 +169,7 @@ describe('annotation_service', () => {
|
|||
|
||||
it('should update annotation text and the username for modified_username', async done => {
|
||||
const { getAnnotations, indexAnnotation } = annotationServiceProvider(callWithRequestSpy);
|
||||
const mockFunct = callWithRequestSpy.ml.mlClient.callAsCurrentUser;
|
||||
const mockFunct = callWithRequestSpy;
|
||||
|
||||
const indexAnnotationArgsMock: IndexAnnotationArgs = {
|
||||
jobIds: [jobIdMock],
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import Boom from 'boom';
|
||||
import _ from 'lodash';
|
||||
import { RequestHandlerContext } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
import { ANNOTATION_TYPE } from '../../../../../legacy/plugins/ml/common/constants/annotations';
|
||||
import {
|
||||
|
@ -68,8 +68,7 @@ export type callWithRequestType = (
|
|||
params: annotationProviderParams
|
||||
) => Promise<any>;
|
||||
|
||||
export function annotationProvider(context: RequestHandlerContext) {
|
||||
const callAsCurrentUser = context.ml!.mlClient.callAsCurrentUser;
|
||||
export function annotationProvider(callAsCurrentUser: APICaller) {
|
||||
async function indexAnnotation(annotation: Annotation, username: string) {
|
||||
if (isAnnotation(annotation) === false) {
|
||||
// No need to translate, this will not be exposed in the UI.
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { RequestHandlerContext } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { annotationProvider } from './annotation';
|
||||
|
||||
export function annotationServiceProvider(context: RequestHandlerContext) {
|
||||
export function annotationServiceProvider(callAsCurrentUser: APICaller) {
|
||||
return {
|
||||
...annotationProvider(context),
|
||||
...annotationProvider(callAsCurrentUser),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { BucketSpanEstimatorData } from '../../../../../legacy/plugins/ml/public/application/services/ml_api_service';
|
||||
|
||||
export function estimateBucketSpanFactory(
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
export function calculateModelMemoryLimitProvider(
|
||||
callAsCurrentUser: APICaller
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { difference } from 'lodash';
|
||||
import Boom from 'boom';
|
||||
import { IScopedClusterClient } from 'src/core/server';
|
||||
import { IScopedClusterClient } from 'kibana/server';
|
||||
import { EventManager, CalendarEvent } from './event_manager';
|
||||
|
||||
interface BasicCalendar {
|
||||
|
|
|
@ -4,26 +4,18 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { RequestHandlerContext } from 'kibana/server';
|
||||
import { APICaller, SavedObjectsClientContract } from 'kibana/server';
|
||||
import { Module } from '../../../../../legacy/plugins/ml/common/types/modules';
|
||||
import { DataRecognizer } from '../data_recognizer';
|
||||
|
||||
describe('ML - data recognizer', () => {
|
||||
const dr = new DataRecognizer(({
|
||||
ml: {
|
||||
mlClient: {
|
||||
callAsCurrentUser: jest.fn(),
|
||||
},
|
||||
},
|
||||
core: {
|
||||
savedObjects: {
|
||||
client: {
|
||||
find: jest.fn(),
|
||||
bulkCreate: jest.fn(),
|
||||
},
|
||||
},
|
||||
},
|
||||
} as unknown) as RequestHandlerContext);
|
||||
const dr = new DataRecognizer(
|
||||
jest.fn() as APICaller,
|
||||
({
|
||||
find: jest.fn(),
|
||||
bulkCreate: jest.fn(),
|
||||
} as never) as SavedObjectsClientContract
|
||||
);
|
||||
|
||||
const moduleIds = [
|
||||
'apache_ecs',
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import fs from 'fs';
|
||||
import Boom from 'boom';
|
||||
import numeral from '@elastic/numeral';
|
||||
import { CallAPIOptions, RequestHandlerContext, SavedObjectsClientContract } from 'kibana/server';
|
||||
import { CallAPIOptions, APICaller, SavedObjectsClientContract } from 'kibana/server';
|
||||
import { IndexPatternAttributes } from 'src/plugins/data/server';
|
||||
import { merge } from 'lodash';
|
||||
import { CombinedJobWithStats } from '../../../../../legacy/plugins/ml/common/types/anomaly_detection_jobs';
|
||||
|
@ -68,7 +68,7 @@ interface Config {
|
|||
json: RawModuleConfig;
|
||||
}
|
||||
|
||||
interface Result {
|
||||
export interface RecognizeResult {
|
||||
id: string;
|
||||
title: string;
|
||||
query: any;
|
||||
|
@ -118,9 +118,9 @@ export class DataRecognizer {
|
|||
options?: CallAPIOptions
|
||||
) => Promise<any>;
|
||||
|
||||
constructor(context: RequestHandlerContext) {
|
||||
this.callAsCurrentUser = context.ml!.mlClient.callAsCurrentUser;
|
||||
this.savedObjectsClient = context.core.savedObjects.client;
|
||||
constructor(callAsCurrentUser: APICaller, savedObjectsClient: SavedObjectsClientContract) {
|
||||
this.callAsCurrentUser = callAsCurrentUser;
|
||||
this.savedObjectsClient = savedObjectsClient;
|
||||
}
|
||||
|
||||
// list all directories under the given directory
|
||||
|
@ -189,9 +189,9 @@ export class DataRecognizer {
|
|||
}
|
||||
|
||||
// called externally by an endpoint
|
||||
async findMatches(indexPattern: string): Promise<Result[]> {
|
||||
async findMatches(indexPattern: string): Promise<RecognizeResult[]> {
|
||||
const manifestFiles = await this.loadManifestFiles();
|
||||
const results: Result[] = [];
|
||||
const results: RecognizeResult[] = [];
|
||||
|
||||
await Promise.all(
|
||||
manifestFiles.map(async i => {
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { DataRecognizer } from './data_recognizer';
|
||||
export { DataRecognizer, RecognizeResult } from './data_recognizer';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { CallAPIOptions, IScopedClusterClient } from 'src/core/server';
|
||||
import { CallAPIOptions, IScopedClusterClient } from 'kibana/server';
|
||||
import _ from 'lodash';
|
||||
import { ML_JOB_FIELD_TYPES } from '../../../../../legacy/plugins/ml/common/constants/field_types';
|
||||
import { getSafeAggregationName } from '../../../../../legacy/plugins/ml/common/util/job_utils';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
export function fieldsServiceProvider(
|
||||
callAsCurrentUser: APICaller
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import Boom from 'boom';
|
||||
import { RequestHandlerContext } from 'kibana/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { FindFileStructureResponse } from '../../../../../legacy/plugins/ml/common/types/file_datavisualizer';
|
||||
|
||||
export type InputData = any[];
|
||||
|
@ -25,12 +25,12 @@ export interface AnalysisResult {
|
|||
overrides?: FormattedOverrides;
|
||||
}
|
||||
|
||||
export function fileDataVisualizerProvider(context: RequestHandlerContext) {
|
||||
export function fileDataVisualizerProvider(callAsCurrentUser: APICaller) {
|
||||
async function analyzeFile(data: any, overrides: any): Promise<AnalysisResult> {
|
||||
let results = [];
|
||||
|
||||
try {
|
||||
results = await context.ml!.mlClient.callAsCurrentUser('ml.fileStructure', {
|
||||
results = await callAsCurrentUser('ml.fileStructure', {
|
||||
body: data,
|
||||
...overrides,
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { RequestHandlerContext } from 'kibana/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { INDEX_META_DATA_CREATED_BY } from '../../../../../legacy/plugins/ml/common/constants/file_datavisualizer';
|
||||
import { InputData } from './file_data_visualizer';
|
||||
|
||||
|
@ -30,9 +30,7 @@ interface Failure {
|
|||
doc: any;
|
||||
}
|
||||
|
||||
export function importDataProvider(context: RequestHandlerContext) {
|
||||
const callAsCurrentUser = context.ml!.mlClient.callAsCurrentUser;
|
||||
|
||||
export function importDataProvider(callAsCurrentUser: APICaller) {
|
||||
async function importData(
|
||||
id: string,
|
||||
index: string,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import Boom from 'boom';
|
||||
import { IScopedClusterClient } from 'src/core/server';
|
||||
import { IScopedClusterClient } from 'kibana/server';
|
||||
|
||||
import {
|
||||
DetectorRule,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
|
||||
export function jobAuditMessagesProvider(
|
||||
callAsCurrentUser: APICaller
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
JOB_STATE,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { CalendarManager } from '../calendar';
|
||||
import { GLOBAL_CALENDAR } from '../../../../../legacy/plugins/ml/common/constants/calendars';
|
||||
import { Job } from '../../../../../legacy/plugins/ml/common/types/anomaly_detection_jobs';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { datafeedsProvider } from './datafeeds';
|
||||
import { jobsProvider } from './jobs';
|
||||
import { groupsProvider } from './groups';
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { uniq } from 'lodash';
|
||||
import { APICaller } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import {
|
||||
JOB_STATE,
|
||||
DATAFEED_STATE,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { SavedObject } from 'src/core/server';
|
||||
import { SavedObject } from 'kibana/server';
|
||||
import { IndexPatternAttributes } from 'src/plugins/data/server';
|
||||
import { SavedObjectsClientContract } from 'kibana/server';
|
||||
import { FieldId } from '../../../../../../legacy/plugins/ml/common/types/fields';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { TypeOf } from '@kbn/config-schema';
|
||||
import { validateJobSchema } from '../../routes/schemas/job_validation_schema';
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { CombinedJob } from '../../../../../legacy/plugins/ml/common/types/anomaly_detection_jobs';
|
||||
|
||||
export function validateCardinality(callAsCurrentUser: APICaller, job: CombinedJob): any[];
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'src/core/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { ES_FIELD_TYPES } from '../../../../../../src/plugins/data/server';
|
||||
import { parseInterval } from '../../../../../legacy/plugins/ml/common/util/parse_interval';
|
||||
import { CombinedJob } from '../../../../../legacy/plugins/ml/common/types/anomaly_detection_jobs';
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
import { SearchResponse } from 'elasticsearch';
|
||||
import { RequestHandlerContext } from 'kibana/server';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { buildAnomalyTableItems, AnomaliesTableRecord } from './build_anomaly_table_items';
|
||||
import { ML_RESULTS_INDEX_PATTERN } from '../../../../../legacy/plugins/ml/common/constants/index_patterns';
|
||||
import { ANOMALIES_TABLE_DEFAULT_QUERY_SIZE } from '../../../../../legacy/plugins/ml/common/constants/search';
|
||||
|
@ -30,9 +30,7 @@ interface Influencer {
|
|||
fieldValue: any;
|
||||
}
|
||||
|
||||
export function resultsServiceProvider(client: RequestHandlerContext | ((...args: any[]) => any)) {
|
||||
const callAsCurrentUser =
|
||||
typeof client === 'object' ? client.ml!.mlClient.callAsCurrentUser : client;
|
||||
export function resultsServiceProvider(callAsCurrentUser: APICaller) {
|
||||
// Obtains data for the anomalies table, aggregating anomalies by day or hour as requested.
|
||||
// Return an Object with properties 'anomalies' and 'interval' (interval used to aggregate anomalies,
|
||||
// one of day, hour or second. Note 'auto' can be provided as the aggregationInterval in the request,
|
||||
|
|
|
@ -5,11 +5,16 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { CoreSetup, IScopedClusterClient, Logger, PluginInitializerContext } from 'src/core/server';
|
||||
import {
|
||||
CoreSetup,
|
||||
Plugin,
|
||||
IScopedClusterClient,
|
||||
Logger,
|
||||
PluginInitializerContext,
|
||||
} from 'kibana/server';
|
||||
import { PluginsSetup, RouteInitialization } from './types';
|
||||
import { PLUGIN_ID } from '../../../legacy/plugins/ml/common/constants/app';
|
||||
|
||||
// @ts-ignore: could not find declaration file for module
|
||||
import { elasticsearchJsPlugin } from './client/elasticsearch_ml';
|
||||
import { makeMlUsageCollector } from './lib/ml_telemetry';
|
||||
import { initMlServerLog } from './client/log';
|
||||
|
@ -34,6 +39,7 @@ import { resultsServiceRoutes } from './routes/results_service';
|
|||
import { systemRoutes } from './routes/system';
|
||||
import { MlLicense } from '../../../legacy/plugins/ml/common/license';
|
||||
import { MlServerLicense } from './lib/license';
|
||||
import { createSharedServices, SharedServices } from './shared_services';
|
||||
|
||||
declare module 'kibana/server' {
|
||||
interface RequestHandlerContext {
|
||||
|
@ -43,7 +49,10 @@ declare module 'kibana/server' {
|
|||
}
|
||||
}
|
||||
|
||||
export class MlServerPlugin {
|
||||
export type MlSetupContract = SharedServices;
|
||||
export type MlStartContract = void;
|
||||
|
||||
export class MlServerPlugin implements Plugin<MlSetupContract, MlStartContract, PluginsSetup> {
|
||||
private log: Logger;
|
||||
private version: string;
|
||||
private mlLicense: MlServerLicense;
|
||||
|
@ -54,7 +63,7 @@ export class MlServerPlugin {
|
|||
this.mlLicense = new MlServerLicense();
|
||||
}
|
||||
|
||||
public setup(coreSetup: CoreSetup, plugins: PluginsSetup) {
|
||||
public setup(coreSetup: CoreSetup, plugins: PluginsSetup): MlSetupContract {
|
||||
plugins.features.registerFeature({
|
||||
id: PLUGIN_ID,
|
||||
name: i18n.translate('xpack.ml.featureRegistry.mlFeatureName', {
|
||||
|
@ -124,9 +133,11 @@ export class MlServerPlugin {
|
|||
coreSetup.getStartServices().then(([core]) => {
|
||||
makeMlUsageCollector(plugins.usageCollection, core.savedObjects);
|
||||
});
|
||||
|
||||
return createSharedServices(this.mlLicense, plugins.spaces, plugins.cloud);
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public start(): MlStartContract {}
|
||||
|
||||
public stop() {
|
||||
this.mlLicense.unsubscribe();
|
||||
|
|
|
@ -62,7 +62,9 @@ export function annotationRoutes(
|
|||
},
|
||||
mlLicense.fullLicenseAPIGuard(async (context, request, response) => {
|
||||
try {
|
||||
const { getAnnotations } = annotationServiceProvider(context);
|
||||
const { getAnnotations } = annotationServiceProvider(
|
||||
context.ml!.mlClient.callAsCurrentUser
|
||||
);
|
||||
const resp = await getAnnotations(request.body);
|
||||
|
||||
return response.ok({
|
||||
|
@ -100,7 +102,9 @@ export function annotationRoutes(
|
|||
throw getAnnotationsFeatureUnavailableErrorMessage();
|
||||
}
|
||||
|
||||
const { indexAnnotation } = annotationServiceProvider(context);
|
||||
const { indexAnnotation } = annotationServiceProvider(
|
||||
context.ml!.mlClient.callAsCurrentUser
|
||||
);
|
||||
|
||||
const currentUser =
|
||||
securityPlugin !== undefined ? securityPlugin.authc.getCurrentUser(request) : {};
|
||||
|
@ -143,7 +147,9 @@ export function annotationRoutes(
|
|||
}
|
||||
|
||||
const annotationId = request.params.annotationId;
|
||||
const { deleteAnnotation } = annotationServiceProvider(context);
|
||||
const { deleteAnnotation } = annotationServiceProvider(
|
||||
context.ml!.mlClient.callAsCurrentUser
|
||||
);
|
||||
const resp = await deleteAnnotation(annotationId);
|
||||
|
||||
return response.ok({
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { RequestHandlerContext } from 'src/core/server';
|
||||
import { RequestHandlerContext } from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { wrapError } from '../client/error_wrapper';
|
||||
import { RouteInitialization } from '../types';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { RequestHandlerContext } from 'src/core/server';
|
||||
import { RequestHandlerContext } from 'kibana/server';
|
||||
import { wrapError } from '../client/error_wrapper';
|
||||
import { RouteInitialization } from '../types';
|
||||
import {
|
||||
|
|
|
@ -22,7 +22,7 @@ import { RouteInitialization } from '../types';
|
|||
import { incrementFileDataVisualizerIndexCreationCount } from '../lib/ml_telemetry';
|
||||
|
||||
function analyzeFiles(context: RequestHandlerContext, data: InputData, overrides: InputOverrides) {
|
||||
const { analyzeFile } = fileDataVisualizerProvider(context);
|
||||
const { analyzeFile } = fileDataVisualizerProvider(context.ml!.mlClient.callAsCurrentUser);
|
||||
return analyzeFile(data, overrides);
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ function importData(
|
|||
ingestPipeline: InjectPipeline,
|
||||
data: InputData
|
||||
) {
|
||||
const { importData: importDataFunc } = importDataProvider(context);
|
||||
const { importData: importDataFunc } = importDataProvider(context.ml!.mlClient.callAsCurrentUser);
|
||||
return importDataFunc(id, index, settings, mappings, ingestPipeline, data);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { RequestHandlerContext } from 'src/core/server';
|
||||
import { RequestHandlerContext } from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { wrapError } from '../client/error_wrapper';
|
||||
import { RouteInitialization } from '../types';
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import Boom from 'boom';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { IScopedClusterClient } from 'src/core/server';
|
||||
import { IScopedClusterClient } from 'kibana/server';
|
||||
import { wrapError } from '../client/error_wrapper';
|
||||
import { RouteInitialization } from '../types';
|
||||
import {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import Boom from 'boom';
|
||||
import { RequestHandlerContext } from 'src/core/server';
|
||||
import { RequestHandlerContext } from 'kibana/server';
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import { wrapError } from '../client/error_wrapper';
|
||||
import { RouteInitialization } from '../types';
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
import { RequestHandlerContext } from 'kibana/server';
|
||||
import { DatafeedOverride, JobOverride } from '../../../../legacy/plugins/ml/common/types/modules';
|
||||
import { wrapError } from '../client/error_wrapper';
|
||||
|
@ -13,12 +14,18 @@ import { getModuleIdParamSchema, setupModuleBodySchema } from './schemas/modules
|
|||
import { RouteInitialization } from '../types';
|
||||
|
||||
function recognize(context: RequestHandlerContext, indexPatternTitle: string) {
|
||||
const dr = new DataRecognizer(context);
|
||||
const dr = new DataRecognizer(
|
||||
context.ml!.mlClient.callAsCurrentUser,
|
||||
context.core.savedObjects.client
|
||||
);
|
||||
return dr.findMatches(indexPatternTitle);
|
||||
}
|
||||
|
||||
function getModule(context: RequestHandlerContext, moduleId: string) {
|
||||
const dr = new DataRecognizer(context);
|
||||
const dr = new DataRecognizer(
|
||||
context.ml!.mlClient.callAsCurrentUser,
|
||||
context.core.savedObjects.client
|
||||
);
|
||||
if (moduleId === undefined) {
|
||||
return dr.listModules();
|
||||
} else {
|
||||
|
@ -40,7 +47,10 @@ function saveModuleItems(
|
|||
jobOverrides: JobOverride[],
|
||||
datafeedOverrides: DatafeedOverride[]
|
||||
) {
|
||||
const dr = new DataRecognizer(context);
|
||||
const dr = new DataRecognizer(
|
||||
context.ml!.mlClient.callAsCurrentUser,
|
||||
context.core.savedObjects.client
|
||||
);
|
||||
return dr.setupModuleItems(
|
||||
moduleId,
|
||||
prefix,
|
||||
|
@ -57,7 +67,10 @@ function saveModuleItems(
|
|||
}
|
||||
|
||||
function dataRecognizerJobsExist(context: RequestHandlerContext, moduleId: string) {
|
||||
const dr = new DataRecognizer(context);
|
||||
const dr = new DataRecognizer(
|
||||
context.ml!.mlClient.callAsCurrentUser,
|
||||
context.core.savedObjects.client
|
||||
);
|
||||
return dr.dataRecognizerJobsExist(moduleId);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { RequestHandlerContext } from 'src/core/server';
|
||||
import { RequestHandlerContext } from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { wrapError } from '../client/error_wrapper';
|
||||
import { RouteInitialization } from '../types';
|
||||
|
@ -18,7 +18,7 @@ import {
|
|||
import { resultsServiceProvider } from '../models/results_service';
|
||||
|
||||
function getAnomaliesTableData(context: RequestHandlerContext, payload: any) {
|
||||
const rs = resultsServiceProvider(context);
|
||||
const rs = resultsServiceProvider(context.ml!.mlClient.callAsCurrentUser);
|
||||
const {
|
||||
jobIds,
|
||||
criteriaFields,
|
||||
|
@ -48,24 +48,24 @@ function getAnomaliesTableData(context: RequestHandlerContext, payload: any) {
|
|||
}
|
||||
|
||||
function getCategoryDefinition(context: RequestHandlerContext, payload: any) {
|
||||
const rs = resultsServiceProvider(context);
|
||||
const rs = resultsServiceProvider(context.ml!.mlClient.callAsCurrentUser);
|
||||
return rs.getCategoryDefinition(payload.jobId, payload.categoryId);
|
||||
}
|
||||
|
||||
function getCategoryExamples(context: RequestHandlerContext, payload: any) {
|
||||
const rs = resultsServiceProvider(context);
|
||||
const rs = resultsServiceProvider(context.ml!.mlClient.callAsCurrentUser);
|
||||
const { jobId, categoryIds, maxExamples } = payload;
|
||||
return rs.getCategoryExamples(jobId, categoryIds, maxExamples);
|
||||
}
|
||||
|
||||
function getMaxAnomalyScore(context: RequestHandlerContext, payload: any) {
|
||||
const rs = resultsServiceProvider(context);
|
||||
const rs = resultsServiceProvider(context.ml!.mlClient.callAsCurrentUser);
|
||||
const { jobIds, earliestMs, latestMs } = payload;
|
||||
return rs.getMaxAnomalyScore(jobIds, earliestMs, latestMs);
|
||||
}
|
||||
|
||||
function getPartitionFieldsValues(context: RequestHandlerContext, payload: any) {
|
||||
const rs = resultsServiceProvider(context);
|
||||
const rs = resultsServiceProvider(context.ml!.mlClient.callAsCurrentUser);
|
||||
const { jobId, searchTerm, criteriaFields, earliestMs, latestMs } = payload;
|
||||
return rs.getPartitionFieldsValues(jobId, searchTerm, criteriaFields, earliestMs, latestMs);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export interface InjectorService {
|
||||
get<T>(name: string, caller?: string): T;
|
||||
}
|
||||
export { SharedServices, createSharedServices } from './shared_services';
|
26
x-pack/plugins/ml/server/shared_services/license_checks.ts
Normal file
26
x-pack/plugins/ml/server/shared_services/license_checks.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { MlServerLicense } from '../lib/license';
|
||||
|
||||
export type LicenseCheck = () => void;
|
||||
|
||||
export function licenseChecks(
|
||||
mlLicense: MlServerLicense
|
||||
): { isFullLicense: LicenseCheck; isMinimumLicense: LicenseCheck } {
|
||||
return {
|
||||
isFullLicense() {
|
||||
if (mlLicense.isFullLicense() === false) {
|
||||
throw Error('Platinum, Enterprise or trial license needed');
|
||||
}
|
||||
},
|
||||
isMinimumLicense() {
|
||||
if (mlLicense.isMinimumLicense() === false) {
|
||||
throw Error('Basic license needed');
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { LicenseCheck } from '../license_checks';
|
||||
|
||||
export interface AnomalyDetectorsProvider {
|
||||
anomalyDetectorsProvider(
|
||||
callAsCurrentUser: APICaller
|
||||
): {
|
||||
jobs(jobId?: string): Promise<any>;
|
||||
};
|
||||
}
|
||||
|
||||
export function getAnomalyDetectorsProvider(isFullLicense: LicenseCheck): AnomalyDetectorsProvider {
|
||||
return {
|
||||
anomalyDetectorsProvider(callAsCurrentUser: APICaller) {
|
||||
return {
|
||||
jobs(jobId?: string) {
|
||||
isFullLicense();
|
||||
return callAsCurrentUser('ml.jobs', jobId !== undefined ? { jobId } : {});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
|
@ -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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { LicenseCheck } from '../license_checks';
|
||||
import { jobServiceProvider } from '../../models/job_service';
|
||||
|
||||
export interface JobServiceProvider {
|
||||
jobServiceProvider(callAsCurrentUser: APICaller): ReturnType<typeof jobServiceProvider>;
|
||||
}
|
||||
|
||||
export function getJobServiceProvider(isFullLicense: LicenseCheck): JobServiceProvider {
|
||||
return {
|
||||
jobServiceProvider(callAsCurrentUser: APICaller) {
|
||||
isFullLicense();
|
||||
return jobServiceProvider(callAsCurrentUser);
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller, SavedObjectsClientContract } from 'kibana/server';
|
||||
import { LicenseCheck } from '../license_checks';
|
||||
import { DataRecognizer, RecognizeResult } from '../../models/data_recognizer';
|
||||
import {
|
||||
Module,
|
||||
DatafeedOverride,
|
||||
JobOverride,
|
||||
DataRecognizerConfigResponse,
|
||||
} from '../../../../../legacy/plugins/ml/common/types/modules';
|
||||
|
||||
export interface ModulesProvider {
|
||||
modulesProvider(
|
||||
callAsCurrentUser: APICaller,
|
||||
savedObjectsClient: SavedObjectsClientContract
|
||||
): {
|
||||
recognize(indexPatternTitle: string): Promise<RecognizeResult[]>;
|
||||
getModule(moduleId?: string): Promise<Module | Module[]>;
|
||||
saveModuleItems(
|
||||
moduleId: string,
|
||||
prefix: string,
|
||||
groups: string[],
|
||||
indexPatternName: string,
|
||||
query: any,
|
||||
useDedicatedIndex: boolean,
|
||||
startDatafeed: boolean,
|
||||
start: number,
|
||||
end: number,
|
||||
jobOverrides: JobOverride[],
|
||||
datafeedOverrides: DatafeedOverride[]
|
||||
): Promise<DataRecognizerConfigResponse>;
|
||||
};
|
||||
}
|
||||
|
||||
export function getModulesProvider(isFullLicense: LicenseCheck): ModulesProvider {
|
||||
return {
|
||||
modulesProvider(callAsCurrentUser: APICaller, savedObjectsClient: SavedObjectsClientContract) {
|
||||
isFullLicense();
|
||||
return {
|
||||
recognize(indexPatternTitle: string) {
|
||||
const dr = dataRecognizerFactory(callAsCurrentUser, savedObjectsClient);
|
||||
return dr.findMatches(indexPatternTitle);
|
||||
},
|
||||
getModule(moduleId?: string) {
|
||||
const dr = dataRecognizerFactory(callAsCurrentUser, savedObjectsClient);
|
||||
if (moduleId === undefined) {
|
||||
return dr.listModules();
|
||||
} else {
|
||||
return dr.getModule(moduleId);
|
||||
}
|
||||
},
|
||||
saveModuleItems(
|
||||
moduleId: string,
|
||||
prefix: string,
|
||||
groups: string[],
|
||||
indexPatternName: string,
|
||||
query: any,
|
||||
useDedicatedIndex: boolean,
|
||||
startDatafeed: boolean,
|
||||
start: number,
|
||||
end: number,
|
||||
jobOverrides: JobOverride[],
|
||||
datafeedOverrides: DatafeedOverride[]
|
||||
) {
|
||||
const dr = dataRecognizerFactory(callAsCurrentUser, savedObjectsClient);
|
||||
return dr.setupModuleItems(
|
||||
moduleId,
|
||||
prefix,
|
||||
groups,
|
||||
indexPatternName,
|
||||
query,
|
||||
useDedicatedIndex,
|
||||
startDatafeed,
|
||||
start,
|
||||
end,
|
||||
jobOverrides,
|
||||
datafeedOverrides
|
||||
);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function dataRecognizerFactory(
|
||||
callAsCurrentUser: APICaller,
|
||||
savedObjectsClient: SavedObjectsClientContract
|
||||
) {
|
||||
return new DataRecognizer(callAsCurrentUser, savedObjectsClient);
|
||||
}
|
|
@ -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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { LicenseCheck } from '../license_checks';
|
||||
import { resultsServiceProvider } from '../../models/results_service';
|
||||
|
||||
export interface ResultsServiceProvider {
|
||||
resultsServiceProvider(callAsCurrentUser: APICaller): ReturnType<typeof resultsServiceProvider>;
|
||||
}
|
||||
|
||||
export function getResultsServiceProvider(isFullLicense: LicenseCheck): ResultsServiceProvider {
|
||||
return {
|
||||
resultsServiceProvider(callAsCurrentUser: APICaller) {
|
||||
isFullLicense();
|
||||
return resultsServiceProvider(callAsCurrentUser);
|
||||
},
|
||||
};
|
||||
}
|
74
x-pack/plugins/ml/server/shared_services/providers/system.ts
Normal file
74
x-pack/plugins/ml/server/shared_services/providers/system.ts
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { SearchResponse, SearchParams } from 'elasticsearch';
|
||||
import { MlServerLicense } from '../../lib/license';
|
||||
import { CloudSetup } from '../../../../cloud/server';
|
||||
import { LicenseCheck } from '../license_checks';
|
||||
import { spacesUtilsProvider, RequestFacade } from '../../lib/spaces_utils';
|
||||
import { SpacesPluginSetup } from '../../../../spaces/server';
|
||||
import { privilegesProvider, MlCapabilities } from '../../lib/check_privileges';
|
||||
import { MlInfoResponse } from '../../../../../legacy/plugins/ml/common/types/ml_server_info';
|
||||
import { ML_RESULTS_INDEX_PATTERN } from '../../../../../legacy/plugins/ml/common/constants/index_patterns';
|
||||
|
||||
export interface MlSystemProvider {
|
||||
mlSystemProvider(
|
||||
callAsCurrentUser: APICaller,
|
||||
request: RequestFacade
|
||||
): {
|
||||
mlCapabilities(ignoreSpaces?: boolean): Promise<MlCapabilities>;
|
||||
mlInfo(): Promise<MlInfoResponse>;
|
||||
mlSearch<T>(searchParams: SearchParams): Promise<SearchResponse<T>>;
|
||||
};
|
||||
}
|
||||
|
||||
export function getMlSystemProvider(
|
||||
isMinimumLicense: LicenseCheck,
|
||||
isFullLicense: LicenseCheck,
|
||||
mlLicense: MlServerLicense,
|
||||
spaces: SpacesPluginSetup | undefined,
|
||||
cloud: CloudSetup | undefined
|
||||
): MlSystemProvider {
|
||||
return {
|
||||
mlSystemProvider(callAsCurrentUser: APICaller, request: RequestFacade) {
|
||||
return {
|
||||
mlCapabilities(ignoreSpaces?: boolean) {
|
||||
isMinimumLicense();
|
||||
|
||||
const { isMlEnabledInSpace } =
|
||||
spaces !== undefined
|
||||
? spacesUtilsProvider(spaces, request)
|
||||
: { isMlEnabledInSpace: async () => true };
|
||||
|
||||
const { getPrivileges } = privilegesProvider(
|
||||
callAsCurrentUser,
|
||||
mlLicense,
|
||||
isMlEnabledInSpace,
|
||||
ignoreSpaces
|
||||
);
|
||||
return getPrivileges();
|
||||
},
|
||||
async mlInfo(): Promise<MlInfoResponse> {
|
||||
isMinimumLicense();
|
||||
const info = await callAsCurrentUser('ml.info');
|
||||
const cloudId = cloud && cloud.cloudId;
|
||||
return {
|
||||
...info,
|
||||
cloudId,
|
||||
};
|
||||
},
|
||||
async mlSearch<T>(searchParams: SearchParams): Promise<SearchResponse<T>> {
|
||||
isFullLicense();
|
||||
return callAsCurrentUser('search', {
|
||||
...searchParams,
|
||||
index: ML_RESULTS_INDEX_PATTERN,
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
41
x-pack/plugins/ml/server/shared_services/shared_services.ts
Normal file
41
x-pack/plugins/ml/server/shared_services/shared_services.ts
Normal file
|
@ -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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { MlServerLicense } from '../lib/license';
|
||||
|
||||
import { SpacesPluginSetup } from '../../../spaces/server';
|
||||
import { CloudSetup } from '../../../cloud/server';
|
||||
import { licenseChecks } from './license_checks';
|
||||
import { MlSystemProvider, getMlSystemProvider } from './providers/system';
|
||||
import { JobServiceProvider, getJobServiceProvider } from './providers/job_service';
|
||||
import { ModulesProvider, getModulesProvider } from './providers/modules';
|
||||
import { ResultsServiceProvider, getResultsServiceProvider } from './providers/results_service';
|
||||
import {
|
||||
AnomalyDetectorsProvider,
|
||||
getAnomalyDetectorsProvider,
|
||||
} from './providers/anomaly_detectors';
|
||||
|
||||
export type SharedServices = JobServiceProvider &
|
||||
AnomalyDetectorsProvider &
|
||||
MlSystemProvider &
|
||||
ModulesProvider &
|
||||
ResultsServiceProvider;
|
||||
|
||||
export function createSharedServices(
|
||||
mlLicense: MlServerLicense,
|
||||
spaces: SpacesPluginSetup | undefined,
|
||||
cloud: CloudSetup
|
||||
): SharedServices {
|
||||
const { isFullLicense, isMinimumLicense } = licenseChecks(mlLicense);
|
||||
|
||||
return {
|
||||
...getJobServiceProvider(isFullLicense),
|
||||
...getAnomalyDetectorsProvider(isFullLicense),
|
||||
...getMlSystemProvider(isMinimumLicense, isFullLicense, mlLicense, spaces, cloud),
|
||||
...getModulesProvider(isFullLicense),
|
||||
...getResultsServiceProvider(isFullLicense),
|
||||
};
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
|
||||
import { HomeServerPluginSetup } from 'src/plugins/home/server';
|
||||
import { IRouter } from 'src/core/server';
|
||||
import { IRouter } from 'kibana/server';
|
||||
import { CloudSetup } from '../../cloud/server';
|
||||
import { SecurityPluginSetup } from '../../security/server';
|
||||
import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue