@backstage/plugin-kubernetes 0.8.1-next.0 → 0.9.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -2,20 +2,24 @@ import { stringifyEntityRef } from '@backstage/catalog-model';
2
2
  import { NotFoundError } from '@backstage/errors';
3
3
  import { createApiRef, createRouteRef, createPlugin, createApiFactory, discoveryApiRef, identityApiRef, gitlabAuthApiRef, googleAuthApiRef, microsoftAuthApiRef, oktaAuthApiRef, oneloginAuthApiRef, createRoutableExtension, useApi } from '@backstage/core-plugin-api';
4
4
  import * as React from 'react';
5
- import React__default, { Fragment, useCallback, useState, useContext } from 'react';
5
+ import React__default, { useState, useCallback, useContext, Fragment } from 'react';
6
6
  import { useEntity } from '@backstage/plugin-catalog-react';
7
7
  import { Routes, Route } from 'react-router-dom';
8
- import { Typography, Chip, makeStyles, createStyles, Button, Drawer, Grid, IconButton, FormControlLabel, Switch, Accordion, AccordionSummary, AccordionDetails, Stepper, Step, StepLabel } from '@material-ui/core';
9
- import { WarningPanel, Table, StatusOK, SubvalueCell, StatusError, StatusAborted, LinkButton, CodeSnippet, StructuredMetadataTable, StatusPending, Page, Content, Progress, MissingAnnotationEmptyState } from '@backstage/core-components';
8
+ import { Typography, Paper, makeStyles, createStyles, Dialog, DialogTitle, IconButton, DialogContent, Button, Card, CardHeader, CardContent, Grid, CardActions, FormControlLabel, Switch, Drawer, withStyles as withStyles$1, List, ListItem, Chip, Accordion, AccordionSummary, AccordionDetails, Stepper, Step, StepLabel } from '@material-ui/core';
9
+ import { WarningPanel, Table, DismissableBanner, LogViewer, StructuredMetadataTable, CodeSnippet, LinkButton, StatusError, StatusOK, StatusWarning, ItemCardGrid, SubvalueCell, StatusAborted, StatusPending, Page, Content, Progress, MissingAnnotationEmptyState } from '@backstage/core-components';
10
10
  import lodash from 'lodash';
11
11
  import { DateTime } from 'luxon';
12
12
  import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
13
- import Close from '@material-ui/icons/Close';
13
+ import { Skeleton } from '@material-ui/lab';
14
+ import { kubernetesProxyApiRef as kubernetesProxyApiRef$1 } from '@backstage/plugin-kubernetes';
15
+ import useAsync from 'react-use/lib/useAsync';
16
+ import SubjectIcon from '@material-ui/icons/Subject';
17
+ import CloseIcon from '@material-ui/icons/Close';
14
18
  import OpenInNewIcon from '@material-ui/icons/OpenInNew';
15
19
  import { withStyles } from '@material-ui/core/styles';
16
- import jsYaml from 'js-yaml';
17
20
  import useInterval from 'react-use/lib/useInterval';
18
21
  import useAsyncRetry from 'react-use/lib/useAsyncRetry';
22
+ import jsyaml from 'js-yaml';
19
23
  import cronstrue from 'cronstrue';
20
24
  import PauseIcon from '@material-ui/icons/Pause';
21
25
  import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
@@ -121,6 +125,9 @@ class KubernetesBackendClient {
121
125
  const kubernetesApiRef = createApiRef({
122
126
  id: "plugin.kubernetes.service"
123
127
  });
128
+ const kubernetesProxyApiRef = createApiRef({
129
+ id: "plugin.kubernetes.proxy-service"
130
+ });
124
131
 
125
132
  const kubernetesAuthProvidersApiRef = createApiRef({
126
133
  id: "plugin.kubernetes-auth-providers.service"
@@ -251,6 +258,41 @@ class KubernetesAuthProviders {
251
258
  }
252
259
  }
253
260
 
261
+ class KubernetesProxyClient {
262
+ constructor(options) {
263
+ this.kubernetesApi = options.kubernetesApi;
264
+ }
265
+ async handleText(response) {
266
+ if (!response.ok) {
267
+ const payload = await response.text();
268
+ let message;
269
+ switch (response.status) {
270
+ default:
271
+ message = `Proxy request failed with ${response.status} ${response.statusText}, ${payload}`;
272
+ }
273
+ throw new Error(message);
274
+ }
275
+ return await response.text();
276
+ }
277
+ async getPodLogs({
278
+ podName,
279
+ namespace,
280
+ clusterName,
281
+ containerName
282
+ }) {
283
+ const params = new URLSearchParams({
284
+ container: containerName
285
+ });
286
+ return await this.kubernetesApi.proxy({
287
+ clusterName,
288
+ path: `/api/v1/namespaces/${namespace}/pods/${podName}/log?${params.toString()}`,
289
+ init: {
290
+ method: "GET"
291
+ }
292
+ }).then((response) => this.handleText(response)).then((text) => ({ text }));
293
+ }
294
+ }
295
+
254
296
  const rootCatalogKubernetesRouteRef = createRouteRef({
255
297
  id: "kubernetes"
256
298
  });
@@ -270,6 +312,15 @@ const kubernetesPlugin = createPlugin({
270
312
  kubernetesAuthProvidersApi
271
313
  })
272
314
  }),
315
+ createApiFactory({
316
+ api: kubernetesProxyApiRef,
317
+ deps: {
318
+ kubernetesApi: kubernetesApiRef
319
+ },
320
+ factory: ({ kubernetesApi }) => new KubernetesProxyClient({
321
+ kubernetesApi
322
+ })
323
+ }),
273
324
  createApiFactory({
274
325
  api: kubernetesAuthProvidersApiRef,
275
326
  deps: {
@@ -316,7 +367,7 @@ const clustersWithErrorsToErrorMessage = (clustersWithErrors) => {
316
367
  }), /* @__PURE__ */ React__default.createElement("br", null));
317
368
  });
318
369
  };
319
- const ErrorPanel$1 = ({
370
+ const ErrorPanel = ({
320
371
  entityName,
321
372
  errorMessage,
322
373
  clustersWithErrors
@@ -626,127 +677,162 @@ const detectErrors = (objects) => {
626
677
  return errors;
627
678
  };
628
679
 
629
- const imageChips = (pod) => {
630
- var _a, _b;
631
- const containerStatuses2 = (_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : [];
632
- const images = containerStatuses2.map((cs, i) => {
633
- return /* @__PURE__ */ React__default.createElement(Chip, { key: i, label: `${cs.name}=${cs.image}`, size: "small" });
634
- });
635
- return /* @__PURE__ */ React__default.createElement("div", null, images);
636
- };
637
- const containersReady = (pod) => {
638
- var _a, _b;
639
- const containerStatuses2 = (_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : [];
640
- const containersReadyItem = containerStatuses2.filter((cs) => cs.ready).length;
641
- return `${containersReadyItem}/${containerStatuses2.length}`;
680
+ const usePodLogs = ({ podScope }) => {
681
+ const kubernetesProxyApi = useApi(kubernetesProxyApiRef$1);
682
+ return useAsync(async () => {
683
+ return await kubernetesProxyApi.getPodLogs({
684
+ podName: podScope.podName,
685
+ namespace: podScope.podNamespace,
686
+ containerName: podScope.containerName,
687
+ clusterName: podScope.clusterName
688
+ });
689
+ }, [JSON.stringify(podScope)]);
642
690
  };
643
- const totalRestarts = (pod) => {
644
- var _a, _b;
645
- const containerStatuses2 = (_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : [];
646
- return containerStatuses2 == null ? void 0 : containerStatuses2.reduce((a, b) => a + b.restartCount, 0);
691
+
692
+ const PodLogs = ({ podScope }) => {
693
+ const { value, error, loading } = usePodLogs({
694
+ podScope
695
+ });
696
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, error && /* @__PURE__ */ React__default.createElement(
697
+ DismissableBanner,
698
+ {
699
+ ...{
700
+ message: error.message,
701
+ variant: "error",
702
+ fixed: false
703
+ },
704
+ id: "pod-logs"
705
+ }
706
+ ), /* @__PURE__ */ React__default.createElement(
707
+ Paper,
708
+ {
709
+ elevation: 1,
710
+ style: { height: "100%", width: "100%", minHeight: "30rem" }
711
+ },
712
+ loading && /* @__PURE__ */ React__default.createElement(Skeleton, { variant: "rect", width: "100%", height: "100%" }),
713
+ !loading && value !== void 0 && /* @__PURE__ */ React__default.createElement(LogViewer, { text: value.text })
714
+ ));
647
715
  };
648
- const containerStatuses = (pod) => {
649
- var _a, _b;
650
- const containerStatusesItem = (_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : [];
651
- const errors = containerStatusesItem.reduce((accum, next) => {
652
- if (next.state === void 0) {
653
- return accum;
716
+
717
+ const useStyles = makeStyles(
718
+ (theme) => createStyles({
719
+ closeButton: {
720
+ position: "absolute",
721
+ right: theme.spacing(1),
722
+ top: theme.spacing(1),
723
+ color: theme.palette.grey[500]
654
724
  }
655
- const waiting = next.state.waiting;
656
- const terminated = next.state.terminated;
657
- const renderCell = (reason) => {
658
- var _a2;
659
- return /* @__PURE__ */ React__default.createElement(Fragment, { key: `${(_a2 = pod.metadata) == null ? void 0 : _a2.name}-${next.name}` }, /* @__PURE__ */ React__default.createElement(
660
- SubvalueCell,
661
- {
662
- value: reason === "Completed" ? /* @__PURE__ */ React__default.createElement(StatusOK, null, "Container: ", next.name) : /* @__PURE__ */ React__default.createElement(StatusError, null, "Container: ", next.name),
663
- subvalue: reason
664
- }
665
- ), /* @__PURE__ */ React__default.createElement("br", null));
725
+ })
726
+ );
727
+ const PodLogsDialog = ({ podScope }) => {
728
+ const classes = useStyles();
729
+ const [open, setOpen] = useState(false);
730
+ const openDialog = () => {
731
+ setOpen(true);
732
+ };
733
+ const closeDialog = () => {
734
+ setOpen(false);
735
+ };
736
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(Dialog, { maxWidth: "xl", fullWidth: true, open, onClose: closeDialog }, /* @__PURE__ */ React__default.createElement(DialogTitle, { id: "dialog-title" }, podScope.podName, " - ", podScope.containerName, " logs on cluster", " ", podScope.clusterName, /* @__PURE__ */ React__default.createElement(
737
+ IconButton,
738
+ {
739
+ "aria-label": "close",
740
+ className: classes.closeButton,
741
+ onClick: closeDialog
742
+ },
743
+ /* @__PURE__ */ React__default.createElement(CloseIcon, null)
744
+ )), /* @__PURE__ */ React__default.createElement(DialogContent, null, /* @__PURE__ */ React__default.createElement(PodLogs, { podScope }))), /* @__PURE__ */ React__default.createElement(
745
+ Button,
746
+ {
747
+ variant: "outlined",
748
+ "aria-label": "get logs",
749
+ component: "label",
750
+ onClick: openDialog,
751
+ startIcon: /* @__PURE__ */ React__default.createElement(SubjectIcon, null)
752
+ },
753
+ "Logs"
754
+ ));
755
+ };
756
+
757
+ const getContainerHealthChecks = (containerSpec, containerStatus) => {
758
+ var _a, _b, _c, _d;
759
+ if (((_b = (_a = containerStatus.state) == null ? void 0 : _a.terminated) == null ? void 0 : _b.reason) === "Completed") {
760
+ return {
761
+ "not waiting to start": ((_c = containerStatus.state) == null ? void 0 : _c.waiting) === void 0,
762
+ "no restarts": containerStatus.restartCount === 0
666
763
  };
667
- if (waiting) {
668
- accum.push(renderCell(waiting.reason));
669
- }
670
- if (terminated) {
671
- accum.push(renderCell(terminated.reason));
672
- }
673
- return accum;
674
- }, []);
675
- if (errors.length === 0) {
676
- return /* @__PURE__ */ React__default.createElement(StatusOK, null, "OK");
677
764
  }
678
- return errors;
765
+ return {
766
+ "not waiting to start": ((_d = containerStatus.state) == null ? void 0 : _d.waiting) === void 0,
767
+ started: !!containerStatus.started,
768
+ ready: containerStatus.ready,
769
+ "no restarts": containerStatus.restartCount === 0,
770
+ "readiness probe set": containerSpec && (containerSpec == null ? void 0 : containerSpec.readinessProbe) !== void 0
771
+ };
679
772
  };
680
- const renderCondition = (condition) => {
681
- var _a;
682
- const status = condition.status;
683
- if (status === "True") {
684
- return [condition.type, /* @__PURE__ */ React__default.createElement(StatusOK, null, "True")];
685
- } else if (status === "False") {
686
- return [
687
- condition.type,
688
- /* @__PURE__ */ React__default.createElement(
689
- SubvalueCell,
690
- {
691
- value: /* @__PURE__ */ React__default.createElement(StatusError, null, "False"),
692
- subvalue: (_a = condition.message) != null ? _a : ""
693
- }
694
- )
695
- ];
696
- }
697
- return [condition.type, /* @__PURE__ */ React__default.createElement(StatusAborted, null)];
773
+ const getCurrentState = (containerStatus) => {
774
+ var _a, _b, _c, _d, _e;
775
+ return ((_b = (_a = containerStatus.state) == null ? void 0 : _a.waiting) == null ? void 0 : _b.reason) || ((_d = (_c = containerStatus.state) == null ? void 0 : _c.terminated) == null ? void 0 : _d.reason) || (((_e = containerStatus.state) == null ? void 0 : _e.running) !== void 0 ? "Running" : "Unknown");
698
776
  };
699
- const currentToDeclaredResourceToPerc = (current, resource) => {
700
- if (Number(resource) === 0)
701
- return `0%`;
702
- if (typeof current === "number" && typeof resource === "number") {
703
- return `${Math.round(current / resource * 100)}%`;
704
- }
705
- const numerator = BigInt(current);
706
- const denominator = BigInt(resource);
707
- return `${numerator * BigInt(100) / denominator}%`;
777
+ const getStartedAtTime = (containerStatus) => {
778
+ var _a, _b, _c, _d;
779
+ return ((_b = (_a = containerStatus.state) == null ? void 0 : _a.running) == null ? void 0 : _b.startedAt) || ((_d = (_c = containerStatus.state) == null ? void 0 : _c.terminated) == null ? void 0 : _d.startedAt);
708
780
  };
709
- const formatMilicores = (value) => {
710
- return `${parseFloat(value.toString()) * 1e3}m`;
781
+ const ContainerDatetime = ({ prefix, dateTime }) => {
782
+ return /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, prefix, ":", " ", DateTime.fromISO(dateTime).toRelative({
783
+ locale: "en"
784
+ }));
711
785
  };
712
- const podStatusToCpuUtil = (podStatus) => {
713
- const cpuUtil = podStatus.cpu;
714
- let currentUsage = cpuUtil.currentUsage;
715
- if (typeof cpuUtil.currentUsage === "number") {
716
- currentUsage = cpuUtil.currentUsage / 10;
786
+ const ContainerCard = ({
787
+ podScope,
788
+ containerSpec,
789
+ containerStatus
790
+ }) => {
791
+ var _a, _b;
792
+ if (containerSpec === void 0) {
793
+ return /* @__PURE__ */ React__default.createElement(Typography, null, "error reading pod from cluster");
717
794
  }
718
- return /* @__PURE__ */ React__default.createElement(
719
- SubvalueCell,
795
+ const containerStartedTime = getStartedAtTime(containerStatus);
796
+ const containerFinishedTime = (_b = (_a = containerStatus.state) == null ? void 0 : _a.terminated) == null ? void 0 : _b.finishedAt;
797
+ return /* @__PURE__ */ React__default.createElement(Card, null, /* @__PURE__ */ React__default.createElement(
798
+ CardHeader,
720
799
  {
721
- value: `requests: ${currentToDeclaredResourceToPerc(
722
- currentUsage,
723
- cpuUtil.requestTotal
724
- )} of ${formatMilicores(cpuUtil.requestTotal)}`,
725
- subvalue: `limits: ${currentToDeclaredResourceToPerc(
726
- currentUsage,
727
- cpuUtil.limitTotal
728
- )} of ${formatMilicores(cpuUtil.limitTotal)}`
800
+ title: containerStatus.name,
801
+ subheader: containerStatus.image
729
802
  }
730
- );
731
- };
732
- const bytesToMiB = (value) => {
733
- return `${parseFloat(value.toString()) / 1024 / 1024}MiB`;
734
- };
735
- const podStatusToMemoryUtil = (podStatus) => {
736
- const memUtil = podStatus.memory;
737
- return /* @__PURE__ */ React__default.createElement(
738
- SubvalueCell,
803
+ ), /* @__PURE__ */ React__default.createElement(CardContent, null, /* @__PURE__ */ React__default.createElement(Grid, { container: true }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, containerStartedTime && /* @__PURE__ */ React__default.createElement(
804
+ ContainerDatetime,
739
805
  {
740
- value: `requests: ${currentToDeclaredResourceToPerc(
741
- memUtil.currentUsage,
742
- memUtil.requestTotal
743
- )} of ${bytesToMiB(memUtil.requestTotal)}`,
744
- subvalue: `limits: ${currentToDeclaredResourceToPerc(
745
- memUtil.currentUsage,
746
- memUtil.limitTotal
747
- )} of ${bytesToMiB(memUtil.limitTotal)}`
806
+ prefix: "Started",
807
+ dateTime: containerStartedTime
748
808
  }
749
- );
809
+ ), containerFinishedTime && /* @__PURE__ */ React__default.createElement(
810
+ ContainerDatetime,
811
+ {
812
+ prefix: "Completed",
813
+ dateTime: containerFinishedTime
814
+ }
815
+ ), containerStartedTime && containerFinishedTime && /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "Execution time:", " ", DateTime.fromISO(containerFinishedTime).diff(DateTime.fromISO(containerStartedTime), [
816
+ "hours",
817
+ "minutes",
818
+ "seconds"
819
+ ]).toHuman())), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "Status: ", getCurrentState(containerStatus))), containerStatus.restartCount > 0 && /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "Restarts: ", containerStatus.restartCount)), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "Container health")), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(
820
+ StructuredMetadataTable,
821
+ {
822
+ metadata: getContainerHealthChecks(
823
+ containerSpec,
824
+ containerStatus
825
+ )
826
+ }
827
+ )))), /* @__PURE__ */ React__default.createElement(CardActions, { disableSpacing: true }, /* @__PURE__ */ React__default.createElement(
828
+ PodLogsDialog,
829
+ {
830
+ podScope: {
831
+ containerName: containerStatus.name,
832
+ ...podScope
833
+ }
834
+ }
835
+ )));
750
836
  };
751
837
 
752
838
  const generateAuth = async (entity, kubernetesApi, kubernetesAuthProvidersApi) => {
@@ -1067,7 +1153,43 @@ function formatClusterLink(options) {
1067
1153
  return url.toString();
1068
1154
  }
1069
1155
 
1070
- const useDrawerStyles = makeStyles(
1156
+ const ManifestYaml = ({ object }) => {
1157
+ const [managedFields, setManagedFields] = useState(false);
1158
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
1159
+ FormControlLabel,
1160
+ {
1161
+ control: /* @__PURE__ */ React__default.createElement(
1162
+ Switch,
1163
+ {
1164
+ checked: managedFields,
1165
+ onChange: (event) => {
1166
+ setManagedFields(event.target.checked);
1167
+ },
1168
+ name: "Managed Fields"
1169
+ }
1170
+ ),
1171
+ label: "Managed Fields"
1172
+ }
1173
+ ), /* @__PURE__ */ React__default.createElement(
1174
+ CodeSnippet,
1175
+ {
1176
+ language: "yaml",
1177
+ text: jsyaml.dump(object, {
1178
+ // NOTE: this will remove any field called `managedFields`
1179
+ // not just the metadata one
1180
+ // TODO: @mclarke make this only remove the `metadata.managedFields`
1181
+ replacer: (key, value) => {
1182
+ if (!managedFields) {
1183
+ return key === "managedFields" ? void 0 : value;
1184
+ }
1185
+ return value;
1186
+ }
1187
+ })
1188
+ }
1189
+ ));
1190
+ };
1191
+
1192
+ const useDrawerStyles$1 = makeStyles(
1071
1193
  (theme) => createStyles({
1072
1194
  paper: {
1073
1195
  width: "50%",
@@ -1076,7 +1198,7 @@ const useDrawerStyles = makeStyles(
1076
1198
  }
1077
1199
  })
1078
1200
  );
1079
- const useDrawerContentStyles = makeStyles(
1201
+ const useDrawerContentStyles$2 = makeStyles(
1080
1202
  (_) => createStyles({
1081
1203
  header: {
1082
1204
  display: "flex",
@@ -1108,7 +1230,7 @@ const PodDrawerButton = withStyles({
1108
1230
  textTransform: "none"
1109
1231
  }
1110
1232
  })(Button);
1111
- const ErrorPanel = ({ cluster, errorMessage }) => /* @__PURE__ */ React__default.createElement(
1233
+ const LinkErrorPanel = ({ cluster, errorMessage }) => /* @__PURE__ */ React__default.createElement(
1112
1234
  WarningPanel,
1113
1235
  {
1114
1236
  title: "There was a problem formatting the link to the Kubernetes dashboard",
@@ -1133,7 +1255,7 @@ function tryFormatClusterLink(options) {
1133
1255
  };
1134
1256
  }
1135
1257
  }
1136
- const KubernetesDrawerContent = ({
1258
+ const KubernetesStructuredMetadataTableDrawerContent = ({
1137
1259
  toggleDrawer,
1138
1260
  object,
1139
1261
  renderObject,
@@ -1141,7 +1263,7 @@ const KubernetesDrawerContent = ({
1141
1263
  }) => {
1142
1264
  var _a, _b;
1143
1265
  const [isYaml, setIsYaml] = useState(false);
1144
- const classes = useDrawerContentStyles();
1266
+ const classes = useDrawerContentStyles$2();
1145
1267
  const cluster = useContext(ClusterContext);
1146
1268
  const { clusterLink, errorMessage } = tryFormatClusterLink({
1147
1269
  dashboardUrl: cluster.dashboardUrl,
@@ -1150,17 +1272,7 @@ const KubernetesDrawerContent = ({
1150
1272
  object,
1151
1273
  kind
1152
1274
  });
1153
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement("div", { className: classes.header }, /* @__PURE__ */ React__default.createElement(
1154
- Grid,
1155
- {
1156
- container: true,
1157
- direction: "column",
1158
- justifyContent: "flex-start",
1159
- alignItems: "flex-start"
1160
- },
1161
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h5" }, (_b = (_a = object.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown name")),
1162
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { color: "textSecondary", variant: "body1" }, kind))
1163
- ), /* @__PURE__ */ React__default.createElement(
1275
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement("div", { className: classes.header }, /* @__PURE__ */ React__default.createElement(Grid, { container: true, justifyContent: "flex-start", alignItems: "flex-start" }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 11 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h5" }, (_b = (_a = object.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown name")), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 1 }, /* @__PURE__ */ React__default.createElement(
1164
1276
  IconButton,
1165
1277
  {
1166
1278
  key: "dismiss",
@@ -1168,18 +1280,8 @@ const KubernetesDrawerContent = ({
1168
1280
  onClick: (e) => toggleDrawer(e, false),
1169
1281
  color: "inherit"
1170
1282
  },
1171
- /* @__PURE__ */ React__default.createElement(Close, { className: classes.icon })
1172
- )), errorMessage && /* @__PURE__ */ React__default.createElement("div", { className: classes.errorMessage }, /* @__PURE__ */ React__default.createElement(ErrorPanel, { cluster, errorMessage })), /* @__PURE__ */ React__default.createElement("div", { className: classes.options }, /* @__PURE__ */ React__default.createElement("div", null, clusterLink && /* @__PURE__ */ React__default.createElement(
1173
- LinkButton,
1174
- {
1175
- variant: "outlined",
1176
- color: "primary",
1177
- size: "small",
1178
- to: clusterLink,
1179
- endIcon: /* @__PURE__ */ React__default.createElement(OpenInNewIcon, null)
1180
- },
1181
- "Open Kubernetes Dashboard"
1182
- )), /* @__PURE__ */ React__default.createElement(
1283
+ /* @__PURE__ */ React__default.createElement(CloseIcon, { className: classes.icon })
1284
+ )), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 11 }, /* @__PURE__ */ React__default.createElement(Typography, { color: "textSecondary", variant: "body1" }, kind)), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 11 }, /* @__PURE__ */ React__default.createElement(
1183
1285
  FormControlLabel,
1184
1286
  {
1185
1287
  control: /* @__PURE__ */ React__default.createElement(
@@ -1194,14 +1296,24 @@ const KubernetesDrawerContent = ({
1194
1296
  ),
1195
1297
  label: "YAML"
1196
1298
  }
1197
- )), /* @__PURE__ */ React__default.createElement("div", { className: classes.content }, isYaml && /* @__PURE__ */ React__default.createElement(CodeSnippet, { language: "yaml", text: jsYaml.dump(object) }), !isYaml && /* @__PURE__ */ React__default.createElement(
1299
+ )))), errorMessage && /* @__PURE__ */ React__default.createElement("div", { className: classes.errorMessage }, /* @__PURE__ */ React__default.createElement(LinkErrorPanel, { cluster, errorMessage })), /* @__PURE__ */ React__default.createElement("div", { className: classes.options }, /* @__PURE__ */ React__default.createElement("div", null, clusterLink && /* @__PURE__ */ React__default.createElement(
1300
+ LinkButton,
1301
+ {
1302
+ variant: "outlined",
1303
+ color: "primary",
1304
+ size: "small",
1305
+ to: clusterLink,
1306
+ endIcon: /* @__PURE__ */ React__default.createElement(OpenInNewIcon, null)
1307
+ },
1308
+ "Open Kubernetes Dashboard"
1309
+ ))), /* @__PURE__ */ React__default.createElement("div", { className: classes.content }, isYaml && /* @__PURE__ */ React__default.createElement(ManifestYaml, { object }), !isYaml && /* @__PURE__ */ React__default.createElement(
1198
1310
  StructuredMetadataTable,
1199
1311
  {
1200
1312
  metadata: renderObject(replaceNullsWithUndefined(object))
1201
1313
  }
1202
1314
  )));
1203
1315
  };
1204
- const KubernetesDrawer = ({
1316
+ const KubernetesStructuredMetadataTableDrawer = ({
1205
1317
  object,
1206
1318
  renderObject,
1207
1319
  kind,
@@ -1211,7 +1323,7 @@ const KubernetesDrawer = ({
1211
1323
  }) => {
1212
1324
  var _a, _b;
1213
1325
  const [isOpen, setIsOpen] = useState(expanded);
1214
- const classes = useDrawerStyles();
1326
+ const classes = useDrawerStyles$1();
1215
1327
  const toggleDrawer = (e, newValue) => {
1216
1328
  e.stopPropagation();
1217
1329
  setIsOpen(newValue);
@@ -1235,7 +1347,7 @@ const KubernetesDrawer = ({
1235
1347
  onClick: (event) => event.stopPropagation()
1236
1348
  },
1237
1349
  /* @__PURE__ */ React__default.createElement(
1238
- KubernetesDrawerContent,
1350
+ KubernetesStructuredMetadataTableDrawerContent,
1239
1351
  {
1240
1352
  kind,
1241
1353
  toggleDrawer,
@@ -1246,61 +1358,306 @@ const KubernetesDrawer = ({
1246
1358
  ));
1247
1359
  };
1248
1360
 
1249
- const PodDrawer = (props) => {
1250
- const { pod, expanded } = props;
1361
+ const useDrawerContentStyles$1 = makeStyles(
1362
+ (_theme) => createStyles({
1363
+ header: {
1364
+ display: "flex",
1365
+ flexDirection: "row",
1366
+ justifyContent: "space-between"
1367
+ },
1368
+ content: {
1369
+ height: "80%"
1370
+ },
1371
+ icon: {
1372
+ fontSize: 20
1373
+ }
1374
+ })
1375
+ );
1376
+ const KubernetesDrawerContent = ({
1377
+ children,
1378
+ header,
1379
+ kubernetesObject,
1380
+ close
1381
+ }) => {
1382
+ var _a;
1383
+ const classes = useDrawerContentStyles$1();
1384
+ const [isYaml, setIsYaml] = useState(false);
1385
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement("div", { className: classes.header }, /* @__PURE__ */ React__default.createElement(Grid, { container: true, justifyContent: "flex-start", alignItems: "flex-start" }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 11 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h5" }, (_a = kubernetesObject.metadata) == null ? void 0 : _a.name)), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 1 }, /* @__PURE__ */ React__default.createElement(
1386
+ IconButton,
1387
+ {
1388
+ key: "dismiss",
1389
+ title: "Close the drawer",
1390
+ onClick: () => close(),
1391
+ color: "inherit"
1392
+ },
1393
+ /* @__PURE__ */ React__default.createElement(CloseIcon, { className: classes.icon })
1394
+ )), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, header), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(
1395
+ FormControlLabel,
1396
+ {
1397
+ control: /* @__PURE__ */ React__default.createElement(
1398
+ Switch,
1399
+ {
1400
+ checked: isYaml,
1401
+ onChange: (event) => {
1402
+ setIsYaml(event.target.checked);
1403
+ },
1404
+ name: "YAML"
1405
+ }
1406
+ ),
1407
+ label: "YAML"
1408
+ }
1409
+ )))), /* @__PURE__ */ React__default.createElement("div", { className: classes.content }, isYaml && /* @__PURE__ */ React__default.createElement(ManifestYaml, { object: kubernetesObject }), !isYaml && children));
1410
+ };
1411
+ const useDrawerStyles = makeStyles(
1412
+ (theme) => createStyles({
1413
+ paper: {
1414
+ width: "50%",
1415
+ justifyContent: "space-between",
1416
+ padding: theme.spacing(2.5)
1417
+ }
1418
+ })
1419
+ );
1420
+ const DrawerButton = withStyles$1({
1421
+ root: {
1422
+ padding: "6px 5px"
1423
+ },
1424
+ label: {
1425
+ textTransform: "none"
1426
+ }
1427
+ })(Button);
1428
+ const KubernetesDrawer = ({
1429
+ open,
1430
+ label,
1431
+ drawerContentsHeader,
1432
+ kubernetesObject,
1433
+ children
1434
+ }) => {
1435
+ const classes = useDrawerStyles();
1436
+ const [isOpen, setIsOpen] = useState(open != null ? open : false);
1437
+ const toggleDrawer = (e, newValue) => {
1438
+ e.stopPropagation();
1439
+ setIsOpen(newValue);
1440
+ };
1441
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(DrawerButton, { onClick: () => setIsOpen(true) }, label), /* @__PURE__ */ React__default.createElement(
1442
+ Drawer,
1443
+ {
1444
+ classes: {
1445
+ paper: classes.paper
1446
+ },
1447
+ anchor: "right",
1448
+ open: isOpen,
1449
+ onClose: (e) => toggleDrawer(e, false),
1450
+ onClick: (event) => event.stopPropagation()
1451
+ },
1452
+ isOpen && /* @__PURE__ */ React__default.createElement(
1453
+ KubernetesDrawerContent,
1454
+ {
1455
+ header: drawerContentsHeader,
1456
+ kubernetesObject,
1457
+ children,
1458
+ close: () => setIsOpen(false)
1459
+ }
1460
+ )
1461
+ ));
1462
+ };
1463
+
1464
+ const PodCondition = ({ condition }) => {
1465
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, condition.status === "False" && /* @__PURE__ */ React__default.createElement(StatusError, null, condition.type, " - (", condition.reason, " ", condition.lastTransitionTime && DateTime.fromISO(condition.lastTransitionTime).toRelative({
1466
+ locale: "en"
1467
+ }), ") - ", condition.message, " "), condition.status === "True" && /* @__PURE__ */ React__default.createElement(StatusOK, null, condition.type, " - (", condition.lastTransitionTime && DateTime.fromISO(condition.lastTransitionTime).toRelative({
1468
+ locale: "en"
1469
+ }), ")"), condition.status === "Unknown" && /* @__PURE__ */ React__default.createElement(StatusWarning, null, condition.type, " - (", condition.lastTransitionTime && DateTime.fromISO(condition.lastTransitionTime).toRelative({
1470
+ locale: "en"
1471
+ }), ") ", condition.message));
1472
+ };
1473
+ const PendingPodContent = ({ pod }) => {
1474
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1475
+ const startupConditions = [
1476
+ (_b = (_a = pod.status) == null ? void 0 : _a.conditions) == null ? void 0 : _b.find((c) => c.type === "PodScheduled"),
1477
+ (_d = (_c = pod.status) == null ? void 0 : _c.conditions) == null ? void 0 : _d.find((c) => c.type === "Initialized"),
1478
+ (_f = (_e = pod.status) == null ? void 0 : _e.conditions) == null ? void 0 : _f.find((c) => c.type === "ContainersReady"),
1479
+ (_h = (_g = pod.status) == null ? void 0 : _g.conditions) == null ? void 0 : _h.find((c) => c.type === "Ready")
1480
+ ].filter((c) => !!c);
1481
+ return /* @__PURE__ */ React__default.createElement(Grid, { container: true, spacing: 2 }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h5" }, "Pod is Pending. Conditions:"), /* @__PURE__ */ React__default.createElement(List, null, startupConditions.map((c) => /* @__PURE__ */ React__default.createElement(ListItem, { key: c.type }, /* @__PURE__ */ React__default.createElement(PodCondition, { condition: c }))))));
1482
+ };
1483
+
1484
+ const useDrawerContentStyles = makeStyles(
1485
+ (_theme) => createStyles({
1486
+ header: {
1487
+ display: "flex",
1488
+ flexDirection: "row",
1489
+ justifyContent: "space-between"
1490
+ },
1491
+ content: {
1492
+ height: "80%"
1493
+ },
1494
+ icon: {
1495
+ fontSize: 20
1496
+ },
1497
+ podoklist: {
1498
+ width: "100%",
1499
+ maxWidth: 360,
1500
+ maxHeight: 360
1501
+ }
1502
+ })
1503
+ );
1504
+ function getContainerSpecByName(pod, containerName) {
1505
+ var _a;
1506
+ return (_a = pod.spec) == null ? void 0 : _a.containers.find((c) => c.name === containerName);
1507
+ }
1508
+ const PodDrawer = ({ podAndErrors, open }) => {
1509
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1510
+ const classes = useDrawerContentStyles();
1251
1511
  return /* @__PURE__ */ React__default.createElement(
1252
1512
  KubernetesDrawer,
1253
1513
  {
1254
- object: pod,
1255
- expanded,
1256
- kind: "Pod",
1257
- renderObject: (podObject) => {
1258
- var _a, _b, _c, _d, _e, _f, _g;
1259
- const phase = (_b = (_a = podObject.status) == null ? void 0 : _a.phase) != null ? _b : "unknown";
1260
- const ports = (_e = (_d = (_c = podObject.spec) == null ? void 0 : _c.containers) == null ? void 0 : _d.map((c) => {
1261
- return {
1262
- [c.name]: c.ports
1263
- };
1264
- })) != null ? _e : "N/A";
1265
- const conditions = ((_g = (_f = podObject.status) == null ? void 0 : _f.conditions) != null ? _g : []).map(renderCondition).reduce((accum, next) => {
1266
- accum[next[0]] = next[1];
1267
- return accum;
1268
- }, {});
1269
- return {
1270
- images: imageChips(podObject),
1271
- phase,
1272
- "Containers Ready": containersReady(podObject),
1273
- "Total Restarts": totalRestarts(podObject),
1274
- "Container Statuses": containerStatuses(podObject),
1275
- ...conditions,
1276
- "Exposed ports": ports
1277
- };
1514
+ open,
1515
+ drawerContentsHeader: /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle1" }, "Pod", " ", ((_a = podAndErrors.pod.status) == null ? void 0 : _a.podIP) && `(${(_b = podAndErrors.pod.status) == null ? void 0 : _b.podIP})`),
1516
+ kubernetesObject: podAndErrors.pod,
1517
+ label: /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle1" }, (_d = (_c = podAndErrors.pod.metadata) == null ? void 0 : _c.name) != null ? _d : "unknown")
1518
+ },
1519
+ /* @__PURE__ */ React__default.createElement("div", { className: classes.content }, ((_e = podAndErrors.pod.status) == null ? void 0 : _e.phase) === "Pending" && /* @__PURE__ */ React__default.createElement(PendingPodContent, { pod: podAndErrors.pod }), ((_g = (_f = podAndErrors.pod.status) == null ? void 0 : _f.containerStatuses) == null ? void 0 : _g.length) && /* @__PURE__ */ React__default.createElement(Grid, { container: true, spacing: 2 }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h5" }, "Containers")), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(ItemCardGrid, null, (_i = (_h = podAndErrors.pod.status) == null ? void 0 : _h.containerStatuses) == null ? void 0 : _i.map(
1520
+ (containerStatus, i) => {
1521
+ var _a2, _b2, _c2, _d2, _e2;
1522
+ const containerSpec = getContainerSpecByName(
1523
+ podAndErrors.pod,
1524
+ containerStatus.name
1525
+ );
1526
+ return /* @__PURE__ */ React__default.createElement(
1527
+ ContainerCard,
1528
+ {
1529
+ key: `container-card-${(_a2 = podAndErrors.pod.metadata) == null ? void 0 : _a2.name}-${i}`,
1530
+ podScope: {
1531
+ podName: (_c2 = (_b2 = podAndErrors.pod.metadata) == null ? void 0 : _b2.name) != null ? _c2 : "unknown",
1532
+ podNamespace: (_e2 = (_d2 = podAndErrors.pod.metadata) == null ? void 0 : _d2.namespace) != null ? _e2 : "unknown",
1533
+ clusterName: podAndErrors.clusterName
1534
+ },
1535
+ containerSpec,
1536
+ containerStatus
1537
+ }
1538
+ );
1278
1539
  }
1540
+ )))))
1541
+ );
1542
+ };
1543
+
1544
+ const containersReady = (pod) => {
1545
+ var _a, _b;
1546
+ const containerStatuses2 = (_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : [];
1547
+ const containersReadyItem = containerStatuses2.filter((cs) => cs.ready).length;
1548
+ return `${containersReadyItem}/${containerStatuses2.length}`;
1549
+ };
1550
+ const totalRestarts = (pod) => {
1551
+ var _a, _b;
1552
+ const containerStatuses2 = (_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : [];
1553
+ return containerStatuses2 == null ? void 0 : containerStatuses2.reduce((a, b) => a + b.restartCount, 0);
1554
+ };
1555
+ const containerStatuses = (pod) => {
1556
+ var _a, _b;
1557
+ const containerStatusesItem = (_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : [];
1558
+ const errors = containerStatusesItem.reduce((accum, next) => {
1559
+ if (next.state === void 0) {
1560
+ return accum;
1561
+ }
1562
+ const waiting = next.state.waiting;
1563
+ const terminated = next.state.terminated;
1564
+ const renderCell = (reason) => {
1565
+ var _a2;
1566
+ return /* @__PURE__ */ React__default.createElement(Fragment, { key: `${(_a2 = pod.metadata) == null ? void 0 : _a2.name}-${next.name}` }, /* @__PURE__ */ React__default.createElement(
1567
+ SubvalueCell,
1568
+ {
1569
+ value: reason === "Completed" ? /* @__PURE__ */ React__default.createElement(StatusOK, null, "Container: ", next.name) : /* @__PURE__ */ React__default.createElement(StatusError, null, "Container: ", next.name),
1570
+ subvalue: reason
1571
+ }
1572
+ ), /* @__PURE__ */ React__default.createElement("br", null));
1573
+ };
1574
+ if (waiting) {
1575
+ accum.push(renderCell(waiting.reason));
1576
+ }
1577
+ if (terminated) {
1578
+ accum.push(renderCell(terminated.reason));
1579
+ }
1580
+ return accum;
1581
+ }, []);
1582
+ if (errors.length === 0) {
1583
+ return /* @__PURE__ */ React__default.createElement(StatusOK, null, "OK");
1584
+ }
1585
+ return errors;
1586
+ };
1587
+ const renderCondition = (condition) => {
1588
+ var _a;
1589
+ const status = condition.status;
1590
+ if (status === "True") {
1591
+ return [condition.type, /* @__PURE__ */ React__default.createElement(StatusOK, null, "True")];
1592
+ } else if (status === "False") {
1593
+ return [
1594
+ condition.type,
1595
+ /* @__PURE__ */ React__default.createElement(
1596
+ SubvalueCell,
1597
+ {
1598
+ value: /* @__PURE__ */ React__default.createElement(StatusError, null, "False"),
1599
+ subvalue: (_a = condition.message) != null ? _a : ""
1600
+ }
1601
+ )
1602
+ ];
1603
+ }
1604
+ return [condition.type, /* @__PURE__ */ React__default.createElement(StatusAborted, null)];
1605
+ };
1606
+ const currentToDeclaredResourceToPerc = (current, resource) => {
1607
+ if (Number(resource) === 0)
1608
+ return `0%`;
1609
+ if (typeof current === "number" && typeof resource === "number") {
1610
+ return `${Math.round(current / resource * 100)}%`;
1611
+ }
1612
+ const numerator = BigInt(current);
1613
+ const denominator = BigInt(resource);
1614
+ return `${numerator * BigInt(100) / denominator}%`;
1615
+ };
1616
+ const formatMilicores = (value) => {
1617
+ return `${parseFloat(value.toString()) * 1e3}m`;
1618
+ };
1619
+ const podStatusToCpuUtil = (podStatus) => {
1620
+ const cpuUtil = podStatus.cpu;
1621
+ let currentUsage = cpuUtil.currentUsage;
1622
+ if (typeof cpuUtil.currentUsage === "number") {
1623
+ currentUsage = cpuUtil.currentUsage / 10;
1624
+ }
1625
+ return /* @__PURE__ */ React__default.createElement(
1626
+ SubvalueCell,
1627
+ {
1628
+ value: `requests: ${currentToDeclaredResourceToPerc(
1629
+ currentUsage,
1630
+ cpuUtil.requestTotal
1631
+ )} of ${formatMilicores(cpuUtil.requestTotal)}`,
1632
+ subvalue: `limits: ${currentToDeclaredResourceToPerc(
1633
+ currentUsage,
1634
+ cpuUtil.limitTotal
1635
+ )} of ${formatMilicores(cpuUtil.limitTotal)}`
1636
+ }
1637
+ );
1638
+ };
1639
+ const bytesToMiB = (value) => {
1640
+ return `${parseFloat(value.toString()) / 1024 / 1024}MiB`;
1641
+ };
1642
+ const podStatusToMemoryUtil = (podStatus) => {
1643
+ const memUtil = podStatus.memory;
1644
+ return /* @__PURE__ */ React__default.createElement(
1645
+ SubvalueCell,
1646
+ {
1647
+ value: `requests: ${currentToDeclaredResourceToPerc(
1648
+ memUtil.currentUsage,
1649
+ memUtil.requestTotal
1650
+ )} of ${bytesToMiB(memUtil.requestTotal)}`,
1651
+ subvalue: `limits: ${currentToDeclaredResourceToPerc(
1652
+ memUtil.currentUsage,
1653
+ memUtil.limitTotal
1654
+ )} of ${bytesToMiB(memUtil.limitTotal)}`
1279
1655
  }
1280
1656
  );
1281
1657
  };
1282
1658
 
1283
1659
  const READY_COLUMNS = "READY";
1284
1660
  const RESOURCE_COLUMNS = "RESOURCE";
1285
- const DEFAULT_COLUMNS = [
1286
- {
1287
- title: "name",
1288
- highlight: true,
1289
- render: (pod) => /* @__PURE__ */ React__default.createElement(PodDrawer, { pod })
1290
- },
1291
- {
1292
- title: "phase",
1293
- render: (pod) => {
1294
- var _a, _b;
1295
- return (_b = (_a = pod.status) == null ? void 0 : _a.phase) != null ? _b : "unknown";
1296
- },
1297
- width: "auto"
1298
- },
1299
- {
1300
- title: "status",
1301
- render: containerStatuses
1302
- }
1303
- ];
1304
1661
  const READY = [
1305
1662
  {
1306
1663
  title: "containers ready",
@@ -1318,7 +1675,36 @@ const READY = [
1318
1675
  ];
1319
1676
  const PodsTable = ({ pods, extraColumns = [] }) => {
1320
1677
  const podNamesWithMetrics = useContext(PodNamesWithMetricsContext);
1321
- const columns = [...DEFAULT_COLUMNS];
1678
+ const cluster = useContext(ClusterContext);
1679
+ const defaultColumns = [
1680
+ {
1681
+ title: "name",
1682
+ highlight: true,
1683
+ render: (pod) => /* @__PURE__ */ React__default.createElement(
1684
+ PodDrawer,
1685
+ {
1686
+ podAndErrors: {
1687
+ pod,
1688
+ clusterName: cluster.name,
1689
+ errors: []
1690
+ }
1691
+ }
1692
+ )
1693
+ },
1694
+ {
1695
+ title: "phase",
1696
+ render: (pod) => {
1697
+ var _a, _b;
1698
+ return (_b = (_a = pod.status) == null ? void 0 : _a.phase) != null ? _b : "unknown";
1699
+ },
1700
+ width: "auto"
1701
+ },
1702
+ {
1703
+ title: "status",
1704
+ render: containerStatuses
1705
+ }
1706
+ ];
1707
+ const columns = [...defaultColumns];
1322
1708
  if (extraColumns.includes(READY_COLUMNS)) {
1323
1709
  columns.push(...READY);
1324
1710
  }
@@ -1376,7 +1762,7 @@ const DeploymentDrawer = ({
1376
1762
  var _a, _b, _c;
1377
1763
  const namespace = (_a = deployment.metadata) == null ? void 0 : _a.namespace;
1378
1764
  return /* @__PURE__ */ React__default.createElement(
1379
- KubernetesDrawer,
1765
+ KubernetesStructuredMetadataTableDrawer,
1380
1766
  {
1381
1767
  object: deployment,
1382
1768
  expanded,
@@ -1414,7 +1800,7 @@ const DeploymentDrawer = ({
1414
1800
  const HorizontalPodAutoscalerDrawer = (props) => {
1415
1801
  const { hpa, expanded, children } = props;
1416
1802
  return /* @__PURE__ */ React__default.createElement(
1417
- KubernetesDrawer,
1803
+ KubernetesStructuredMetadataTableDrawer,
1418
1804
  {
1419
1805
  kind: "HorizontalPodAutoscaler",
1420
1806
  object: hpa,
@@ -1580,7 +1966,7 @@ const StatefulSetDrawer = ({
1580
1966
  var _a, _b, _c;
1581
1967
  const namespace = (_a = statefulset.metadata) == null ? void 0 : _a.namespace;
1582
1968
  return /* @__PURE__ */ React__default.createElement(
1583
- KubernetesDrawer,
1969
+ KubernetesStructuredMetadataTableDrawer,
1584
1970
  {
1585
1971
  object: statefulset,
1586
1972
  expanded,
@@ -1729,7 +2115,7 @@ const IngressDrawer = ({
1729
2115
  }) => {
1730
2116
  var _a, _b;
1731
2117
  return /* @__PURE__ */ React__default.createElement(
1732
- KubernetesDrawer,
2118
+ KubernetesStructuredMetadataTableDrawer,
1733
2119
  {
1734
2120
  object: ingress,
1735
2121
  expanded,
@@ -1798,7 +2184,7 @@ const ServiceDrawer = ({
1798
2184
  }) => {
1799
2185
  var _a, _b;
1800
2186
  return /* @__PURE__ */ React__default.createElement(
1801
- KubernetesDrawer,
2187
+ KubernetesStructuredMetadataTableDrawer,
1802
2188
  {
1803
2189
  object: service,
1804
2190
  expanded,
@@ -1883,7 +2269,7 @@ const JobDrawer = ({
1883
2269
  }) => {
1884
2270
  var _a, _b;
1885
2271
  return /* @__PURE__ */ React__default.createElement(
1886
- KubernetesDrawer,
2272
+ KubernetesStructuredMetadataTableDrawer,
1887
2273
  {
1888
2274
  object: job,
1889
2275
  expanded,
@@ -1972,7 +2358,7 @@ const CronJobDrawer = ({
1972
2358
  var _a, _b, _c;
1973
2359
  const namespace = (_a = cronJob.metadata) == null ? void 0 : _a.namespace;
1974
2360
  return /* @__PURE__ */ React__default.createElement(
1975
- KubernetesDrawer,
2361
+ KubernetesStructuredMetadataTableDrawer,
1976
2362
  {
1977
2363
  object: cronJob,
1978
2364
  expanded,
@@ -2080,7 +2466,7 @@ const RolloutDrawer = ({
2080
2466
  }) => {
2081
2467
  var _a, _b;
2082
2468
  return /* @__PURE__ */ React__default.createElement(
2083
- KubernetesDrawer,
2469
+ KubernetesStructuredMetadataTableDrawer,
2084
2470
  {
2085
2471
  object: rollout,
2086
2472
  expanded,
@@ -2304,7 +2690,7 @@ const DefaultCustomResourceDrawer = ({
2304
2690
  var _a, _b;
2305
2691
  const capitalizedName = capitalize(customResourceName);
2306
2692
  return /* @__PURE__ */ React__default.createElement(
2307
- KubernetesDrawer,
2693
+ KubernetesStructuredMetadataTableDrawer,
2308
2694
  {
2309
2695
  object: customResource,
2310
2696
  expanded,
@@ -2494,13 +2880,13 @@ const KubernetesContent = ({
2494
2880
  const clustersWithErrors = (_a = kubernetesObjects == null ? void 0 : kubernetesObjects.items.filter((r) => r.errors.length > 0)) != null ? _a : [];
2495
2881
  const detectedErrors = kubernetesObjects !== void 0 ? detectErrors(kubernetesObjects) : /* @__PURE__ */ new Map();
2496
2882
  return /* @__PURE__ */ React__default.createElement(Page, { themeId: "tool" }, /* @__PURE__ */ React__default.createElement(Content, null, kubernetesObjects === void 0 && error === void 0 && /* @__PURE__ */ React__default.createElement(Progress, null), clustersWithErrors.length > 0 && /* @__PURE__ */ React__default.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(
2497
- ErrorPanel$1,
2883
+ ErrorPanel,
2498
2884
  {
2499
2885
  entityName: entity.metadata.name,
2500
2886
  clustersWithErrors
2501
2887
  }
2502
2888
  ))), error !== void 0 && /* @__PURE__ */ React__default.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(
2503
- ErrorPanel$1,
2889
+ ErrorPanel,
2504
2890
  {
2505
2891
  entityName: entity.metadata.name,
2506
2892
  errorMessage: error
@@ -2583,5 +2969,5 @@ var Router$1 = /*#__PURE__*/Object.freeze({
2583
2969
  Router: Router
2584
2970
  });
2585
2971
 
2586
- export { Cluster, ClusterContext, CronJobsAccordions, CustomResources, EntityKubernetesContent, ErrorPanel$1 as ErrorPanel, ErrorReporting, GoogleKubernetesAuthProvider, GroupedResponsesContext, HorizontalPodAutoscalerDrawer, IngressesAccordions, JobsAccordions, KubernetesAuthProviders, KubernetesBackendClient, KubernetesContent, KubernetesDrawer, PodDrawer, PodNamesWithErrorsContext, PodNamesWithMetricsContext, PodsTable, Router, ServerSideKubernetesAuthProvider, ServicesAccordions, clusterLinksFormatters, detectErrors, formatClusterLink, isKubernetesAvailable, kubernetesApiRef, kubernetesAuthProvidersApiRef, kubernetesPlugin, kubernetesPlugin as plugin, useCustomResources, useKubernetesObjects };
2972
+ export { Cluster, ClusterContext, CronJobsAccordions, CustomResources, EntityKubernetesContent, ErrorPanel, ErrorReporting, GoogleKubernetesAuthProvider, GroupedResponsesContext, HorizontalPodAutoscalerDrawer, IngressesAccordions, JobsAccordions, KubernetesAuthProviders, KubernetesBackendClient, KubernetesContent, KubernetesDrawer, KubernetesDrawerContent, KubernetesProxyClient, KubernetesStructuredMetadataTableDrawer, LinkErrorPanel, PodDrawer, PodNamesWithErrorsContext, PodNamesWithMetricsContext, PodsTable, Router, ServerSideKubernetesAuthProvider, ServicesAccordions, clusterLinksFormatters, detectErrors, formatClusterLink, isKubernetesAvailable, kubernetesApiRef, kubernetesAuthProvidersApiRef, kubernetesPlugin, kubernetesProxyApiRef, kubernetesPlugin as plugin, useCustomResources, useKubernetesObjects };
2587
2973
  //# sourceMappingURL=index.esm.js.map