github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controller/builder/builder_base.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 builder 21 22 import ( 23 "reflect" 24 25 appsv1 "k8s.io/api/apps/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/types" 28 "sigs.k8s.io/controller-runtime/pkg/client" 29 30 intctrlutil "github.com/1aal/kubeblocks/pkg/generics" 31 ) 32 33 // TODO(free6om): a copy(and updated) of testutil.apps.base_factory, should make this as a common util both used by builder and testing 34 // Manipulate common attributes here to save boilerplate code 35 36 type BaseBuilder[T intctrlutil.Object, PT intctrlutil.PObject[T], B any] struct { 37 object PT 38 concreteBuilder *B 39 } 40 41 func (builder *BaseBuilder[T, PT, B]) init(namespace, name string, obj PT, b *B) { 42 obj.SetNamespace(namespace) 43 obj.SetName(name) 44 builder.object = obj 45 builder.concreteBuilder = b 46 } 47 48 func (builder *BaseBuilder[T, PT, B]) get() PT { 49 return builder.object 50 } 51 52 func (builder *BaseBuilder[T, PT, B]) SetName(name string) *B { 53 builder.object.SetName(name) 54 return builder.concreteBuilder 55 } 56 57 func (builder *BaseBuilder[T, PT, B]) SetUID(uid types.UID) *B { 58 builder.object.SetUID(uid) 59 return builder.concreteBuilder 60 } 61 62 func (builder *BaseBuilder[T, PT, B]) AddLabels(keysAndValues ...string) *B { 63 builder.AddLabelsInMap(WithMap(keysAndValues...)) 64 return builder.concreteBuilder 65 } 66 67 func (builder *BaseBuilder[T, PT, B]) AddLabelsInMap(labels map[string]string) *B { 68 if len(labels) == 0 { 69 return builder.concreteBuilder 70 } 71 l := builder.object.GetLabels() 72 if l == nil { 73 l = make(map[string]string, 0) 74 } 75 for k, v := range labels { 76 l[k] = v 77 } 78 builder.object.SetLabels(l) 79 return builder.concreteBuilder 80 } 81 82 func (builder *BaseBuilder[T, PT, B]) AddAnnotations(keysAndValues ...string) *B { 83 builder.AddAnnotationsInMap(WithMap(keysAndValues...)) 84 return builder.concreteBuilder 85 } 86 func (builder *BaseBuilder[T, PT, B]) AddAnnotationsInMap(annotations map[string]string) *B { 87 if len(annotations) == 0 { 88 return builder.concreteBuilder 89 } 90 a := builder.object.GetAnnotations() 91 if a == nil { 92 a = make(map[string]string, 0) 93 } 94 for k, v := range annotations { 95 a[k] = v 96 } 97 builder.object.SetAnnotations(a) 98 return builder.concreteBuilder 99 } 100 101 func (builder *BaseBuilder[T, PT, B]) AddControllerRevisionHashLabel(value string) *B { 102 return builder.AddLabels(appsv1.ControllerRevisionHashLabelKey, value) 103 } 104 105 func (builder *BaseBuilder[T, PT, B]) SetOwnerReferences(ownerAPIVersion string, ownerKind string, owner client.Object) *B { 106 // interface object needs to determine whether the value is nil. 107 // otherwise, nil pointer error may be reported. 108 if owner != nil && !reflect.ValueOf(owner).IsNil() { 109 t := true 110 builder.object.SetOwnerReferences([]metav1.OwnerReference{ 111 {APIVersion: ownerAPIVersion, Kind: ownerKind, Controller: &t, 112 BlockOwnerDeletion: &t, Name: owner.GetName(), UID: owner.GetUID()}, 113 }) 114 } 115 return builder.concreteBuilder 116 } 117 118 func (builder *BaseBuilder[T, PT, B]) AddFinalizers(finalizers []string) *B { 119 builder.object.SetFinalizers(finalizers) 120 return builder.concreteBuilder 121 } 122 123 func (builder *BaseBuilder[T, PT, B]) GetObject() PT { 124 return builder.object 125 } 126 127 func WithMap(keysAndValues ...string) map[string]string { 128 // ignore mismatching for kvs 129 m := make(map[string]string, len(keysAndValues)/2) 130 for i := 0; i+1 < len(keysAndValues); i += 2 { 131 m[keysAndValues[i]] = keysAndValues[i+1] 132 } 133 return m 134 }