@@ -23,6 +23,7 @@ import (
23
23
"sort"
24
24
"strings"
25
25
"time"
26
+ neturl "net/url"
26
27
27
28
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
28
29
csi "github.com/container-storage-interface/spec/lib/go/csi"
@@ -138,6 +139,14 @@ const (
138
139
139
140
// Keys in the volume context.
140
141
contextForceAttach = "force-attach"
142
+
143
+ resourceApiScheme = "http"
144
+ resourceApiService = "compute"
145
+ resourceProject = "project"
146
+ )
147
+
148
+ var (
149
+ resourceApiHost = regexp .Compile ("^www.*apis.com$" )
141
150
)
142
151
143
152
func isDiskReady (disk * gce.CloudDisk ) (bool , error ) {
@@ -434,7 +443,7 @@ func (gceCS *GCEControllerServer) CreateVolume(ctx context.Context, req *csi.Cre
434
443
}
435
444
436
445
klog .V (4 ).Infof ("CreateVolume succeeded for disk %v" , volKey )
437
- return generateCreateVolumeResponse (disk , zones , params ), nil
446
+ return generateCreateVolumeResponse (disk , zones , params )
438
447
439
448
}
440
449
@@ -869,13 +878,23 @@ func (gceCS *GCEControllerServer) ListVolumes(ctx context.Context, req *csi.List
869
878
entries := []* csi.ListVolumesResponse_Entry {}
870
879
for i := 0 ; i + offset < len (gceCS .disks ) && i < maxEntries ; i ++ {
871
880
d := gceCS .disks [i + offset ]
881
+ diskRsrc , err := getResourceId (d .SelfLink )
882
+ if err != nil {
883
+ klog .Warning ("Bad ListVolumes disk resource %s, skipped: %v" , d .SelfLink , err )
884
+ continue
885
+ }
872
886
users := []string {}
873
887
for _ , u := range d .Users {
874
- users = append (users , cleanSelfLink (u ))
888
+ rsrc , err := getResourceId (u )
889
+ if err != nil {
890
+ klog .Warning ("Bad ListVolumes user %s, skipped: %v" , u , err )
891
+ } else {
892
+ users = append (users , rsrc )
893
+ }
875
894
}
876
895
entries = append (entries , & csi.ListVolumesResponse_Entry {
877
896
Volume : & csi.Volume {
878
- VolumeId : cleanSelfLink ( d . SelfLink ) ,
897
+ VolumeId : diskRsrc ,
879
898
},
880
899
Status : & csi.ListVolumesResponse_VolumeStatus {
881
900
PublishedNodeIds : users ,
@@ -988,6 +1007,10 @@ func (gceCS *GCEControllerServer) createPDSnapshot(ctx context.Context, project
988
1007
return nil , common .LoggedError ("Failed to create snapshot: " , err )
989
1008
}
990
1009
}
1010
+ snapshotId , err := getResourceId (snapshot .SelfLink )
1011
+ if err != nil {
1012
+ return nil , common .LoggedError (fmt .Sprintf ("Cannot extract resource id from snapshot %s" , snapshot .SelfLink ), err )
1013
+ }
991
1014
992
1015
err = gceCS .validateExistingSnapshot (snapshot , volKey )
993
1016
if err != nil {
@@ -1006,7 +1029,7 @@ func (gceCS *GCEControllerServer) createPDSnapshot(ctx context.Context, project
1006
1029
1007
1030
return & csi.Snapshot {
1008
1031
SizeBytes : common .GbToBytes (snapshot .DiskSizeGb ),
1009
- SnapshotId : cleanSelfLink ( snapshot . SelfLink ) ,
1032
+ SnapshotId : SnapshotId ,
1010
1033
SourceVolumeId : volumeID ,
1011
1034
CreationTime : timestamp ,
1012
1035
ReadyToUse : ready ,
@@ -1035,6 +1058,10 @@ func (gceCS *GCEControllerServer) createImage(ctx context.Context, project strin
1035
1058
return nil , common .LoggedError ("Failed to create image: " , err )
1036
1059
}
1037
1060
}
1061
+ imageId , err := getResourceId (image .SelfLink )
1062
+ if err != nil {
1063
+ return nil , common .LoggedError (fmt .Sprintf ("Cannot extract resource id from snapshot %s" , image .SelfLink ), err )
1064
+ }
1038
1065
1039
1066
err = gceCS .validateExistingImage (image , volKey )
1040
1067
if err != nil {
@@ -1053,7 +1080,7 @@ func (gceCS *GCEControllerServer) createImage(ctx context.Context, project strin
1053
1080
1054
1081
return & csi.Snapshot {
1055
1082
SizeBytes : common .GbToBytes (image .DiskSizeGb ),
1056
- SnapshotId : cleanSelfLink ( image . SelfLink ) ,
1083
+ SnapshotId : imageId ,
1057
1084
SourceVolumeId : volumeID ,
1058
1085
CreationTime : timestamp ,
1059
1086
ReadyToUse : ready ,
@@ -1065,9 +1092,13 @@ func (gceCS *GCEControllerServer) validateExistingImage(image *compute.Image, vo
1065
1092
return fmt .Errorf ("disk does not exist" )
1066
1093
}
1067
1094
1068
- _ , sourceKey , err := common .VolumeIDToKey (cleanSelfLink (image .SourceDisk ))
1095
+ sourceId , err := getResourceId (image .SourceDisk )
1096
+ if err != nil {
1097
+ return fmt .Errorf ("failed to get source id from %s: %w" , image .SourceDisk , err )
1098
+ }
1099
+ _ , sourceKey , err := common .VolumeIDToKey (sourceId )
1069
1100
if err != nil {
1070
- return fmt .Errorf ("fail to get source disk key %s, %w" , image .SourceDisk , err )
1101
+ return fmt .Errorf ("failed to get source disk key %s: %w" , image .SourceDisk , err )
1071
1102
}
1072
1103
1073
1104
if sourceKey .String () != volKey .String () {
@@ -1116,7 +1147,11 @@ func (gceCS *GCEControllerServer) validateExistingSnapshot(snapshot *compute.Sna
1116
1147
return fmt .Errorf ("disk does not exist" )
1117
1148
}
1118
1149
1119
- _ , sourceKey , err := common .VolumeIDToKey (cleanSelfLink (snapshot .SourceDisk ))
1150
+ sourceId , err := getResourceId (snapshot .SourceDisk )
1151
+ if err != nil {
1152
+ retur fmt .Errorf ("failed to get source id from %s: %w" , snapshot .SourceDisk , err )
1153
+ }
1154
+ _ , sourceKey , err := common .VolumeIDToKey (sourceId )
1120
1155
if err != nil {
1121
1156
return fmt .Errorf ("fail to get source disk key %s, %w" , snapshot .SourceDisk , err )
1122
1157
}
@@ -1350,7 +1385,7 @@ func (gceCS *GCEControllerServer) getSnapshotByID(ctx context.Context, snapshotI
1350
1385
return & csi.ListSnapshotsResponse {}, nil
1351
1386
}
1352
1387
}
1353
- e , err := generateImageEntry (image )
1388
+ e , err := generateDiskImageEntry (image )
1354
1389
if err != nil {
1355
1390
return nil , fmt .Errorf ("failed to generate image entry: %w" , err )
1356
1391
}
@@ -1372,6 +1407,15 @@ func generateDiskSnapshotEntry(snapshot *compute.Snapshot) (*csi.ListSnapshotsRe
1372
1407
return nil , fmt .Errorf ("Failed to covert creation timestamp: %w" , err )
1373
1408
}
1374
1409
1410
+ snapshotId , err := getResourceId (snapshot .SelfLink )
1411
+ if err != nil {
1412
+ return nil , fmt .Errorf ("failed to get snapshot id from %s: %w" , snapshot .SelfLink , err )
1413
+ }
1414
+ sourceId , err := getResourceId (snapshot .SourceDisk )
1415
+ if err != nil {
1416
+ return nil , fmt .Errorf ("failed to get source id from %s: %w" , snapshot .SourceDisk , err )
1417
+ }
1418
+
1375
1419
// We ignore the error intentionally here since we are just listing snapshots
1376
1420
// TODO: If the snapshot is in "FAILED" state we need to think through what this
1377
1421
// should actually look like.
@@ -1380,8 +1424,8 @@ func generateDiskSnapshotEntry(snapshot *compute.Snapshot) (*csi.ListSnapshotsRe
1380
1424
entry := & csi.ListSnapshotsResponse_Entry {
1381
1425
Snapshot : & csi.Snapshot {
1382
1426
SizeBytes : common .GbToBytes (snapshot .DiskSizeGb ),
1383
- SnapshotId : cleanSelfLink ( snapshot . SelfLink ) ,
1384
- SourceVolumeId : cleanSelfLink ( snapshot . SourceDisk ) ,
1427
+ SnapshotId : snapshotId ,
1428
+ SourceVolumeId : sourceId ,
1385
1429
CreationTime : tp ,
1386
1430
ReadyToUse : ready ,
1387
1431
},
@@ -1397,35 +1441,23 @@ func generateDiskImageEntry(image *compute.Image) (*csi.ListSnapshotsResponse_En
1397
1441
return nil , fmt .Errorf ("failed to covert creation timestamp: %w" , err )
1398
1442
}
1399
1443
1400
- ready , _ := isImageReady (image .Status )
1401
-
1402
- entry := & csi.ListSnapshotsResponse_Entry {
1403
- Snapshot : & csi.Snapshot {
1404
- SizeBytes : common .GbToBytes (image .DiskSizeGb ),
1405
- SnapshotId : cleanSelfLink (image .SelfLink ),
1406
- SourceVolumeId : cleanSelfLink (image .SourceDisk ),
1407
- CreationTime : tp ,
1408
- ReadyToUse : ready ,
1409
- },
1444
+ imageId , err := getResourceId (image .SelfLink )
1445
+ if err != nil {
1446
+ return nil , fmt .Errorf ("cannot get image id from %s: %w" , image .SelfLink , err )
1410
1447
}
1411
- return entry , nil
1412
- }
1413
-
1414
- func generateImageEntry (image * compute.Image ) (* csi.ListSnapshotsResponse_Entry , error ) {
1415
- timestamp , err := parseTimestamp (image .CreationTimestamp )
1448
+ sourceId , err := getResourceId (image .SourceDisk )
1416
1449
if err != nil {
1417
- return nil , fmt .Errorf ("Failed to covert creation timestamp : %w" , err )
1450
+ return nil , fmt .Errorf ("cannot get sourcee id from %s : %w" , image . SourceLink , err )
1418
1451
}
1419
1452
1420
- // ignore the error intentionally here since we are just listing images
1421
1453
ready , _ := isImageReady (image .Status )
1422
1454
1423
1455
entry := & csi.ListSnapshotsResponse_Entry {
1424
1456
Snapshot : & csi.Snapshot {
1425
1457
SizeBytes : common .GbToBytes (image .DiskSizeGb ),
1426
- SnapshotId : cleanSelfLink ( image . SelfLink ) ,
1427
- SourceVolumeId : cleanSelfLink ( image . SourceDisk ) ,
1428
- CreationTime : timestamp ,
1458
+ SnapshotId : imageId ,
1459
+ SourceVolumeId : sourceId ,
1460
+ CreationTime : tp ,
1429
1461
ReadyToUse : ready ,
1430
1462
},
1431
1463
}
@@ -1691,7 +1723,12 @@ func extractVolumeContext(context map[string]string) (*PDCSIContext, error) {
1691
1723
return info , nil
1692
1724
}
1693
1725
1694
- func generateCreateVolumeResponse (disk * gce.CloudDisk , zones []string , params common.DiskParameters ) * csi.CreateVolumeResponse {
1726
+ func generateCreateVolumeResponse (disk * gce.CloudDisk , zones []string , params common.DiskParameters ) * csi.CreateVolumeResponse , error {
1727
+ volumeId , err := getResourceId (disk .GetSelfLink ())
1728
+ if err != nil {
1729
+ return nil , fmt .Errorf ("cannot get volume id from %s: %w" , disk .GetSelfLink (), err )
1730
+ }
1731
+
1695
1732
tops := []* csi.Topology {}
1696
1733
for _ , zone := range zones {
1697
1734
tops = append (tops , & csi.Topology {
@@ -1702,7 +1739,7 @@ func generateCreateVolumeResponse(disk *gce.CloudDisk, zones []string, params co
1702
1739
createResp := & csi.CreateVolumeResponse {
1703
1740
Volume : & csi.Volume {
1704
1741
CapacityBytes : realDiskSizeBytes ,
1705
- VolumeId : cleanSelfLink ( disk . GetSelfLink ()) ,
1742
+ VolumeId : volumeId ,
1706
1743
VolumeContext : paramsToVolumeContext (params ),
1707
1744
AccessibleTopology : tops ,
1708
1745
},
@@ -1744,9 +1781,28 @@ func generateCreateVolumeResponse(disk *gce.CloudDisk, zones []string, params co
1744
1781
return createResp
1745
1782
}
1746
1783
1747
- func cleanSelfLink (selfLink string ) string {
1748
- r , _ := regexp .Compile ("https:\\ /\\ /www.*apis.com\\ /.*(v1|beta|alpha)\\ /" )
1749
- return r .ReplaceAllString (selfLink , "" )
1784
+ func getResourceId (resourceLink string ) (string , error ) {
1785
+ url , err := neturl .Parse (resourceLink )
1786
+ if err != nil {
1787
+ return fmt .Errorf ("Could not parse resource %s: %w" , resourceLink , err )
1788
+ }
1789
+ if url .Scheme != resourceApiScheme {
1790
+ return fmt .Errorf ("Unexpected API scheme for resource %s" , resourceLink )
1791
+ }
1792
+ if ! resourceApiHost .MatchString (url .Host ) {
1793
+ return fmt .Errorf ("Unexpected API host for resource %s" , resourceLink )
1794
+ }
1795
+ elts := strings .Split (url .Path , "/" )
1796
+ if len (elts ) < 3 {
1797
+ return fmt .Errorf ("Bad resource path %s" , resourceLink )
1798
+ }
1799
+ if elts [0 ] != resourceApiService {
1800
+ return fmt .Errorf ("Bad resource service %s in %s" , elts [0 ], resourceLink )
1801
+ }
1802
+ if elts [2 ] != resourceProject {
1803
+ return fmt .Errorf ("Expected %s to start with %s in resource %s" , elts [2 :], resourceProject , resourceLink )
1804
+ }
1805
+ return elts [2 :]
1750
1806
}
1751
1807
1752
1808
func createRegionalDisk (ctx context.Context , cloudProvider gce.GCECompute , name string , zones []string , params common.DiskParameters , capacityRange * csi.CapacityRange , capBytes int64 , snapshotID string , volumeContentSourceVolumeID string , multiWriter bool ) (* gce.CloudDisk , error ) {
0 commit comments