| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- package config
- import (
- "errors"
- "fmt"
- "dario.cat/mergo"
- "git.ikuban.com/server/yaml"
- "github.com/elliotchance/orderedmap/v3"
- "github.com/go-kratos/kratos/v2/config"
- )
- func Init(sources []Source, bc any) error {
- configSources := make([]config.Source, 0)
- sourceMap := orderedmap.NewOrderedMap[string, any]() // 有序map控制优先级
- for _, source := range sources {
- if !source.Validate() {
- continue
- }
- s, err := source.NewSource()
- if err != nil {
- return fmt.Errorf("%v, new source error: %v", source.String(), err)
- }
- kvs, err := s.Load()
- if err != nil {
- return fmt.Errorf("%v, source load error: %v", source.String(), err)
- }
- for _, v := range kvs {
- sourceMap.Set(v.Key, map[string]any{})
- }
- configSources = append(configSources, s)
- }
- if sourceMap.Len() == 0 {
- return errors.New("config source is empty")
- }
- c := config.New(
- config.WithSource(configSources...),
- config.WithDecoder(func(kv *config.KeyValue, v map[string]interface{}) error {
- ok := sourceMap.Has(kv.Key)
- if !ok {
- return errors.New("unknown config key")
- }
- next := map[string]any{}
- err := yaml.Unmarshal(kv.Value, next)
- if err != nil {
- return err
- }
- sourceMap.Set(kv.Key, convertMap(next))
- merged := make(map[string]any)
- for c := range sourceMap.Values() {
- err = mergo.Merge(&merged, c, mergo.WithOverride)
- if err != nil {
- return err
- }
- }
- b, err := yaml.Marshal(merged)
- if err != nil {
- return err
- }
- err = yaml.Unmarshal(b, bc)
- if err != nil {
- return err
- }
- return nil
- }),
- )
- if err := c.Load(); err != nil {
- return err
- }
- return nil
- }
- func convertMap(src interface{}) interface{} {
- switch m := src.(type) {
- case map[string]interface{}:
- dst := make(map[string]interface{}, len(m))
- for k, v := range m {
- dst[k] = convertMap(v)
- }
- return dst
- case map[interface{}]interface{}:
- dst := make(map[string]interface{}, len(m))
- for k, v := range m {
- dst[fmt.Sprint(k)] = convertMap(v)
- }
- return dst
- case []interface{}:
- dst := make([]interface{}, len(m))
- for k, v := range m {
- dst[k] = convertMap(v)
- }
- return dst
- case []byte:
- // there will be no binary data in the config data
- return string(m)
- default:
- return src
- }
- }
|