Skip to content

Commit 84cca93

Browse files
authored
Merge pull request #98 from kastenhq/prebound-fix
Fix for pre-bound snapshot empty source error
2 parents 76f6d7f + 2fcfc8b commit 84cca93

File tree

3 files changed

+67
-32
lines changed

3 files changed

+67
-32
lines changed

pkg/controller/framework_test.go

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ import (
2828
"testing"
2929
"time"
3030

31-
"k8s.io/klog"
32-
3331
crdv1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1"
3432
clientset "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned"
3533
"github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/fake"
@@ -54,6 +52,7 @@ import (
5452
core "k8s.io/client-go/testing"
5553
"k8s.io/client-go/tools/cache"
5654
"k8s.io/client-go/tools/record"
55+
"k8s.io/klog"
5756
)
5857

5958
// This is a unit test framework for snapshot controller.
@@ -768,15 +767,17 @@ func newContent(name, className, snapshotHandle, volumeUID, volumeName, boundToS
768767
},
769768
},
770769
VolumeSnapshotClassName: &className,
771-
PersistentVolumeRef: &v1.ObjectReference{
772-
Kind: "PersistentVolume",
773-
APIVersion: "v1",
774-
UID: types.UID(volumeUID),
775-
Name: volumeName,
776-
},
777-
DeletionPolicy: deletionPolicy,
770+
DeletionPolicy: deletionPolicy,
778771
},
779772
}
773+
if volumeName != noVolume {
774+
content.Spec.PersistentVolumeRef = &v1.ObjectReference{
775+
Kind: "PersistentVolume",
776+
APIVersion: "v1",
777+
UID: types.UID(volumeUID),
778+
Name: volumeName,
779+
}
780+
}
780781
if boundToSnapshotName != "" {
781782
content.Spec.VolumeSnapshotRef = &v1.ObjectReference{
782783
Kind: "VolumeSnapshot",
@@ -817,10 +818,6 @@ func newSnapshot(name, className, boundToContent, snapshotUID, claimName string,
817818
SelfLink: "/apis/snapshot.storage.k8s.io/v1alpha1/namespaces/" + testNamespace + "/volumesnapshots/" + name,
818819
},
819820
Spec: crdv1.VolumeSnapshotSpec{
820-
Source: &v1.TypedLocalObjectReference{
821-
Name: claimName,
822-
Kind: "PersistentVolumeClaim",
823-
},
824821
VolumeSnapshotClassName: &className,
825822
SnapshotContentName: boundToContent,
826823
},
@@ -831,6 +828,12 @@ func newSnapshot(name, className, boundToContent, snapshotUID, claimName string,
831828
RestoreSize: size,
832829
},
833830
}
831+
if claimName != noClaim {
832+
snapshot.Spec.Source = &v1.TypedLocalObjectReference{
833+
Name: claimName,
834+
Kind: "PersistentVolumeClaim",
835+
}
836+
}
834837

835838
return withSnapshotFinalizer(&snapshot)
836839
}
@@ -969,6 +972,9 @@ var (
969972
validSecretClass = "valid-secret-class"
970973
sameDriver = "sameDriver"
971974
diffDriver = "diffDriver"
975+
noClaim = ""
976+
noBoundUID = ""
977+
noVolume = ""
972978
)
973979

974980
// wrapTestWithInjectedOperation returns a testCall that:

pkg/controller/snapshot_controller.go

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -256,16 +256,15 @@ func (ctrl *csiSnapshotController) syncUnreadySnapshot(snapshot *crdv1.VolumeSna
256256
if !ok {
257257
return fmt.Errorf("expected volume snapshot content, got %+v", contentObj)
258258
}
259-
260-
if err := ctrl.checkandBindSnapshotContent(snapshot, content); err != nil {
259+
contentBound, err := ctrl.checkandBindSnapshotContent(snapshot, content)
260+
if err != nil {
261261
// snapshot is bound but content is not bound to snapshot correctly
262262
ctrl.updateSnapshotErrorStatusWithEvent(snapshot, v1.EventTypeWarning, "SnapshotBindFailed", fmt.Sprintf("Snapshot failed to bind VolumeSnapshotContent, %v", err))
263263
return fmt.Errorf("snapshot %s is bound, but VolumeSnapshotContent %s is not bound to the VolumeSnapshot correctly, %v", uniqueSnapshotName, content.Name, err)
264264
}
265-
266265
// snapshot is already bound correctly, check the status and update if it is ready.
267266
klog.V(5).Infof("Check and update snapshot %s status", uniqueSnapshotName)
268-
if err = ctrl.checkandUpdateBoundSnapshotStatus(snapshot, content); err != nil {
267+
if err = ctrl.checkandUpdateBoundSnapshotStatus(snapshot, contentBound); err != nil {
269268
return err
270269
}
271270
return nil
@@ -492,13 +491,13 @@ func (ctrl *csiSnapshotController) isVolumeBeingCreatedFromSnapshot(snapshot *cr
492491
}
493492

494493
// The function checks whether the volumeSnapshotRef in snapshot content matches the given snapshot. If match, it binds the content with the snapshot
495-
func (ctrl *csiSnapshotController) checkandBindSnapshotContent(snapshot *crdv1.VolumeSnapshot, content *crdv1.VolumeSnapshotContent) error {
494+
func (ctrl *csiSnapshotController) checkandBindSnapshotContent(snapshot *crdv1.VolumeSnapshot, content *crdv1.VolumeSnapshotContent) (*crdv1.VolumeSnapshotContent, error) {
496495
if content.Spec.VolumeSnapshotRef == nil || content.Spec.VolumeSnapshotRef.Name != snapshot.Name {
497-
return fmt.Errorf("Could not bind snapshot %s and content %s, the VolumeSnapshotRef does not match", snapshot.Name, content.Name)
496+
return nil, fmt.Errorf("Could not bind snapshot %s and content %s, the VolumeSnapshotRef does not match", snapshot.Name, content.Name)
498497
} else if content.Spec.VolumeSnapshotRef.UID != "" && content.Spec.VolumeSnapshotRef.UID != snapshot.UID {
499-
return fmt.Errorf("Could not bind snapshot %s and content %s, the VolumeSnapshotRef does not match", snapshot.Name, content.Name)
498+
return nil, fmt.Errorf("Could not bind snapshot %s and content %s, the VolumeSnapshotRef does not match", snapshot.Name, content.Name)
500499
} else if content.Spec.VolumeSnapshotRef.UID != "" && content.Spec.VolumeSnapshotClassName != nil {
501-
return nil
500+
return content, nil
502501
}
503502
contentClone := content.DeepCopy()
504503
contentClone.Spec.VolumeSnapshotRef.UID = snapshot.UID
@@ -507,14 +506,14 @@ func (ctrl *csiSnapshotController) checkandBindSnapshotContent(snapshot *crdv1.V
507506
newContent, err := ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshotContents().Update(contentClone)
508507
if err != nil {
509508
klog.V(4).Infof("updating VolumeSnapshotContent[%s] error status failed %v", newContent.Name, err)
510-
return err
509+
return nil, err
511510
}
512511
_, err = ctrl.storeContentUpdate(newContent)
513512
if err != nil {
514513
klog.V(4).Infof("updating VolumeSnapshotContent[%s] error status: cannot update internal cache %v", newContent.Name, err)
515-
return err
514+
return nil, err
516515
}
517-
return nil
516+
return newContent, nil
518517
}
519518

520519
func (ctrl *csiSnapshotController) getCreateSnapshotInput(snapshot *crdv1.VolumeSnapshot) (*crdv1.VolumeSnapshotClass, *v1.PersistentVolume, string, map[string]string, error) {
@@ -560,14 +559,29 @@ func (ctrl *csiSnapshotController) checkandUpdateBoundSnapshotStatusOperation(sn
560559
var timestamp int64
561560
var size int64
562561
var readyToUse = false
563-
class, volume, _, snapshotterCredentials, err := ctrl.getCreateSnapshotInput(snapshot)
564-
if err != nil {
565-
return nil, fmt.Errorf("failed to get input parameters to create snapshot %s: %q", snapshot.Name, err)
566-
}
567-
driverName, snapshotID, timestamp, size, readyToUse, err := ctrl.handler.CreateSnapshot(snapshot, volume, class.Parameters, snapshotterCredentials)
568-
if err != nil {
569-
klog.Errorf("checkandUpdateBoundSnapshotStatusOperation: failed to call create snapshot to check whether the snapshot is ready to use %q", err)
570-
return nil, err
562+
var driverName string
563+
var snapshotID string
564+
565+
if snapshot.Spec.Source == nil {
566+
klog.V(5).Infof("checkandUpdateBoundSnapshotStatusOperation: checking whether snapshot [%s] is pre-bound to content [%s]", snapshot.Name, content.Name)
567+
readyToUse, timestamp, size, err = ctrl.handler.GetSnapshotStatus(content)
568+
if err != nil {
569+
klog.Errorf("checkandUpdateBoundSnapshotStatusOperation: failed to call get snapshot status to check whether snapshot is ready to use %q", err)
570+
return nil, err
571+
}
572+
if content.Spec.CSI != nil {
573+
driverName, snapshotID = content.Spec.CSI.Driver, content.Spec.CSI.SnapshotHandle
574+
}
575+
} else {
576+
class, volume, _, snapshotterCredentials, err := ctrl.getCreateSnapshotInput(snapshot)
577+
if err != nil {
578+
return nil, fmt.Errorf("failed to get input parameters to create snapshot %s: %q", snapshot.Name, err)
579+
}
580+
driverName, snapshotID, timestamp, size, readyToUse, err = ctrl.handler.CreateSnapshot(snapshot, volume, class.Parameters, snapshotterCredentials)
581+
if err != nil {
582+
klog.Errorf("checkandUpdateBoundSnapshotStatusOperation: failed to call create snapshot to check whether the snapshot is ready to use %q", err)
583+
return nil, err
584+
}
571585
}
572586
klog.V(5).Infof("checkandUpdateBoundSnapshotStatusOperation: driver %s, snapshotId %s, timestamp %d, size %d, readyToUse %t", driverName, snapshotID, timestamp, size, readyToUse)
573587

pkg/controller/snapshot_ready_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,21 @@ func TestSync(t *testing.T) {
123123
errors: noerrors,
124124
test: testSyncSnapshot,
125125
},
126+
{
127+
name: "2-6 - snapshot bound to prebound content correctly, status ready false -> true, ref.UID '' -> 'snapuid2-6'",
128+
initialContents: newContentArray("content2-6", validSecretClass, "sid2-6", noVolume, noVolume, noBoundUID, "snap2-6", &deletePolicy, nil, &timeNow, false),
129+
expectedContents: newContentArray("content2-6", validSecretClass, "sid2-6", noVolume, noVolume, "snapuid2-6", "snap2-6", &deletePolicy, nil, &timeNow, false),
130+
initialSnapshots: newSnapshotArray("snap2-6", validSecretClass, "content2-6", "snapuid2-6", noClaim, false, nil, metaTimeNow, nil),
131+
expectedSnapshots: newSnapshotArray("snap2-6", validSecretClass, "content2-6", "snapuid2-6", noClaim, true, nil, metaTimeNow, nil),
132+
expectedListCalls: []listCall{
133+
{
134+
snapshotID: "sid2-6",
135+
readyToUse: true,
136+
},
137+
},
138+
errors: noerrors,
139+
test: testSyncSnapshot,
140+
},
126141
{
127142
name: "2-7 - snapshot and content bound, csi driver get status error",
128143
initialContents: newContentArray("content2-7", validSecretClass, "sid2-7", "vuid2-7", "volume2-7", "snapuid2-7", "snap2-7", &deletePolicy, nil, nil, false),

0 commit comments

Comments
 (0)