github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/configuration/config_reconcile_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 configuration 21 22 import ( 23 appv1 "k8s.io/api/apps/v1" 24 corev1 "k8s.io/api/core/v1" 25 "sigs.k8s.io/controller-runtime/pkg/client" 26 27 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 28 workloads "github.com/1aal/kubeblocks/apis/workloads/v1alpha1" 29 "github.com/1aal/kubeblocks/controllers/apps/components" 30 cfgcore "github.com/1aal/kubeblocks/pkg/configuration/core" 31 intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil" 32 "github.com/1aal/kubeblocks/pkg/generics" 33 ) 34 35 type configSpecList []appsv1alpha1.ComponentConfigSpec 36 37 type configReconcileContext struct { 38 intctrlutil.ResourceFetcher[configReconcileContext] 39 40 Name string 41 MatchingLabels client.MatchingLabels 42 ConfigSpec *appsv1alpha1.ComponentConfigSpec 43 ConfigMap *corev1.ConfigMap 44 45 Containers []string 46 StatefulSets []appv1.StatefulSet 47 RSMList []workloads.ReplicatedStateMachine 48 Deployments []appv1.Deployment 49 50 ConfigConstraint *appsv1alpha1.ConfigConstraint 51 } 52 53 func newConfigReconcileContext(resourceCtx *intctrlutil.ResourceCtx, 54 cm *corev1.ConfigMap, 55 cc *appsv1alpha1.ConfigConstraint, 56 configSpecName string, 57 matchingLabels client.MatchingLabels) *configReconcileContext { 58 configContext := configReconcileContext{ 59 ConfigMap: cm, 60 ConfigConstraint: cc, 61 Name: configSpecName, 62 MatchingLabels: matchingLabels, 63 } 64 return configContext.Init(resourceCtx, &configContext) 65 } 66 67 func (l configSpecList) findByName(name string) *appsv1alpha1.ComponentConfigSpec { 68 for i := range l { 69 configSpec := &l[i] 70 if configSpec.Name == name { 71 return configSpec 72 } 73 } 74 return nil 75 } 76 77 func (c *configReconcileContext) GetRelatedObjects() error { 78 return c.Cluster(). 79 ClusterDef(). 80 ClusterVer(). 81 ClusterComponent(). 82 ClusterDefComponent(). 83 RSM(). 84 StatefulSet(). 85 Deployment(). 86 Complete() 87 } 88 89 func (c *configReconcileContext) StatefulSet() *configReconcileContext { 90 stsFn := func() (err error) { 91 dComp := c.ClusterDefComObj 92 if dComp == nil || dComp.WorkloadType == appsv1alpha1.Stateless || len(c.RSMList) != 0 { 93 return 94 } 95 96 c.StatefulSets, c.Containers, err = retrieveRelatedComponentsByConfigmap( 97 c.Client, 98 c.Context, 99 c.Name, 100 generics.StatefulSetSignature, 101 client.ObjectKeyFromObject(c.ConfigMap), 102 client.InNamespace(c.Namespace), 103 c.MatchingLabels) 104 return 105 } 106 return c.Wrap(stsFn) 107 } 108 109 func (c *configReconcileContext) RSM() *configReconcileContext { 110 stsFn := func() (err error) { 111 dComp := c.ClusterDefComObj 112 if dComp == nil { 113 return 114 } 115 c.RSMList, c.Containers, err = retrieveRelatedComponentsByConfigmap( 116 c.Client, 117 c.Context, 118 c.Name, 119 generics.RSMSignature, 120 client.ObjectKeyFromObject(c.ConfigMap), 121 client.InNamespace(c.Namespace), 122 c.MatchingLabels) 123 if err != nil { 124 return 125 } 126 127 // fix uid mismatch bug: convert rsm to sts 128 // NODE: all components use the StatefulSet 129 for _, rsm := range c.RSMList { 130 var stsObject appv1.StatefulSet 131 if err = c.Client.Get(c.Context, client.ObjectKeyFromObject(components.ConvertRSMToSTS(&rsm)), &stsObject); err != nil { 132 return 133 } 134 c.StatefulSets = append(c.StatefulSets, stsObject) 135 } 136 return 137 } 138 return c.Wrap(stsFn) 139 } 140 141 func (c *configReconcileContext) Deployment() *configReconcileContext { 142 deployFn := func() (err error) { 143 dComp := c.ClusterDefComObj 144 if dComp == nil || dComp.WorkloadType != appsv1alpha1.Stateless || len(c.RSMList) != 0 { 145 return 146 } 147 148 c.Deployments, c.Containers, err = retrieveRelatedComponentsByConfigmap( 149 c.Client, 150 c.Context, 151 c.Name, 152 generics.DeploymentSignature, 153 client.ObjectKeyFromObject(c.ConfigMap), 154 client.InNamespace(c.Namespace), 155 c.MatchingLabels) 156 return 157 } 158 return c.Wrap(deployFn) 159 } 160 161 func (c *configReconcileContext) Complete() (err error) { 162 err = c.Err 163 if err != nil { 164 return 165 } 166 167 var configSpecs configSpecList 168 if configSpecs, err = cfgcore.GetConfigTemplatesFromComponent( 169 c.clusterComponents(), 170 c.clusterDefComponents(), 171 c.clusterVerComponents(), 172 c.ComponentName); err != nil { 173 return 174 } 175 c.ConfigSpec = configSpecs.findByName(c.Name) 176 return 177 } 178 179 func (c *configReconcileContext) clusterComponents() []appsv1alpha1.ClusterComponentSpec { 180 return c.ClusterObj.Spec.ComponentSpecs 181 } 182 183 func (c *configReconcileContext) clusterDefComponents() []appsv1alpha1.ClusterComponentDefinition { 184 return c.ClusterDefObj.Spec.ComponentDefs 185 } 186 187 func (c *configReconcileContext) clusterVerComponents() []appsv1alpha1.ClusterComponentVersion { 188 if c.ClusterVerObj == nil { 189 return nil 190 } 191 return c.ClusterVerObj.Spec.ComponentVersions 192 }