Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ require (
github.com/container-storage-interface/spec v1.11.0
github.com/go-ini/ini v1.67.0
github.com/golang/protobuf v1.5.4
github.com/google/uuid v1.6.0
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1
github.com/kubernetes-csi/csi-lib-utils v0.16.0
github.com/onsi/ginkgo/v2 v2.23.4
Expand Down Expand Up @@ -107,7 +108,6 @@ require (
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
Expand Down
173 changes: 173 additions & 0 deletions pkg/blob/nodeserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (

"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage"
"github.com/container-storage-interface/spec/lib/go/csi"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"go.uber.org/mock/gomock"

Expand Down Expand Up @@ -234,6 +235,113 @@ func TestNodePublishVolume(t *testing.T) {
},
expectedErr: status.Error(codes.InvalidArgument, fmt.Sprintf("invalid mountPermissions %s", "07ab")),
},
{
desc: "Valid request with service account token and clientID",
setup: func(d *Driver) {
// Mock NodeStageVolume to return success
d.cloud.ResourceGroup = "rg"
d.enableBlobMockMount = true
},
req: &csi.NodePublishVolumeRequest{
VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
VolumeId: "vol_1",
TargetPath: targetTest,
StagingTargetPath: sourceTest,
VolumeContext: map[string]string{
serviceAccountTokenField: `{"api://AzureADTokenExchange":{"token":"test-token","expirationTimestamp":"2023-01-01T00:00:00Z"}}`,
clientIDField: "client-id-value",
},
},
expectedErr: nil,
},
{
desc: "Valid request with ephemeral volume",
setup: func(d *Driver) {
// Mock NodeStageVolume to return success
d.cloud.ResourceGroup = "rg"
d.enableBlobMockMount = true
},
req: &csi.NodePublishVolumeRequest{
VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
VolumeId: "vol_1",
TargetPath: targetTest,
StagingTargetPath: sourceTest,
VolumeContext: map[string]string{
"csi.storage.k8s.io/ephemeral": "true",
"csi.storage.k8s.io/pod.namespace": "test-namespace",
"containername": "test-container", // Add container name to avoid error
},
},
expectedErr: nil,
},
{
desc: "Volume already mounted",
setup: func(_ *Driver) {
// Create the directory and ensure it's seen as already mounted
_ = makeDir("./false_is_likely")
},
req: &csi.NodePublishVolumeRequest{
VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
VolumeId: "vol_1",
TargetPath: "./false_is_likely", // This path will make IsLikelyNotMountPoint return false
StagingTargetPath: sourceTest,
},
expectedErr: nil,
cleanup: func(_ *Driver) {
// Clean up the directory
_ = os.RemoveAll("./false_is_likely")
},
},
{
desc: "enableBlobMockMount enabled",
setup: func(d *Driver) {
// Enable mock mount
d.enableBlobMockMount = true

// Create a temporary directory for the test
_ = makeDir("./mock_mount_test")
},
req: &csi.NodePublishVolumeRequest{
VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
VolumeId: "vol_1",
TargetPath: "./mock_mount_test",
StagingTargetPath: sourceTest,
VolumeContext: map[string]string{
mountPermissionsField: "0755",
},
},
expectedErr: nil,
cleanup: func(d *Driver) {
// Disable mock mount
d.enableBlobMockMount = false

// Clean up the directory
_ = os.RemoveAll("./mock_mount_test")
},
},
{
desc: "enableBlobMockMount enabled - MakeDir fails",
setup: func(d *Driver) {
// Enable mock mount
d.enableBlobMockMount = true
},
req: &csi.NodePublishVolumeRequest{
VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
VolumeId: "vol_1",
TargetPath: "./azure.go", // This will fail because it's a file, not a directory
StagingTargetPath: sourceTest,
VolumeContext: map[string]string{
mountPermissionsField: "0755",
},
},
expectedErr: func() error {
if runtime.GOOS == "windows" {
t.Skip("Skipping test on ", runtime.GOOS)
return nil
}
return status.Errorf(codes.Internal, "Could not mount target \"./azure.go\": mkdir ./azure.go: not a directory")
}(),
},
}

// Setup
Expand Down Expand Up @@ -273,6 +381,71 @@ func TestNodePublishVolume(t *testing.T) {
assert.NoError(t, err)
}

func TestNodePublishVolumeMountError(t *testing.T) {
d := NewFakeDriver()
fakeMounter := &fakeMounter{}
fakeExec := &testingexec.FakeExec{ExactOrder: true}
d.mounter = &mount.SafeFormatAndMount{
Interface: fakeMounter,
Exec: fakeExec,
}

volumeCap := csi.VolumeCapability_AccessMode{
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
}

// Test case 1: Mount fails with source error
targetPath := "./mount_test_target"
_ = makeDir(targetPath)

req := &csi.NodePublishVolumeRequest{
VolumeId: "vol_1",
TargetPath: targetPath,
StagingTargetPath: "error_mount", // This will trigger an error in Mount
VolumeCapability: &csi.VolumeCapability{
AccessMode: &volumeCap,
},
}

// Run the test
_, err := d.NodePublishVolume(context.Background(), req)
expectedErr := status.Errorf(codes.Internal, "Could not mount \"error_mount\" at \"./mount_test_target\": fake Mount: source error")
if err == nil || err.Error() != expectedErr.Error() {
t.Errorf("Expected error: %v, got: %v", expectedErr, err)
}

// Clean up
_ = os.RemoveAll(targetPath)

// Let's try a different approach
// Let's create a custom fakeMounter that returns a specific error for Mount

// We'll continue to use the same fakeMounter
// It's already configured to return an error for paths containing "error_mount"

// Create a test directory that doesn't exist
nonExistentPath := "/tmp/non-existent-path-" + uuid.NewString()

req = &csi.NodePublishVolumeRequest{
VolumeId: "vol_1",
TargetPath: nonExistentPath,
StagingTargetPath: "error_mount", // This will trigger an error in Mount
VolumeCapability: &csi.VolumeCapability{
AccessMode: &volumeCap,
},
}

// Run the test
_, err = d.NodePublishVolume(context.Background(), req)

// The error should be about failing to mount, not about removing the target
// because the target doesn't exist
expectedErr = status.Errorf(codes.Internal, "Could not mount \"error_mount\" at \"%s\": fake Mount: source error", nonExistentPath)
if err == nil || err.Error() != expectedErr.Error() {
t.Errorf("Expected error: %v, got: %v", expectedErr, err)
}
}

func TestNodePublishVolumeIdempotentMount(t *testing.T) {
if runtime.GOOS != "linux" || os.Getuid() != 0 {
return
Expand Down
Loading