[ML] NP: migrate server (#58680)

* remove obsolete legacy server deps

* licensePreRoutingFactory uses licensing plugin rather than legacy xpack

* move schemas to dir in routes

* use NP license check method for license check

* store license data in plugin for passing to check

* create server plugin files in NP plugin dir

* remove dependency on legacy xpack plugin

* add sample data links first step

* move all server dirs from legacy to np dir

* fix requiredPlugin spaces name and update import routes

* delete unnecessary files and add sample data links

* update license and privilege check tests

* add routeInit types
This commit is contained in:
Melissa Alvarez 2020-02-27 21:15:08 -05:00 committed by GitHub
parent facae44f5b
commit 8c3d71b370
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
339 changed files with 655 additions and 873 deletions

View file

@ -26,7 +26,7 @@
"xpack.logstash": "legacy/plugins/logstash",
"xpack.main": "legacy/plugins/xpack_main",
"xpack.maps": "legacy/plugins/maps",
"xpack.ml": "legacy/plugins/ml",
"xpack.ml": ["plugins/ml", "legacy/plugins/ml"],
"xpack.monitoring": "legacy/plugins/monitoring",
"xpack.remoteClusters": "plugins/remote_clusters",
"xpack.reporting": ["plugins/reporting", "legacy/plugins/reporting"],

View file

@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
export const API_BASE_PATH = '/api/transform/';
export const PLUGIN_ID = 'ml';

View file

@ -8,3 +8,5 @@ export enum LICENSE_TYPE {
BASIC,
FULL, // >= platinum
}
export const VALID_FULL_LICENSE_MODES = ['platinum', 'enterprise', 'trial'];

View file

@ -6,23 +6,13 @@
import { resolve } from 'path';
import { i18n } from '@kbn/i18n';
import KbnServer, { Server } from 'src/legacy/server/kbn_server';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { plugin } from './server/new_platform';
import { CloudSetup } from '../../../plugins/cloud/server';
import { Server } from 'src/legacy/server/kbn_server';
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
import {
MlInitializerContext,
MlCoreSetup,
MlHttpServiceSetup,
} from './server/new_platform/plugin';
// @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
import mappings from './mappings';
interface MlServer extends Server {
addAppLinksToSampleDataset: () => {};
}
export const ml = (kibana: any) => {
return new kibana.Plugin({
require: ['kibana', 'elasticsearch', 'xpack_main'],
@ -60,43 +50,8 @@ export const ml = (kibana: any) => {
},
},
async init(server: MlServer) {
const kbnServer = (server as unknown) as KbnServer;
const initializerContext = ({
legacyConfig: server.config(),
logger: {
get(...contextParts: string[]) {
return kbnServer.newPlatform.coreContext.logger.get('plugins', 'ml', ...contextParts);
},
},
} as unknown) as MlInitializerContext;
const mlHttpService: MlHttpServiceSetup = {
...kbnServer.newPlatform.setup.core.http,
route: server.route.bind(server),
};
const core: MlCoreSetup = {
injectUiAppVars: server.injectUiAppVars,
http: mlHttpService,
savedObjects: server.savedObjects,
coreSavedObjects: kbnServer.newPlatform.start.core.savedObjects,
elasticsearch: kbnServer.newPlatform.setup.core.elasticsearch,
};
const { usageCollection, cloud, home } = kbnServer.newPlatform.setup.plugins;
const plugins = {
elasticsearch: server.plugins.elasticsearch, // legacy
security: server.newPlatform.setup.plugins.security,
xpackMain: server.plugins.xpack_main,
spaces: server.plugins.spaces,
home,
usageCollection: usageCollection as UsageCollectionSetup,
cloud: cloud as CloudSetup,
ml: this,
};
plugin(initializerContext).setup(core, plugins);
async init(server: Server) {
mirrorPluginStatus(server.plugins.xpack_main, this);
},
});
};

View file

@ -1,8 +0,0 @@
{
"id": "ml",
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["ml"],
"server": true,
"ui": true
}

View file

@ -82,9 +82,16 @@ function setLicenseExpired(features: any) {
}
}
}
// Temporary hack for cutting over server to NP
function getFeatures() {
return xpackInfo.get('features.ml');
return {
isAvailable: true,
showLinks: true,
enableLinks: true,
licenseType: 1,
hasExpired: false,
};
// return xpackInfo.get('features.ml');
}
function redirectToKibana() {

View file

@ -1,9 +0,0 @@
/*
* 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 { ElasticsearchPlugin } from 'src/legacy/core_plugins/elasticsearch';
export function callWithInternalUserFactory(elasticsearchPlugin: ElasticsearchPlugin): any;

View file

@ -1,18 +0,0 @@
/*
* 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 { once } from 'lodash';
const _callWithInternalUser = once(elasticsearchPlugin => {
const { callWithInternalUser } = elasticsearchPlugin.getCluster('admin');
return callWithInternalUser;
});
export const callWithInternalUserFactory = elasticsearchPlugin => {
return (...args) => {
return _callWithInternalUser(elasticsearchPlugin)(...args);
};
};

View file

@ -1,28 +0,0 @@
/*
* 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 { callWithInternalUserFactory } from './call_with_internal_user_factory';
describe('call_with_internal_user_factory', () => {
describe('callWithInternalUserFactory', () => {
let elasticsearchPlugin: any;
let callWithInternalUser: any;
beforeEach(() => {
callWithInternalUser = jest.fn();
elasticsearchPlugin = {
getCluster: jest.fn(() => ({ callWithInternalUser })),
};
});
it('should use internal user "admin"', () => {
const callWithInternalUserInstance = callWithInternalUserFactory(elasticsearchPlugin);
callWithInternalUserInstance();
expect(elasticsearchPlugin.getCluster).toHaveBeenCalledWith('admin');
});
});
});

View file

@ -1,21 +0,0 @@
/*
* 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 { once } from 'lodash';
import { elasticsearchJsPlugin } from './elasticsearch_ml';
const callWithRequest = once(elasticsearchPlugin => {
const config = { plugins: [elasticsearchJsPlugin] };
const cluster = elasticsearchPlugin.createCluster('ml', config);
return cluster.callWithRequest;
});
export const callWithRequestFactory = (elasticsearchPlugin, request) => {
return (...args) => {
return callWithRequest(elasticsearchPlugin)(request, ...args);
};
};

View file

@ -1,35 +0,0 @@
/*
* 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 expect from '@kbn/expect';
import { isSecurityDisabled } from '../security_utils';
describe('ML - security utils', () => {
function mockXpackMainPluginFactory(isAvailable = true, isEnabled = true) {
return {
info: {
isAvailable: () => isAvailable,
feature: () => ({
isEnabled: () => isEnabled,
}),
},
};
}
describe('isSecurityDisabled', () => {
it('returns not disabled for given mock server object #1', () => {
expect(isSecurityDisabled(mockXpackMainPluginFactory())).to.be(false);
});
it('returns not disabled for given mock server object #2', () => {
expect(isSecurityDisabled(mockXpackMainPluginFactory(false))).to.be(false);
});
it('returns disabled for given mock server object #3', () => {
expect(isSecurityDisabled(mockXpackMainPluginFactory(true, false))).to.be(true);
});
});
});

View file

@ -1,9 +0,0 @@
/*
* 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 { XPackMainPlugin } from '../../../xpack_main/server/xpack_main';
export function isSecurityDisabled(xpackMainPlugin: XPackMainPlugin): boolean;

View file

@ -1,19 +0,0 @@
/*
* 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.
*/
/*
* Contains utility functions related to x-pack security.
*/
export function isSecurityDisabled(xpackMainPlugin) {
const xpackInfo = xpackMainPlugin && xpackMainPlugin.info;
// we assume that `xpack.isAvailable()` always returns `true` because we're inside x-pack
// if for whatever reason it returns `false`, `isSecurityDisabled()` would also return `false`
// which would result in follow-up behavior assuming security is enabled. This is intentional,
// because it results in more defensive behavior.
const securityInfo = xpackInfo && xpackInfo.isAvailable() && xpackInfo.feature('security');
return securityInfo && securityInfo.isEnabled() === false;
}

View file

@ -1,238 +0,0 @@
/*
* 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 Boom from 'boom';
import { i18n } from '@kbn/i18n';
import { ServerRoute } from 'hapi';
import { KibanaConfig, SavedObjectsLegacyService } from 'src/legacy/server/kbn_server';
import {
Logger,
PluginInitializerContext,
CoreSetup,
IRouter,
IScopedClusterClient,
SavedObjectsServiceStart,
} from 'src/core/server';
import { ElasticsearchPlugin } from 'src/legacy/core_plugins/elasticsearch';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { ElasticsearchServiceSetup } from 'src/core/server';
import { CloudSetup } from '../../../../../plugins/cloud/server';
import { XPackMainPlugin } from '../../../xpack_main/server/xpack_main';
import { addLinksToSampleDatasets } from '../lib/sample_data_sets';
import { checkLicense } from '../lib/check_license';
// @ts-ignore: could not find declaration file for module
import { mirrorPluginStatus } from '../../../../server/lib/mirror_plugin_status';
import { LICENSE_TYPE } from '../../common/constants/license';
import { annotationRoutes } from '../routes/annotations';
import { jobRoutes } from '../routes/anomaly_detectors';
import { dataFeedRoutes } from '../routes/datafeeds';
import { indicesRoutes } from '../routes/indices';
import { jobValidationRoutes } from '../routes/job_validation';
import { makeMlUsageCollector } from '../lib/ml_telemetry';
import { notificationRoutes } from '../routes/notification_settings';
import { systemRoutes } from '../routes/system';
import { dataFrameAnalyticsRoutes } from '../routes/data_frame_analytics';
import { dataRecognizer } from '../routes/modules';
import { dataVisualizerRoutes } from '../routes/data_visualizer';
import { calendars } from '../routes/calendars';
// @ts-ignore: could not find declaration file for module
import { fieldsService } from '../routes/fields_service';
import { filtersRoutes } from '../routes/filters';
import { resultsServiceRoutes } from '../routes/results_service';
import { jobServiceRoutes } from '../routes/job_service';
import { jobAuditMessagesRoutes } from '../routes/job_audit_messages';
import { fileDataVisualizerRoutes } from '../routes/file_data_visualizer';
import { initMlServerLog, LogInitialization } from '../client/log';
import { HomeServerPluginSetup } from '../../../../../../src/plugins/home/server';
// @ts-ignore: could not find declaration file for module
import { elasticsearchJsPlugin } from '../client/elasticsearch_ml';
export const PLUGIN_ID = 'ml';
type CoreHttpSetup = CoreSetup['http'];
export interface MlHttpServiceSetup extends CoreHttpSetup {
route(route: ServerRoute | ServerRoute[]): void;
}
export interface MlXpackMainPlugin extends XPackMainPlugin {
status?: any;
}
export interface MlCoreSetup {
injectUiAppVars: (id: string, callback: () => {}) => any;
http: MlHttpServiceSetup;
savedObjects: SavedObjectsLegacyService;
coreSavedObjects: SavedObjectsServiceStart;
elasticsearch: ElasticsearchServiceSetup;
}
export interface MlInitializerContext extends PluginInitializerContext {
legacyConfig: KibanaConfig;
log: Logger;
}
export interface PluginsSetup {
elasticsearch: ElasticsearchPlugin;
xpackMain: MlXpackMainPlugin;
security: any;
spaces: any;
usageCollection?: UsageCollectionSetup;
cloud?: CloudSetup;
home?: HomeServerPluginSetup;
// TODO: this is temporary for `mirrorPluginStatus`
ml: any;
}
export interface RouteInitialization {
commonRouteConfig: any;
config?: any;
elasticsearchPlugin: ElasticsearchPlugin;
elasticsearchService: ElasticsearchServiceSetup;
route(route: ServerRoute | ServerRoute[]): void;
router: IRouter;
xpackMainPlugin: MlXpackMainPlugin;
savedObjects?: SavedObjectsServiceStart;
spacesPlugin: any;
securityPlugin: any;
cloud?: CloudSetup;
}
declare module 'kibana/server' {
interface RequestHandlerContext {
ml?: {
mlClient: IScopedClusterClient;
};
}
}
export class Plugin {
private readonly pluginId: string = PLUGIN_ID;
private config: any;
private log: Logger;
constructor(initializerContext: MlInitializerContext) {
this.config = initializerContext.legacyConfig;
this.log = initializerContext.logger.get();
}
public setup(core: MlCoreSetup, plugins: PluginsSetup) {
const xpackMainPlugin: MlXpackMainPlugin = plugins.xpackMain;
const { http, coreSavedObjects } = core;
const pluginId = this.pluginId;
mirrorPluginStatus(xpackMainPlugin, plugins.ml);
xpackMainPlugin.status.once('green', () => {
// Register a function that is called whenever the xpack info changes,
// to re-compute the license check results for this plugin
const mlFeature = xpackMainPlugin.info.feature(pluginId);
mlFeature.registerLicenseCheckResultsGenerator(checkLicense);
// Add links to the Kibana sample data sets if ml is enabled
// and there is a full license (trial or platinum).
if (mlFeature.isEnabled() === true && plugins.home) {
const licenseCheckResults = mlFeature.getLicenseCheckResults();
if (licenseCheckResults.licenseType === LICENSE_TYPE.FULL) {
addLinksToSampleDatasets({
addAppLinksToSampleDataset: plugins.home.sampleData.addAppLinksToSampleDataset,
});
}
}
});
xpackMainPlugin.registerFeature({
id: 'ml',
name: i18n.translate('xpack.ml.featureRegistry.mlFeatureName', {
defaultMessage: 'Machine Learning',
}),
icon: 'machineLearningApp',
navLinkId: 'ml',
app: ['ml', 'kibana'],
catalogue: ['ml'],
privileges: {},
reserved: {
privilege: {
savedObject: {
all: [],
read: [],
},
ui: [],
},
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.',
}),
},
});
// Add server routes and initialize the plugin here
const commonRouteConfig = {
pre: [
function forbidApiAccess() {
const licenseCheckResults = xpackMainPlugin.info
.feature(pluginId)
.getLicenseCheckResults();
if (licenseCheckResults.isAvailable) {
return null;
} else {
throw Boom.forbidden(licenseCheckResults.message);
}
},
],
};
// Can access via new platform router's handler function 'context' parameter - context.ml.mlClient
const mlClient = core.elasticsearch.createClient('ml', { plugins: [elasticsearchJsPlugin] });
http.registerRouteHandlerContext('ml', (context, request) => {
return {
mlClient: mlClient.asScoped(request),
};
});
const routeInitializationDeps: RouteInitialization = {
commonRouteConfig,
route: http.route,
router: http.createRouter(),
elasticsearchPlugin: plugins.elasticsearch,
elasticsearchService: core.elasticsearch,
xpackMainPlugin: plugins.xpackMain,
spacesPlugin: plugins.spaces,
securityPlugin: plugins.security,
};
const extendedRouteInitializationDeps: RouteInitialization = {
...routeInitializationDeps,
config: this.config,
savedObjects: coreSavedObjects,
spacesPlugin: plugins.spaces,
cloud: plugins.cloud,
};
const logInitializationDeps: LogInitialization = {
log: this.log,
};
annotationRoutes(routeInitializationDeps);
jobRoutes(routeInitializationDeps);
dataFeedRoutes(routeInitializationDeps);
dataFrameAnalyticsRoutes(routeInitializationDeps);
indicesRoutes(routeInitializationDeps);
jobValidationRoutes(extendedRouteInitializationDeps);
notificationRoutes(routeInitializationDeps);
systemRoutes(extendedRouteInitializationDeps);
dataRecognizer(extendedRouteInitializationDeps);
dataVisualizerRoutes(routeInitializationDeps);
calendars(routeInitializationDeps);
fieldsService(routeInitializationDeps);
filtersRoutes(routeInitializationDeps);
resultsServiceRoutes(routeInitializationDeps);
jobServiceRoutes(routeInitializationDeps);
jobAuditMessagesRoutes(routeInitializationDeps);
fileDataVisualizerRoutes(extendedRouteInitializationDeps);
initMlServerLog(logInitializationDeps);
makeMlUsageCollector(plugins.usageCollection, coreSavedObjects);
}
public stop() {}
}

View file

@ -0,0 +1,9 @@
{
"id": "ml",
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["ml"],
"requiredPlugins": ["cloud", "features", "home", "licensing", "security", "spaces", "usageCollection"],
"server": true,
"ui": false
}

View file

@ -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 '../../../../../src/core/server';
export interface LogInitialization {
log: Logger;

View file

@ -4,8 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Plugin, MlInitializerContext } from './plugin';
import { PluginInitializerContext } from 'kibana/server';
import { MlServerPlugin } from './plugin';
export function plugin(initializerContext: MlInitializerContext) {
return new Plugin(initializerContext);
}
export const plugin = (ctx: PluginInitializerContext) => new MlServerPlugin(ctx);

View file

@ -10,7 +10,7 @@ import {
ML_ANNOTATIONS_INDEX_ALIAS_READ,
ML_ANNOTATIONS_INDEX_ALIAS_WRITE,
ML_ANNOTATIONS_INDEX_PATTERN,
} from '../../../common/constants/index_patterns';
} from '../../../../../legacy/plugins/ml/common/constants/index_patterns';
// Annotations Feature is available if:
// - ML_ANNOTATIONS_INDEX_PATTERN index is present

View file

@ -7,12 +7,12 @@
import expect from '@kbn/expect';
import sinon from 'sinon';
import { set } from 'lodash';
import { XPackInfo } from '../../../../xpack_main/server/lib/xpack_info';
import { LicenseCheckResult } from '../../types';
import { checkLicense } from './check_license';
describe('check_license', () => {
let mockLicenseInfo: XPackInfo;
beforeEach(() => (mockLicenseInfo = {} as XPackInfo));
let mockLicenseInfo: LicenseCheckResult;
beforeEach(() => (mockLicenseInfo = {} as LicenseCheckResult));
describe('license information is undefined', () => {
it('should set isAvailable to false', () => {
@ -33,7 +33,9 @@ describe('check_license', () => {
});
describe('license information is not available', () => {
beforeEach(() => (mockLicenseInfo.isAvailable = () => false));
beforeEach(() => {
mockLicenseInfo.isAvailable = false;
});
it('should set isAvailable to false', () => {
expect(checkLicense(mockLicenseInfo).isAvailable).to.be(false);
@ -54,8 +56,8 @@ describe('check_license', () => {
describe('license information is available', () => {
beforeEach(() => {
mockLicenseInfo.isAvailable = () => true;
set(mockLicenseInfo, 'license.getType', () => 'basic');
mockLicenseInfo.isAvailable = true;
mockLicenseInfo.type = 'basic';
});
describe('& ML is disabled in Elasticsearch', () => {
@ -66,7 +68,7 @@ describe('check_license', () => {
sinon
.stub()
.withArgs('ml')
.returns({ isEnabled: () => false })
.returns({ isEnabled: false })
);
});
@ -89,21 +91,17 @@ describe('check_license', () => {
describe('& ML is enabled in Elasticsearch', () => {
beforeEach(() => {
set(
mockLicenseInfo,
'feature',
sinon
.stub()
.withArgs('ml')
.returns({ isEnabled: () => true })
);
mockLicenseInfo.isEnabled = true;
});
describe('& license is >= platinum', () => {
beforeEach(() => set(mockLicenseInfo, 'license.isOneOf', () => true));
beforeEach(() => {
mockLicenseInfo.type = 'platinum';
});
describe('& license is active', () => {
beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => true));
beforeEach(() => {
mockLicenseInfo.isActive = true;
});
it('should set isAvailable to true', () => {
expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true);
@ -123,7 +121,9 @@ describe('check_license', () => {
});
describe('& license is expired', () => {
beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => false));
beforeEach(() => {
mockLicenseInfo.isActive = false;
});
it('should set isAvailable to true', () => {
expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true);
@ -144,10 +144,14 @@ describe('check_license', () => {
});
describe('& license is basic', () => {
beforeEach(() => set(mockLicenseInfo, 'license.isOneOf', () => false));
beforeEach(() => {
mockLicenseInfo.type = 'basic';
});
describe('& license is active', () => {
beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => true));
beforeEach(() => {
mockLicenseInfo.isActive = true;
});
it('should set isAvailable to true', () => {
expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true);

View file

@ -5,8 +5,11 @@
*/
import { i18n } from '@kbn/i18n';
import { LICENSE_TYPE } from '../../../common/constants/license';
import { XPackInfo } from '../../../../../../legacy/plugins/xpack_main/server/lib/xpack_info';
import {
LICENSE_TYPE,
VALID_FULL_LICENSE_MODES,
} from '../../../../../legacy/plugins/ml/common/constants/license';
import { LicenseCheckResult } from '../../types';
interface Response {
isAvailable: boolean;
@ -17,10 +20,10 @@ interface Response {
message?: string;
}
export function checkLicense(xpackLicenseInfo: XPackInfo): Response {
export function checkLicense(licenseCheckResult: LicenseCheckResult): Response {
// If, for some reason, we cannot get the license information
// from Elasticsearch, assume worst case and disable the Machine Learning UI
if (!xpackLicenseInfo || !xpackLicenseInfo.isAvailable()) {
if (licenseCheckResult === undefined || !licenseCheckResult.isAvailable) {
return {
isAvailable: false,
showLinks: true,
@ -35,7 +38,7 @@ export function checkLicense(xpackLicenseInfo: XPackInfo): Response {
};
}
const featureEnabled = xpackLicenseInfo.feature('ml').isEnabled();
const featureEnabled = licenseCheckResult.isEnabled;
if (!featureEnabled) {
return {
isAvailable: false,
@ -47,12 +50,11 @@ export function checkLicense(xpackLicenseInfo: XPackInfo): Response {
};
}
const VALID_FULL_LICENSE_MODES = ['platinum', 'enterprise', 'trial'];
const isLicenseModeValid = xpackLicenseInfo.license.isOneOf(VALID_FULL_LICENSE_MODES);
const isLicenseModeValid =
licenseCheckResult.type && VALID_FULL_LICENSE_MODES.includes(licenseCheckResult.type);
const licenseType = isLicenseModeValid === true ? LICENSE_TYPE.FULL : LICENSE_TYPE.BASIC;
const isLicenseActive = xpackLicenseInfo.license.isActive();
const licenseTypeName = xpackLicenseInfo.license.getType();
const isLicenseActive = licenseCheckResult.isActive;
const licenseTypeName = licenseCheckResult.type;
// Platinum or trial license is valid but not active, i.e. expired
if (licenseType === LICENSE_TYPE.FULL && isLicenseActive === false) {

View file

@ -8,81 +8,29 @@ import { callWithRequestProvider } from './__mocks__/call_with_request';
import { privilegesProvider } from './check_privileges';
import { mlPrivileges } from './privileges';
const xpackMainPluginWithSecurity = {
info: {
isAvailable: () => true,
feature: (f: string) => {
switch (f) {
case 'ml':
return { isEnabled: () => true };
case 'security':
return { isEnabled: () => true };
}
},
license: {
isOneOf: () => true,
isActive: () => true,
getType: () => 'platinum',
},
},
} as any;
const licenseCheckResultWithSecurity = {
isAvailable: true,
isEnabled: true,
isSecurityDisabled: false,
type: 'platinum',
isActive: true,
};
const xpackMainPluginWithOutSecurity = {
info: {
isAvailable: () => true,
feature: (f: string) => {
switch (f) {
case 'ml':
return { isEnabled: () => true };
case 'security':
return { isEnabled: () => false };
}
},
license: {
isOneOf: () => true,
isActive: () => true,
getType: () => 'platinum',
},
},
} as any;
const licenseCheckResultWithOutSecurity = {
...licenseCheckResultWithSecurity,
isSecurityDisabled: true,
};
const xpackMainPluginWithOutSecurityBasicLicense = {
info: {
isAvailable: () => true,
feature: (f: string) => {
switch (f) {
case 'ml':
return { isEnabled: () => true };
case 'security':
return { isEnabled: () => false };
}
},
license: {
isOneOf: () => false,
isActive: () => true,
getType: () => 'basic',
},
},
} as any;
const licenseCheckResultWithOutSecurityBasicLicense = {
...licenseCheckResultWithSecurity,
isSecurityDisabled: true,
type: 'basic',
};
const xpackMainPluginWithSecurityBasicLicense = {
info: {
isAvailable: () => true,
feature: (f: string) => {
switch (f) {
case 'ml':
return { isEnabled: () => true };
case 'security':
return { isEnabled: () => true };
}
},
license: {
isOneOf: () => false,
isActive: () => true,
getType: () => 'basic',
},
},
} as any;
const licenseCheckResultWithSecurityBasicLicense = {
...licenseCheckResultWithSecurity,
type: 'basic',
};
const mlIsEnabled = async () => true;
const mlIsNotEnabled = async () => false;
@ -99,7 +47,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('partialPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithSecurity,
licenseCheckResultWithSecurity,
mlIsEnabled
);
const { capabilities } = await getPrivileges();
@ -114,7 +62,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('partialPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithSecurity,
licenseCheckResultWithSecurity,
mlIsEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();
@ -149,7 +97,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('fullPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithSecurity,
licenseCheckResultWithSecurity,
mlIsEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();
@ -184,7 +132,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('upgradeWithFullPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithSecurity,
licenseCheckResultWithSecurity,
mlIsEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();
@ -219,7 +167,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('upgradeWithPartialPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithSecurity,
licenseCheckResultWithSecurity,
mlIsEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();
@ -254,7 +202,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('partialPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithSecurityBasicLicense,
licenseCheckResultWithSecurityBasicLicense,
mlIsEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();
@ -289,7 +237,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('fullPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithSecurityBasicLicense,
licenseCheckResultWithSecurityBasicLicense,
mlIsEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();
@ -324,7 +272,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('fullPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithSecurity,
licenseCheckResultWithSecurity,
mlIsNotEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();
@ -361,7 +309,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('partialPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithOutSecurity,
licenseCheckResultWithOutSecurity,
mlIsEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();
@ -396,7 +344,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('upgradeWithFullPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithOutSecurity,
licenseCheckResultWithOutSecurity,
mlIsEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();
@ -431,7 +379,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('upgradeWithPartialPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithOutSecurity,
licenseCheckResultWithOutSecurity,
mlIsEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();
@ -466,7 +414,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('partialPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithOutSecurityBasicLicense,
licenseCheckResultWithOutSecurityBasicLicense,
mlIsEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();
@ -501,7 +449,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('fullPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithOutSecurityBasicLicense,
licenseCheckResultWithOutSecurityBasicLicense,
mlIsEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();
@ -536,7 +484,7 @@ describe('check_privileges', () => {
const callWithRequest = callWithRequestProvider('partialPrivileges');
const { getPrivileges } = privilegesProvider(
callWithRequest,
xpackMainPluginWithOutSecurity,
licenseCheckResultWithOutSecurity,
mlIsNotEnabled
);
const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges();

View file

@ -5,12 +5,14 @@
*/
import { IScopedClusterClient } from 'kibana/server';
import { Privileges, getDefaultPrivileges } from '../../../common/types/privileges';
import { XPackMainPlugin } from '../../../../xpack_main/server/xpack_main';
import { isSecurityDisabled } from '../../lib/security_utils';
import {
Privileges,
getDefaultPrivileges,
} from '../../../../../legacy/plugins/ml/common/types/privileges';
import { upgradeCheckProvider } from './upgrade';
import { checkLicense } from '../check_license';
import { LICENSE_TYPE } from '../../../common/constants/license';
import { LICENSE_TYPE } from '../../../../../legacy/plugins/ml/common/constants/license';
import { LicenseCheckResult } from '../../types';
import { mlPrivileges } from './privileges';
@ -25,7 +27,7 @@ interface Response {
export function privilegesProvider(
callAsCurrentUser: IScopedClusterClient['callAsCurrentUser'],
xpackMainPlugin: XPackMainPlugin,
licenseCheckResult: LicenseCheckResult,
isMlEnabledInSpace: () => Promise<boolean>,
ignoreSpaces: boolean = false
) {
@ -35,8 +37,8 @@ export function privilegesProvider(
const privileges = getDefaultPrivileges();
const upgradeInProgress = await isUpgradeInProgress();
const securityDisabled = isSecurityDisabled(xpackMainPlugin);
const license = checkLicense(xpackMainPlugin.info);
const securityDisabled = licenseCheckResult.isSecurityDisabled;
const license = checkLicense(licenseCheckResult);
const isPlatinumOrTrialLicense = license.licenseType === LICENSE_TYPE.FULL;
const mlFeatureEnabledInSpace = await isMlEnabledInSpace();

View file

@ -55,10 +55,9 @@ describe('ml_telemetry', () => {
});
describe('incrementFileDataVisualizerIndexCreationCount', () => {
let savedObjects: any;
let internalRepository: any;
let savedObjectsClient: any;
function createInternalRepositoryInstance(
function createSavedObjectsClientInstance(
telemetryEnabled?: boolean,
indexCreationCount?: number
) {
@ -93,42 +92,39 @@ describe('ml_telemetry', () => {
}
function mockInit(telemetryEnabled?: boolean, indexCreationCount?: number): void {
internalRepository = createInternalRepositoryInstance(telemetryEnabled, indexCreationCount);
savedObjects = {
createInternalRepository: jest.fn(() => internalRepository),
};
savedObjectsClient = createSavedObjectsClientInstance(telemetryEnabled, indexCreationCount);
}
it('should not increment if telemetry status cannot be determined', async () => {
mockInit();
await incrementFileDataVisualizerIndexCreationCount(savedObjects);
await incrementFileDataVisualizerIndexCreationCount(savedObjectsClient);
expect(internalRepository.create.mock.calls).toHaveLength(0);
expect(savedObjectsClient.create.mock.calls).toHaveLength(0);
});
it('should not increment if telemetry status is disabled', async () => {
mockInit(false);
await incrementFileDataVisualizerIndexCreationCount(savedObjects);
await incrementFileDataVisualizerIndexCreationCount(savedObjectsClient);
expect(internalRepository.create.mock.calls).toHaveLength(0);
expect(savedObjectsClient.create.mock.calls).toHaveLength(0);
});
it('should initialize index_creation_count with 1', async () => {
mockInit(true);
await incrementFileDataVisualizerIndexCreationCount(savedObjects);
await incrementFileDataVisualizerIndexCreationCount(savedObjectsClient);
expect(internalRepository.create.mock.calls[0][0]).toBe('ml-telemetry');
expect(internalRepository.create.mock.calls[0][1]).toEqual({
expect(savedObjectsClient.create.mock.calls[0][0]).toBe('ml-telemetry');
expect(savedObjectsClient.create.mock.calls[0][1]).toEqual({
file_data_visualizer: { index_creation_count: 1 },
});
});
it('should increment index_creation_count to 2', async () => {
mockInit(true, 1);
await incrementFileDataVisualizerIndexCreationCount(savedObjects);
await incrementFileDataVisualizerIndexCreationCount(savedObjectsClient);
expect(internalRepository.create.mock.calls[0][0]).toBe('ml-telemetry');
expect(internalRepository.create.mock.calls[0][1]).toEqual({
expect(savedObjectsClient.create.mock.calls[0][0]).toBe('ml-telemetry');
expect(savedObjectsClient.create.mock.calls[0][1]).toEqual({
file_data_visualizer: { index_creation_count: 2 },
});
});

View file

@ -4,11 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import {
SavedObjectAttributes,
SavedObjectsServiceStart,
ISavedObjectsRepository,
} from 'src/core/server';
import { SavedObjectAttributes, SavedObjectsClientContract } from 'src/core/server';
export interface MlTelemetry extends SavedObjectAttributes {
file_data_visualizer: {
@ -31,21 +27,20 @@ export function createMlTelemetry(count: number = 0): MlTelemetry {
}
// savedObjects
export function storeMlTelemetry(
internalRepository: ISavedObjectsRepository,
savedObjectsClient: SavedObjectsClientContract,
mlTelemetry: MlTelemetry
): void {
internalRepository.create('ml-telemetry', mlTelemetry, {
savedObjectsClient.create('ml-telemetry', mlTelemetry, {
id: ML_TELEMETRY_DOC_ID,
overwrite: true,
});
}
export async function incrementFileDataVisualizerIndexCreationCount(
savedObjects: SavedObjectsServiceStart
savedObjectsClient: SavedObjectsClientContract
): Promise<void> {
const internalRepository = await savedObjects.createInternalRepository();
try {
const { attributes } = await internalRepository.get('telemetry', 'telemetry');
const { attributes } = await savedObjectsClient.get('telemetry', 'telemetry');
if (attributes.enabled === false) {
return;
@ -59,7 +54,7 @@ export async function incrementFileDataVisualizerIndexCreationCount(
let indicesCount = 1;
try {
const { attributes } = (await internalRepository.get(
const { attributes } = (await savedObjectsClient.get(
'ml-telemetry',
ML_TELEMETRY_DOC_ID
)) as MlTelemetrySavedObject;
@ -69,5 +64,5 @@ export async function incrementFileDataVisualizerIndexCreationCount(
}
const mlTelemetry = createMlTelemetry(indicesCount);
storeMlTelemetry(internalRepository, mlTelemetry);
storeMlTelemetry(savedObjectsClient, mlTelemetry);
}

View file

@ -5,20 +5,19 @@
*/
import { Request } from 'hapi';
import { Space } from '../../../../../plugins/spaces/server';
import { LegacySpacesPlugin } from '../../../spaces';
import { Space, SpacesPluginSetup } from '../../../spaces/server';
interface GetActiveSpaceResponse {
valid: boolean;
space?: Space;
}
export function spacesUtilsProvider(spacesPlugin: LegacySpacesPlugin, request: Request) {
export function spacesUtilsProvider(spacesPlugin: SpacesPluginSetup, request: Request) {
async function activeSpace(): Promise<GetActiveSpaceResponse> {
try {
return {
valid: true,
space: await spacesPlugin.getActiveSpace(request),
space: await spacesPlugin.spacesService.getActiveSpace(request),
};
} catch (e) {
return {

View file

@ -8,9 +8,12 @@ import getAnnotationsRequestMock from './__mocks__/get_annotations_request.json'
import getAnnotationsResponseMock from './__mocks__/get_annotations_response.json';
import { RequestHandlerContext } from 'src/core/server';
import { ANNOTATION_TYPE } from '../../../common/constants/annotations';
import { ML_ANNOTATIONS_INDEX_ALIAS_WRITE } from '../../../common/constants/index_patterns';
import { Annotation, isAnnotations } from '../../../common/types/annotations';
import { ANNOTATION_TYPE } from '../../../../../legacy/plugins/ml/common/constants/annotations';
import { ML_ANNOTATIONS_INDEX_ALIAS_WRITE } from '../../../../../legacy/plugins/ml/common/constants/index_patterns';
import {
Annotation,
isAnnotations,
} from '../../../../../legacy/plugins/ml/common/types/annotations';
import { DeleteParams, GetResponse, IndexAnnotationArgs } from './annotation';
import { annotationServiceProvider } from './index';

View file

@ -8,18 +8,18 @@ import Boom from 'boom';
import _ from 'lodash';
import { RequestHandlerContext } from 'src/core/server';
import { ANNOTATION_TYPE } from '../../../common/constants/annotations';
import { ANNOTATION_TYPE } from '../../../../../legacy/plugins/ml/common/constants/annotations';
import {
ML_ANNOTATIONS_INDEX_ALIAS_READ,
ML_ANNOTATIONS_INDEX_ALIAS_WRITE,
} from '../../../common/constants/index_patterns';
} from '../../../../../legacy/plugins/ml/common/constants/index_patterns';
import {
Annotation,
Annotations,
isAnnotation,
isAnnotations,
} from '../../../common/types/annotations';
} from '../../../../../legacy/plugins/ml/common/types/annotations';
// TODO All of the following interface/type definitions should
// eventually be replaced by the proper upstream definitions

View file

@ -5,10 +5,10 @@
*/
import { APICaller } from 'src/core/server';
import { BucketSpanEstimatorData } from '../../../public/application/services/ml_api_service';
import { BucketSpanEstimatorData } from '../../../../../legacy/plugins/ml/public/application/services/ml_api_service';
export function estimateBucketSpanFactory(
callAsCurrentUser: APICaller,
callAsInternalUser: APICaller,
xpackMainPlugin: any
isSecurityDisabled: boolean
): (config: BucketSpanEstimatorData) => Promise<any>;

View file

@ -12,9 +12,11 @@ import { INTERVALS } from './intervals';
import { singleSeriesCheckerFactory } from './single_series_checker';
import { polledDataCheckerFactory } from './polled_data_checker';
import { isSecurityDisabled } from '../../lib/security_utils';
export function estimateBucketSpanFactory(callAsCurrentUser, callAsInternalUser, xpackMainPlugin) {
export function estimateBucketSpanFactory(
callAsCurrentUser,
callAsInternalUser,
isSecurityDisabled
) {
const PolledDataChecker = polledDataCheckerFactory(callAsCurrentUser);
const SingleSeriesChecker = singleSeriesCheckerFactory(callAsCurrentUser);
@ -384,7 +386,7 @@ export function estimateBucketSpanFactory(callAsCurrentUser, callAsInternalUser,
});
}
if (isSecurityDisabled(xpackMainPlugin)) {
if (isSecurityDisabled) {
getBucketSpanEstimation();
} else {
// if security is enabled, check that the user has permission to

View file

@ -6,7 +6,7 @@
import Boom from 'boom';
import { GLOBAL_CALENDAR } from '../../../common/constants/calendars';
import { GLOBAL_CALENDAR } from '../../../../../legacy/plugins/ml/common/constants/calendars';
export interface CalendarEvent {
calendar_id?: string;

View file

@ -4,9 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { callWithRequestType } from '../../../common/types/kibana';
import { ML_NOTIFICATION_INDEX_PATTERN } from '../../../common/constants/index_patterns';
import { JobMessage } from '../../../common/types/audit_message';
import { callWithRequestType } from '../../../../../legacy/plugins/ml/common/types/kibana';
import { ML_NOTIFICATION_INDEX_PATTERN } from '../../../../../legacy/plugins/ml/common/constants/index_patterns';
import { JobMessage } from '../../../../../legacy/plugins/ml/common/types/audit_message';
const SIZE = 50;

View file

@ -5,7 +5,7 @@
*/
import { RequestHandlerContext } from 'kibana/server';
import { Module } from '../../../common/types/modules';
import { Module } from '../../../../../legacy/plugins/ml/common/types/modules';
import { DataRecognizer } from '../data_recognizer';
describe('ML - data recognizer', () => {

View file

@ -10,7 +10,7 @@ import numeral from '@elastic/numeral';
import { CallAPIOptions, RequestHandlerContext, SavedObjectsClientContract } from 'kibana/server';
import { IndexPatternAttributes } from 'src/plugins/data/server';
import { merge } from 'lodash';
import { MlJob } from '../../../common/types/jobs';
import { MlJob } from '../../../../../legacy/plugins/ml/common/types/jobs';
import {
KibanaObjects,
ModuleDataFeed,
@ -23,8 +23,11 @@ import {
JobResponse,
KibanaObjectResponse,
DataRecognizerConfigResponse,
} from '../../../common/types/modules';
import { getLatestDataOrBucketTimestamp, prefixDatafeedId } from '../../../common/util/job_utils';
} from '../../../../../legacy/plugins/ml/common/types/modules';
import {
getLatestDataOrBucketTimestamp,
prefixDatafeedId,
} from '../../../../../legacy/plugins/ml/common/util/job_utils';
import { mlLog } from '../../client/log';
// @ts-ignore
import { jobServiceProvider } from '../job_service';

Some files were not shown because too many files have changed in this diff Show more