github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/configuration/core/config_patch_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 25 "github.com/StudioSol/set" 26 "sigs.k8s.io/controller-runtime/pkg/log" 27 28 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 29 "github.com/1aal/kubeblocks/pkg/configuration/util" 30 "github.com/1aal/kubeblocks/pkg/unstructured" 31 ) 32 33 // CreateConfigPatch creates a patch for configuration files with different version. 34 func CreateConfigPatch(oldVersion, newVersion map[string]string, format appsv1alpha1.CfgFileFormat, keys []string, comparableAllFiles bool) (*ConfigPatchInfo, bool, error) { 35 var hasFilesUpdated = false 36 37 if comparableAllFiles && len(keys) > 0 { 38 hasFilesUpdated = checkExcludeConfigDifference(oldVersion, newVersion, keys) 39 } 40 41 cmKeySet := FromCMKeysSelector(keys) 42 patch, err := CreateMergePatch( 43 FromConfigData(oldVersion, cmKeySet), 44 FromConfigData(newVersion, cmKeySet), 45 CfgOption{ 46 CfgType: format, 47 Type: CfgTplType, 48 Log: log.FromContext(context.TODO()), 49 }) 50 return patch, hasFilesUpdated, err 51 } 52 53 func checkExcludeConfigDifference(oldVersion map[string]string, newVersion map[string]string, keys []string) bool { 54 keySet := set.NewLinkedHashSetString(keys...) 55 leftOldKey := util.Difference(util.ToSet(oldVersion), keySet) 56 leftNewKey := util.Difference(util.ToSet(newVersion), keySet) 57 58 if !util.EqSet(leftOldKey, leftNewKey) { 59 return true 60 } 61 62 for e := range leftOldKey.Iter() { 63 if oldVersion[e] != newVersion[e] { 64 return true 65 } 66 } 67 return false 68 } 69 70 func LoadRawConfigObject(data map[string]string, formatConfig *appsv1alpha1.FormatterConfig, keys []string) (map[string]unstructured.ConfigObject, error) { 71 r := make(map[string]unstructured.ConfigObject) 72 cmKeySet := FromCMKeysSelector(keys) 73 for key, val := range data { 74 if cmKeySet != nil && !cmKeySet.InArray(key) { 75 continue 76 } 77 configObject, err := FromConfigObject(key, val, formatConfig) 78 if err != nil { 79 return nil, err 80 } 81 r[key] = configObject 82 } 83 return r, nil 84 } 85 86 func FromConfigObject(name, config string, formatConfig *appsv1alpha1.FormatterConfig) (unstructured.ConfigObject, error) { 87 configObject, err := unstructured.LoadConfig(name, config, formatConfig.Format) 88 if err != nil { 89 return nil, err 90 } 91 if formatConfig.IniConfig != nil { 92 configObject = configObject.SubConfig(formatConfig.IniConfig.SectionName) 93 } 94 return configObject, nil 95 } 96 97 // TransformConfigFileToKeyValueMap transforms a config file in appsv1alpha1.CfgFileFormat format to a map in which the key is config name and the value is config value 98 // sectionName means the desired section of config file, such as [mysqld] section. 99 // If config file has no section structure, sectionName should be default to get all values in this config file. 100 func TransformConfigFileToKeyValueMap(fileName string, formatterConfig *appsv1alpha1.FormatterConfig, configData []byte) (map[string]string, error) { 101 oldData := map[string]string{ 102 fileName: "", 103 } 104 newData := map[string]string{ 105 fileName: string(configData), 106 } 107 keys := []string{fileName} 108 patchInfo, _, err := CreateConfigPatch(oldData, newData, formatterConfig.Format, keys, false) 109 if err != nil { 110 return nil, err 111 } 112 params := GenerateVisualizedParamsList(patchInfo, formatterConfig, nil) 113 result := make(map[string]string) 114 for _, param := range params { 115 if param.Key != fileName { 116 continue 117 } 118 for _, kv := range param.Parameters { 119 if kv.Value != nil { 120 result[kv.Key] = *kv.Value 121 } 122 } 123 } 124 return result, nil 125 }