@@ -20,7 +20,6 @@ import (
20
20
"context"
21
21
"fmt"
22
22
"os"
23
- "sort"
24
23
"strings"
25
24
26
25
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -380,119 +379,149 @@ func warningsForWeightedPodAffinityTerms(terms []api.WeightedPodAffinityTerm, fi
380
379
func warningsForOverlappingVirtualPaths (volumes []api.Volume ) []string {
381
380
var warnings []string
382
381
382
+ mkWarn := func (volName , volDesc , body string ) string {
383
+ return fmt .Sprintf ("volume %q (%s): overlapping paths: %s" , volName , volDesc , body )
384
+ }
385
+
383
386
for _ , v := range volumes {
384
387
if v .ConfigMap != nil && v .ConfigMap .Items != nil {
385
- warnings = append (warnings , checkVolumeMappingForOverlap (extractPaths (v .ConfigMap .Items ), fmt .Sprintf ("volume %q (ConfigMap %q): overlapping paths" , v .Name , v .ConfigMap .Name ))... )
388
+ overlaps := checkVolumeMappingForOverlap (extractPaths (v .ConfigMap .Items , "" ))
389
+ for _ , ol := range overlaps {
390
+ warnings = append (warnings , mkWarn (v .Name , fmt .Sprintf ("ConfigMap %q" , v .ConfigMap .Name ), ol ))
391
+ }
386
392
}
387
393
388
394
if v .Secret != nil && v .Secret .Items != nil {
389
- warnings = append (warnings , checkVolumeMappingForOverlap (extractPaths (v .Secret .Items ), fmt .Sprintf ("volume %q (Secret %q): overlapping paths" , v .Name , v .Secret .SecretName ))... )
395
+ overlaps := checkVolumeMappingForOverlap (extractPaths (v .Secret .Items , "" ))
396
+ for _ , ol := range overlaps {
397
+ warnings = append (warnings , mkWarn (v .Name , fmt .Sprintf ("Secret %q" , v .Secret .SecretName ), ol ))
398
+ }
390
399
}
391
400
392
401
if v .DownwardAPI != nil && v .DownwardAPI .Items != nil {
393
- warnings = append (warnings , checkVolumeMappingForOverlap (extractPathsDownwardAPI (v .DownwardAPI .Items ), fmt .Sprintf ("volume %q (DownwardAPI): overlapping paths" , v .Name ))... )
402
+ overlaps := checkVolumeMappingForOverlap (extractPathsDownwardAPI (v .DownwardAPI .Items , "" ))
403
+ for _ , ol := range overlaps {
404
+ warnings = append (warnings , mkWarn (v .Name , "DownwardAPI" , ol ))
405
+ }
394
406
}
395
407
396
408
if v .Projected != nil {
397
- var sourcePaths []string
398
- var errorMessage string
399
- allPaths := sets .New [string ]()
409
+ var sourcePaths []pathAndSource
410
+ var allPaths []pathAndSource
400
411
401
412
for _ , source := range v .Projected .Sources {
402
413
if source == (api.VolumeProjection {}) {
403
414
warnings = append (warnings , fmt .Sprintf ("volume %q (Projected) has no sources provided" , v .Name ))
404
415
continue
405
416
}
417
+
406
418
switch {
407
419
case source .ConfigMap != nil && source .ConfigMap .Items != nil :
408
- sourcePaths = extractPaths (source .ConfigMap .Items )
409
- errorMessage = fmt .Sprintf ("volume %q (Projected ConfigMap %q): overlapping paths" , v .Name , source .ConfigMap .Name )
420
+ sourcePaths = extractPaths (source .ConfigMap .Items , fmt .Sprintf ("ConfigMap %q" , source .ConfigMap .Name ))
410
421
case source .Secret != nil && source .Secret .Items != nil :
411
- sourcePaths = extractPaths (source .Secret .Items )
412
- errorMessage = fmt .Sprintf ("volume %q (Projected Secret %q): overlapping paths" , v .Name , source .Secret .Name )
422
+ sourcePaths = extractPaths (source .Secret .Items , fmt .Sprintf ("Secret %q" , source .Secret .Name ))
413
423
case source .DownwardAPI != nil && source .DownwardAPI .Items != nil :
414
- sourcePaths = extractPathsDownwardAPI (source .DownwardAPI .Items )
415
- errorMessage = fmt .Sprintf ("volume %q (Projected DownwardAPI): overlapping paths" , v .Name )
424
+ sourcePaths = extractPathsDownwardAPI (source .DownwardAPI .Items , "DownwardAPI" )
416
425
case source .ServiceAccountToken != nil :
417
- sourcePaths = []string {source .ServiceAccountToken .Path }
418
- errorMessage = fmt .Sprintf ("volume %q (Projected ServiceAccountToken): overlapping paths" , v .Name )
426
+ sourcePaths = []pathAndSource {{source .ServiceAccountToken .Path , "ServiceAccountToken" }}
419
427
case source .ClusterTrustBundle != nil :
420
- sourcePaths = [] string { source . ClusterTrustBundle . Path }
428
+ name := ""
421
429
if source .ClusterTrustBundle .Name != nil {
422
- errorMessage = fmt . Sprintf ( "volume %q (Projected ClusterTrustBundle %q): overlapping paths" , v . Name , * source .ClusterTrustBundle .Name )
430
+ name = * source .ClusterTrustBundle .Name
423
431
} else {
424
- errorMessage = fmt . Sprintf ( "volume %q (Projected ClusterTrustBundle %q): overlapping paths" , v . Name , * source .ClusterTrustBundle .SignerName )
432
+ name = * source .ClusterTrustBundle .SignerName
425
433
}
434
+ sourcePaths = []pathAndSource {{source .ClusterTrustBundle .Path , fmt .Sprintf ("ClusterTrustBundle %q" , name )}}
426
435
}
427
436
428
437
if len (sourcePaths ) == 0 {
429
438
continue
430
439
}
431
440
432
- warnings = append (warnings , checkVolumeMappingForOverlap (sourcePaths , errorMessage )... )
433
-
434
- // remove duplicates path and sort the new array, so we can get predetermined result
435
- uniqueSourcePaths := sets .New [string ](sourcePaths ... ).UnsortedList ()
436
- orderedSourcePaths := append (uniqueSourcePaths , allPaths .UnsortedList ()... )
437
- sort .Strings (orderedSourcePaths )
438
- warnings = append (warnings , checkVolumeMappingForOverlap (orderedSourcePaths , errorMessage )... )
439
- allPaths .Insert (uniqueSourcePaths ... )
441
+ for _ , ps := range sourcePaths {
442
+ ps .path = strings .TrimRight (ps .path , string (os .PathSeparator ))
443
+ if collisions := checkForOverlap (allPaths , ps ); len (collisions ) > 0 {
444
+ for _ , c := range collisions {
445
+ warnings = append (warnings , mkWarn (v .Name , "Projected" , fmt .Sprintf ("%s with %s" , ps .String (), c .String ())))
446
+ }
447
+ }
448
+ allPaths = append (allPaths , ps )
449
+ }
440
450
}
441
451
}
442
-
443
452
}
444
453
return warnings
445
454
}
446
455
447
- func extractPaths (mapping []api.KeyToPath ) []string {
448
- result := make ([]string , 0 , len (mapping ))
456
+ // this lets us track a path and where it came from, for better errors
457
+ type pathAndSource struct {
458
+ path string
459
+ source string
460
+ }
461
+
462
+ func (ps pathAndSource ) String () string {
463
+ if ps .source != "" {
464
+ return fmt .Sprintf ("%q (%s)" , ps .path , ps .source )
465
+ }
466
+ return fmt .Sprintf ("%q" , ps .path )
467
+ }
468
+
469
+ func extractPaths (mapping []api.KeyToPath , source string ) []pathAndSource {
470
+ result := make ([]pathAndSource , 0 , len (mapping ))
449
471
450
472
for _ , v := range mapping {
451
- result = append (result , v .Path )
473
+ result = append (result , pathAndSource { v .Path , source } )
452
474
}
453
475
return result
454
476
}
455
477
456
- func extractPathsDownwardAPI (mapping []api.DownwardAPIVolumeFile ) []string {
457
- result := make ([]string , 0 , len (mapping ))
478
+ func extractPathsDownwardAPI (mapping []api.DownwardAPIVolumeFile , source string ) []pathAndSource {
479
+ result := make ([]pathAndSource , 0 , len (mapping ))
458
480
459
481
for _ , v := range mapping {
460
- result = append (result , v .Path )
482
+ result = append (result , pathAndSource { v .Path , source } )
461
483
}
462
484
return result
463
485
}
464
486
465
- func checkVolumeMappingForOverlap (paths []string , warningMessage string ) []string {
466
- var warnings []string
487
+ func checkVolumeMappingForOverlap (paths []pathAndSource ) []string {
467
488
pathSeparator := string (os .PathSeparator )
468
- uniquePaths := sets .New [string ]()
489
+ var warnings []string
490
+ var allPaths []pathAndSource
469
491
470
- for _ , path := range paths {
471
- normalizedPath := strings .TrimRight (path , pathSeparator )
472
- if collision := checkForOverlap (uniquePaths , normalizedPath ); collision != "" {
473
- warnings = append (warnings , fmt .Sprintf ("%s: %q with %q" , warningMessage , normalizedPath , collision ))
492
+ for _ , ps := range paths {
493
+ ps .path = strings .TrimRight (ps .path , pathSeparator )
494
+ if collisions := checkForOverlap (allPaths , ps ); len (collisions ) > 0 {
495
+ for _ , c := range collisions {
496
+ warnings = append (warnings , fmt .Sprintf ("%s with %s" , ps .String (), c .String ()))
497
+ }
474
498
}
475
- uniquePaths . Insert ( normalizedPath )
499
+ allPaths = append ( allPaths , ps )
476
500
}
477
501
478
502
return warnings
479
503
}
480
504
481
- func checkForOverlap (paths sets. Set [ string ], path string ) string {
505
+ func checkForOverlap (haystack [] pathAndSource , needle pathAndSource ) [] pathAndSource {
482
506
pathSeparator := string (os .PathSeparator )
483
507
484
- for item := range paths {
508
+ if needle .path == "" {
509
+ return nil
510
+ }
511
+
512
+ var result []pathAndSource
513
+ for _ , item := range haystack {
485
514
switch {
486
- case item == "" || path == "" :
487
- return ""
488
- case item == path :
489
- return item
490
- case strings .HasPrefix (item + pathSeparator , path ):
491
- return item
492
- case strings .HasPrefix (path + pathSeparator , item ):
493
- return item
515
+ case item . path == "" :
516
+ continue
517
+ case item == needle :
518
+ result = append ( result , item )
519
+ case strings .HasPrefix (item . path + pathSeparator , needle . path + pathSeparator ):
520
+ result = append ( result , item )
521
+ case strings .HasPrefix (needle . path + pathSeparator , item . path + pathSeparator ):
522
+ result = append ( result , item )
494
523
}
495
524
}
496
525
497
- return ""
526
+ return result
498
527
}
0 commit comments