github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controllerutil/resource_wrapper.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 controllerutil 21 22 import ( 23 "context" 24 25 corev1 "k8s.io/api/core/v1" 26 "sigs.k8s.io/controller-runtime/pkg/client" 27 28 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 29 cfgcore "github.com/1aal/kubeblocks/pkg/configuration/core" 30 ) 31 32 type ResourceCtx struct { 33 context.Context 34 35 Err error 36 Client client.Client 37 38 Namespace string 39 ClusterName string 40 ComponentName string 41 } 42 43 type ResourceFetcher[T any] struct { 44 obj *T 45 *ResourceCtx 46 47 ClusterObj *appsv1alpha1.Cluster 48 ClusterDefObj *appsv1alpha1.ClusterDefinition 49 ClusterVerObj *appsv1alpha1.ClusterVersion 50 51 ConfigMapObj *corev1.ConfigMap 52 ConfigurationObj *appsv1alpha1.Configuration 53 ConfigConstraintObj *appsv1alpha1.ConfigConstraint 54 55 ClusterComObj *appsv1alpha1.ClusterComponentSpec 56 ClusterDefComObj *appsv1alpha1.ClusterComponentDefinition 57 ClusterVerComObj *appsv1alpha1.ClusterComponentVersion 58 } 59 60 func (r *ResourceFetcher[T]) Init(ctx *ResourceCtx, object *T) *T { 61 r.obj = object 62 r.ResourceCtx = ctx 63 return r.obj 64 } 65 66 func (r *ResourceFetcher[T]) Wrap(fn func() error) (ret *T) { 67 ret = r.obj 68 if r.Err != nil { 69 return 70 } 71 r.Err = fn() 72 return 73 } 74 75 func (r *ResourceFetcher[T]) Cluster() *T { 76 clusterKey := client.ObjectKey{ 77 Namespace: r.Namespace, 78 Name: r.ClusterName, 79 } 80 return r.Wrap(func() error { 81 r.ClusterObj = &appsv1alpha1.Cluster{} 82 return r.Client.Get(r.Context, clusterKey, r.ClusterObj) 83 }) 84 } 85 86 func (r *ResourceFetcher[T]) ClusterDef() *T { 87 clusterDefKey := client.ObjectKey{ 88 Namespace: "", 89 Name: r.ClusterObj.Spec.ClusterDefRef, 90 } 91 return r.Wrap(func() error { 92 r.ClusterDefObj = &appsv1alpha1.ClusterDefinition{} 93 return r.Client.Get(r.Context, clusterDefKey, r.ClusterDefObj) 94 }) 95 } 96 97 func (r *ResourceFetcher[T]) ClusterVer() *T { 98 clusterVerKey := client.ObjectKey{ 99 Namespace: "", 100 Name: r.ClusterObj.Spec.ClusterVersionRef, 101 } 102 return r.Wrap(func() error { 103 if clusterVerKey.Name == "" { 104 return nil 105 } 106 r.ClusterVerObj = &appsv1alpha1.ClusterVersion{} 107 return r.Client.Get(r.Context, clusterVerKey, r.ClusterVerObj) 108 }) 109 } 110 func (r *ResourceFetcher[T]) ClusterDefComponent() *T { 111 foundFn := func() (err error) { 112 if r.ClusterComObj == nil { 113 return 114 } 115 r.ClusterDefComObj = r.ClusterDefObj.GetComponentDefByName(r.ClusterComObj.ComponentDefRef) 116 return 117 } 118 return r.Wrap(foundFn) 119 } 120 121 func (r *ResourceFetcher[T]) ClusterVerComponent() *T { 122 foundFn := func() (err error) { 123 if r.ClusterComObj == nil || r.ClusterVerObj == nil { 124 return 125 } 126 components := r.ClusterVerObj.Spec.GetDefNameMappingComponents() 127 r.ClusterVerComObj = components[r.ClusterComObj.ComponentDefRef] 128 return 129 } 130 return r.Wrap(foundFn) 131 } 132 133 func (r *ResourceFetcher[T]) ClusterComponent() *T { 134 return r.Wrap(func() (err error) { 135 r.ClusterComObj = r.ClusterObj.Spec.GetComponentByName(r.ComponentName) 136 return 137 }) 138 } 139 140 func (r *ResourceFetcher[T]) Configuration() *T { 141 configKey := client.ObjectKey{ 142 Name: cfgcore.GenerateComponentConfigurationName(r.ClusterName, r.ComponentName), 143 Namespace: r.Namespace, 144 } 145 return r.Wrap(func() (err error) { 146 configuration := appsv1alpha1.Configuration{} 147 err = r.Client.Get(r.Context, configKey, &configuration) 148 if err != nil { 149 return client.IgnoreNotFound(err) 150 } 151 r.ConfigurationObj = &configuration 152 return 153 }) 154 } 155 156 func (r *ResourceFetcher[T]) ConfigMap(configSpec string) *T { 157 cmKey := client.ObjectKey{ 158 Name: cfgcore.GetComponentCfgName(r.ClusterName, r.ComponentName, configSpec), 159 Namespace: r.Namespace, 160 } 161 162 return r.Wrap(func() error { 163 r.ConfigMapObj = &corev1.ConfigMap{} 164 return r.Client.Get(r.Context, cmKey, r.ConfigMapObj) 165 }) 166 } 167 168 func (r *ResourceFetcher[T]) ConfigConstraints(ccName string) *T { 169 return r.Wrap(func() error { 170 if ccName != "" { 171 r.ConfigConstraintObj = &appsv1alpha1.ConfigConstraint{} 172 return r.Client.Get(r.Context, client.ObjectKey{Name: ccName}, r.ConfigConstraintObj) 173 } 174 return nil 175 }) 176 } 177 178 func (r *ResourceFetcher[T]) Complete() error { 179 return r.Err 180 } 181 182 type Fetcher struct { 183 ResourceFetcher[Fetcher] 184 } 185 186 func NewResourceFetcher(resourceCtx *ResourceCtx) *Fetcher { 187 f := &Fetcher{} 188 return f.Init(resourceCtx, f) 189 }