From a3f52eee17eb1a493110a56fd6b5fa15d4369b5f Mon Sep 17 00:00:00 2001 From: nijayf Date: Mon, 3 Nov 2025 19:39:13 +0530 Subject: [PATCH 1/4] Release v2.15.1 changes --- go.mod | 8 +- service/controller.go | 17 ++- service/controller_test.go | 2 + service/node.go | 51 +++++-- service/node_test.go | 283 ++++++++++++++++++++++++++++++++++++- service/service.go | 48 ++++++- 6 files changed, 384 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index 08d6771f..195da6de 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.20.0 github.com/stretchr/testify v1.11.0 - golang.org/x/net v0.43.0 + golang.org/x/net v0.46.0 google.golang.org/grpc v1.75.0 google.golang.org/protobuf v1.36.6 gopkg.in/yaml.v3 v3.0.1 @@ -92,9 +92,9 @@ require ( go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sys v0.36.0 // indirect - golang.org/x/term v0.34.0 // indirect - golang.org/x/text v0.28.0 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/term v0.36.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.9.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect diff --git a/service/controller.go b/service/controller.go index 10e941f9..275e9e8e 100644 --- a/service/controller.go +++ b/service/controller.go @@ -1287,8 +1287,14 @@ func (s *service) ControllerPublishVolume( } if exportPath = volumeContext[ExportPathParam]; exportPath == "" { - exportPath = isilonfs.GetPathForVolume(isiConfig.IsiPath, volName) + // if not in request, calculate it from the export + exportPath, err = getExportPathFromExportID(ctx, isiConfig, exportID, accessZone) + if err != nil { + log.Infof("Could not get export path by export ID: %v", err) + exportPath = isilonfs.GetPathForVolume(isiConfig.IsiPath, volName) + } } + log.Infof("Export path: %s", exportPath) isROVolumeFromSnapshot = isiConfig.isiSvc.isROVolumeFromSnapshot(volumeContext["Path"], accessZone) if isROVolumeFromSnapshot { @@ -1472,7 +1478,7 @@ func (s *service) ValidateVolumeCapabilities( // parse the input volume id and fetch it's components volID := req.GetVolumeId() - volName, _, _, clusterName, err := id.ParseNormalizedVolumeID(ctx, volID) + volName, exportID, accessZone, clusterName, err := id.ParseNormalizedVolumeID(ctx, volID) if err != nil { return nil, status.Error(codes.NotFound, err.Error()) } @@ -1493,7 +1499,12 @@ func (s *service) ValidateVolumeCapabilities( volumeContext := req.GetVolumeContext() if exportPath = volumeContext[ExportPathParam]; exportPath == "" { - exportPath = isilonfs.GetPathForVolume(isiConfig.IsiPath, volName) + // if not in request, calculate it from the export + exportPath, err = getExportPathFromExportID(ctx, isiConfig, exportID, accessZone) + if err != nil { + log.Infof("Could not get export path by export ID: %v", err) + exportPath = isilonfs.GetPathForVolume(isiConfig.IsiPath, volName) + } } isiPath = isilonfs.GetIsiPathFromExportPath(exportPath) diff --git a/service/controller_test.go b/service/controller_test.go index e4d7145a..0c058ac2 100644 --- a/service/controller_test.go +++ b/service/controller_test.go @@ -1564,6 +1564,7 @@ func TestControllerPublishVolume_MaxVolumesPerNode(t *testing.T) { // Mock the necessary calls isiConfig.isiSvc.client.API.(*isimocks.Client).ExpectedCalls = nil + isiConfig.isiSvc.client.API.(*isimocks.Client).On("Get", anyArgs[0:6]...).Return(errors.New("mocked export lookup failure")).Once() isiConfig.isiSvc.client.API.(*isimocks.Client).On("Get", anyArgs[0:6]...).Return(nil).Run(func(args mock.Arguments) { resp := args.Get(5).(**apiv1.GetIsiVolumeAttributesResp) *resp = &apiv1.GetIsiVolumeAttributesResp{} @@ -1588,6 +1589,7 @@ func TestControllerPublishVolume_MaxVolumesPerNode(t *testing.T) { // Error Scenario isiConfig.isiSvc.client.API.(*isimocks.Client).ExpectedCalls = nil + isiConfig.isiSvc.client.API.(*isimocks.Client).On("Get", anyArgs[0:6]...).Return(errors.New("mocked export lookup failure")).Once() isiConfig.isiSvc.client.API.(*isimocks.Client).On("Get", anyArgs[0:6]...).Return(nil).Run(func(args mock.Arguments) { resp := args.Get(5).(**apiv1.GetIsiVolumeAttributesResp) *resp = &apiv1.GetIsiVolumeAttributesResp{} diff --git a/service/node.go b/service/node.go index 5d00a9ff..925db85c 100644 --- a/service/node.go +++ b/service/node.go @@ -460,27 +460,62 @@ func (s *service) NodeGetVolumeStats( return nil, status.Error(codes.InvalidArgument, logging.GetMessageWithRunID(runID, "no Volume Path found in request")) } - volName, _, _, clusterName, _ := id.ParseNormalizedVolumeID(ctx, volID) + volName, exportID, accessZone, clusterName, _ := id.ParseNormalizedVolumeID(ctx, volID) if volName == "" { volName = volID } // Check if given volume exists + // Create copy of isiconfig so we don't modify the original isiConfig, err := s.getIsilonConfig(ctx, &clusterName) if err != nil { return nil, err } - isiPath := isiConfig.IsiPath - + isiConfigCopy := &IsilonClusterConfig{ + ClusterName: isiConfig.ClusterName, + Endpoint: isiConfig.Endpoint, + EndpointPort: isiConfig.EndpointPort, + MountEndpoint: isiConfig.MountEndpoint, + EndpointURL: isiConfig.EndpointURL, + accessZone: isiConfig.accessZone, + User: isiConfig.User, + Password: isiConfig.Password, + SkipCertificateValidation: isiConfig.SkipCertificateValidation, + IsiPath: isiConfig.IsiPath, + IsiVolumePathPermissions: isiConfig.IsiVolumePathPermissions, + IsDefault: isiConfig.IsDefault, + ReplicationCertificateID: isiConfig.ReplicationCertificateID, + IgnoreUnresolvableHosts: isiConfig.IgnoreUnresolvableHosts, + isiSvc: isiConfig.isiSvc, + } + + // save the isiPath var, if we cannot find another isiPath tied to the vol, we will use this one + isiPath := isiConfigCopy.IsiPath + + // first we check pv, sc for isiPath + // if we cannot find it there, we check the export isiPathFromParams, err := s.validateIsiPath(ctx, volName) if err != nil { - log.Error("Failed get isiPath", err.Error()) + log.Error("Failed to get isiPath: ", err.Error()) + // if not in pv or sc, calculate it from the export + exportPath, err := getExportPathFromExportID(ctx, isiConfig, exportID, accessZone) + if err != nil { + log.Debugf("Failed to get export path: %s, using default: %s", err.Error(), isiPath) + } else { + isiPathFromParams = isilonfs.GetIsiPathFromExportPath(exportPath) + } } - - if isiPathFromParams != isiPath && isiPathFromParams != "" { - log.Debug("overriding isiPath with value from StorageClass", isiPathFromParams) + if isiPathFromParams != "" { + log.Debug("Found IsiPath from PV/SC/Export: ", isiPathFromParams) isiPath = isiPathFromParams + // set service to utilize new path + isiConfigCopy.IsiPath = isiPath + isiConfigCopy.isiSvc, err = s.GetIsiService(ctx, isiConfigCopy, logging.GetCurrentLogLevel()) + if err != nil { + log.Error("NodeGetVolumeStats: Failed to get isiService: ", err.Error()) + return nil, err + } } // Probe the node if required and make sure startup called @@ -489,7 +524,7 @@ func (s *service) NodeGetVolumeStats( return nil, err } - isiVol, err := isiConfig.isiSvc.GetVolume(ctx, "", volName) + isiVol, err := isiConfigCopy.isiSvc.GetVolume(ctx, "", volName) if err != nil || isiVol == nil { return nil, status.Error(codes.NotFound, logging.GetMessageWithRunID(runID, "volume %v does not exist at path %v", volName, volPath)) } diff --git a/service/node_test.go b/service/node_test.go index 92278bc7..7abf1b1e 100644 --- a/service/node_test.go +++ b/service/node_test.go @@ -29,11 +29,16 @@ import ( "github.com/container-storage-interface/spec/lib/go/csi" isi "github.com/dell/goisilon" - apiv1 "github.com/dell/goisilon/api/v1" isimocks "github.com/dell/goisilon/mocks" + v1 "github.com/dell/gopowerscale/api/v1" + v2 "github.com/dell/gopowerscale/api/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "golang.org/x/net/context" + corev1 "k8s.io/api/core/v1" + storagev1 "k8s.io/api/storage/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" ) const testTargetPath = "/tmp/csi-powerscale-test" @@ -46,12 +51,53 @@ func Test_node_readFileFunc(t *testing.T) { assert.Equal(t, []byte("dummy-content"), result) } +func setK8sClient(s *service) { + pv := &corev1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "volume-id", + }, + Spec: corev1.PersistentVolumeSpec{ + StorageClassName: "test-sc", + }, + } + sc := &storagev1.StorageClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sc", + }, + Parameters: map[string]string{ + IsiPathParam: "/new/isi/path", + }, + } + s.k8sclient = fake.NewClientset(pv, sc) +} + +func setNewIsiClientWithArgsFunc(mockClient *isimocks.Client) { + newIsiClientWithArgsFunc = func( + _ context.Context, + _ string, + _ bool, + _ uint, + _ string, + _ string, + _ string, + _ string, + _ string, + _ bool, + _ uint8, + ) (*isi.Client, error) { + return &isi.Client{ + API: mockClient, + }, nil + } +} + func TestNodeGetVolumeStats(t *testing.T) { // Original function references originalGetIsVolumeExistentFunc := getIsVolumeExistentFunc originalGetIsVolumeMounted := getIsVolumeMounted originalGetOsReadDir := getOsReadDir originalGetK8sutilsGetStats := getK8sutilsGetStats + originalNewIsiClientWithArgsFunc := newIsiClientWithArgsFunc // Reset function to reset mocks after tests resetMocks := func() { @@ -59,10 +105,12 @@ func TestNodeGetVolumeStats(t *testing.T) { getIsVolumeMounted = originalGetIsVolumeMounted getOsReadDir = originalGetOsReadDir getK8sutilsGetStats = originalGetK8sutilsGetStats + newIsiClientWithArgsFunc = originalNewIsiClientWithArgsFunc } - // Mock IsiCluster and service setup mockClient := &isimocks.Client{} + + // Setup mock IsiCluster and service IsiClusters := new(sync.Map) testBool := false testIsilonClusterConfig := IsilonClusterConfig{ @@ -94,10 +142,35 @@ func TestNodeGetVolumeStats(t *testing.T) { isiClusters: IsiClusters, } mockClient.On("VolumesPath").Return("/path/to/volumes") - mockClient.On("Get", anyArgs[0:6]...).Return(nil).Run(func(args mock.Arguments) { - resp := args.Get(5).(**apiv1.GetIsiVolumeAttributesResp) - *resp = &apiv1.GetIsiVolumeAttributesResp{} + mockClient.On( + "Get", + mock.AnythingOfType("*context.valueCtx"), + "platform/2/protocols/nfs/exports", + mock.AnythingOfType("string"), + mock.AnythingOfType("api.OrderedValues"), + mock.AnythingOfType("map[string]string"), + mock.MatchedBy(func(arg interface{}) bool { + _, ok := arg.(*v2.ExportList) + return ok + }), + ).Return(errors.New("mocked export lookup failure")) + + mockClient.On( + "Get", + mock.AnythingOfType("*context.valueCtx"), + "namespace/path/to/volumes", + "volume-id", + mock.AnythingOfType("api.OrderedValues"), + mock.AnythingOfType("map[string]string"), + mock.MatchedBy(func(arg interface{}) bool { + _, ok := arg.(**v1.GetIsiVolumeAttributesResp) + return ok + }), + ).Return(nil).Run(func(args mock.Arguments) { + resp := args.Get(5).(**v1.GetIsiVolumeAttributesResp) + *resp = &v1.GetIsiVolumeAttributesResp{} }) + tests := []struct { name string ctx context.Context @@ -114,6 +187,7 @@ func TestNodeGetVolumeStats(t *testing.T) { VolumePath: "/path/to/volume", }, setup: func() { + setK8sClient(s) getIsVolumeExistentFunc = func(_ *IsilonClusterConfig) func(ctx context.Context, isiPath, volID, name string) bool { return func(_ context.Context, _, _, _ string) bool { return true @@ -131,6 +205,7 @@ func TestNodeGetVolumeStats(t *testing.T) { getK8sutilsGetStats = func(_ context.Context, _ string) (int64, int64, int64, int64, int64, int64, error) { return 0, 0, 0, 0, 0, 0, errors.New("failed to get volume stats metrics") } + setNewIsiClientWithArgsFunc(mockClient) }, wantResponse: &csi.NodeGetVolumeStatsResponse{ Usage: []*csi.VolumeUsage{ @@ -202,6 +277,148 @@ func TestNodeGetVolumeStats(t *testing.T) { VolumePath: "/path/to/volume", }, setup: func() { + setK8sClient(s) + getIsVolumeExistentFunc = func(_ *IsilonClusterConfig) func(ctx context.Context, isiPath, volID, name string) bool { + return func(_ context.Context, _, _, _ string) bool { + return true + } + } + + getIsVolumeMounted = func(_ context.Context, _ string, _ string) (bool, error) { + return true, nil + } + + getOsReadDir = func(_ string) ([]os.DirEntry, error) { + return []os.DirEntry{}, nil + } + + getK8sutilsGetStats = func(_ context.Context, _ string) (int64, int64, int64, int64, int64, int64, error) { + return 1000, 2000, 1000, 4, 2, 2, nil + } + setNewIsiClientWithArgsFunc(mockClient) + }, + wantResponse: &csi.NodeGetVolumeStatsResponse{ + Usage: []*csi.VolumeUsage{ + { + Unit: csi.VolumeUsage_BYTES, + Available: 1000, + Total: 2000, + Used: 1000, + }, + { + Unit: csi.VolumeUsage_INODES, + Available: 2, + Total: 4, + Used: 2, + }, + }, + VolumeCondition: &csi.VolumeCondition{ + Abnormal: false, + Message: "", + }, + }, + wantErr: false, + }, + { + name: "Success in NodeGetVolumeStats- isiPathFromParams is used", + ctx: context.Background(), + req: &csi.NodeGetVolumeStatsRequest{ + VolumeId: "volume-id", + VolumePath: "/path/to/volume", + }, + setup: func() { + pv := &corev1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "volume-id", + }, + Spec: corev1.PersistentVolumeSpec{ + StorageClassName: "test-sc", + }, + } + sc := &storagev1.StorageClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sc", + }, + Parameters: map[string]string{ + IsiPathParam: "/new/isi/path", + }, + } + s.k8sclient = fake.NewClientset(pv, sc) + + getIsVolumeExistentFunc = func(_ *IsilonClusterConfig) func(ctx context.Context, isiPath, volID, name string) bool { + return func(_ context.Context, _, _, _ string) bool { + return true + } + } + + getIsVolumeMounted = func(_ context.Context, _ string, _ string) (bool, error) { + return true, nil + } + + getOsReadDir = func(_ string) ([]os.DirEntry, error) { + return []os.DirEntry{}, nil + } + + getK8sutilsGetStats = func(_ context.Context, _ string) (int64, int64, int64, int64, int64, int64, error) { + return 1000, 2000, 1000, 4, 2, 2, nil + } + setNewIsiClientWithArgsFunc(mockClient) + }, + wantResponse: &csi.NodeGetVolumeStatsResponse{ + Usage: []*csi.VolumeUsage{ + { + Unit: csi.VolumeUsage_BYTES, + Available: 1000, + Total: 2000, + Used: 1000, + }, + { + Unit: csi.VolumeUsage_INODES, + Available: 2, + Total: 4, + Used: 2, + }, + }, + VolumeCondition: &csi.VolumeCondition{ + Abnormal: false, + Message: "", + }, + }, + wantErr: false, + }, + { + name: "Success in NodeGetVolumeStats- isiPath from pv is used", + ctx: context.Background(), + req: &csi.NodeGetVolumeStatsRequest{ + VolumeId: "volume-id", + VolumePath: "/path/to/volume", + }, + setup: func() { + pv := &corev1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "volume-id", + }, + Spec: corev1.PersistentVolumeSpec{ + StorageClassName: "test-sc", + PersistentVolumeSource: corev1.PersistentVolumeSource{ + CSI: &corev1.CSIPersistentVolumeSource{ + VolumeAttributes: map[string]string{ + "Path": "/new/isi/path", + }, + }, + }, + }, + } + sc := &storagev1.StorageClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sc", + }, + Parameters: map[string]string{ + IsiPathParam: "/new/isi/path", + }, + } + s.k8sclient = fake.NewClientset(pv, sc) + getIsVolumeExistentFunc = func(_ *IsilonClusterConfig) func(ctx context.Context, isiPath, volID, name string) bool { return func(_ context.Context, _, _, _ string) bool { return true @@ -219,6 +436,8 @@ func TestNodeGetVolumeStats(t *testing.T) { getK8sutilsGetStats = func(_ context.Context, _ string) (int64, int64, int64, int64, int64, int64, error) { return 1000, 2000, 1000, 4, 2, 2, nil } + + setNewIsiClientWithArgsFunc(mockClient) }, wantResponse: &csi.NodeGetVolumeStatsResponse{ Usage: []*csi.VolumeUsage{ @@ -242,6 +461,52 @@ func TestNodeGetVolumeStats(t *testing.T) { }, wantErr: false, }, + { + name: "Failure in NodeGetVolumeStats- isiPathFromParams is used but cannot get isi Service", + ctx: context.Background(), + req: &csi.NodeGetVolumeStatsRequest{ + VolumeId: "volume-id", + VolumePath: "/path/to/volume", + }, + setup: func() { + pv := &corev1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "volume-id", + }, + Spec: corev1.PersistentVolumeSpec{ + StorageClassName: "test-sc", + }, + } + sc := &storagev1.StorageClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sc", + }, + Parameters: map[string]string{ + IsiPathParam: "/new/isi/path", + }, + } + + s.k8sclient = fake.NewClientset(pv, sc) + + newIsiClientWithArgsFunc = func( + _ context.Context, + _ string, + _ bool, + _ uint, + _ string, + _ string, + _ string, + _ string, + _ string, + _ bool, + _ uint8, + ) (*isi.Client, error) { + return nil, errors.New("cannot get isi Service") + } + }, + wantResponse: nil, + wantErr: true, + }, } // Run the test cases @@ -257,6 +522,9 @@ func TestNodeGetVolumeStats(t *testing.T) { // Call the function under test got, err := s.NodeGetVolumeStats(tt.ctx, tt.req) + // reset the k8sclient + s.k8sclient = nil + // Check if the error status matches if (err != nil) != tt.wantErr { t.Errorf("NodeGetVolumeStats() error = %v, wantErr %v", err, tt.wantErr) @@ -270,7 +538,10 @@ func TestNodeGetVolumeStats(t *testing.T) { }) } - t.Run("Volume does not exists", func(t *testing.T) { + t.Run("Volume does not exist", func(t *testing.T) { + defer resetMocks() + setK8sClient(s) + setNewIsiClientWithArgsFunc(mockClient) mockClient.ExpectedCalls = nil mockClient.On("VolumesPath").Return("/path/to/volumes") mockClient.On("Get", anyArgs[0:6]...).Return(fmt.Errorf("not found")) diff --git a/service/service.go b/service/service.go index 58574819..d9bc64c1 100644 --- a/service/service.go +++ b/service/service.go @@ -31,6 +31,7 @@ import ( "github.com/akutz/gournal" "github.com/dell/csi-isilon/v2/common/k8sutils" + isilonfs "github.com/dell/csi-powerscale/v2/common/utils/powerscale-fs" "google.golang.org/grpc" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/types/known/wrapperspb" @@ -75,6 +76,8 @@ var ( "formed": core.CommitTime.Format(time.RFC1123), } noProbeOnStart bool + + newIsiClientWithArgsFunc = isi.NewClientWithArgs ) // Service is the CSI service provider. @@ -463,7 +466,7 @@ func (s *service) GetIsiClient(clientCtx context.Context, isiConfig *IsilonClust gournal.DefaultLevel = gournalLevel } - client, err := isi.NewClientWithArgs( + client, err := newIsiClientWithArgsFunc( clientCtx, isiConfig.EndpointURL, *isiConfig.SkipCertificateValidation, @@ -1242,28 +1245,65 @@ func (s *service) WithRP(key string) string { } func (s *service) validateIsiPath(ctx context.Context, volName string) (string, error) { + ctx, log := GetLogger(ctx) if s.k8sclient == nil { return "", errors.New("no k8s clientset") } - pvc, err := s.k8sclient.CoreV1().PersistentVolumes().Get(ctx, volName, v1.GetOptions{}) + pv, err := s.k8sclient.CoreV1().PersistentVolumes().Get(ctx, volName, v1.GetOptions{}) if err != nil { return "", fmt.Errorf("unable to get PersistentVolume: %w", err) } - if pvc.Spec.StorageClassName == "" { + // check pv for IsiPath + // will be in VolumeAttributes like: + // Path: IsiPath/volumeName + if pv.Spec.CSI != nil && pv.Spec.CSI.VolumeAttributes != nil { + if pv.Spec.CSI.VolumeAttributes[ExportPathParam] != "" { + exportPath := pv.Spec.CSI.VolumeAttributes[ExportPathParam] + isiPath := isilonfs.GetIsiPathFromExportPath(exportPath) + log.Debug("Found IsiPath from PersistentVolume: ", isiPath) + return isiPath, nil + } + } + + log.Debug("IsiPath not found in PersistentVolume") + + // if we cannot find IsiPath in VolumeAttributes, check StorageClass next + if pv.Spec.StorageClassName == "" { + log.Debug("StorageClass not found in PersistentVolume") return "", nil } - sc, err := s.k8sclient.StorageV1().StorageClasses().Get(ctx, pvc.Spec.StorageClassName, v1.GetOptions{}) + log.Debug("Checking StorageClass: ", pv.Spec.StorageClassName) + + sc, err := s.k8sclient.StorageV1().StorageClasses().Get(ctx, pv.Spec.StorageClassName, v1.GetOptions{}) if err != nil { return "", fmt.Errorf("unable to get StorageClass: %w", err) } isiPath, ok := sc.Parameters[IsiPathParam] if !ok || isiPath == "" { + log.Debug("IsiPath not found in StorageClass") return "", nil } return isiPath, nil } + +func getExportPathFromExportID(ctx context.Context, isiConfig *IsilonClusterConfig, exportID int, accessZone string) (string, error) { + ctx, log, _ := GetRunIDLog(ctx) + export, err := isiConfig.isiSvc.GetExportByIDWithZone(ctx, exportID, accessZone) + if err != nil { + log.Error("Failed to get export with error: " + err.Error()) + return "", status.Error(codes.NotFound, err.Error()) + } + if len(*export.Paths) == 0 { + return "", status.Error(codes.NotFound, fmt.Sprintf("can't find paths for export with ID %d", exportID)) + } + log.Debugf("Export paths are: %v", export.Paths) + exportPath := (*export.Paths)[0] + log.Debugf("Returning export path: %s", exportPath) + + return exportPath, nil +} From 01b9d24f584a91b2a5b352ae4911e36bd9cea321 Mon Sep 17 00:00:00 2001 From: francis-nijay Date: Mon, 3 Nov 2025 09:24:00 -0500 Subject: [PATCH 2/4] Release v2.15.1 changes --- go.sum | 24 ++++++++++++------------ service/service.go | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/go.sum b/go.sum index 5c1d640a..6b278b31 100644 --- a/go.sum +++ b/go.sum @@ -600,8 +600,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -678,8 +678,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -755,8 +755,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -768,8 +768,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -784,8 +784,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -834,8 +834,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= -golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/service/service.go b/service/service.go index d9bc64c1..5a0025e4 100644 --- a/service/service.go +++ b/service/service.go @@ -31,7 +31,7 @@ import ( "github.com/akutz/gournal" "github.com/dell/csi-isilon/v2/common/k8sutils" - isilonfs "github.com/dell/csi-powerscale/v2/common/utils/powerscale-fs" + isilonfs "github.com/dell/csi-isilon/v2/common/utils/powerscale-fs" "google.golang.org/grpc" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/types/known/wrapperspb" From 69aeea259b957e854270be753490b211d31b9a13 Mon Sep 17 00:00:00 2001 From: francis-nijay Date: Mon, 3 Nov 2025 09:26:35 -0500 Subject: [PATCH 3/4] Release v2.15.1 changes --- service/node_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/node_test.go b/service/node_test.go index 7abf1b1e..a51a140c 100644 --- a/service/node_test.go +++ b/service/node_test.go @@ -29,9 +29,9 @@ import ( "github.com/container-storage-interface/spec/lib/go/csi" isi "github.com/dell/goisilon" + v1 "github.com/dell/goisilon/api/v1" + v2 "github.com/dell/goisilon/api/v2" isimocks "github.com/dell/goisilon/mocks" - v1 "github.com/dell/gopowerscale/api/v1" - v2 "github.com/dell/gopowerscale/api/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "golang.org/x/net/context" From f360b6f80b9ed3d4e5c05aa432427b1a188be91f Mon Sep 17 00:00:00 2001 From: francis-nijay Date: Fri, 7 Nov 2025 01:48:07 -0500 Subject: [PATCH 4/4] Fix lint error --- test/integration/step_defs_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/step_defs_test.go b/test/integration/step_defs_test.go index bdafd063..f21e9ab8 100644 --- a/test/integration/step_defs_test.go +++ b/test/integration/step_defs_test.go @@ -319,7 +319,7 @@ func (f *feature) thereIsAnExport(name string) error { accessZone := f.vol.VolumeContext["AccessZone"] path := isilonfs.GetPathForVolume(f.isiPath, name) export, err := isiClient.GetExportByIDWithZone(ctx, f.exportID, accessZone) - //export, err := isiClient.GetExportWithPathAndZone(ctx, path, accessZone) + // export, err := isiClient.GetExportWithPathAndZone(ctx, path, accessZone) fmt.Printf("export is: '%v'\n", export) if err != nil || export == nil { f.addError(err)