diff --git a/package.json b/package.json index dd30eced22..9351ba701a 100644 --- a/package.json +++ b/package.json @@ -393,7 +393,7 @@ "ts-jest": "26.5.6", "ts-loader": "^9.2.6", "ts-node": "^10.7.0", - "type-fest": "^1.4.0", + "type-fest": "^2.12.0", "typed-emitter": "^1.4.0", "typedoc": "0.22.10", "typedoc-plugin-markdown": "^3.11.12", diff --git a/src/renderer/components/+pod-security-policies/pod-security-policy-details.tsx b/src/renderer/components/+pod-security-policies/pod-security-policy-details.tsx index 51ff9f4872..3a0bf5fe0f 100644 --- a/src/renderer/components/+pod-security-policies/pod-security-policy-details.tsx +++ b/src/renderer/components/+pod-security-policies/pod-security-policy-details.tsx @@ -28,26 +28,23 @@ interface RuleGroup { @observer export class PodSecurityPolicyDetails extends React.Component { - renderRuleGroup( title: React.ReactNode, group: RuleGroup) { - if (!group) return null; - const { rule, ranges } = group; - - return ( - <> - - - {rule} + renderRuleGroup = (title: React.ReactNode, { rule, ranges }: RuleGroup) => ( + <> + {title} + + {rule} + + {ranges && ( + + {ranges.map(({ min, max }, index) => ( + + ))} - {ranges && ( - - {ranges.map(({ min, max }, index) => { - return ; - })} - - )} - - ); - } + )} + + ); render() { const { object: psp } = this.props; @@ -179,10 +176,10 @@ export class PodSecurityPolicyDetails extends React.Component )} - {this.renderRuleGroup("Fs Group", fsGroup)} - {this.renderRuleGroup("Run As Group", runAsGroup)} - {this.renderRuleGroup("Run As User", runAsUser)} - {this.renderRuleGroup("Supplemental Groups", supplementalGroups)} + {fsGroup && this.renderRuleGroup("Fs Group", fsGroup)} + {runAsGroup && this.renderRuleGroup("Run As Group", runAsGroup)} + {runAsUser && this.renderRuleGroup("Run As User", runAsUser)} + {supplementalGroups && this.renderRuleGroup("Supplemental Groups", supplementalGroups)} {runtimeClass && ( <> diff --git a/src/renderer/components/+workloads-pods/pod-details-volumes.tsx b/src/renderer/components/+workloads-pods/pod-details-volumes.tsx index d52898cdd5..fd1cafc15c 100644 --- a/src/renderer/components/+workloads-pods/pod-details-volumes.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-volumes.tsx @@ -7,9 +7,11 @@ import jsyaml from "js-yaml"; import { observer } from "mobx-react"; import React from "react"; import { Link } from "react-router-dom"; +import type { RequireAllOrNone } from "type-fest"; import { configMapApi, Pod, PodVolume, PodVolumeKind, PodVolumeVariants, pvcApi, SecretReference, secretsApi } from "../../../common/k8s-api/endpoints"; import type { KubeApi } from "../../../common/k8s-api/kube-api"; import type { KubeObject, LocalObjectReference } from "../../../common/k8s-api/kube-object"; +import { entries } from "../../utils"; import { DrawerItem, DrawerItemLabels, DrawerTitle } from "../drawer"; import { Icon } from "../icon"; import { getDetailsUrl } from "../kube-detail-params"; @@ -36,7 +38,7 @@ function renderLocalRef(pod: Pod, title: string, ref: LocalObjectReference | Sec * */ type PodVolumeVariantRenderers = { - [Key in keyof PodVolumeVariants]: (variant: PodVolumeVariants[Key], opts: VariantOptions) => React.ReactNode; + [Key in keyof PodVolumeVariants]: (variant: PodVolumeVariants[Key], opts: VariantOptions) => React.ReactChild; }; const volumeRenderers: PodVolumeVariantRenderers = { @@ -583,23 +585,28 @@ const deprecatedVolumeTypes = new Set([ "storageos", ]); -function getVolumeType(volume: PodVolume): PodVolumeKind | undefined { - const keys = new Set(Object.keys(volume)); +interface VolumeRendererPair { + kind: PodVolumeKind; + render: () => React.ReactChild; +} - keys.delete("name"); // This key is not a kind field - - for (const key of keys) { - // skip other random keys - if (key in volumeRenderers) { - const kind = key as PodVolumeKind; - - if (volume[kind] && typeof volume[kind] === "object") { - return kind; - } +function getVolumeType(pod: Pod, volume: PodVolume): RequireAllOrNone { + for (const [kind, varient] of entries(volume)) { + if (kind === "name") { + continue; // This key is not a kind field } + + if (!varient || typeof varient !== "object") { + continue; + } + + return { + kind, + render: () => volumeRenderers[kind](varient as never, { pod, volumeName: volume.name }), + }; } - return undefined; + return {}; } export const PodVolumes = observer(({ pod }: PodVolumesProps) => { @@ -608,9 +615,10 @@ export const PodVolumes = observer(({ pod }: PodVolumesProps) => { } const renderVolume = (volume: PodVolume) => { - const type = getVolumeType(volume); - const isDeprecated = deprecatedVolumeTypes.has(type); - const renderVolume = volumeRenderers[type]; + const { kind, render } = getVolumeType(pod, volume); + const isDeprecated = deprecatedVolumeTypes.has(kind); + + console.log(volume, render); return (
@@ -619,23 +627,17 @@ export const PodVolumes = observer(({ pod }: PodVolumesProps) => { {volume.name}
{ - renderVolume + kind ? ( <> - - {type} + + {kind} {isDeprecated && } - {renderVolume(volume[type] as any, { pod, volumeName: volume.name })} + {render?.()} ) - : type - ? ( - - {type} - - ) - :

Error! Unknown pod volume kind

+ :

Error! Unknown pod volume kind

} ); diff --git a/src/renderer/components/+workloads-pods/pod-details.tsx b/src/renderer/components/+workloads-pods/pod-details.tsx index 7ff23d83da..6510fd90ff 100644 --- a/src/renderer/components/+workloads-pods/pod-details.tsx +++ b/src/renderer/components/+workloads-pods/pod-details.tsx @@ -11,7 +11,7 @@ import { disposeOnUnmount, observer } from "mobx-react"; import { Link } from "react-router-dom"; import { observable, reaction, makeObservable } from "mobx"; import { type IPodMetrics, nodesApi, Pod, getMetricsForPods } from "../../../common/k8s-api/endpoints"; -import { DrawerItem, DrawerSection } from "../drawer"; +import { DrawerItem, DrawerTitle } from "../drawer"; import { Badge } from "../badge"; import { boundMethod, cssNames, toJS } from "../../utils"; import { PodDetailsContainer } from "./pod-details-container"; @@ -79,6 +79,7 @@ export class PodDetails extends React.Component { const nodeSelector = pod.getNodeSelectors(); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Pod); const initContainers = pod.getInitContainers(); + const containers = pod.getContainers(); return (
@@ -138,22 +139,28 @@ export class PodDetails extends React.Component { - - - - { - pod.getContainers().map(container => ( + {initContainers.length > 0 && ( + <> + Init Containers + {initContainers.map(container => ( - )) - } - + ))} + + )} + + Containers + {containers.map(container => ( + + ))}
diff --git a/src/renderer/components/drawer/drawer-item.tsx b/src/renderer/components/drawer/drawer-item.tsx index 2656a635e2..1e0a50f8e4 100644 --- a/src/renderer/components/drawer/drawer-item.tsx +++ b/src/renderer/components/drawer/drawer-item.tsx @@ -7,29 +7,32 @@ import "./drawer-item.scss"; import React from "react"; import { cssNames, displayBooleans } from "../../utils"; -export interface DrawerItemProps extends React.HTMLAttributes { +export interface DrawerItemProps extends React.HTMLAttributes { name: React.ReactNode; - className?: string; title?: string; labelsOnly?: boolean; hidden?: boolean; renderBoolean?: boolean; // show "true" or "false" for all of the children elements are "typeof boolean" } -export class DrawerItem extends React.Component { - render() { - const { name, title, labelsOnly, children, hidden, className, renderBoolean, ...elemProps } = this.props; - - if (hidden) return null; - - const classNames = cssNames("DrawerItem", className, { labelsOnly }); - const content = displayBooleans(renderBoolean, children); - - return ( -
- {name} - {content} -
- ); +export function DrawerItem({ + name, + title, + labelsOnly, + children, + hidden, + className, + renderBoolean, + ...elemProps +}: DrawerItemProps) { + if (!hidden) { + return null; } + + return ( +
+ {name} + {displayBooleans(renderBoolean, children)} +
+ ); } diff --git a/yarn.lock b/yarn.lock index 4e84cd82cf..dcd7a22215 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13211,10 +13211,10 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-fest@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" - integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== +type-fest@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.0.tgz#ce342f58cab9114912f54b493d60ab39c3fc82b6" + integrity sha512-Qe5GRT+n/4GoqCNGGVp5Snapg1Omq3V7irBJB3EaKsp7HWDo5Gv2d/67gfNyV+d5EXD+x/RF5l1h4yJ7qNkcGA== type-is@~1.6.18: version "1.6.18"