mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[8.4][Session View]Cloud section on Metadata Tab (#136168)
* added base functionality for Cloud section * added unit test for Cloud section on session details panel metadata tab * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
68e2ff6cbf
commit
735b69d1ac
7 changed files with 217 additions and 5 deletions
|
@ -151,6 +151,7 @@ export interface ProcessEvent {
|
|||
};
|
||||
container?: ProcessEventContainer;
|
||||
orchestrator?: ProcessEventOrchestrator;
|
||||
cloud?: ProcessEventCloud;
|
||||
}
|
||||
|
||||
export interface ProcessEventsPage {
|
||||
|
@ -218,3 +219,17 @@ export interface ProcessEventOrchestrator {
|
|||
type?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ProcessEventCloud {
|
||||
instance?: {
|
||||
name?: string;
|
||||
};
|
||||
account?: {
|
||||
id?: string;
|
||||
};
|
||||
project?: {
|
||||
id?: string;
|
||||
};
|
||||
provider?: string;
|
||||
region?: string;
|
||||
}
|
||||
|
|
|
@ -8,9 +8,10 @@ import {
|
|||
ProcessEventHost,
|
||||
ProcessEventContainer,
|
||||
ProcessEventOrchestrator,
|
||||
ProcessEventCloud,
|
||||
} from '../../../common/types/process_tree';
|
||||
import { DASH } from '../../constants';
|
||||
import { getHostData, getContainerData, getOrchestratorData } from './helpers';
|
||||
import { getHostData, getContainerData, getOrchestratorData, getCloudData } from './helpers';
|
||||
|
||||
const MOCK_HOST_DATA: ProcessEventHost = {
|
||||
architecture: 'x86_64',
|
||||
|
@ -57,6 +58,20 @@ const MOCK_ORCHESTRATOR_DATA: ProcessEventOrchestrator = {
|
|||
},
|
||||
};
|
||||
|
||||
const MOCK_CLOUD_DATA: ProcessEventCloud = {
|
||||
instance: {
|
||||
name: 'gke-cluster-1-paulo-default-pool-f0fea4ab-lhx2',
|
||||
},
|
||||
account: {
|
||||
id: 'PLACEHOLDER_FOR_CLOUD_ACCOUNT_ID',
|
||||
},
|
||||
project: {
|
||||
id: 'elastic-security-dev',
|
||||
},
|
||||
provider: 'gcp',
|
||||
region: 'us-central1-c',
|
||||
};
|
||||
|
||||
describe('detail panel host tab helpers tests', () => {
|
||||
it('getHostData returns fields with a dash with undefined host', () => {
|
||||
const result = getHostData(undefined);
|
||||
|
@ -178,4 +193,34 @@ describe('detail panel host tab helpers tests', () => {
|
|||
expect(result.cluster.id).toEqual(MOCK_ORCHESTRATOR_DATA?.cluster?.id);
|
||||
expect(result.parent.type).toEqual(MOCK_ORCHESTRATOR_DATA?.parent?.type);
|
||||
});
|
||||
|
||||
it('getCloudData returns dashes for missing fields', () => {
|
||||
const result = getCloudData({
|
||||
instance: {
|
||||
name: 'gke-cluster-1-paulo-default-pool-f0fea4ab-lhx2',
|
||||
},
|
||||
account: {
|
||||
id: undefined,
|
||||
},
|
||||
project: {
|
||||
id: 'elastic-security-dev',
|
||||
},
|
||||
provider: undefined,
|
||||
region: 'us-central1-c',
|
||||
});
|
||||
expect(result.instance.name).toEqual(MOCK_CLOUD_DATA?.instance?.name);
|
||||
expect(result.account.id).toEqual(DASH);
|
||||
expect(result.project.id).toEqual(MOCK_CLOUD_DATA?.project?.id);
|
||||
expect(result.provider).toEqual(DASH);
|
||||
expect(result.region).toEqual(MOCK_CLOUD_DATA?.region);
|
||||
});
|
||||
|
||||
it('getCloudData returns all data provided', () => {
|
||||
const result = getCloudData(MOCK_CLOUD_DATA);
|
||||
expect(result.instance.name).toEqual(MOCK_CLOUD_DATA?.instance?.name);
|
||||
expect(result.account.id).toEqual(MOCK_CLOUD_DATA?.account?.id);
|
||||
expect(result.project.id).toEqual(MOCK_CLOUD_DATA?.project?.id);
|
||||
expect(result.provider).toEqual(MOCK_CLOUD_DATA?.provider);
|
||||
expect(result.region).toEqual(MOCK_CLOUD_DATA?.region);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,9 +9,15 @@ import {
|
|||
ProcessEventHost,
|
||||
ProcessEventContainer,
|
||||
ProcessEventOrchestrator,
|
||||
ProcessEventCloud,
|
||||
} from '../../../common/types/process_tree';
|
||||
import { DASH } from '../../constants';
|
||||
import { DetailPanelHost, DetailPanelContainer, DetailPanelOrchestrator } from '../../types';
|
||||
import {
|
||||
DetailPanelHost,
|
||||
DetailPanelContainer,
|
||||
DetailPanelOrchestrator,
|
||||
DetailPanelCloud,
|
||||
} from '../../types';
|
||||
import { dataOrDash } from '../../utils/data_or_dash';
|
||||
|
||||
export const getHostData = (host: ProcessEventHost | undefined): DetailPanelHost => {
|
||||
|
@ -113,3 +119,31 @@ export const getOrchestratorData = (
|
|||
|
||||
return detailPanelOrchestrator;
|
||||
};
|
||||
|
||||
export const getCloudData = (cloud: ProcessEventCloud | undefined): DetailPanelCloud => {
|
||||
const detailPanelCloud: DetailPanelCloud = {
|
||||
instance: {
|
||||
name: DASH,
|
||||
},
|
||||
account: {
|
||||
id: DASH,
|
||||
},
|
||||
project: {
|
||||
id: DASH,
|
||||
},
|
||||
provider: DASH,
|
||||
region: DASH,
|
||||
};
|
||||
|
||||
if (!cloud) {
|
||||
return detailPanelCloud;
|
||||
}
|
||||
|
||||
detailPanelCloud.instance.name = dataOrDash(cloud?.instance?.name).toString();
|
||||
detailPanelCloud.account.id = dataOrDash(cloud?.account?.id).toString();
|
||||
detailPanelCloud.project.id = dataOrDash(cloud?.project?.id).toString();
|
||||
detailPanelCloud.provider = dataOrDash(cloud?.provider).toString();
|
||||
detailPanelCloud.region = dataOrDash(cloud?.region).toString();
|
||||
|
||||
return detailPanelCloud;
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
ProcessEventHost,
|
||||
ProcessEventContainer,
|
||||
ProcessEventOrchestrator,
|
||||
ProcessEventCloud,
|
||||
} from '../../../common/types/process_tree';
|
||||
import { DetailPanelMetadataTab } from '.';
|
||||
|
||||
|
@ -44,6 +45,13 @@ const TEST_ORCHESTRATOR_PARENT_TYPE = 'elastic-k8s-cluster';
|
|||
const TEST_ORCHESTRATOR_CLUSTER_ID = 'PLACEHOLDER_FOR_CLUSTER.ID';
|
||||
const TEST_ORCHESTRATOR_CLUSTER_NAME = 'PLACEHOLDER_FOR_PARENT.TYPE';
|
||||
|
||||
// Cloud data
|
||||
const TEST_CLOUD_INSTANCE_NAME = 'gke-cluster-1-paulo-default-pool-f0fea4ab-lhx2';
|
||||
const TEST_CLOUD_ACCOUNT_ID = 'PLACEHOLDER_FOR_CLOUD_ACCOUNT_ID';
|
||||
const TEST_CLOUD_PROJECT_ID = 'elastic-security-dev';
|
||||
const TEST_CLOUD_PROVIDER = 'gcp';
|
||||
const TEST_CLOUD_REGION = 'us-central1-c';
|
||||
|
||||
const TEST_HOST: ProcessEventHost = {
|
||||
architecture: TEST_ARCHITECTURE,
|
||||
hostname: TEST_HOSTNAME,
|
||||
|
@ -89,6 +97,20 @@ const TEST_ORCHESTRATOR: ProcessEventOrchestrator = {
|
|||
},
|
||||
};
|
||||
|
||||
const TEST_CLOUD: ProcessEventCloud = {
|
||||
instance: {
|
||||
name: TEST_CLOUD_INSTANCE_NAME,
|
||||
},
|
||||
account: {
|
||||
id: TEST_CLOUD_ACCOUNT_ID,
|
||||
},
|
||||
project: {
|
||||
id: TEST_CLOUD_PROJECT_ID,
|
||||
},
|
||||
provider: TEST_CLOUD_PROVIDER,
|
||||
region: TEST_CLOUD_REGION,
|
||||
};
|
||||
|
||||
describe('DetailPanelMetadataTab component', () => {
|
||||
let render: () => ReturnType<AppContextTestRender['render']>;
|
||||
let renderResult: ReturnType<typeof render>;
|
||||
|
@ -133,6 +155,7 @@ describe('DetailPanelMetadataTab component', () => {
|
|||
// Orchestrator and Container should be missing if session came from a Non-cloud env
|
||||
expect(renderResult.queryByText('Container')).toBeNull();
|
||||
expect(renderResult.queryByText('Orchestrator')).toBeNull();
|
||||
expect(renderResult.queryByText('Cloud')).toBeNull();
|
||||
});
|
||||
|
||||
it('renders DetailPanelMetadataTab correctly (cloud environment)', async () => {
|
||||
|
@ -141,6 +164,7 @@ describe('DetailPanelMetadataTab component', () => {
|
|||
processHost={TEST_HOST}
|
||||
processContainer={TEST_CONTAINER}
|
||||
processOrchestrator={TEST_ORCHESTRATOR}
|
||||
processCloud={TEST_CLOUD}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -201,6 +225,17 @@ describe('DetailPanelMetadataTab component', () => {
|
|||
expect(renderResult.queryByText(TEST_ORCHESTRATOR_PARENT_TYPE)).toBeVisible();
|
||||
expect(renderResult.queryByText(TEST_ORCHESTRATOR_CLUSTER_ID)).toBeVisible();
|
||||
expect(renderResult.queryByText(TEST_ORCHESTRATOR_CLUSTER_NAME)).toBeVisible();
|
||||
|
||||
// expand Cloud Accordion
|
||||
renderResult.queryByText('Cloud')?.click();
|
||||
expect(renderResult.queryByText('provider')).toBeVisible();
|
||||
expect(renderResult.queryByText('region')).toBeVisible();
|
||||
expect(renderResult.queryByText('account.id')).toBeVisible();
|
||||
expect(renderResult.queryByText('project.id')).toBeVisible();
|
||||
expect(renderResult.queryByText(TEST_CLOUD_PROVIDER)).toBeVisible();
|
||||
expect(renderResult.queryByText(TEST_CLOUD_REGION)).toBeVisible();
|
||||
expect(renderResult.queryByText(TEST_CLOUD_ACCOUNT_ID)).toBeVisible();
|
||||
expect(renderResult.queryByText(TEST_CLOUD_PROJECT_ID)).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,18 +11,20 @@ import {
|
|||
ProcessEventHost,
|
||||
ProcessEventContainer,
|
||||
ProcessEventOrchestrator,
|
||||
ProcessEventCloud,
|
||||
} from '../../../common/types/process_tree';
|
||||
import { DetailPanelAccordion } from '../detail_panel_accordion';
|
||||
import { DetailPanelCopy } from '../detail_panel_copy';
|
||||
import { DetailPanelListItem } from '../detail_panel_list_item';
|
||||
import { useStyles } from '../detail_panel_process_tab/styles';
|
||||
import { useStyles as useStylesChild } from './styles';
|
||||
import { getHostData, getContainerData, getOrchestratorData } from './helpers';
|
||||
import { getHostData, getContainerData, getOrchestratorData, getCloudData } from './helpers';
|
||||
|
||||
interface DetailPanelMetadataTabDeps {
|
||||
processHost?: ProcessEventHost;
|
||||
processContainer?: ProcessEventContainer;
|
||||
processOrchestrator?: ProcessEventOrchestrator;
|
||||
processCloud?: ProcessEventCloud;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,6 +34,7 @@ export const DetailPanelMetadataTab = ({
|
|||
processHost,
|
||||
processContainer,
|
||||
processOrchestrator,
|
||||
processCloud,
|
||||
}: DetailPanelMetadataTabDeps) => {
|
||||
const styles = useStyles();
|
||||
const stylesChild = useStylesChild();
|
||||
|
@ -41,6 +44,7 @@ export const DetailPanelMetadataTab = ({
|
|||
() => getOrchestratorData(processOrchestrator),
|
||||
[processOrchestrator]
|
||||
);
|
||||
const cloudData = useMemo(() => getCloudData(processCloud), [processCloud]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -120,8 +124,8 @@ export const DetailPanelMetadataTab = ({
|
|||
>
|
||||
<EuiPanel
|
||||
hasShadow={false}
|
||||
color="subdued"
|
||||
hasBorder={true}
|
||||
color="plain"
|
||||
hasBorder={false}
|
||||
borderRadius="m"
|
||||
paddingSize="none"
|
||||
css={stylesChild.metadataHostOS}
|
||||
|
@ -228,6 +232,70 @@ export const DetailPanelMetadataTab = ({
|
|||
</EuiPanel>
|
||||
</DetailPanelAccordion>
|
||||
|
||||
{processCloud && (
|
||||
<>
|
||||
<DetailPanelAccordion
|
||||
id="metadataCloud"
|
||||
title={i18n.translate('xpack.sessionView.metadataDetailsTab.cloud', {
|
||||
defaultMessage: 'Cloud',
|
||||
})}
|
||||
listItems={[
|
||||
{
|
||||
title: <DetailPanelListItem>provider</DetailPanelListItem>,
|
||||
description: (
|
||||
<DetailPanelCopy
|
||||
textToCopy={`cloud.provider: "${cloudData.provider}"`}
|
||||
tooltipContent={cloudData.provider}
|
||||
>
|
||||
<EuiTextColor color="subdued" css={styles.descriptionSemibold}>
|
||||
{cloudData.provider}
|
||||
</EuiTextColor>
|
||||
</DetailPanelCopy>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: <DetailPanelListItem>region</DetailPanelListItem>,
|
||||
description: (
|
||||
<DetailPanelCopy
|
||||
textToCopy={`cloud.region: "${cloudData.region}"`}
|
||||
tooltipContent={cloudData.region}
|
||||
>
|
||||
<EuiTextColor color="subdued" css={styles.descriptionSemibold}>
|
||||
{cloudData.region}
|
||||
</EuiTextColor>
|
||||
</DetailPanelCopy>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: <DetailPanelListItem>account.id</DetailPanelListItem>,
|
||||
description: (
|
||||
<DetailPanelCopy
|
||||
textToCopy={`cloud.account.id: "${cloudData.account.id}"`}
|
||||
tooltipContent={cloudData.account.id}
|
||||
>
|
||||
<EuiTextColor color="subdued" css={styles.descriptionSemibold}>
|
||||
{cloudData.account.id}
|
||||
</EuiTextColor>
|
||||
</DetailPanelCopy>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: <DetailPanelListItem>project.id</DetailPanelListItem>,
|
||||
description: (
|
||||
<DetailPanelCopy
|
||||
textToCopy={`cloud.project.id: "${cloudData.project.id}"`}
|
||||
tooltipContent={cloudData.project.id}
|
||||
>
|
||||
<EuiTextColor color="subdued" css={styles.descriptionSemibold}>
|
||||
{cloudData.project.id}
|
||||
</EuiTextColor>
|
||||
</DetailPanelCopy>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{processContainer && (
|
||||
<>
|
||||
<DetailPanelAccordion
|
||||
|
|
|
@ -69,6 +69,7 @@ export const SessionViewDetailPanel = ({
|
|||
processHost={selectedProcess?.events[0]?.host}
|
||||
processContainer={selectedProcess?.events[0]?.container}
|
||||
processOrchestrator={selectedProcess?.events[0]?.orchestrator}
|
||||
processCloud={selectedProcess?.events[0]?.cloud}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
|
|
@ -118,6 +118,20 @@ export interface DetailPanelOrchestrator {
|
|||
};
|
||||
}
|
||||
|
||||
export interface DetailPanelCloud {
|
||||
instance: {
|
||||
name: string;
|
||||
};
|
||||
account: {
|
||||
id: string;
|
||||
};
|
||||
project: {
|
||||
id: string;
|
||||
};
|
||||
provider: string;
|
||||
region: string;
|
||||
}
|
||||
|
||||
export interface SessionViewStart {
|
||||
getSessionView: (props: SessionViewDeps) => JSX.Element;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue