Skip to content

Commit ec9dda7

Browse files
authored
Merge pull request #254 from ggriffiths/common-ctrl-test-refactor
Refactor common controller tests to use withXYZ functions and add tests
2 parents 62e1dbb + 05efba2 commit ec9dda7

File tree

3 files changed

+109
-60
lines changed

3 files changed

+109
-60
lines changed

pkg/common-controller/framework_test.go

+32-11
Original file line numberDiff line numberDiff line change
@@ -164,16 +164,17 @@ type reactorError struct {
164164
error error
165165
}
166166

167-
func withSnapshotFinalizer(snapshot *crdv1.VolumeSnapshot) *crdv1.VolumeSnapshot {
168-
snapshot.ObjectMeta.Finalizers = append(snapshot.ObjectMeta.Finalizers, utils.VolumeSnapshotContentFinalizer)
169-
snapshot.ObjectMeta.Finalizers = append(snapshot.ObjectMeta.Finalizers, utils.VolumeSnapshotAsSourceFinalizer)
170-
snapshot.ObjectMeta.Finalizers = append(snapshot.ObjectMeta.Finalizers, utils.VolumeSnapshotBoundFinalizer)
171-
return snapshot
167+
func withSnapshotFinalizers(snapshots []*crdv1.VolumeSnapshot, finalizers ...string) []*crdv1.VolumeSnapshot {
168+
for i := range snapshots {
169+
for _, f := range finalizers {
170+
snapshots[i].ObjectMeta.Finalizers = append(snapshots[i].ObjectMeta.Finalizers, f)
171+
}
172+
}
173+
return snapshots
172174
}
173175

174176
func withContentFinalizer(content *crdv1.VolumeSnapshotContent) *crdv1.VolumeSnapshotContent {
175177
content.ObjectMeta.Finalizers = append(content.ObjectMeta.Finalizers, utils.VolumeSnapshotContentFinalizer)
176-
metav1.SetMetaDataAnnotation(&content.ObjectMeta, utils.AnnVolumeSnapshotBeingDeleted, "yes")
177178
return content
178179
}
179180

@@ -824,6 +825,18 @@ func newContent(contentName, boundToSnapshotUID, boundToSnapshotName, snapshotHa
824825
return &content
825826
}
826827

828+
func withContentAnnotations(contents []*crdv1.VolumeSnapshotContent, annotations map[string]string) []*crdv1.VolumeSnapshotContent {
829+
for i := range contents {
830+
if contents[i].ObjectMeta.Annotations == nil {
831+
contents[i].ObjectMeta.Annotations = make(map[string]string)
832+
}
833+
for k, v := range annotations {
834+
contents[i].ObjectMeta.Annotations[k] = v
835+
}
836+
}
837+
return contents
838+
}
839+
827840
func newContentArray(contentName, boundToSnapshotUID, boundToSnapshotName, snapshotHandle, snapshotClassName, desiredSnapshotHandle, volumeHandle string,
828841
deletionPolicy crdv1.DeletionPolicy, size, creationTime *int64,
829842
withFinalizer bool) []*crdv1.VolumeSnapshotContent {
@@ -863,7 +876,7 @@ func newContentWithUnmatchDriverArray(contentName, boundToSnapshotUID, boundToSn
863876
func newSnapshot(
864877
snapshotName, snapshotUID, pvcName, targetContentName, snapshotClassName, boundContentName string,
865878
readyToUse *bool, creationTime *metav1.Time, restoreSize *resource.Quantity,
866-
err *crdv1.VolumeSnapshotError, nilStatus bool, withFinalizer bool, deletionTimestamp *metav1.Time) *crdv1.VolumeSnapshot {
879+
err *crdv1.VolumeSnapshotError, nilStatus bool, withAllFinalizers bool, deletionTimestamp *metav1.Time) *crdv1.VolumeSnapshot {
867880
snapshot := crdv1.VolumeSnapshot{
868881
ObjectMeta: metav1.ObjectMeta{
869882
Name: snapshotName,
@@ -904,18 +917,18 @@ func newSnapshot(
904917
VolumeSnapshotContentName: &targetContentName,
905918
}
906919
}
907-
if withFinalizer {
908-
return withSnapshotFinalizer(&snapshot)
920+
if withAllFinalizers {
921+
return withSnapshotFinalizers([]*crdv1.VolumeSnapshot{&snapshot}, utils.VolumeSnapshotAsSourceFinalizer, utils.VolumeSnapshotBoundFinalizer)[0]
909922
}
910923
return &snapshot
911924
}
912925

913926
func newSnapshotArray(
914927
snapshotName, snapshotUID, pvcName, targetContentName, snapshotClassName, boundContentName string,
915928
readyToUse *bool, creationTime *metav1.Time, restoreSize *resource.Quantity,
916-
err *crdv1.VolumeSnapshotError, nilStatus bool, withFinalizer bool, deletionTimestamp *metav1.Time) []*crdv1.VolumeSnapshot {
929+
err *crdv1.VolumeSnapshotError, nilStatus bool, withAllFinalizers bool, deletionTimestamp *metav1.Time) []*crdv1.VolumeSnapshot {
917930
return []*crdv1.VolumeSnapshot{
918-
newSnapshot(snapshotName, snapshotUID, pvcName, targetContentName, snapshotClassName, boundContentName, readyToUse, creationTime, restoreSize, err, nilStatus, withFinalizer, deletionTimestamp),
931+
newSnapshot(snapshotName, snapshotUID, pvcName, targetContentName, snapshotClassName, boundContentName, readyToUse, creationTime, restoreSize, err, nilStatus, withAllFinalizers, deletionTimestamp),
919932
}
920933
}
921934

@@ -1071,6 +1084,14 @@ func testSyncContent(ctrl *csiSnapshotCommonController, reactor *snapshotReactor
10711084
return ctrl.syncContent(test.initialContents[0])
10721085
}
10731086

1087+
func testSyncContentError(ctrl *csiSnapshotCommonController, reactor *snapshotReactor, test controllerTest) error {
1088+
err := ctrl.syncContent(test.initialContents[0])
1089+
if err != nil {
1090+
return nil
1091+
}
1092+
return fmt.Errorf("syncContent succeeded when failure was expected")
1093+
}
1094+
10741095
func testAddPVCFinalizer(ctrl *csiSnapshotCommonController, reactor *snapshotReactor, test controllerTest) error {
10751096
return ctrl.ensurePVCFinalizer(test.initialSnapshots[0])
10761097
}

pkg/common-controller/snapshot_delete_test.go

+22-48
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,13 @@ limitations under the License.
1717
package common_controller
1818

1919
import (
20-
//"errors"
20+
"errors"
2121
"testing"
2222

2323
crdv1 "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1"
2424
"github.com/kubernetes-csi/external-snapshotter/v2/pkg/utils"
2525
v1 "k8s.io/api/core/v1"
2626
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27-
"k8s.io/apimachinery/pkg/types"
2827
)
2928

3029
var class1Parameters = map[string]string{
@@ -175,22 +174,7 @@ func TestDeleteSync(t *testing.T) {
175174
initialSecrets: []*v1.Secret{secret()},
176175
//expectedDeleteCalls: []deleteCall{{"sid1-3", map[string]string{"foo": "bar"}, nil}},
177176
test: testSyncContent,
178-
}, /*{
179-
name: "1-6 - api server delete content returns error",
180-
initialContents: newContentArray("content1-6", "sid1-6", "snap1-6", "sid1-6", validSecretClass, "", "", deletionPolicy, nil, nil, true),
181-
expectedContents: newContentArray("content1-6", "sid1-6", "snap1-6", "sid1-6", validSecretClass, "", "", deletionPolicy, nil, nil, true),
182-
initialSnapshots: nosnapshots,
183-
expectedSnapshots: nosnapshots,
184-
initialSecrets: []*v1.Secret{secret()},
185-
//expectedDeleteCalls: []deleteCall{{"sid1-6", map[string]string{"foo": "bar"}, nil}},
186-
expectedEvents: []string{"Warning SnapshotContentObjectDeleteError"},
187-
errors: []reactorError{
188-
// Inject error to the first client.VolumesnapshotV1beta1().VolumeSnapshotContents().Delete call.
189-
// All other calls will succeed.
190-
{"delete", "volumesnapshotcontents", errors.New("mock delete error")},
191-
},
192-
test: testSyncContent,
193-
},*/
177+
},
194178
{
195179
// delete success - snapshot that the content was pointing to was deleted, and another
196180
// with the same name created.
@@ -304,42 +288,32 @@ func TestDeleteSync(t *testing.T) {
304288
initialContents: newContentArray("content3-1", "", "snap3-1", "sid3-1", validSecretClass, "", "", deletePolicy, nil, nil, true),
305289
expectedContents: nocontents,
306290
initialSnapshots: newSnapshotArray("snap3-1", "snapuid3-1", "claim3-1", "", validSecretClass, "content3-1", &False, nil, nil, nil, false, true, &timeNowMetav1),
307-
expectedSnapshots: []*crdv1.VolumeSnapshot{
308-
&crdv1.VolumeSnapshot{
309-
ObjectMeta: metav1.ObjectMeta{
310-
Name: "snap3-1",
311-
Namespace: testNamespace,
312-
UID: types.UID("snapuid3-1"),
313-
ResourceVersion: "1",
314-
Finalizers: []string{
315-
"snapshot.storage.kubernetes.io/volumesnapshotcontent-bound-protection",
316-
"snapshot.storage.kubernetes.io/volumesnapshot-bound-protection",
317-
},
318-
SelfLink: "/apis/snapshot.storage.k8s.io/v1beta1/namespaces/" + testNamespace + "/volumesnapshots/" + "snap3-1",
319-
DeletionTimestamp: &timeNowMetav1,
320-
},
321-
Spec: crdv1.VolumeSnapshotSpec{
322-
VolumeSnapshotClassName: &validSecretClass,
323-
Source: crdv1.VolumeSnapshotSource{
324-
PersistentVolumeClaimName: &claim31,
325-
},
326-
},
327-
328-
Status: &crdv1.VolumeSnapshotStatus{
329-
CreationTime: nil,
330-
ReadyToUse: &False,
331-
Error: nil,
332-
RestoreSize: nil,
333-
BoundVolumeSnapshotContentName: &content31,
334-
},
335-
},
336-
},
291+
expectedSnapshots: withSnapshotFinalizers(newSnapshotArray("snap3-1", "snapuid3-1", "claim3-1", "", validSecretClass, "content3-1", &False, nil, nil, nil, false, false, &timeNowMetav1),
292+
utils.VolumeSnapshotBoundFinalizer,
293+
),
337294
initialClaims: newClaimArray("claim3-1", "pvc-uid3-1", "1Gi", "volume3-1", v1.ClaimBound, &classEmpty),
338295
expectedEvents: noevents,
339296
initialSecrets: []*v1.Secret{secret()},
340297
errors: noerrors,
341298
test: testSyncSnapshot,
342299
},
300+
{
301+
name: "3-2 - content will not be deleted if deletion API call fails",
302+
initialContents: newContentArray("content3-2", "", "snap3-2", "sid3-2", validSecretClass, "", "", deletePolicy, nil, nil, true),
303+
expectedContents: newContentArray("content3-2", "", "snap3-2", "sid3-2", validSecretClass, "", "", deletePolicy, nil, nil, true),
304+
initialSnapshots: newSnapshotArray("snap3-2", "snapuid3-2", "claim3-2", "", validSecretClass, "content3-2", &False, nil, nil, nil, false, true, &timeNowMetav1),
305+
expectedSnapshots: newSnapshotArray("snap3-2", "snapuid3-2", "claim3-2", "", validSecretClass, "content3-2", &False, nil, nil, nil, false, true, &timeNowMetav1),
306+
initialClaims: newClaimArray("claim3-2", "pvc-uid3-2", "1Gi", "volume3-2", v1.ClaimBound, &classEmpty),
307+
expectedEvents: []string{"Warning SnapshotContentObjectDeleteError"},
308+
initialSecrets: []*v1.Secret{secret()},
309+
errors: []reactorError{
310+
// Inject error to the first client.VolumesnapshotV1beta1().VolumeSnapshotContents().Delete call.
311+
// All other calls will succeed.
312+
{"delete", "volumesnapshotcontents", errors.New("mock delete error")},
313+
},
314+
expectSuccess: false,
315+
test: testSyncSnapshotError,
316+
},
343317
}
344318
runSyncTests(t, tests, snapshotClasses)
345319
}

pkg/common-controller/snapshot_update_test.go

+55-1
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ limitations under the License.
1717
package common_controller
1818

1919
import (
20-
//"errors"
20+
"errors"
2121
"testing"
2222
"time"
2323

24+
"github.com/kubernetes-csi/external-snapshotter/v2/pkg/utils"
2425
v1 "k8s.io/api/core/v1"
2526
storagev1beta1 "k8s.io/api/storage/v1beta1"
2627
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -282,6 +283,59 @@ func TestSync(t *testing.T) {
282283
errors: noerrors,
283284
test: testSyncSnapshot,
284285
},
286+
{
287+
name: "5-1 - content missing finalizer is updated to have finalizer",
288+
initialContents: newContentArray("content5-1", "snapuid5-1", "snap5-1", "sid5-1", validSecretClass, "", "", deletionPolicy, nil, nil, false),
289+
expectedContents: newContentArray("content5-1", "snapuid5-1", "snap5-1", "sid5-1", validSecretClass, "", "", deletionPolicy, nil, nil, true),
290+
initialClaims: newClaimArray("claim5-1", "pvc-uid5-1", "1Gi", "volume5-1", v1.ClaimBound, &classEmpty),
291+
initialVolumes: newVolumeArray("volume5-1", "pv-uid5-1", "pv-handle5-1", "1Gi", "pvc-uid5-1", "claim5-1", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
292+
initialSecrets: []*v1.Secret{secret()},
293+
errors: noerrors,
294+
test: testSyncContent,
295+
},
296+
{
297+
name: "5-2 - content missing finalizer update attempt fails because of failed API call",
298+
initialContents: newContentArray("content5-2", "snapuid5-2", "snap5-2", "sid5-2", validSecretClass, "", "", deletionPolicy, nil, nil, false),
299+
expectedContents: newContentArray("content5-2", "snapuid5-2", "snap5-2", "sid5-2", validSecretClass, "", "", deletionPolicy, nil, nil, false),
300+
initialClaims: newClaimArray("claim5-2", "pvc-uid5-2", "1Gi", "volume5-2", v1.ClaimBound, &classEmpty),
301+
initialVolumes: newVolumeArray("volume5-2", "pv-uid5-2", "pv-handle5-2", "1Gi", "pvc-uid5-2", "claim5-2", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
302+
initialSecrets: []*v1.Secret{secret()},
303+
errors: []reactorError{
304+
// Inject error to the forth client.VolumesnapshotV1beta1().VolumeSnapshots().Update call.
305+
{"update", "volumesnapshotcontents", errors.New("mock update error")},
306+
},
307+
expectSuccess: false,
308+
test: testSyncContentError,
309+
},
310+
{
311+
name: "5-3 - snapshot deletion candidate marked for deletion",
312+
initialSnapshots: newSnapshotArray("snap5-3", "snapuid5-3", "claim5-3", "", validSecretClass, "content5-3", &False, nil, nil, nil, false, true, &timeNowMetav1),
313+
expectedSnapshots: newSnapshotArray("snap5-3", "snapuid5-3", "claim5-3", "", validSecretClass, "content5-3", &False, nil, nil, nil, false, true, &timeNowMetav1),
314+
initialContents: newContentArray("content5-3", "snapuid5-3", "snap5-3", "sid5-3", validSecretClass, "", "", deletionPolicy, nil, nil, true),
315+
expectedContents: withContentAnnotations(newContentArray("content5-3", "snapuid5-3", "snap5-3", "sid5-3", validSecretClass, "", "", deletionPolicy, nil, nil, true), map[string]string{utils.AnnVolumeSnapshotBeingDeleted: "yes"}),
316+
initialClaims: newClaimArray("claim5-3", "pvc-uid5-3", "1Gi", "volume5-3", v1.ClaimBound, &classEmpty),
317+
initialVolumes: newVolumeArray("volume5-3", "pv-uid5-3", "pv-handle5-3", "1Gi", "pvc-uid5-3", "claim5-3", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
318+
initialSecrets: []*v1.Secret{secret()},
319+
expectSuccess: true,
320+
test: testSyncContent,
321+
},
322+
{
323+
name: "5-4 - snapshot deletion candidate fail to mark for deletion due to failed API call",
324+
initialSnapshots: newSnapshotArray("snap5-4", "snapuid5-4", "claim5-4", "", validSecretClass, "content5-4", &False, nil, nil, nil, false, true, &timeNowMetav1),
325+
expectedSnapshots: newSnapshotArray("snap5-4", "snapuid5-4", "claim5-4", "", validSecretClass, "content5-4", &False, nil, nil, nil, false, true, &timeNowMetav1),
326+
initialContents: newContentArray("content5-4", "snapuid5-4", "snap5-4", "sid5-4", validSecretClass, "", "", deletionPolicy, nil, nil, true),
327+
// result of the test framework - annotation is still set in memory, but update call fails.
328+
expectedContents: withContentAnnotations(newContentArray("content5-4", "snapuid5-4", "snap5-4", "sid5-4", validSecretClass, "", "", deletionPolicy, nil, nil, true), map[string]string{utils.AnnVolumeSnapshotBeingDeleted: "yes"}),
329+
initialClaims: newClaimArray("claim5-4", "pvc-uid5-4", "1Gi", "volume5-4", v1.ClaimBound, &classEmpty),
330+
initialVolumes: newVolumeArray("volume5-4", "pv-uid5-4", "pv-handle5-4", "1Gi", "pvc-uid5-4", "claim5-4", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
331+
initialSecrets: []*v1.Secret{secret()},
332+
errors: []reactorError{
333+
// Inject error to the forth client.VolumesnapshotV1beta1().VolumeSnapshots().Update call.
334+
{"update", "volumesnapshotcontents", errors.New("mock update error")},
335+
},
336+
expectSuccess: false,
337+
test: testSyncContentError,
338+
},
285339
}
286340

287341
runSyncTests(t, tests, snapshotClasses)

0 commit comments

Comments
 (0)