@@ -16,6 +16,7 @@ import (
1616 "errors"
1717 "fmt"
1818 "io"
19+ "strconv"
1920 "strings"
2021 "time"
2122
@@ -50,6 +51,7 @@ func (cs *controllerServer) CreateVolume(_ context.Context, req *csi.CreateVolum
5051 pvcName string
5152 pvcNamespace string
5253 bucketVersioning string
54+ quotaLimitEnabled bool
5355 )
5456
5557 modifiedRequest , err := utils .ReplaceAndReturnCopy (req )
@@ -60,7 +62,7 @@ func (cs *controllerServer) CreateVolume(_ context.Context, req *csi.CreateVolum
6062
6163 volumeName , err := sanitizeVolumeID (req .GetName ())
6264 if err != nil {
63- return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("Error in sanitizeVolumeID %v" , err ))
65+ return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("Error in sanitizeVolumeID %v" , err ))
6466 }
6567 volumeID := volumeName
6668 if len (volumeID ) == 0 {
@@ -141,6 +143,28 @@ func (cs *controllerServer) CreateVolume(_ context.Context, req *csi.CreateVolum
141143
142144 secretMap = secretMapCustom
143145 }
146+ if quotaLimitStr , ok := secretMap [constants .QuotaLimitKey ]; ok && quotaLimitStr != "" {
147+ klog .Infof ("quotaLimit from secretMap: %q" , quotaLimitStr )
148+ quotaLimitEnabled , err = strconv .ParseBool (quotaLimitStr )
149+ if err != nil {
150+ return nil , status .Error (codes .InvalidArgument ,
151+ fmt .Sprintf ("invalid quotaLimit value %q: must be 'true' or 'false'" , quotaLimitStr ))
152+ }
153+
154+ if quotaLimitEnabled {
155+ if secretMap [constants .ResourceConfigApiKey ] == "" {
156+ return nil , status .Error (codes .InvalidArgument ,
157+ "resourceConfigApiKey missing in secret, cannot set quota limit for bucket" )
158+ }
159+
160+ quotaBytes := req .GetCapacityRange ().GetRequiredBytes ()
161+ if quotaBytes <= 0 {
162+ return nil , status .Error (codes .InvalidArgument ,
163+ "enable quotaLimit requested but no positive storage size requested in PVC" )
164+ }
165+ klog .Infof ("enable quota limit requested with %d bytes" , quotaBytes )
166+ }
167+ }
144168
145169 endPoint = secretMap ["cosEndpoint" ]
146170 if endPoint == "" {
@@ -216,6 +240,22 @@ func (cs *controllerServer) CreateVolume(_ context.Context, req *csi.CreateVolum
216240 klog .Infof ("Created bucket: %s" , bucketName )
217241 }
218242
243+ if quotaLimitEnabled {
244+ quotaBytes := req .GetCapacityRange ().GetRequiredBytes ()
245+ resConfApikey := secretMap [constants .ResourceConfigApiKey ]
246+
247+ klog .Infof ("Applying hard quota of %d bytes to bucket %s" , quotaBytes , bucketName )
248+ err = sess .UpdateQuotaLimit (quotaBytes , resConfApikey , bucketName , endPoint , creds .IAMEndpoint )
249+ if err != nil {
250+ klog .Errorf ("Failed to set quota limit on bucket %s: %v" , bucketName , err )
251+ if params ["userProvidedBucket" ] == "false" {
252+ _ = sess .DeleteBucket (bucketName )
253+ }
254+ return nil , status .Error (codes .Internal , fmt .Sprintf ("failed to set bucket quota limit: %v" , err ))
255+ }
256+ klog .Infof ("Successfully applied hard quota %d bytes to bucket %s" , quotaBytes , bucketName )
257+ }
258+
219259 if bucketVersioning != "" {
220260 enable := strings .ToLower (strings .TrimSpace (bucketVersioning )) == "true"
221261 klog .Infof ("Bucket versioning value evaluated to: %t" , enable )
@@ -247,6 +287,20 @@ func (cs *controllerServer) CreateVolume(_ context.Context, req *csi.CreateVolum
247287 return nil , status .Error (codes .PermissionDenied , fmt .Sprintf ("%v: %v" , err , tempBucketName ))
248288 }
249289
290+ if quotaLimitEnabled {
291+ quotaBytes := req .GetCapacityRange ().GetRequiredBytes ()
292+ resConfApikey := secretMap [constants .ResourceConfigApiKey ]
293+
294+ klog .Infof ("Applying hard quota of %d bytes to temp bucket %s" , quotaBytes , tempBucketName )
295+ err = sess .UpdateQuotaLimit (quotaBytes , resConfApikey , tempBucketName , endPoint , creds .IAMEndpoint )
296+ if err != nil {
297+ klog .Errorf ("Failed to set quota limit on temp bucket %s: %v" , tempBucketName , err )
298+ _ = sess .DeleteBucket (tempBucketName )
299+ return nil , status .Error (codes .Internal , fmt .Sprintf ("failed to set bucket quota limit: %v" , err ))
300+ }
301+ klog .Infof ("Successfully applied hard quota %d bytes to temp bucket %s" , quotaBytes , tempBucketName )
302+ }
303+
250304 if bucketVersioning != "" {
251305 enable := strings .ToLower (strings .TrimSpace (bucketVersioning )) == "true"
252306 klog .Infof ("Temp bucket versioning value evaluated to: %t" , enable )
@@ -505,6 +559,8 @@ func parseCustomSecret(secret *v1.Secret) map[string]string {
505559 locationConstraint string
506560 bucketVersioning string
507561 objectPath string
562+ resConfApiKey string
563+ quotaLimit string
508564 )
509565
510566 if bytesVal , ok := secret .Data ["accessKey" ]; ok {
@@ -551,6 +607,13 @@ func parseCustomSecret(secret *v1.Secret) map[string]string {
551607 objectPath = string (bytesVal )
552608 }
553609
610+ if bytesVal , ok := secret .Data [constants .ResourceConfigApiKey ]; ok {
611+ resConfApiKey = string (bytesVal )
612+ }
613+ if bytesVal , ok := secret .Data [constants .QuotaLimitKey ]; ok {
614+ quotaLimit = string (bytesVal )
615+ }
616+
554617 secretMapCustom ["accessKey" ] = accessKey
555618 secretMapCustom ["secretKey" ] = secretKey
556619 secretMapCustom ["apiKey" ] = apiKey
@@ -562,6 +625,8 @@ func parseCustomSecret(secret *v1.Secret) map[string]string {
562625 secretMapCustom ["locationConstraint" ] = locationConstraint
563626 secretMapCustom [constants .BucketVersioning ] = bucketVersioning
564627 secretMapCustom ["objectPath" ] = objectPath
628+ secretMapCustom [constants .ResourceConfigApiKey ] = resConfApiKey
629+ secretMapCustom [constants .QuotaLimitKey ] = quotaLimit
565630
566631 return secretMapCustom
567632}
0 commit comments