[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:
Rickyanto Ang 2022-07-12 10:25:25 -07:00 committed by GitHub
parent 68e2ff6cbf
commit 735b69d1ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 217 additions and 5 deletions

View file

@ -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;
}

View file

@ -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);
});
});

View file

@ -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;
};

View file

@ -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();
});
});
});

View file

@ -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

View file

@ -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}
/>
),
},

View file

@ -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;
}