github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/configuration/core/config_util.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 core 21 22 import ( 23 "context" 24 "regexp" 25 "strings" 26 27 "github.com/spf13/cast" 28 "sigs.k8s.io/controller-runtime/pkg/client" 29 "sigs.k8s.io/controller-runtime/pkg/log" 30 31 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 32 cfgutil "github.com/1aal/kubeblocks/pkg/configuration/util" 33 ) 34 35 type ParamPairs struct { 36 Key string 37 UpdatedParams map[string]interface{} 38 } 39 40 const pattern = `^[a-z0-9A-Z]([a-zA-Z0-9\.\-\_]*[a-zA-Z0-9])?$` 41 42 var regxPattern = regexp.MustCompile(pattern) 43 44 func FromValueToString(val interface{}) string { 45 str := strings.Trim(cast.ToString(val), ` '"`) 46 if regxPattern.MatchString(str) { 47 return str 48 } 49 return "" 50 } 51 52 // MergeUpdatedConfig replaces the file content of the changed key. 53 // baseMap is the original configuration file, 54 // updatedMap is the updated configuration file 55 func MergeUpdatedConfig(baseMap, updatedMap map[string]string) map[string]string { 56 r := make(map[string]string) 57 for key, val := range baseMap { 58 r[key] = val 59 if v, ok := updatedMap[key]; ok { 60 r[key] = v 61 } 62 } 63 return r 64 } 65 66 // FromStringMap converts a map[string]string to a map[string]interface{} 67 func FromStringMap(m map[string]*string) map[string]interface{} { 68 r := make(map[string]interface{}, len(m)) 69 for key, v := range m { 70 if v != nil { 71 r[key] = *v 72 } else { 73 // delete config parameter if value is nil 74 r[key] = nil 75 } 76 } 77 return r 78 } 79 80 // FromStringPointerMap converts a map[string]string to a map[string]interface{} 81 func FromStringPointerMap(m map[string]string) map[string]*string { 82 r := make(map[string]*string, len(m)) 83 for key, v := range m { 84 r[key] = cfgutil.ToPointer(v) 85 } 86 return r 87 } 88 89 func ApplyConfigPatch(baseCfg []byte, updatedParameters map[string]*string, formatConfig *appsv1alpha1.FormatterConfig) (string, error) { 90 configLoaderOption := CfgOption{ 91 Type: CfgRawType, 92 Log: log.FromContext(context.TODO()), 93 CfgType: formatConfig.Format, 94 RawData: baseCfg, 95 } 96 configWrapper, err := NewConfigLoader(configLoaderOption) 97 if err != nil { 98 return "", err 99 } 100 101 mergedOptions := NewCfgOptions("", WithFormatterConfig(formatConfig)) 102 err = configWrapper.MergeFrom(FromStringMap(updatedParameters), mergedOptions) 103 if err != nil { 104 return "", err 105 } 106 mergedConfig := configWrapper.getConfigObject(mergedOptions) 107 return mergedConfig.Marshal() 108 } 109 110 func NeedReloadVolume(config appsv1alpha1.ComponentConfigSpec) bool { 111 // TODO distinguish between scripts and configuration 112 return config.ConfigConstraintRef != "" 113 } 114 115 func GetReloadOptions(cli client.Client, ctx context.Context, configSpecs []appsv1alpha1.ComponentConfigSpec) (*appsv1alpha1.ReloadOptions, *appsv1alpha1.FormatterConfig, error) { 116 for _, configSpec := range configSpecs { 117 if !NeedReloadVolume(configSpec) { 118 continue 119 } 120 ccKey := client.ObjectKey{ 121 Namespace: "", 122 Name: configSpec.ConfigConstraintRef, 123 } 124 cfgConst := &appsv1alpha1.ConfigConstraint{} 125 if err := cli.Get(ctx, ccKey, cfgConst); err != nil { 126 return nil, nil, WrapError(err, "failed to get ConfigConstraint, key[%v]", ccKey) 127 } 128 if cfgConst.Spec.ReloadOptions != nil { 129 return cfgConst.Spec.ReloadOptions, cfgConst.Spec.FormatterConfig, nil 130 } 131 } 132 return nil, nil, nil 133 } 134 135 func IsWatchModuleForShellTrigger(trigger *appsv1alpha1.ShellTrigger) bool { 136 if trigger == nil || trigger.Sync == nil { 137 return true 138 } 139 return !*trigger.Sync 140 } 141 142 func IsWatchModuleForTplTrigger(trigger *appsv1alpha1.TPLScriptTrigger) bool { 143 if trigger == nil || trigger.Sync == nil { 144 return true 145 } 146 return !*trigger.Sync 147 }