Skip to content

Commit

Permalink
Merge pull request #165 from xing-yang/ann_secret
Browse files Browse the repository at this point in the history
Add deletion secret as annotation to content
  • Loading branch information
k8s-ci-robot authored Sep 5, 2019
2 parents ffee5f4 + e647a80 commit a791d62
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 95 deletions.
33 changes: 28 additions & 5 deletions pkg/controller/framework_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -790,11 +790,12 @@ func newTestController(kubeClient kubernetes.Interface, clientset clientset.Inte
}

// newContent returns a new content with given attributes
func newContent(name, className, snapshotHandle, volumeUID, volumeName, boundToSnapshotUID, boundToSnapshotName string, deletionPolicy *crdv1.DeletionPolicy, size *int64, creationTime *int64, withFinalizer bool) *crdv1.VolumeSnapshotContent {
func newContent(name, className, snapshotHandle, volumeUID, volumeName, boundToSnapshotUID, boundToSnapshotName string, deletionPolicy *crdv1.DeletionPolicy, size *int64, creationTime *int64, withFinalizer bool, annotations map[string]string) *crdv1.VolumeSnapshotContent {
content := crdv1.VolumeSnapshotContent{
ObjectMeta: metav1.ObjectMeta{
Name: name,
ResourceVersion: "1",
Annotations: annotations,
},
Spec: crdv1.VolumeSnapshotContentSpec{
VolumeSnapshotSource: crdv1.VolumeSnapshotSource{
Expand Down Expand Up @@ -833,14 +834,14 @@ func newContent(name, className, snapshotHandle, volumeUID, volumeName, boundToS
return &content
}

func newContentArray(name, className, snapshotHandle, volumeUID, volumeName, boundToSnapshotUID, boundToSnapshotName string, deletionPolicy *crdv1.DeletionPolicy, size *int64, creationTime *int64, withFinalizer bool) []*crdv1.VolumeSnapshotContent {
func newContentArray(name, className, snapshotHandle, volumeUID, volumeName, boundToSnapshotUID, boundToSnapshotName string, deletionPolicy *crdv1.DeletionPolicy, size *int64, creationTime *int64, withFinalizer bool, annotations map[string]string) []*crdv1.VolumeSnapshotContent {
return []*crdv1.VolumeSnapshotContent{
newContent(name, className, snapshotHandle, volumeUID, volumeName, boundToSnapshotUID, boundToSnapshotName, deletionPolicy, size, creationTime, withFinalizer),
newContent(name, className, snapshotHandle, volumeUID, volumeName, boundToSnapshotUID, boundToSnapshotName, deletionPolicy, size, creationTime, withFinalizer, annotations),
}
}

func newContentWithUnmatchDriverArray(name, className, snapshotHandle, volumeUID, volumeName, boundToSnapshotUID, boundToSnapshotName string, deletionPolicy *crdv1.DeletionPolicy, size *int64, creationTime *int64) []*crdv1.VolumeSnapshotContent {
content := newContent(name, className, snapshotHandle, volumeUID, volumeName, boundToSnapshotUID, boundToSnapshotName, deletionPolicy, size, creationTime, false)
content := newContent(name, className, snapshotHandle, volumeUID, volumeName, boundToSnapshotUID, boundToSnapshotName, deletionPolicy, size, creationTime, false, nil)
content.Spec.VolumeSnapshotSource.CSI.Driver = "fake"
return []*crdv1.VolumeSnapshotContent{
content,
Expand Down Expand Up @@ -1287,6 +1288,28 @@ func secret() *v1.Secret {
}
}

func secretAnnotations() map[string]string {
return map[string]string{
AnnDeletionSecretRefName: "secret",
AnnDeletionSecretRefNamespace: "default",
}
}

func emptyNamespaceSecretAnnotations() map[string]string {
return map[string]string{
AnnDeletionSecretRefName: "name",
AnnDeletionSecretRefNamespace: "",
}
}

// this refers to emptySecret(), which is missing data.
func emptyDataSecretAnnotations() map[string]string {
return map[string]string{
AnnDeletionSecretRefName: "emptysecret",
AnnDeletionSecretRefNamespace: "default",
}
}

type listCall struct {
snapshotID string
// information to return
Expand Down Expand Up @@ -1368,7 +1391,7 @@ func (f *fakeSnapshotter) CreateSnapshot(ctx context.Context, snapshotName strin
func (f *fakeSnapshotter) DeleteSnapshot(ctx context.Context, snapshotID string, snapshotterCredentials map[string]string) error {
if f.deleteCallCounter >= len(f.deleteCalls) {
f.t.Errorf("Unexpected CSI Delete Snapshot call: snapshotID=%s, index: %d, calls: %+v", snapshotID, f.createCallCounter, f.createCalls)
return fmt.Errorf("unexpected call")
return fmt.Errorf("unexpected DeleteSnapshot call")
}
call := f.deleteCalls[f.deleteCallCounter]
f.deleteCallCounter++
Expand Down
66 changes: 44 additions & 22 deletions pkg/controller/snapshot_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ func (ctrl *csiSnapshotController) checkandBindSnapshotContent(snapshot *crdv1.V
return newContent, nil
}

func (ctrl *csiSnapshotController) getCreateSnapshotInput(snapshot *crdv1.VolumeSnapshot) (*crdv1.VolumeSnapshotClass, *v1.PersistentVolume, string, map[string]string, error) {
func (ctrl *csiSnapshotController) getCreateSnapshotInput(snapshot *crdv1.VolumeSnapshot) (*crdv1.VolumeSnapshotClass, *v1.PersistentVolume, string, *v1.SecretReference, error) {
className := snapshot.Spec.VolumeSnapshotClassName
klog.V(5).Infof("getCreateSnapshotInput [%s]: VolumeSnapshotClassName [%s]", snapshot.Name, *className)
var class *crdv1.VolumeSnapshotClass
Expand Down Expand Up @@ -553,12 +553,8 @@ func (ctrl *csiSnapshotController) getCreateSnapshotInput(snapshot *crdv1.Volume
if err != nil {
return nil, nil, "", nil, err
}
snapshotterCredentials, err := getCredentials(ctrl.client, snapshotterSecretRef)
if err != nil {
return nil, nil, "", nil, err
}

return class, volume, contentName, snapshotterCredentials, nil
return class, volume, contentName, snapshotterSecretRef, nil
}

func (ctrl *csiSnapshotController) checkandUpdateBoundSnapshotStatusOperation(snapshot *crdv1.VolumeSnapshot, content *crdv1.VolumeSnapshotContent) (*crdv1.VolumeSnapshot, error) {
Expand All @@ -580,10 +576,14 @@ func (ctrl *csiSnapshotController) checkandUpdateBoundSnapshotStatusOperation(sn
driverName, snapshotID = content.Spec.CSI.Driver, content.Spec.CSI.SnapshotHandle
}
} else {
class, volume, _, snapshotterCredentials, err := ctrl.getCreateSnapshotInput(snapshot)
class, volume, _, snapshotterSecretRef, err := ctrl.getCreateSnapshotInput(snapshot)
if err != nil {
return nil, fmt.Errorf("failed to get input parameters to create snapshot %s: %q", snapshot.Name, err)
}
snapshotterCredentials, err := getCredentials(ctrl.client, snapshotterSecretRef)
if err != nil {
return nil, err
}
driverName, snapshotID, creationTime, size, readyToUse, err = ctrl.handler.CreateSnapshot(snapshot, volume, class.Parameters, snapshotterCredentials)
if err != nil {
klog.Errorf("checkandUpdateBoundSnapshotStatusOperation: failed to call create snapshot to check whether the snapshot is ready to use %q", err)
Expand Down Expand Up @@ -627,11 +627,16 @@ func (ctrl *csiSnapshotController) createSnapshotOperation(snapshot *crdv1.Volum
return nil, err
}

class, volume, contentName, snapshotterCredentials, err := ctrl.getCreateSnapshotInput(snapshot)
class, volume, contentName, snapshotterSecretRef, err := ctrl.getCreateSnapshotInput(snapshot)
if err != nil {
return nil, fmt.Errorf("failed to get input parameters to create snapshot %s: %q", snapshot.Name, err)
}

snapshotterCredentials, err := getCredentials(ctrl.client, snapshotterSecretRef)
if err != nil {
return nil, err
}

driverName, snapshotID, creationTime, size, readyToUse, err := ctrl.handler.CreateSnapshot(snapshot, volume, class.Parameters, snapshotterCredentials)
if err != nil {
return nil, fmt.Errorf("failed to take snapshot of the volume, %s: %q", volume.Name, err)
Expand Down Expand Up @@ -687,6 +692,16 @@ func (ctrl *csiSnapshotController) createSnapshotOperation(snapshot *crdv1.Volum
DeletionPolicy: class.DeletionPolicy,
},
}

// Set AnnDeletionSecretRefName and AnnDeletionSecretRefNamespace
if snapshotterSecretRef != nil {
klog.V(5).Infof("createSnapshotOperation: set annotation [%s] on content [%s].", AnnDeletionSecretRefName, snapshotContent.Name)
metav1.SetMetaDataAnnotation(&snapshotContent.ObjectMeta, AnnDeletionSecretRefName, snapshotterSecretRef.Name)

klog.V(5).Infof("syncContent: set annotation [%s] on content [%s].", AnnDeletionSecretRefNamespace, snapshotContent.Name)
metav1.SetMetaDataAnnotation(&snapshotContent.ObjectMeta, AnnDeletionSecretRefNamespace, snapshotterSecretRef.Namespace)
}

klog.V(3).Infof("volume snapshot content %v", snapshotContent)
// Try to create the VolumeSnapshotContent object several times
for i := 0; i < ctrl.createSnapshotContentRetryCount; i++ {
Expand Down Expand Up @@ -736,23 +751,30 @@ func (ctrl *csiSnapshotController) deleteSnapshotContentOperation(content *crdv1

// get secrets if VolumeSnapshotClass specifies it
var snapshotterCredentials map[string]string
snapshotClassName := content.Spec.VolumeSnapshotClassName
if snapshotClassName != nil {
if snapshotClass, err := ctrl.classLister.Get(*snapshotClassName); err == nil {
// Resolve snapshotting secret credentials.
// No VolumeSnapshot is provided when resolving delete secret names, since the VolumeSnapshot may or may not exist at delete time.
snapshotterSecretRef, err := getSecretReference(snapshotClass.Parameters, content.Name, nil)
if err != nil {
return err
}
snapshotterCredentials, err = getCredentials(ctrl.client, snapshotterSecretRef)
if err != nil {
return err
}
var err error

// Check if annotation exists
if metav1.HasAnnotation(content.ObjectMeta, AnnDeletionSecretRefName) && metav1.HasAnnotation(content.ObjectMeta, AnnDeletionSecretRefNamespace) {
annDeletionSecretName := content.Annotations[AnnDeletionSecretRefName]
annDeletionSecretNamespace := content.Annotations[AnnDeletionSecretRefNamespace]

snapshotterSecretRef := &v1.SecretReference{}

if annDeletionSecretName == "" || annDeletionSecretNamespace == "" {
return fmt.Errorf("cannot delete snapshot %#v, err: secret name or namespace not specified", content.Name)
}

snapshotterSecretRef.Name = annDeletionSecretName
snapshotterSecretRef.Namespace = annDeletionSecretNamespace

snapshotterCredentials, err = getCredentials(ctrl.client, snapshotterSecretRef)
if err != nil {
// Continue with deletion, as the secret may have already been deleted.
klog.Errorf("Failed to get credentials for snapshot %s: %s", content.Name, err.Error())
}
}

err := ctrl.handler.DeleteSnapshot(content, snapshotterCredentials)
err = ctrl.handler.DeleteSnapshot(content, snapshotterCredentials)
if err != nil {
ctrl.eventRecorder.Event(content, v1.EventTypeWarning, "SnapshotDeleteError", "Failed to delete snapshot")
return fmt.Errorf("failed to delete snapshot %#v, err: %v", content.Name, err)
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/snapshot_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
)

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, nil, false)
content := newContent("contentName", classEmpty, "sid1-1", "vuid1-1", "volume1-1", "snapuid1-1", "snap1-1", nil, nil, nil, false, nil)
content.ResourceVersion = version
ret, err := storeObjectUpdate(c, content, "content")
if err != nil {
Expand Down Expand Up @@ -82,7 +82,7 @@ func TestControllerCacheParsingError(t *testing.T) {
// 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, nil, false)
content := newContent("contentName", classEmpty, "sid1-1", "vuid1-1", "volume1-1", "snapuid1-1", "snap1-1", nil, nil, nil, false, nil)
content.ResourceVersion = "xxx"
_, err := storeObjectUpdate(c, content, "content")
if err == nil {
Expand Down
24 changes: 18 additions & 6 deletions pkg/controller/snapshot_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func TestCreateSnapshotSync(t *testing.T) {
{
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", &deletePolicy, &defaultSize, &timeNowStamp, false),
expectedContents: newContentArray("snapcontent-snapuid6-1", classGold, "sid6-1", "pv-uid6-1", "volume6-1", "snapuid6-1", "snap6-1", &deletePolicy, &defaultSize, &timeNowStamp, false, nil),
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),
Expand All @@ -93,7 +93,7 @@ func TestCreateSnapshotSync(t *testing.T) {
{
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", &deletePolicy, &defaultSize, &timeNowStamp, false),
expectedContents: newContentArray("snapcontent-snapuid6-2", classSilver, "sid6-2", "pv-uid6-2", "volume6-2", "snapuid6-2", "snap6-2", &deletePolicy, &defaultSize, &timeNowStamp, false, nil),
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),
Expand All @@ -117,7 +117,7 @@ func TestCreateSnapshotSync(t *testing.T) {
{
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", &deletePolicy, &defaultSize, &timeNowStamp, false),
expectedContents: newContentArray("snapcontent-snapuid6-3", validSecretClass, "sid6-3", "pv-uid6-3", "volume6-3", "snapuid6-3", "snap6-3", &deletePolicy, &defaultSize, &timeNowStamp, false, secretAnnotations()),
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),
Expand All @@ -143,7 +143,7 @@ func TestCreateSnapshotSync(t *testing.T) {
{
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", &deletePolicy, &defaultSize, &timeNowStamp, false),
expectedContents: newContentArray("snapcontent-snapuid6-4", emptySecretClass, "sid6-4", "pv-uid6-4", "volume6-4", "snapuid6-4", "snap6-4", &deletePolicy, &defaultSize, &timeNowStamp, false, emptyDataSecretAnnotations()),
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),
Expand All @@ -169,7 +169,7 @@ func TestCreateSnapshotSync(t *testing.T) {
{
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", &deletePolicy, &defaultSize, &timeNowStamp, false),
expectedContents: newContentArray("snapcontent-snapuid6-5", classGold, "sid6-5", "pv-uid6-5", "volume6-5", "snapuid6-5", "snap6-5", &deletePolicy, &defaultSize, &timeNowStamp, false, nil),
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),
Expand All @@ -193,7 +193,7 @@ func TestCreateSnapshotSync(t *testing.T) {
{
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", &deletePolicy, &defaultSize, &timeNowStamp, false),
expectedContents: newContentArray("snapcontent-snapuid6-6", classGold, "sid6-6", "pv-uid6-6", "volume6-6", "snapuid6-6", "snap6-6", &deletePolicy, &defaultSize, &timeNowStamp, false, nil),
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),
Expand Down Expand Up @@ -365,6 +365,18 @@ 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),
initialSecrets: []*v1.Secret{}, // no initial secret created
errors: noerrors,
test: testSyncSnapshot,
},
}
runSyncTests(t, tests, snapshotClasses)
}
Loading

0 comments on commit a791d62

Please sign in to comment.