config.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. package config
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "os"
  8. "strings"
  9. "time"
  10. "github.com/fsnotify/fsnotify"
  11. "go.etcd.io/etcd/client"
  12. )
  13. var Conf *Configure
  14. const ConfigPath = "conf/common.json"
  15. // 容联云配置
  16. type RongLianNode struct {
  17. RongLianSid string `json:"rong_lian_sid"`
  18. RongLianToken string `json:"rong_lian_token"`
  19. RongLianServerIp string `json:"rong_lian_server_ip"`
  20. RongLianServerPort string `json:"rong_lian_server_port"`
  21. RongLianSoftVersion string `json:"rong_lian_soft_version"`
  22. RongLianAppId string `json:"rong_lian_app_id"`
  23. ClVCodeTemplateId string `json:"cl_v_code_template_id"`
  24. BillNotifyTemplateId json.Number `json:"bill_notify_template_id"`
  25. }
  26. // mysql 配置
  27. type MysqlConfig struct {
  28. User string `json:"user"`
  29. Password string `json:"password"`
  30. Addr string `json:"addr"`
  31. DefaultDB string `json:"default_db"`
  32. Charset string `json:"charset"`
  33. MaxIdle json.Number `json:"max_idle"`
  34. MaxConn json.Number `json:"max_conn"`
  35. ServiceName string `json:"service_name"`
  36. ServicePort int `json:"service_port"`
  37. }
  38. type ThirdPartConfig struct {
  39. EdAppId string `json:"ed_app_id"` //eds16787f343c1676853
  40. EdAppSecret string `json:"ed_app_secret"` //3d3f47bef850c5a2b0c15d4b94b6b3a3
  41. C300Token string `json:"c_300_token"` //be318b5cf56c65e9172b8636699fcf17
  42. ArcbangAppId string `json:"arcbang_app_id"` //476795160986910721
  43. ArcbangAppKey string `json:"arcbang_app_key"` //897c86f2779341e88e38b3eb9acb384f
  44. NjKey string `json:"nj_key"` //E78E1F76-A9FE-4687-A3EB-198B7628D959
  45. NjEncKey string `json:"nj_enc_key"` //yfctct5X
  46. DbDwkey string `json:"db_dwkey"` //chejinjia
  47. DbToken string `json:"db_token"` //chejinjia2017030
  48. DbEncKey string `json:"db_enc_key"` //91724890
  49. ScViolationDwkey string `json:"sc_violation_dwkey"` //be2hjdeii1f90c5c55bfa0af7
  50. ScViolationToken string `json:"sc_violation_token"` //be2hjdeii1f90c5c55bfa0af7
  51. ScViolationEncKey string `json:"sc_violation_enc_key"` //33725169
  52. MojiAppKey string `json:"moji_app_key"` //25270402
  53. MojiAppSecret string `json:"moji_app_secret"` //bc1ec844f9a516919c85c09b1c75d682
  54. MojiAppCode string `json:"moji_app_code"` //fd4df24553a04d08a71a2566203a37db
  55. LcbAppCode string `json:"lcb_app_code"` //3101
  56. LcbSecret string `json:"lcb_secret"` //b9b548a34220f097e6c22ca933f76a8e
  57. JhAppKey string `json:"jh_app_key"` //1ef0aa20c3d4cbe71f4a799122625bb9
  58. ZxCompanyKey string `json:"zx_company_key"` //001061808271603202J1I3Q1H0T2L
  59. ZxCompanyCode string `json:"zx_company_code"` //65db6e13ecef31a54642df747986472a
  60. MsToken string `json:"ms_token"` //81ed9993bcad8cd0d1f55f9565104b76
  61. CheCheMd5Key string `json:"che_che_md5_key"` //e10adc3949ba59abbe56e057f20f883e
  62. CheCheAid string `json:"che_che_aid"` //78900
  63. CheCheMid string `json:"che_che_mid"` //78900
  64. LeCheAppCode string `json:"le_che_app_code"`
  65. LeCheSecret string `json:"le_che_secret"`
  66. BiHuAgent string `json:"bi_hu_agent"`
  67. BiHuSecret string `json:"bi_hu_secret"`
  68. CxyUserName string `json:"cxy_user_name"` //yiborantest
  69. CxyUserPasswd string `json:"cxy_user_passwd"` //EC26E0A72785474884D04EC4ADA8837B
  70. Dwkey string `json:"dwkey"` //wdhyiylhotoabycqtq
  71. Token string `json:"token"` //OBYLOIYOKUOKULLUIUOLJKU
  72. EncKey string `json:"enc_key"` //91724890
  73. LeCheCallBackUrl string `json:"le_che_call_back_url"`
  74. XiaomaApiKey string `json:"xiaoma_api_key"`
  75. ZqyKey string `json:"zqy_key"` //CETRo4r-KIkk05-uoyiE-20V7NU-Ab36
  76. ZhUser string `json:"zh_user"` //tangmimi
  77. ZhPwd string `json:"zh_pwd"` //E37A41FE3B1843E1AC46E6589CD76412
  78. ZjtAuthorizationCode string `json:"zjt_authorization_code"` //LkPw8252672h4NmF
  79. ZjtCryptoKey string `json:"zjt_crypto_key"` //Wuz2162IF9O60X58
  80. ZjtUserNo string `json:"zjt_user_no"` //SYZNCQCAR
  81. HystrixPublishChannel string `json:"hystrix_publish_channel"`
  82. RongLian RongLianNode `json:"rong_lian"`
  83. //DingDing DingDingConfig `json:"ding_ding"`
  84. RobotUrl string `json:"robot_url"`
  85. }
  86. // redis 配置
  87. type RedisConfig struct {
  88. Addrs string `json:"addrs"`
  89. Password string `json:"password"`
  90. DefaultDB json.Number `json:"default_db"`
  91. PoolSize json.Number `json:"pool_size"`
  92. MinIdleConns json.Number `json:"min_idle_conns"`
  93. MaxRetries json.Number `json:"max_retries"`
  94. IsCluster string `json:"is_cluster"`
  95. }
  96. type ElasticConfig struct {
  97. Addr string `json:"addr"`
  98. Sniff string `json:"sniff"`
  99. }
  100. type LogConfig struct {
  101. MaxSize json.Number `json:"max_size"`
  102. MaxBackups json.Number `json:"max_backups"`
  103. MaxAge json.Number `json:"max_age"`
  104. DisableStacktrace string `json:"disable_stacktrace"`
  105. }
  106. type RPCNode struct {
  107. Scheme string `json:"scheme"`
  108. Name string `json:"name"`
  109. UpdateInterval json.Number `json:"update_interval"`
  110. MysqlDB string `json:"mysql_db"`
  111. RedisDB json.Number `json:"redis_db"`
  112. Log LogConfig `json:"log"`
  113. ServiceName string `json:"service_name"`
  114. ServicePort json.Number `json:"service_port"`
  115. }
  116. type RPCConfig struct {
  117. BasePath string `json:"base_path"`
  118. Service RPCNode `json:"gd_service"`
  119. Vehicle RPCNode `json:"gd_vehicle"`
  120. Management RPCNode `json:"gd_management"`
  121. AccessLog RPCNode `json:"gd_access_log"`
  122. }
  123. type RateLimitConf struct {
  124. RateLimitChannel string `json:"rate_limit_channel"`
  125. }
  126. type OssConfig struct {
  127. DefaultSeriesImage string `json:"default_series_image"`
  128. SeriesImage string `json:"series_image"`
  129. Bucket string `json:"bucket"`
  130. EndPoint string `json:"end_point"`
  131. AccessKeyId string `json:"access_key_id"`
  132. AccessKeySecret string `json:"access_key_secret"`
  133. UploadBucket string `json:"upload_bucket"`
  134. }
  135. // dingding 配置
  136. type DingDingConfig struct {
  137. AccessToken string `json:"access_token"`
  138. Secret string `json:"secret"`
  139. }
  140. type WarningConfig struct {
  141. DefaultMails string `json:"default_mails"`
  142. MailHost string `json:"mail_host"`
  143. MailPassword string `json:"mail_password"`
  144. MailUser string `json:"mail_user"`
  145. }
  146. type Configure struct {
  147. RunMode string `json:"run_mode"`
  148. AppKey string `json:"app_key"`
  149. AppSecret string `json:"app_secret"`
  150. Mysql MysqlConfig `json:"mysql"`
  151. Redis RedisConfig `json:"redis"`
  152. Elastic ElasticConfig `json:"elastic"`
  153. Rpc RPCConfig `json:"rpc"`
  154. GdApiAppKey string `json:"gd_api_app_key"`
  155. GdApiAppSecret string `json:"gd_api_app_secret"`
  156. GdApiHost string `json:"gd_api_host"`
  157. GdInnerAccount string `json:"gd_inner_account"`
  158. GdLicenseOcrUrl string `json:"gd_license_ocr_url"`
  159. GdPlateOcrUrl string `json:"gd_plate_ocr_url"`
  160. ThirdPart ThirdPartConfig `json:"third_part"`
  161. OrderExpireMinute json.Number `json:"order_expire_minute"`
  162. RateLimit RateLimitConf `json:"rate_limit"`
  163. Oss OssConfig `json:"oss"`
  164. OrderConfirmTime json.Number `json:"order_confirm_time"`
  165. Warning WarningConfig `json:warning`
  166. }
  167. func watchEtcd(keysAPI client.KeysAPI, index uint64, runmode, key string, cli client.Client) {
  168. basePath := fmt.Sprintf("/%s/config", runmode)
  169. watcherOptions := &client.WatcherOptions{
  170. AfterIndex: index,
  171. Recursive: true,
  172. }
  173. watcher := keysAPI.Watcher(basePath, watcherOptions)
  174. for {
  175. r, err := watcher.Next(context.Background())
  176. if err != nil || r == nil {
  177. break
  178. }
  179. if r.Node != nil && r.PrevNode != nil {
  180. if r.Node.Key == r.PrevNode.Key && (r.Node.Value != r.PrevNode.Value) {
  181. reloadEtcd(runmode, key, cli)
  182. }
  183. }
  184. if r.Node != nil && r.PrevNode == nil {
  185. reloadEtcd(runmode, key, cli)
  186. }
  187. }
  188. }
  189. func reloadEtcd(runmode, key string, cli client.Client) {
  190. keysAPI := client.NewKeysAPI(cli)
  191. basePath := fmt.Sprintf("/%s/config", runmode)
  192. if resp, err := keysAPI.Get(context.Background(), basePath, &client.GetOptions{
  193. Recursive: true,
  194. }); err == nil && resp != nil && resp.Node != nil {
  195. conf := &Configure{}
  196. value := getNodeData(key, resp.Node)
  197. if jsonStr, err := json.Marshal(value); err == nil {
  198. if err := json.Unmarshal(jsonStr, &conf); err == nil {
  199. *Conf = *conf
  200. return
  201. } else {
  202. fmt.Printf("json Unmarshal failed. error:%s", err)
  203. }
  204. } else {
  205. fmt.Printf("json Marshal failed. error:%s", err)
  206. }
  207. } else {
  208. fmt.Printf("get %s failed. error:%s", basePath, err)
  209. }
  210. }
  211. // key 为加密密钥
  212. func GetConfig(runmode, key string, cli client.Client) *Configure {
  213. keysAPI := client.NewKeysAPI(cli)
  214. fmt.Printf("a1\n")
  215. basePath := fmt.Sprintf("/%s/config", runmode)
  216. fmt.Printf("a2\n")
  217. if resp, err := keysAPI.Get(context.Background(), basePath, &client.GetOptions{
  218. Recursive: true,
  219. }); err == nil && resp != nil && resp.Node != nil {
  220. Conf = &Configure{}
  221. value := getNodeData(key, resp.Node)
  222. if jsonStr, err := json.Marshal(value); err == nil {
  223. if err := json.Unmarshal(jsonStr, &Conf); err == nil {
  224. go watchEtcd(keysAPI, resp.Index, runmode, key, cli)
  225. return Conf
  226. } else {
  227. fmt.Printf("json Unmarshal failed. error:%s", err)
  228. }
  229. } else {
  230. fmt.Printf("json Marshal failed. error:%s", err)
  231. }
  232. } else {
  233. fmt.Printf("a3\n")
  234. fmt.Printf("get %s failed. error:%s", basePath, err)
  235. os.Exit(1)
  236. }
  237. return nil
  238. }
  239. // 递归取出node的叶子节点值
  240. func getNodeData(key string, head *client.Node) (value interface{}) {
  241. s0 := strings.Split(head.Key, "/")
  242. len0 := len(s0)
  243. if len0 == 0 {
  244. return
  245. }
  246. if head.Dir {
  247. mapData := map[string]interface{}{}
  248. for _, node := range head.Nodes {
  249. s1 := strings.Split(node.Key, "/")
  250. len1 := len(s1)
  251. if len1 == 0 {
  252. break
  253. }
  254. mapData[s1[len1-1]] = getNodeData(key, node)
  255. }
  256. value = mapData
  257. } else {
  258. if key != "" && head.Value != "" {
  259. if bytesData, err := Base64URLDecode(head.Value); err != nil {
  260. fmt.Printf("Base64URLDecode(%s) failed. error:%s", head.Value, err)
  261. os.Exit(1)
  262. } else {
  263. if data, err := AesDecrypt(bytesData, []byte(key)); err != nil {
  264. fmt.Printf("AesDecrypt failed. error:%s", err)
  265. os.Exit(1)
  266. } else {
  267. value = string(data)
  268. }
  269. }
  270. } else {
  271. // 无加密,直接取值
  272. value = head.Value
  273. }
  274. }
  275. return
  276. }
  277. // 适配k8s 方式
  278. // 公共配置会以configmap的方式映射到容器的conf/common.json中
  279. func GetConfigForK8s() *Configure {
  280. buffer, err := ioutil.ReadFile(ConfigPath)
  281. if err != nil {
  282. fmt.Printf("get %s failed. error:%s", ConfigPath, err)
  283. return nil
  284. }
  285. Conf = &Configure{}
  286. if err := json.Unmarshal(buffer, Conf); err != nil {
  287. fmt.Printf("json Unmarshal failed. error:%s", err)
  288. return nil
  289. }
  290. go watchConfigFileForK8s()
  291. return Conf
  292. }
  293. func ReloadConfigForK8s() {
  294. buffer, err := ioutil.ReadFile(ConfigPath)
  295. if err != nil {
  296. fmt.Printf("get %s failed. error:%s", ConfigPath, err)
  297. }
  298. confTmp := &Configure{}
  299. if err := json.Unmarshal(buffer, confTmp); err != nil {
  300. fmt.Printf("json Unmarshal failed. error:%s", err)
  301. }
  302. Conf = confTmp
  303. }
  304. // 判断路径文件/文件夹是否存在
  305. func Exists(path string) bool {
  306. _, err := os.Stat(path)
  307. if err != nil {
  308. if os.IsExist(err) {
  309. return true
  310. }
  311. return false
  312. }
  313. return true
  314. }
  315. func watchConfigFileForK8s() {
  316. fileExist := true
  317. watch, err := fsnotify.NewWatcher()
  318. if err != nil {
  319. fmt.Printf("new file watcher failed\n\n")
  320. os.Exit(1)
  321. }
  322. defer watch.Close()
  323. /*err = watch.Add(ConfigPath)
  324. if err != nil {
  325. fmt.Printf("add file watcher failed\n\n")
  326. os.Exit(1)
  327. }*/
  328. for {
  329. // 判断文件是否存在
  330. if !Exists(ConfigPath) {
  331. time.Sleep(10 * time.Second)
  332. fileExist = false
  333. continue
  334. } else {
  335. watch.Remove(ConfigPath)
  336. watch.Add(ConfigPath)
  337. if !fileExist { // 文件重新创建
  338. ReloadConfigForK8s()
  339. }
  340. fileExist = true
  341. }
  342. select {
  343. case ev := <-watch.Events:
  344. {
  345. fmt.Println("op : ", ev.Op)
  346. ReloadConfigForK8s()
  347. }
  348. case err := <-watch.Errors:
  349. {
  350. fmt.Println("error : ", err)
  351. continue
  352. }
  353. }
  354. }
  355. }