init.go 2.7 KB

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