PR #552 ("CSI volume support") introduced the initial CSI integration—a CSIDriverConfig CRD, an internal/volume/csi plugin, and control-plane/worker-plane wiring. It landed with seven TODO comments in non-vendored code. This issue tracks them so they aren't lost.
1. Correctness / driver compatibility
2. Efficiency and log noise
3. Consistency and API hardening
PR #552 ("CSI volume support") introduced the initial CSI integration—a
CSIDriverConfigCRD, aninternal/volume/csiplugin, and control-plane/worker-plane wiring. It landed with sevenTODOcomments in non-vendored code. This issue tracks them so they aren't lost.1. Correctness / driver compatibility
Propagate
PublishContextfromControllerPublishVolumeto the node mount path—
substrate/internal/volume/csi/plugin.go
Line 125 in d7629ed
Current behavior:
Plugin.AttachVolumediscards the response (_ = resp.GetPublishContext()) because the SubstrateVolumePlugininterface has nowhere to put it.Proposed fix: extend
VolumePluginsoAttachVolumereturns the publish context, persist it alongside the volume's assignment state, and pass it intoNodeStageVolume/NodePublishVolumeon the worker.Why it matters: drivers that require it (e.g. AWS EBS) cannot successfully mount today, so this gates any real cloud driver beyond the hostpath test driver.
Support configurable volume access modes instead of hardcoding
SINGLE_NODE_WRITER—
substrate/internal/volume/csi/plugin.go
Line 236 in d7629ed
Current behavior:
getStandardCapabilities()returns one hardcodedSINGLE_NODE_WRITER+Mountcapability, used for every create, attach, and mount call.Proposed fix: add an access-mode field to the volume API type, map it to the corresponding
csi.VolumeCapability_AccessModeenum, and validate the requested mode against the driver's reported capabilities. UnblocksReadWriteMany/ReadOnlyManyvolumes shared across actors.2. Efficiency and log noise
Query CSI driver capabilities at plugin initialization
—
substrate/internal/volume/csi/plugin.go
Line 113 in d7629ed
Current behavior:
AttachVolumeoptimistically callsControllerPublishVolume, catchescodes.Unimplemented, and logs a warning on every attach for drivers withoutPUBLISH_UNPUBLISH_VOLUME(including the hostpath driver used in e2e).Proposed fix: call
ControllerGetCapabilitiesonce during plugin init, cache the capability set on thePlugin, and skip attach/detach entirely when unsupported.Reconsider the shared informer used solely for the
CSIDriverConfiglister in atelet—
substrate/cmd/atelet/main.go
Line 221 in d7629ed
Current behavior: atelet spins up a full
SharedInformerFactory(resync0) on every worker node just to obtainApi().V1alpha1().CSIDriverConfigs().Lister(), caching all CSIDriverConfigs cluster-wide per node.Proposed fix: given the lister is read infrequently, evaluate a direct client
Getwith a small TTL cache, or a field/label-filtered (or metadata-only) informer, to reduce per-node memory and API-server watch load.3. Consistency and API hardening
Extract a shared volume-plugin lookup helper for control plane and worker plane
— control plane:
substrate/cmd/ateapi/internal/controlapi/volumes.go
Line 145 in d7629ed
— worker plane:
substrate/cmd/atelet/volumes.go
Line 69 in d7629ed
Current behavior:
deleteActorVolumes(registry.GetPlugin) andunmountExternalVolumes(s.getPlugin) each duplicate plugin resolution and error wrapping with slightly different message formats.Proposed fix: add one helper in
internal/volumethat resolves a plugin by volume type and returns a consistently wrapped error. Constraint: it must preserve the underlying gRPC status code—the worker path relies onstatus.Code(err) == codes.NotFoundto treat an unmount as already completed.Harden
CSIDriverConfig.ControllerEndpointvalidation—
substrate/pkg/api/v1alpha1/csidriverconfig_types.go
Line 34 in d7629ed
Current behavior: validated only by
+kubebuilder:validation:Pattern=+ "^(tcp|dns)://.+$", which accepts effectively any string after the scheme and has no length bound.Proposed fix: tighten the CEL/regex validation to a real host:port (or
dns:///target) form, add aMaxLength, and consider a validating webhook for anything the schema can't express. This field determines where the control plane dials, so a permissive value is a request-forgery vector.