From eeaeb71dbe5ec5e3190a1ef54bd2ea2247e62b49 Mon Sep 17 00:00:00 2001 From: Sirish Bathina Date: Fri, 11 Sep 2020 12:45:13 -0700 Subject: [PATCH] Change status to ReadyToUse to true for VolumeSnapshot (#752) * changes to test hack * tailored for dell * Adding return * UTs and comments * small change to trigger build --- pkg/kube/snapshot/snapshot_alpha.go | 28 ++++++++++ pkg/kube/snapshot/snapshot_beta.go | 28 +++++++++- pkg/kube/snapshot/snapshot_test.go | 87 +++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 1 deletion(-) diff --git a/pkg/kube/snapshot/snapshot_alpha.go b/pkg/kube/snapshot/snapshot_alpha.go index 396f6affaf..ecbb633129 100644 --- a/pkg/kube/snapshot/snapshot_alpha.go +++ b/pkg/kube/snapshot/snapshot_alpha.go @@ -45,6 +45,7 @@ const ( DeletionPolicyDelete = "Delete" DeletionPolicyRetain = "Retain" CloneVolumeSnapshotClassLabelName = "kanister-cloned-from" + DellFlexOSDriver = "csi-vxflexos.dellemc.com" ) type SnapshotAlpha struct { @@ -208,10 +209,37 @@ func (sna *SnapshotAlpha) CreateFromSource(ctx context.Context, source *Source, if !waitForReady { return nil } + if source.Driver == DellFlexOSDriver { + // Temporary work around till upstream issue is resolved- + // github- https://github.com/dell/csi-vxflexos/pull/11 + // forum- https://www.dell.com/community/Containers/Issue-where-volumeSnapshots-have-ReadyToUse-field-set-to-false/m-p/7685881#M249 + err := sna.UpdateVolumeSnapshotStatusAlpha(ctx, namespace, snap.GetName(), true) + if err != nil { + return err + } + } return sna.WaitOnReadyToUse(ctx, snapshotName, namespace) } +// UpdateVolumeSnapshotStatusAlpha sets the readyToUse valuse of a VolumeSnapshot. +func (sna *SnapshotAlpha) UpdateVolumeSnapshotStatusAlpha(ctx context.Context, namespace string, snapshotName string, readyToUse bool) error { + us, err := sna.dynCli.Resource(v1alpha1.VolSnapGVR).Namespace(namespace).Get(ctx, snapshotName, metav1.GetOptions{}) + if err != nil { + return err + } + status, ok := us.Object["status"].(map[string]interface{}) + if !ok { + return errors.Errorf("Failed to convert status to map, Volumesnapshot: %s, Status: %v", snapshotName, status) + } + status["readyToUse"] = readyToUse + us.Object["status"] = status + if _, err := sna.dynCli.Resource(v1alpha1.VolSnapGVR).Namespace(namespace).UpdateStatus(ctx, us, metav1.UpdateOptions{}); err != nil { + return errors.Errorf("Failed to update status, Volumesnapshot: %s, Error: %v", snapshotName, err) + } + return nil +} + // CreateContentFromSource will create a 'VolumesnaphotContent' for the underlying snapshot source. func (sna *SnapshotAlpha) CreateContentFromSource(ctx context.Context, source *Source, contentName, snapshotName, namespace, deletionPolicy string) error { content := UnstructuredVolumeSnapshotContentAlpha(contentName, snapshotName, namespace, deletionPolicy, source.Driver, source.Handle, source.VolumeSnapshotClassName) diff --git a/pkg/kube/snapshot/snapshot_beta.go b/pkg/kube/snapshot/snapshot_beta.go index 9d22aeffcf..9a6595acea 100644 --- a/pkg/kube/snapshot/snapshot_beta.go +++ b/pkg/kube/snapshot/snapshot_beta.go @@ -239,11 +239,37 @@ func (sna *SnapshotBeta) CreateFromSource(ctx context.Context, source *Source, s if !waitForReady { return nil } - + if source.Driver == DellFlexOSDriver { + // Temporary work around till upstream issue is resolved- + // github- https://github.com/dell/csi-vxflexos/pull/11 + // forum- https://www.dell.com/community/Containers/Issue-where-volumeSnapshots-have-ReadyToUse-field-set-to-false/m-p/7685881#M249 + err := sna.UpdateVolumeSnapshotStatusBeta(ctx, namespace, snap.GetName(), true) + if err != nil { + return err + } + } err = sna.WaitOnReadyToUse(ctx, snapshotName, namespace) return err } +// UpdateVolumeSnapshotStatusBeta sets the readyToUse valuse of a VolumeSnapshot. +func (sna *SnapshotBeta) UpdateVolumeSnapshotStatusBeta(ctx context.Context, namespace string, snapshotName string, readyToUse bool) error { + us, err := sna.dynCli.Resource(v1beta1.VolSnapGVR).Namespace(namespace).Get(ctx, snapshotName, metav1.GetOptions{}) + if err != nil { + return err + } + status, ok := us.Object["status"].(map[string]interface{}) + if !ok { + return errors.Errorf("Failed to convert status to map, Volumesnapshot: %s, Status: %v", snapshotName, status) + } + status["readyToUse"] = readyToUse + us.Object["status"] = status + if _, err := sna.dynCli.Resource(v1beta1.VolSnapGVR).Namespace(namespace).UpdateStatus(ctx, us, metav1.UpdateOptions{}); err != nil { + return errors.Errorf("Failed to update status, Volumesnapshot: %s, Error: %v", snapshotName, err) + } + return nil +} + // CreateContentFromSource will create a 'VolumesnaphotContent' for the underlying snapshot source. func (sna *SnapshotBeta) CreateContentFromSource(ctx context.Context, source *Source, contentName, snapshotName, namespace, deletionPolicy string) error { content := UnstructuredVolumeSnapshotContentBeta(contentName, snapshotName, namespace, deletionPolicy, source.Driver, source.Handle, source.VolumeSnapshotClassName) diff --git a/pkg/kube/snapshot/snapshot_test.go b/pkg/kube/snapshot/snapshot_test.go index 848c56619c..7a799a4bca 100644 --- a/pkg/kube/snapshot/snapshot_test.go +++ b/pkg/kube/snapshot/snapshot_test.go @@ -757,3 +757,90 @@ func findSnapshotClassName(c *C, dynCli dynamic.Interface, gvr schema.GroupVersi } return snapshotClass, snapshotterName } + +func (s *SnapshotTestSuite) TestCreateFromSourceAlpha(c *C) { + ctx := context.Background() + namespace := "namespace" + snapshotName := "snapname" + snapshotClass := "volSnapClass" + + volSnap := snapshot.UnstructuredVolumeSnapshotAlpha(snapshotName, namespace, "pvcName", "content", snapshotClass) + volSnap.Object["status"] = map[string]interface{}{ + "readyToUse": false, + } + scheme := runtime.NewScheme() + dynCli := dynfake.NewSimpleDynamicClient(scheme, volSnap) + kubeCli := fake.NewSimpleClientset() + + snapshotterAlpha, ok := snapshot.NewSnapshotAlpha(kubeCli, dynCli).(*snapshot.SnapshotAlpha) + c.Assert(ok, Equals, true) + + // set true + err := snapshotterAlpha.UpdateVolumeSnapshotStatusAlpha(ctx, namespace, snapshotName, true) + c.Assert(err, IsNil) + us, err := dynCli.Resource(v1alpha1.VolSnapGVR).Namespace(namespace).Get(ctx, snapshotName, metav1.GetOptions{}) + c.Assert(err, IsNil) + status, ok := us.Object["status"].(map[string]interface{}) + c.Assert(ok, Equals, true) + c.Assert(status["readyToUse"], Equals, true) + + // set false + err = snapshotterAlpha.UpdateVolumeSnapshotStatusAlpha(ctx, namespace, snapshotName, false) + c.Assert(err, IsNil) + us, err = dynCli.Resource(v1alpha1.VolSnapGVR).Namespace(namespace).Get(ctx, snapshotName, metav1.GetOptions{}) + c.Assert(err, IsNil) + status, ok = us.Object["status"].(map[string]interface{}) + c.Assert(ok, Equals, true) + c.Assert(status["readyToUse"], Equals, false) + + // status not set + volSnap = snapshot.UnstructuredVolumeSnapshotAlpha(snapshotName, namespace, "pvcName", "content", snapshotClass) + dynCli = dynfake.NewSimpleDynamicClient(scheme, volSnap) + snapshotterAlpha, ok = snapshot.NewSnapshotAlpha(kubeCli, dynCli).(*snapshot.SnapshotAlpha) + c.Assert(ok, Equals, true) + err = snapshotterAlpha.UpdateVolumeSnapshotStatusAlpha(ctx, namespace, snapshotName, false) + c.Assert(err, NotNil) +} +func (s *SnapshotTestSuite) TestCreateFromSourceBeta(c *C) { + ctx := context.Background() + namespace := "namespace" + snapshotName := "snapname" + snapshotClass := "volSnapClass" + + volSnap := snapshot.UnstructuredVolumeSnapshotBeta(snapshotName, namespace, "pvcName", "content", snapshotClass) + volSnap.Object["status"] = map[string]interface{}{ + "readyToUse": false, + } + scheme := runtime.NewScheme() + dynCli := dynfake.NewSimpleDynamicClient(scheme, volSnap) + kubeCli := fake.NewSimpleClientset() + + snapshotterBeta, ok := snapshot.NewSnapshotBeta(kubeCli, dynCli).(*snapshot.SnapshotBeta) + c.Assert(ok, Equals, true) + + // set true + err := snapshotterBeta.UpdateVolumeSnapshotStatusBeta(ctx, namespace, snapshotName, true) + c.Assert(err, IsNil) + us, err := dynCli.Resource(v1beta1.VolSnapGVR).Namespace(namespace).Get(ctx, snapshotName, metav1.GetOptions{}) + c.Assert(err, IsNil) + status, ok := us.Object["status"].(map[string]interface{}) + c.Assert(ok, Equals, true) + c.Assert(status["readyToUse"], Equals, true) + + // set false + err = snapshotterBeta.UpdateVolumeSnapshotStatusBeta(ctx, namespace, snapshotName, false) + c.Assert(err, IsNil) + us, err = dynCli.Resource(v1beta1.VolSnapGVR).Namespace(namespace).Get(ctx, snapshotName, metav1.GetOptions{}) + c.Assert(err, IsNil) + status, ok = us.Object["status"].(map[string]interface{}) + c.Assert(ok, Equals, true) + c.Assert(status["readyToUse"], Equals, false) + + // status not set + volSnap = snapshot.UnstructuredVolumeSnapshotBeta(snapshotName, namespace, "pvcName", "content", snapshotClass) + dynCli = dynfake.NewSimpleDynamicClient(scheme, volSnap) + snapshotterBeta, ok = snapshot.NewSnapshotBeta(kubeCli, dynCli).(*snapshot.SnapshotBeta) + c.Assert(ok, Equals, true) + err = snapshotterBeta.UpdateVolumeSnapshotStatusBeta(ctx, namespace, snapshotName, false) + c.Assert(err, NotNil) +}