Skip to content

Commit 06794ef

Browse files
committed
status to optional, comments update
remove unnecessary binding call
1 parent 19abc09 commit 06794ef

6 files changed

+54
-77
lines changed

config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ spec:
4242
type: string
4343
driver:
4444
description: driver is the name of the storage driver that handles this
45-
VolumeSnapshotClass.
45+
VolumeSnapshotClass. Required.
4646
type: string
4747
kind:
4848
description: 'Kind is a string value representing the REST resource this

config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml

+7-6
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ spec:
3535
type: object
3636
spec:
3737
description: spec defines properties of a VolumeSnapshotContent created
38-
by the underlying storage system.
38+
by the underlying storage system. Required.
3939
properties:
4040
deletionPolicy:
4141
allOf:
@@ -68,15 +68,17 @@ spec:
6868
type: string
6969
source:
7070
description: source specifies from where a snapshot will be created.
71-
Required.
71+
This field is immutable after creation. Required.
7272
properties:
7373
snapshotHandle:
7474
description: snapshotHandle specifies the CSI name of a pre-existing
75-
snapshot on the underlying storage system.
75+
snapshot on the underlying storage system. This field is immutable
76+
once specified.
7677
type: string
7778
volumeHandle:
7879
description: volumeHandle specifies the CSI name of the volume from
79-
which a snapshot should be dynamically taken from.
80+
which a snapshot should be dynamically taken from. This field
81+
is immutable once specified.
8082
type: string
8183
type: object
8284
volumeSnapshotRef:
@@ -85,7 +87,7 @@ spec:
8587
field must reference to this VolumeSnapshotContent's name for the
8688
bidirectional binding to be valid. For a pre-existing VolumeSnapshotContent
8789
object, name and namespace of the VolumeSnapshot object MUST be provided
88-
for binding to happen. Required.
90+
for binding to happen. This field is immutable after creation. Required.
8991
properties:
9092
apiVersion:
9193
description: API version of the referent.
@@ -177,7 +179,6 @@ spec:
177179
type: object
178180
required:
179181
- spec
180-
- status
181182
type: object
182183
version: v1beta1
183184
versions:

config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml

+11-7
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,18 @@ spec:
4141
properties:
4242
source:
4343
description: source specifies where a snapshot will be created from.
44-
Required.
44+
This field is immutable after creation. Required.
4545
properties:
4646
persistentVolumeClaimName:
4747
description: persistentVolumeClaimName specifies the name of the
4848
PersistentVolumeClaim object in the same namespace as the VolumeSnapshot
49-
object where the snapshot should be dynamically taken from.
49+
object where the snapshot should be dynamically taken from. This
50+
field is immutable once specified.
5051
type: string
5152
volumeSnapshotContentName:
5253
description: volumeSnapshotContentName specifies the name of a pre-existing
5354
VolumeSnapshotContent object a user asks to statically bind the
54-
VolumeSnapshot object to.
55+
VolumeSnapshot object to. This field is immutable once specified.
5556
type: string
5657
type: object
5758
volumeSnapshotClassName:
@@ -72,11 +73,14 @@ spec:
7273
is accurate and complete.'
7374
properties:
7475
boundVolumeSnapshotContentName:
75-
description: boundVolumeSnapshotContentName represents the name of the
76-
VolumeSnapshotContent object to which the VolumeSnapshot object is
77-
bound. If not specified, it indicates that the VolumeSnapshot object
76+
description: 'boundVolumeSnapshotContentName represents the name of
77+
the VolumeSnapshotContent object to which the VolumeSnapshot object
78+
is bound. If not specified, it indicates that the VolumeSnapshot object
7879
has not been successfully bound to a VolumeSnapshotContent object
79-
yet.
80+
yet. NOTE: Specified boundVolumeSnapshotContentName alone does not
81+
mean binding is valid. Controllers MUST always verify bidirectional
82+
binding between VolumeSnapshot and VolumeSnapshotContent to
83+
avoid possible security issues.'
8084
type: string
8185
creationTime:
8286
description: creationTime, if not nil, represents the timestamp when

pkg/apis/volumesnapshot/v1beta1/types.go

+24-9
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ type VolumeSnapshotList struct {
6767
// VolumeSnapshotSpec describes the common attributes of a volume snapshot.
6868
type VolumeSnapshotSpec struct {
6969
// source specifies where a snapshot will be created from.
70+
// This field is immutable after creation.
7071
// Required.
7172
Source VolumeSnapshotSource `json:"source" protobuf:"bytes,1,opt,name=source"`
7273

@@ -78,7 +79,9 @@ type VolumeSnapshotSpec struct {
7879
VolumeSnapshotClassName *string `json:"volumeSnapshotClassName,omitempty" protobuf:"bytes,2,opt,name=volumeSnapshotClassName"`
7980
}
8081

81-
// VolumeSnapshotSource represents the source of a snapshot.
82+
// VolumeSnapshotSource specifies whether the underlying snapshot should be
83+
// dynamically taken upon creation or if a pre-existing VolumeSnapshotContent
84+
// object should be used.
8285
// Exactly one of its members must be set.
8386
// Members in VolumeSnapshotSource are immutable.
8487
// TODO(xiangqian): Add a webhook to ensure that VolumeSnapshotSource members
@@ -87,24 +90,26 @@ type VolumeSnapshotSource struct {
8790
// persistentVolumeClaimName specifies the name of the PersistentVolumeClaim
8891
// object in the same namespace as the VolumeSnapshot object where the
8992
// snapshot should be dynamically taken from.
93+
// This field is immutable once specified.
9094
// +optional
9195
PersistentVolumeClaimName *string `json:"persistentVolumeClaimName,omitempty" protobuf:"bytes,1,opt,name=persistentVolumeClaimName"`
9296

9397
// volumeSnapshotContentName specifies the name of a pre-existing VolumeSnapshotContent
9498
// object a user asks to statically bind the VolumeSnapshot object to.
99+
// This field is immutable once specified.
95100
// +optional
96101
VolumeSnapshotContentName *string `json:"volumeSnapshotContentName,omitempty" protobuf:"bytes,2,opt,name=volumeSnapshotContentName"`
97102
}
98103

99104
// VolumeSnapshotStatus is the status of the VolumeSnapshot
100105
type VolumeSnapshotStatus struct {
101-
// NOTE: All fields in VolumeSnapshotStatus are informational for user references.
102-
// Controllers MUST NOT rely on any fields programmatically.
103-
104106
// boundVolumeSnapshotContentName represents the name of the VolumeSnapshotContent
105107
// object to which the VolumeSnapshot object is bound.
106108
// If not specified, it indicates that the VolumeSnapshot object has not been
107109
// successfully bound to a VolumeSnapshotContent object yet.
110+
// NOTE: Specified boundVolumeSnapshotContentName alone does not mean binding
111+
// is valid. Controllers MUST always verify bidirectional binding between
112+
// VolumeSnapshot and VolumeSnapshotContent to avoid possible security issues.
108113
// +optional
109114
BoundVolumeSnapshotContentName *string `json:"boundVolumeSnapshotContentName,omitempty" protobuf:"bytes,1,opt,name=boundVolumeSnapshotContentName"`
110115

@@ -166,6 +171,7 @@ type VolumeSnapshotClass struct {
166171
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
167172

168173
// driver is the name of the storage driver that handles this VolumeSnapshotClass.
174+
// Required.
169175
Driver string `json:"driver" protobuf:"bytes,2,opt,name=driver"`
170176

171177
// parameters is a key-value map with storage driver specific parameters for creating snapshots.
@@ -215,10 +221,12 @@ type VolumeSnapshotContent struct {
215221
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
216222

217223
// spec defines properties of a VolumeSnapshotContent created by the underlying storage system.
224+
// Required.
218225
Spec VolumeSnapshotContentSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
219226

220227
// status represents the current information of a snapshot.
221-
Status VolumeSnapshotContentStatus `json:"status" protobuf:"bytes,3,opt,name=status"`
228+
// +optional
229+
Status VolumeSnapshotContentStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
222230
}
223231

224232
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@@ -242,6 +250,7 @@ type VolumeSnapshotContentSpec struct {
242250
// this VolumeSnapshotContent's name for the bidirectional binding to be valid.
243251
// For a pre-existing VolumeSnapshotContent object, name and namespace of the
244252
// VolumeSnapshot object MUST be provided for binding to happen.
253+
// This field is immutable after creation.
245254
// Required.
246255
VolumeSnapshotRef core_v1.ObjectReference `json:"volumeSnapshotRef" protobuf:"bytes,1,opt,name=volumeSnapshotRef"`
247256

@@ -269,23 +278,26 @@ type VolumeSnapshotContentSpec struct {
269278
SnapshotClassName *string `json:"snapshotClassName,omitempty" protobuf:"bytes,4,opt,name=snapshotClassName"`
270279

271280
// source specifies from where a snapshot will be created.
281+
// This field is immutable after creation.
272282
// Required.
273283
Source VolumeSnapshotContentSource `json:"source" protobuf:"bytes,5,opt,name=source"`
274284
}
275285

276-
// VolumeSnapshotContentSource represents the source of a snapshot.
286+
// VolumeSnapshotContentSource represents the CSI source of a snapshot.
277287
// Exactly one of its members must be set.
278288
// Members in VolumeSnapshotContentSource are immutable.
279289
// TODO(xiangqian): Add a webhook to ensure that VolumeSnapshotContentSource members
280-
// will not be updated once specified.
290+
// will be immutable once specified.
281291
type VolumeSnapshotContentSource struct {
282292
// volumeHandle specifies the CSI name of the volume from which a snapshot
283293
// should be dynamically taken from.
294+
// This field is immutable once specified.
284295
// +optional
285296
VolumeHandle *string `json:"volumeHandle,omitempty" protobuf:"bytes,1,opt,name=volumeHandle"`
286297

287298
// snapshotHandle specifies the CSI name of a pre-existing snapshot on the
288299
// underlying storage system.
300+
// This field is immutable once specified.
289301
// +optional
290302
SnapshotHandle *string `json:"snapshotHandle,omitempty" protobuf:"bytes,2,opt,name=snapshotHandle"`
291303
}
@@ -322,6 +334,7 @@ type VolumeSnapshotContentStatus struct {
322334
// If not specified, it means the readiness of a snapshot is unknown.
323335
// +optional.
324336
ReadyToUse *bool `json:"readyToUse,omitempty" protobuf:"varint,4,opt,name=readyToUse"`
337+
325338
// error is the latest observed error during snapshot creation, if any.
326339
// +optional
327340
Error *VolumeSnapshotError `json:"error,omitempty" protobuf:"bytes,5,opt,name=error,casttype=VolumeSnapshotError"`
@@ -332,10 +345,12 @@ type VolumeSnapshotContentStatus struct {
332345
type DeletionPolicy string
333346

334347
const (
335-
// volumeSnapshotContentDelete means the snapshot will be deleted from Kubernetes on release from its volume snapshot.
348+
// volumeSnapshotContentDelete means the snapshot will be deleted from the
349+
// underlying storage system on release from its volume snapshot.
336350
VolumeSnapshotContentDelete DeletionPolicy = "Delete"
337351

338-
// volumeSnapshotContentRetain means the snapshot will be left in its current state on release from its volume snapshot.
352+
// volumeSnapshotContentRetain means the snapshot will be left in its current
353+
// state on release from its volume snapshot.
339354
VolumeSnapshotContentRetain DeletionPolicy = "Retain"
340355
)
341356

pkg/controller/snapshot_controller.go

+9-52
Original file line numberDiff line numberDiff line change
@@ -274,14 +274,10 @@ func (ctrl *csiSnapshotController) syncUnreadySnapshot(snapshot *crdv1.VolumeSna
274274
// find a matching volume snapshot content
275275
if contentObj := ctrl.getMatchSnapshotContent(snapshot); contentObj != nil {
276276
klog.V(5).Infof("Find VolumeSnapshotContent object %s for snapshot %s", contentObj.Name, uniqueSnapshotName)
277-
newSnapshot, err := ctrl.bindandUpdateVolumeSnapshot(contentObj, snapshot)
278-
if err != nil {
279-
return err
280-
}
281-
if err = ctrl.checkandUpdateBoundSnapshotStatus(newSnapshot, contentObj); err != nil {
277+
if err := ctrl.checkandUpdateBoundSnapshotStatus(snapshot, contentObj); err != nil {
282278
return err
283279
}
284-
klog.V(5).Infof("bindandUpdateVolumeSnapshot %v", newSnapshot)
280+
klog.V(5).Infof("checkandUpdateBoundSnapshotStatus %v", snapshot)
285281
} else if snapshot.Status.BoundVolumeSnapshotContentName != nil {
286282
contentObj, found, err := ctrl.contentStore.GetByKey(*snapshot.Status.BoundVolumeSnapshotContentName)
287283
if err != nil {
@@ -686,12 +682,6 @@ func (ctrl *csiSnapshotController) createSnapshotOperation(snapshot *crdv1.Volum
686682
VolumeHandle: &volume.Spec.CSI.VolumeHandle,
687683
},
688684
},
689-
Status: crdv1.VolumeSnapshotContentStatus{
690-
SnapshotHandle: &snapshotID,
691-
CreationTime: &timestamp,
692-
RestoreSize: &size,
693-
ReadyToUse: &readyToUse,
694-
},
695685
}
696686

697687
// Set AnnDeletionSecretRefName and AnnDeletionSecretRefNamespace
@@ -707,15 +697,19 @@ func (ctrl *csiSnapshotController) createSnapshotOperation(snapshot *crdv1.Volum
707697
// Try to create the VolumeSnapshotContent object several times
708698
for i := 0; i < ctrl.createSnapshotContentRetryCount; i++ {
709699
klog.V(5).Infof("createSnapshot [%s]: trying to save volume snapshot content %s", snapshotKey(snapshot), snapshotContent.Name)
710-
if _, err = ctrl.clientset.SnapshotV1beta1().VolumeSnapshotContents().Create(snapshotContent); err == nil || apierrs.IsAlreadyExists(err) {
700+
var newContent *crdv1.VolumeSnapshotContent
701+
if newContent, err = ctrl.clientset.SnapshotV1beta1().VolumeSnapshotContents().Create(snapshotContent); err == nil || apierrs.IsAlreadyExists(err) {
711702
// Save succeeded.
712703
if err != nil {
713704
klog.V(3).Infof("volume snapshot content %q for snapshot %q already exists, reusing", snapshotContent.Name, snapshotKey(snapshot))
714705
err = nil
715706
} else {
716707
klog.V(3).Infof("volume snapshot content %q for snapshot %q saved, %v", snapshotContent.Name, snapshotKey(snapshot), snapshotContent)
717708
}
718-
break
709+
err = ctrl.updateSnapshotContentStatus(newContent, snapshotID, readyToUse, timestamp, size)
710+
if err == nil {
711+
break
712+
}
719713
}
720714
// Save failed, try again after a while.
721715
klog.V(3).Infof("failed to save volume snapshot content %q for snapshot %q: %v", snapshotContent.Name, snapshotKey(snapshot), err)
@@ -731,13 +725,7 @@ func (ctrl *csiSnapshotController) createSnapshotOperation(snapshot *crdv1.Volum
731725
ctrl.eventRecorder.Event(newSnapshot, v1.EventTypeWarning, "CreateSnapshotContentFailed", strerr)
732726
return nil, newControllerUpdateError(snapshotKey(snapshot), err.Error())
733727
}
734-
735-
// save succeeded, bind and update status for snapshot.
736-
result, err := ctrl.bindandUpdateVolumeSnapshot(snapshotContent, newSnapshot)
737-
if err != nil {
738-
return nil, err
739-
}
740-
return result, nil
728+
return newSnapshot, nil
741729
}
742730

743731
// Delete a snapshot
@@ -784,37 +772,6 @@ func (ctrl *csiSnapshotController) deleteSnapshotContentOperation(content *crdv1
784772
return nil
785773
}
786774

787-
func (ctrl *csiSnapshotController) bindandUpdateVolumeSnapshot(snapshotContent *crdv1.VolumeSnapshotContent, snapshot *crdv1.VolumeSnapshot) (*crdv1.VolumeSnapshot, error) {
788-
klog.V(5).Infof("bindandUpdateVolumeSnapshot for snapshot [%s]: snapshotContent [%s]", snapshot.Name, snapshotContent.Name)
789-
snapshotObj, err := ctrl.clientset.SnapshotV1beta1().VolumeSnapshots(snapshot.Namespace).Get(snapshot.Name, metav1.GetOptions{})
790-
if err != nil {
791-
return nil, fmt.Errorf("error get snapshot %s from api server: %v", snapshotKey(snapshot), err)
792-
}
793-
794-
// Copy the snapshot object before updating it
795-
snapshotCopy := snapshotObj.DeepCopy()
796-
797-
if snapshotObj.Status.BoundVolumeSnapshotContentName != nil && *snapshotObj.Status.BoundVolumeSnapshotContentName == snapshotContent.Name {
798-
klog.Infof("bindVolumeSnapshotContentToVolumeSnapshot: VolumeSnapshot %s already bind to volumeSnapshotContent [%s]", snapshot.Name, snapshotContent.Name)
799-
} else {
800-
klog.Infof("bindVolumeSnapshotContentToVolumeSnapshot: before bind VolumeSnapshot %s to volumeSnapshotContent [%s]", snapshot.Name, snapshotContent.Name)
801-
snapshotCopy.Status.BoundVolumeSnapshotContentName = &snapshotContent.Name
802-
updateSnapshot, err := ctrl.clientset.SnapshotV1beta1().VolumeSnapshots(snapshot.Namespace).Update(snapshotCopy)
803-
if err != nil {
804-
klog.Infof("bindVolumeSnapshotContentToVolumeSnapshot: Error binding VolumeSnapshot %s to volumeSnapshotContent [%s]. Error [%#v]", snapshot.Name, snapshotContent.Name, err)
805-
return nil, newControllerUpdateError(snapshotKey(snapshot), err.Error())
806-
}
807-
snapshotCopy = updateSnapshot
808-
_, err = ctrl.storeSnapshotUpdate(snapshotCopy)
809-
if err != nil {
810-
klog.Errorf("%v", err)
811-
}
812-
}
813-
814-
klog.V(5).Infof("bindandUpdateVolumeSnapshot for snapshot completed [%#v]", snapshotCopy)
815-
return snapshotCopy, nil
816-
}
817-
818775
// TODO(xiangqian) This is a temp implementation to make sure the test cases pass
819776
func (ctrl *csiSnapshotController) updateSnapshotContentStatus(
820777
content *crdv1.VolumeSnapshotContent,

pkg/controller/snapshot_ready_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,11 @@ func TestSync(t *testing.T) {
196196
test: testSyncSnapshot,
197197
},
198198
{
199-
name: "2-9 - bind when snapshot and content matches, fail on status update as there is not pvc provided",
199+
name: "2-9 - fail on status update as there is not pvc provided",
200200
initialContents: newContentArray("content2-9", "snapuid2-9", "snap2-9", "sid2-9", validSecretClass, "", "", deletionPolicy, nil, nil, false),
201201
expectedContents: newContentArray("content2-9", "snapuid2-9", "snap2-9", "sid2-9", validSecretClass, "", "", deletionPolicy, nil, nil, false),
202202
initialSnapshots: newSnapshotArray("snap2-9", "snapuid2-9", "claim2-9", "", validSecretClass, "", &False, nil, nil, nil),
203-
expectedSnapshots: newSnapshotArray("snap2-9", "snapuid2-9", "claim2-9", "", validSecretClass, "content2-9", &False, nil, nil, newVolumeError("Failed to check and update snapshot: failed to get input parameters to create snapshot snap2-9: \"failed to retrieve PVC claim2-9 from the lister: \\\"persistentvolumeclaim \\\\\\\"claim2-9\\\\\\\" not found\\\"\"")),
203+
expectedSnapshots: newSnapshotArray("snap2-9", "snapuid2-9", "claim2-9", "", validSecretClass, "", &False, nil, nil, newVolumeError("Failed to check and update snapshot: failed to get input parameters to create snapshot snap2-9: \"failed to retrieve PVC claim2-9 from the lister: \\\"persistentvolumeclaim \\\\\\\"claim2-9\\\\\\\" not found\\\"\"")),
204204
errors: noerrors,
205205
test: testSyncSnapshot,
206206
},

0 commit comments

Comments
 (0)