config.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "os"
  6. "sync"
  7. "time"
  8. "gopkg.in/fsnotify.v1"
  9. "gopkg.in/gcfg.v1"
  10. )
  11. type AppConfig struct {
  12. StatHat struct {
  13. ApiKey string
  14. }
  15. Flags struct {
  16. HasStatHat bool
  17. }
  18. GeoIP struct {
  19. Directory string
  20. }
  21. HTTP struct {
  22. User string
  23. Password string
  24. }
  25. QueryLog struct {
  26. Path string
  27. MaxSize int
  28. Keep int
  29. }
  30. Nodeping struct {
  31. Token string
  32. }
  33. Pingdom struct {
  34. Username string
  35. Password string
  36. AccountEmail string
  37. AppKey string
  38. StateMap string
  39. }
  40. }
  41. var Config = new(AppConfig)
  42. var cfgMutex sync.RWMutex
  43. func (conf *AppConfig) HasStatHat() bool {
  44. cfgMutex.RLock()
  45. defer cfgMutex.RUnlock()
  46. return conf.Flags.HasStatHat
  47. }
  48. func (conf *AppConfig) StatHatApiKey() string {
  49. cfgMutex.RLock()
  50. defer cfgMutex.RUnlock()
  51. return conf.StatHat.ApiKey
  52. }
  53. func (conf *AppConfig) GeoIPDirectory() string {
  54. cfgMutex.RLock()
  55. defer cfgMutex.RUnlock()
  56. return conf.GeoIP.Directory
  57. }
  58. func configWatcher(fileName string) {
  59. watcher, err := fsnotify.NewWatcher()
  60. if err != nil {
  61. fmt.Println(err)
  62. return
  63. }
  64. if err := watcher.Add(*flagconfig); err != nil {
  65. fmt.Println(err)
  66. return
  67. }
  68. for {
  69. select {
  70. case ev := <-watcher.Events:
  71. if ev.Name == fileName {
  72. // Write = when the file is updated directly
  73. // Rename = when it's updated atomicly
  74. // Chmod = for `touch`
  75. if ev.Op&fsnotify.Write == fsnotify.Write ||
  76. ev.Op&fsnotify.Rename == fsnotify.Rename ||
  77. ev.Op&fsnotify.Chmod == fsnotify.Chmod {
  78. time.Sleep(200 * time.Millisecond)
  79. configReader(fileName)
  80. }
  81. }
  82. case err := <-watcher.Errors:
  83. log.Println("fsnotify error:", err)
  84. }
  85. }
  86. }
  87. var lastReadConfig time.Time
  88. func configReader(fileName string) error {
  89. stat, err := os.Stat(fileName)
  90. if err != nil {
  91. log.Printf("Failed to find config file: %s\n", err)
  92. return err
  93. }
  94. if !stat.ModTime().After(lastReadConfig) {
  95. return err
  96. }
  97. lastReadConfig = time.Now()
  98. log.Printf("Loading config: %s\n", fileName)
  99. cfg := new(AppConfig)
  100. err = gcfg.ReadFileInto(cfg, fileName)
  101. if err != nil {
  102. log.Printf("Failed to parse config data: %s\n", err)
  103. return err
  104. }
  105. cfg.Flags.HasStatHat = len(cfg.StatHat.ApiKey) > 0
  106. // log.Println("STATHAT APIKEY:", cfg.StatHat.ApiKey)
  107. // log.Println("STATHAT FLAG :", cfg.Flags.HasStatHat)
  108. cfgMutex.Lock()
  109. *Config = *cfg // shallow copy to prevent race conditions in referring to Config.foo()
  110. cfgMutex.Unlock()
  111. return nil
  112. }