From 64e87cd6b5300ad229ce640ddc754decf3b9eb83 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 29 Jun 2020 15:36:59 +0200 Subject: [PATCH] [Uptime] Use ML Capabilities API to determine license type (#66921) Co-authored-by: Elastic Machine --- .../__snapshots__/license_info.test.tsx.snap | 44 ++++++++------- .../__snapshots__/ml_flyout.test.tsx.snap | 29 +++++----- .../ml/__tests__/license_info.test.tsx | 8 +++ .../monitor/ml/__tests__/ml_flyout.test.tsx | 51 +++++------------- .../components/monitor/ml/license_info.tsx | 54 ++++++++++++++++--- .../components/monitor/ml/ml_flyout.tsx | 12 +++-- .../components/monitor/ml/ml_integeration.tsx | 4 +- .../monitor_duration_container.tsx | 4 +- .../contexts/uptime_settings_context.tsx | 20 +------ .../uptime/public/state/selectors/index.ts | 2 +- 10 files changed, 122 insertions(+), 106 deletions(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap index 2ba4eda82a391c..09c58b6336871c 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap @@ -26,22 +26,24 @@ Array [

In order to access duration anomaly detection, you have to be subscribed to an Elastic Platinum license.

- - + - Start free 14-day trial + + Start free 14-day trial + - - + + ,
In order to access duration anomaly detection, you have to be subscribed to an Elastic Platinum license.

- - Start free 14-day trial - + + Start free 14-day trial + + diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap index 7a61eb7391a10f..5c7215edcbce74 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap @@ -17,7 +17,6 @@ exports[`ML Flyout component renders without errors 1`] = ` /> -

Here you can create a machine learning job to calculate anomaly scores on @@ -67,7 +66,7 @@ exports[`ML Flyout component renders without errors 1`] = ` > In order to access duration anomaly detection, you have to be subscribed to an Elastic Platinum license.

- - + - Start free 14-day trial + + Start free 14-day trial + - - + +
{ + beforeEach(() => { + const spy = jest.spyOn(redux, 'useDispatch'); + spy.mockReturnValue(jest.fn()); + + const spy1 = jest.spyOn(redux, 'useSelector'); + spy1.mockReturnValue(true); + }); it('shallow renders without errors', () => { const wrapper = shallowWithIntl(); expect(wrapper).toMatchSnapshot(); diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/ml_flyout.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/ml_flyout.test.tsx index 31cdcfac9feef3..4795042ed845fd 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/ml_flyout.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/ml_flyout.test.tsx @@ -9,47 +9,21 @@ import { renderWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; import { MLFlyoutView } from '../ml_flyout'; import { UptimeSettingsContext } from '../../../../contexts'; import { CLIENT_DEFAULTS } from '../../../../../common/constants'; -import { License } from '../../../../../../../plugins/licensing/common/license'; - -const expiredLicense = new License({ - signature: 'test signature', - license: { - expiryDateInMillis: 0, - mode: 'platinum', - status: 'expired', - type: 'platinum', - uid: '1', - }, - features: { - ml: { - isAvailable: false, - isEnabled: false, - }, - }, -}); - -const validLicense = new License({ - signature: 'test signature', - license: { - expiryDateInMillis: 30000, - mode: 'platinum', - status: 'active', - type: 'platinum', - uid: '2', - }, - features: { - ml: { - isAvailable: true, - isEnabled: true, - }, - }, -}); +import * as redux from 'react-redux'; describe('ML Flyout component', () => { const createJob = () => {}; const onClose = () => {}; const { DATE_RANGE_START, DATE_RANGE_END } = CLIENT_DEFAULTS; + beforeEach(() => { + const spy = jest.spyOn(redux, 'useDispatch'); + spy.mockReturnValue(jest.fn()); + + const spy1 = jest.spyOn(redux, 'useSelector'); + spy1.mockReturnValue(true); + }); + it('renders without errors', () => { const wrapper = shallowWithIntl( { expect(wrapper).toMatchSnapshot(); }); it('shows license info if no ml available', () => { + const spy1 = jest.spyOn(redux, 'useSelector'); + + // return false value for no license + spy1.mockReturnValue(false); + const value = { - license: expiredLicense, basePath: '', dateRangeStart: DATE_RANGE_START, dateRangeEnd: DATE_RANGE_END, @@ -88,7 +66,6 @@ describe('ML Flyout component', () => { it('able to create job if valid license is available', () => { const value = { - license: validLicense, basePath: '', dateRangeStart: DATE_RANGE_START, dateRangeEnd: DATE_RANGE_END, diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/license_info.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/license_info.tsx index e37ec4cc4715d4..2461875d502b77 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/license_info.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ml/license_info.tsx @@ -3,13 +3,48 @@ * 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, { useContext } from 'react'; +import React, { useContext, useState, useEffect } from 'react'; import { EuiCallOut, EuiButton, EuiSpacer } from '@elastic/eui'; +import { useDispatch, useSelector } from 'react-redux'; import { UptimeSettingsContext } from '../../../contexts'; import * as labels from './translations'; +import { getMLCapabilitiesAction } from '../../../state/actions'; +import { hasMLFeatureSelector } from '../../../state/selectors'; export const ShowLicenseInfo = () => { const { basePath } = useContext(UptimeSettingsContext); + const [loading, setLoading] = useState(false); + const hasMlFeature = useSelector(hasMLFeatureSelector); + + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(getMLCapabilitiesAction.get()); + }, [dispatch]); + + useEffect(() => { + let retryInterval: any; + if (loading) { + retryInterval = setInterval(() => { + dispatch(getMLCapabilitiesAction.get()); + }, 5000); + } else { + clearInterval(retryInterval); + } + + return () => { + clearInterval(retryInterval); + }; + }, [dispatch, loading]); + + useEffect(() => { + setLoading(false); + }, [hasMlFeature]); + + const startLicenseTrial = () => { + setLoading(true); + }; + return ( <> { iconType="help" >

{labels.START_TRAIL_DESC}

- - {labels.START_TRAIL} - + {}}> + + {labels.START_TRAIL} + +
diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx index 8c3f814e841f7a..3e60f09452587a 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx @@ -20,9 +20,11 @@ import { EuiTitle, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { useSelector } from 'react-redux'; import * as labels from './translations'; import { UptimeSettingsContext } from '../../../contexts'; import { ShowLicenseInfo } from './license_info'; +import { hasMLFeatureSelector } from '../../../state/selectors'; interface Props { isCreatingJob: boolean; @@ -32,11 +34,11 @@ interface Props { } export function MLFlyoutView({ isCreatingJob, onClickCreate, onClose, canCreateMLJob }: Props) { - const { basePath, license } = useContext(UptimeSettingsContext); + const { basePath } = useContext(UptimeSettingsContext); - const isLoadingMLJob = false; + const hasMlFeature = useSelector(hasMLFeatureSelector); - const hasPlatinumLicense = license?.getFeature('ml')?.isAvailable; + const isLoadingMLJob = false; return ( @@ -47,7 +49,7 @@ export function MLFlyoutView({ isCreatingJob, onClickCreate, onClose, canCreateM - {!hasPlatinumLicense && } + {!hasMlFeature && }

{labels.CREAT_ML_JOB_DESC}

@@ -80,7 +82,7 @@ export function MLFlyoutView({ isCreatingJob, onClickCreate, onClose, canCreateM onClick={() => onClickCreate()} fill isLoading={isCreatingJob} - disabled={isCreatingJob || isLoadingMLJob || !hasPlatinumLicense || !canCreateMLJob} + disabled={isCreatingJob || isLoadingMLJob || !hasMlFeature || !canCreateMLJob} > {labels.CREATE_NEW_JOB} diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/ml_integeration.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/ml_integeration.tsx index e66808f76d24a2..1de19dda3b88f4 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/ml_integeration.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ml/ml_integeration.tsx @@ -8,7 +8,7 @@ import React, { useContext, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { MachineLearningFlyout } from './ml_flyout_container'; import { - hasMLFeatureAvailable, + hasMLFeatureSelector, hasMLJobSelector, isMLJobDeletedSelector, isMLJobDeletingSelector, @@ -35,7 +35,7 @@ export const MLIntegrationComponent = () => { const dispatch = useDispatch(); - const isMLAvailable = useSelector(hasMLFeatureAvailable); + const isMLAvailable = useSelector(hasMLFeatureSelector); const deleteMLJob = () => dispatch(deleteMLJobAction.get({ monitorId: monitorId as string })); const isMLJobDeleting = useSelector(isMLJobDeletingSelector); diff --git a/x-pack/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx b/x-pack/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx index b586c1241290bc..df8ceed76b7968 100644 --- a/x-pack/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx @@ -14,7 +14,7 @@ import { } from '../../../state/actions'; import { anomaliesSelector, - hasMLFeatureAvailable, + hasMLFeatureSelector, hasMLJobSelector, selectDurationLines, } from '../../../state/selectors'; @@ -34,7 +34,7 @@ export const MonitorDuration: React.FC = ({ monitorId }) => { const { durationLines, loading } = useSelector(selectDurationLines); - const isMLAvailable = useSelector(hasMLFeatureAvailable); + const isMLAvailable = useSelector(hasMLFeatureSelector); const { data: mlJobs, loading: jobsLoading } = useSelector(hasMLJobSelector); diff --git a/x-pack/plugins/uptime/public/contexts/uptime_settings_context.tsx b/x-pack/plugins/uptime/public/contexts/uptime_settings_context.tsx index 4fabf3f2ed4972..142c6e17c5fd90 100644 --- a/x-pack/plugins/uptime/public/contexts/uptime_settings_context.tsx +++ b/x-pack/plugins/uptime/public/contexts/uptime_settings_context.tsx @@ -9,11 +9,9 @@ import { UptimeAppProps } from '../uptime_app'; import { CLIENT_DEFAULTS, CONTEXT_DEFAULTS } from '../../common/constants'; import { CommonlyUsedRange } from '../components/common/uptime_date_picker'; import { useGetUrlParams } from '../hooks'; -import { ILicense } from '../../../../plugins/licensing/common/types'; export interface UptimeSettingsContextValues { basePath: string; - license?: ILicense | null; dateRangeStart: string; dateRangeEnd: string; isApmAvailable: boolean; @@ -41,27 +39,12 @@ const defaultContext: UptimeSettingsContextValues = { export const UptimeSettingsContext = createContext(defaultContext); export const UptimeSettingsContextProvider: React.FC = ({ children, ...props }) => { - const { - basePath, - isApmAvailable, - isInfraAvailable, - isLogsAvailable, - commonlyUsedRanges, - plugins, - } = props; + const { basePath, isApmAvailable, isInfraAvailable, isLogsAvailable, commonlyUsedRanges } = props; const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); - let license: ILicense | null = null; - - // @ts-ignore - plugins.licensing.license$.subscribe((licenseItem: ILicense) => { - license = licenseItem; - }); - const value = useMemo(() => { return { - license, basePath, isApmAvailable, isInfraAvailable, @@ -71,7 +54,6 @@ export const UptimeSettingsContextProvider: React.FC = ({ childr dateRangeEnd: dateRangeEnd ?? DATE_RANGE_END, }; }, [ - license, basePath, isApmAvailable, isInfraAvailable, diff --git a/x-pack/plugins/uptime/public/state/selectors/index.ts b/x-pack/plugins/uptime/public/state/selectors/index.ts index d08db2ccf5f2d2..4c2b671203f0ad 100644 --- a/x-pack/plugins/uptime/public/state/selectors/index.ts +++ b/x-pack/plugins/uptime/public/state/selectors/index.ts @@ -36,7 +36,7 @@ export const snapshotDataSelector = ({ snapshot }: AppState) => snapshot; const mlCapabilitiesSelector = (state: AppState) => state.ml.mlCapabilities.data; -export const hasMLFeatureAvailable = createSelector( +export const hasMLFeatureSelector = createSelector( mlCapabilitiesSelector, (mlCapabilities) => mlCapabilities?.isPlatinumOrTrialLicense && mlCapabilities?.mlFeatureEnabledInSpace