mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
659 lines
19 KiB
TypeScript
659 lines
19 KiB
TypeScript
/**
|
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
*/
|
|
|
|
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";
|
|
|
|
/**
|
|
* Additional parameters for each volume variant
|
|
*/
|
|
export interface VariantOptions {
|
|
pod: Pod;
|
|
volumeName: string;
|
|
}
|
|
|
|
function renderLocalRef(pod: Pod, title: string, ref: LocalObjectReference | SecretReference, typeApi: KubeApi<KubeObject>) {
|
|
return (
|
|
<DrawerItem name={title}>
|
|
<Link to={getDetailsUrl(typeApi.getUrl({ namespace: pod.getNs(), ...ref }))}>
|
|
{ref.name}
|
|
</Link>
|
|
</DrawerItem>
|
|
);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
type PodVolumeVariantRenderers = {
|
|
[Key in keyof PodVolumeVariants]: (variant: PodVolumeVariants[Key], opts: VariantOptions) => React.ReactChild;
|
|
};
|
|
|
|
const volumeRenderers: PodVolumeVariantRenderers = {
|
|
awsElasticBlockStore: ({ volumeID, fsType = "ext4" }) => (
|
|
<>
|
|
<DrawerItem name="Volume ID">
|
|
{volumeID}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem Type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
azureDisk: ({ diskName, diskURI, kind = "Shared", cachingMode = "None", fsType = "ext4", readonly = false }) => (
|
|
<>
|
|
<DrawerItem name={kind === "Managed" ? "Disk Name" : "VHD blob Name"}>
|
|
{diskName}
|
|
</DrawerItem>
|
|
<DrawerItem name={kind === "Managed" ? "Resource ID" : "Disk URI"}>
|
|
{diskURI}
|
|
</DrawerItem>
|
|
<DrawerItem name="Kind">
|
|
{kind}
|
|
</DrawerItem>
|
|
<DrawerItem name="Caching Mode">
|
|
{cachingMode}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem Type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
<DrawerItem name="Readonly">
|
|
{readonly.toString()}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
azureFile: ({ readOnly = false, secretName, shareName, secretNamespace = "default" }) => (
|
|
<>
|
|
<DrawerItem name="Secret Name">
|
|
{secretName}
|
|
</DrawerItem>
|
|
<DrawerItem name="Share Name">
|
|
{shareName}
|
|
</DrawerItem>
|
|
<DrawerItem name="Namespace of Secret">
|
|
{secretNamespace}
|
|
</DrawerItem>
|
|
<DrawerItem name="Readonly">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
ephemeral: ({ volumeClaimTemplate: { metadata, spec }}, { pod, volumeName }) => (
|
|
<>
|
|
<DrawerItem name="PVC Template Name">
|
|
{pod.getName()}-{volumeName}
|
|
</DrawerItem>
|
|
<DrawerItemLabels
|
|
name="Template Labels"
|
|
labels={metadata.labels}
|
|
/>
|
|
<DrawerItemLabels
|
|
name="Template Annotations"
|
|
labels={metadata.annotations}
|
|
/>
|
|
<DrawerItem name="Template PVC Spec">
|
|
{jsyaml.dump(spec)}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
emptyDir: ({ medium, sizeLimit }) => (
|
|
<>
|
|
<DrawerItem name="Medium" hidden={!medium}>
|
|
{medium}
|
|
</DrawerItem>
|
|
<DrawerItem name="Size Limit" hidden={!sizeLimit}>
|
|
{sizeLimit}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
cephfs: ({ monitors, path = "/", user = "admin", secretFile = "/etc/ceph/user.secret", secretRef, readOnly }, { pod }) => (
|
|
<>
|
|
<DrawerItem name="Monitors">
|
|
<ul>
|
|
{monitors.map(monitor => <li key={monitor}>{monitor}</li>)}
|
|
</ul>
|
|
</DrawerItem>
|
|
<DrawerItem name="Mount Path">
|
|
{path}
|
|
</DrawerItem>
|
|
<DrawerItem name="Username">
|
|
{user}
|
|
</DrawerItem>
|
|
{
|
|
secretRef
|
|
? renderLocalRef(pod, "Secret", secretRef, secretsApi)
|
|
: (
|
|
<DrawerItem name="Secret Filepath">
|
|
{secretFile}
|
|
</DrawerItem>
|
|
)
|
|
}
|
|
<DrawerItem name="Readonly">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
cinder: ({ volumeID, fsType = "ext4" }) => (
|
|
<>
|
|
<DrawerItem name="Volume ID">
|
|
{volumeID}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem Type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
configMap: ({ name }, { pod }) => renderLocalRef(pod, "Name", { name }, configMapApi),
|
|
downwardAPI: ({ items }) => (
|
|
<>
|
|
<DrawerItem name="Items">
|
|
<ul>
|
|
{items.map(item => <li key={item.path}>{item.path}</li>)}
|
|
</ul>
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
fc: ({ targetWWNs, lun, fsType = "ext4", readOnly = false }) => (
|
|
<>
|
|
<DrawerItem name="Target World Wide Names">
|
|
<ul>
|
|
{targetWWNs.map(targetWWN => <li key={targetWWN}>{targetWWN}</li>)}
|
|
</ul>
|
|
</DrawerItem>
|
|
<DrawerItem name="Logical Unit Number">
|
|
{lun.toString()}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem Type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
<DrawerItem name="Readonly">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
flexVolume: ({ driver, fsType, secretRef, readOnly = false, options }, { pod }) => (
|
|
<>
|
|
<DrawerItem name="Driver">
|
|
{driver}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem Type">
|
|
{fsType || "-- system default --"}
|
|
</DrawerItem>
|
|
{secretRef && renderLocalRef(pod, "Secret", secretRef, secretsApi)}
|
|
<DrawerItem name="Readonly">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
{
|
|
...Object.entries(options)
|
|
.map(([key, value]) => (
|
|
<DrawerItem key={key} name={`Option: ${key}`}>
|
|
{value}
|
|
</DrawerItem>
|
|
))
|
|
}
|
|
</>
|
|
),
|
|
flocker: ({ datasetName }) => (
|
|
<>
|
|
<DrawerItem name="Dataset Name">
|
|
{datasetName}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
gcePersistentDisk: ({ pdName, fsType = "ext4" }) => (
|
|
<>
|
|
<DrawerItem name="Persistent Disk Name">
|
|
{pdName}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem Type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
gitRepo: ({ repository, revision }) => (
|
|
<>
|
|
<DrawerItem name="Repository URL">
|
|
{repository}
|
|
</DrawerItem>
|
|
<DrawerItem name="Commit Hash">
|
|
{revision}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
glusterfs: ({ endpoints, path, readOnly = false }) => (
|
|
<>
|
|
<DrawerItem name="Endpoints object name">
|
|
{endpoints}
|
|
</DrawerItem>
|
|
<DrawerItem name="Glusterfs volume name">
|
|
{path}
|
|
</DrawerItem>
|
|
<DrawerItem name="Readonly Mountpoint">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
hostPath: ({ path, type }) => (
|
|
<>
|
|
<DrawerItem name="Node's Host Filesystem Path">
|
|
{path}
|
|
</DrawerItem>
|
|
<DrawerItem name="Check Behaviour">
|
|
{type || "-- none --"}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
iscsi: ({ targetPortal, iqn, lun, fsType = "ext4", readOnly = false, chapAuthDiscovery, chapAuthSession, secretRef }) => (
|
|
<>
|
|
<DrawerItem name="Target Address">
|
|
{targetPortal}
|
|
</DrawerItem>
|
|
<DrawerItem name="iSCSI qualified name">
|
|
{iqn}
|
|
</DrawerItem>
|
|
<DrawerItem name="Logical Unit Number">
|
|
{lun.toString()}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem Type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
<DrawerItem name="Readonly">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
{chapAuthDiscovery && (
|
|
<DrawerItem name="CHAP Discovery Authentication">
|
|
{chapAuthDiscovery.toString()}
|
|
</DrawerItem>
|
|
)}
|
|
{chapAuthSession && (
|
|
<DrawerItem name="CHAP Session Authentication">
|
|
{chapAuthSession.toString()}
|
|
</DrawerItem>
|
|
)}
|
|
{ secretRef && (
|
|
<DrawerItem name="CHAP Secret">
|
|
{secretRef.name}
|
|
</DrawerItem>
|
|
)}
|
|
</>
|
|
),
|
|
local: ({ path }) => (
|
|
<>
|
|
<DrawerItem name="Path">
|
|
{path}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
nfs: ({ server, path, readOnly = false }) => (
|
|
<>
|
|
<DrawerItem name="Server">
|
|
{server}
|
|
</DrawerItem>
|
|
<DrawerItem name="Path">
|
|
{path}
|
|
</DrawerItem>
|
|
<DrawerItem name="Readonly">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
persistentVolumeClaim: ({ claimName }, { pod }) => renderLocalRef(pod, "Name", { name: claimName }, pvcApi),
|
|
photonPersistentDisk: ({ pdID, fsType = "ext4" }) => (
|
|
<>
|
|
<DrawerItem name="Persistent Disk ID">
|
|
{pdID}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem Type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
portworxVolume: ({ volumeID, fsType = "ext4", readOnly = false }) => (
|
|
<>
|
|
<DrawerItem name="Volume ID">
|
|
{volumeID}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem Type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
<DrawerItem name="Readonly">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
projected: ({ sources, defaultMode }) => (
|
|
<>
|
|
<DrawerItem name="Default Mount Mode">
|
|
0o{defaultMode.toString(8)}
|
|
</DrawerItem>
|
|
<DrawerItem name="Sources">
|
|
{
|
|
sources.map(({ secret, downwardAPI, configMap, serviceAccountToken }, index) => (
|
|
<React.Fragment key={index}>
|
|
{secret && (
|
|
<>
|
|
<DrawerTitle size="sub-title">Secret</DrawerTitle>
|
|
<DrawerItem name="Name">
|
|
{secret.name}
|
|
</DrawerItem>
|
|
{secret.items && (
|
|
<DrawerItem name="Items">
|
|
<ul>
|
|
{secret.items.map(({ key }) => <li key={key}>{key}</li>)}
|
|
</ul>
|
|
</DrawerItem>
|
|
)}
|
|
</>
|
|
)}
|
|
{downwardAPI && (
|
|
<>
|
|
<DrawerTitle size="sub-title">Downward API</DrawerTitle>
|
|
{downwardAPI.items && (
|
|
<DrawerItem name="Items">
|
|
<ul>
|
|
{downwardAPI.items.map(({ path }) => <li key={path}>{path}</li>)}
|
|
</ul>
|
|
</DrawerItem>
|
|
)}
|
|
</>
|
|
)}
|
|
{configMap && (
|
|
<>
|
|
<DrawerTitle size="sub-title">Config Map</DrawerTitle>
|
|
<DrawerItem name="Name">
|
|
{configMap.name}
|
|
</DrawerItem>
|
|
{configMap.items && (
|
|
<DrawerItem name="Items">
|
|
<ul>
|
|
{configMap.items.map(({ path }) => <li key={path}>{path}</li>)}
|
|
</ul>
|
|
</DrawerItem>
|
|
)}
|
|
</>
|
|
)}
|
|
{serviceAccountToken && (
|
|
<>
|
|
<DrawerTitle size="sub-title">Service Account Token</DrawerTitle>
|
|
<DrawerItem name="Audience" hidden={!serviceAccountToken.audience}>
|
|
{serviceAccountToken.audience}
|
|
</DrawerItem>
|
|
<DrawerItem name="Expiration" hidden={!serviceAccountToken.expirationSeconds}>
|
|
{serviceAccountToken.expirationSeconds}s
|
|
</DrawerItem>
|
|
<DrawerItem name="Path">
|
|
{serviceAccountToken.path}
|
|
</DrawerItem>
|
|
</>
|
|
)}
|
|
</React.Fragment>
|
|
))
|
|
}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
quobyte: ({ registry, volume, readOnly = false, user = "serviceaccount", group, tenant }) => (
|
|
<>
|
|
<DrawerItem name="Registry">
|
|
{registry}
|
|
</DrawerItem>
|
|
<DrawerItem name="Volume">
|
|
{volume}
|
|
</DrawerItem>
|
|
<DrawerItem name="Readonly">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
<DrawerItem name="User">
|
|
{user}
|
|
</DrawerItem>
|
|
<DrawerItem name="Group">
|
|
{group ?? "-- no group --"}
|
|
</DrawerItem>
|
|
<DrawerItem name="Tenant" hidden={!tenant}>
|
|
{tenant}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
rbd: ({ monitors, image, fsType = "ext4", pool = "rbd", user = "admin", keyring = "/etc/ceph/keyright", secretRef, readOnly = false }, { pod }) => (
|
|
<>
|
|
<DrawerItem name="Ceph Monitors">
|
|
<ul>
|
|
{monitors.map(monitor => <li key={monitor}>{monitor}</li>)}
|
|
</ul>
|
|
</DrawerItem>
|
|
<DrawerItem name="Image">
|
|
{image}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem Type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
<DrawerItem name="Pool">
|
|
{pool}
|
|
</DrawerItem>
|
|
<DrawerItem name="User">
|
|
{user}
|
|
</DrawerItem>
|
|
{
|
|
secretRef
|
|
? renderLocalRef(pod, "Authentication Secret", secretRef, secretsApi)
|
|
: (
|
|
<DrawerItem name="Keyright Path">
|
|
{keyring}
|
|
</DrawerItem>
|
|
)
|
|
}
|
|
<DrawerItem name="Readonly">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
scaleIO: ({ gateway, system, secretRef, sslEnabled = false, protectionDomain, storagePool, storageMode = "ThinProvisioned", volumeName, fsType = "xfs", readOnly = false }, { pod }) => (
|
|
<>
|
|
<DrawerItem name="Gateway">
|
|
{gateway}
|
|
</DrawerItem>
|
|
<DrawerItem name="System">
|
|
{system}
|
|
</DrawerItem>
|
|
{renderLocalRef(pod, "Name", secretRef, secretsApi)}
|
|
<DrawerItem name="SSL Enabled">
|
|
{sslEnabled.toString()}
|
|
</DrawerItem>
|
|
<DrawerItem name="SSL Enabled">
|
|
{sslEnabled.toString()}
|
|
</DrawerItem>
|
|
<DrawerItem name="Protection Domain Name" hidden={!protectionDomain}>
|
|
{protectionDomain}
|
|
</DrawerItem>
|
|
<DrawerItem name="Storage Pool" hidden={!storagePool}>
|
|
{storagePool}
|
|
</DrawerItem>
|
|
<DrawerItem name="Storage Mode" hidden={!storageMode}>
|
|
{storageMode}
|
|
</DrawerItem>
|
|
<DrawerItem name="Volume Name">
|
|
{volumeName}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem Type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
<DrawerItem name="Readonly">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
secret: ({ secretName, items = [], defaultMode = 0o644, optional = false }, { pod }) => (
|
|
<>
|
|
{renderLocalRef(pod, "Name", { name: secretName }, secretsApi)}
|
|
<DrawerItem name="Items" hidden={items.length === 0}>
|
|
<ul>
|
|
{items.map(({ key }) => <li key={key}>{key}</li>)}
|
|
</ul>
|
|
</DrawerItem>
|
|
<DrawerItem name="Default File Mode">
|
|
0o{defaultMode.toString(8)}
|
|
</DrawerItem>
|
|
<DrawerItem name="Optional">
|
|
{optional.toString()}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
storageos: ({ volumeName, volumeNamespace, fsType = "ext4", readOnly = false, secretRef }, { pod }) => (
|
|
<>
|
|
<DrawerItem name="Volume Name">
|
|
{volumeName}
|
|
</DrawerItem>
|
|
<DrawerItem name="Volume Namespace" hidden={volumeNamespace === "default"}>
|
|
{
|
|
volumeNamespace === volumeName
|
|
? "- no default behaviour -"
|
|
: volumeNamespace || pod.getNs()
|
|
}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
<DrawerItem name="Readonly">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
{secretRef && renderLocalRef(pod, "Secret", secretRef, secretsApi)}
|
|
</>
|
|
),
|
|
vsphereVolume: ({ volumePath, fsType = "ext4", storagePolicyName, storagePolicyID }) => (
|
|
<>
|
|
<DrawerItem name="Virtual Machine Disk Volume">
|
|
{volumePath}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
<DrawerItem name="Storage Policy Based Management Profile Name" hidden={!storagePolicyName}>
|
|
{storagePolicyName}
|
|
</DrawerItem>
|
|
<DrawerItem name="Storage Policy Based Management Profile ID" hidden={!storagePolicyID}>
|
|
{storagePolicyID}
|
|
</DrawerItem>
|
|
</>
|
|
),
|
|
csi: ({ driver, readOnly = false, fsType = "ext4", volumeAttributes = {}, nodePublishSecretRef, controllerPublishSecretRef, nodeStageSecretRef, controllerExpandSecretRef }, { pod }) => (
|
|
<>
|
|
<DrawerItem name="Driver">
|
|
{driver}
|
|
</DrawerItem>
|
|
<DrawerItem name="ReadOnly">
|
|
{readOnly.toString()}
|
|
</DrawerItem>
|
|
<DrawerItem name="Filesystem Type">
|
|
{fsType}
|
|
</DrawerItem>
|
|
{controllerPublishSecretRef && renderLocalRef(pod, "Controller Publish Secret", controllerPublishSecretRef, secretsApi)}
|
|
{controllerExpandSecretRef && renderLocalRef(pod, "Controller Expand Secret", controllerExpandSecretRef, secretsApi)}
|
|
{nodePublishSecretRef && renderLocalRef(pod, "Node Publish Secret", nodePublishSecretRef, secretsApi)}
|
|
{nodeStageSecretRef && renderLocalRef(pod, "Node Stage Secret", nodeStageSecretRef, secretsApi)}
|
|
{
|
|
...Object.entries(volumeAttributes)
|
|
.map(([key, value]) => (
|
|
<DrawerItem key={key} name={key}>
|
|
{value}
|
|
</DrawerItem>
|
|
))
|
|
}
|
|
</>
|
|
),
|
|
};
|
|
|
|
export interface PodVolumesProps {
|
|
pod: Pod;
|
|
}
|
|
|
|
const deprecatedVolumeTypes = new Set<PodVolumeKind>([
|
|
"flocker",
|
|
"gitRepo",
|
|
"quobyte",
|
|
"storageos",
|
|
]);
|
|
|
|
interface VolumeRendererPair {
|
|
kind: PodVolumeKind;
|
|
render: () => React.ReactChild;
|
|
}
|
|
|
|
function getVolumeType(pod: Pod, volume: PodVolume): RequireAllOrNone<VolumeRendererPair, keyof VolumeRendererPair> {
|
|
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 {};
|
|
}
|
|
|
|
export const PodVolumes = observer(({ pod }: PodVolumesProps) => {
|
|
if (!pod) {
|
|
return null;
|
|
}
|
|
|
|
const renderVolume = (volume: PodVolume) => {
|
|
const { kind, render } = getVolumeType(pod, volume);
|
|
const isDeprecated = deprecatedVolumeTypes.has(kind);
|
|
|
|
console.log(volume, render);
|
|
|
|
return (
|
|
<div key={volume.name} className="volume">
|
|
<div className="title flex gaps">
|
|
<Icon small material="storage" />
|
|
<span>{volume.name}</span>
|
|
</div>
|
|
{
|
|
kind
|
|
? (
|
|
<>
|
|
<DrawerItem name="Kind">
|
|
{kind}
|
|
{isDeprecated && <Icon title="Deprecated" material="warning_amber" />}
|
|
</DrawerItem>
|
|
{render?.()}
|
|
</>
|
|
)
|
|
: <p>Error! Unknown pod volume kind</p>
|
|
}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const volumes = pod.getVolumes();
|
|
|
|
if (volumes.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<DrawerTitle>Volumes</DrawerTitle>
|
|
{volumes.map(renderVolume)}
|
|
</>
|
|
);
|
|
});
|