github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/testutil/type.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 "context" 24 "fmt" 25 "os" 26 "time" 27 28 "github.com/onsi/gomega" 29 "github.com/sethvargo/go-password/password" 30 corev1 "k8s.io/api/core/v1" 31 apierrors "k8s.io/apimachinery/pkg/api/errors" 32 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 "k8s.io/apimachinery/pkg/version" 34 "sigs.k8s.io/controller-runtime/pkg/client" 35 "sigs.k8s.io/controller-runtime/pkg/envtest" 36 37 "github.com/1aal/kubeblocks/pkg/constant" 38 viper "github.com/1aal/kubeblocks/pkg/viperx" 39 ) 40 41 type TestContext struct { 42 Ctx context.Context 43 Cli client.Client 44 TestEnv *envtest.Environment 45 TestObjLabelKey string 46 DefaultNamespace string 47 DefaultEventuallyTimeout time.Duration 48 DefaultEventuallyPollingInterval time.Duration 49 DefaultConsistentlyDuration time.Duration 50 DefaultConsistentlyPollingInterval time.Duration 51 ClearResourceTimeout time.Duration 52 ClearResourcePollingInterval time.Duration 53 CreateObj func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error 54 CheckedCreateObj func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error 55 } 56 57 var ErrUninitError = fmt.Errorf("cli uninitialized error") 58 59 const ( 60 envExistingClusterType = "EXISTING_CLUSTER_TYPE" 61 envUseExistingCluster = "USE_EXISTING_CLUSTER" 62 DefaultStorageProvisoner = "kubernetes.io/no-provisioner" 63 DefaultCSIDriver = "hostpath.csi.k8s.io" 64 ) 65 66 func init() { 67 viper.AutomaticEnv() 68 viper.SetDefault("EventuallyTimeout", time.Second*10) 69 viper.SetDefault("EventuallyPollingInterval", time.Millisecond) 70 viper.SetDefault("ConsistentlyDuration", time.Second*3) 71 viper.SetDefault("ConsistentlyPollingInterval", time.Millisecond) 72 viper.SetDefault("ClearResourceTimeout", time.Second*10) 73 viper.SetDefault("ClearResourcePollingInterval", time.Millisecond) 74 } 75 76 // NewDefaultTestContext creates default test context, if provided namespace optional arg, a namespace 77 // will be created if not exist 78 func NewDefaultTestContext(ctx context.Context, cli client.Client, testEnv *envtest.Environment, namespace ...string) TestContext { 79 if cli == nil { 80 panic("missing required cli arg") 81 } 82 t := TestContext{ 83 TestObjLabelKey: "kubeblocks.io/test", 84 DefaultNamespace: "default", 85 DefaultEventuallyTimeout: viper.GetDuration("EventuallyTimeout"), 86 DefaultEventuallyPollingInterval: viper.GetDuration("EventuallyPollingInterval"), 87 DefaultConsistentlyDuration: viper.GetDuration("ConsistentlyDuration"), 88 DefaultConsistentlyPollingInterval: viper.GetDuration("ConsistentlyPollingInterval"), 89 ClearResourceTimeout: viper.GetDuration("ClearResourceTimeout"), 90 ClearResourcePollingInterval: viper.GetDuration("ClearResourcePollingInterval"), 91 Ctx: ctx, 92 Cli: cli, 93 TestEnv: testEnv, 94 } 95 t.CreateObj = func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { 96 l := obj.GetLabels() 97 if l == nil { 98 l = map[string]string{} 99 } 100 l[t.TestObjLabelKey] = "true" 101 obj.SetLabels(l) 102 return t.Cli.Create(ctx, obj, opts...) 103 } 104 105 t.CheckedCreateObj = func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { 106 if err := t.CreateObj(ctx, obj, opts...); err != nil && !apierrors.IsAlreadyExists(err) { 107 return err 108 } 109 return nil 110 } 111 112 gomega.SetDefaultEventuallyTimeout(t.DefaultEventuallyTimeout) 113 gomega.SetDefaultEventuallyPollingInterval(t.DefaultEventuallyPollingInterval) 114 gomega.SetDefaultConsistentlyDuration(t.DefaultConsistentlyDuration) 115 gomega.SetDefaultConsistentlyPollingInterval(t.DefaultConsistentlyPollingInterval) 116 117 if len(namespace) > 0 && len(namespace[0]) > 0 && namespace[0] != "default" { 118 t.DefaultNamespace = namespace[0] 119 err := t.CreateNamespace() 120 gomega.Expect(client.IgnoreAlreadyExists(err)).To(gomega.Not(gomega.HaveOccurred())) 121 } 122 return t 123 } 124 125 func (testCtx TestContext) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { 126 return testCtx.CreateObj(ctx, obj, opts...) 127 } 128 129 func (testCtx TestContext) GetNamespaceKey() client.ObjectKey { 130 return client.ObjectKey{ 131 Name: testCtx.DefaultNamespace, 132 } 133 } 134 135 func (testCtx TestContext) GetNamespaceObj() corev1.Namespace { 136 return corev1.Namespace{ 137 ObjectMeta: metav1.ObjectMeta{ 138 Name: testCtx.DefaultNamespace, 139 }, 140 } 141 } 142 143 func (testCtx TestContext) CreateNamespace() error { 144 if testCtx.DefaultNamespace == "default" { 145 return nil 146 } 147 namespace := testCtx.GetNamespaceObj() 148 return testCtx.Create(testCtx.Ctx, &namespace) 149 } 150 151 func (testCtx TestContext) GetRandomStr() string { 152 seq, _ := password.Generate(6, 2, 0, true, true) 153 return seq 154 } 155 156 func (testCtx TestContext) UsingExistingCluster() bool { 157 if testCtx.TestEnv == nil || testCtx.TestEnv.UseExistingCluster == nil { 158 return viper.GetBool(envUseExistingCluster) 159 } 160 return *testCtx.TestEnv.UseExistingCluster 161 } 162 163 func (testCtx TestContext) GetWebhookHostExternalName() string { 164 var ( 165 minikubeType = "minikube" 166 minikubeHost = "host.minikube.internal" 167 k3dType = "k3d" 168 k3dHost = "host.k3d.internal" 169 ) 170 clusterType := os.Getenv(envExistingClusterType) 171 if !testCtx.UsingExistingCluster() { 172 return "" 173 } 174 switch clusterType { 175 case minikubeType: 176 return minikubeHost 177 case k3dType: 178 return k3dHost 179 default: 180 return "" 181 } 182 } 183 184 func (testCtx TestContext) UseDefaultNamespace() func(client.Object) { 185 return func(obj client.Object) { 186 obj.SetNamespace(testCtx.DefaultNamespace) 187 } 188 } 189 190 // SetKubeServerVersionWithDistro provides "_KUBE_SERVER_INFO" viper settings helper function. 191 func SetKubeServerVersionWithDistro(major, minor, patch, distro string) { 192 ver := version.Info{ 193 Major: major, 194 Minor: minor, 195 GitVersion: fmt.Sprintf("v%s.%s.%s+%s", major, minor, patch, distro), 196 } 197 viper.Set(constant.CfgKeyServerInfo, ver) 198 } 199 200 // SetKubeServerVersion provides "_KUBE_SERVER_INFO" viper settings helper function. 201 func SetKubeServerVersion(major, minor, patch string) { 202 ver := version.Info{ 203 Major: major, 204 Minor: minor, 205 GitVersion: fmt.Sprintf("v%s.%s.%s", major, minor, patch), 206 } 207 viper.Set(constant.CfgKeyServerInfo, ver) 208 }