config.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. package config
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/fsnotify/fsnotify"
  7. "io/ioutil"
  8. "os"
  9. "strings"
  10. "time"
  11. "go.etcd.io/etcd/client"
  12. )
  13. var Conf *Configure
  14. const ConfigPath = "conf/common.json"
  15. // mysql 配置
  16. type MysqlConfig struct {
  17. User string `json:"user"`
  18. Password string `json:"password"`
  19. Addr string `json:"addr"`
  20. DefaultDB string `json:"default_db"`
  21. Charset string `json:"charset"`
  22. MaxIdle json.Number `json:"max_idle"`
  23. MaxConn json.Number `json:"max_conn"`
  24. }
  25. // redis 配置
  26. type RedisConfig struct {
  27. Addrs string `json:"addrs"`
  28. Password string `json:"password"`
  29. DefaultDB json.Number `json:"default_db"`
  30. PoolSize json.Number `json:"pool_size"`
  31. MinIdleConns json.Number `json:"min_idle_conns"`
  32. MaxRetries json.Number `json:"max_retries"`
  33. IsCluster string `json:"is_cluster"`
  34. }
  35. type ElasticConfig struct {
  36. Addr string `json:"addr"`
  37. Sniff string `json:"sniff"`
  38. }
  39. type LogConfig struct {
  40. MaxSize json.Number `json:"max_size"`
  41. MaxBackups json.Number `json:"max_backups"`
  42. MaxAge json.Number `json:"max_age"`
  43. Level string `json:"level"`
  44. DisableStacktrace string `json:"disable_stacktrace"`
  45. }
  46. type CGINode struct {
  47. Log LogConfig `json:"log"`
  48. TokenExpired json.Number `json:"token_expired"`
  49. ServiceName string `json:"service_name"`
  50. ServicePort json.Number `json:"service_port"`
  51. Name string `json:"name"`
  52. }
  53. type CGIConfig struct {
  54. GdGateway CGINode `json:"gd_gateway"`
  55. }
  56. type RPCNode struct {
  57. Scheme string `json:"scheme"`
  58. Name string `json:"name"`
  59. UpdateInterval json.Number `json:"update_interval"`
  60. Log LogConfig `json:"log"`
  61. ServiceName string `json:"service_name"`
  62. ServicePort json.Number `json:"service_port"`
  63. }
  64. type RPCConfig struct {
  65. BasePath string `json:"base_path"`
  66. Vehicle RPCNode `json:"gd_vehicle"`
  67. Service RPCNode `json:"gd_service"`
  68. AuthCheck RPCNode `json:"gd_auth_check"`
  69. AccessLog RPCNode `json:"gd_access_log"`
  70. Management RPCNode `json:"gd_management"`
  71. }
  72. type JwtConfig struct {
  73. }
  74. type Configure struct {
  75. RunMode string `json:"run_mode"`
  76. AppKey string `json:"app_key"`
  77. AppSecret string `json:"app_secret"`
  78. Mysql MysqlConfig `json:"mysql"`
  79. Redis RedisConfig `json:"redis"`
  80. Elastic ElasticConfig `json:"elastic"`
  81. Cgi CGIConfig `json:"cgi"`
  82. Rpc RPCConfig `json:"rpc"`
  83. }
  84. // key 为加密密钥
  85. func GetConfig(runmode, key string, cli client.Client) *Configure {
  86. keysAPI := client.NewKeysAPI(cli)
  87. basePath := fmt.Sprintf("/%s/config", runmode)
  88. if resp, err := keysAPI.Get(context.Background(), basePath, &client.GetOptions{
  89. Recursive: true,
  90. }); err == nil && resp != nil && resp.Node != nil {
  91. Conf = &Configure{}
  92. value := getNodeData(key, resp.Node)
  93. if jsonStr, err := json.Marshal(value); err == nil {
  94. if err := json.Unmarshal(jsonStr, &Conf); err == nil {
  95. return Conf
  96. } else {
  97. fmt.Printf("json Unmarshal failed. error:%s", err)
  98. }
  99. } else {
  100. fmt.Printf("json Marshal failed. error:%s", err)
  101. }
  102. } else {
  103. fmt.Printf("get %s failed. error:%s", basePath, err)
  104. os.Exit(1)
  105. }
  106. return nil
  107. }
  108. // 递归取出node的叶子节点值
  109. func getNodeData(key string, head *client.Node) (value interface{}) {
  110. s0 := strings.Split(head.Key, "/")
  111. len0 := len(s0)
  112. if len0 == 0 {
  113. return
  114. }
  115. if head.Dir {
  116. mapData := map[string]interface{}{}
  117. for _, node := range head.Nodes {
  118. s1 := strings.Split(node.Key, "/")
  119. len1 := len(s1)
  120. if len1 == 0 {
  121. break
  122. }
  123. mapData[s1[len1-1]] = getNodeData(key, node)
  124. }
  125. value = mapData
  126. } else {
  127. if key != "" && head.Value != "" {
  128. if bytesData, err := Base64URLDecode(head.Value); err != nil {
  129. fmt.Printf("Base64URLDecode(%s) failed. error:%s", head.Value, err)
  130. os.Exit(1)
  131. } else {
  132. if data, err := AesDecrypt(bytesData, []byte(key)); err != nil {
  133. fmt.Printf("AesDecrypt failed. error:%s", err)
  134. os.Exit(1)
  135. } else {
  136. value = string(data)
  137. }
  138. }
  139. } else {
  140. // 无加密,直接取值
  141. value = head.Value
  142. }
  143. }
  144. return
  145. }
  146. func GetConfigForK8s() *Configure {
  147. buffer, err := ioutil.ReadFile(ConfigPath)
  148. if err != nil {
  149. fmt.Printf("get %s failed. error:%s", ConfigPath, err)
  150. return nil
  151. }
  152. Conf = &Configure{}
  153. if err := json.Unmarshal(buffer, Conf); err != nil {
  154. fmt.Printf("json Unmarshal failed. error:%s", err)
  155. return nil
  156. }
  157. go watchConfigFileForK8s()
  158. return Conf
  159. }
  160. func ReloadConfigForK8s() {
  161. buffer, err := ioutil.ReadFile(ConfigPath)
  162. if err != nil {
  163. fmt.Printf("get %s failed. error:%s", ConfigPath, err)
  164. }
  165. confTmp := &Configure{}
  166. if err := json.Unmarshal(buffer, confTmp); err != nil {
  167. fmt.Printf("json Unmarshal failed. error:%s", err)
  168. }
  169. Conf = confTmp
  170. }
  171. // 判断路径文件/文件夹是否存在
  172. func Exists(path string) bool {
  173. _, err := os.Stat(path)
  174. if err != nil {
  175. if os.IsExist(err) {
  176. return true
  177. }
  178. return false
  179. }
  180. return true
  181. }
  182. func watchConfigFileForK8s() {
  183. fileExist := true
  184. watch, err := fsnotify.NewWatcher()
  185. if err != nil {
  186. fmt.Printf("new file watcher failed\n\n")
  187. os.Exit(1)
  188. }
  189. defer watch.Close()
  190. /*err = watch.Add(ConfigPath)
  191. if err != nil {
  192. fmt.Printf("add file watcher failed\n\n")
  193. os.Exit(1)
  194. }*/
  195. for {
  196. // 判断文件是否存在
  197. if !Exists(ConfigPath) {
  198. time.Sleep(10 * time.Second)
  199. fileExist = false
  200. continue
  201. } else {
  202. watch.Remove(ConfigPath)
  203. watch.Add(ConfigPath)
  204. if !fileExist { // 文件重新创建
  205. ReloadConfigForK8s()
  206. }
  207. fileExist = true
  208. }
  209. select {
  210. case ev := <-watch.Events:
  211. {
  212. fmt.Println("op : ", ev.Op)
  213. ReloadConfigForK8s()
  214. }
  215. case err := <-watch.Errors:
  216. {
  217. fmt.Println("error : ", err)
  218. continue
  219. }
  220. }
  221. }
  222. }