init.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package config
  2. import (
  3. "errors"
  4. "fmt"
  5. "dario.cat/mergo"
  6. "git.ikuban.com/server/yaml"
  7. "github.com/elliotchance/orderedmap/v3"
  8. "github.com/go-kratos/kratos/v2/config"
  9. )
  10. func Init(sources []Source, bc any) error {
  11. configSources := make([]config.Source, 0)
  12. sourceMap := orderedmap.NewOrderedMap[string, any]() // 有序map控制优先级
  13. for _, source := range sources {
  14. if !source.Validate() {
  15. continue
  16. }
  17. s, err := source.NewSource()
  18. if err != nil {
  19. return fmt.Errorf("%v, new source error: %v", source.String(), err)
  20. }
  21. kvs, err := s.Load()
  22. if err != nil {
  23. return fmt.Errorf("%v, source load error: %v", source.String(), err)
  24. }
  25. for _, v := range kvs {
  26. sourceMap.Set(v.Key, map[string]any{})
  27. }
  28. configSources = append(configSources, s)
  29. }
  30. if sourceMap.Len() == 0 {
  31. return errors.New("config source is empty")
  32. }
  33. c := config.New(
  34. config.WithSource(configSources...),
  35. config.WithDecoder(func(kv *config.KeyValue, v map[string]interface{}) error {
  36. ok := sourceMap.Has(kv.Key)
  37. if !ok {
  38. return errors.New("unknown config key")
  39. }
  40. next := map[string]any{}
  41. err := yaml.Unmarshal(kv.Value, next)
  42. if err != nil {
  43. return err
  44. }
  45. sourceMap.Set(kv.Key, convertMap(next))
  46. merged := make(map[string]any)
  47. for c := range sourceMap.Values() {
  48. err = mergo.Merge(&merged, c, mergo.WithOverride)
  49. if err != nil {
  50. return err
  51. }
  52. }
  53. b, err := yaml.Marshal(merged)
  54. if err != nil {
  55. return err
  56. }
  57. err = yaml.Unmarshal(b, bc)
  58. if err != nil {
  59. return err
  60. }
  61. return nil
  62. }),
  63. )
  64. if err := c.Load(); err != nil {
  65. return err
  66. }
  67. return nil
  68. }
  69. func convertMap(src interface{}) interface{} {
  70. switch m := src.(type) {
  71. case map[string]interface{}:
  72. dst := make(map[string]interface{}, len(m))
  73. for k, v := range m {
  74. dst[k] = convertMap(v)
  75. }
  76. return dst
  77. case map[interface{}]interface{}:
  78. dst := make(map[string]interface{}, len(m))
  79. for k, v := range m {
  80. dst[fmt.Sprint(k)] = convertMap(v)
  81. }
  82. return dst
  83. case []interface{}:
  84. dst := make([]interface{}, len(m))
  85. for k, v := range m {
  86. dst[k] = convertMap(v)
  87. }
  88. return dst
  89. case []byte:
  90. // there will be no binary data in the config data
  91. return string(m)
  92. default:
  93. return src
  94. }
  95. }