config.go 2.6 KB

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