From b3123547a47547ba3cd2a81402f3679f1764ad65 Mon Sep 17 00:00:00 2001 From: f10atin9 Date: Mon, 23 Aug 2021 18:01:28 +0800 Subject: [PATCH] Capability controller can add annotations, no matter whether the storageClass has CSIDriver. Snapshot controller will create volumeSnapshotClass based on allowSnapshot annotation. Signed-off-by: f10atin9 --- .../capability/capability_controller.go | 30 ++++++------- .../storage/snapshot/snapshot_controller.go | 43 ++++++++++++++----- .../snapshot/snapshot_controller_test.go | 1 + 3 files changed, 46 insertions(+), 28 deletions(-) diff --git a/pkg/controller/storage/capability/capability_controller.go b/pkg/controller/storage/capability/capability_controller.go index 9acd35bdf..bdbaef632 100644 --- a/pkg/controller/storage/capability/capability_controller.go +++ b/pkg/controller/storage/capability/capability_controller.go @@ -237,28 +237,24 @@ func (c *StorageCapabilityController) hasCSIDriver(storageClass *storagev1.Stora } func (c *StorageCapabilityController) addStorageClassSnapshotAnnotation(storageClass *storagev1.StorageClass, snapshotAllow bool) error { - if snapshotAllow { - if storageClass.Annotations == nil { - storageClass.Annotations = make(map[string]string) - } - _, err := strconv.ParseBool(storageClass.Annotations[annotationAllowSnapshot]) - // err != nil means annotationAllowSnapshot is not illegal, include empty - if err != nil { - storageClass.Annotations[annotationAllowSnapshot] = strconv.FormatBool(snapshotAllow) - } + if storageClass.Annotations == nil { + storageClass.Annotations = make(map[string]string) + } + _, err := strconv.ParseBool(storageClass.Annotations[annotationAllowSnapshot]) + // err != nil means annotationAllowSnapshot is not illegal, include empty + if err != nil { + storageClass.Annotations[annotationAllowSnapshot] = strconv.FormatBool(snapshotAllow) } return nil } func (c *StorageCapabilityController) addCloneVolumeAnnotation(storageClass *storagev1.StorageClass, cloneAllow bool) error { - if cloneAllow { - if storageClass.Annotations == nil { - storageClass.Annotations = make(map[string]string) - } - _, err := strconv.ParseBool(storageClass.Annotations[annotationAllowClone]) - if err != nil { - storageClass.Annotations[annotationAllowClone] = strconv.FormatBool(cloneAllow) - } + if storageClass.Annotations == nil { + storageClass.Annotations = make(map[string]string) + } + _, err := strconv.ParseBool(storageClass.Annotations[annotationAllowClone]) + if err != nil { + storageClass.Annotations[annotationAllowClone] = strconv.FormatBool(cloneAllow) } return nil } diff --git a/pkg/controller/storage/snapshot/snapshot_controller.go b/pkg/controller/storage/snapshot/snapshot_controller.go index 90808e28c..696d10da4 100644 --- a/pkg/controller/storage/snapshot/snapshot_controller.go +++ b/pkg/controller/storage/snapshot/snapshot_controller.go @@ -21,8 +21,11 @@ package snapshot import ( "context" "fmt" + "strconv" "time" + storagev1 "k8s.io/api/storage/v1" + snapshotv1beta1 "github.com/kubernetes-csi/external-snapshotter/client/v3/apis/volumesnapshot/v1beta1" snapshotclient "github.com/kubernetes-csi/external-snapshotter/client/v3/clientset/versioned/typed/volumesnapshot/v1beta1" snapinformers "github.com/kubernetes-csi/external-snapshotter/client/v3/informers/externalversions/volumesnapshot/v1beta1" @@ -41,6 +44,8 @@ import ( crdscheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" ) +const annotationAllowSnapshot = "storageclass.kubesphere.io/allow-snapshot" + type VolumeSnapshotClassController struct { storageClassLister storagelistersv1.StorageClassLister storageClassSynced cache.InformerSynced @@ -71,7 +76,15 @@ func NewController( } storageClassInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ - AddFunc: controller.enqueueStorageClass, + AddFunc: controller.enqueueStorageClass, + UpdateFunc: func(old, new interface{}) { + newStorageClass := new.(*storagev1.StorageClass) + oldStorageClass := old.(*storagev1.StorageClass) + if newStorageClass.ResourceVersion == oldStorageClass.ResourceVersion { + return + } + controller.enqueueStorageClass(newStorageClass) + }, DeleteFunc: controller.enqueueStorageClass, }) @@ -167,19 +180,27 @@ func (c *VolumeSnapshotClassController) syncHandler(key string) error { return err } - // If VolumeSnapshotClass not exist, create it - _, err = c.snapshotClassLister.Get(name) - if err != nil { - if errors.IsNotFound(err) { - volumeSnapshotClassCreate := &snapshotv1beta1.VolumeSnapshotClass{ - ObjectMeta: metav1.ObjectMeta{Name: name}, - Driver: storageClass.Provisioner, - DeletionPolicy: snapshotv1beta1.VolumeSnapshotContentDelete, + if storageClass.Annotations != nil { + if annotationSnap, ok := storageClass.Annotations[annotationAllowSnapshot]; ok { + allowSnapshot, err := strconv.ParseBool(annotationSnap) + if err == nil && allowSnapshot { + // If VolumeSnapshotClass not exist, create it + _, err = c.snapshotClassLister.Get(name) + if err != nil { + if errors.IsNotFound(err) { + volumeSnapshotClassCreate := &snapshotv1beta1.VolumeSnapshotClass{ + ObjectMeta: metav1.ObjectMeta{Name: name}, + Driver: storageClass.Provisioner, + DeletionPolicy: snapshotv1beta1.VolumeSnapshotContentDelete, + } + _, err = c.snapshotClassClient.Create(context.Background(), volumeSnapshotClassCreate, metav1.CreateOptions{}) + } + } } - _, err = c.snapshotClassClient.Create(context.Background(), volumeSnapshotClassCreate, metav1.CreateOptions{}) + return err } } - return err + return nil } func (c *VolumeSnapshotClassController) deleteSnapshotClass(name string) error { diff --git a/pkg/controller/storage/snapshot/snapshot_controller_test.go b/pkg/controller/storage/snapshot/snapshot_controller_test.go index 82b4bd660..04ae8e1fb 100644 --- a/pkg/controller/storage/snapshot/snapshot_controller_test.go +++ b/pkg/controller/storage/snapshot/snapshot_controller_test.go @@ -227,6 +227,7 @@ func getKey(sc *storagev1.StorageClass, t *testing.T) string { func TestCreateStorageClass(t *testing.T) { fixture := newFixture(t) storageClass := newStorageClass("csi-example") + storageClass.Annotations = map[string]string{annotationAllowSnapshot: "true"} snapshotClass := newSnapshotClass(storageClass) // Objects exist