diff --git a/portal-ui/src/screens/Console/Tenants/TenantDetails/pods/PodDescribe.tsx b/portal-ui/src/screens/Console/Tenants/TenantDetails/pods/PodDescribe.tsx
new file mode 100644
index 000000000..ed91a6e2f
--- /dev/null
+++ b/portal-ui/src/screens/Console/Tenants/TenantDetails/pods/PodDescribe.tsx
@@ -0,0 +1,454 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+import React, { useEffect, useState } from "react";
+import { connect } from "react-redux";
+import { Theme } from "@mui/material/styles";
+import createStyles from "@mui/styles/createStyles";
+import withStyles from "@mui/styles/withStyles";
+import {
+ actionsTray,
+ buttonsStyles,
+ hrClass,
+ searchField,
+} from "../../../Common/FormComponents/common/styleLibrary";
+import { Box } from "@mui/material";
+import Grid from "@mui/material/Grid";
+import Chip from "@mui/material/Chip";
+import Table from "@mui/material/Table";
+import TableBody from "@mui/material/TableBody";
+import TableCell from "@mui/material/TableCell";
+import TableHead from "@mui/material/TableHead";
+import TableRow from "@mui/material/TableRow";
+import Tabs from "@mui/material/Tabs";
+import Tab from "@mui/material/Tab";
+import TableContainer from "@mui/material/TableContainer";
+import Paper from "@mui/material/Paper";
+import { setErrorSnackMessage } from "../../../../../actions";
+import { ErrorResponseHandler } from "../../../../../common/types";
+import api from "../../../../../common/api";
+import { AppState } from "../../../../../store";
+import LabelValuePair from "../../../Common/UsageBarWrapper/LabelValuePair";
+
+interface IPodEventsProps {
+ classes: any;
+ tenant: string;
+ namespace: string;
+ podName: string;
+ propLoading: boolean;
+ setErrorSnackMessage: typeof setErrorSnackMessage;
+ loadingTenant: boolean;
+}
+
+interface Annotation {
+ key: string;
+ value: string;
+}
+
+interface Condition {
+ status: string;
+ type: string;
+}
+
+interface EnvVar {
+ key: string;
+ value: string;
+}
+
+interface Mount {
+ mountPath: string;
+ name: string;
+}
+
+interface State {
+ started: string;
+ state: string;
+}
+
+interface Container {
+ args: string[];
+ containerID: string;
+ environmentVariables: EnvVar[];
+ hostPorts: string[];
+ image: string;
+ imageID: string;
+ lastState: any;
+ mounts: Mount[];
+ name: string;
+ ports: string[];
+ ready: boolean;
+ state: State
+}
+
+interface Label {
+ key: string;
+ value: string;
+}
+
+interface Toleration {
+ effect: string;
+ key: string;
+ operator: string;
+ tolerationSeconds: number;
+}
+
+interface VolumePVC{
+ claimName: string;
+}
+
+interface Volume {
+ name: string;
+ pvc?: VolumePVC;
+ projected?: any;
+}
+
+interface DescribeResponse {
+ annotations: Annotation[];
+ conditions: Condition[];
+ containers: Container[];
+ controllerRef: string;
+ labels: Label[];
+ name: string;
+ namespace: string;
+ nodeName: string;
+ nodeSelector: string[];
+ phase: string;
+ podIP: string;
+ qosClass: string;
+ startTime: string;
+ tolerations: Toleration[];
+ volumes: Volume[];
+}
+
+interface IPodDescribeSummaryProps {
+ describeInfo: DescribeResponse;
+}
+
+interface IPodDescribeAnnotationsProps {
+ annotations: Annotation[];
+}
+
+interface IPodDescribeLabelsProps {
+ labels: Label[];
+}
+
+interface IPodDescribeConditionsProps {
+ conditions: Condition[];
+}
+
+interface IPodDescribeTolerationsProps {
+ tolerations: Toleration[];
+}
+
+interface IPodDescribeVolumesProps {
+ volumes: Volume[];
+}
+
+interface IPodDescribeContainersProps {
+ containers: Container[];
+}
+
+interface IPodDescribeTableProps {
+ title: string;
+ columns: string[];
+ columnsLabels: string[];
+ items: any[];
+}
+
+
+const styles = (theme: Theme) =>
+ createStyles({
+ ...actionsTray,
+ ...buttonsStyles,
+ ...searchField,
+ ...hrClass,
+ actionsTray: {
+ ...actionsTray.actionsTray,
+ padding: "15px 0 0",
+ },
+ });
+
+const twoColCssGridLayoutConfig = {
+ display: "grid",
+ gridTemplateColumns: { xs: "1fr", sm: "2fr 1fr" },
+ gridAutoFlow: { xs: "dense", sm: "row" },
+ gap: 2,
+ padding: "15px",
+};
+
+const HeaderSection = ({ title }: { title: string }) => {
+ return (
+
+ {title}
+
+
+ );
+};
+
+const PodDescribeSummary = ({describeInfo}: IPodDescribeSummaryProps) => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const PodDescribeAnnotations = ({annotations}: IPodDescribeAnnotationsProps) => {
+ return (
+
+
+
+ {annotations.map((annotation, index) => (
+
+ ))}
+
+
+ );
+};
+
+const PodDescribeLabels = ({labels}: IPodDescribeLabelsProps) => {
+ return (
+
+
+
+ {labels.map((label, index) => (
+
+ ))}
+
+
+ );
+};
+
+
+const PodDescribeConditions = ({conditions}: IPodDescribeConditionsProps) => {
+ return ;
+};
+
+const PodDescribeTolerations = ({tolerations}: IPodDescribeTolerationsProps) => {
+ return ;
+};
+
+const PodDescribeVolumes = ({volumes}: IPodDescribeVolumesProps) => {
+ return (
+
+ {volumes.map((volume, index) => (
+
+
+
+ {volume.pvc && (
+
+
+
+
+ )}
+ {/* TODO Add component to display projected data (Maybe change API response) */}
+ {volume.projected && }
+
+
+ ))}
+
+ );
+};
+
+const PodDescribeTable = ({title, items, columns, columnsLabels}: IPodDescribeTableProps) => {
+ return (
+
+
+
+
+
+
+
+ {columnsLabels.map((label, index) => {label} )}
+
+
+
+ {items.map((item, i) => (
+
+ {columns.map((column, j) => {item[column]} )}
+
+ ))}
+
+
+
+
+
+ );
+};
+
+
+const PodDescribeContainers = ({containers}: IPodDescribeContainersProps) => {
+ return (
+
+ {containers.map((container, index) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+ );
+};
+
+
+const PodDescribe = ({
+ classes,
+ tenant,
+ namespace,
+ podName,
+ propLoading,
+ setErrorSnackMessage,
+ loadingTenant,
+}: IPodEventsProps) => {
+ const [describeInfo, setDescribeInfo] = useState();
+ const [loading, setLoading] = useState(true);
+ const [curTab, setCurTab] = useState(0);
+
+ useEffect(() => {
+ if (propLoading) {
+ setLoading(true);
+ }
+ }, [propLoading]);
+
+ useEffect(() => {
+ if (loadingTenant) {
+ setLoading(true);
+ }
+ }, [loadingTenant]);
+
+ useEffect(() => {
+ if (loading) {
+ api
+ .invoke(
+ "GET",
+ `/api/v1/namespaces/${namespace}/tenants/${tenant}/pods/${podName}/describe`
+ )
+ .then((res: DescribeResponse) => {
+ setDescribeInfo(res);
+ setLoading(false);
+ })
+ .catch((err: ErrorResponseHandler) => {
+ setErrorSnackMessage(err);
+ setLoading(false);
+ });
+ }
+ }, [loading, podName, namespace, tenant, setErrorSnackMessage]);
+
+ const renderTabComponent = (index: number, info: DescribeResponse) => {
+ switch (index) {
+ case 0:
+ return
+ case 1:
+ return
+ case 2:
+ return
+ case 3:
+ return
+ case 4:
+ return
+ case 5:
+ return
+ case 6:
+ return
+ default:
+ break;
+ }
+ };
+ return (
+
+ {describeInfo && (
+ , newValue: number) => {
+ setCurTab(newValue);
+ }}
+ indicatorColor="primary"
+ textColor="primary"
+ aria-label="cluster-tabs"
+ variant="scrollable"
+ scrollButtons="auto">
+
+
+
+
+
+
+
+
+ {renderTabComponent(curTab, describeInfo)}
+ )}
+
+ );
+};
+const mapState = (state: AppState) => ({
+ loadingTenant: state.tenants.tenantDetails.loadingTenant,
+});
+const connector = connect(mapState, {
+ setErrorSnackMessage,
+});
+
+export default withStyles(styles)(connector(PodDescribe));
diff --git a/portal-ui/src/screens/Console/Tenants/TenantDetails/pods/PodDetails.tsx b/portal-ui/src/screens/Console/Tenants/TenantDetails/pods/PodDetails.tsx
index db5c59927..1b736aad7 100644
--- a/portal-ui/src/screens/Console/Tenants/TenantDetails/pods/PodDetails.tsx
+++ b/portal-ui/src/screens/Console/Tenants/TenantDetails/pods/PodDetails.tsx
@@ -26,6 +26,7 @@ import { Link } from "react-router-dom";
import { setErrorSnackMessage } from "../../../../../actions";
import PodLogs from "./PodLogs";
import PodEvents from "./PodEvents";
+import PodDescribe from "./PodDescribe";
interface IPodDetailsProps {
classes: any;
@@ -89,7 +90,8 @@ const PodDetails = ({ classes, match }: IPodDetailsProps) => {
scrollButtons="auto"
>
-
+
+
{curTab === 0 && (
@@ -101,6 +103,14 @@ const PodDetails = ({ classes, match }: IPodDetailsProps) => {
/>
)}
{curTab === 1 && (
+
+ )}
+ {curTab === 2 && (