github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/testutil/k8s/storage_util.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 This file is part of KubeBlocks project 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package testutil 21 22 import ( 23 snapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1" 24 "github.com/onsi/gomega" 25 storagev1 "k8s.io/api/storage/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/types" 28 "k8s.io/kubectl/pkg/util/storage" 29 "sigs.k8s.io/controller-runtime/pkg/client" 30 31 "github.com/1aal/kubeblocks/pkg/testutil" 32 ) 33 34 var ( 35 DefaultStorageClassName = "default-sc-for-testing" 36 defaultVolumeSnapshotClassName = "default-vsc-for-testing" 37 defaultProvisioner = "testing.kubeblocks.io" 38 ) 39 40 func GetDefaultStorageClass(testCtx *testutil.TestContext) *storagev1.StorageClass { 41 scList := &storagev1.StorageClassList{} 42 gomega.Expect(testCtx.Cli.List(testCtx.Ctx, scList)).Should(gomega.Succeed()) 43 if len(scList.Items) == 0 { 44 return nil 45 } 46 47 for _, sc := range scList.Items { 48 annot := sc.Annotations 49 if annot == nil { 50 continue 51 } 52 if isDefaultStorageClassAnnotation(&sc) { 53 return &sc 54 } 55 } 56 return nil 57 } 58 59 func isDefaultStorageClassAnnotation(storageClass *storagev1.StorageClass) bool { 60 return storageClass.Annotations != nil && storageClass.Annotations[storage.IsDefaultStorageClassAnnotation] == "true" 61 } 62 63 func CreateMockStorageClass(testCtx *testutil.TestContext, storageClassName string) *storagev1.StorageClass { 64 sc := getStorageClass(testCtx, storageClassName) 65 if sc == nil { 66 sc = createStorageClass(testCtx, storageClassName) 67 } 68 return sc 69 } 70 71 func MockEnableVolumeSnapshot(testCtx *testutil.TestContext, storageClassName string) { 72 sc := getStorageClass(testCtx, storageClassName) 73 if sc == nil { 74 sc = createStorageClass(testCtx, storageClassName) 75 } 76 vsc := getVolumeSnapshotClass(testCtx, sc) 77 if vsc == nil { 78 CreateVolumeSnapshotClass(testCtx, sc.Provisioner) 79 } 80 gomega.Expect(IsMockVolumeSnapshotEnabled(testCtx, storageClassName)).Should(gomega.BeTrue()) 81 } 82 83 func MockDisableVolumeSnapshot(testCtx *testutil.TestContext, storageClassName string) { 84 sc := getStorageClass(testCtx, storageClassName) 85 if sc != nil { 86 deleteVolumeSnapshotClass(testCtx, sc) 87 deleteStorageClass(testCtx, storageClassName) 88 } 89 } 90 91 func IsMockVolumeSnapshotEnabled(testCtx *testutil.TestContext, storageClassName string) bool { 92 sc := getStorageClass(testCtx, storageClassName) 93 if sc == nil { 94 return false 95 } 96 return getVolumeSnapshotClass(testCtx, sc) != nil 97 } 98 99 func getStorageClass(testCtx *testutil.TestContext, storageClassName string) *storagev1.StorageClass { 100 sc := &storagev1.StorageClass{} 101 if err := testCtx.Cli.Get(testCtx.Ctx, types.NamespacedName{Name: storageClassName}, sc); err != nil { 102 if client.IgnoreNotFound(err) == nil { 103 return nil 104 } 105 gomega.Expect(err).Should(gomega.Succeed()) 106 } 107 return sc 108 } 109 110 func createStorageClass(testCtx *testutil.TestContext, storageClassName string) *storagev1.StorageClass { 111 allowVolumeExpansion := true 112 sc := &storagev1.StorageClass{ 113 ObjectMeta: metav1.ObjectMeta{ 114 Name: storageClassName, 115 }, 116 Provisioner: defaultProvisioner, 117 AllowVolumeExpansion: &allowVolumeExpansion, 118 } 119 gomega.Expect(testCtx.Create(testCtx.Ctx, sc)).Should(gomega.Succeed()) 120 return sc 121 } 122 123 func deleteStorageClass(testCtx *testutil.TestContext, storageClassName string) { 124 sc := getStorageClass(testCtx, storageClassName) 125 if sc != nil { 126 gomega.Expect(testCtx.Cli.Delete(testCtx.Ctx, sc)).Should(gomega.Succeed()) 127 } 128 } 129 130 func getVolumeSnapshotClass(testCtx *testutil.TestContext, storageClass *storagev1.StorageClass) *snapshotv1.VolumeSnapshotClass { 131 vscList := &snapshotv1.VolumeSnapshotClassList{} 132 gomega.Expect(testCtx.Cli.List(testCtx.Ctx, vscList)).Should(gomega.Succeed()) 133 for i, vsc := range vscList.Items { 134 if vsc.Driver == storageClass.Provisioner { 135 return &vscList.Items[i] 136 } 137 } 138 return nil 139 } 140 141 func CreateVolumeSnapshotClass(testCtx *testutil.TestContext, storageProvisioner string) *snapshotv1.VolumeSnapshotClass { 142 vsc := &snapshotv1.VolumeSnapshotClass{ 143 ObjectMeta: metav1.ObjectMeta{ 144 Name: defaultVolumeSnapshotClassName, 145 }, 146 Driver: storageProvisioner, 147 DeletionPolicy: snapshotv1.VolumeSnapshotContentDelete, 148 } 149 gomega.Expect(testCtx.Create(testCtx.Ctx, vsc)).Should(gomega.Succeed()) 150 return vsc 151 } 152 153 func deleteVolumeSnapshotClass(testCtx *testutil.TestContext, storageClass *storagev1.StorageClass) { 154 vsc := getVolumeSnapshotClass(testCtx, storageClass) 155 if vsc != nil { 156 gomega.Expect(testCtx.Cli.Delete(testCtx.Ctx, vsc)).Should(gomega.Succeed()) 157 } 158 }