github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/cmd/cluster/config_resource.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 cluster 21 22 import ( 23 corev1 "k8s.io/api/core/v1" 24 "k8s.io/client-go/dynamic" 25 "sigs.k8s.io/controller-runtime/pkg/client" 26 27 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 28 "github.com/1aal/kubeblocks/pkg/cli/types" 29 "github.com/1aal/kubeblocks/pkg/cli/util" 30 "github.com/1aal/kubeblocks/pkg/configuration/core" 31 ) 32 33 type configSpecsType []*configSpecMeta 34 35 type configSpecMeta struct { 36 Spec appsv1alpha1.ComponentTemplateSpec 37 ConfigMap *corev1.ConfigMap 38 39 ConfigSpec *appsv1alpha1.ComponentConfigSpec 40 ConfigConstraint *appsv1alpha1.ConfigConstraint 41 } 42 43 type ConfigRelatedObjects struct { 44 Cluster *appsv1alpha1.Cluster 45 ClusterDef *appsv1alpha1.ClusterDefinition 46 ClusterVersion *appsv1alpha1.ClusterVersion 47 48 ConfigSpecs map[string]configSpecsType 49 } 50 51 type configObjectsWrapper struct { 52 namespace string 53 clusterName string 54 components []string 55 56 err error 57 cli dynamic.Interface 58 } 59 60 func (c configSpecsType) findByName(name string) *configSpecMeta { 61 for _, spec := range c { 62 if spec.Spec.Name == name { 63 return spec 64 } 65 } 66 return nil 67 } 68 69 func (c configSpecsType) listConfigSpecs(ccFilter bool) []string { 70 var names []string 71 for _, spec := range c { 72 if spec.ConfigSpec != nil && (!ccFilter || spec.ConfigConstraint != nil) { 73 names = append(names, spec.Spec.Name) 74 } 75 } 76 return names 77 } 78 79 func New(clusterName string, namespace string, cli dynamic.Interface, component ...string) *configObjectsWrapper { 80 return &configObjectsWrapper{namespace, clusterName, component, nil, cli} 81 } 82 83 func (w *configObjectsWrapper) GetObjects() (*ConfigRelatedObjects, error) { 84 objects := &ConfigRelatedObjects{} 85 err := w.cluster(objects). 86 clusterDefinition(objects). 87 clusterVersion(objects). 88 configSpecsObjects(objects). 89 finish() 90 if err != nil { 91 return nil, err 92 } 93 return objects, nil 94 } 95 96 func (w *configObjectsWrapper) configMap(specName string, component string, out *configSpecMeta) *configObjectsWrapper { 97 fn := func() error { 98 key := client.ObjectKey{ 99 Namespace: w.namespace, 100 Name: core.GetComponentCfgName(w.clusterName, component, specName), 101 } 102 out.ConfigMap = &corev1.ConfigMap{} 103 return util.GetResourceObjectFromGVR(types.ConfigmapGVR(), key, w.cli, out.ConfigMap) 104 } 105 return w.objectWrapper(fn) 106 } 107 108 func (w *configObjectsWrapper) configConstraint(specName string, out *configSpecMeta) *configObjectsWrapper { 109 fn := func() error { 110 if specName == "" { 111 return nil 112 } 113 key := client.ObjectKey{ 114 Namespace: "", 115 Name: specName, 116 } 117 out.ConfigConstraint = &appsv1alpha1.ConfigConstraint{} 118 return util.GetResourceObjectFromGVR(types.ConfigConstraintGVR(), key, w.cli, out.ConfigConstraint) 119 } 120 return w.objectWrapper(fn) 121 } 122 123 func (w *configObjectsWrapper) cluster(objects *ConfigRelatedObjects) *configObjectsWrapper { 124 fn := func() error { 125 clusterKey := client.ObjectKey{ 126 Namespace: w.namespace, 127 Name: w.clusterName, 128 } 129 objects.Cluster = &appsv1alpha1.Cluster{} 130 if err := util.GetResourceObjectFromGVR(types.ClusterGVR(), clusterKey, w.cli, objects.Cluster); err != nil { 131 return makeClusterNotExistErr(w.clusterName) 132 } 133 return nil 134 } 135 return w.objectWrapper(fn) 136 } 137 138 func (w *configObjectsWrapper) clusterVersion(objects *ConfigRelatedObjects) *configObjectsWrapper { 139 fn := func() error { 140 clusterVerName := objects.Cluster.Spec.ClusterVersionRef 141 if clusterVerName == "" { 142 return nil 143 } 144 clusterVerKey := client.ObjectKey{ 145 Namespace: "", 146 Name: clusterVerName, 147 } 148 objects.ClusterVersion = &appsv1alpha1.ClusterVersion{} 149 return util.GetResourceObjectFromGVR(types.ClusterVersionGVR(), clusterVerKey, w.cli, objects.ClusterVersion) 150 } 151 return w.objectWrapper(fn) 152 } 153 154 func (w *configObjectsWrapper) clusterDefinition(objects *ConfigRelatedObjects) *configObjectsWrapper { 155 fn := func() error { 156 clusterVerKey := client.ObjectKey{ 157 Namespace: "", 158 Name: objects.Cluster.Spec.ClusterDefRef, 159 } 160 objects.ClusterDef = &appsv1alpha1.ClusterDefinition{} 161 return util.GetResourceObjectFromGVR(types.ClusterDefGVR(), clusterVerKey, w.cli, objects.ClusterDef) 162 } 163 return w.objectWrapper(fn) 164 } 165 166 func (w *configObjectsWrapper) configSpecsObjects(objects *ConfigRelatedObjects) *configObjectsWrapper { 167 fn := func() error { 168 components := w.components 169 if len(components) == 0 { 170 components = getComponentNames(objects.Cluster) 171 } 172 configSpecs := make(map[string]configSpecsType, len(components)) 173 for _, component := range components { 174 componentConfigSpecs, err := w.genConfigSpecs(objects, component) 175 if err != nil { 176 return err 177 } 178 componentScriptsSpecs, err := w.genScriptsSpecs(objects, component) 179 if err != nil { 180 return err 181 } 182 configSpecs[component] = append(componentConfigSpecs, componentScriptsSpecs...) 183 } 184 objects.ConfigSpecs = configSpecs 185 return nil 186 } 187 return w.objectWrapper(fn) 188 } 189 190 func (w *configObjectsWrapper) finish() error { 191 return w.err 192 } 193 194 func (w *configObjectsWrapper) genScriptsSpecs(objects *ConfigRelatedObjects, component string) ([]*configSpecMeta, error) { 195 cComponent := objects.Cluster.Spec.GetComponentByName(component) 196 if cComponent == nil { 197 return nil, core.MakeError("not found component %s in cluster %s", component, objects.Cluster.Name) 198 } 199 dComponent := objects.ClusterDef.GetComponentDefByName(cComponent.ComponentDefRef) 200 if dComponent == nil { 201 return nil, core.MakeError("not found component %s in cluster definition %s", component, objects.ClusterDef.Name) 202 } 203 configSpecMetas := make([]*configSpecMeta, 0) 204 for _, spec := range dComponent.ScriptSpecs { 205 meta, err := w.transformScriptsSpecMeta(spec, component) 206 if err != nil { 207 return nil, err 208 } 209 configSpecMetas = append(configSpecMetas, meta) 210 } 211 return configSpecMetas, nil 212 } 213 214 func (w *configObjectsWrapper) transformConfigSpecMeta(spec appsv1alpha1.ComponentConfigSpec, component string) (*configSpecMeta, error) { 215 specMeta := &configSpecMeta{ 216 Spec: spec.ComponentTemplateSpec, 217 ConfigSpec: spec.DeepCopy(), 218 } 219 err := w.configMap(spec.Name, component, specMeta). 220 configConstraint(spec.ConfigConstraintRef, specMeta). 221 finish() 222 if err != nil { 223 return nil, err 224 } 225 return specMeta, nil 226 } 227 228 func (w *configObjectsWrapper) transformScriptsSpecMeta(spec appsv1alpha1.ComponentTemplateSpec, component string) (*configSpecMeta, error) { 229 specMeta := &configSpecMeta{ 230 Spec: spec, 231 } 232 err := w.configMap(spec.Name, component, specMeta). 233 finish() 234 if err != nil { 235 return nil, err 236 } 237 return specMeta, nil 238 } 239 240 func (w *configObjectsWrapper) objectWrapper(fn func() error) *configObjectsWrapper { 241 if w.err != nil { 242 return w 243 } 244 w.err = fn() 245 return w 246 } 247 248 func (w *configObjectsWrapper) genConfigSpecs(objects *ConfigRelatedObjects, component string) ([]*configSpecMeta, error) { 249 var ( 250 ret []*configSpecMeta 251 252 cComponents = objects.Cluster.Spec.ComponentSpecs 253 dComponents = objects.ClusterDef.Spec.ComponentDefs 254 vComponents []appsv1alpha1.ClusterComponentVersion 255 ) 256 257 if objects.ClusterVersion != nil { 258 vComponents = objects.ClusterVersion.Spec.ComponentVersions 259 } 260 configSpecs, err := core.GetConfigTemplatesFromComponent(cComponents, dComponents, vComponents, component) 261 if err != nil { 262 return nil, err 263 } 264 for _, spec := range configSpecs { 265 meta, err := w.transformConfigSpecMeta(spec, component) 266 if err != nil { 267 return nil, err 268 } 269 ret = append(ret, meta) 270 } 271 return ret, nil 272 }