diff --git a/Makefile b/Makefile index b39f45245..8af9d93a2 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ REGISTRY_NAME=quay.io/k8scsi IMAGE_NAME=csi-snapshotter -IMAGE_VERSION=v0.4.1 +IMAGE_VERSION=v0.4-canary IMAGE_TAG=$(REGISTRY_NAME)/$(IMAGE_NAME):$(IMAGE_VERSION) REV=$(shell git describe --long --tags --match='v*' --dirty) diff --git a/pkg/controller/framework_test.go b/pkg/controller/framework_test.go index e789a2f8e..af8d61365 100644 --- a/pkg/controller/framework_test.go +++ b/pkg/controller/framework_test.go @@ -875,7 +875,15 @@ func newClaimArray(name, claimUID, capacity, boundToVolume string, phase v1.Pers } // newVolume returns a new volume with given attributes -func newVolume(name, volumeUID, volumeHandle, capacity, boundToClaimUID, boundToClaimName string, phase v1.PersistentVolumePhase, reclaimPolicy v1.PersistentVolumeReclaimPolicy, class string, annotations ...string) *v1.PersistentVolume { +func newVolume(name, volumeUID, volumeHandle, capacity, boundToClaimUID, boundToClaimName string, phase v1.PersistentVolumePhase, reclaimPolicy v1.PersistentVolumeReclaimPolicy, class string, driver string, namespace string, annotations ...string) *v1.PersistentVolume { + inDriverName := mockDriverName + if driver != "" { + inDriverName = driver + } + inNamespace := testNamespace + if namespace != "" { + inNamespace = namespace + } volume := v1.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -889,7 +897,7 @@ func newVolume(name, volumeUID, volumeHandle, capacity, boundToClaimUID, boundTo }, PersistentVolumeSource: v1.PersistentVolumeSource{ CSI: &v1.CSIPersistentVolumeSource{ - Driver: mockDriverName, + Driver: inDriverName, VolumeHandle: volumeHandle, }, }, @@ -907,7 +915,7 @@ func newVolume(name, volumeUID, volumeHandle, capacity, boundToClaimUID, boundTo Kind: "PersistentVolumeClaim", APIVersion: "v1", UID: types.UID(boundToClaimUID), - Namespace: testNamespace, + Namespace: inNamespace, Name: boundToClaimName, } } @@ -917,9 +925,9 @@ func newVolume(name, volumeUID, volumeHandle, capacity, boundToClaimUID, boundTo // newVolumeArray returns array with a single volume that would be returned by // newVolume() with the same parameters. -func newVolumeArray(name, volumeUID, volumeHandle, capacity, boundToClaimUID, boundToClaimName string, phase v1.PersistentVolumePhase, reclaimPolicy v1.PersistentVolumeReclaimPolicy, class string) []*v1.PersistentVolume { +func newVolumeArray(name, volumeUID, volumeHandle, capacity, boundToClaimUID, boundToClaimName string, phase v1.PersistentVolumePhase, reclaimPolicy v1.PersistentVolumeReclaimPolicy, class string, driver string, namespace string) []*v1.PersistentVolume { return []*v1.PersistentVolume{ - newVolume(name, volumeUID, volumeHandle, capacity, boundToClaimUID, boundToClaimName, phase, reclaimPolicy, class), + newVolume(name, volumeUID, volumeHandle, capacity, boundToClaimUID, boundToClaimName, phase, reclaimPolicy, class, driver, namespace), } } diff --git a/pkg/controller/snapshot_controller.go b/pkg/controller/snapshot_controller.go index ef4fe3588..2e78f9404 100644 --- a/pkg/controller/snapshot_controller.go +++ b/pkg/controller/snapshot_controller.go @@ -735,11 +735,40 @@ func (ctrl *csiSnapshotController) getVolumeFromVolumeSnapshot(snapshot *crdv1.V return nil, fmt.Errorf("failed to retrieve PV %s from the API server: %q", pvName, err) } + // Verify binding between PV/PVC is still valid + bound := ctrl.IsVolumeBoundToClaim(pv, pvc) + if bound == false { + glog.Warningf("binding between PV %s and PVC %s is broken", pvName, pvc.Name) + return nil, fmt.Errorf("claim in dataSource not bound or invalid") + } + + // Verify driver for PVC is the same as driver for VolumeSnapshot + if pv.Spec.PersistentVolumeSource.CSI == nil || pv.Spec.PersistentVolumeSource.CSI.Driver != ctrl.snapshotterName { + glog.Warningf("driver for PV %s is different from driver %s for snapshot %s", pvName, ctrl.snapshotterName, snapshot.Name) + return nil, fmt.Errorf("claim in dataSource not bound or invalid") + } + glog.V(5).Infof("getVolumeFromVolumeSnapshot: snapshot [%s] PV name [%s]", snapshot.Name, pvName) return pv, nil } +// IsVolumeBoundToClaim returns true, if given volume is pre-bound or bound +// to specific claim. Both claim.Name and claim.Namespace must be equal. +// If claim.UID is present in volume.Spec.ClaimRef, it must be equal too. +func (ctrl *csiSnapshotController) IsVolumeBoundToClaim(volume *v1.PersistentVolume, claim *v1.PersistentVolumeClaim) bool { + if volume.Spec.ClaimRef == nil { + return false + } + if claim.Name != volume.Spec.ClaimRef.Name || claim.Namespace != volume.Spec.ClaimRef.Namespace { + return false + } + if volume.Spec.ClaimRef.UID != "" && claim.UID != volume.Spec.ClaimRef.UID { + return false + } + return true +} + func (ctrl *csiSnapshotController) getStorageClassFromVolumeSnapshot(snapshot *crdv1.VolumeSnapshot) (*storagev1.StorageClass, error) { // Get storage class from PVC or PV pvc, err := ctrl.getClaimFromVolumeSnapshot(snapshot) diff --git a/pkg/controller/snapshot_create_test.go b/pkg/controller/snapshot_create_test.go index d900015a3..b8052a3c8 100644 --- a/pkg/controller/snapshot_create_test.go +++ b/pkg/controller/snapshot_create_test.go @@ -70,11 +70,11 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume6-1", "pv-uid6-1", "pv-handle6-1", "1Gi", "pvc-uid6-1", "claim6-1", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), 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), + volume: newVolume("volume6-1", "pv-uid6-1", "pv-handle6-1", "1Gi", "pvc-uid6-1", "claim6-1", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), parameters: map[string]string{"param1": "value1"}, // information to return driverName: mockDriverName, @@ -97,11 +97,11 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume6-2", "pv-uid6-2", "pv-handle6-2", "1Gi", "pvc-uid6-2", "claim6-2", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), 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), + volume: newVolume("volume6-2", "pv-uid6-2", "pv-handle6-2", "1Gi", "pvc-uid6-2", "claim6-2", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), parameters: map[string]string{"param2": "value2"}, // information to return driverName: mockDriverName, @@ -124,12 +124,12 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume6-3", "pv-uid6-3", "pv-handle6-3", "1Gi", "pvc-uid6-3", "claim6-3", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), 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), + volume: newVolume("volume6-3", "pv-uid6-3", "pv-handle6-3", "1Gi", "pvc-uid6-3", "claim6-3", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), parameters: class5Parameters, secrets: map[string]string{"foo": "bar"}, // information to return @@ -153,12 +153,12 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume6-4", "pv-uid6-4", "pv-handle6-4", "1Gi", "pvc-uid6-4", "claim6-4", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), 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), + volume: newVolume("volume6-4", "pv-uid6-4", "pv-handle6-4", "1Gi", "pvc-uid6-4", "claim6-4", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), parameters: class4Parameters, secrets: map[string]string{}, // information to return @@ -182,11 +182,11 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume6-5", "pv-uid6-5", "pv-handle6-5", "1Gi", "pvc-uid6-5", "claim6-5", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), 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), + volume: newVolume("volume6-5", "pv-uid6-5", "pv-handle6-5", "1Gi", "pvc-uid6-5", "claim6-5", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), parameters: map[string]string{"param1": "value1"}, // information to return driverName: mockDriverName, @@ -209,11 +209,11 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume6-6", "pv-uid6-6", "pv-handle6-6", "1Gi", "pvc-uid6-6", "claim6-6", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), 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), + volume: newVolume("volume6-6", "pv-uid6-6", "pv-handle6-6", "1Gi", "pvc-uid6-6", "claim6-6", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), parameters: map[string]string{"param1": "value1"}, // information to return driverName: mockDriverName, @@ -236,7 +236,7 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume7-1", "pv-uid7-1", "pv-handle7-1", "1Gi", "pvc-uid7-1", "claim7-1", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), expectedEvents: []string{"Warning SnapshotCreationFailed"}, errors: noerrors, test: testSyncSnapshot, @@ -248,7 +248,7 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume7-2", "pv-uid7-2", "pv-handle7-2", "1Gi", "pvc-uid7-2", "claim7-2", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), expectedEvents: []string{"Warning SnapshotCreationFailed"}, errors: noerrors, test: testSyncSnapshot, @@ -260,7 +260,7 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume7-3", "pv-uid7-3", "pv-handle7-3", "1Gi", "pvc-uid7-3", "claim7-3", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), initialStorageClasses: []*storage.StorageClass{diffDriverStorageClass}, expectedEvents: []string{"Warning SnapshotCreationFailed"}, errors: noerrors, @@ -272,7 +272,7 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume7-4", "pv-uid7-4", "pv-handle7-4", "1Gi", "pvc-uid7-4", "claim7-4", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), expectedEvents: []string{"Warning SnapshotCreationFailed"}, errors: noerrors, test: testSyncSnapshot, @@ -306,11 +306,11 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume7-7", "pv-uid7-7", "pv-handle7-7", "1Gi", "pvc-uid7-7", "claim7-7", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), 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), + volume: newVolume("volume7-7", "pv-uid7-7", "pv-handle7-7", "1Gi", "pvc-uid7-7", "claim7-7", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), parameters: map[string]string{"param1": "value1"}, // information to return err: errors.New("mock create snapshot error"), @@ -327,11 +327,11 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume7-8", "pv-uid7-8", "pv-handle7-8", "1Gi", "pvc-uid7-8", "claim7-8", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), 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), + volume: newVolume("volume7-8", "pv-uid7-8", "pv-handle7-8", "1Gi", "pvc-uid7-8", "claim7-8", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), parameters: map[string]string{"param1": "value1"}, // information to return driverName: mockDriverName, @@ -361,11 +361,11 @@ func TestCreateSnapshotSync(t *testing.T) { 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), + initialVolumes: newVolumeArray("volume7-9", "pv-uid7-9", "pv-handle7-9", "1Gi", "pvc-uid7-9", "claim7-9", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), 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), + volume: newVolume("volume7-9", "pv-uid7-9", "pv-handle7-9", "1Gi", "pvc-uid7-9", "claim7-9", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), parameters: map[string]string{"param1": "value1"}, // information to return driverName: mockDriverName, @@ -386,6 +386,78 @@ func TestCreateSnapshotSync(t *testing.T) { expectedEvents: []string{"Warning CreateSnapshotContentFailed"}, test: testSyncSnapshot, }, + { + name: "7-10 - fail create snapshot with secret not found", + initialContents: nocontents, + expectedContents: nocontents, + initialSnapshots: newSnapshotArray("snap7-10", validSecretClass, "", "snapuid7-10", "claim7-10", false, nil, nil, nil), + expectedSnapshots: newSnapshotArray("snap7-10", validSecretClass, "", "snapuid7-10", "claim7-10", false, newVolumeError("Failed to create snapshot: error getting secret secret in namespace default: cannot find secret secret"), nil, nil), + initialClaims: newClaimArray("claim7-10", "pvc-uid7-10", "1Gi", "volume7-10", v1.ClaimBound, &classEmpty), + initialVolumes: newVolumeArray("volume7-10", "pv-uid7-10", "pv-handle7-10", "1Gi", "pvc-uid7-10", "claim7-10", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), + initialSecrets: []*v1.Secret{}, // no initial secret created + errors: noerrors, + test: testSyncSnapshot, + }, + { + name: "8-1 - fail create snapshot with PVC using unbound PV", + initialContents: nocontents, + expectedContents: nocontents, + initialSnapshots: newSnapshotArray("snap8-1", classGold, "", "snapuid8-1", "claim8-1", false, nil, nil, nil), + expectedSnapshots: newSnapshotArray("snap8-1", classGold, "", "snapuid8-1", "claim8-1", false, newVolumeError("Failed to create snapshot: claim in dataSource not bound or invalid"), nil, nil), + initialClaims: newClaimArray("claim8-1", "pvc-uid8-1", "1Gi", "volume8-1", v1.ClaimBound, &classEmpty), + initialVolumes: newVolumeArray("volume8-1", "pv-uid8-1", "pv-handle8-1", "1Gi", "pvc-uid8-1", "", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), + errors: noerrors, + expectedEvents: []string{"Warning SnapshotCreationFailed"}, + test: testSyncSnapshot, + }, + { + name: "8-2 - fail create snapshot with PVC using PV bound to another PVC (with wrong UID)", + initialContents: nocontents, + expectedContents: nocontents, + initialSnapshots: newSnapshotArray("snap8-2", classGold, "", "snapuid8-2", "claim8-2", false, nil, nil, nil), + expectedSnapshots: newSnapshotArray("snap8-2", classGold, "", "snapuid8-2", "claim8-2", false, newVolumeError("Failed to create snapshot: claim in dataSource not bound or invalid"), nil, nil), + initialClaims: newClaimArray("claim8-2", "pvc-uid8-2", "1Gi", "volume8-2", v1.ClaimBound, &classEmpty), + initialVolumes: newVolumeArray("volume8-2", "pv-uid8-2", "pv-handle8-2", "1Gi", "pvc-uid8-2-wrong-UID", "claim8-2", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), + errors: noerrors, + expectedEvents: []string{"Warning SnapshotCreationFailed"}, + test: testSyncSnapshot, + }, + { + name: "8-3 - fail create snapshot with PVC using PV bound to another PVC (with wrong namespace)", + initialContents: nocontents, + expectedContents: nocontents, + initialSnapshots: newSnapshotArray("snap8-3", classGold, "", "snapuid8-3", "claim8-3", false, nil, nil, nil), + expectedSnapshots: newSnapshotArray("snap8-3", classGold, "", "snapuid8-3", "claim8-3", false, newVolumeError("Failed to create snapshot: claim in dataSource not bound or invalid"), nil, nil), + initialClaims: newClaimArray("claim8-3", "pvc-uid8-3", "1Gi", "volume8-3", v1.ClaimBound, &classEmpty), + initialVolumes: newVolumeArray("volume8-3", "pv-uid8-3", "pv-handle8-3", "1Gi", "pvc-uid8-3", "claim8-3", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, "wrong-namespace"), + errors: noerrors, + expectedEvents: []string{"Warning SnapshotCreationFailed"}, + test: testSyncSnapshot, + }, + { + name: "8-4 - fail create snapshot with PVC using PV bound to another PVC (with wrong name)", + initialContents: nocontents, + expectedContents: nocontents, + initialSnapshots: newSnapshotArray("snap8-4", classGold, "", "snapuid8-4", "claim8-4", false, nil, nil, nil), + expectedSnapshots: newSnapshotArray("snap8-4", classGold, "", "snapuid8-4", "claim8-4", false, newVolumeError("Failed to create snapshot: claim in dataSource not bound or invalid"), nil, nil), + initialClaims: newClaimArray("claim8-4", "pvc-uid8-4", "1Gi", "volume8-4", v1.ClaimBound, &classEmpty), + initialVolumes: newVolumeArray("volume8-4", "pv-uid8-4", "pv-handle8-4", "1Gi", "pvc-uid8-4", "claim8-4-wrong-name", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), + errors: noerrors, + expectedEvents: []string{"Warning SnapshotCreationFailed"}, + test: testSyncSnapshot, + }, + { + name: "8-5 - fail create snapshot with PVC bound to PV with wrong provisioner", + initialContents: nocontents, + expectedContents: nocontents, + initialSnapshots: newSnapshotArray("snap8-5", classGold, "", "snapuid8-5", "claim8-5", false, nil, nil, nil), + expectedSnapshots: newSnapshotArray("snap8-5", classGold, "", "snapuid8-5", "claim8-5", false, newVolumeError("Failed to create snapshot: claim in dataSource not bound or invalid"), nil, nil), + initialClaims: newClaimArray("claim8-5", "pvc-uid8-5", "1Gi", "volume8-5", v1.ClaimBound, &classEmpty), + initialVolumes: newVolumeArray("volume8-5", "pv-uid8-5", "pv-handle8-5", "1Gi", "pvc-uid8-5", "claim8-5", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, "wrong-driver", testNamespace), + errors: noerrors, + expectedEvents: []string{"Warning SnapshotCreationFailed"}, + test: testSyncSnapshot, + }, } runSyncTests(t, tests, snapshotClasses) } diff --git a/pkg/controller/snapshot_ready_test.go b/pkg/controller/snapshot_ready_test.go index 93aeaa960..b7dd9bc7a 100644 --- a/pkg/controller/snapshot_ready_test.go +++ b/pkg/controller/snapshot_ready_test.go @@ -22,6 +22,7 @@ import ( "time" "github.com/container-storage-interface/spec/lib/go/csi/v0" + "k8s.io/api/core/v1" storagev1beta1 "k8s.io/api/storage/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -78,8 +79,11 @@ func TestSync(t *testing.T) { }, }, }, - errors: noerrors, - test: testSyncSnapshot, + initialClaims: newClaimArray("claim2-3", "pvc-uid2-3", "1Gi", "volume2-3", v1.ClaimBound, &classEmpty), + initialVolumes: newVolumeArray("volume2-3", "pv-uid2-3", "pv-handle2-3", "1Gi", "pvc-uid2-3", "claim2-3", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), + initialSecrets: []*v1.Secret{secret()}, + errors: noerrors, + test: testSyncSnapshot, }, { // nothing changed @@ -115,8 +119,11 @@ func TestSync(t *testing.T) { }, }, }, - errors: noerrors, - test: testSyncSnapshot, + initialClaims: newClaimArray("claim2-5", "pvc-uid2-5", "1Gi", "volume2-5", v1.ClaimBound, &classEmpty), + initialVolumes: newVolumeArray("volume2-5", "pv-uid2-5", "pv-handle2-5", "1Gi", "pvc-uid2-5", "claim2-5", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), + initialSecrets: []*v1.Secret{secret()}, + errors: noerrors, + test: testSyncSnapshot, }, { name: "2-6 - snapshot and content bound, status -> error uploading", @@ -150,8 +157,11 @@ func TestSync(t *testing.T) { err: errors.New("mock driver get status error"), }, }, - errors: noerrors, - test: testSyncSnapshot, + initialClaims: newClaimArray("claim2-7", "pvc-uid2-7", "1Gi", "volume2-7", v1.ClaimBound, &classEmpty), + initialVolumes: newVolumeArray("volume2-7", "pv-uid2-7", "pv-handle2-7", "1Gi", "pvc-uid2-7", "claim2-7", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), + initialSecrets: []*v1.Secret{secret()}, + errors: noerrors, + test: testSyncSnapshot, }, { name: "2-8 - snapshot and content bound, apiserver update status error", @@ -169,6 +179,9 @@ func TestSync(t *testing.T) { }, }, }, + initialClaims: newClaimArray("claim2-8", "pvc-uid2-8", "1Gi", "volume2-8", v1.ClaimBound, &classEmpty), + initialVolumes: newVolumeArray("volume2-8", "pv-uid2-8", "pv-handle2-8", "1Gi", "pvc-uid2-8", "claim2-8", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty, mockDriverName, testNamespace), + initialSecrets: []*v1.Secret{secret()}, errors: []reactorError{ // Inject error to the first client.VolumesnapshotV1alpha1().VolumeSnapshots().Update call. // All other calls will succeed.