add UT for snapshot controller
This commit is contained in:
91
pkg/controller/snapshot_controller_test.go
Normal file
91
pkg/controller/snapshot_controller_test.go
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controller
|
||||
|
||||
import (
|
||||
crdv1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func storeVersion(t *testing.T, prefix string, c cache.Store, version string, expectedReturn bool) {
|
||||
content := newContent("contentName", classEmpty, "sid1-1", "vuid1-1", "volume1-1", "snapuid1-1", "snap1-1", nil, nil)
|
||||
content.ResourceVersion = version
|
||||
ret, err := storeObjectUpdate(c, content, "content")
|
||||
if err != nil {
|
||||
t.Errorf("%s: expected storeObjectUpdate to succeed, got: %v", prefix, err)
|
||||
}
|
||||
if expectedReturn != ret {
|
||||
t.Errorf("%s: expected storeObjectUpdate to return %v, got: %v", prefix, expectedReturn, ret)
|
||||
}
|
||||
|
||||
// find the stored version
|
||||
|
||||
contentObj, found, err := c.GetByKey("contentName")
|
||||
if err != nil {
|
||||
t.Errorf("expected content 'contentName' in the cache, got error instead: %v", err)
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("expected content 'contentName' in the cache but it was not found")
|
||||
}
|
||||
content, ok := contentObj.(*crdv1.VolumeSnapshotContent)
|
||||
if !ok {
|
||||
t.Errorf("expected content in the cache, got different object instead: %#v", contentObj)
|
||||
}
|
||||
|
||||
if ret {
|
||||
if content.ResourceVersion != version {
|
||||
t.Errorf("expected content with version %s in the cache, got %s instead", version, content.ResourceVersion)
|
||||
}
|
||||
} else {
|
||||
if content.ResourceVersion == version {
|
||||
t.Errorf("expected content with version other than %s in the cache, got %s instead", version, content.ResourceVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestControllerCache tests func storeObjectUpdate()
|
||||
func TestControllerCache(t *testing.T) {
|
||||
// Cache under test
|
||||
c := cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc)
|
||||
|
||||
// Store new PV
|
||||
storeVersion(t, "Step1", c, "1", true)
|
||||
// Store the same PV
|
||||
storeVersion(t, "Step2", c, "1", true)
|
||||
// Store newer PV
|
||||
storeVersion(t, "Step3", c, "2", true)
|
||||
// Store older PV - simulating old "PV updated" event or periodic sync with
|
||||
// old data
|
||||
storeVersion(t, "Step4", c, "1", false)
|
||||
// Store newer PV - test integer parsing ("2" > "10" as string,
|
||||
// while 2 < 10 as integers)
|
||||
storeVersion(t, "Step5", c, "10", true)
|
||||
}
|
||||
|
||||
func TestControllerCacheParsingError(t *testing.T) {
|
||||
c := cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc)
|
||||
// There must be something in the cache to compare with
|
||||
storeVersion(t, "Step1", c, "1", true)
|
||||
|
||||
content := newContent("contentName", classEmpty, "sid1-1", "vuid1-1", "volume1-1", "snapuid1-1", "snap1-1", nil, nil)
|
||||
content.ResourceVersion = "xxx"
|
||||
_, err := storeObjectUpdate(c, content, "content")
|
||||
if err == nil {
|
||||
t.Errorf("Expected parsing error, got nil instead")
|
||||
}
|
||||
}
|
391
pkg/controller/snapshot_create_test.go
Normal file
391
pkg/controller/snapshot_create_test.go
Normal file
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controller
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi/v0"
|
||||
"k8s.io/api/core/v1"
|
||||
storage "k8s.io/api/storage/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
var timeNow = time.Now().UnixNano()
|
||||
|
||||
var metaTimeNowUnix = &metav1.Time{
|
||||
Time: time.Unix(0, timeNow),
|
||||
}
|
||||
|
||||
var defaultSize int64 = 1000
|
||||
|
||||
var sameDriverStorageClass = &storage.StorageClass{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "sameDriver",
|
||||
},
|
||||
Provisioner: mockDriverName,
|
||||
Parameters: class1Parameters,
|
||||
}
|
||||
|
||||
var diffDriverStorageClass = &storage.StorageClass{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "diffDriver",
|
||||
},
|
||||
Provisioner: mockDriverName,
|
||||
Parameters: class1Parameters,
|
||||
}
|
||||
|
||||
// Test single call to SyncSnapshot, expecting create snapshot to happen.
|
||||
// 1. Fill in the controller with initial data
|
||||
// 2. Call the SyncSnapshot *once*.
|
||||
// 3. Compare resulting contents with expected contents.
|
||||
func TestCreateSnapshotSync(t *testing.T) {
|
||||
tests := []controllerTest{
|
||||
{
|
||||
name: "6-1 - successful create snapshot with snapshot class gold",
|
||||
initialContents: nocontents,
|
||||
expectedContents: newContentArray("snapcontent-snapuid6-1", classGold, "sid6-1", "pv-uid6-1", "volume6-1", "snapuid6-1", "snap6-1", getSize(defaultSize), &timeNow),
|
||||
initialSnapshots: newSnapshotArray("snap6-1", classGold, "", "snapuid6-1", "claim6-1", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap6-1", classGold, "snapcontent-snapuid6-1", "snapuid6-1", "claim6-1", false, nil, metaTimeNowUnix, getSize(defaultSize)),
|
||||
initialClaims: newClaimArray("claim6-1", "pvc-uid6-1", "1Gi", "volume6-1", v1.ClaimBound, &classEmpty),
|
||||
initialVolumes: newVolumeArray("volume6-1", "pv-uid6-1", "pv-handle6-1", "1Gi", "pvc-uid6-1", "claim6-1", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
expectedCreateCalls: []createCall{
|
||||
{
|
||||
snapshotName: "snapshot-snapuid6-1",
|
||||
volume: newVolume("volume6-1", "pv-uid6-1", "pv-handle6-1", "1Gi", "pvc-uid6-1", "claim6-1", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
parameters: map[string]string{"param1": "value1"},
|
||||
// information to return
|
||||
driverName: mockDriverName,
|
||||
size: defaultSize,
|
||||
snapshotId: "sid6-1",
|
||||
timestamp: timeNow,
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_READY,
|
||||
Details: "success",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "6-2 - successful create snapshot with snapshot class silver",
|
||||
initialContents: nocontents,
|
||||
expectedContents: newContentArray("snapcontent-snapuid6-2", classSilver, "sid6-2", "pv-uid6-2", "volume6-2", "snapuid6-2", "snap6-2", getSize(defaultSize), &timeNow),
|
||||
initialSnapshots: newSnapshotArray("snap6-2", classSilver, "", "snapuid6-2", "claim6-2", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap6-2", classSilver, "snapcontent-snapuid6-2", "snapuid6-2", "claim6-2", false, nil, metaTimeNowUnix, getSize(defaultSize)),
|
||||
initialClaims: newClaimArray("claim6-2", "pvc-uid6-2", "1Gi", "volume6-2", v1.ClaimBound, &classEmpty),
|
||||
initialVolumes: newVolumeArray("volume6-2", "pv-uid6-2", "pv-handle6-2", "1Gi", "pvc-uid6-2", "claim6-2", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
expectedCreateCalls: []createCall{
|
||||
{
|
||||
snapshotName: "snapshot-snapuid6-2",
|
||||
volume: newVolume("volume6-2", "pv-uid6-2", "pv-handle6-2", "1Gi", "pvc-uid6-2", "claim6-2", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
parameters: map[string]string{"param2": "value2"},
|
||||
// information to return
|
||||
driverName: mockDriverName,
|
||||
size: defaultSize,
|
||||
snapshotId: "sid6-2",
|
||||
timestamp: timeNow,
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_READY,
|
||||
Details: "success",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "6-3 - successful create snapshot with snapshot class valid-secret-class",
|
||||
initialContents: nocontents,
|
||||
expectedContents: newContentArray("snapcontent-snapuid6-3", validSecretClass, "sid6-3", "pv-uid6-3", "volume6-3", "snapuid6-3", "snap6-3", getSize(defaultSize), &timeNow),
|
||||
initialSnapshots: newSnapshotArray("snap6-3", validSecretClass, "", "snapuid6-3", "claim6-3", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap6-3", validSecretClass, "snapcontent-snapuid6-3", "snapuid6-3", "claim6-3", false, nil, metaTimeNowUnix, getSize(defaultSize)),
|
||||
initialClaims: newClaimArray("claim6-3", "pvc-uid6-3", "1Gi", "volume6-3", v1.ClaimBound, &classEmpty),
|
||||
initialVolumes: newVolumeArray("volume6-3", "pv-uid6-3", "pv-handle6-3", "1Gi", "pvc-uid6-3", "claim6-3", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
initialSecrets: []*v1.Secret{secret()},
|
||||
expectedCreateCalls: []createCall{
|
||||
{
|
||||
snapshotName: "snapshot-snapuid6-3",
|
||||
volume: newVolume("volume6-3", "pv-uid6-3", "pv-handle6-3", "1Gi", "pvc-uid6-3", "claim6-3", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
parameters: class5Parameters,
|
||||
secrets: map[string]string{"foo": "bar"},
|
||||
// information to return
|
||||
driverName: mockDriverName,
|
||||
size: defaultSize,
|
||||
snapshotId: "sid6-3",
|
||||
timestamp: timeNow,
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_READY,
|
||||
Details: "success",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "6-4 - successful create snapshot with snapshot class empty-secret-class",
|
||||
initialContents: nocontents,
|
||||
expectedContents: newContentArray("snapcontent-snapuid6-4", emptySecretClass, "sid6-4", "pv-uid6-4", "volume6-4", "snapuid6-4", "snap6-4", getSize(defaultSize), &timeNow),
|
||||
initialSnapshots: newSnapshotArray("snap6-4", emptySecretClass, "", "snapuid6-4", "claim6-4", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap6-4", emptySecretClass, "snapcontent-snapuid6-4", "snapuid6-4", "claim6-4", false, nil, metaTimeNowUnix, getSize(defaultSize)),
|
||||
initialClaims: newClaimArray("claim6-4", "pvc-uid6-4", "1Gi", "volume6-4", v1.ClaimBound, &classEmpty),
|
||||
initialVolumes: newVolumeArray("volume6-4", "pv-uid6-4", "pv-handle6-4", "1Gi", "pvc-uid6-4", "claim6-4", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
initialSecrets: []*v1.Secret{emptySecret()},
|
||||
expectedCreateCalls: []createCall{
|
||||
{
|
||||
snapshotName: "snapshot-snapuid6-4",
|
||||
volume: newVolume("volume6-4", "pv-uid6-4", "pv-handle6-4", "1Gi", "pvc-uid6-4", "claim6-4", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
parameters: class4Parameters,
|
||||
secrets: map[string]string{},
|
||||
// information to return
|
||||
driverName: mockDriverName,
|
||||
size: defaultSize,
|
||||
snapshotId: "sid6-4",
|
||||
timestamp: timeNow,
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_READY,
|
||||
Details: "success",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "6-5 - successful create snapshot with status uploading",
|
||||
initialContents: nocontents,
|
||||
expectedContents: newContentArray("snapcontent-snapuid6-5", classGold, "sid6-5", "pv-uid6-5", "volume6-5", "snapuid6-5", "snap6-5", getSize(defaultSize), &timeNow),
|
||||
initialSnapshots: newSnapshotArray("snap6-5", classGold, "", "snapuid6-5", "claim6-5", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap6-5", classGold, "snapcontent-snapuid6-5", "snapuid6-5", "claim6-5", false, nil, metaTimeNowUnix, getSize(defaultSize)),
|
||||
initialClaims: newClaimArray("claim6-5", "pvc-uid6-5", "1Gi", "volume6-5", v1.ClaimBound, &classEmpty),
|
||||
initialVolumes: newVolumeArray("volume6-5", "pv-uid6-5", "pv-handle6-5", "1Gi", "pvc-uid6-5", "claim6-5", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
expectedCreateCalls: []createCall{
|
||||
{
|
||||
snapshotName: "snapshot-snapuid6-5",
|
||||
volume: newVolume("volume6-5", "pv-uid6-5", "pv-handle6-5", "1Gi", "pvc-uid6-5", "claim6-5", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
parameters: map[string]string{"param1": "value1"},
|
||||
// information to return
|
||||
driverName: mockDriverName,
|
||||
size: defaultSize,
|
||||
snapshotId: "sid6-5",
|
||||
timestamp: timeNow,
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_READY,
|
||||
Details: "success",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "6-6 - successful create snapshot with status error uploading",
|
||||
initialContents: nocontents,
|
||||
expectedContents: newContentArray("snapcontent-snapuid6-6", classGold, "sid6-6", "pv-uid6-6", "volume6-6", "snapuid6-6", "snap6-6", getSize(defaultSize), &timeNow),
|
||||
initialSnapshots: newSnapshotArray("snap6-6", classGold, "", "snapuid6-6", "claim6-6", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap6-6", classGold, "snapcontent-snapuid6-6", "snapuid6-6", "claim6-6", false, nil, metaTimeNowUnix, getSize(defaultSize)),
|
||||
initialClaims: newClaimArray("claim6-6", "pvc-uid6-6", "1Gi", "volume6-6", v1.ClaimBound, &classEmpty),
|
||||
initialVolumes: newVolumeArray("volume6-6", "pv-uid6-6", "pv-handle6-6", "1Gi", "pvc-uid6-6", "claim6-6", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
expectedCreateCalls: []createCall{
|
||||
{
|
||||
snapshotName: "snapshot-snapuid6-6",
|
||||
volume: newVolume("volume6-6", "pv-uid6-6", "pv-handle6-6", "1Gi", "pvc-uid6-6", "claim6-6", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
parameters: map[string]string{"param1": "value1"},
|
||||
// information to return
|
||||
driverName: mockDriverName,
|
||||
size: defaultSize,
|
||||
snapshotId: "sid6-6",
|
||||
timestamp: timeNow,
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_READY,
|
||||
Details: "success",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "7-1 - fail create snapshot with snapshot class non-existing",
|
||||
initialContents: nocontents,
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap7-1", classNonExisting, "", "snapuid7-1", "claim7-1", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap7-1", classNonExisting, "", "snapuid7-1", "claim7-1", false, newVolumeError("Failed to create snapshot: failed to retrieve snapshot class non-existing from the API server: \"volumesnapshotclass.snapshot.storage.k8s.io \\\"non-existing\\\" not found\""), nil, nil),
|
||||
initialClaims: newClaimArray("claim7-1", "pvc-uid7-1", "1Gi", "volume7-1", v1.ClaimBound, &classEmpty),
|
||||
initialVolumes: newVolumeArray("volume7-1", "pv-uid7-1", "pv-handle7-1", "1Gi", "pvc-uid7-1", "claim7-1", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
expectedEvents: []string{"Warning SnapshotCreationFailed"},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "7-2 - fail create snapshot with snapshot class invalid-secret-class",
|
||||
initialContents: nocontents,
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap7-2", invalidSecretClass, "", "snapuid7-2", "claim7-2", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap7-2", invalidSecretClass, "", "snapuid7-2", "claim7-2", false, newVolumeError("Failed to create snapshot: csiSnapshotterSecretName and csiSnapshotterSecretNamespace parameters must be specified together"), nil, nil),
|
||||
initialClaims: newClaimArray("claim7-2", "pvc-uid7-2", "1Gi", "volume7-2", v1.ClaimBound, &classEmpty),
|
||||
initialVolumes: newVolumeArray("volume7-2", "pv-uid7-2", "pv-handle7-2", "1Gi", "pvc-uid7-2", "claim7-2", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
expectedEvents: []string{"Warning SnapshotCreationFailed"},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "7-3 - fail create snapshot with none snapshot class ",
|
||||
initialContents: nocontents,
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap7-3", "", "", "snapuid7-3", "claim7-3", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap7-3", "", "", "snapuid7-3", "claim7-3", false, newVolumeError("Failed to create snapshot: failed to retrieve snapshot class from the API server: \"volumesnapshotclass.snapshot.storage.k8s.io \\\"\\\" not found\""), nil, nil),
|
||||
initialClaims: newClaimArray("claim7-3", "pvc-uid7-3", "1Gi", "volume7-3", v1.ClaimBound, &classEmpty),
|
||||
initialVolumes: newVolumeArray("volume7-3", "pv-uid7-3", "pv-handle7-3", "1Gi", "pvc-uid7-3", "claim7-3", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
initialStorageClasses: []*storage.StorageClass{diffDriverStorageClass},
|
||||
expectedEvents: []string{"Warning SnapshotCreationFailed"},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "7-4 - fail create snapshot with no-existing claim",
|
||||
initialContents: nocontents,
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap7-4", classGold, "", "snapuid7-4", "claim7-4", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap7-4", classGold, "", "snapuid7-4", "claim7-4", false, newVolumeError("Failed to create snapshot: failed to retrieve PVC claim7-4 from the API server: \"Cannot find claim claim7-4\""), nil, nil),
|
||||
initialVolumes: newVolumeArray("volume7-4", "pv-uid7-4", "pv-handle7-4", "1Gi", "pvc-uid7-4", "claim7-4", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
expectedEvents: []string{"Warning SnapshotCreationFailed"},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "7-5 - fail create snapshot with no-existing volume",
|
||||
initialContents: nocontents,
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap7-5", classGold, "", "snapuid7-5", "claim7-5", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap7-5", classGold, "", "snapuid7-5", "claim7-5", false, newVolumeError("Failed to create snapshot: failed to retrieve PV volume7-5 from the API server: \"Cannot find volume volume7-5\""), nil, nil),
|
||||
initialClaims: newClaimArray("claim7-5", "pvc-uid7-5", "1Gi", "volume7-5", v1.ClaimBound, &classEmpty),
|
||||
expectedEvents: []string{"Warning SnapshotCreationFailed"},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "7-6 - fail create snapshot with claim that is not yet bound",
|
||||
initialContents: nocontents,
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap7-6", classGold, "", "snapuid7-6", "claim7-6", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap7-6", classGold, "", "snapuid7-6", "claim7-6", false, newVolumeError("Failed to create snapshot: the PVC claim7-6 is not yet bound to a PV, will not attempt to take a snapshot"), nil, nil),
|
||||
initialClaims: newClaimArray("claim7-6", "pvc-uid7-6", "1Gi", "", v1.ClaimPending, &classEmpty),
|
||||
expectedEvents: []string{"Warning SnapshotCreationFailed"},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "7-7 - fail create snapshot due to csi driver error",
|
||||
initialContents: nocontents,
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap7-7", classGold, "", "snapuid7-7", "claim7-7", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap7-7", classGold, "", "snapuid7-7", "claim7-7", false, newVolumeError("Failed to create snapshot: failed to take snapshot of the volume, volume7-7: \"mock create snapshot error\""), nil, nil),
|
||||
initialClaims: newClaimArray("claim7-7", "pvc-uid7-7", "1Gi", "volume7-7", v1.ClaimBound, &classEmpty),
|
||||
initialVolumes: newVolumeArray("volume7-7", "pv-uid7-7", "pv-handle7-7", "1Gi", "pvc-uid7-7", "claim7-7", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
expectedCreateCalls: []createCall{
|
||||
{
|
||||
snapshotName: "snapshot-snapuid7-7",
|
||||
volume: newVolume("volume7-7", "pv-uid7-7", "pv-handle7-7", "1Gi", "pvc-uid7-7", "claim7-7", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
parameters: map[string]string{"param1": "value1"},
|
||||
// information to return
|
||||
err: errors.New("mock create snapshot error"),
|
||||
},
|
||||
},
|
||||
errors: noerrors,
|
||||
expectedEvents: []string{"Warning SnapshotCreationFailed"},
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "7-8 - fail create snapshot due to cannot update snapshot status",
|
||||
initialContents: nocontents,
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap7-8", classGold, "", "snapuid7-8", "claim7-8", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap7-8", classGold, "", "snapuid7-8", "claim7-8", false, newVolumeError("Failed to create snapshot: snapshot controller failed to update default/snap7-8 on API server: mock update error"), nil, nil),
|
||||
initialClaims: newClaimArray("claim7-8", "pvc-uid7-8", "1Gi", "volume7-8", v1.ClaimBound, &classEmpty),
|
||||
initialVolumes: newVolumeArray("volume7-8", "pv-uid7-8", "pv-handle7-8", "1Gi", "pvc-uid7-8", "claim7-8", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
expectedCreateCalls: []createCall{
|
||||
{
|
||||
snapshotName: "snapshot-snapuid7-8",
|
||||
volume: newVolume("volume7-8", "pv-uid7-8", "pv-handle7-8", "1Gi", "pvc-uid7-8", "claim7-8", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
parameters: map[string]string{"param1": "value1"},
|
||||
// information to return
|
||||
driverName: mockDriverName,
|
||||
size: defaultSize,
|
||||
snapshotId: "sid7-8",
|
||||
timestamp: timeNow,
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_READY,
|
||||
Details: "success",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: []reactorError{
|
||||
// Inject error to the forth client.VolumesnapshotV1alpha1().VolumeSnapshots().Update call.
|
||||
// All other calls will succeed.
|
||||
{"update", "volumesnapshots", errors.New("mock update error")},
|
||||
{"update", "volumesnapshots", errors.New("mock update error")},
|
||||
{"update", "volumesnapshots", errors.New("mock update error")},
|
||||
},
|
||||
expectedEvents: []string{"Warning SnapshotCreationFailed"},
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "7-9 - fail create snapshot due to cannot save snapshot content",
|
||||
initialContents: nocontents,
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap7-9", classGold, "", "snapuid7-9", "claim7-9", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap7-9", classGold, "", "snapuid7-9", "claim7-9", false, nil, metaTimeNowUnix, getSize(defaultSize)),
|
||||
initialClaims: newClaimArray("claim7-9", "pvc-uid7-9", "1Gi", "volume7-9", v1.ClaimBound, &classEmpty),
|
||||
initialVolumes: newVolumeArray("volume7-9", "pv-uid7-9", "pv-handle7-9", "1Gi", "pvc-uid7-9", "claim7-9", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
expectedCreateCalls: []createCall{
|
||||
{
|
||||
snapshotName: "snapshot-snapuid7-9",
|
||||
volume: newVolume("volume7-9", "pv-uid7-9", "pv-handle7-9", "1Gi", "pvc-uid7-9", "claim7-9", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
|
||||
parameters: map[string]string{"param1": "value1"},
|
||||
// information to return
|
||||
driverName: mockDriverName,
|
||||
size: defaultSize,
|
||||
snapshotId: "sid7-9",
|
||||
timestamp: timeNow,
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_READY,
|
||||
Details: "success",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: []reactorError{
|
||||
{"create", "volumesnapshotcontents", errors.New("mock create error")},
|
||||
{"create", "volumesnapshotcontents", errors.New("mock create error")},
|
||||
{"create", "volumesnapshotcontents", errors.New("mock create error")},
|
||||
},
|
||||
expectedEvents: []string{"Warning CreateSnapshotContentFailed"},
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
}
|
||||
runSyncTests(t, tests, snapshotClasses)
|
||||
}
|
227
pkg/controller/snapshot_delete_test.go
Normal file
227
pkg/controller/snapshot_delete_test.go
Normal file
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controller
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
crdv1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1"
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
var class1Parameters = map[string]string{
|
||||
"param1": "value1",
|
||||
}
|
||||
|
||||
var class2Parameters = map[string]string{
|
||||
"param2": "value2",
|
||||
}
|
||||
|
||||
var class3Parameters = map[string]string{
|
||||
"param3": "value3",
|
||||
snapshotterSecretNameKey: "name",
|
||||
}
|
||||
|
||||
var class4Parameters = map[string]string{
|
||||
snapshotterSecretNameKey: "emptysecret",
|
||||
snapshotterSecretNamespaceKey: "default",
|
||||
}
|
||||
|
||||
var class5Parameters = map[string]string{
|
||||
snapshotterSecretNameKey: "secret",
|
||||
snapshotterSecretNamespaceKey: "default",
|
||||
}
|
||||
|
||||
var snapshotClasses = []*crdv1.VolumeSnapshotClass{
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "VolumeSnapshotClass",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: classGold,
|
||||
},
|
||||
Snapshotter: mockDriverName,
|
||||
Parameters: class1Parameters,
|
||||
},
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "VolumeSnapshotClass",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: classSilver,
|
||||
},
|
||||
Snapshotter: mockDriverName,
|
||||
Parameters: class2Parameters,
|
||||
},
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "VolumeSnapshotClass",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: emptySecretClass,
|
||||
},
|
||||
Snapshotter: mockDriverName,
|
||||
Parameters: class4Parameters,
|
||||
},
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "VolumeSnapshotClass",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: invalidSecretClass,
|
||||
},
|
||||
Snapshotter: mockDriverName,
|
||||
Parameters: class3Parameters,
|
||||
},
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "VolumeSnapshotClass",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: validSecretClass,
|
||||
},
|
||||
Snapshotter: mockDriverName,
|
||||
Parameters: class5Parameters,
|
||||
},
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "VolumeSnapshotClass",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: defaultClass,
|
||||
Annotations: map[string]string{IsDefaultSnapshotClassAnnotation: "true"},
|
||||
},
|
||||
Snapshotter: mockDriverName,
|
||||
},
|
||||
}
|
||||
|
||||
// Test single call to syncContent, expecting deleting to happen.
|
||||
// 1. Fill in the controller with initial data
|
||||
// 2. Call the syncContent *once*.
|
||||
// 3. Compare resulting contents with expected contents.
|
||||
func TestDeleteSync(t *testing.T) {
|
||||
tests := []controllerTest{
|
||||
{
|
||||
name: "1-1 - successful delete with empty snapshot class",
|
||||
initialContents: newContentArray("content1-1", classEmpty, "sid1-1", "vuid1-1", "volume1-1", "snapuid1-1", "snap1-1", nil, nil),
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: nosnapshots,
|
||||
expectedSnapshots: nosnapshots,
|
||||
expectedEvents: noevents,
|
||||
errors: noerrors,
|
||||
expectedDeleteCalls: []deleteCall{{"sid1-1", nil, nil}},
|
||||
test: testSyncContent,
|
||||
},
|
||||
{
|
||||
name: "1-2 - successful delete with snapshot class that has empty secret parameter",
|
||||
initialContents: newContentArray("content1-2", emptySecretClass, "sid1-2", "vuid1-2", "volume1-2", "snapuid1-2", "snap1-2", nil, nil),
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: nosnapshots,
|
||||
expectedSnapshots: nosnapshots,
|
||||
initialSecrets: []*v1.Secret{emptySecret()},
|
||||
expectedEvents: noevents,
|
||||
errors: noerrors,
|
||||
expectedDeleteCalls: []deleteCall{{"sid1-2", map[string]string{}, nil}},
|
||||
test: testSyncContent,
|
||||
},
|
||||
{
|
||||
name: "1-3 - successful delete with snapshot class that has valid secret parameter",
|
||||
initialContents: newContentArray("content1-3", validSecretClass, "sid1-3", "vuid1-3", "volume1-3", "snapuid1-3", "snap1-3", nil, nil),
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: nosnapshots,
|
||||
expectedSnapshots: nosnapshots,
|
||||
expectedEvents: noevents,
|
||||
errors: noerrors,
|
||||
initialSecrets: []*v1.Secret{secret()},
|
||||
expectedDeleteCalls: []deleteCall{{"sid1-3", map[string]string{"foo": "bar"}, nil}},
|
||||
test: testSyncContent,
|
||||
},
|
||||
{
|
||||
name: "1-4 - fail delete with snapshot class that has invalid secret parameter",
|
||||
initialContents: newContentArray("content1-4", invalidSecretClass, "sid1-4", "vuid1-4", "volume1-4", "snapuid1-4", "snap1-4", nil, nil),
|
||||
expectedContents: newContentArray("content1-4", invalidSecretClass, "sid1-4", "vuid1-4", "volume1-4", "snapuid1-4", "snap1-4", nil, nil),
|
||||
initialSnapshots: nosnapshots,
|
||||
expectedSnapshots: nosnapshots,
|
||||
expectedEvents: noevents,
|
||||
errors: noerrors,
|
||||
test: testSyncContent,
|
||||
},
|
||||
{
|
||||
name: "1-5 - csi driver delete snapshot returns error",
|
||||
initialContents: newContentArray("content1-5", validSecretClass, "sid1-5", "vuid1-5", "volume1-5", "snapuid1-5", "snap1-5", nil, nil),
|
||||
expectedContents: newContentArray("content1-5", validSecretClass, "sid1-5", "vuid1-5", "volume1-5", "snapuid1-5", "snap1-5", nil, nil),
|
||||
initialSnapshots: nosnapshots,
|
||||
expectedSnapshots: nosnapshots,
|
||||
initialSecrets: []*v1.Secret{secret()},
|
||||
expectedDeleteCalls: []deleteCall{{"sid1-5", map[string]string{"foo": "bar"}, errors.New("mock csi driver delete error")}},
|
||||
expectedEvents: []string{"Warning SnapshotDeleteError"},
|
||||
errors: noerrors,
|
||||
test: testSyncContent,
|
||||
},
|
||||
{
|
||||
name: "1-6 - api server delete content returns error",
|
||||
initialContents: newContentArray("content1-6", validSecretClass, "sid1-6", "vuid1-6", "volume1-6", "snapuid1-6", "snap1-6", nil, nil),
|
||||
expectedContents: newContentArray("content1-6", validSecretClass, "sid1-6", "vuid1-6", "volume1-6", "snapuid1-6", "snap1-6", nil, nil),
|
||||
initialSnapshots: nosnapshots,
|
||||
expectedSnapshots: nosnapshots,
|
||||
initialSecrets: []*v1.Secret{secret()},
|
||||
expectedDeleteCalls: []deleteCall{{"sid1-6", map[string]string{"foo": "bar"}, nil}},
|
||||
expectedEvents: []string{"Warning SnapshotContentObjectDeleteError"},
|
||||
errors: []reactorError{
|
||||
// Inject error to the first client.VolumesnapshotV1alpha1().VolumeSnapshotContents().Delete call.
|
||||
// All other calls will succeed.
|
||||
{"delete", "volumesnapshotcontents", errors.New("mock delete error")},
|
||||
},
|
||||
test: testSyncContent,
|
||||
},
|
||||
{
|
||||
// delete success - snapshot that the content was pointing to was deleted, and another
|
||||
// with the same name created.
|
||||
name: "1-7 - prebound content is deleted while the snapshot exists",
|
||||
initialContents: newContentArray("content1-7", validSecretClass, "sid1-7", "vuid1-7", "volume1-7", "snapuid1-7", "snap1-7", nil, nil),
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap1-7", validSecretClass, "content1-7", "snapuid1-7-x", "claim1-7", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap1-7", validSecretClass, "content1-7", "snapuid1-7-x", "claim1-7", false, nil, nil, nil),
|
||||
initialSecrets: []*v1.Secret{secret()},
|
||||
expectedDeleteCalls: []deleteCall{{"sid1-7", map[string]string{"foo": "bar"}, nil}},
|
||||
expectedEvents: noevents,
|
||||
errors: noerrors,
|
||||
test: testSyncContent,
|
||||
},
|
||||
{
|
||||
// delete success(?) - content is deleted before doDelete() starts
|
||||
name: "1-8 - content is deleted before deleting",
|
||||
initialContents: newContentArray("content1-8", validSecretClass, "sid1-8", "vuid1-8", "volume1-8", "snapuid1-8", "snap1-8", nil, nil),
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: nosnapshots,
|
||||
expectedSnapshots: nosnapshots,
|
||||
initialSecrets: []*v1.Secret{secret()},
|
||||
expectedDeleteCalls: []deleteCall{{"sid1-8", map[string]string{"foo": "bar"}, nil}},
|
||||
expectedEvents: noevents,
|
||||
errors: noerrors,
|
||||
test: wrapTestWithInjectedOperation(testSyncContent, func(ctrl *csiSnapshotController, reactor *snapshotReactor) {
|
||||
// Delete the volume before delete operation starts
|
||||
reactor.lock.Lock()
|
||||
delete(reactor.contents, "content1-8")
|
||||
reactor.lock.Unlock()
|
||||
}),
|
||||
},
|
||||
}
|
||||
runSyncTests(t, tests, snapshotClasses)
|
||||
}
|
238
pkg/controller/snapshot_ready_test.go
Normal file
238
pkg/controller/snapshot_ready_test.go
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controller
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi/v0"
|
||||
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
var metaTimeNow = &metav1.Time{
|
||||
Time: time.Now(),
|
||||
}
|
||||
|
||||
var volumeErr = &storagev1beta1.VolumeError{
|
||||
Time: *metaTimeNow,
|
||||
Message: "Failed to upload the snapshot",
|
||||
}
|
||||
|
||||
// Test single call to syncSnapshot and syncContent methods.
|
||||
// 1. Fill in the controller with initial data
|
||||
// 2. Call the tested function (syncSnapshot/syncContent) via
|
||||
// controllerTest.testCall *once*.
|
||||
// 3. Compare resulting contents and snapshots with expected contents and snapshots.
|
||||
func TestSync(t *testing.T) {
|
||||
tests := []controllerTest{
|
||||
{
|
||||
// snapshot is bound to a non-existing content
|
||||
name: "2-1 - snapshot is bound to a non-existing content",
|
||||
initialContents: nocontents,
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap2-1", validSecretClass, "content2-1", "snapuid2-1", "claim2-1", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap2-1", validSecretClass, "content2-1", "snapuid2-1", "claim2-1", false, newVolumeError("VolumeSnapshotContent is missing"), nil, nil),
|
||||
expectedEvents: []string{"Warning SnapshotContentMissing"},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshotError,
|
||||
},
|
||||
{
|
||||
name: "2-2 - could not bind snapshot and content, the VolumeSnapshotRef does not match",
|
||||
initialContents: newContentArray("content2-2", validSecretClass, "sid2-2", "vuid2-2", "volume2-2", "snapuid2-2-x", "snap2-2", nil, nil),
|
||||
expectedContents: newContentArray("content2-2", validSecretClass, "sid2-2", "vuid2-2", "volume2-2", "snapuid2-2-x", "snap2-2", nil, nil),
|
||||
initialSnapshots: newSnapshotArray("snap2-2", validSecretClass, "content2-2", "snapuid2-2", "claim2-2", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap2-2", validSecretClass, "content2-2", "snapuid2-2", "claim2-2", false, newVolumeError("Snapshot failed to bind VolumeSnapshotContent, Could not bind snapshot snap2-2 and content content2-2, the VolumeSnapshotRef does not match"), nil, nil),
|
||||
expectedEvents: []string{"Warning SnapshotBindFailed"},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshotError,
|
||||
},
|
||||
{
|
||||
name: "2-3 - success bind snapshot and content, no status changed",
|
||||
initialContents: newContentArray("content2-3", validSecretClass, "sid2-3", "vuid2-3", "volume2-3", "", "snap2-3", nil, nil),
|
||||
expectedContents: newContentArray("content2-3", validSecretClass, "sid2-3", "vuid2-3", "volume2-3", "snapuid2-3", "snap2-3", nil, nil),
|
||||
initialSnapshots: newSnapshotArray("snap2-3", validSecretClass, "content2-3", "snapuid2-3", "claim2-3", false, nil, metaTimeNow, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap2-3", validSecretClass, "content2-3", "snapuid2-3", "claim2-3", false, nil, metaTimeNow, nil),
|
||||
expectedListCalls: []listCall{
|
||||
{
|
||||
snapshotID: "sid2-3",
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_UPLOADING,
|
||||
Details: "uploading",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
// nothing changed
|
||||
name: "2-4 - noop",
|
||||
initialContents: newContentArray("content2-4", validSecretClass, "sid2-4", "vuid2-4", "volume2-4", "snapuid2-4", "snap2-4", nil, nil),
|
||||
expectedContents: newContentArray("content2-4", validSecretClass, "sid2-4", "vuid2-4", "volume2-4", "snapuid2-4", "snap2-4", nil, nil),
|
||||
initialSnapshots: newSnapshotArray("snap2-4", validSecretClass, "content2-4", "snapuid2-4", "claim2-4", false, nil, metaTimeNow, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap2-4", validSecretClass, "content2-4", "snapuid2-4", "claim2-4", false, nil, metaTimeNow, nil),
|
||||
expectedListCalls: []listCall{
|
||||
{
|
||||
snapshotID: "sid2-4",
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_UPLOADING,
|
||||
Details: "uploading",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "2-5 - snapshot and content bound, status ready false -> true",
|
||||
initialContents: newContentArray("content2-5", validSecretClass, "sid2-5", "vuid2-5", "volume2-5", "snapuid2-5", "snap2-5", nil, nil),
|
||||
expectedContents: newContentArray("content2-5", validSecretClass, "sid2-5", "vuid2-5", "volume2-5", "snapuid2-5", "snap2-5", nil, nil),
|
||||
initialSnapshots: newSnapshotArray("snap2-5", validSecretClass, "content2-5", "snapuid2-5", "claim2-5", false, nil, metaTimeNow, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap2-5", validSecretClass, "content2-5", "snapuid2-5", "claim2-5", true, nil, metaTimeNow, nil),
|
||||
expectedListCalls: []listCall{
|
||||
{
|
||||
snapshotID: "sid2-5",
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_READY,
|
||||
Details: "success",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "2-6 - snapshot and content bound, status -> error uploading",
|
||||
initialContents: newContentArray("content2-6", validSecretClass, "sid2-6", "vuid2-6", "volume2-6", "snapuid2-6", "snap2-6", nil, nil),
|
||||
expectedContents: newContentArray("content2-6", validSecretClass, "sid2-6", "vuid2-6", "volume2-6", "snapuid2-6", "snap2-6", nil, nil),
|
||||
initialSnapshots: newSnapshotArray("snap2-6", validSecretClass, "content2-6", "snapuid2-6", "claim2-6", false, nil, metaTimeNow, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap2-6", validSecretClass, "content2-6", "snapuid2-6", "claim2-6", false, volumeErr, metaTimeNow, nil),
|
||||
expectedEvents: []string{"Warning SnapshotUploadError"},
|
||||
expectedListCalls: []listCall{
|
||||
{
|
||||
snapshotID: "sid2-6",
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_ERROR_UPLOADING,
|
||||
Details: "error upload",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "2-7 - snapshot and content bound, csi driver get status error",
|
||||
initialContents: newContentArray("content2-7", validSecretClass, "sid2-7", "vuid2-7", "volume2-7", "snapuid2-7", "snap2-7", nil, nil),
|
||||
expectedContents: newContentArray("content2-7", validSecretClass, "sid2-7", "vuid2-7", "volume2-7", "snapuid2-7", "snap2-7", nil, nil),
|
||||
initialSnapshots: newSnapshotArray("snap2-7", validSecretClass, "content2-7", "snapuid2-7", "claim2-7", false, nil, metaTimeNow, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap2-7", validSecretClass, "content2-7", "snapuid2-7", "claim2-7", false, newVolumeError("Failed to check and update snapshot: failed to check snapshot status snap2-7 with error failed to list snapshot data content2-7: \"mock driver get status error\""), metaTimeNow, nil),
|
||||
expectedEvents: []string{"Warning SnapshotCheckandUpdateFailed"},
|
||||
expectedListCalls: []listCall{
|
||||
{
|
||||
snapshotID: "sid2-7",
|
||||
err: errors.New("mock driver get status error"),
|
||||
},
|
||||
},
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "2-8 - snapshot and content bound, apiserver update status error",
|
||||
initialContents: newContentArray("content2-8", validSecretClass, "sid2-8", "vuid2-8", "volume2-8", "snapuid2-8", "snap2-8", nil, nil),
|
||||
expectedContents: newContentArray("content2-8", validSecretClass, "sid2-8", "vuid2-8", "volume2-8", "snapuid2-8", "snap2-8", nil, nil),
|
||||
initialSnapshots: newSnapshotArray("snap2-8", validSecretClass, "content2-8", "snapuid2-8", "claim2-8", false, nil, metaTimeNow, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap2-8", validSecretClass, "content2-8", "snapuid2-8", "claim2-8", false, newVolumeError("Failed to check and update snapshot: snapshot controller failed to update default/snap2-8 on API server: mock update error"), metaTimeNow, nil),
|
||||
expectedEvents: []string{"Warning SnapshotUploadError"},
|
||||
expectedListCalls: []listCall{
|
||||
{
|
||||
snapshotID: "sid2-8",
|
||||
status: &csi.SnapshotStatus{
|
||||
Type: csi.SnapshotStatus_ERROR_UPLOADING,
|
||||
Details: "error upload",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: []reactorError{
|
||||
// Inject error to the first client.VolumesnapshotV1alpha1().VolumeSnapshots().Update call.
|
||||
// All other calls will succeed.
|
||||
{"update", "volumesnapshots", errors.New("mock update error")},
|
||||
},
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "2-9 - bind when snapshot and content matches",
|
||||
initialContents: newContentArray("content2-9", validSecretClass, "sid2-9", "vuid2-9", "volume2-9", "snapuid2-9", "snap2-9", nil, nil),
|
||||
expectedContents: newContentArray("content2-9", validSecretClass, "sid2-9", "vuid2-9", "volume2-9", "snapuid2-9", "snap2-9", nil, nil),
|
||||
initialSnapshots: newSnapshotArray("snap2-9", validSecretClass, "", "snapuid2-9", "claim2-9", false, nil, nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap2-9", validSecretClass, "content2-9", "snapuid2-9", "claim2-9", false, nil, nil, nil),
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "2-10 - do not bind when snapshot and content not match",
|
||||
initialContents: newContentArray("content2-10", validSecretClass, "sid2-10", "vuid2-10", "volume2-10", "snapuid2-10-x", "snap2-10", nil, nil),
|
||||
expectedContents: newContentArray("content2-10", validSecretClass, "sid2-10", "vuid2-10", "volume2-10", "snapuid2-10-x", "snap2-10", nil, nil),
|
||||
initialSnapshots: newSnapshotArray("snap2-10", validSecretClass, "", "snapuid2-10", "claim2-10", false, newVolumeError("mock driver error"), nil, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap2-10", validSecretClass, "", "snapuid2-10", "claim2-10", false, newVolumeError("mock driver error"), nil, nil),
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "3-1 - ready snapshot lost reference to VolumeSnapshotContent",
|
||||
initialContents: nocontents,
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap3-1", validSecretClass, "", "snapuid3-1", "claim3-1", true, nil, metaTimeNow, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap3-1", validSecretClass, "", "snapuid3-1", "claim3-1", false, newVolumeError("Bound snapshot has lost reference to VolumeSnapshotContent"), metaTimeNow, nil),
|
||||
errors: noerrors,
|
||||
expectedEvents: []string{"Warning SnapshotLost"},
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "3-2 - ready snapshot bound to none-exist content",
|
||||
initialContents: nocontents,
|
||||
expectedContents: nocontents,
|
||||
initialSnapshots: newSnapshotArray("snap3-2", validSecretClass, "content3-2", "snapuid3-2", "claim3-2", true, nil, metaTimeNow, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap3-2", validSecretClass, "content3-2", "snapuid3-2", "claim3-2", false, newVolumeError("VolumeSnapshotContent is missing"), metaTimeNow, nil),
|
||||
errors: noerrors,
|
||||
expectedEvents: []string{"Warning SnapshotContentMissing"},
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "3-3 - ready snapshot(everything is well, do nothing)",
|
||||
initialContents: newContentArray("content3-3", validSecretClass, "sid3-3", "vuid3-3", "volume3-3", "snapuid3-3", "snap3-3", nil, nil),
|
||||
expectedContents: newContentArray("content3-3", validSecretClass, "sid3-3", "vuid3-3", "volume3-3", "snapuid3-3", "snap3-3", nil, nil),
|
||||
initialSnapshots: newSnapshotArray("snap3-3", validSecretClass, "content3-3", "snapuid3-3", "claim3-3", true, nil, metaTimeNow, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap3-3", validSecretClass, "content3-3", "snapuid3-3", "claim3-3", true, nil, metaTimeNow, nil),
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
{
|
||||
name: "3-4 - ready snapshot misbound to VolumeSnapshotContent",
|
||||
initialContents: newContentArray("content3-4", validSecretClass, "sid3-4", "vuid3-4", "volume3-4", "snapuid3-4-x", "snap3-4", nil, nil),
|
||||
expectedContents: newContentArray("content3-4", validSecretClass, "sid3-4", "vuid3-4", "volume3-4", "snapuid3-4-x", "snap3-4", nil, nil),
|
||||
initialSnapshots: newSnapshotArray("snap3-4", validSecretClass, "content3-4", "snapuid3-4", "claim3-4", true, nil, metaTimeNow, nil),
|
||||
expectedSnapshots: newSnapshotArray("snap3-4", validSecretClass, "content3-4", "snapuid3-4", "claim3-4", false, newVolumeError("VolumeSnapshotContent is not bound to the VolumeSnapshot correctly"), metaTimeNow, nil),
|
||||
errors: noerrors,
|
||||
test: testSyncSnapshot,
|
||||
},
|
||||
}
|
||||
|
||||
runSyncTests(t, tests, snapshotClasses)
|
||||
}
|
Reference in New Issue
Block a user