diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json
index 0c78649cf7..a127c9edf6 100644
--- a/plugins/kubernetes/package.json
+++ b/plugins/kubernetes/package.json
@@ -42,6 +42,7 @@
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
+ "cronstrue": "^1.122.0",
"js-yaml": "^4.0.0",
"lodash": "^4.17.21",
"luxon": "^2.0.2",
diff --git a/plugins/kubernetes/src/components/Cluster/Cluster.tsx b/plugins/kubernetes/src/components/Cluster/Cluster.tsx
index d238396f53..416d6e23e3 100644
--- a/plugins/kubernetes/src/components/Cluster/Cluster.tsx
+++ b/plugins/kubernetes/src/components/Cluster/Cluster.tsx
@@ -29,6 +29,7 @@ import { DeploymentsAccordions } from '../DeploymentsAccordions';
import { groupResponses } from '../../utils/response';
import { IngressesAccordions } from '../IngressesAccordions';
import { ServicesAccordions } from '../ServicesAccordions';
+import { CronJobsAccordions } from '../CronJobsAccordions';
import { CustomResources } from '../CustomResources';
import {
ClusterContext,
@@ -133,6 +134,9 @@ export const Cluster = ({ clusterObjects, podsWithErrors }: ClusterProps) => {
+
+
+
diff --git a/plugins/kubernetes/src/components/CronJobsAccordions/CronJobsAccordions.tsx b/plugins/kubernetes/src/components/CronJobsAccordions/CronJobsAccordions.tsx
new file mode 100644
index 0000000000..992fa6c469
--- /dev/null
+++ b/plugins/kubernetes/src/components/CronJobsAccordions/CronJobsAccordions.tsx
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React, { useContext } from 'react';
+import {
+ Accordion,
+ AccordionDetails,
+ AccordionSummary,
+ Divider,
+ Grid,
+} from '@material-ui/core';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+import { V1CronJob, V1Job } from '@kubernetes/client-node';
+import { JobsAccordions } from '../JobsAccordions';
+import { CronJobDrawer } from './CronJobsDrawer';
+import { getOwnedResources } from '../../utils/owner';
+import { GroupedResponsesContext } from '../../hooks';
+import { StatusError, StatusOK } from '@backstage/core-components';
+import cronstrue from 'cronstrue';
+
+type CronJobsAccordionsProps = {
+ children?: React.ReactNode;
+};
+
+type CronJobAccordionProps = {
+ cronJob: V1CronJob;
+ ownedJobs: V1Job[];
+ children?: React.ReactNode;
+};
+
+type CronJobSummaryProps = {
+ cronJob: V1CronJob;
+ children?: React.ReactNode;
+};
+
+const CronJobSummary = ({ cronJob }: CronJobSummaryProps) => {
+ return (
+
+
+
+
+
+
+
+
+
+ {cronJob.spec?.suspend ? (
+ Suspended
+ ) : (
+ Active
+ )}
+
+
+ Schedule:{' '}
+ {cronJob.spec?.schedule
+ ? `${cronJob.spec.schedule} (
+ ${cronstrue.toString(cronJob.spec.schedule)})`
+ : '???'}
+
+
+
+ );
+};
+
+const CronJobAccordion = ({ cronJob, ownedJobs }: CronJobAccordionProps) => {
+ return (
+
+ }>
+
+
+
+
+
+
+ );
+};
+
+export const CronJobsAccordions = ({}: CronJobsAccordionsProps) => {
+ const groupedResponses = useContext(GroupedResponsesContext);
+
+ return (
+
+ {groupedResponses.cronJobs.map((cronJob, i) => (
+
+
+
+
+
+ ))}
+
+ );
+};
diff --git a/plugins/kubernetes/src/components/CronJobsAccordions/CronJobsDrawer.tsx b/plugins/kubernetes/src/components/CronJobsAccordions/CronJobsDrawer.tsx
new file mode 100644
index 0000000000..758f17ade0
--- /dev/null
+++ b/plugins/kubernetes/src/components/CronJobsAccordions/CronJobsDrawer.tsx
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react';
+import { V1CronJob } from '@kubernetes/client-node';
+import { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';
+import { Typography, Grid, Chip } from '@material-ui/core';
+
+export const CronJobDrawer = ({
+ cronJob,
+ expanded,
+}: {
+ cronJob: V1CronJob;
+ expanded?: boolean;
+}) => {
+ const namespace = cronJob.metadata?.namespace;
+ return (
+ ({
+ schedule: cronJobObj.spec?.schedule ?? '???',
+ startingDeadlineSeconds:
+ cronJobObj.spec?.startingDeadlineSeconds ?? '???',
+ concurrencyPolicy: cronJobObj.spec?.concurrencyPolicy ?? '???',
+ lastScheduleTime: cronJobObj.status?.lastScheduleTime ?? '???',
+ })}
+ >
+
+
+
+ {cronJob.metadata?.name ?? 'unknown object'}
+
+
+
+
+ CronJob
+
+
+ {namespace && (
+
+
+
+ )}
+
+
+ );
+};
diff --git a/plugins/kubernetes/src/components/CronJobsAccordions/index.ts b/plugins/kubernetes/src/components/CronJobsAccordions/index.ts
new file mode 100644
index 0000000000..e72e3f7e6d
--- /dev/null
+++ b/plugins/kubernetes/src/components/CronJobsAccordions/index.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export { CronJobsAccordions } from './CronJobsAccordions';
diff --git a/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx b/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx
index e27c2bfbe1..2fa140b5f7 100644
--- a/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx
+++ b/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx
@@ -36,11 +36,12 @@ import {
getOwnedPodsThroughReplicaSets,
getMatchingHpa,
} from '../../utils/owner';
+import { containersReady, totalRestarts } from '../../utils/pod';
import {
GroupedResponsesContext,
PodNamesWithErrorsContext,
} from '../../hooks';
-import { StatusError, StatusOK } from '@backstage/core-components';
+import { StatusError, StatusOK, TableColumn } from '@backstage/core-components';
type DeploymentsAccordionsProps = {
children?: React.ReactNode;
@@ -61,6 +62,20 @@ type DeploymentSummaryProps = {
children?: React.ReactNode;
};
+const deploymentPodColumns: TableColumn[] = [
+ {
+ title: 'containers ready',
+ align: 'center',
+ render: containersReady,
+ },
+ {
+ title: 'total restarts',
+ align: 'center',
+ render: totalRestarts,
+ type: 'numeric',
+ },
+];
+
const DeploymentSummary = ({
deployment,
numberOfCurrentPods,
@@ -161,7 +176,7 @@ const DeploymentAccordion = ({
/>
-
+
);
diff --git a/plugins/kubernetes/src/components/JobsAccordions/JobsAccordions.tsx b/plugins/kubernetes/src/components/JobsAccordions/JobsAccordions.tsx
new file mode 100644
index 0000000000..5c95dfbb6d
--- /dev/null
+++ b/plugins/kubernetes/src/components/JobsAccordions/JobsAccordions.tsx
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React, { useContext } from 'react';
+import {
+ Accordion,
+ AccordionDetails,
+ AccordionSummary,
+ Divider,
+ Grid,
+} from '@material-ui/core';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+import { V1Job, V1Pod } from '@kubernetes/client-node';
+import { PodsTable } from '../Pods';
+import { JobDrawer } from './JobsDrawer';
+import { getOwnedResources } from '../../utils/owner';
+import { GroupedResponsesContext } from '../../hooks';
+import {
+ StatusError,
+ StatusOK,
+ StatusPending,
+} from '@backstage/core-components';
+
+type JobsAccordionsProps = {
+ jobs: V1Job[];
+ children?: React.ReactNode;
+};
+
+type JobAccordionProps = {
+ job: V1Job;
+ ownedPods: V1Pod[];
+ children?: React.ReactNode;
+};
+
+type JobSummaryProps = {
+ job: V1Job;
+ children?: React.ReactNode;
+};
+
+const JobSummary = ({ job }: JobSummaryProps) => {
+ return (
+
+
+
+
+
+
+
+
+
+ {job.status?.succeeded && Succeeded}
+ {job.status?.active && Running}
+ {job.status?.failed && Failed}
+
+ Start time: {job.status?.startTime}
+ {job.status?.completionTime && (
+ Completion time: {job.status.completionTime}
+ )}
+
+
+ );
+};
+
+const JobAccordion = ({ job, ownedPods }: JobAccordionProps) => {
+ return (
+
+ }>
+
+
+
+
+
+
+ );
+};
+
+export const JobsAccordions = ({ jobs }: JobsAccordionsProps) => {
+ const groupedResponses = useContext(GroupedResponsesContext);
+
+ return (
+
+ {jobs.map((job, i) => (
+
+
+
+
+
+ ))}
+
+ );
+};
diff --git a/plugins/kubernetes/src/components/JobsAccordions/JobsDrawer.tsx b/plugins/kubernetes/src/components/JobsAccordions/JobsDrawer.tsx
new file mode 100644
index 0000000000..d81e099acc
--- /dev/null
+++ b/plugins/kubernetes/src/components/JobsAccordions/JobsDrawer.tsx
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react';
+import { V1Job } from '@kubernetes/client-node';
+import { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';
+import { Typography, Grid } from '@material-ui/core';
+
+export const JobDrawer = ({
+ job,
+ expanded,
+}: {
+ job: V1Job;
+ expanded?: boolean;
+}) => {
+ return (
+ {
+ return {
+ parallelism: jobObj.spec?.parallelism ?? '???',
+ completions: jobObj.spec?.completions ?? '???',
+ backOffLimit: jobObj.spec?.backoffLimit ?? '???',
+ startTime: jobObj.status?.startTime ?? '???',
+ };
+ }}
+ >
+
+
+
+ {job.metadata?.name ?? 'unknown object'}
+
+
+
+
+ Job
+
+
+
+
+ );
+};
diff --git a/plugins/kubernetes/src/components/JobsAccordions/index.ts b/plugins/kubernetes/src/components/JobsAccordions/index.ts
new file mode 100644
index 0000000000..392309de79
--- /dev/null
+++ b/plugins/kubernetes/src/components/JobsAccordions/index.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export { JobsAccordions } from './JobsAccordions';
diff --git a/plugins/kubernetes/src/components/Pods/PodsTable.tsx b/plugins/kubernetes/src/components/Pods/PodsTable.tsx
index 7b5497ff37..8ce5f813b3 100644
--- a/plugins/kubernetes/src/components/Pods/PodsTable.tsx
+++ b/plugins/kubernetes/src/components/Pods/PodsTable.tsx
@@ -17,14 +17,10 @@
import React from 'react';
import { V1Pod } from '@kubernetes/client-node';
import { PodDrawer } from './PodDrawer';
-import {
- containersReady,
- containerStatuses,
- totalRestarts,
-} from '../../utils/pod';
+import { containerStatuses } from '../../utils/pod';
import { Table, TableColumn } from '@backstage/core-components';
-const columns: TableColumn[] = [
+const DEFAULT_COLUMNS: TableColumn[] = [
{
title: 'name',
highlight: true,
@@ -34,29 +30,19 @@ const columns: TableColumn[] = [
title: 'phase',
render: (pod: V1Pod) => pod.status?.phase ?? 'unknown',
},
- {
- title: 'containers ready',
- align: 'center',
- render: containersReady,
- },
- {
- title: 'total restarts',
- align: 'center',
- render: totalRestarts,
- type: 'numeric',
- },
{
title: 'status',
render: containerStatuses,
},
];
-type DeploymentTablesProps = {
+type PodsTablesProps = {
pods: V1Pod[];
+ extraColumns?: TableColumn[];
children?: React.ReactNode;
};
-export const PodsTable = ({ pods }: DeploymentTablesProps) => {
+export const PodsTable = ({ pods, extraColumns = [] }: PodsTablesProps) => {
const tableStyle = {
minWidth: '0',
width: '100%',
@@ -67,7 +53,7 @@ export const PodsTable = ({ pods }: DeploymentTablesProps) => {
);
diff --git a/plugins/kubernetes/src/hooks/GroupedResponses.ts b/plugins/kubernetes/src/hooks/GroupedResponses.ts
index d000086b7c..35f7e10b5c 100644
--- a/plugins/kubernetes/src/hooks/GroupedResponses.ts
+++ b/plugins/kubernetes/src/hooks/GroupedResponses.ts
@@ -24,5 +24,7 @@ export const GroupedResponsesContext = React.createContext({
configMaps: [],
horizontalPodAutoscalers: [],
ingresses: [],
+ jobs: [],
+ cronJobs: [],
customResources: [],
});
diff --git a/plugins/kubernetes/src/types/types.ts b/plugins/kubernetes/src/types/types.ts
index 05337086be..d6df99cb95 100644
--- a/plugins/kubernetes/src/types/types.ts
+++ b/plugins/kubernetes/src/types/types.ts
@@ -22,6 +22,8 @@ import {
V1Service,
V1ConfigMap,
ExtensionsV1beta1Ingress,
+ V1Job,
+ V1CronJob,
} from '@kubernetes/client-node';
export interface DeploymentResources {
@@ -35,6 +37,8 @@ export interface GroupedResponses extends DeploymentResources {
services: V1Service[];
configMaps: V1ConfigMap[];
ingresses: ExtensionsV1beta1Ingress[];
+ jobs: V1Job[];
+ cronJobs: V1CronJob[];
customResources: any[];
}
diff --git a/plugins/kubernetes/src/utils/response.ts b/plugins/kubernetes/src/utils/response.ts
index 97501bb102..cfe3d20580 100644
--- a/plugins/kubernetes/src/utils/response.ts
+++ b/plugins/kubernetes/src/utils/response.ts
@@ -45,6 +45,12 @@ export const groupResponses = (
case 'ingresses':
prev.ingresses.push(...next.resources);
break;
+ case 'jobs':
+ prev.jobs.push(...next.resources);
+ break;
+ case 'cronjobs':
+ prev.cronJobs.push(...next.resources);
+ break;
case 'customresources':
prev.customResources.push(...next.resources);
break;
@@ -60,6 +66,8 @@ export const groupResponses = (
configMaps: [],
horizontalPodAutoscalers: [],
ingresses: [],
+ jobs: [],
+ cronJobs: [],
customResources: [],
} as GroupedResponses,
);
diff --git a/yarn.lock b/yarn.lock
index 1628c2eea1..8f92fd2316 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11978,6 +11978,11 @@ create-require@^1.1.0:
resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
+cronstrue@^1.122.0:
+ version "1.122.0"
+ resolved "https://registry.npmjs.org/cronstrue/-/cronstrue-1.122.0.tgz#bd6838077b476d28f61d381398b47b8c3912a126"
+ integrity sha512-PFuhZd+iPQQ0AWTXIEYX+t3nFGzBrWxmTWUKJOrsGRewaBSLKZ4I1f8s2kryU75nNxgyugZgiGh2OJsCTA/XlA==
+
cross-env@^7.0.0:
version "7.0.3"
resolved "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"