[ML] Server info service refactor (#50302)

* [ML] Server info service refactor

* removing new job defaults

* changes based on review

* renaming all ml server info getter functions

* missed a file
This commit is contained in:
James Gowdy 2019-11-13 11:05:49 +00:00 committed by GitHub
parent e6ea2bf16b
commit 167dd7f5a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 163 additions and 110 deletions

View file

@ -16,7 +16,7 @@ import { getFileDataVisualizerBreadcrumbs } from './breadcrumbs';
import { checkBasicLicense } from '../../license/check_license';
import { checkFindFileStructurePrivilege } from '../../privilege/check_privilege';
import { getMlNodeCount } from '../../ml_nodes_check/check_ml_nodes';
import { loadNewJobDefaults } from '../../jobs/new_job_new/utils/new_job_defaults';
import { loadMlServerInfo } from '../../services/ml_server_info';
import { loadIndexPatterns } from '../../util/index_utils';
import { FileDataVisualizerPage } from './file_datavisualizer';
@ -36,7 +36,7 @@ uiRoutes
privileges: checkFindFileStructurePrivilege,
indexPatterns: loadIndexPatterns,
mlNodeCount: getMlNodeCount,
loadNewJobDefaults,
loadMlServerInfo,
}
});

View file

@ -7,7 +7,7 @@
import { difference } from 'lodash';
import chrome from 'ui/chrome';
import { newJobLimits } from 'plugins/ml/jobs/new_job_new/utils/new_job_defaults';
import { getNewJobLimits } from '../../../../services/ml_server_info';
import { mlJobService } from 'plugins/ml/services/job_service';
import { processCreatedBy } from '../../../../../common/util/job_utils';
@ -157,7 +157,7 @@ function extractGroups(job, newJobData) {
}
function extractMML(job, newJobData) {
const jobLimits = newJobLimits();
const jobLimits = getNewJobLimits();
const mmlData = {};
// if the job's model_memory_limit has changed, add it to the jobData json
if (job.analysis_limits.model_memory_limit !== undefined) {

View file

@ -19,7 +19,7 @@ import {
} from '@elastic/eui';
import { calculateDatafeedFrequencyDefaultSeconds } from 'plugins/ml/../common/util/job_utils';
import { newJobDefaults } from 'plugins/ml/jobs/new_job_new/utils/new_job_defaults';
import { getNewJobDefaults } from '../../../../../services/ml_server_info';
import { parseInterval } from 'plugins/ml/../common/util/parse_interval';
import { MLJobEditor } from '../../ml_job_editor';
import { FormattedMessage } from '@kbn/i18n/react';
@ -47,7 +47,7 @@ export class Datafeed extends Component {
frequency: '',
scrollSize: 0,
},
jobDefaults: newJobDefaults()
jobDefaults: getNewJobDefaults()
};
this.setDatafeed = props.setDatafeed;

View file

@ -9,58 +9,58 @@ import React, { Fragment, FC } from 'react';
import { EuiCallOut, EuiLink, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { mlNodesAvailable, permissionToViewMlNodeCount } from '../../../../ml_nodes_check';
import { cloudDeploymentId, isCloud } from '../../../../jobs/new_job_new/utils/new_job_defaults';
import { getCloudDeploymentId, isCloud } from '../../../../services/ml_server_info';
export const NodeAvailableWarning: FC = () => {
if (mlNodesAvailable() === true || permissionToViewMlNodeCount() === false) {
return null;
} else {
const id = cloudDeploymentId();
return (
<Fragment>
<EuiCallOut
title={
<FormattedMessage
id="xpack.ml.jobsList.nodeAvailableWarning.noMLNodesAvailableTitle"
defaultMessage="No ML nodes available"
/>
}
color="warning"
iconType="alert"
>
<p>
<FormattedMessage
id="xpack.ml.jobsList.nodeAvailableWarning.noMLNodesAvailableDescription"
defaultMessage="There are no ML nodes available."
/>
<br />
<FormattedMessage
id="xpack.ml.jobsList.nodeAvailableWarning.unavailableCreateOrRunJobsDescription"
defaultMessage="You will not be able to create or run jobs."
/>
{isCloud && id !== null && (
<Fragment>
<br />
<FormattedMessage
id="xpack.ml.jobsList.nodeAvailableWarning.linkToCloudDescription"
defaultMessage="Please edit your {link}. You may enable a free 1GB machine learning node or expand your existing ML configuration."
values={{
link: (
<EuiLink href={`https://cloud.elastic.co/deployments?q=${id}`}>
<FormattedMessage
id="xpack.ml.jobsList.nodeAvailableWarning.linkToCloud.hereLinkText"
defaultMessage="Elastic Cloud deployment"
/>
</EuiLink>
),
}}
/>
</Fragment>
)}
</p>
</EuiCallOut>
<EuiSpacer size="m" />
</Fragment>
);
}
const id = getCloudDeploymentId();
return (
<Fragment>
<EuiCallOut
title={
<FormattedMessage
id="xpack.ml.jobsList.nodeAvailableWarning.noMLNodesAvailableTitle"
defaultMessage="No ML nodes available"
/>
}
color="warning"
iconType="alert"
>
<div>
<FormattedMessage
id="xpack.ml.jobsList.nodeAvailableWarning.noMLNodesAvailableDescription"
defaultMessage="There are no ML nodes available."
/>
</div>
<div>
<FormattedMessage
id="xpack.ml.jobsList.nodeAvailableWarning.unavailableCreateOrRunJobsDescription"
defaultMessage="You will not be able to create or run jobs."
/>
</div>
{isCloud && id !== null && (
<div>
<FormattedMessage
id="xpack.ml.jobsList.nodeAvailableWarning.linkToCloudDescription"
defaultMessage="Please edit your {link}. You may enable a free 1GB machine learning node or expand your existing ML configuration."
values={{
link: (
<EuiLink href={`https://cloud.elastic.co/deployments?q=${id}`}>
<FormattedMessage
id="xpack.ml.jobsList.nodeAvailableWarning.linkToCloud.hereLinkText"
defaultMessage="Elastic Cloud deployment"
/>
</EuiLink>
),
}}
/>
</div>
)}
</EuiCallOut>
<EuiSpacer size="m" />
</Fragment>
);
};

View file

@ -5,7 +5,7 @@
*/
import { newJobLimits } from '../../new_job_new/utils/new_job_defaults';
import { getNewJobLimits } from '../../../services/ml_server_info';
import { populateValidationMessages } from '../../new_job_new/common/job_validator/util';
import {
@ -16,7 +16,7 @@ import {
import { isValidLabel, isValidTimeRange } from '../../../util/custom_url_utils';
export function validateModelMemoryLimit(mml) {
const limits = newJobLimits();
const limits = getNewJobLimits();
const tempJob = {
analysis_limits: {
model_memory_limit: mml

View file

@ -16,7 +16,7 @@ import { checkFullLicense } from 'plugins/ml/license/check_license';
import { checkGetJobsPrivilege } from 'plugins/ml/privilege/check_privilege';
import { getMlNodeCount } from 'plugins/ml/ml_nodes_check/check_ml_nodes';
import { getJobManagementBreadcrumbs } from 'plugins/ml/jobs/breadcrumbs';
import { loadNewJobDefaults } from 'plugins/ml/jobs/new_job_new/utils/new_job_defaults';
import { loadMlServerInfo } from 'plugins/ml/services/ml_server_info';
import uiRoutes from 'ui/routes';
@ -31,7 +31,7 @@ uiRoutes
indexPatterns: loadIndexPatterns,
privileges: checkGetJobsPrivilege,
mlNodeCount: getMlNodeCount,
loadNewJobDefaults,
loadMlServerInfo,
}
});

View file

@ -6,7 +6,7 @@
import { ReactElement } from 'react';
import { basicJobValidation, basicDatafeedValidation } from '../../../../../common/util/job_utils';
import { newJobLimits } from '../../../new_job_new/utils/new_job_defaults';
import { getNewJobLimits } from '../../../../services/ml_server_info';
import { JobCreatorType } from '../job_creator';
import { populateValidationMessages, checkForExistingJobAndGroupIds } from './util';
import { ExistingJobsAndGroups } from '../../../../services/job_service';
@ -111,7 +111,7 @@ export class JobValidator {
const jobConfig = this._jobCreator.jobConfig;
const datafeedConfig = this._jobCreator.datafeedConfig;
const limits = newJobLimits();
const limits = getNewJobLimits();
// run standard basic validation
const basicJobResults = basicJobValidation(jobConfig, undefined, limits);

View file

@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n';
import { BasicValidations } from './job_validator';
import { Job, Datafeed } from '../job_creator/configs';
import { ALLOWED_DATA_UNITS, JOB_ID_MAX_LENGTH } from '../../../../../common/constants/validation';
import { newJobLimits } from '../../../new_job_new/utils/new_job_defaults';
import { getNewJobLimits } from '../../../../services/ml_server_info';
import { ValidationResults, ValidationMessage } from '../../../../../common/util/job_utils';
import { ExistingJobsAndGroups } from '../../../../services/job_service';
@ -18,7 +18,7 @@ export function populateValidationMessages(
jobConfig: Job,
datafeedConfig: Datafeed
) {
const limits = newJobLimits();
const limits = getNewJobLimits();
if (validationResults.contains('job_id_empty')) {
basicValidations.jobId.valid = false;

View file

@ -6,7 +6,7 @@
import React, { FC, useState, useContext, useEffect } from 'react';
import { EuiFieldText } from '@elastic/eui';
import { newJobDefaults } from '../../../../../new_job_new/utils/new_job_defaults';
import { getNewJobDefaults } from '../../../../../../services/ml_server_info';
import { JobCreatorContext } from '../../job_creator_context';
import { Description } from './description';
@ -23,7 +23,7 @@ export const ModelMemoryLimitInput: FC = () => {
jobCreator.modelMemoryLimit === null ? '' : jobCreator.modelMemoryLimit
);
const { anomaly_detectors: anomalyDetectors } = newJobDefaults();
const { anomaly_detectors: anomalyDetectors } = getNewJobDefaults();
const { model_memory_limit: modelMemoryLimitDefault } = anomalyDetectors;
useEffect(() => {

View file

@ -6,7 +6,7 @@
import React, { FC, useState, useContext, useEffect } from 'react';
import { EuiFieldNumber } from '@elastic/eui';
import { newJobDefaults } from '../../../../../utils/new_job_defaults';
import { getNewJobDefaults } from '../../../../../../../services/ml_server_info';
import { JobCreatorContext } from '../../../job_creator_context';
import { Description } from './description';
@ -19,7 +19,7 @@ export const ScrollSizeInput: FC = () => {
jobCreator.scrollSize === null ? '' : `${jobCreator.scrollSize}`
);
const { datafeeds } = newJobDefaults();
const { datafeeds } = getNewJobDefaults();
const scrollSizeDefault = datafeeds.scroll_size !== undefined ? `${datafeeds.scroll_size}` : '';
useEffect(() => {

View file

@ -11,14 +11,14 @@ import { JobCreatorContext } from '../../../job_creator_context';
import { MLJobEditor } from '../../../../../../jobs_list/components/ml_job_editor';
import { calculateDatafeedFrequencyDefaultSeconds } from '../../../../../../../../common/util/job_utils';
import { DEFAULT_QUERY_DELAY } from '../../../../../common/job_creator/util/constants';
import { newJobDefaults } from '../../../../../utils/new_job_defaults';
import { getNewJobDefaults } from '../../../../../../../services/ml_server_info';
import { ListItems, defaultLabel, Italic } from '../common';
const EDITOR_HEIGHT = '200px';
export const DatafeedDetails: FC = () => {
const { jobCreator } = useContext(JobCreatorContext);
const { datafeeds } = newJobDefaults();
const { datafeeds } = getNewJobDefaults();
const queryString = JSON.stringify(jobCreator.query, null, 2);
const defaultFrequency = calculateDatafeedFrequencyDefaultSeconds(jobCreator.bucketSpanMs / 1000);

View file

@ -15,7 +15,7 @@ import {
isPopulationJobCreator,
isAdvancedJobCreator,
} from '../../../../../common/job_creator';
import { newJobDefaults } from '../../../../../utils/new_job_defaults';
import { getNewJobDefaults } from '../../../../../../../services/ml_server_info';
import { ListItems, falseLabel, trueLabel, defaultLabel, Italic } from '../common';
import { useKibanaContext } from '../../../../../../../contexts/kibana';
@ -23,7 +23,7 @@ export const JobDetails: FC = () => {
const { jobCreator } = useContext(JobCreatorContext);
const kibanaContext = useKibanaContext();
const dateFormat: string = kibanaContext.kibanaConfig.get('dateFormat');
const { anomaly_detectors: anomalyDetectors } = newJobDefaults();
const { anomaly_detectors: anomalyDetectors } = getNewJobDefaults();
const isAdvanced = isAdvancedJobCreator(jobCreator);

View file

@ -22,7 +22,7 @@ import { Route } from '../../../../../common/types/kibana';
import { loadNewJobCapabilities } from '../../../../services/new_job_capabilities_service';
import { loadNewJobDefaults } from '../../utils/new_job_defaults';
import { loadMlServerInfo } from '../../../../services/ml_server_info';
import { mlJobService } from '../../../../services/job_service';
import { JOB_TYPE } from '../../common/job_creator/util/constants';
@ -58,7 +58,7 @@ routes.forEach((route: Route) => {
indexPattern: loadCurrentIndexPattern,
savedSearch: loadCurrentSavedSearch,
loadNewJobCapabilities,
loadNewJobDefaults,
loadMlServerInfo,
existingJobsAndGroups: mlJobService.getJobAndGroupIds,
jobType: () => route.id,
},

View file

@ -0,0 +1,21 @@
{
"defaults": {
"anomaly_detectors": {
"model_memory_limit": "128mb",
"categorization_examples_limit": 4,
"model_snapshot_retention_days": 1
},
"datafeeds": {
"scroll_size": 1000
}
},
"upgrade_mode": false,
"native_code": {
"version": "8.0.0-SNAPSHOT",
"build_hash": "4cde1d7c50fc28"
},
"limits": {
"max_model_memory_limit": "128mb"
},
"cloudId": "cloud_message_test:ZXUtd2VzdC0yLmF3cy5jbG91ZC5lcy5pbyQ4NWQ2NjZmMzM1MGM0NjllOGMzMjQyZDc2YTdmNDU5YyQxNmI1ZDM2ZGE1Mzk0YjlkYjIyZWJlNDk1OWY1OGQzMg=="
}

View file

@ -1,30 +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.
*/
export function cloudServiceProvider(config) {
function isRunningOnCloud() {
try {
return config.get('cloud.enabled');
} catch (error) {
return false;
}
}
function getCloudId() {
try {
return config.get('cloud.id');
} catch (error) {
return undefined;
}
}
return {
isRunningOnCloud,
getCloudId
};
}

View file

@ -9,7 +9,7 @@ import { AggFieldNamePair } from '../../../common/types/fields';
import { ExistingJobsAndGroups } from '../job_service';
import { PrivilegesResponse } from '../../../common/types/privileges';
import { MlSummaryJobs } from '../../../common/types/jobs';
import { MlServerDefaults, MlServerLimits } from '../../jobs/new_job_new/utils/new_job_defaults';
import { MlServerDefaults, MlServerLimits } from '../../services/ml_server_info';
import { ES_AGGREGATION } from '../../../common/constants/aggregation_types';
import { DataFrameAnalyticsStats } from '../../data_frame_analytics/pages/analytics_management/components/analytics_list/common';

View file

@ -0,0 +1,62 @@
/*
* 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 {
loadMlServerInfo,
getCloudDeploymentId,
isCloud,
getNewJobDefaults,
getNewJobLimits,
} from './ml_server_info';
import mockMlInfoResponse from './__mocks__/ml_info_response.json';
jest.mock('./ml_api_service', () => ({
ml: {
mlInfo: jest.fn(() => Promise.resolve(mockMlInfoResponse)),
},
}));
describe('ml_server_info initial state', () => {
it('server info not loaded ', () => {
expect(isCloud()).toBe(false);
expect(getCloudDeploymentId()).toBe(null);
});
});
describe('ml_server_info', () => {
beforeEach(async done => {
await loadMlServerInfo();
done();
});
describe('cloud information', () => {
it('can get could deployment id', () => {
expect(isCloud()).toBe(true);
expect(getCloudDeploymentId()).toBe('85d666f3350c469e8c3242d76a7f459c');
});
});
describe('defaults', () => {
it('can get defaults', async done => {
const defaults = getNewJobDefaults();
expect(defaults.anomaly_detectors.model_memory_limit).toBe('128mb');
expect(defaults.anomaly_detectors.categorization_examples_limit).toBe(4);
expect(defaults.anomaly_detectors.model_snapshot_retention_days).toBe(1);
expect(defaults.datafeeds.scroll_size).toBe(1000);
done();
});
});
describe('limits', () => {
it('can get limits', async done => {
const limits = getNewJobLimits();
expect(limits.max_model_memory_limit).toBe('128mb');
done();
});
});
});

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { ml } from '../../../services/ml_api_service';
import { ml } from './ml_api_service';
export interface MlServerDefaults {
anomaly_detectors: {
@ -35,7 +35,7 @@ const cloudInfo: CloudInfo = {
isCloud: false,
};
export async function loadNewJobDefaults() {
export async function loadMlServerInfo() {
try {
const resp = await ml.mlInfo();
defaults = resp.defaults;
@ -48,15 +48,15 @@ export async function loadNewJobDefaults() {
}
}
export function newJobDefaults(): MlServerDefaults {
export function getNewJobDefaults(): MlServerDefaults {
return defaults;
}
export function newJobLimits(): MlServerLimits {
export function getNewJobLimits(): MlServerLimits {
return limits;
}
export function cloudId(): string | null {
export function getCloudId(): string | null {
return cloudInfo.cloudId;
}
@ -64,7 +64,7 @@ export function isCloud(): boolean {
return cloudInfo.isCloud;
}
export function cloudDeploymentId(): string | null {
export function getCloudDeploymentId(): string | null {
if (cloudInfo.cloudId === null) {
return null;
}