Skip to content

Commit 64e87cd

Browse files
[Uptime] Use ML Capabilities API to determine license type (#66921)
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent e91594a commit 64e87cd

File tree

10 files changed

+122
-106
lines changed

10 files changed

+122
-106
lines changed

x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap

Lines changed: 26 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap

Lines changed: 15 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/plugins/uptime/public/components/monitor/ml/__tests__/license_info.test.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,16 @@
77
import React from 'react';
88
import { renderWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
99
import { ShowLicenseInfo } from '../license_info';
10+
import * as redux from 'react-redux';
1011

1112
describe('ShowLicenseInfo', () => {
13+
beforeEach(() => {
14+
const spy = jest.spyOn(redux, 'useDispatch');
15+
spy.mockReturnValue(jest.fn());
16+
17+
const spy1 = jest.spyOn(redux, 'useSelector');
18+
spy1.mockReturnValue(true);
19+
});
1220
it('shallow renders without errors', () => {
1321
const wrapper = shallowWithIntl(<ShowLicenseInfo />);
1422
expect(wrapper).toMatchSnapshot();

x-pack/plugins/uptime/public/components/monitor/ml/__tests__/ml_flyout.test.tsx

Lines changed: 14 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,47 +9,21 @@ import { renderWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
99
import { MLFlyoutView } from '../ml_flyout';
1010
import { UptimeSettingsContext } from '../../../../contexts';
1111
import { CLIENT_DEFAULTS } from '../../../../../common/constants';
12-
import { License } from '../../../../../../../plugins/licensing/common/license';
13-
14-
const expiredLicense = new License({
15-
signature: 'test signature',
16-
license: {
17-
expiryDateInMillis: 0,
18-
mode: 'platinum',
19-
status: 'expired',
20-
type: 'platinum',
21-
uid: '1',
22-
},
23-
features: {
24-
ml: {
25-
isAvailable: false,
26-
isEnabled: false,
27-
},
28-
},
29-
});
30-
31-
const validLicense = new License({
32-
signature: 'test signature',
33-
license: {
34-
expiryDateInMillis: 30000,
35-
mode: 'platinum',
36-
status: 'active',
37-
type: 'platinum',
38-
uid: '2',
39-
},
40-
features: {
41-
ml: {
42-
isAvailable: true,
43-
isEnabled: true,
44-
},
45-
},
46-
});
12+
import * as redux from 'react-redux';
4713

4814
describe('ML Flyout component', () => {
4915
const createJob = () => {};
5016
const onClose = () => {};
5117
const { DATE_RANGE_START, DATE_RANGE_END } = CLIENT_DEFAULTS;
5218

19+
beforeEach(() => {
20+
const spy = jest.spyOn(redux, 'useDispatch');
21+
spy.mockReturnValue(jest.fn());
22+
23+
const spy1 = jest.spyOn(redux, 'useSelector');
24+
spy1.mockReturnValue(true);
25+
});
26+
5327
it('renders without errors', () => {
5428
const wrapper = shallowWithIntl(
5529
<MLFlyoutView
@@ -62,8 +36,12 @@ describe('ML Flyout component', () => {
6236
expect(wrapper).toMatchSnapshot();
6337
});
6438
it('shows license info if no ml available', () => {
39+
const spy1 = jest.spyOn(redux, 'useSelector');
40+
41+
// return false value for no license
42+
spy1.mockReturnValue(false);
43+
6544
const value = {
66-
license: expiredLicense,
6745
basePath: '',
6846
dateRangeStart: DATE_RANGE_START,
6947
dateRangeEnd: DATE_RANGE_END,
@@ -88,7 +66,6 @@ describe('ML Flyout component', () => {
8866

8967
it('able to create job if valid license is available', () => {
9068
const value = {
91-
license: validLicense,
9269
basePath: '',
9370
dateRangeStart: DATE_RANGE_START,
9471
dateRangeEnd: DATE_RANGE_END,

x-pack/plugins/uptime/public/components/monitor/ml/license_info.tsx

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,48 @@
33
* or more contributor license agreements. Licensed under the Elastic License;
44
* you may not use this file except in compliance with the Elastic License.
55
*/
6-
import React, { useContext } from 'react';
6+
import React, { useContext, useState, useEffect } from 'react';
77
import { EuiCallOut, EuiButton, EuiSpacer } from '@elastic/eui';
8+
import { useDispatch, useSelector } from 'react-redux';
89
import { UptimeSettingsContext } from '../../../contexts';
910
import * as labels from './translations';
11+
import { getMLCapabilitiesAction } from '../../../state/actions';
12+
import { hasMLFeatureSelector } from '../../../state/selectors';
1013

1114
export const ShowLicenseInfo = () => {
1215
const { basePath } = useContext(UptimeSettingsContext);
16+
const [loading, setLoading] = useState<boolean>(false);
17+
const hasMlFeature = useSelector(hasMLFeatureSelector);
18+
19+
const dispatch = useDispatch();
20+
21+
useEffect(() => {
22+
dispatch(getMLCapabilitiesAction.get());
23+
}, [dispatch]);
24+
25+
useEffect(() => {
26+
let retryInterval: any;
27+
if (loading) {
28+
retryInterval = setInterval(() => {
29+
dispatch(getMLCapabilitiesAction.get());
30+
}, 5000);
31+
} else {
32+
clearInterval(retryInterval);
33+
}
34+
35+
return () => {
36+
clearInterval(retryInterval);
37+
};
38+
}, [dispatch, loading]);
39+
40+
useEffect(() => {
41+
setLoading(false);
42+
}, [hasMlFeature]);
43+
44+
const startLicenseTrial = () => {
45+
setLoading(true);
46+
};
47+
1348
return (
1449
<>
1550
<EuiCallOut
@@ -20,13 +55,16 @@ export const ShowLicenseInfo = () => {
2055
iconType="help"
2156
>
2257
<p>{labels.START_TRAIL_DESC}</p>
23-
<EuiButton
24-
color="primary"
25-
href={basePath + `/app/management/stack/license_management/home`}
26-
target="_blank"
27-
>
28-
{labels.START_TRAIL}
29-
</EuiButton>
58+
<span onClick={startLicenseTrial} onKeyDown={() => {}}>
59+
<EuiButton
60+
color="primary"
61+
isLoading={loading}
62+
target="_blank"
63+
href={basePath + `/app/management/stack/license_management/home`}
64+
>
65+
{labels.START_TRAIL}
66+
</EuiButton>
67+
</span>
3068
</EuiCallOut>
3169
<EuiSpacer />
3270
</>

x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ import {
2020
EuiTitle,
2121
} from '@elastic/eui';
2222
import { FormattedMessage } from '@kbn/i18n/react';
23+
import { useSelector } from 'react-redux';
2324
import * as labels from './translations';
2425
import { UptimeSettingsContext } from '../../../contexts';
2526
import { ShowLicenseInfo } from './license_info';
27+
import { hasMLFeatureSelector } from '../../../state/selectors';
2628

2729
interface Props {
2830
isCreatingJob: boolean;
@@ -32,11 +34,11 @@ interface Props {
3234
}
3335

3436
export function MLFlyoutView({ isCreatingJob, onClickCreate, onClose, canCreateMLJob }: Props) {
35-
const { basePath, license } = useContext(UptimeSettingsContext);
37+
const { basePath } = useContext(UptimeSettingsContext);
3638

37-
const isLoadingMLJob = false;
39+
const hasMlFeature = useSelector(hasMLFeatureSelector);
3840

39-
const hasPlatinumLicense = license?.getFeature('ml')?.isAvailable;
41+
const isLoadingMLJob = false;
4042

4143
return (
4244
<EuiFlyout onClose={onClose} size="s" data-test-subj="uptimeMLFlyout">
@@ -47,7 +49,7 @@ export function MLFlyoutView({ isCreatingJob, onClickCreate, onClose, canCreateM
4749
<EuiSpacer size="s" />
4850
</EuiFlyoutHeader>
4951
<EuiFlyoutBody>
50-
{!hasPlatinumLicense && <ShowLicenseInfo />}
52+
{!hasMlFeature && <ShowLicenseInfo />}
5153
<EuiText>
5254
<p>{labels.CREAT_ML_JOB_DESC}</p>
5355
<p>
@@ -80,7 +82,7 @@ export function MLFlyoutView({ isCreatingJob, onClickCreate, onClose, canCreateM
8082
onClick={() => onClickCreate()}
8183
fill
8284
isLoading={isCreatingJob}
83-
disabled={isCreatingJob || isLoadingMLJob || !hasPlatinumLicense || !canCreateMLJob}
85+
disabled={isCreatingJob || isLoadingMLJob || !hasMlFeature || !canCreateMLJob}
8486
>
8587
{labels.CREATE_NEW_JOB}
8688
</EuiButton>

x-pack/plugins/uptime/public/components/monitor/ml/ml_integeration.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import React, { useContext, useEffect, useState } from 'react';
88
import { useDispatch, useSelector } from 'react-redux';
99
import { MachineLearningFlyout } from './ml_flyout_container';
1010
import {
11-
hasMLFeatureAvailable,
11+
hasMLFeatureSelector,
1212
hasMLJobSelector,
1313
isMLJobDeletedSelector,
1414
isMLJobDeletingSelector,
@@ -35,7 +35,7 @@ export const MLIntegrationComponent = () => {
3535

3636
const dispatch = useDispatch();
3737

38-
const isMLAvailable = useSelector(hasMLFeatureAvailable);
38+
const isMLAvailable = useSelector(hasMLFeatureSelector);
3939

4040
const deleteMLJob = () => dispatch(deleteMLJobAction.get({ monitorId: monitorId as string }));
4141
const isMLJobDeleting = useSelector(isMLJobDeletingSelector);

x-pack/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
} from '../../../state/actions';
1515
import {
1616
anomaliesSelector,
17-
hasMLFeatureAvailable,
17+
hasMLFeatureSelector,
1818
hasMLJobSelector,
1919
selectDurationLines,
2020
} from '../../../state/selectors';
@@ -34,7 +34,7 @@ export const MonitorDuration: React.FC<MonitorIdParam> = ({ monitorId }) => {
3434

3535
const { durationLines, loading } = useSelector(selectDurationLines);
3636

37-
const isMLAvailable = useSelector(hasMLFeatureAvailable);
37+
const isMLAvailable = useSelector(hasMLFeatureSelector);
3838

3939
const { data: mlJobs, loading: jobsLoading } = useSelector(hasMLJobSelector);
4040

0 commit comments

Comments
 (0)