Skip to content

Commit

Permalink
[Inventory][ECO] Enable elastic entity model from inventory (elastic#…
Browse files Browse the repository at this point in the history
  • Loading branch information
kpatticha committed Sep 23, 2024
1 parent 636baad commit b5a061e
Show file tree
Hide file tree
Showing 10 changed files with 403 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import { coreMock } from '@kbn/core/public/mocks';
import { EntityManagerPublicPluginStart } from '@kbn/entityManager-plugin/public';
import type { ObservabilitySharedPluginStart } from '@kbn/observability-shared-plugin/public';
import type { InferencePublicStart } from '@kbn/inference-plugin/public';
import type { SharePluginStart } from '@kbn/share-plugin/public';
Expand All @@ -17,6 +18,7 @@ export function getMockInventoryContext(): InventoryKibanaContext {

return {
...coreStart,
entityManager: {} as unknown as EntityManagerPublicPluginStart,
observabilityShared: {} as unknown as ObservabilitySharedPluginStart,
inference: {} as unknown as InferencePublicStart,
share: {} as unknown as SharePluginStart,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useState } from 'react';
import { EntityManagerUnauthorizedError } from '@kbn/entityManager-plugin/public';
import type { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public';
import { useKibana } from '../../hooks/use_kibana';
import { Unauthorized } from './unauthorized_modal';

export function EnableEntityModelButton({ onSuccess }: { onSuccess: () => void }) {
const {
services: { entityManager, notifications },
} = useKibana();

const [isLoading, setIsLoading] = useState(false);
const [showModal, setModalVisible] = useState(false);

const handleEnablement = async () => {
setIsLoading(true);
try {
const response = await entityManager.entityClient.enableManagedEntityDiscovery();

if (response.success) {
setIsLoading(false);
onSuccess();
} else {
throw new Error(response.message);
}
} catch (error) {
setIsLoading(false);

if (error instanceof EntityManagerUnauthorizedError) {
setModalVisible(true);
return;
}

const err = error as Error | IHttpFetchError<ResponseErrorBody>;
notifications.toasts.addDanger({
title: i18n.translate('xpack.inventory.eemEnablement.errorTitle', {
defaultMessage: 'Error while enabling the new entity model',
}),
text: 'response' in err ? err.body?.message ?? err.response?.statusText : err.message,
});
}
};

return (
<>
<EuiButton
isLoading={isLoading}
data-test-subj="inventoryInventoryPageTemplateFilledButton"
fill
onClick={handleEnablement}
>
{i18n.translate('xpack.inventory.noData.card.button', {
defaultMessage: 'Enable',
})}
</EuiButton>
{showModal ? <Unauthorized onClose={() => setModalVisible(false)} /> : null}
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React from 'react';
import { i18n } from '@kbn/i18n';
import {
EuiButton,
EuiConfirmModal,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiImage,
EuiLink,
EuiPanel,
EuiSpacer,
EuiText,
EuiTitle,
useEuiTheme,
COLOR_MODES_STANDARD,
} from '@elastic/eui';
import inventoryLight from '../../assets/entities_inventory_light.png';
import inventoryDark from '../../assets/entities_inventory_dark.png';

export function Unauthorized({ onClose }: { onClose: () => void }) {
const { colorMode } = useEuiTheme();

return (
<EuiConfirmModal
style={{
width: '630px',
}}
onCancel={onClose}
onConfirm={onClose}
confirmButtonText={
<EuiButton data-test-subj="xpack.inventory.unauthorised.button" fill size="s">
{i18n.translate('xpack.inventory.unauthorised.button', {
defaultMessage: 'OK',
})}
</EuiButton>
}
cancelButtonText={
<EuiLink
target="_blank"
data-test-subj="inventoryUnauthorizedLinkExternal"
href="https://ela.st/docs-entity-inventory"
external
>
{i18n.translate('xpack.inventory.unauthorized.linkLabel', {
defaultMessage: 'Learn more',
})}
</EuiLink>
}
defaultFocusedButton="confirm"
>
<EuiPanel hasShadow={false}>
<EuiFlexGroup direction="column" justifyContent="center" alignItems="center" gutterSize="m">
<EuiFlexItem>
<EuiIcon type="lock" size="l" />
</EuiFlexItem>
<EuiFlexItem>
<EuiTitle>
<h2>
{i18n.translate('xpack.inventory.unauthorised.title', {
defaultMessage: 'Insufficient permissions',
})}
</h2>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>

<EuiPanel hasShadow={false} paddingSize="s">
<EuiText grow={false} textAlign="center">
<p>
{i18n.translate('xpack.inventory.unauthorised.body', {
defaultMessage:
"You don't have permissions to turn on the Elastic Entity Model. Please ask your administrator to enable this for you so you can see everything you have in one place.",
})}
</p>
</EuiText>
</EuiPanel>
<EuiSpacer size="m" />
<EuiPanel hasBorder paddingSize="none">
<EuiImage
allowFullScreen
size="xl"
src={colorMode === COLOR_MODES_STANDARD.dark ? inventoryDark : inventoryLight}
alt={i18n.translate('xpack.inventory.unauthorised.image.at,', {
defaultMessage:
'Image of the new experience of the entities inventory, showing services, hosts and containers',
})}
/>
</EuiPanel>
</EuiConfirmModal>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React from 'react';
import { i18n } from '@kbn/i18n';
import {
EuiButton,
EuiConfirmModal,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiImage,
EuiLink,
EuiPanel,
EuiSpacer,
EuiText,
EuiTitle,
useEuiTheme,
COLOR_MODES_STANDARD,
} from '@elastic/eui';
import inventoryLight from '../../assets/entities_inventory_light.png';
import inventoryDark from '../../assets/entities_inventory_dark.png';

export function Welcome({ onClose, onConfirm }: { onClose: () => void; onConfirm: () => void }) {
const { colorMode } = useEuiTheme();

return (
<EuiConfirmModal
style={{
width: '630px',
}}
onCancel={onClose}
onConfirm={onConfirm}
confirmButtonText={
<EuiButton data-test-subj="xpack.inventory.welcome.button.open" fill size="s">
{i18n.translate('xpack.inventory.welcome.button', {
defaultMessage: 'OK',
})}
</EuiButton>
}
cancelButtonText={
<EuiLink
target="_blank"
data-test-subj="inventoryWelcomeLinkExternal"
href="https://ela.st/docs-entity-inventory"
external
>
{i18n.translate('xpack.inventory.welcome.linkLabel', {
defaultMessage: 'Learn more',
})}
</EuiLink>
}
defaultFocusedButton="confirm"
>
<EuiPanel hasShadow={false}>
<EuiFlexGroup direction="column" justifyContent="center" alignItems="center" gutterSize="m">
<EuiFlexItem>
<EuiIcon type="logoElastic" size="l" />
</EuiFlexItem>
<EuiFlexItem>
<EuiTitle>
<h2>
{i18n.translate('xpack.inventory.welcome.title', {
defaultMessage: 'See everything you have in one place!',
})}
</h2>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>

<EuiPanel hasShadow={false} paddingSize="s">
<EuiText grow={false} textAlign="center">
<p>
{i18n.translate('xpack.inventory.welcome.body', {
defaultMessage:
'The inventory will show all of your observed entities in one place so you can detect and resolve problems with them faster.',
})}
</p>
</EuiText>
</EuiPanel>
<EuiSpacer size="m" />
<EuiPanel hasBorder paddingSize="none">
<EuiImage
size="xl"
src={colorMode === COLOR_MODES_STANDARD.dark ? inventoryDark : inventoryLight}
allowFullScreen
alt={i18n.translate('xpack.inventory.welcome.image.alt', {
defaultMessage:
'Image of the new experience of the entities inventory, showing services, hosts and containers',
})}
/>
</EuiPanel>
</EuiConfirmModal>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,46 @@
import { i18n } from '@kbn/i18n';
import React from 'react';
import { useKibana } from '../../hooks/use_kibana';
import { getEntityManagerEnablement } from './no_data_config';
import { useEntityManager } from '../../hooks/use_entity_manager';
import { Welcome } from '../entity_enablement/welcome_modal';

export function InventoryPageTemplate({ children }: { children: React.ReactNode }) {
const {
services: { observabilityShared },
} = useKibana();

const { PageTemplate: ObservabilityPageTemplate } = observabilityShared.navigation;
const {
isEntityManagerEnabled,
isEnablementLoading,
refresh,
showWelcomedModal,
toggleWelcomedModal,
} = useEntityManager();

const handleSuccess = () => {
refresh();
toggleWelcomedModal();
};

return (
<ObservabilityPageTemplate
noDataConfig={getEntityManagerEnablement({
enabled: isEntityManagerEnabled,
loading: isEnablementLoading,
onSuccess: handleSuccess,
})}
pageHeader={{
pageTitle: i18n.translate('xpack.inventory.inventoryPageHeaderLabel', {
defaultMessage: 'Inventory',
}),
}}
>
{children}
{showWelcomedModal ? (
<Welcome onClose={toggleWelcomedModal} onConfirm={toggleWelcomedModal} />
) : null}
</ObservabilityPageTemplate>
);
}
Loading

0 comments on commit b5a061e

Please sign in to comment.