Skip to content

Commit 8c2be6e

Browse files
committed
Add support for extra-create-metadata when creating snapshots
1 parent 94ca74d commit 8c2be6e

File tree

6 files changed

+83
-17
lines changed

6 files changed

+83
-17
lines changed

pkg/common/parameters.go

+23-2
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,21 @@ const (
4141
ParameterKeyPVCNamespace = "csi.storage.k8s.io/pvc/namespace"
4242
ParameterKeyPVName = "csi.storage.k8s.io/pv/name"
4343

44-
// Keys for tags to put in the provisioned disk description.
44+
// Keys for tags to put in the provisioned disk description
4545
tagKeyCreatedForClaimNamespace = "kubernetes.io/created-for/pvc/namespace"
4646
tagKeyCreatedForClaimName = "kubernetes.io/created-for/pvc/name"
4747
tagKeyCreatedForVolumeName = "kubernetes.io/created-for/pv/name"
4848
tagKeyCreatedBy = "storage.gke.io/created-by"
49+
50+
// Keys for Snapshot and SnapshotContent parameters as reported by external-snapshotter
51+
ParameterKeyVolumeSnapshotName = "csi.storage.k8s.io/volumesnapshot/name"
52+
ParameterKeyVolumeSnapshotNamespace = "csi.storage.k8s.io/volumesnapshot/namespace"
53+
ParameterKeyVolumeSnapshotContentName = "csi.storage.k8s.io/volumesnapshotcontent/name"
54+
55+
// Keys for tags to put in the provisioned snapshot description
56+
tagKeyCreatedForSnapshotName = "kubernetes.io/created-for/volumesnapshot/name"
57+
tagKeyCreatedForSnapshotNamespace = "kubernetes.io/created-for/volumesnapshot/namespace"
58+
tagKeyCreatedForSnapshotContentName = "kubernetes.io/created-for/volumesnapshotcontent/name"
4959
)
5060

5161
// DiskParameters contains normalized and defaulted disk parameters
@@ -72,6 +82,7 @@ type SnapshotParameters struct {
7282
StorageLocations []string
7383
SnapshotType string
7484
ImageFamily string
85+
Tags map[string]string
7586
}
7687

7788
// ExtractAndDefaultParameters will take the relevant parameters from a map and
@@ -133,10 +144,11 @@ func ExtractAndDefaultParameters(parameters map[string]string, driverName string
133144
return p, nil
134145
}
135146

136-
func ExtractAndDefaultSnapshotParameters(parameters map[string]string) (SnapshotParameters, error) {
147+
func ExtractAndDefaultSnapshotParameters(parameters map[string]string, driverName string) (SnapshotParameters, error) {
137148
p := SnapshotParameters{
138149
StorageLocations: []string{},
139150
SnapshotType: DiskSnapshotType,
151+
Tags: make(map[string]string), // Default
140152
}
141153
for k, v := range parameters {
142154
switch strings.ToLower(k) {
@@ -154,9 +166,18 @@ func ExtractAndDefaultSnapshotParameters(parameters map[string]string) (Snapshot
154166
p.SnapshotType = v
155167
case ParameterKeyImageFamily:
156168
p.ImageFamily = v
169+
case ParameterKeyVolumeSnapshotName:
170+
p.Tags[tagKeyCreatedForSnapshotName] = v
171+
case ParameterKeyVolumeSnapshotNamespace:
172+
p.Tags[tagKeyCreatedForSnapshotNamespace] = v
173+
case ParameterKeyVolumeSnapshotContentName:
174+
p.Tags[tagKeyCreatedForSnapshotContentName] = v
157175
default:
158176
return p, fmt.Errorf("parameters contains invalid option %q", k)
159177
}
160178
}
179+
if len(p.Tags) > 0 {
180+
p.Tags[tagKeyCreatedBy] = driverName
181+
}
161182
return p, nil
162183
}

pkg/common/parameters_test.go

+17-3
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,25 @@ func TestSnapshotParameters(t *testing.T) {
175175
expectError bool
176176
}{
177177
{
178-
desc: "valid parameter",
179-
parameters: map[string]string{ParameterKeyStorageLocations: "ASIA ", ParameterKeySnapshotType: "images", ParameterKeyImageFamily: "test-family"},
178+
desc: "valid parameter",
179+
parameters: map[string]string{
180+
ParameterKeyStorageLocations: "ASIA ",
181+
ParameterKeySnapshotType: "images",
182+
ParameterKeyImageFamily: "test-family",
183+
ParameterKeyVolumeSnapshotName: "snapshot-name",
184+
ParameterKeyVolumeSnapshotContentName: "snapshot-content-name",
185+
ParameterKeyVolumeSnapshotNamespace: "snapshot-namespace",
186+
},
180187
expectedSnapshotParames: SnapshotParameters{
181188
StorageLocations: []string{"asia"},
182189
SnapshotType: DiskImageType,
183190
ImageFamily: "test-family",
191+
Tags: map[string]string{
192+
tagKeyCreatedForSnapshotName: "snapshot-name",
193+
tagKeyCreatedForSnapshotContentName: "snapshot-content-name",
194+
tagKeyCreatedForSnapshotNamespace: "snapshot-namespace",
195+
tagKeyCreatedBy: "test-driver",
196+
},
184197
},
185198
expectError: false,
186199
},
@@ -190,6 +203,7 @@ func TestSnapshotParameters(t *testing.T) {
190203
expectedSnapshotParames: SnapshotParameters{
191204
StorageLocations: []string{},
192205
SnapshotType: DiskSnapshotType,
206+
Tags: make(map[string]string),
193207
},
194208
expectError: false,
195209
},
@@ -201,7 +215,7 @@ func TestSnapshotParameters(t *testing.T) {
201215
}
202216
for _, tc := range tests {
203217
t.Run(tc.desc, func(t *testing.T) {
204-
p, err := ExtractAndDefaultSnapshotParameters(tc.parameters)
218+
p, err := ExtractAndDefaultSnapshotParameters(tc.parameters, "test-driver")
205219
if err != nil && !tc.expectError {
206220
t.Errorf("Got error %v; expect no error", err)
207221
}

pkg/gce-cloud-provider/compute/gce-compute.go

+34-9
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ func ValidateDiskParameters(disk *CloudDisk, params common.DiskParameters) error
324324
func (cloud *CloudProvider) InsertDisk(ctx context.Context, project string, volKey *meta.Key, params common.DiskParameters, capBytes int64, capacityRange *csi.CapacityRange, replicaZones []string, snapshotID string, volumeContentSourceVolumeID string, multiWriter bool) error {
325325
klog.V(5).Infof("Inserting disk %v", volKey)
326326

327-
description, err := encodeDiskTags(params.Tags)
327+
description, err := encodeTags(params.Tags)
328328
if err != nil {
329329
return err
330330
}
@@ -848,18 +848,40 @@ func (cloud *CloudProvider) DeleteSnapshot(ctx context.Context, project, snapsho
848848

849849
func (cloud *CloudProvider) CreateSnapshot(ctx context.Context, project string, volKey *meta.Key, snapshotName string, snapshotParams common.SnapshotParameters) (*computev1.Snapshot, error) {
850850
klog.V(5).Infof("Creating snapshot %s for volume %v", snapshotName, volKey)
851+
852+
description, err := encodeTags(snapshotParams.Tags)
853+
if err != nil {
854+
return nil, err
855+
}
856+
851857
switch volKey.Type() {
852858
case meta.Zonal:
853-
return cloud.createZonalDiskSnapshot(ctx, project, volKey, snapshotName, snapshotParams)
859+
if description == "" {
860+
description = "Snapshot created by GCE-PD CSI Driver"
861+
}
862+
return cloud.createZonalDiskSnapshot(ctx, project, volKey, snapshotName, snapshotParams, description)
854863
case meta.Regional:
855-
return cloud.createRegionalDiskSnapshot(ctx, project, volKey, snapshotName, snapshotParams)
864+
if description == "" {
865+
description = "Regional Snapshot created by GCE-PD CSI Driver"
866+
}
867+
return cloud.createRegionalDiskSnapshot(ctx, project, volKey, snapshotName, snapshotParams, description)
856868
default:
857869
return nil, fmt.Errorf("could not create snapshot, key was neither zonal nor regional, instead got: %v", volKey.String())
858870
}
859871
}
860872

861873
func (cloud *CloudProvider) CreateImage(ctx context.Context, project string, volKey *meta.Key, imageName string, snapshotParams common.SnapshotParameters) (*computev1.Image, error) {
862874
klog.V(5).Infof("Creating image %s for source %v", imageName, volKey)
875+
876+
description, err := encodeTags(snapshotParams.Tags)
877+
if err != nil {
878+
return nil, err
879+
}
880+
881+
if description == "" {
882+
description = "Image created by GCE-PD CSI Driver"
883+
}
884+
863885
diskID, err := common.KeyToVolumeID(volKey, project)
864886
if err != nil {
865887
return nil, err
@@ -869,6 +891,7 @@ func (cloud *CloudProvider) CreateImage(ctx context.Context, project string, vol
869891
Family: snapshotParams.ImageFamily,
870892
Name: imageName,
871893
StorageLocations: snapshotParams.StorageLocations,
894+
Description: description,
872895
}
873896

874897
_, err = cloud.service.Images.Insert(project, image).Context(ctx).Do()
@@ -1013,10 +1036,11 @@ func (cloud *CloudProvider) resizeRegionalDisk(ctx context.Context, project stri
10131036
return requestGb, nil
10141037
}
10151038

1016-
func (cloud *CloudProvider) createZonalDiskSnapshot(ctx context.Context, project string, volKey *meta.Key, snapshotName string, snapshotParams common.SnapshotParameters) (*computev1.Snapshot, error) {
1039+
func (cloud *CloudProvider) createZonalDiskSnapshot(ctx context.Context, project string, volKey *meta.Key, snapshotName string, snapshotParams common.SnapshotParameters, description string) (*computev1.Snapshot, error) {
10171040
snapshotToCreate := &computev1.Snapshot{
10181041
Name: snapshotName,
10191042
StorageLocations: snapshotParams.StorageLocations,
1043+
Description: description,
10201044
}
10211045

10221046
_, err := cloud.service.Disks.CreateSnapshot(project, volKey.Zone, volKey.Name, snapshotToCreate).Context(ctx).Do()
@@ -1028,10 +1052,11 @@ func (cloud *CloudProvider) createZonalDiskSnapshot(ctx context.Context, project
10281052
return cloud.waitForSnapshotCreation(ctx, project, snapshotName)
10291053
}
10301054

1031-
func (cloud *CloudProvider) createRegionalDiskSnapshot(ctx context.Context, project string, volKey *meta.Key, snapshotName string, snapshotParams common.SnapshotParameters) (*computev1.Snapshot, error) {
1055+
func (cloud *CloudProvider) createRegionalDiskSnapshot(ctx context.Context, project string, volKey *meta.Key, snapshotName string, snapshotParams common.SnapshotParameters, description string) (*computev1.Snapshot, error) {
10321056
snapshotToCreate := &computev1.Snapshot{
10331057
Name: snapshotName,
10341058
StorageLocations: snapshotParams.StorageLocations,
1059+
Description: description,
10351060
}
10361061

10371062
_, err := cloud.service.RegionDisks.CreateSnapshot(project, volKey.Region, volKey.Name, snapshotToCreate).Context(ctx).Do()
@@ -1088,17 +1113,17 @@ func removeCryptoKeyVersion(kmsKey string) string {
10881113
return kmsKey
10891114
}
10901115

1091-
// encodeDiskTags encodes requested volume tags into JSON string, as GCE does
1092-
// not support tags on GCE PDs and we use Description field as fallback.
1093-
func encodeDiskTags(tags map[string]string) (string, error) {
1116+
// encodeTags encodes requested volume or snapshot tags into JSON string, suitable for putting into
1117+
// the PD or Snapshot Description field.
1118+
func encodeTags(tags map[string]string) (string, error) {
10941119
if len(tags) == 0 {
10951120
// No tags -> empty JSON
10961121
return "", nil
10971122
}
10981123

10991124
enc, err := json.Marshal(tags)
11001125
if err != nil {
1101-
return "", fmt.Errorf("failed to encodeDiskTags %v: %v", tags, err)
1126+
return "", fmt.Errorf("failed to encodeTags %v: %v", tags, err)
11021127
}
11031128
return string(enc), nil
11041129
}

pkg/gce-pd-csi-driver/controller.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ func (gceCS *GCEControllerServer) CreateSnapshot(ctx context.Context, req *csi.C
811811
return nil, status.Error(codes.Internal, fmt.Sprintf("CreateSnapshot unknown get disk error: %v", err))
812812
}
813813

814-
snapshotParams, err := common.ExtractAndDefaultSnapshotParameters(req.GetParameters())
814+
snapshotParams, err := common.ExtractAndDefaultSnapshotParameters(req.GetParameters(), gceCS.Driver.name)
815815
if err != nil {
816816
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("Invalid snapshot parameters: %v", err))
817817
}

pkg/gce-pd-csi-driver/controller_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -940,7 +940,7 @@ func TestCreateVolumeWithVolumeSourceFromSnapshot(t *testing.T) {
940940
// Setup new driver each time so no interference
941941
gceDriver := initGCEDriver(t, nil)
942942

943-
snapshotParams, err := common.ExtractAndDefaultSnapshotParameters(nil)
943+
snapshotParams, err := common.ExtractAndDefaultSnapshotParameters(nil, gceDriver.name)
944944
if err != nil {
945945
t.Errorf("Got error extracting snapshot parameters: %v", err)
946946
}

test/e2e/tests/single_zone_e2e_test.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -839,14 +839,20 @@ var _ = Describe("GCE PD CSI Driver", func() {
839839
// This is safe because we hardcode the zones.
840840
snapshotLocation := z[:len(z)-2]
841841

842-
snapshotParams := map[string]string{common.ParameterKeyStorageLocations: snapshotLocation}
842+
snapshotParams := map[string]string{
843+
common.ParameterKeyStorageLocations: snapshotLocation,
844+
common.ParameterKeyVolumeSnapshotName: "test-volumesnapshot-name",
845+
common.ParameterKeyVolumeSnapshotNamespace: "test-volumesnapshot-namespace",
846+
common.ParameterKeyVolumeSnapshotContentName: "test-volumesnapshotcontent-name",
847+
}
843848
snapshotID, err := client.CreateSnapshot(snapshotName, volID, snapshotParams)
844849
Expect(err).To(BeNil(), "CreateSnapshot failed with error: %v", err)
845850

846851
// Validate Snapshot Created
847852
snapshot, err := computeService.Snapshots.Get(p, snapshotName).Do()
848853
Expect(err).To(BeNil(), "Could not get snapshot from cloud directly")
849854
Expect(snapshot.Name).To(Equal(snapshotName))
855+
Expect(snapshot.Description).To(Equal("{\"kubernetes.io/created-for/volumesnapshot/name\":\"test-volumesnapshot-name\",\"kubernetes.io/created-for/volumesnapshot/namespace\":\"test-volumesnapshot-namespace\",\"kubernetes.io/created-for/volumesnapshotcontent/name\":\"test-volumesnapshotcontent-name\",\"storage.gke.io/created-by\":\"pd.csi.storage.gke.io\"}"))
850856

851857
err = wait.Poll(10*time.Second, 3*time.Minute, func() (bool, error) {
852858
snapshot, err := computeService.Snapshots.Get(p, snapshotName).Do()

0 commit comments

Comments
 (0)