github.com/oam-dev/kubevela@v1.9.11/pkg/config/writer/writer.go (about) 1 /* 2 Copyright 2022 The KubeVela Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package writer 18 19 import ( 20 "context" 21 "encoding/json" 22 "fmt" 23 "reflect" 24 "strings" 25 26 "cuelang.org/go/cue" 27 28 "github.com/magiconair/properties" 29 "github.com/pelletier/go-toml" 30 "gopkg.in/yaml.v3" 31 "k8s.io/klog/v2" 32 33 "github.com/kubevela/workflow/pkg/cue/model/value" 34 35 icontext "github.com/oam-dev/kubevela/pkg/config/context" 36 "github.com/oam-dev/kubevela/pkg/cue/script" 37 ) 38 39 // ExpandedWriterConfig define the supported output ways. 40 type ExpandedWriterConfig struct { 41 Nacos *NacosConfig `json:"nacos"` 42 } 43 44 // ExpandedWriterData the data for the expanded writer 45 type ExpandedWriterData struct { 46 Nacos *NacosData `json:"nacos"` 47 } 48 49 // ConfigRef reference a config secret, it must be system scope. 50 type ConfigRef struct { 51 Name string `json:"name"` 52 Namespace string `json:"namespace"` 53 } 54 55 // ParseExpandedWriterConfig parse the expanded writer config from the template value 56 func ParseExpandedWriterConfig(template cue.Value) ExpandedWriterConfig { 57 var ewc = ExpandedWriterConfig{} 58 nacos := template.LookupPath(cue.ParsePath("nacos")) 59 if nacos.Exists() { 60 nacosConfig := &NacosConfig{} 61 if err := nacos.Decode(&nacosConfig); err != nil { 62 klog.Warningf("failed to decode the nacos config: %s", err.Error()) 63 } 64 ewc.Nacos = nacosConfig 65 } 66 // parse the other writer configs 67 return ewc 68 } 69 70 // RenderForExpandedWriter render the configuration for all expanded writers 71 func RenderForExpandedWriter(ewc ExpandedWriterConfig, template script.CUE, context icontext.ConfigRenderContext, properties map[string]interface{}) (*ExpandedWriterData, error) { 72 var ewd = ExpandedWriterData{} 73 var err error 74 if ewc.Nacos != nil { 75 ewd.Nacos, err = renderNacos(ewc.Nacos, template, context, properties) 76 if err != nil { 77 return nil, err 78 } 79 klog.Info("the config render to nacos context successfully") 80 } 81 return &ewd, nil 82 } 83 84 // Write write the config by the all writers 85 func Write(ctx context.Context, ewd *ExpandedWriterData, ri icontext.ReadConfigProvider) (list []error) { 86 if ewd.Nacos != nil { 87 if err := ewd.Nacos.write(ctx, ri); err != nil { 88 list = append(list, err) 89 } else { 90 klog.Info("the config write to the nacos successfully") 91 } 92 } 93 return 94 } 95 96 // encodingOutput support the json、toml、xml、properties and yaml formats. 97 func encodingOutput(input *value.Value, format string) ([]byte, error) { 98 var data = make(map[string]interface{}) 99 if err := input.UnmarshalTo(&data); err != nil { 100 return nil, err 101 } 102 switch strings.ToLower(format) { 103 case "json": 104 return json.Marshal(data) 105 case "toml": 106 return toml.Marshal(data) 107 case "properties": 108 var kv = map[string]string{} 109 if err := convertMap2PropertiesKV("", data, kv); err != nil { 110 return nil, err 111 } 112 return []byte(properties.LoadMap(kv).String()), nil 113 default: 114 return yaml.Marshal(data) 115 } 116 } 117 118 func convertMap2PropertiesKV(last string, input map[string]interface{}, result map[string]string) error { 119 120 interface2str := func(key string, v interface{}, result map[string]string) (string, error) { 121 switch t := v.(type) { 122 case string: 123 return t, nil 124 case bool: 125 return fmt.Sprintf("%t", t), nil 126 case int64, int, int32: 127 return fmt.Sprintf("%d", t), nil 128 case float64, float32: 129 return fmt.Sprintf("%v", t), nil 130 case map[string]interface{}: 131 if err := convertMap2PropertiesKV(key, t, result); err != nil { 132 return "", err 133 } 134 return "", nil 135 default: 136 return fmt.Sprintf("%v", t), nil 137 } 138 } 139 140 for k, v := range input { 141 key := k 142 if last != "" { 143 key = fmt.Sprintf("%s.%s", last, k) 144 } 145 switch t := v.(type) { 146 case string, bool, int64, int, int32, float32, float64, map[string]interface{}: 147 v, err := interface2str(key, t, result) 148 if err != nil { 149 return err 150 } 151 if v != "" { 152 result[key] = v 153 } 154 case []interface{}, []string, []int64, []float64, []map[string]interface{}: 155 var ints []string 156 s := reflect.ValueOf(t) 157 for i := 0; i < s.Len(); i++ { 158 re, err := interface2str(fmt.Sprintf("%s.%d", key, i), s.Index(i).Interface(), result) 159 if err != nil { 160 return err 161 } 162 if re != "" { 163 ints = append(ints, re) 164 } 165 } 166 if len(ints) > 0 { 167 result[key] = strings.Join(ints, ",") 168 } 169 default: 170 return fmt.Errorf("the value type of %s(%T) can not be supported", key, t) 171 } 172 } 173 return nil 174 }