-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ML] Adding cloud specific ML node warning #50139
Changes from 12 commits
554fef7
b47f616
550d2a2
3b71612
451edf6
1d37b4c
d0d5f91
7172372
47f5fb8
7555757
d55e11d
12f27a5
5087302
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* 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 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'; | ||
|
||
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> | ||
); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,20 +19,32 @@ export interface MlServerLimits { | |
max_model_memory_limit?: string; | ||
} | ||
|
||
export interface CloudInfo { | ||
cloudId: string | null; | ||
isCloud: boolean; | ||
} | ||
|
||
let defaults: MlServerDefaults = { | ||
anomaly_detectors: {}, | ||
datafeeds: {}, | ||
}; | ||
let limits: MlServerLimits = {}; | ||
|
||
const cloudInfo: CloudInfo = { | ||
cloudId: null, | ||
isCloud: false, | ||
}; | ||
|
||
export async function loadNewJobDefaults() { | ||
try { | ||
const resp = await ml.mlInfo(); | ||
defaults = resp.defaults; | ||
limits = resp.limits; | ||
return { defaults, limits }; | ||
cloudInfo.cloudId = resp.cloudId || null; | ||
cloudInfo.isCloud = resp.cloudId !== undefined; | ||
return { defaults, limits, cloudId: cloudInfo }; | ||
} catch (error) { | ||
return { defaults, limits }; | ||
return { defaults, limits, cloudId: cloudInfo }; | ||
} | ||
} | ||
|
||
|
@@ -43,3 +55,24 @@ export function newJobDefaults(): MlServerDefaults { | |
export function newJobLimits(): MlServerLimits { | ||
return limits; | ||
} | ||
|
||
export function cloudId(): string | null { | ||
return cloudInfo.cloudId; | ||
} | ||
|
||
export function isCloud(): boolean { | ||
return cloudInfo.isCloud; | ||
} | ||
|
||
export function cloudDeploymentId(): string | null { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: |
||
if (cloudInfo.cloudId === null) { | ||
return null; | ||
} | ||
const tempCloudId = cloudInfo.cloudId.replace(/^.+:/, ''); | ||
try { | ||
const matches = atob(tempCloudId).match(/^.+\$(.+)(?=\$)/); | ||
return matches !== null && matches.length === 2 ? matches[1] : null; | ||
} catch (error) { | ||
return null; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ import { isSecurityDisabled } from '../lib/security_utils'; | |
export function systemRoutes({ | ||
commonRouteConfig, | ||
elasticsearchPlugin, | ||
config, | ||
route, | ||
xpackMainPlugin, | ||
spacesPlugin | ||
|
@@ -168,10 +169,17 @@ export function systemRoutes({ | |
route({ | ||
method: 'GET', | ||
path: '/api/ml/info', | ||
handler(request) { | ||
async handler(request) { | ||
const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); | ||
return callWithRequest('ml.info') | ||
.catch(resp => wrapError(resp)); | ||
|
||
try { | ||
const info = await callWithRequest('ml.info'); | ||
const cloudIdKey = 'xpack.cloud.id'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: would be convenient to have a dictionary for such constants |
||
const cloudId = config.has(cloudIdKey) && config.get(cloudIdKey); | ||
return { ...info, cloudId }; | ||
} catch (error) { | ||
return wrapError(error); | ||
} | ||
}, | ||
config: { | ||
...commonRouteConfig | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: else is redundant