diff --git a/cmd/main.go b/cmd/main.go index efbd737b..76ed9b7c 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -32,8 +32,8 @@ import ( "github.com/IBM/ibm-csi-common/pkg/metrics" mountManager "github.com/IBM/ibm-csi-common/pkg/mountmanager" "github.com/IBM/ibm-csi-common/pkg/utils" - "github.com/IBM/ibm-csi-common/pkg/watcher" cloudProvider "github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider" + "github.com/IBM/ibmcloud-volume-vpc/pkg/watcher" csiConfig "github.com/kubernetes-sigs/ibm-vpc-block-csi-driver/config" driver "github.com/kubernetes-sigs/ibm-vpc-block-csi-driver/pkg/ibmcsidriver" "go.uber.org/zap" diff --git a/go.mod b/go.mod index b8ca958b..90f8dd07 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ go 1.22.0 require ( github.com/IBM/ibm-csi-common v1.1.15 - github.com/IBM/ibmcloud-volume-interface v1.2.6 - github.com/IBM/ibmcloud-volume-vpc v1.1.11 + github.com/IBM/ibmcloud-volume-interface v1.2.9 + github.com/IBM/ibmcloud-volume-vpc v1.1.14 github.com/IBM/secret-utils-lib v1.1.11 github.com/container-storage-interface/spec v1.9.0 github.com/golang/glog v1.2.1 diff --git a/go.sum b/go.sum index 0ad862bd..c486aa9a 100644 --- a/go.sum +++ b/go.sum @@ -8,10 +8,10 @@ github.com/IBM/go-sdk-core/v5 v5.17.4 h1:VGb9+mRrnS2HpHZFM5hy4J6ppIWnwNrw0G+tLSg github.com/IBM/go-sdk-core/v5 v5.17.4/go.mod h1:KsAAI7eStAWwQa4F96MLy+whYSh39JzNjklZRbN/8ns= github.com/IBM/ibm-csi-common v1.1.15 h1:oJ0NsrVBqfXKCZXSc/EI+s7/RlUK/TpzTI+jcdoAqpI= github.com/IBM/ibm-csi-common v1.1.15/go.mod h1:oKYsmovJ4HAmbHfhQvVn1dJ+xeQHqaa3hQsN/Z5itlc= -github.com/IBM/ibmcloud-volume-interface v1.2.6 h1:OLumrSQ0XTOp6gW+k0z2X53uTYOIt1wWSkTCXzK/vAM= -github.com/IBM/ibmcloud-volume-interface v1.2.6/go.mod h1:sDeQiPuN8k9yTRl9FbE2GZCXPNg4cV3oldUfL8wwGNA= -github.com/IBM/ibmcloud-volume-vpc v1.1.11 h1:HnDPi7ZN+iAPVLZ29sLeQnJ7y0lvorc8/q4csDnxht4= -github.com/IBM/ibmcloud-volume-vpc v1.1.11/go.mod h1:V4Xw+ETu4nnIHn8lZ8T/tD6UlCTSDLt4kT8oEs4o80w= +github.com/IBM/ibmcloud-volume-interface v1.2.9 h1:ug55V2mzK/IaFkfuKDOt74yzhLapSR/+qVgfQblfAjw= +github.com/IBM/ibmcloud-volume-interface v1.2.9/go.mod h1:sDeQiPuN8k9yTRl9FbE2GZCXPNg4cV3oldUfL8wwGNA= +github.com/IBM/ibmcloud-volume-vpc v1.1.14 h1:rs8f4OO+lP3jOIi5tpgiWVyVEL6g4lazGfMEsLpsfUI= +github.com/IBM/ibmcloud-volume-vpc v1.1.14/go.mod h1:CSAsBgEXN6WL8y/EpEj9GA+w+vs3fVLoRadtuCWUAz8= github.com/IBM/secret-common-lib v1.1.11 h1:EpfEe1gT1bnFQ3bxQPrh6bzTPeGjUo1NReVkCCP+TOc= github.com/IBM/secret-common-lib v1.1.11/go.mod h1:7YJF0ipT979nHIPkiCpvjFboFoIhrmYnIliE1vjCjZM= github.com/IBM/secret-utils-lib v1.1.11 h1:w87BzkddoFFlhRuWRteuGj3/561lEUg6Oo0RajVC87A= @@ -121,8 +121,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -299,8 +299,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= 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/pkg/ibmcsidriver/controller.go b/pkg/ibmcsidriver/controller.go index 01301a08..eae5c9c9 100644 --- a/pkg/ibmcsidriver/controller.go +++ b/pkg/ibmcsidriver/controller.go @@ -22,7 +22,6 @@ import ( "strings" "time" - cloudProvider "github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider" commonError "github.com/IBM/ibm-csi-common/pkg/messages" "github.com/IBM/ibm-csi-common/pkg/metrics" "github.com/IBM/ibm-csi-common/pkg/utils" @@ -30,6 +29,7 @@ import ( providerError "github.com/IBM/ibmcloud-volume-interface/lib/utils" utilReasonCode "github.com/IBM/ibmcloud-volume-interface/lib/utils/reasoncode" userError "github.com/IBM/ibmcloud-volume-vpc/common/messages" + cloudProvider "github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider" csi "github.com/container-storage-interface/spec/lib/go/csi" "go.uber.org/zap" diff --git a/pkg/ibmcsidriver/controller_helper_test.go b/pkg/ibmcsidriver/controller_helper_test.go index d8592630..f69d6552 100644 --- a/pkg/ibmcsidriver/controller_helper_test.go +++ b/pkg/ibmcsidriver/controller_helper_test.go @@ -21,10 +21,10 @@ import ( "fmt" "testing" - cloudProvider "github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider" "github.com/IBM/ibm-csi-common/pkg/utils" "github.com/IBM/ibmcloud-volume-interface/config" "github.com/IBM/ibmcloud-volume-interface/lib/provider" + cloudProvider "github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider" csi "github.com/container-storage-interface/spec/lib/go/csi" "github.com/stretchr/testify/assert" ) @@ -177,9 +177,8 @@ func TestGetVolumeParameters(t *testing.T) { }, expectedVolume: &provider.Volume{Name: &volumeName, Capacity: &volumeSize, - VPCVolume: provider.VPCVolume{VPCBlockVolume: provider.VPCBlockVolume{ - Tags: []string{createdByIBM}, - }, + VPCVolume: provider.VPCVolume{ + Tags: []string{createdByIBM}, Profile: &provider.Profile{Name: "general-purpose"}, ResourceGroup: &provider.ResourceGroup{ID: "myresourcegroups"}, }, @@ -312,9 +311,8 @@ func TestGetVolumeParameters(t *testing.T) { }, expectedVolume: &provider.Volume{Name: &volumeName, Capacity: &volumeSize, - VPCVolume: provider.VPCVolume{VPCBlockVolume: provider.VPCBlockVolume{ - Tags: []string{createdByIBM}, - }, + VPCVolume: provider.VPCVolume{ + Tags: []string{createdByIBM}, Profile: &provider.Profile{Name: "general-purpose"}, ResourceGroup: &provider.ResourceGroup{ID: "myresourcegroups"}, }, @@ -444,9 +442,8 @@ func TestOverrideParams(t *testing.T) { }, expectedVolume: &provider.Volume{Name: &volumeName, Capacity: &volumeSize, - VPCVolume: provider.VPCVolume{VPCBlockVolume: provider.VPCBlockVolume{ - Tags: []string{createdByIBM}, - }, + VPCVolume: provider.VPCVolume{ + Tags: []string{createdByIBM}, Profile: &provider.Profile{Name: "general-purpose"}, ResourceGroup: &provider.ResourceGroup{ID: "secret-rg"}, }, @@ -530,9 +527,8 @@ func TestOverrideParams(t *testing.T) { }, expectedVolume: &provider.Volume{Name: &volumeName, Capacity: &volumeSize, - VPCVolume: provider.VPCVolume{VPCBlockVolume: provider.VPCBlockVolume{ - Tags: []string{createdByIBM}, - }, + VPCVolume: provider.VPCVolume{ + Tags: []string{createdByIBM}, Profile: &provider.Profile{Name: "custom"}, ResourceGroup: &provider.ResourceGroup{ID: "myresourcegroups"}, }, @@ -650,9 +646,8 @@ func TestCreateCSIVolumeResponse(t *testing.T) { { testCaseName: "Valid volume response", requestVol: provider.Volume{VolumeID: volumeID, - VPCVolume: provider.VPCVolume{VPCBlockVolume: provider.VPCBlockVolume{ - Tags: []string{createdByIBM}, - }, + VPCVolume: provider.VPCVolume{ + Tags: []string{createdByIBM}, Profile: &provider.Profile{Name: "general-purpose"}, ResourceGroup: &provider.ResourceGroup{ID: "myresourcegroups"}, }, @@ -682,9 +677,8 @@ func TestCreateCSIVolumeResponse(t *testing.T) { { testCaseName: "Valid volume response with region in vol request empty", requestVol: provider.Volume{VolumeID: volumeID, - VPCVolume: provider.VPCVolume{VPCBlockVolume: provider.VPCBlockVolume{ - Tags: []string{createdByIBM}, - }, + VPCVolume: provider.VPCVolume{ + Tags: []string{createdByIBM}, Profile: &provider.Profile{Name: "general-purpose"}, ResourceGroup: &provider.ResourceGroup{ID: "myresourcegroups"}, }, diff --git a/pkg/ibmcsidriver/controller_test.go b/pkg/ibmcsidriver/controller_test.go index 0978015c..f4496247 100644 --- a/pkg/ibmcsidriver/controller_test.go +++ b/pkg/ibmcsidriver/controller_test.go @@ -33,8 +33,8 @@ import ( csi "github.com/container-storage-interface/spec/lib/go/csi" "github.com/stretchr/testify/assert" - cloudProvider "github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider" "github.com/IBM/ibmcloud-volume-interface/lib/provider/fake" + cloudProvider "github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider" "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/pkg/ibmcsidriver/fileOps_test.go b/pkg/ibmcsidriver/fileOps_test.go index b264bc8e..6e92b06a 100644 --- a/pkg/ibmcsidriver/fileOps_test.go +++ b/pkg/ibmcsidriver/fileOps_test.go @@ -21,7 +21,7 @@ import ( "os" "testing" - cloudProvider "github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider" + cloudProvider "github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider" "github.com/kubernetes-sigs/ibm-vpc-block-csi-driver/pkg/ibmcsidriver/ibmcsidriverfakes" "github.com/stretchr/testify/assert" ) diff --git a/pkg/ibmcsidriver/ibm_csi_driver.go b/pkg/ibmcsidriver/ibm_csi_driver.go index e70c88bb..b00dadd0 100644 --- a/pkg/ibmcsidriver/ibm_csi_driver.go +++ b/pkg/ibmcsidriver/ibm_csi_driver.go @@ -20,11 +20,11 @@ package ibmcsidriver import ( "fmt" - cloudProvider "github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider" commonError "github.com/IBM/ibm-csi-common/pkg/messages" nodeMetadata "github.com/IBM/ibm-csi-common/pkg/metadata" mountManager "github.com/IBM/ibm-csi-common/pkg/mountmanager" "github.com/IBM/ibm-csi-common/pkg/utils" + cloudProvider "github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider" csi "github.com/container-storage-interface/spec/lib/go/csi" "go.uber.org/zap" ) diff --git a/pkg/ibmcsidriver/ibm_csi_driver_test.go b/pkg/ibmcsidriver/ibm_csi_driver_test.go index 7ae572cf..0e1e5b21 100644 --- a/pkg/ibmcsidriver/ibm_csi_driver_test.go +++ b/pkg/ibmcsidriver/ibm_csi_driver_test.go @@ -21,10 +21,10 @@ import ( testingexec "k8s.io/utils/exec/testing" "testing" - cloudProvider "github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider" nodeMetadata "github.com/IBM/ibm-csi-common/pkg/metadata" nodeInfo "github.com/IBM/ibm-csi-common/pkg/metadata/fake" mountManager "github.com/IBM/ibm-csi-common/pkg/mountmanager" + cloudProvider "github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider" "github.com/stretchr/testify/assert" ) diff --git a/pkg/ibmcsidriver/node_helper_test.go b/pkg/ibmcsidriver/node_helper_test.go index 61403a09..c3f00627 100644 --- a/pkg/ibmcsidriver/node_helper_test.go +++ b/pkg/ibmcsidriver/node_helper_test.go @@ -19,7 +19,7 @@ package ibmcsidriver import ( "testing" - cloudProvider "github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider" + cloudProvider "github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider" "github.com/stretchr/testify/assert" ) diff --git a/pkg/ibmcsidriver/server_test.go b/pkg/ibmcsidriver/server_test.go index 62dead26..1f651eec 100644 --- a/pkg/ibmcsidriver/server_test.go +++ b/pkg/ibmcsidriver/server_test.go @@ -21,7 +21,7 @@ import ( "flag" "testing" - cloudProvider "github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider" + cloudProvider "github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider" "github.com/stretchr/testify/assert" ) diff --git a/tests/sanity/sanity_test.go b/tests/sanity/sanity_test.go index 1a9f56b4..e67b43ad 100644 --- a/tests/sanity/sanity_test.go +++ b/tests/sanity/sanity_test.go @@ -41,8 +41,8 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - cloudProvider "github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider" nodeMetadata "github.com/IBM/ibm-csi-common/pkg/metadata" + cloudProvider "github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider" mountManager "github.com/IBM/ibm-csi-common/pkg/mountmanager" diff --git a/vendor/github.com/IBM/ibmcloud-volume-interface/lib/provider/vpc_data_types.go b/vendor/github.com/IBM/ibmcloud-volume-interface/lib/provider/vpc_data_types.go index caa396ad..92e1e600 100644 --- a/vendor/github.com/IBM/ibmcloud-volume-interface/lib/provider/vpc_data_types.go +++ b/vendor/github.com/IBM/ibmcloud-volume-interface/lib/provider/vpc_data_types.go @@ -26,13 +26,14 @@ type VPCVolume struct { VolumeEncryptionKey *VolumeEncryptionKey `json:"encryption_key,omitempty"` Profile *Profile `json:"profile,omitempty"` CRN string `json:"crn,omitempty"` + Status string `json:"status,omitempty"` + Tags []string `json:"volume_tags,omitempty"` VPCBlockVolume VPCFileVolume } // VPCBlockVolume specific parameters type VPCBlockVolume struct { - Tags []string `json:"volume_tags,omitempty"` VolumeAttachments *[]VolumeAttachment `json:"volume_attachments,omitempty"` } diff --git a/vendor/github.com/IBM/ibmcloud-volume-vpc/block/provider/create_volume.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/block/provider/create_volume.go index aa882cbe..37210c17 100644 --- a/vendor/github.com/IBM/ibmcloud-volume-vpc/block/provider/create_volume.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/block/provider/create_volume.go @@ -30,6 +30,7 @@ import ( const ( customProfile = "custom" + sdpProfile = "sdp" minSize = 10 ) @@ -121,13 +122,6 @@ func validateVolumeRequest(volumeRequest *provider.Volume, clusterVolumeLabel st return resourceGroup, iops, userError.GetUserError("InvalidVolumeName", nil, *volumeRequest.Name) } - // Capacity should not be empty - if volumeRequest.Capacity == nil { - return resourceGroup, iops, userError.GetUserError("VolumeCapacityInvalid", nil, nil) - } else if *volumeRequest.Capacity < minSize { - return resourceGroup, iops, userError.GetUserError("VolumeCapacityInvalid", nil, *volumeRequest.Capacity) - } - // Read user provided error, no harm to pass the 0 values to RIaaS in case of tiered profiles if volumeRequest.Iops != nil { iops = ToInt64(*volumeRequest.Iops) @@ -135,7 +129,19 @@ func validateVolumeRequest(volumeRequest *provider.Volume, clusterVolumeLabel st if volumeRequest.VPCVolume.Profile == nil { return resourceGroup, iops, userError.GetUserError("VolumeProfileEmpty", nil) } - if volumeRequest.VPCVolume.Profile.Name != customProfile && iops > 0 { + + // Capacity should not be empty + if volumeRequest.Capacity == nil { + return resourceGroup, iops, userError.GetUserError("VolumeCapacityInvalid", nil, nil) + } + + // Minimum Capacity validation for non SDP profiles. + if *volumeRequest.Capacity < minSize && volumeRequest.VPCVolume.Profile.Name != sdpProfile { + return resourceGroup, iops, userError.GetUserError("VolumeCapacityInvalid", nil, *volumeRequest.Capacity) + } + + // IOPS not modifiable if profile is not custom or sdp + if (volumeRequest.VPCVolume.Profile.Name != customProfile && volumeRequest.VPCVolume.Profile.Name != sdpProfile) && iops > 0 { return resourceGroup, iops, userError.GetUserError("VolumeProfileIopsInvalid", nil) } diff --git a/vendor/github.com/IBM/ibmcloud-volume-vpc/block/provider/update_volume.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/block/provider/update_volume.go index 5f4c00d4..c766290b 100644 --- a/vendor/github.com/IBM/ibmcloud-volume-vpc/block/provider/update_volume.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/block/provider/update_volume.go @@ -18,12 +18,77 @@ package provider import ( - "errors" + "strings" "github.com/IBM/ibmcloud-volume-interface/lib/provider" + userError "github.com/IBM/ibmcloud-volume-vpc/common/messages" + "github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/models" + "go.uber.org/zap" ) -// UpdateVolume POSTs to /volumes -func (vpc *VPCSession) UpdateVolume(volumeTemplate provider.Volume) error { - return errors.New("unsupported Operation") +// UpdateVolume PATCH to /volumes +func (vpcs *VPCSession) UpdateVolume(volumeRequest provider.Volume) error { + var existVolume *models.Volume + var err error + var etag string + + //Fetch existing volume Tags + err = RetryWithMinRetries(vpcs.Logger, func() error { + // Get volume details + existVolume, etag, err = vpcs.Apiclient.VolumeService().GetVolumeEtag(volumeRequest.VolumeID, vpcs.Logger) + + if err != nil { + return err + } + if existVolume != nil && existVolume.Status == validVolumeStatus { + vpcs.Logger.Info("Volume got valid (available) state",zap.Reflect("etag", etag)) + return nil + } + return userError.GetUserError("VolumeNotInValidState", err, volumeRequest.VolumeID) + }) + + if err != nil { + return err + } + + //If tags are equal then skip the UpdateVolume RIAAS API call + if ifTagsEqual(existVolume.UserTags, volumeRequest.VPCVolume.Tags) { + vpcs.Logger.Info("There is no change in user tags for volume, skipping the updateVolume for VPC IaaS... ", zap.Reflect("existVolume", existVolume.UserTags), zap.Reflect("volumeRequest", volumeRequest.VPCVolume.Tags)) + return nil + } + + //Append the existing tags with the requested input tags + existVolume.UserTags = append(existVolume.UserTags, volumeRequest.VPCVolume.Tags...) + + volume := &models.Volume{ + UserTags: existVolume.UserTags, + } + + vpcs.Logger.Info("Calling VPC provider for volume UpdateVolumeWithTags...") + + err = RetryWithMinRetries(vpcs.Logger, func() error { + err = vpcs.Apiclient.VolumeService().UpdateVolumeWithEtag(volumeRequest.VolumeID, etag, volume, vpcs.Logger) + return err + }) + + if err != nil { + vpcs.Logger.Error("Failed to update volume tags from VPC provider", zap.Reflect("BackendError", err)) + return userError.GetUserError("FailedToUpdateVolume", err, volumeRequest.VolumeID) + } + + return err +} + +// ifTagsEqual will check if there is change to existing tags +func ifTagsEqual(existingTags []string, newTags []string) bool { + //Join slice into a string + tags := strings.ToLower(strings.Join(existingTags, ",")) + for _, v := range newTags { + if !strings.Contains(tags, strings.ToLower(v)) { + //Tags are different + return false + } + } + //Tags are equal + return true } diff --git a/vendor/github.com/IBM/ibmcloud-volume-vpc/block/provider/util.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/block/provider/util.go index c7289d71..e1e9ca8f 100644 --- a/vendor/github.com/IBM/ibmcloud-volume-vpc/block/provider/util.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/block/provider/util.go @@ -31,6 +31,9 @@ import ( // maxRetryAttempt ... var maxRetryAttempt = 10 +// minRetryAttempt ... +var minRetryAttempt = 3 + // maxRetryGap ... var maxRetryGap = 60 @@ -71,6 +74,7 @@ var skipErrorCodes = map[string]bool{ SnapshotIDNotFound: true, "snapshots_source_volume_not_found": true, "snapshots_source_volume_not_attached": true, + "volume_capacity_maximum": true, // IKS ms error code for skip re-try "ST0008": true, //resources not found @@ -118,6 +122,41 @@ func retry(logger *zap.Logger, retryfunc func() error) error { return err } +// retry ... +func RetryWithMinRetries(logger *zap.Logger, retryfunc func() error) error { + var err error + retryGap := 10 + for i := 0; i < minRetryAttempt; i++ { + if i > 0 { + time.Sleep(time.Duration(retryGap) * time.Second) + } + err = retryfunc() + if err != nil { + logger.Info("err object is not nil", zap.Reflect("ERR", err)) + //Skip retry for the below type of Errors + modelError, ok := err.(*models.Error) + if !ok { + continue + } + if skipRetry(modelError) { + break + } + if i >= 1 { + retryGap = 2 * retryGap + if retryGap > maxRetryGap { + retryGap = maxRetryGap + } + } + if (i + 1) < minRetryAttempt { + logger.Info("Error while executing the function. Re-attempting execution ..", zap.Int("attempt..", i+2), zap.Int("retry-gap", retryGap), zap.Int("max-retry-Attempts", minRetryAttempt), zap.Error(err)) + } + continue + } + return err + } + return err +} + // skipRetry skip retry as per listed error codes func skipRetry(err *models.Error) bool { for _, errorItem := range err.Errors { @@ -350,6 +389,7 @@ func FromProviderToLibVolume(vpcVolume *models.Volume, logger *zap.Logger) (libV } libVolume.CRN = vpcVolume.CRN libVolume.Tags = vpcVolume.UserTags + libVolume.Status = string(vpcVolume.Status) return } diff --git a/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/client/request.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/client/request.go index 8ba71f20..a9674736 100644 --- a/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/client/request.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/client/request.go @@ -126,6 +126,12 @@ func (r *Request) SetQueryValue(key, value string) *Request { return r } +// SetHeader ... +func (r *Request) SetHeader(key, value string) *Request { + r.headers.Set(key, value) + return r +} + // JSONBody converts the supplied argument to JSON to use as the body of a request func (r *Request) JSONBody(p interface{}) *Request { if r.operation.Method == http.MethodPost && reflect.ValueOf(p).Kind() == reflect.Struct { diff --git a/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/get_volume.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/get_volume.go index f8d43646..34d935e2 100644 --- a/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/get_volume.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/get_volume.go @@ -47,6 +47,7 @@ func (vs *VolumeService) GetVolume(volumeID string, ctxLogger *zap.Logger) (*mod req := request.PathParameter(volumeIDParam, volumeID) _, err := req.JSONSuccess(&volume).JSONError(&apiErr).Invoke() + if err != nil { return nil, err } diff --git a/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/get_volume_etag.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/get_volume_etag.go new file mode 100644 index 00000000..6b27bf72 --- /dev/null +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/get_volume_etag.go @@ -0,0 +1,56 @@ +/** + * Copyright 2025 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Package vpcvolume ... +package vpcvolume + +import ( + "time" + + util "github.com/IBM/ibmcloud-volume-interface/lib/utils" + "github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/client" + "github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/models" + "go.uber.org/zap" +) + +// GetVolume POSTs to /volumes +func (vs *VolumeService) GetVolumeEtag(volumeID string, ctxLogger *zap.Logger) (*models.Volume, string, error) { + ctxLogger.Debug("Entry Backend GetVolumeEtag") + defer ctxLogger.Debug("Exit Backend GetVolumeEtag") + + defer util.TimeTracker("GetVolumeEtag", time.Now()) + + operation := &client.Operation{ + Name: "GetVolume", + Method: "GET", + PathPattern: volumeIDPath, + } + + var volume models.Volume + var apiErr models.Error + + request := vs.client.NewRequest(operation) + ctxLogger.Info("Equivalent curl command", zap.Reflect("URL", request.URL()), zap.Reflect("Operation", operation)) + + req := request.PathParameter(volumeIDParam, volumeID) + resp, err := req.JSONSuccess(&volume).JSONError(&apiErr).Invoke() + + if err != nil { + return nil, "", err + } + + return &volume, resp.Header.Get("etag"), nil +} diff --git a/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/update_volume.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/update_volume.go index 78bfdc82..2a8f377d 100644 --- a/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/update_volume.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/update_volume.go @@ -24,7 +24,7 @@ import ( "go.uber.org/zap" ) -// UpdateVolume POSTs to /volumes. Riaas/VPC does have volume update support yet +// UpdateVolume PATCH to /volumes for updating func (vs *VolumeService) UpdateVolume(volumeTemplate *models.Volume, ctxLogger *zap.Logger) error { return errors.New("unsupported Operation") } diff --git a/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/update_volume_with_etag.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/update_volume_with_etag.go new file mode 100644 index 00000000..69bd797a --- /dev/null +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/update_volume_with_etag.go @@ -0,0 +1,56 @@ +/** + * Copyright 2025 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Package vpcvolume ... +package vpcvolume + +import ( + "time" + + util "github.com/IBM/ibmcloud-volume-interface/lib/utils" + "github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/client" + "github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/models" + "go.uber.org/zap" +) + +// UpdateVolume PATCH to /volumes for updating user tags only +func (vs *VolumeService) UpdateVolumeWithEtag(volumeID string, etag string, volumeTemplate *models.Volume, ctxLogger *zap.Logger) error { + ctxLogger.Debug("Entry Backend UpdateVolumeWithEtag") + defer ctxLogger.Debug("Exit Backend UpdateVolumeWithEtag") + + defer util.TimeTracker("UpdateVolumeWithEtag", time.Now()) + + operation := &client.Operation{ + Name: "UpdateVolume", + Method: "PATCH", + PathPattern: volumeIDPath, + } + + var apiErr models.Error + + request := vs.client.NewRequest(operation) + request.SetHeader("If-Match", etag) + + req := request.PathParameter(volumeIDParam, volumeID) + ctxLogger.Info("Equivalent curl command and payload details", zap.Reflect("URL", req.URL()), zap.Reflect("Payload", volumeTemplate), zap.Reflect("Operation", operation)) + _, err := req.JSONBody(volumeTemplate).JSONError(&apiErr).Invoke() + + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/volume_service.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/volume_service.go index 0569f566..9f4537e0 100644 --- a/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/volume_service.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume/volume_service.go @@ -24,12 +24,18 @@ import ( ) // VolumeManager operations +// +//go:generate counterfeiter -o fakes/volume.go --fake-name VolumeService . VolumeManager type VolumeManager interface { // Create the volume with authorisation by passing required information in the volume object CreateVolume(volumeTemplate *models.Volume, ctxLogger *zap.Logger) (*models.Volume, error) + // UpdateVolume updates the volume with authorisation by passing required information in the volume object UpdateVolume(volumeTemplate *models.Volume, ctxLogger *zap.Logger) error + // UpdateVolumeWithEtag updates the volume with tags by passing etag in header + UpdateVolumeWithEtag(volumeID string, etag string, volumeTemplate *models.Volume, ctxLogger *zap.Logger) error + // ExpandVolume ... ExpandVolume(volumeID string, volumeTemplate *models.Volume, ctxLogger *zap.Logger) (*models.Volume, error) @@ -42,6 +48,9 @@ type VolumeManager interface { // Get the volume by using volume name GetVolumeByName(volumeName string, ctxLogger *zap.Logger) (*models.Volume, error) + // Get the volume etag by using ID + GetVolumeEtag(volumeID string, ctxLogger *zap.Logger) (*models.Volume, string, error) + // Others // Get volume lists by using snapshot tags ListVolumes(limit int, start string, filters *models.ListVolumeFilters, ctxLogger *zap.Logger) (*models.VolumeList, error) diff --git a/vendor/github.com/IBM/ibmcloud-volume-vpc/iks/provider/session.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/iks/provider/session.go index ba570f1a..1948df4f 100644 --- a/vendor/github.com/IBM/ibmcloud-volume-vpc/iks/provider/session.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/iks/provider/session.go @@ -61,35 +61,35 @@ func (vpcIks *IksVpcSession) Type() provider.VolumeType { // AttachVolume attach volume based on given volume attachment request func (vpcIks *IksVpcSession) AttachVolume(volumeAttachmentRequest provider.VolumeAttachmentRequest) (*provider.VolumeAttachmentResponse, error) { - vpcIks.Logger.Debug("Entry of IksVpcSession.AttachVolume method...") - defer vpcIks.Logger.Debug("Exit from IksVpcSession.AttachVolume method...") + vpcIks.IksSession.Logger.Debug("Entry of IksVpcSession.AttachVolume method...") + defer vpcIks.IksSession.Logger.Debug("Exit from IksVpcSession.AttachVolume method...") return vpcIks.IksSession.AttachVolume(volumeAttachmentRequest) } // DetachVolume attach volume based on given volume attachment request func (vpcIks *IksVpcSession) DetachVolume(volumeAttachmentRequest provider.VolumeAttachmentRequest) (*http.Response, error) { vpcIks.IksSession.Logger.Debug("Entry of IksVpcSession.DetachVolume method...") - defer vpcIks.Logger.Debug("Exit from IksVpcSession.DetachVolume method...") + defer vpcIks.IksSession.Logger.Debug("Exit from IksVpcSession.DetachVolume method...") return vpcIks.IksSession.DetachVolume(volumeAttachmentRequest) } // GetVolumeAttachment attach volume based on given volume attachment request func (vpcIks *IksVpcSession) GetVolumeAttachment(volumeAttachmentRequest provider.VolumeAttachmentRequest) (*provider.VolumeAttachmentResponse, error) { - vpcIks.Logger.Debug("Entry of IksVpcSession.GetVolumeAttachment method...") - defer vpcIks.Logger.Debug("Exit from IksVpcSession.GetVolumeAttachment method...") + vpcIks.IksSession.Logger.Debug("Entry of IksVpcSession.GetVolumeAttachment method...") + defer vpcIks.IksSession.Logger.Debug("Exit from IksVpcSession.GetVolumeAttachment method...") return vpcIks.IksSession.GetVolumeAttachment(volumeAttachmentRequest) } // WaitForAttachVolume attach volume based on given volume attachment request func (vpcIks *IksVpcSession) WaitForAttachVolume(volumeAttachmentRequest provider.VolumeAttachmentRequest) (*provider.VolumeAttachmentResponse, error) { - vpcIks.Logger.Debug("Entry of IksVpcSession.WaitForAttachVolume method...") - defer vpcIks.Logger.Debug("Exit from IksVpcSession.WaitForAttachVolume method...") + vpcIks.IksSession.Logger.Debug("Entry of IksVpcSession.WaitForAttachVolume method...") + defer vpcIks.IksSession.Logger.Debug("Exit from IksVpcSession.WaitForAttachVolume method...") return vpcIks.IksSession.WaitForAttachVolume(volumeAttachmentRequest) } // WaitForDetachVolume attach volume based on given volume attachment request func (vpcIks *IksVpcSession) WaitForDetachVolume(volumeAttachmentRequest provider.VolumeAttachmentRequest) error { - vpcIks.Logger.Debug("Entry of IksVpcSession.WaitForDetachVolume method...") - defer vpcIks.Logger.Debug("Exit from IksVpcSession.WaitForDetachVolume method...") + vpcIks.IksSession.Logger.Debug("Entry of IksVpcSession.WaitForDetachVolume method...") + defer vpcIks.IksSession.Logger.Debug("Exit from IksVpcSession.WaitForDetachVolume method...") return vpcIks.IksSession.WaitForDetachVolume(volumeAttachmentRequest) } diff --git a/vendor/github.com/IBM/ibmcloud-volume-vpc/iks/provider/update_volume.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/iks/provider/update_volume.go index a70dafb2..9fbda549 100644 --- a/vendor/github.com/IBM/ibmcloud-volume-vpc/iks/provider/update_volume.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/iks/provider/update_volume.go @@ -54,7 +54,7 @@ func (vpcIks *IksVpcSession) UpdateVolume(volumeRequest provider.Volume) (err er vpcIks.Logger.Debug("Failed to update volume", zap.Reflect("BackendError", err)) return userError.GetUserError("UpdateFailed", err) } - + vpcIks.Logger.Info("Successfully updated volume...") return err } diff --git a/vendor/github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider/fake_volume_provider.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider/fake_volume_provider.go similarity index 96% rename from vendor/github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider/fake_volume_provider.go rename to vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider/fake_volume_provider.go index 486752b4..817a8884 100644 --- a/vendor/github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider/fake_volume_provider.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider/fake_volume_provider.go @@ -1,5 +1,5 @@ /** - * Copyright 2021 IBM Corp. + * Copyright 2025 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,15 +18,15 @@ package ibmcloudprovider import ( - "bytes" + "bytes" "testing" - "github.com/IBM/ibmcloud-volume-interface/config" "github.com/IBM/ibmcloud-volume-interface/lib/provider" "github.com/IBM/ibmcloud-volume-interface/lib/provider/fake" "go.uber.org/zap" - "go.uber.org/zap/zapcore" "golang.org/x/net/context" + "github.com/stretchr/testify/assert" + "go.uber.org/zap/zapcore" ) const ( @@ -64,7 +64,16 @@ const ( TestAPIVersion = "2019-07-02" ) -// GetTestLogger ... +// FakeIBMCloudStorageProvider Provider +type FakeIBMCloudStorageProvider struct { + ProviderName string + ProviderConfig *config.Config + ClusterID string + fakeSession *fake.FakeSession +} + +var _ CloudProviderInterface = &FakeIBMCloudStorageProvider{} + func GetTestLogger(t *testing.T) (logger *zap.Logger, teardown func()) { atom := zap.NewAtomicLevel() atom.SetLevel(zap.DebugLevel) @@ -85,24 +94,17 @@ func GetTestLogger(t *testing.T) (logger *zap.Logger, teardown func()) { ) teardown = func() { - _ = logger.Sync() + err := logger.Sync() + assert.Nil(t, err) + if t.Failed() { t.Log(buf) } } - return -} -// FakeIBMCloudStorageProvider Provider -type FakeIBMCloudStorageProvider struct { - ProviderName string - ProviderConfig *config.Config - ClusterID string - fakeSession *fake.FakeSession + return } -var _ CloudProviderInterface = &FakeIBMCloudStorageProvider{} - // NewFakeIBMCloudStorageProvider ... func NewFakeIBMCloudStorageProvider(configPath string, logger *zap.Logger) (*FakeIBMCloudStorageProvider, error) { return &FakeIBMCloudStorageProvider{ProviderName: "FakeIBMCloudStorageProvider", diff --git a/vendor/github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider/ibm_volume_provider.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider/ibm_volume_provider.go similarity index 97% rename from vendor/github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider/ibm_volume_provider.go rename to vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider/ibm_volume_provider.go index 98c4c5c0..7f572498 100644 --- a/vendor/github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider/ibm_volume_provider.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider/ibm_volume_provider.go @@ -1,5 +1,5 @@ /** - * Copyright 2021 IBM Corp. + * Copyright 2025 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider/volume_provider.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider/volume_provider.go index d24188ea..a48eb52f 100644 --- a/vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider/volume_provider.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider/volume_provider.go @@ -23,7 +23,6 @@ import ( "strings" "time" - cloudProvider "github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider" "github.com/IBM/ibmcloud-volume-interface/config" "github.com/IBM/ibmcloud-volume-interface/lib/provider" "github.com/IBM/ibmcloud-volume-interface/provider/local" @@ -44,7 +43,7 @@ type IBMCloudStorageProvider struct { ClusterID string } -var _ cloudProvider.CloudProviderInterface = &IBMCloudStorageProvider{} +var _ CloudProviderInterface = &IBMCloudStorageProvider{} // NewIBMCloudStorageProvider ... func NewIBMCloudStorageProvider(clusterVolumeLabel string, k8sClient *k8s_utils.KubernetesClient, logger *zap.Logger) (*IBMCloudStorageProvider, error) { diff --git a/vendor/github.com/IBM/ibm-csi-common/pkg/watcher/pv_watcher.go b/vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/watcher/pv_watcher.go similarity index 63% rename from vendor/github.com/IBM/ibm-csi-common/pkg/watcher/pv_watcher.go rename to vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/watcher/pv_watcher.go index 9ab79c30..f0884685 100644 --- a/vendor/github.com/IBM/ibm-csi-common/pkg/watcher/pv_watcher.go +++ b/vendor/github.com/IBM/ibmcloud-volume-vpc/pkg/watcher/pv_watcher.go @@ -1,5 +1,5 @@ /** - * Copyright 2021 IBM Corp. + * Copyright 2025 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,12 +23,16 @@ import ( "strings" "time" + uid "github.com/gofrs/uuid" + "go.uber.org/zap/zapcore" + "github.com/golang/glog" - cloudprovider "github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider" - "github.com/IBM/ibm-csi-common/pkg/utils" "github.com/IBM/ibmcloud-volume-interface/config" "github.com/IBM/ibmcloud-volume-interface/lib/provider" + iks_vpc_provider "github.com/IBM/ibmcloud-volume-vpc/iks/provider" + cloudprovider "github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider" + "go.uber.org/zap" "golang.org/x/net/context" v1 "k8s.io/api/core/v1" @@ -81,6 +85,24 @@ const ( VolumeUpdateEventReason = "VolumeMetaDataSaved" //VolumeUpdateEventSuccess ... VolumeUpdateEventSuccess = "Success" + + // VolumeIDLabel ... + VolumeIDLabel = "volumeId" + + // VolumeCRNLabel ... + VolumeCRNLabel = "volumeCRN" + + // ClusterIDLabel ... + ClusterIDLabel = "clusterID" + + // IOPSLabel ... + IOPSLabel = "iops" + + // ZoneLabel ... + ZoneLabel = "zone" + + // GiB in bytes + GiB = 1024 * 1024 * 1024 ) // VolumeTypeMap ... @@ -151,7 +173,7 @@ func (pvw *PVWatcher) Start() { func (pvw *PVWatcher) updateVolume(oldobj, obj interface{}) { // Run as non-blocking thread to allow parallel processing of volumes go func() { - ctxLogger, requestID := utils.GetContextLogger(context.Background(), false) + ctxLogger, requestID := GetContextLogger(context.Background(), false) // panic-recovery function that avoid watcher thread to stop because of unexexpected error defer func() { if r := recover(); r != nil { @@ -159,18 +181,45 @@ func (pvw *PVWatcher) updateVolume(oldobj, obj interface{}) { } }() - ctxLogger.Info("Entry updateVolume()", zap.Reflect("obj", obj)) - pv, _ := obj.(*v1.PersistentVolume) + ctxLogger.Info("Entry updateVolume()", zap.Reflect("obj", obj), zap.Reflect("oldobj", oldobj)) + newpv, _ := obj.(*v1.PersistentVolume) + //If there is no change to status , capacity or iops we can skip the updateVolume call. + if oldobj != nil { + oldpv, _ := oldobj.(*v1.PersistentVolume) + oldCapacity := oldpv.Spec.Capacity[v1.ResourceStorage] + capacity := newpv.Spec.Capacity[v1.ResourceStorage] + iops := newpv.Spec.CSI.VolumeAttributes[IOPSLabel] + oldiops := oldpv.Spec.CSI.VolumeAttributes[IOPSLabel] + + if (newpv.Status.Phase == oldpv.Status.Phase) && (oldCapacity.Value() == capacity.Value()) && (oldiops == iops) { + ctxLogger.Info("Skipping update Volume as there is no change in status , capacity and iops") + return + } + } + session, err := pvw.cloudProvider.GetProviderSession(context.Background(), ctxLogger) if session != nil { - volume := pvw.getVolume(pv, ctxLogger) - ctxLogger.Info("volume to update ", zap.Reflect("volume", volume)) - err := session.UpdateVolume(volume) + iksVpc, ok := session.(*iks_vpc_provider.IksVpcSession) + + if !ok { + ctxLogger.Error("Failed to get the IKS-VPC session, Try to restart the CSI driver controller POD") + return + } + + volume := pvw.getVolume(newpv, ctxLogger) + ctxLogger.Info("Updating metadata for the volume", zap.Reflect("volume", volume)) + err := iksVpc.UpdateVolume(volume) + if err != nil { + ctxLogger.Warn("Failed to update volume metadata", zap.Error(err)) + pvw.recorder.Event(newpv, v1.EventTypeWarning, VolumeUpdateEventReason, err.Error()) + } + ctxLogger.Info("Updating tags from VPC IaaS") + err = iksVpc.VPCSession.UpdateVolume(volume) if err != nil { - ctxLogger.Warn("Unable to update the volume", zap.Error(err)) - pvw.recorder.Event(pv, v1.EventTypeWarning, VolumeUpdateEventReason, err.Error()) + ctxLogger.Warn("Failed to update volume with tags from VPC IaaS", zap.Error(err)) + pvw.recorder.Event(newpv, v1.EventTypeWarning, VolumeUpdateEventReason, err.Error()) } else { - pvw.recorder.Event(pv, v1.EventTypeNormal, VolumeUpdateEventReason, VolumeUpdateEventSuccess) + pvw.recorder.Event(newpv, v1.EventTypeNormal, VolumeUpdateEventReason, VolumeUpdateEventSuccess) ctxLogger.Warn("Volume Metadata saved successfully") } } @@ -188,7 +237,7 @@ func (pvw *PVWatcher) getTags(pv *v1.PersistentVolume, ctxLogger *zap.Logger) (s tags = strings.Split(tagstr, ",") } // append default tags to users tag list - tags = append(tags, utils.ClusterIDLabel+":"+volAttributes[utils.ClusterIDLabel]) + tags = append(tags, ClusterIDLabel+":"+volAttributes[ClusterIDLabel]) tags = append(tags, ReclaimPolicyTag+string(pv.Spec.PersistentVolumeReclaimPolicy)) tags = append(tags, StorageClassTag+pv.Spec.StorageClassName) tags = append(tags, NameSpaceTag+pv.Spec.ClaimRef.Namespace) @@ -208,8 +257,8 @@ func (pvw *PVWatcher) getVolume(pv *v1.PersistentVolume, ctxLogger *zap.Logger) VolumeType: provider.VolumeType(VolumeTypeMap[pv.Spec.CSI.Driver]), } volume.CRN = crn - clusterID := pv.Spec.CSI.VolumeAttributes[utils.ClusterIDLabel] - volume.Attributes = map[string]string{strings.ToLower(utils.ClusterIDLabel): clusterID} + clusterID := pv.Spec.CSI.VolumeAttributes[ClusterIDLabel] + volume.Attributes = map[string]string{strings.ToLower(ClusterIDLabel): clusterID} if pv.Status.Phase == v1.VolumeReleased { // Set only status in case of delete operation volume.Attributes[VolumeStatus] = VolumeStatusDeleted @@ -217,9 +266,9 @@ func (pvw *PVWatcher) getVolume(pv *v1.PersistentVolume, ctxLogger *zap.Logger) volume.Tags = tags //Get Capacity and convert to GiB capacity := pv.Spec.Capacity[v1.ResourceStorage] - capacityGiB := utils.BytesToGiB(capacity.Value()) + capacityGiB := BytesToGiB(capacity.Value()) volume.Capacity = &capacityGiB - iops := pv.Spec.CSI.VolumeAttributes[utils.IOPSLabel] + iops := pv.Spec.CSI.VolumeAttributes[IOPSLabel] volume.Iops = &iops volume.Attributes[VolumeStatus] = VolumeStatusCreated } @@ -237,3 +286,48 @@ func (pvw *PVWatcher) filter(obj interface{}) bool { pvw.logger.Debug("Exit filter()", zap.Bool("provisoinerMatch", provisoinerMatch)) return provisoinerMatch } + +// BytesToGiB converts Bytes to GiB +func BytesToGiB(volumeSizeBytes int64) int { + return int(volumeSizeBytes / GiB) +} + +// GetContextLogger ... +func GetContextLogger(ctx context.Context, isDebug bool) (*zap.Logger, string) { + return GetContextLoggerWithRequestID(ctx, isDebug, nil) +} + +// GetContextLoggerWithRequestID adds existing requestID in the logger +// The Existing requestID might be coming from ControllerPublishVolume etc +func GetContextLoggerWithRequestID(ctx context.Context, isDebug bool, requestIDIn *string) (*zap.Logger, string) { + consoleDebugging := zapcore.Lock(os.Stdout) + consoleErrors := zapcore.Lock(os.Stderr) + encoderConfig := zap.NewProductionEncoderConfig() + encoderConfig.TimeKey = "ts" + encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + traceLevel := zap.NewAtomicLevel() + if isDebug { + traceLevel.SetLevel(zap.DebugLevel) + } else { + traceLevel.SetLevel(zap.InfoLevel) + } + + core := zapcore.NewTee( + zapcore.NewCore(zapcore.NewJSONEncoder(encoderConfig), consoleDebugging, zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { + return (lvl >= traceLevel.Level()) && (lvl < zapcore.ErrorLevel) + })), + zapcore.NewCore(zapcore.NewJSONEncoder(encoderConfig), consoleErrors, zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { + return lvl >= zapcore.ErrorLevel + })), + ) + logger := zap.New(core, zap.AddCaller()) + // generating a unique request ID so that logs can be filter + if requestIDIn == nil { + // Generate New RequestID if not provided + uuid, _ := uid.NewV4() // #nosec G104: Attempt to randomly generate uuid + requestID := uuid.String() + requestIDIn = &requestID + } + logger = logger.With(zap.String("RequestID", *requestIDIn)) + return logger, *requestIDIn + " " +} diff --git a/vendor/modules.txt b/vendor/modules.txt index e50651ac..15713b70 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -10,15 +10,13 @@ github.com/IBM-Cloud/ibm-cloud-cli-sdk/common/rest github.com/IBM/go-sdk-core/v5/core # github.com/IBM/ibm-csi-common v1.1.15 ## explicit; go 1.22.0 -github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider github.com/IBM/ibm-csi-common/pkg/messages github.com/IBM/ibm-csi-common/pkg/metadata github.com/IBM/ibm-csi-common/pkg/metadata/fake github.com/IBM/ibm-csi-common/pkg/metrics github.com/IBM/ibm-csi-common/pkg/mountmanager github.com/IBM/ibm-csi-common/pkg/utils -github.com/IBM/ibm-csi-common/pkg/watcher -# github.com/IBM/ibmcloud-volume-interface v1.2.6 +# github.com/IBM/ibmcloud-volume-interface v1.2.9 ## explicit; go 1.22.0 github.com/IBM/ibmcloud-volume-interface/config github.com/IBM/ibmcloud-volume-interface/lib/metrics @@ -29,7 +27,7 @@ github.com/IBM/ibmcloud-volume-interface/lib/utils/reasoncode github.com/IBM/ibmcloud-volume-interface/provider/auth github.com/IBM/ibmcloud-volume-interface/provider/iam github.com/IBM/ibmcloud-volume-interface/provider/local -# github.com/IBM/ibmcloud-volume-vpc v1.1.11 +# github.com/IBM/ibmcloud-volume-vpc v1.1.14 ## explicit; go 1.22.0 github.com/IBM/ibmcloud-volume-vpc/block/provider github.com/IBM/ibmcloud-volume-vpc/block/utils @@ -46,6 +44,7 @@ github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/riaas github.com/IBM/ibmcloud-volume-vpc/common/vpcclient/vpcvolume github.com/IBM/ibmcloud-volume-vpc/iks/provider github.com/IBM/ibmcloud-volume-vpc/pkg/ibmcloudprovider +github.com/IBM/ibmcloud-volume-vpc/pkg/watcher # github.com/IBM/secret-common-lib v1.1.11 ## explicit; go 1.22.0 github.com/IBM/secret-common-lib/pkg/secret_provider