github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/testutil/apps/base_factory.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 apps 21 22 import ( 23 "context" 24 "reflect" 25 26 "github.com/onsi/gomega" 27 appsv1 "k8s.io/api/apps/v1" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "sigs.k8s.io/controller-runtime/pkg/client" 30 31 "github.com/1aal/kubeblocks/pkg/constant" 32 intctrlutil "github.com/1aal/kubeblocks/pkg/generics" 33 "github.com/1aal/kubeblocks/pkg/testutil" 34 ) 35 36 // Manipulate common attributes here to save boilerplate code 37 38 type BaseFactory[T intctrlutil.Object, PT intctrlutil.PObject[T], F any] struct { 39 object PT 40 concreteFactory *F 41 } 42 43 func (factory *BaseFactory[T, PT, F]) Init(namespace, name string, obj PT, f *F) { 44 obj.SetNamespace(namespace) 45 obj.SetName(name) 46 if obj.GetLabels() == nil { 47 obj.SetLabels(map[string]string{}) 48 } 49 if obj.GetAnnotations() == nil { 50 obj.SetAnnotations(map[string]string{}) 51 } 52 factory.object = obj 53 factory.concreteFactory = f 54 } 55 56 func (factory *BaseFactory[T, PT, F]) Get() PT { 57 return factory.object 58 } 59 60 func (factory *BaseFactory[T, PT, F]) WithRandomName() *F { 61 key := GetRandomizedKey("", factory.object.GetName()) 62 factory.object.SetName(key.Name) 63 return factory.concreteFactory 64 } 65 66 func (factory *BaseFactory[T, PT, F]) AddLabels(keysAndValues ...string) *F { 67 factory.AddLabelsInMap(WithMap(keysAndValues...)) 68 return factory.concreteFactory 69 } 70 71 func (factory *BaseFactory[T, PT, F]) AddLabelsInMap(labels map[string]string) *F { 72 l := factory.object.GetLabels() 73 for k, v := range labels { 74 l[k] = v 75 } 76 factory.object.SetLabels(l) 77 return factory.concreteFactory 78 } 79 80 func (factory *BaseFactory[T, PT, F]) AddAppNameLabel(value string) *F { 81 return factory.AddLabels(constant.AppNameLabelKey, value) 82 } 83 84 func (factory *BaseFactory[T, PT, F]) AddAppInstanceLabel(value string) *F { 85 return factory.AddLabels(constant.AppInstanceLabelKey, value) 86 } 87 88 func (factory *BaseFactory[T, PT, F]) AddAppComponentLabel(value string) *F { 89 return factory.AddLabels(constant.KBAppComponentLabelKey, value) 90 } 91 92 func (factory *BaseFactory[T, PT, F]) AddAppManagedByLabel() *F { 93 return factory.AddLabels(constant.AppManagedByLabelKey, constant.AppName) 94 } 95 96 func (factory *BaseFactory[T, PT, F]) AddConsensusSetAccessModeLabel(value string) *F { 97 return factory.AddLabels(constant.ConsensusSetAccessModeLabelKey, value) 98 } 99 100 func (factory *BaseFactory[T, PT, F]) AddRoleLabel(value string) *F { 101 return factory.AddLabels(constant.RoleLabelKey, value) 102 } 103 104 func (factory *BaseFactory[T, PT, F]) AddAnnotations(keysAndValues ...string) *F { 105 factory.AddAnnotationsInMap(WithMap(keysAndValues...)) 106 return factory.concreteFactory 107 } 108 func (factory *BaseFactory[T, PT, F]) AddAnnotationsInMap(annotations map[string]string) *F { 109 a := factory.object.GetAnnotations() 110 for k, v := range annotations { 111 a[k] = v 112 } 113 factory.object.SetAnnotations(a) 114 return factory.concreteFactory 115 } 116 117 func (factory *BaseFactory[T, PT, F]) AddControllerRevisionHashLabel(value string) *F { 118 return factory.AddLabels(appsv1.ControllerRevisionHashLabelKey, value) 119 } 120 121 func (factory *BaseFactory[T, PT, F]) SetOwnerReferences(ownerAPIVersion string, ownerKind string, owner client.Object) *F { 122 // interface object needs to determine whether the value is nil. 123 // otherwise, nil pointer error may be reported. 124 if owner != nil && !reflect.ValueOf(owner).IsNil() { 125 t := true 126 factory.object.SetOwnerReferences([]metav1.OwnerReference{ 127 {APIVersion: ownerAPIVersion, Kind: ownerKind, Controller: &t, 128 BlockOwnerDeletion: &t, Name: owner.GetName(), UID: owner.GetUID()}, 129 }) 130 } 131 return factory.concreteFactory 132 } 133 134 func (factory *BaseFactory[T, PT, F]) AddFinalizers(finalizers []string) *F { 135 factory.object.SetFinalizers(finalizers) 136 return factory.concreteFactory 137 } 138 139 func (factory *BaseFactory[T, PT, F]) Apply(changeFn func(PT)) *F { 140 if changeFn != nil { 141 changeFn(factory.object) 142 } 143 return factory.concreteFactory 144 } 145 146 func (factory *BaseFactory[T, PT, F]) Create(testCtx *testutil.TestContext) *F { 147 gomega.Expect(testCtx.CreateObj(testCtx.Ctx, factory.Get())).Should(gomega.Succeed()) 148 return factory.concreteFactory 149 } 150 151 func (factory *BaseFactory[T, PT, F]) CheckedCreate(testCtx *testutil.TestContext) *F { 152 gomega.Expect(testCtx.CheckedCreateObj(testCtx.Ctx, factory.Get())).Should(gomega.Succeed()) 153 return factory.concreteFactory 154 } 155 156 func (factory *BaseFactory[T, PT, F]) CreateCli(ctx context.Context, cli client.Client) *F { 157 gomega.Expect(cli.Create(ctx, factory.Get())).Should(gomega.Succeed()) 158 return factory.concreteFactory 159 } 160 161 func (factory *BaseFactory[T, PT, F]) GetObject() PT { 162 return factory.object 163 }