@@ -34,9 +34,7 @@ import (
34
34
"google.golang.org/api/googleapi"
35
35
"google.golang.org/grpc/codes"
36
36
"google.golang.org/grpc/status"
37
- "k8s.io/apimachinery/pkg/api/resource"
38
37
"k8s.io/apimachinery/pkg/util/sets"
39
- volumehelpers "k8s.io/cloud-provider/volume/helpers"
40
38
"k8s.io/klog/v2"
41
39
"sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/constants"
42
40
)
@@ -91,15 +89,10 @@ const (
91
89
)
92
90
93
91
var (
94
- multiRegionalPattern = regexp .MustCompile (multiRegionalLocationFmt )
95
- regionalPattern = regexp .MustCompile (regionalLocationFmt )
96
-
97
92
// Full or partial URL of the machine type resource, in the format:
98
93
// zones/zone/machineTypes/machine-type
99
94
machineTypeRegex = regexp .MustCompile (machineTypePattern )
100
95
101
- storagePoolFieldsRegex = regexp .MustCompile (`^projects/([^/]+)/zones/([^/]+)/storagePools/([^/]+)$` )
102
-
103
96
zoneURIRegex = regexp .MustCompile (zoneURIPattern )
104
97
105
98
// userErrorCodeMap tells how API error types are translated to error codes.
@@ -111,13 +104,6 @@ var (
111
104
http .StatusConflict : codes .FailedPrecondition ,
112
105
}
113
106
114
- validDataCacheMode = []string {constants .DataCacheModeWriteBack , constants .DataCacheModeWriteThrough }
115
-
116
- // Regular expressions for validating parent_id, key and value of a resource tag.
117
- regexParent = regexp .MustCompile (`(^[1-9][0-9]{0,31}$)|(^[a-z][a-z0-9-]{4,28}[a-z0-9]$)` )
118
- regexKey = regexp .MustCompile (`^[a-zA-Z0-9]([0-9A-Za-z_.-]{0,61}[a-zA-Z0-9])?$` )
119
- regexValue = regexp .MustCompile (`^[a-zA-Z0-9]([0-9A-Za-z_.@%=+:,*#&()\[\]{}\-\s]{0,61}[a-zA-Z0-9])?$` )
120
-
121
107
csiRetryableErrorCodes = []codes.Code {codes .Canceled , codes .DeadlineExceeded , codes .Unavailable , codes .Aborted , codes .ResourceExhausted }
122
108
)
123
109
@@ -234,212 +220,6 @@ func CreateZonalVolumeID(project, zone, name string) string {
234
220
return fmt .Sprintf (volIDZonalFmt , project , zone , name )
235
221
}
236
222
237
- // ConvertLabelsStringToMap converts the labels from string to map
238
- // example: "key1=value1,key2=value2" gets converted into {"key1": "value1", "key2": "value2"}
239
- // See https://cloud.google.com/compute/docs/labeling-resources#label_format for details.
240
- func ConvertLabelsStringToMap (labels string ) (map [string ]string , error ) {
241
- const labelsDelimiter = ","
242
- const labelsKeyValueDelimiter = "="
243
-
244
- labelsMap := make (map [string ]string )
245
- if labels == "" {
246
- return labelsMap , nil
247
- }
248
-
249
- regexKey , _ := regexp .Compile (`^\p{Ll}[\p{Ll}0-9_-]{0,62}$` )
250
- checkLabelKeyFn := func (key string ) error {
251
- if ! regexKey .MatchString (key ) {
252
- return fmt .Errorf ("label value %q is invalid (should start with lowercase letter / lowercase letter, digit, _ and - chars are allowed / 1-63 characters" , key )
253
- }
254
- return nil
255
- }
256
-
257
- regexValue , _ := regexp .Compile (`^[\p{Ll}0-9_-]{0,63}$` )
258
- checkLabelValueFn := func (value string ) error {
259
- if ! regexValue .MatchString (value ) {
260
- return fmt .Errorf ("label value %q is invalid (lowercase letter, digit, _ and - chars are allowed / 0-63 characters" , value )
261
- }
262
-
263
- return nil
264
- }
265
-
266
- keyValueStrings := strings .Split (labels , labelsDelimiter )
267
- for _ , keyValue := range keyValueStrings {
268
- keyValue := strings .Split (keyValue , labelsKeyValueDelimiter )
269
-
270
- if len (keyValue ) != 2 {
271
- return nil , fmt .Errorf ("labels %q are invalid, correct format: 'key1=value1,key2=value2'" , labels )
272
- }
273
-
274
- key := strings .TrimSpace (keyValue [0 ])
275
- if err := checkLabelKeyFn (key ); err != nil {
276
- return nil , err
277
- }
278
-
279
- value := strings .TrimSpace (keyValue [1 ])
280
- if err := checkLabelValueFn (value ); err != nil {
281
- return nil , err
282
- }
283
-
284
- labelsMap [key ] = value
285
- }
286
-
287
- const maxNumberOfLabels = 64
288
- if len (labelsMap ) > maxNumberOfLabels {
289
- return nil , fmt .Errorf ("more than %d labels is not allowed, given: %d" , maxNumberOfLabels , len (labelsMap ))
290
- }
291
-
292
- return labelsMap , nil
293
- }
294
-
295
- // ConvertTagsStringToMap converts the tags from string to Tag slice
296
- // example: "parent_id1/tag_key1/tag_value1,parent_id2/tag_key2/tag_value2" gets
297
- // converted into {"parent_id1/tag_key1":"tag_value1", "parent_id2/tag_key2":"tag_value2"}
298
- // See https://cloud.google.com/resource-manager/docs/tags/tags-overview,
299
- // https://cloud.google.com/resource-manager/docs/tags/tags-creating-and-managing for details
300
- func ConvertTagsStringToMap (tags string ) (map [string ]string , error ) {
301
- const tagsDelimiter = ","
302
- const tagsParentIDKeyValueDelimiter = "/"
303
-
304
- tagsMap := make (map [string ]string )
305
- if tags == "" {
306
- return nil , nil
307
- }
308
-
309
- checkTagParentIDFn := func (tag , parentID string ) error {
310
- if ! regexParent .MatchString (parentID ) {
311
- return fmt .Errorf ("tag parent_id %q for tag %q is invalid. parent_id can have a maximum of 32 characters and cannot be empty. parent_id can be either OrganizationID or ProjectID. OrganizationID must consist of decimal numbers, and cannot have leading zeroes and ProjectID must be 6 to 30 characters in length, can only contain lowercase letters, numbers, and hyphens, and must start with a letter, and cannot end with a hyphen" , parentID , tag )
312
- }
313
- return nil
314
- }
315
-
316
- checkTagKeyFn := func (tag , key string ) error {
317
- if ! regexKey .MatchString (key ) {
318
- return fmt .Errorf ("tag key %q for tag %q is invalid. Tag key can have a maximum of 63 characters and cannot be empty. Tag key must begin and end with an alphanumeric character, and must contain only uppercase, lowercase alphanumeric characters, and the following special characters `._-`" , key , tag )
319
- }
320
- return nil
321
- }
322
-
323
- checkTagValueFn := func (tag , value string ) error {
324
- if ! regexValue .MatchString (value ) {
325
- return fmt .Errorf ("tag value %q for tag %q is invalid. Tag value can have a maximum of 63 characters and cannot be empty. Tag value must begin and end with an alphanumeric character, and must contain only uppercase, lowercase alphanumeric characters, and the following special characters `_-.@%%=+:,*#&(){}[]` and spaces" , value , tag )
326
- }
327
-
328
- return nil
329
- }
330
-
331
- checkTagParentIDKey := sets.String {}
332
- parentIDkeyValueStrings := strings .Split (tags , tagsDelimiter )
333
- for _ , parentIDkeyValueString := range parentIDkeyValueStrings {
334
- parentIDKeyValue := strings .Split (parentIDkeyValueString , tagsParentIDKeyValueDelimiter )
335
-
336
- if len (parentIDKeyValue ) != 3 {
337
- return nil , fmt .Errorf ("tag %q is invalid, correct format: 'parent_id1/key1/value1,parent_id2/key2/value2'" , parentIDkeyValueString )
338
- }
339
-
340
- parentID := strings .TrimSpace (parentIDKeyValue [0 ])
341
- if err := checkTagParentIDFn (parentIDkeyValueString , parentID ); err != nil {
342
- return nil , err
343
- }
344
-
345
- key := strings .TrimSpace (parentIDKeyValue [1 ])
346
- if err := checkTagKeyFn (parentIDkeyValueString , key ); err != nil {
347
- return nil , err
348
- }
349
-
350
- value := strings .TrimSpace (parentIDKeyValue [2 ])
351
- if err := checkTagValueFn (parentIDkeyValueString , value ); err != nil {
352
- return nil , err
353
- }
354
-
355
- parentIDKeyStr := fmt .Sprintf ("%s/%s" , parentID , key )
356
- if checkTagParentIDKey .Has (parentIDKeyStr ) {
357
- return nil , fmt .Errorf ("tag parent_id & key combination %q exists more than once" , parentIDKeyStr )
358
- }
359
- checkTagParentIDKey .Insert (parentIDKeyStr )
360
-
361
- tagsMap [parentIDKeyStr ] = value
362
- }
363
-
364
- // The maximum number of tags allowed per resource is 50. For more details check the following:
365
- // https://cloud.google.com/resource-manager/docs/tags/tags-creating-and-managing#attaching
366
- // https://cloud.google.com/resource-manager/docs/limits#tag-limits
367
- const maxNumberOfTags = 50
368
- if len (tagsMap ) > maxNumberOfTags {
369
- return nil , fmt .Errorf ("more than %d tags is not allowed, given: %d" , maxNumberOfTags , len (tagsMap ))
370
- }
371
-
372
- return tagsMap , nil
373
- }
374
-
375
- // ProcessStorageLocations trims and normalizes storage location to lower letters.
376
- func ProcessStorageLocations (storageLocations string ) ([]string , error ) {
377
- normalizedLoc := strings .ToLower (strings .TrimSpace (storageLocations ))
378
- if ! multiRegionalPattern .MatchString (normalizedLoc ) && ! regionalPattern .MatchString (normalizedLoc ) {
379
- return []string {}, fmt .Errorf ("invalid location for snapshot: %q" , storageLocations )
380
- }
381
- return []string {normalizedLoc }, nil
382
- }
383
-
384
- // ValidateSnapshotType validates the type
385
- func ValidateSnapshotType (snapshotType string ) error {
386
- switch snapshotType {
387
- case DiskSnapshotType , DiskImageType :
388
- return nil
389
- default :
390
- return fmt .Errorf ("invalid snapshot type %s" , snapshotType )
391
- }
392
- }
393
-
394
- // ConvertStringToInt64 converts a string to int64
395
- func ConvertStringToInt64 (str string ) (int64 , error ) {
396
- quantity , err := resource .ParseQuantity (str )
397
- if err != nil {
398
- return - 1 , err
399
- }
400
- return volumehelpers .RoundUpToB (quantity )
401
- }
402
-
403
- // ConvertMiStringToInt64 converts a GiB string to int64
404
- func ConvertMiStringToInt64 (str string ) (int64 , error ) {
405
- quantity , err := resource .ParseQuantity (str )
406
- if err != nil {
407
- return - 1 , err
408
- }
409
- return volumehelpers .RoundUpToMiB (quantity )
410
- }
411
-
412
- // ConvertGiStringToInt64 converts a GiB string to int64
413
- func ConvertGiStringToInt64 (str string ) (int64 , error ) {
414
- quantity , err := resource .ParseQuantity (str )
415
- if err != nil {
416
- return - 1 , err
417
- }
418
- return volumehelpers .RoundUpToGiB (quantity )
419
- }
420
-
421
- // ConvertStringToBool converts a string to a boolean.
422
- func ConvertStringToBool (str string ) (bool , error ) {
423
- switch strings .ToLower (str ) {
424
- case "true" :
425
- return true , nil
426
- case "false" :
427
- return false , nil
428
- }
429
- return false , fmt .Errorf ("Unexpected boolean string %s" , str )
430
- }
431
-
432
- // ConvertStringToAvailabilityClass converts a string to an availability class string.
433
- func ConvertStringToAvailabilityClass (str string ) (string , error ) {
434
- switch strings .ToLower (str ) {
435
- case ParameterNoAvailabilityClass :
436
- return ParameterNoAvailabilityClass , nil
437
- case ParameterRegionalHardFailoverClass :
438
- return ParameterRegionalHardFailoverClass , nil
439
- }
440
- return "" , fmt .Errorf ("Unexpected boolean string %s" , str )
441
- }
442
-
443
223
// ParseMachineType returns an extracted machineType from a URL, or empty if not found.
444
224
// machineTypeUrl: Full or partial URL of the machine type resource, in the format:
445
225
//
@@ -614,12 +394,6 @@ func NewCombinedError(msg string, errs []error) error {
614
394
return LoggedError (msg , errors .Join (errs ... ))
615
395
}
616
396
617
- func isValidDiskEncryptionKmsKey (DiskEncryptionKmsKey string ) bool {
618
- // Validate key against default kmskey pattern
619
- kmsKeyPattern := regexp .MustCompile ("projects/[^/]+/locations/([^/]+)/keyRings/[^/]+/cryptoKeys/[^/]+" )
620
- return kmsKeyPattern .MatchString (DiskEncryptionKmsKey )
621
- }
622
-
623
397
func ParseZoneFromURI (zoneURI string ) (string , error ) {
624
398
zoneMatch := zoneURIRegex .FindStringSubmatch (zoneURI )
625
399
if zoneMatch == nil {
@@ -628,65 +402,8 @@ func ParseZoneFromURI(zoneURI string) (string, error) {
628
402
return zoneMatch [1 ], nil
629
403
}
630
404
631
- // ParseStoragePools returns an error if none of the given storagePools
632
- // (delimited by a comma) are in the format
633
- // projects/project/zones/zone/storagePools/storagePool.
634
- func ParseStoragePools (storagePools string ) ([]StoragePool , error ) {
635
- spSlice := strings .Split (storagePools , "," )
636
- parsedStoragePools := []StoragePool {}
637
- for _ , sp := range spSlice {
638
- project , location , spName , err := fieldsFromStoragePoolResourceName (sp )
639
- if err != nil {
640
- return nil , err
641
- }
642
- spObj := StoragePool {Project : project , Zone : location , Name : spName , ResourceName : sp }
643
- parsedStoragePools = append (parsedStoragePools , spObj )
644
-
645
- }
646
- return parsedStoragePools , nil
647
- }
648
-
649
- // fieldsFromResourceName returns the project, zone, and Storage Pool name from the given
650
- // Storage Pool resource name. The resource name must be in the format
651
- // projects/project/zones/zone/storagePools/storagePool.
652
- // All other formats are invalid, and an error will be returned.
653
- func fieldsFromStoragePoolResourceName (resourceName string ) (project , location , spName string , err error ) {
654
- fieldMatches := storagePoolFieldsRegex .FindStringSubmatch (resourceName )
655
- // Field matches should have 4 strings: [resourceName, project, zone, storagePool]. The first
656
- // match is the entire string.
657
- if len (fieldMatches ) != 4 {
658
- err := fmt .Errorf ("invalid Storage Pool resource name. Got %s, expected projects/project/zones/zone/storagePools/storagePool" , resourceName )
659
- return "" , "" , "" , err
660
- }
661
- project = fieldMatches [1 ]
662
- location = fieldMatches [2 ]
663
- spName = fieldMatches [3 ]
664
- return
665
- }
666
-
667
405
// StoragePoolZones returns the unique zones of the given storage pool resource names.
668
406
// Returns an error if multiple storage pools in 1 zone are found.
669
- func StoragePoolZones (storagePools []StoragePool ) ([]string , error ) {
670
- zonesSet := sets.String {}
671
- var zones []string
672
- for _ , sp := range storagePools {
673
- if zonesSet .Has (sp .Zone ) {
674
- return nil , fmt .Errorf ("found multiple storage pools in zone %s. Only one storage pool per zone is allowed" , sp .Zone )
675
- }
676
- zonesSet .Insert (sp .Zone )
677
- zones = append (zones , sp .Zone )
678
- }
679
- return zones , nil
680
- }
681
-
682
- func StoragePoolInZone (storagePools []StoragePool , zone string ) * StoragePool {
683
- for _ , pool := range storagePools {
684
- if zone == pool .Zone {
685
- return & pool
686
- }
687
- }
688
- return nil
689
- }
690
407
691
408
func UnorderedSlicesEqual (slice1 []string , slice2 []string ) bool {
692
409
set1 := sets .NewString (slice1 ... )
@@ -710,29 +427,6 @@ func VolumeIdAsMultiZone(volumeId string) (string, error) {
710
427
return strings .Join (splitId , "/" ), nil
711
428
}
712
429
713
- func StringInSlice (s string , list []string ) bool {
714
- for _ , v := range list {
715
- if v == s {
716
- return true
717
- }
718
- }
719
- return false
720
- }
721
-
722
- func ValidateDataCacheMode (s string ) error {
723
- if StringInSlice (s , validDataCacheMode ) {
724
- return nil
725
- }
726
- return fmt .Errorf ("invalid data-cache-mode %s. Only \" writeback\" and \" writethrough\" is a valid input" , s )
727
- }
728
-
729
- func ValidateNonNegativeInt (n int64 ) error {
730
- if n <= 0 {
731
- return fmt .Errorf ("Input should be set to > 0, got %d" , n )
732
- }
733
- return nil
734
- }
735
-
736
430
// NewLimiter returns a token bucket based request rate limiter after initializing
737
431
// the passed values for limit, burst (or token bucket) size. If opted for emptyBucket
738
432
// all initial tokens are reserved for the first burst.
0 commit comments