client_v2.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. package conf
  2. import (
  3. "bytes"
  4. "crypto/md5"
  5. "encoding/hex"
  6. "encoding/json"
  7. "fmt"
  8. "io/ioutil"
  9. "net/http"
  10. "net/url"
  11. "path"
  12. "strings"
  13. "time"
  14. "go-common/library/ecode"
  15. "go-common/library/log"
  16. )
  17. const (
  18. // api
  19. _apiGet1 = "http://%s/config/v2/get?%s"
  20. _apiCheck1 = "http://%s/config/v2/check?%s"
  21. _apiCreate = "http://%s/config/v2/create"
  22. _apiUpdate = "http://%s/config/v2/update"
  23. _apiConfIng = "http://%s/config/v2/config/ing?%s"
  24. )
  25. type version1 struct {
  26. Code int `json:"code"`
  27. Message string `json:"message"`
  28. Data *ver `json:"data"`
  29. }
  30. type ver struct {
  31. Version int64 `json:"version"`
  32. Diffs []int64 `json:"diffs"`
  33. }
  34. type confIng struct {
  35. Code int `json:"code"`
  36. Message string `json:"message"`
  37. Data *Value `json:"data"`
  38. }
  39. type res struct {
  40. Code int `json:"code"`
  41. Message string `json:"message"`
  42. }
  43. //Value value.
  44. type Value struct {
  45. CID int64 `json:"cid"`
  46. Name string `json:"name"`
  47. Config string `json:"config"`
  48. }
  49. // Toml2 return config value.
  50. func (c *Client) Toml2() (cf string, ok bool) {
  51. var (
  52. m map[string]*Value
  53. val *Value
  54. )
  55. if m, ok = c.data.Load().(map[string]*Value); !ok {
  56. return
  57. }
  58. if val, ok = m[commonKey]; !ok {
  59. return
  60. }
  61. cf = val.Config
  62. return
  63. }
  64. // Value2 return config value.
  65. func (c *Client) Value2(key string) (cf string, ok bool) {
  66. var (
  67. m map[string]*Value
  68. val *Value
  69. )
  70. if m, ok = c.data.Load().(map[string]*Value); !ok {
  71. return
  72. }
  73. if val, ok = m[key]; !ok {
  74. return
  75. }
  76. cf = val.Config
  77. return
  78. }
  79. // init check local config is ok
  80. func (c *Client) init2() (err error) {
  81. var v *ver
  82. c.data.Store(make(map[string]*Value))
  83. if v, err = c.checkVersion2(&ver{Version: _unknownVersion}); err != nil {
  84. fmt.Printf("get remote version error(%v)\n", err)
  85. return
  86. }
  87. for i := 0; i < 3; i++ {
  88. if v.Version == _unknownVersion {
  89. fmt.Println("get null version")
  90. return
  91. }
  92. if err = c.download2(v, true); err == nil {
  93. return
  94. }
  95. fmt.Printf("retry times: %d, c.download() error(%v)\n", i, err)
  96. time.Sleep(_retryInterval)
  97. }
  98. return
  99. }
  100. func (c *Client) updateproc2() (err error) {
  101. var ver *ver
  102. for {
  103. time.Sleep(_retryInterval)
  104. if ver, err = c.checkVersion2(c.diff); err != nil {
  105. log.Error("c.checkVersion(%d) error(%v)", c.ver, err)
  106. continue
  107. } else if ver.Version == c.diff.Version {
  108. continue
  109. }
  110. if err = c.download2(ver, false); err != nil {
  111. log.Error("c.download() error(%s)", err)
  112. continue
  113. }
  114. }
  115. }
  116. // download download config from config service
  117. func (c *Client) download2(ver *ver, isFirst bool) (err error) {
  118. var (
  119. d *data
  120. tmp []*Value
  121. oConfs, confs map[string]*Value
  122. buf = new(bytes.Buffer)
  123. ok bool
  124. )
  125. if d, err = c.getConfig2(ver); err != nil {
  126. return
  127. }
  128. bs := []byte(d.Content)
  129. // md5 file
  130. if mh := md5.Sum(bs); hex.EncodeToString(mh[:]) != d.Md5 {
  131. err = fmt.Errorf("md5 mismatch, local:%s, remote:%s", hex.EncodeToString(mh[:]), d.Md5)
  132. return
  133. }
  134. // write conf
  135. if err = json.Unmarshal(bs, &tmp); err != nil {
  136. return
  137. }
  138. confs = make(map[string]*Value)
  139. if oConfs, ok = c.data.Load().(map[string]*Value); ok {
  140. for k, v := range oConfs {
  141. confs[k] = v
  142. }
  143. }
  144. for _, v := range tmp {
  145. if err = ioutil.WriteFile(path.Join(conf.Path, v.Name), []byte(v.Config), 0644); err != nil {
  146. return
  147. }
  148. confs[v.Name] = v
  149. }
  150. for _, v := range confs {
  151. if strings.Contains(v.Name, ".toml") {
  152. buf.WriteString(v.Config)
  153. buf.WriteString("\n")
  154. }
  155. }
  156. confs[commonKey] = &Value{Config: buf.String()}
  157. // update current version
  158. c.diff = ver
  159. c.data.Store(confs)
  160. if isFirst {
  161. return
  162. }
  163. for _, v := range tmp {
  164. if c.watchAll {
  165. c.event <- v.Name
  166. continue
  167. }
  168. if c.watchFile == nil {
  169. continue
  170. }
  171. if _, ok := c.watchFile[v.Name]; ok {
  172. c.event <- v.Name
  173. }
  174. }
  175. return
  176. }
  177. // poll config server
  178. func (c *Client) checkVersion2(reqVer *ver) (ver *ver, err error) {
  179. var (
  180. url string
  181. req *http.Request
  182. resp *http.Response
  183. rb []byte
  184. )
  185. if url, err = c.makeURL2(_apiCheck1, reqVer); err != nil {
  186. err = fmt.Errorf("checkVersion() c.makeUrl() error url empty")
  187. return
  188. }
  189. // http
  190. if req, err = http.NewRequest("GET", url, nil); err != nil {
  191. return
  192. }
  193. if resp, err = c.httpCli.Do(req); err != nil {
  194. return
  195. }
  196. defer resp.Body.Close()
  197. if resp.StatusCode != http.StatusOK {
  198. err = fmt.Errorf("checkVersion() http error url(%s) status: %d", url, resp.StatusCode)
  199. return
  200. }
  201. // ok
  202. if rb, err = ioutil.ReadAll(resp.Body); err != nil {
  203. return
  204. }
  205. v := &version1{}
  206. if err = json.Unmarshal(rb, v); err != nil {
  207. return
  208. }
  209. switch v.Code {
  210. case _codeOk:
  211. if v.Data == nil {
  212. err = fmt.Errorf("checkVersion() response error result: %v", v)
  213. return
  214. }
  215. ver = v.Data
  216. case _codeNotModified:
  217. ver = reqVer
  218. default:
  219. err = fmt.Errorf("checkVersion() response error result: %v", v)
  220. }
  221. return
  222. }
  223. // updateVersion update config version
  224. func (c *Client) getConfig2(ver *ver) (data *data, err error) {
  225. var (
  226. url string
  227. req *http.Request
  228. resp *http.Response
  229. rb []byte
  230. res = &result{}
  231. )
  232. if url, err = c.makeURL2(_apiGet1, ver); err != nil {
  233. err = fmt.Errorf("getConfig() c.makeUrl() error url empty")
  234. return
  235. }
  236. // http
  237. if req, err = http.NewRequest("GET", url, nil); err != nil {
  238. return
  239. }
  240. if resp, err = c.httpCli.Do(req); err != nil {
  241. return
  242. }
  243. defer resp.Body.Close()
  244. // ok
  245. if resp.StatusCode != http.StatusOK {
  246. err = fmt.Errorf("getConfig() http error url(%s) status: %d", url, resp.StatusCode)
  247. return
  248. }
  249. if rb, err = ioutil.ReadAll(resp.Body); err != nil {
  250. return
  251. }
  252. if err = json.Unmarshal(rb, res); err != nil {
  253. return
  254. }
  255. switch res.Code {
  256. case _codeOk:
  257. // has new config
  258. if res.Data == nil {
  259. err = fmt.Errorf("getConfig() response error result: %v", res)
  260. return
  261. }
  262. data = res.Data
  263. default:
  264. err = fmt.Errorf("getConfig() response error result: %v", res)
  265. }
  266. return
  267. }
  268. // makeUrl signed url
  269. func (c *Client) makeURL2(api string, ver *ver) (query string, err error) {
  270. var ids []byte
  271. params := url.Values{}
  272. // service
  273. params.Set("service", service())
  274. params.Set("hostname", conf.Host)
  275. params.Set("build", conf.Ver)
  276. params.Set("version", fmt.Sprint(ver.Version))
  277. if ids, err = json.Marshal(ver.Diffs); err != nil {
  278. return
  279. }
  280. params.Set("ids", string(ids))
  281. params.Set("ip", localIP())
  282. params.Set("token", conf.Token)
  283. params.Set("appoint", conf.Appoint)
  284. params.Set("customize", c.customize)
  285. // api
  286. query = fmt.Sprintf(api, conf.Addr, params.Encode())
  287. return
  288. }
  289. //Create create.
  290. func (c *Client) Create(name, content, operator, mark string) (err error) {
  291. var (
  292. resp *http.Response
  293. rb []byte
  294. res = &res{}
  295. )
  296. params := url.Values{}
  297. params.Set("service", service())
  298. params.Set("name", name)
  299. params.Set("content", content)
  300. params.Set("operator", operator)
  301. params.Set("mark", mark)
  302. params.Set("token", conf.Token)
  303. if resp, err = c.httpCli.PostForm(fmt.Sprintf(_apiCreate, conf.Addr), params); err != nil {
  304. return
  305. }
  306. defer resp.Body.Close()
  307. // ok
  308. if resp.StatusCode != http.StatusOK {
  309. err = fmt.Errorf("Create() http error url(%s) status: %d", fmt.Sprintf(_apiCreate, conf.Addr), resp.StatusCode)
  310. return
  311. }
  312. if rb, err = ioutil.ReadAll(resp.Body); err != nil {
  313. return
  314. }
  315. if err = json.Unmarshal(rb, res); err != nil {
  316. return
  317. }
  318. if res.Code != ecode.OK.Code() {
  319. err = ecode.Int(res.Code)
  320. }
  321. return
  322. }
  323. //Update update.
  324. func (c *Client) Update(ID int64, content, operator, mark string) (err error) {
  325. var (
  326. resp *http.Response
  327. rb []byte
  328. res = &result{}
  329. )
  330. params := url.Values{}
  331. params.Set("conf_id", fmt.Sprintf("%d", ID))
  332. params.Set("content", content)
  333. params.Set("operator", operator)
  334. params.Set("mark", mark)
  335. params.Set("service", service())
  336. params.Set("token", conf.Token)
  337. if resp, err = c.httpCli.PostForm(fmt.Sprintf(_apiUpdate, conf.Addr), params); err != nil {
  338. return
  339. }
  340. defer resp.Body.Close()
  341. // ok
  342. if resp.StatusCode != http.StatusOK {
  343. err = fmt.Errorf("Update() http error url(%s) status: %d", fmt.Sprintf(_apiUpdate, conf.Addr), resp.StatusCode)
  344. return
  345. }
  346. if rb, err = ioutil.ReadAll(resp.Body); err != nil {
  347. return
  348. }
  349. if err = json.Unmarshal(rb, res); err != nil {
  350. return
  351. }
  352. if res.Code != ecode.OK.Code() {
  353. err = ecode.Int(res.Code)
  354. }
  355. return
  356. }
  357. //ConfIng confIng.
  358. func (c *Client) ConfIng(name string) (v *Value, err error) {
  359. var (
  360. req *http.Request
  361. resp *http.Response
  362. rb []byte
  363. res = &confIng{}
  364. )
  365. params := url.Values{}
  366. params.Set("name", name)
  367. params.Set("service", service())
  368. params.Set("token", conf.Token)
  369. // http
  370. if req, err = http.NewRequest("GET", fmt.Sprintf(_apiConfIng, conf.Addr, params.Encode()), nil); err != nil {
  371. return
  372. }
  373. if resp, err = c.httpCli.Do(req); err != nil {
  374. return
  375. }
  376. defer resp.Body.Close()
  377. // ok
  378. if resp.StatusCode != http.StatusOK {
  379. err = fmt.Errorf("ConfIng() http error url(%s) status: %d", _apiCreate, resp.StatusCode)
  380. return
  381. }
  382. if rb, err = ioutil.ReadAll(resp.Body); err != nil {
  383. return
  384. }
  385. if err = json.Unmarshal(rb, res); err != nil {
  386. return
  387. }
  388. if res.Code != ecode.OK.Code() {
  389. err = ecode.Int(res.Code)
  390. return
  391. }
  392. v = res.Data
  393. return
  394. }
  395. //Configs configs.
  396. func (c *Client) Configs() (confs []*Value, ok bool) {
  397. var (
  398. m map[string]*Value
  399. )
  400. if m, ok = c.data.Load().(map[string]*Value); !ok {
  401. return
  402. }
  403. for _, v := range m {
  404. if v.CID == 0 {
  405. continue
  406. }
  407. confs = append(confs, v)
  408. }
  409. return
  410. }
  411. func service() string {
  412. return fmt.Sprintf("%s_%s_%s", conf.TreeID, conf.DeployEnv, conf.Zone)
  413. }