Files
s3-csi/pkg/driver/capacity_test.go
zeekayandHanzo Dev 69ddc9947a s3-csi: ZAP-native CSI driver for the Hanzo filer
Fork of seaweedfs/seaweedfs-csi-driver, renamed seaweedfs -> s3 throughout and
ported off protobuf entirely.

WHY a fork was unavoidable: hanzoai/s3 serves HanzoFiler over the native ZAP
transport on the port still named "grpc" (18888) — s3/command/filer.go binds it
with transport.ListenStream and says it "replaces the legacy gRPC HanzoFiler
server: the whole filer (28 unary + 5 streaming RPCs) now answers over ZAP, no
gRPC". RegisterHanzoFilerServer exists nowhere in that tree. So the upstream
driver's gRPC client cannot connect at all; it fails as
`Unimplemented: unknown service filer_pb.SeaweedFiler`, which LOOKS like a
service-name mismatch but is a gRPC client hitting a non-gRPC port. Renaming the
service in the client would not have helped.

pkg/filer is the only place this driver touches storage, and it speaks ZAP:
  Mkdir  -> CreateEntry           (CreateVolume)
  Remove -> DeleteEntry           (DeleteVolume)
  Exists -> LookupDirectoryEntry  (ValidateVolumeCapabilities)
One shared, concurrency-safe client multiplexes over a single ZAP connection,
dials lazily so controller start does not depend on filer readiness, and redials
exactly once on a transport fault (covers a filer restart closing an idle conn
without becoming a retry storm against a struggling backend).

pkg/driver/volume.go Quota() likewise moves to s3/wire/mount — the fork generates
no mount_pb at all. Dead gRPC plumbing (WithFilerClient, AdjustedUrl,
grpcDialOption) is deleted rather than left inert.

The kubelet-facing side stays CSI gRPC: that is the Kubernetes contract between
kubelet and any CSI driver, not a Hanzo choice.

Zero protobuf call sites remain. Whole module compiles clean.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 16:42:29 -07:00

79 lines
1.9 KiB
Go

package driver
import (
"errors"
"testing"
)
func TestResolveVolumeCapacityUsesVolumeContextFallback(t *testing.T) {
ns := &NodeServer{
capacityFn: func(volumeID string) (int64, error) {
return 0, errors.New("Kubernetes API unavailable")
},
}
got, ok, err := ns.resolveVolumeCapacity("/buckets/pvc-1234", map[string]string{
volumeCapacityKey: "5368709120",
})
if err != nil {
t.Fatalf("resolveVolumeCapacity: %v", err)
}
if !ok {
t.Fatal("expected volume capacity to be available")
}
if want := int64(5368709120); got != want {
t.Fatalf("capacity = %d, want %d", got, want)
}
}
func TestResolveVolumeCapacityPrefersOrchestratorValue(t *testing.T) {
ns := &NodeServer{
capacityFn: func(volumeID string) (int64, error) {
return 10 * 1024 * 1024 * 1024, nil
},
}
got, ok, err := ns.resolveVolumeCapacity("pvc-1234", map[string]string{
volumeCapacityKey: "5368709120",
})
if err != nil {
t.Fatalf("resolveVolumeCapacity: %v", err)
}
if !ok {
t.Fatal("expected volume capacity to be available")
}
if want := int64(10 * 1024 * 1024 * 1024); got != want {
t.Fatalf("capacity = %d, want %d", got, want)
}
}
func TestResolveVolumeCapacityRejectsInvalidContextValue(t *testing.T) {
ns := &NodeServer{
capacityFn: func(volumeID string) (int64, error) {
return 0, errors.New("Kubernetes API unavailable")
},
}
if _, _, err := ns.resolveVolumeCapacity("pvc-1234", map[string]string{
volumeCapacityKey: "not-a-size",
}); err == nil {
t.Fatal("expected invalid volume capacity to return an error")
}
}
func TestResolveVolumeCapacityAllowsUnavailableCapacity(t *testing.T) {
ns := &NodeServer{
capacityFn: func(volumeID string) (int64, error) {
return 0, errors.New("Kubernetes API unavailable")
},
}
_, ok, err := ns.resolveVolumeCapacity("pvc-1234", nil)
if err != nil {
t.Fatalf("resolveVolumeCapacity: %v", err)
}
if ok {
t.Fatal("expected volume capacity to be unavailable")
}
}