@backstage/plugin-kubernetes 0.4.21 → 0.4.22

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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @backstage/plugin-kubernetes
2
2
 
3
+ ## 0.4.22
4
+
5
+ ### Patch Changes
6
+
7
+ - 86ed770308: Added accordions to display information on Jobs and CronJobs in the kubernetes plugin. Updated the PodsTable with fewer default columns and the ability to pass in additional ones depending on the use case.
8
+ - Updated dependencies
9
+ - @backstage/core-components@0.7.6
10
+ - @backstage/theme@0.2.14
11
+ - @backstage/core-plugin-api@0.2.2
12
+ - @backstage/plugin-kubernetes-common@0.1.7
13
+
3
14
  ## 0.4.21
4
15
 
5
16
  ### Patch Changes
package/dist/index.esm.js CHANGED
@@ -4,7 +4,7 @@ import React__default, { Fragment, useState, useEffect, useContext } from 'react
4
4
  import { useEntity } from '@backstage/plugin-catalog-react';
5
5
  import { Routes, Route } from 'react-router-dom';
6
6
  import { Typography, Chip, Grid, makeStyles, createStyles, Button, Drawer, IconButton, FormControlLabel, Switch, Accordion, AccordionSummary, AccordionDetails, Divider, Stepper, Step, StepLabel } from '@material-ui/core';
7
- import { WarningPanel, InfoCard, Table, SubvalueCell, StatusError, StatusOK, StatusAborted, Button as Button$1, CodeSnippet, StructuredMetadataTable, Page, Content, Progress, MissingAnnotationEmptyState } from '@backstage/core-components';
7
+ import { WarningPanel, InfoCard, Table, SubvalueCell, StatusError, StatusOK, StatusAborted, Button as Button$1, CodeSnippet, StructuredMetadataTable, StatusPending, Page, Content, Progress, MissingAnnotationEmptyState } from '@backstage/core-components';
8
8
  import EmptyStateImage from './assets/emptystate.svg';
9
9
  import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
10
10
  import Close from '@material-ui/icons/Close';
@@ -12,6 +12,7 @@ import OpenInNewIcon from '@material-ui/icons/OpenInNew';
12
12
  import { withStyles } from '@material-ui/core/styles';
13
13
  import jsYaml from 'js-yaml';
14
14
  import { useInterval } from 'react-use';
15
+ import cronstrue from 'cronstrue';
15
16
  import lodash from 'lodash';
16
17
  import PauseIcon from '@material-ui/icons/Pause';
17
18
  import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
@@ -176,7 +177,7 @@ const ErrorPanel$1 = ({
176
177
  variant: "body2"
177
178
  }, "Errors: ", errorMessage));
178
179
 
179
- const columns$1 = [
180
+ const columns = [
180
181
  {
181
182
  title: "cluster",
182
183
  width: "15%",
@@ -247,7 +248,7 @@ const ErrorReporting = ({detectedErrors}) => {
247
248
  }, /* @__PURE__ */ React.createElement(ErrorEmptyState, null)) : /* @__PURE__ */ React.createElement(Table, {
248
249
  title: "Error Reporting",
249
250
  data: errors,
250
- columns: columns$1,
251
+ columns,
251
252
  options: {paging: true, search: false}
252
253
  }));
253
254
  };
@@ -276,6 +277,12 @@ const groupResponses = (fetchResponse) => {
276
277
  case "ingresses":
277
278
  prev.ingresses.push(...next.resources);
278
279
  break;
280
+ case "jobs":
281
+ prev.jobs.push(...next.resources);
282
+ break;
283
+ case "cronjobs":
284
+ prev.cronJobs.push(...next.resources);
285
+ break;
279
286
  case "customresources":
280
287
  prev.customResources.push(...next.resources);
281
288
  break;
@@ -289,6 +296,8 @@ const groupResponses = (fetchResponse) => {
289
296
  configMaps: [],
290
297
  horizontalPodAutoscalers: [],
291
298
  ingresses: [],
299
+ jobs: [],
300
+ cronJobs: [],
292
301
  customResources: []
293
302
  });
294
303
  };
@@ -582,6 +591,8 @@ const GroupedResponsesContext = React__default.createContext({
582
591
  configMaps: [],
583
592
  horizontalPodAutoscalers: [],
584
593
  ingresses: [],
594
+ jobs: [],
595
+ cronJobs: [],
585
596
  customResources: []
586
597
  });
587
598
 
@@ -912,7 +923,7 @@ const PodDrawer = ({
912
923
  });
913
924
  };
914
925
 
915
- const columns = [
926
+ const DEFAULT_COLUMNS = [
916
927
  {
917
928
  title: "name",
918
929
  highlight: true,
@@ -927,23 +938,12 @@ const columns = [
927
938
  return (_b = (_a = pod.status) == null ? void 0 : _a.phase) != null ? _b : "unknown";
928
939
  }
929
940
  },
930
- {
931
- title: "containers ready",
932
- align: "center",
933
- render: containersReady
934
- },
935
- {
936
- title: "total restarts",
937
- align: "center",
938
- render: totalRestarts,
939
- type: "numeric"
940
- },
941
941
  {
942
942
  title: "status",
943
943
  render: containerStatuses
944
944
  }
945
945
  ];
946
- const PodsTable = ({pods}) => {
946
+ const PodsTable = ({pods, extraColumns = []}) => {
947
947
  const tableStyle = {
948
948
  minWidth: "0",
949
949
  width: "100%"
@@ -953,7 +953,7 @@ const PodsTable = ({pods}) => {
953
953
  }, /* @__PURE__ */ React__default.createElement(Table, {
954
954
  options: {paging: true, search: false},
955
955
  data: pods,
956
- columns
956
+ columns: DEFAULT_COLUMNS.concat(extraColumns)
957
957
  }));
958
958
  };
959
959
 
@@ -1047,6 +1047,19 @@ const getMatchingHpa = (ownerName, ownerKind, hpas) => {
1047
1047
  });
1048
1048
  };
1049
1049
 
1050
+ const deploymentPodColumns = [
1051
+ {
1052
+ title: "containers ready",
1053
+ align: "center",
1054
+ render: containersReady
1055
+ },
1056
+ {
1057
+ title: "total restarts",
1058
+ align: "center",
1059
+ render: totalRestarts,
1060
+ type: "numeric"
1061
+ }
1062
+ ];
1050
1063
  const DeploymentSummary = ({
1051
1064
  deployment,
1052
1065
  numberOfCurrentPods,
@@ -1127,7 +1140,8 @@ const DeploymentAccordion = ({
1127
1140
  numberOfPodsWithErrors: podsWithErrors.length,
1128
1141
  hpa: matchingHpa
1129
1142
  })), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(PodsTable, {
1130
- pods: ownedPods
1143
+ pods: ownedPods,
1144
+ extraColumns: deploymentPodColumns
1131
1145
  })));
1132
1146
  };
1133
1147
  const DeploymentsAccordions = ({}) => {
@@ -1339,6 +1353,214 @@ const ServicesAccordions = ({}) => {
1339
1353
  }))));
1340
1354
  };
1341
1355
 
1356
+ const JobDrawer = ({
1357
+ job,
1358
+ expanded
1359
+ }) => {
1360
+ var _a, _b;
1361
+ return /* @__PURE__ */ React__default.createElement(KubernetesDrawer, {
1362
+ object: job,
1363
+ expanded,
1364
+ kind: "Job",
1365
+ renderObject: (jobObj) => {
1366
+ var _a2, _b2, _c, _d, _e, _f, _g, _h;
1367
+ return {
1368
+ parallelism: (_b2 = (_a2 = jobObj.spec) == null ? void 0 : _a2.parallelism) != null ? _b2 : "???",
1369
+ completions: (_d = (_c = jobObj.spec) == null ? void 0 : _c.completions) != null ? _d : "???",
1370
+ backoffLimit: (_f = (_e = jobObj.spec) == null ? void 0 : _e.backoffLimit) != null ? _f : "???",
1371
+ startTime: (_h = (_g = jobObj.status) == null ? void 0 : _g.startTime) != null ? _h : "???"
1372
+ };
1373
+ }
1374
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1375
+ container: true,
1376
+ direction: "column",
1377
+ justifyContent: "flex-start",
1378
+ alignItems: "flex-start",
1379
+ spacing: 0
1380
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1381
+ item: true
1382
+ }, /* @__PURE__ */ React__default.createElement(Typography, {
1383
+ variant: "h6"
1384
+ }, (_b = (_a = job.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown object")), /* @__PURE__ */ React__default.createElement(Grid, {
1385
+ item: true
1386
+ }, /* @__PURE__ */ React__default.createElement(Typography, {
1387
+ color: "textSecondary",
1388
+ variant: "body1"
1389
+ }, "Job"))));
1390
+ };
1391
+
1392
+ const JobSummary = ({job}) => {
1393
+ var _a, _b, _c, _d, _e, _f;
1394
+ return /* @__PURE__ */ React__default.createElement(Grid, {
1395
+ container: true,
1396
+ direction: "row",
1397
+ justifyContent: "flex-start",
1398
+ alignItems: "center"
1399
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1400
+ xs: 3,
1401
+ item: true
1402
+ }, /* @__PURE__ */ React__default.createElement(JobDrawer, {
1403
+ job
1404
+ })), /* @__PURE__ */ React__default.createElement(Grid, {
1405
+ item: true,
1406
+ xs: 1
1407
+ }, /* @__PURE__ */ React__default.createElement(Divider, {
1408
+ style: {height: "5em"},
1409
+ orientation: "vertical"
1410
+ })), /* @__PURE__ */ React__default.createElement(Grid, {
1411
+ item: true,
1412
+ container: true,
1413
+ xs: 8,
1414
+ direction: "column",
1415
+ justifyContent: "flex-start",
1416
+ alignItems: "flex-start"
1417
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1418
+ item: true
1419
+ }, ((_a = job.status) == null ? void 0 : _a.succeeded) && /* @__PURE__ */ React__default.createElement(StatusOK, null, "Succeeded"), ((_b = job.status) == null ? void 0 : _b.active) && /* @__PURE__ */ React__default.createElement(StatusPending, null, "Running"), ((_c = job.status) == null ? void 0 : _c.failed) && /* @__PURE__ */ React__default.createElement(StatusError, null, "Failed")), /* @__PURE__ */ React__default.createElement(Grid, {
1420
+ item: true
1421
+ }, "Start time: ", (_e = (_d = job.status) == null ? void 0 : _d.startTime) == null ? void 0 : _e.toString()), ((_f = job.status) == null ? void 0 : _f.completionTime) && /* @__PURE__ */ React__default.createElement(Grid, {
1422
+ item: true
1423
+ }, "Completion time: ", job.status.completionTime.toString())));
1424
+ };
1425
+ const JobAccordion = ({job, ownedPods}) => {
1426
+ return /* @__PURE__ */ React__default.createElement(Accordion, {
1427
+ TransitionProps: {unmountOnExit: true}
1428
+ }, /* @__PURE__ */ React__default.createElement(AccordionSummary, {
1429
+ expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null)
1430
+ }, /* @__PURE__ */ React__default.createElement(JobSummary, {
1431
+ job
1432
+ })), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(PodsTable, {
1433
+ pods: ownedPods
1434
+ })));
1435
+ };
1436
+ const JobsAccordions = ({jobs}) => {
1437
+ const groupedResponses = useContext(GroupedResponsesContext);
1438
+ return /* @__PURE__ */ React__default.createElement(Grid, {
1439
+ container: true,
1440
+ direction: "column",
1441
+ justifyContent: "flex-start",
1442
+ alignItems: "flex-start"
1443
+ }, jobs.map((job, i) => /* @__PURE__ */ React__default.createElement(Grid, {
1444
+ container: true,
1445
+ item: true,
1446
+ key: i,
1447
+ xs: true
1448
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1449
+ item: true,
1450
+ xs: true
1451
+ }, /* @__PURE__ */ React__default.createElement(JobAccordion, {
1452
+ ownedPods: getOwnedResources(job, groupedResponses.pods),
1453
+ job
1454
+ })))));
1455
+ };
1456
+
1457
+ const CronJobDrawer = ({
1458
+ cronJob,
1459
+ expanded
1460
+ }) => {
1461
+ var _a, _b, _c;
1462
+ const namespace = (_a = cronJob.metadata) == null ? void 0 : _a.namespace;
1463
+ return /* @__PURE__ */ React__default.createElement(KubernetesDrawer, {
1464
+ object: cronJob,
1465
+ expanded,
1466
+ kind: "CronJob",
1467
+ renderObject: (cronJobObj) => {
1468
+ var _a2, _b2, _c2, _d, _e, _f, _g, _h;
1469
+ return {
1470
+ schedule: (_b2 = (_a2 = cronJobObj.spec) == null ? void 0 : _a2.schedule) != null ? _b2 : "???",
1471
+ startingDeadlineSeconds: (_d = (_c2 = cronJobObj.spec) == null ? void 0 : _c2.startingDeadlineSeconds) != null ? _d : "???",
1472
+ concurrencyPolicy: (_f = (_e = cronJobObj.spec) == null ? void 0 : _e.concurrencyPolicy) != null ? _f : "???",
1473
+ lastScheduleTime: (_h = (_g = cronJobObj.status) == null ? void 0 : _g.lastScheduleTime) != null ? _h : "???"
1474
+ };
1475
+ }
1476
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1477
+ container: true,
1478
+ direction: "column",
1479
+ justifyContent: "flex-start",
1480
+ alignItems: "flex-start",
1481
+ spacing: 0
1482
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1483
+ item: true
1484
+ }, /* @__PURE__ */ React__default.createElement(Typography, {
1485
+ variant: "h5"
1486
+ }, (_c = (_b = cronJob.metadata) == null ? void 0 : _b.name) != null ? _c : "unknown object")), /* @__PURE__ */ React__default.createElement(Grid, {
1487
+ item: true
1488
+ }, /* @__PURE__ */ React__default.createElement(Typography, {
1489
+ color: "textSecondary",
1490
+ variant: "body1"
1491
+ }, "CronJob")), namespace && /* @__PURE__ */ React__default.createElement(Grid, {
1492
+ item: true
1493
+ }, /* @__PURE__ */ React__default.createElement(Chip, {
1494
+ size: "small",
1495
+ label: `namespace: ${namespace}`
1496
+ }))));
1497
+ };
1498
+
1499
+ const CronJobSummary = ({cronJob}) => {
1500
+ var _a, _b;
1501
+ return /* @__PURE__ */ React__default.createElement(Grid, {
1502
+ container: true,
1503
+ direction: "row",
1504
+ justifyContent: "flex-start",
1505
+ alignItems: "center"
1506
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1507
+ xs: 3,
1508
+ item: true
1509
+ }, /* @__PURE__ */ React__default.createElement(CronJobDrawer, {
1510
+ cronJob
1511
+ })), /* @__PURE__ */ React__default.createElement(Grid, {
1512
+ item: true,
1513
+ xs: 1
1514
+ }, /* @__PURE__ */ React__default.createElement(Divider, {
1515
+ style: {height: "5em"},
1516
+ orientation: "vertical"
1517
+ })), /* @__PURE__ */ React__default.createElement(Grid, {
1518
+ item: true,
1519
+ container: true,
1520
+ xs: 5,
1521
+ direction: "column",
1522
+ justifyContent: "flex-start",
1523
+ alignItems: "flex-start"
1524
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1525
+ item: true
1526
+ }, ((_a = cronJob.spec) == null ? void 0 : _a.suspend) ? /* @__PURE__ */ React__default.createElement(StatusError, null, "Suspended") : /* @__PURE__ */ React__default.createElement(StatusOK, null, "Active")), /* @__PURE__ */ React__default.createElement(Grid, {
1527
+ item: true
1528
+ }, /* @__PURE__ */ React__default.createElement(Typography, {
1529
+ variant: "body1"
1530
+ }, "Schedule:", " ", ((_b = cronJob.spec) == null ? void 0 : _b.schedule) ? `${cronJob.spec.schedule} (${cronstrue.toString(cronJob.spec.schedule)})` : "N/A"))));
1531
+ };
1532
+ const CronJobAccordion = ({cronJob, ownedJobs}) => {
1533
+ return /* @__PURE__ */ React__default.createElement(Accordion, {
1534
+ TransitionProps: {unmountOnExit: true}
1535
+ }, /* @__PURE__ */ React__default.createElement(AccordionSummary, {
1536
+ expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null)
1537
+ }, /* @__PURE__ */ React__default.createElement(CronJobSummary, {
1538
+ cronJob
1539
+ })), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(JobsAccordions, {
1540
+ jobs: ownedJobs.reverse()
1541
+ })));
1542
+ };
1543
+ const CronJobsAccordions = ({}) => {
1544
+ const groupedResponses = useContext(GroupedResponsesContext);
1545
+ return /* @__PURE__ */ React__default.createElement(Grid, {
1546
+ container: true,
1547
+ direction: "column",
1548
+ justifyContent: "flex-start",
1549
+ alignItems: "flex-start"
1550
+ }, groupedResponses.cronJobs.map((cronJob, i) => /* @__PURE__ */ React__default.createElement(Grid, {
1551
+ container: true,
1552
+ item: true,
1553
+ key: i,
1554
+ xs: true
1555
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1556
+ item: true,
1557
+ xs: true
1558
+ }, /* @__PURE__ */ React__default.createElement(CronJobAccordion, {
1559
+ ownedJobs: getOwnedResources(cronJob, groupedResponses.jobs),
1560
+ cronJob
1561
+ })))));
1562
+ };
1563
+
1342
1564
  const RolloutDrawer = ({
1343
1565
  rollout,
1344
1566
  expanded
@@ -1753,7 +1975,9 @@ const Cluster = ({clusterObjects, podsWithErrors}) => {
1753
1975
  item: true
1754
1976
  }, /* @__PURE__ */ React__default.createElement(IngressesAccordions, null)), /* @__PURE__ */ React__default.createElement(Grid, {
1755
1977
  item: true
1756
- }, /* @__PURE__ */ React__default.createElement(ServicesAccordions, null))))))));
1978
+ }, /* @__PURE__ */ React__default.createElement(ServicesAccordions, null)), /* @__PURE__ */ React__default.createElement(Grid, {
1979
+ item: true
1980
+ }, /* @__PURE__ */ React__default.createElement(CronJobsAccordions, null))))))));
1757
1981
  };
1758
1982
 
1759
1983
  const KubernetesContent = ({entity}) => {