@backstage/plugin-kubernetes 0.4.18 → 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,48 @@
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
+
14
+ ## 0.4.21
15
+
16
+ ### Patch Changes
17
+
18
+ - 3739d3f773: Implement support for formatting OpenShift dashboard url links
19
+ - Updated dependencies
20
+ - @backstage/plugin-kubernetes-common@0.1.6
21
+ - @backstage/core-plugin-api@0.2.1
22
+ - @backstage/core-components@0.7.5
23
+
24
+ ## 0.4.20
25
+
26
+ ### Patch Changes
27
+
28
+ - a125278b81: Refactor out the deprecated path and icon from RouteRefs
29
+ - Updated dependencies
30
+ - @backstage/catalog-model@0.9.7
31
+ - @backstage/plugin-catalog-react@0.6.4
32
+ - @backstage/core-components@0.7.4
33
+ - @backstage/core-plugin-api@0.2.0
34
+
35
+ ## 0.4.19
36
+
37
+ ### Patch Changes
38
+
39
+ - 9f3dd76bc7: fix: kubernetes plugin shall pass id token on get clusters request if possible
40
+ - Updated dependencies
41
+ - @backstage/core-components@0.7.3
42
+ - @backstage/theme@0.2.13
43
+ - @backstage/core-plugin-api@0.1.13
44
+ - @backstage/plugin-catalog-react@0.6.3
45
+
3
46
  ## 0.4.18
4
47
 
5
48
  ### 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';
@@ -54,9 +55,13 @@ class KubernetesBackendClient {
54
55
  return await this.postRequired(`/services/${requestBody.entity.metadata.name}`, requestBody);
55
56
  }
56
57
  async getClusters() {
58
+ const idToken = await this.identityApi.getIdToken();
57
59
  const url = `${await this.discoveryApi.getBaseUrl("kubernetes")}/clusters`;
58
60
  const response = await fetch(url, {
59
- method: "GET"
61
+ method: "GET",
62
+ headers: {
63
+ ...idToken && {Authorization: `Bearer ${idToken}`}
64
+ }
60
65
  });
61
66
  return (await this.handleResponse(response)).items;
62
67
  }
@@ -116,8 +121,7 @@ class KubernetesAuthProviders {
116
121
  }
117
122
 
118
123
  const rootCatalogKubernetesRouteRef = createRouteRef({
119
- path: "*",
120
- title: "Kubernetes"
124
+ id: "kubernetes"
121
125
  });
122
126
  const kubernetesPlugin = createPlugin({
123
127
  id: "kubernetes",
@@ -173,7 +177,7 @@ const ErrorPanel$1 = ({
173
177
  variant: "body2"
174
178
  }, "Errors: ", errorMessage));
175
179
 
176
- const columns$1 = [
180
+ const columns = [
177
181
  {
178
182
  title: "cluster",
179
183
  width: "15%",
@@ -244,7 +248,7 @@ const ErrorReporting = ({detectedErrors}) => {
244
248
  }, /* @__PURE__ */ React.createElement(ErrorEmptyState, null)) : /* @__PURE__ */ React.createElement(Table, {
245
249
  title: "Error Reporting",
246
250
  data: errors,
247
- columns: columns$1,
251
+ columns,
248
252
  options: {paging: true, search: false}
249
253
  }));
250
254
  };
@@ -273,6 +277,12 @@ const groupResponses = (fetchResponse) => {
273
277
  case "ingresses":
274
278
  prev.ingresses.push(...next.resources);
275
279
  break;
280
+ case "jobs":
281
+ prev.jobs.push(...next.resources);
282
+ break;
283
+ case "cronjobs":
284
+ prev.cronJobs.push(...next.resources);
285
+ break;
276
286
  case "customresources":
277
287
  prev.customResources.push(...next.resources);
278
288
  break;
@@ -286,6 +296,8 @@ const groupResponses = (fetchResponse) => {
286
296
  configMaps: [],
287
297
  horizontalPodAutoscalers: [],
288
298
  ingresses: [],
299
+ jobs: [],
300
+ cronJobs: [],
289
301
  customResources: []
290
302
  });
291
303
  };
@@ -579,6 +591,8 @@ const GroupedResponsesContext = React__default.createContext({
579
591
  configMaps: [],
580
592
  horizontalPodAutoscalers: [],
581
593
  ingresses: [],
594
+ jobs: [],
595
+ cronJobs: [],
582
596
  customResources: []
583
597
  });
584
598
 
@@ -586,51 +600,86 @@ const ClusterContext = React__default.createContext({
586
600
  name: ""
587
601
  });
588
602
 
589
- const kindMappings$1 = {
603
+ const kindMappings$2 = {
590
604
  deployment: "deployment",
591
605
  ingress: "ingress",
592
606
  service: "service",
593
607
  horizontalpodautoscaler: "deployment"
594
608
  };
595
609
  function standardFormatter(options) {
596
- var _a, _b;
610
+ var _a, _b, _c, _d;
597
611
  const result = new URL(options.dashboardUrl.href);
598
- const name = (_a = options.object.metadata) == null ? void 0 : _a.name;
599
- const namespace = (_b = options.object.metadata) == null ? void 0 : _b.namespace;
600
- const validKind = kindMappings$1[options.kind.toLocaleLowerCase("en-US")];
601
- if (namespace) {
602
- result.searchParams.set("namespace", namespace);
612
+ const name = encodeURIComponent((_b = (_a = options.object.metadata) == null ? void 0 : _a.name) != null ? _b : "");
613
+ const namespace = encodeURIComponent((_d = (_c = options.object.metadata) == null ? void 0 : _c.namespace) != null ? _d : "");
614
+ const validKind = kindMappings$2[options.kind.toLocaleLowerCase("en-US")];
615
+ if (!result.pathname.endsWith("/")) {
616
+ result.pathname += "/";
603
617
  }
604
618
  if (validKind && name && namespace) {
605
619
  result.hash = `/${validKind}/${namespace}/${name}`;
606
620
  } else if (namespace) {
607
621
  result.hash = "/workloads";
608
622
  }
623
+ if (namespace) {
624
+ result.hash += `?namespace=${namespace}`;
625
+ }
609
626
  return result;
610
627
  }
611
628
 
612
- const kindMappings = {
629
+ const kindMappings$1 = {
613
630
  deployment: "apps.deployment",
614
631
  ingress: "networking.k8s.io.ingress",
615
632
  service: "service",
616
633
  horizontalpodautoscaler: "autoscaling.horizontalpodautoscaler"
617
634
  };
618
635
  function rancherFormatter(options) {
619
- var _a, _b;
620
- const result = new URL(options.dashboardUrl.href);
621
- const name = (_a = options.object.metadata) == null ? void 0 : _a.name;
622
- const namespace = (_b = options.object.metadata) == null ? void 0 : _b.namespace;
623
- const validKind = kindMappings[options.kind.toLocaleLowerCase("en-US")];
636
+ var _a, _b, _c, _d;
637
+ const basePath = new URL(options.dashboardUrl.href);
638
+ const name = encodeURIComponent((_b = (_a = options.object.metadata) == null ? void 0 : _a.name) != null ? _b : "");
639
+ const namespace = encodeURIComponent((_d = (_c = options.object.metadata) == null ? void 0 : _c.namespace) != null ? _d : "");
640
+ const validKind = kindMappings$1[options.kind.toLocaleLowerCase("en-US")];
641
+ if (!basePath.pathname.endsWith("/")) {
642
+ basePath.pathname += "/";
643
+ }
644
+ let path = "";
624
645
  if (validKind && name && namespace) {
625
- result.pathname += `explorer/${validKind}/${namespace}/${name}`;
646
+ path = `explorer/${validKind}/${namespace}/${name}`;
626
647
  } else if (namespace) {
627
- result.pathname += "explorer/workload";
648
+ path = "explorer/workload";
628
649
  }
629
- return result;
650
+ return new URL(path, basePath);
630
651
  }
631
652
 
632
- function openshiftFormatter(_options) {
633
- throw new Error("OpenShift formatter is not yet implemented. Please, contribute!");
653
+ const kindMappings = {
654
+ deployment: "deployments",
655
+ ingress: "ingresses",
656
+ service: "services",
657
+ horizontalpodautoscaler: "horizontalpodautoscalers",
658
+ persistentvolume: "persistentvolumes"
659
+ };
660
+ function openshiftFormatter(options) {
661
+ var _a, _b, _c, _d;
662
+ const basePath = new URL(options.dashboardUrl.href);
663
+ const name = encodeURIComponent((_b = (_a = options.object.metadata) == null ? void 0 : _a.name) != null ? _b : "");
664
+ const namespace = encodeURIComponent((_d = (_c = options.object.metadata) == null ? void 0 : _c.namespace) != null ? _d : "");
665
+ const validKind = kindMappings[options.kind.toLocaleLowerCase("en-US")];
666
+ if (!basePath.pathname.endsWith("/")) {
667
+ basePath.pathname += "/";
668
+ }
669
+ let path = "";
670
+ if (namespace) {
671
+ if (name && validKind) {
672
+ path = `k8s/ns/${namespace}/${validKind}/${name}`;
673
+ } else {
674
+ path = `k8s/cluster/projects/${namespace}`;
675
+ }
676
+ } else if (validKind) {
677
+ path = `k8s/cluster/${validKind}`;
678
+ if (name) {
679
+ path += `/${name}`;
680
+ }
681
+ }
682
+ return new URL(path, basePath);
634
683
  }
635
684
 
636
685
  function aksFormatter(_options) {
@@ -672,7 +721,7 @@ function formatClusterLink(options) {
672
721
  object: options.object,
673
722
  kind: options.kind
674
723
  });
675
- return `${url.origin}${url.pathname}${url.hash}${url.search}`;
724
+ return url.toString();
676
725
  }
677
726
 
678
727
  const useDrawerStyles = makeStyles((theme) => createStyles({
@@ -874,7 +923,7 @@ const PodDrawer = ({
874
923
  });
875
924
  };
876
925
 
877
- const columns = [
926
+ const DEFAULT_COLUMNS = [
878
927
  {
879
928
  title: "name",
880
929
  highlight: true,
@@ -889,23 +938,12 @@ const columns = [
889
938
  return (_b = (_a = pod.status) == null ? void 0 : _a.phase) != null ? _b : "unknown";
890
939
  }
891
940
  },
892
- {
893
- title: "containers ready",
894
- align: "center",
895
- render: containersReady
896
- },
897
- {
898
- title: "total restarts",
899
- align: "center",
900
- render: totalRestarts,
901
- type: "numeric"
902
- },
903
941
  {
904
942
  title: "status",
905
943
  render: containerStatuses
906
944
  }
907
945
  ];
908
- const PodsTable = ({pods}) => {
946
+ const PodsTable = ({pods, extraColumns = []}) => {
909
947
  const tableStyle = {
910
948
  minWidth: "0",
911
949
  width: "100%"
@@ -915,7 +953,7 @@ const PodsTable = ({pods}) => {
915
953
  }, /* @__PURE__ */ React__default.createElement(Table, {
916
954
  options: {paging: true, search: false},
917
955
  data: pods,
918
- columns
956
+ columns: DEFAULT_COLUMNS.concat(extraColumns)
919
957
  }));
920
958
  };
921
959
 
@@ -1009,6 +1047,19 @@ const getMatchingHpa = (ownerName, ownerKind, hpas) => {
1009
1047
  });
1010
1048
  };
1011
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
+ ];
1012
1063
  const DeploymentSummary = ({
1013
1064
  deployment,
1014
1065
  numberOfCurrentPods,
@@ -1089,7 +1140,8 @@ const DeploymentAccordion = ({
1089
1140
  numberOfPodsWithErrors: podsWithErrors.length,
1090
1141
  hpa: matchingHpa
1091
1142
  })), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(PodsTable, {
1092
- pods: ownedPods
1143
+ pods: ownedPods,
1144
+ extraColumns: deploymentPodColumns
1093
1145
  })));
1094
1146
  };
1095
1147
  const DeploymentsAccordions = ({}) => {
@@ -1301,6 +1353,214 @@ const ServicesAccordions = ({}) => {
1301
1353
  }))));
1302
1354
  };
1303
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
+
1304
1564
  const RolloutDrawer = ({
1305
1565
  rollout,
1306
1566
  expanded
@@ -1715,7 +1975,9 @@ const Cluster = ({clusterObjects, podsWithErrors}) => {
1715
1975
  item: true
1716
1976
  }, /* @__PURE__ */ React__default.createElement(IngressesAccordions, null)), /* @__PURE__ */ React__default.createElement(Grid, {
1717
1977
  item: true
1718
- }, /* @__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))))))));
1719
1981
  };
1720
1982
 
1721
1983
  const KubernetesContent = ({entity}) => {
@@ -1805,7 +2067,7 @@ const Router = (_props) => {
1805
2067
  const kubernetesLabelSelectorQueryAnnotationValue = (_b = entity.metadata.annotations) == null ? void 0 : _b[KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION];
1806
2068
  if (kubernetesAnnotationValue || kubernetesLabelSelectorQueryAnnotationValue) {
1807
2069
  return /* @__PURE__ */ React__default.createElement(Routes, null, /* @__PURE__ */ React__default.createElement(Route, {
1808
- path: `/${rootCatalogKubernetesRouteRef.path}`,
2070
+ path: "/",
1809
2071
  element: /* @__PURE__ */ React__default.createElement(KubernetesContent, {
1810
2072
  entity
1811
2073
  })