conf.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. package conf
  2. import (
  3. "errors"
  4. "net/url"
  5. "os"
  6. "strconv"
  7. "strings"
  8. "time"
  9. "github.com/BurntSushi/toml"
  10. "go-common/library/conf"
  11. "go-common/library/log"
  12. xtime "go-common/library/time"
  13. )
  14. // ENV Key
  15. const (
  16. BNSDNSAddr = "BNS_DNS_HOST"
  17. BNSDNSPort = "BNS_DNS_PORT"
  18. BNSHTTPAddr = "BNS_HTTP_ADDR"
  19. BNSHTTPPort = "BNS_HTTP_PORT"
  20. )
  21. // default value
  22. const (
  23. defaultBNSDNSAddr = "0.0.0.0"
  24. defaultBNSDNSPort = 15353
  25. defaultBNSHTTPAddr = "0.0.0.0"
  26. defaultBNSHTTPPort = 15380
  27. )
  28. var defaultConfig Config
  29. func init() {
  30. // default dns config
  31. defaultDNSConfig := DNSConfig{
  32. TTL: 0,
  33. AllowStale: true,
  34. UDPAnswerLimit: 3,
  35. MaxStale: xtime.Duration(time.Second * 87600),
  36. Domain: "bili.",
  37. RecursorTimeout: xtime.Duration(time.Second),
  38. }
  39. defaultDNSServer := &DNSServer{
  40. Addr: defaultBNSDNSAddr,
  41. Port: defaultBNSDNSPort,
  42. Config: &defaultDNSConfig,
  43. }
  44. // default http config
  45. defaultHTTPServer := &HTTPServer{
  46. Addr: defaultBNSHTTPAddr,
  47. Port: defaultBNSHTTPPort,
  48. }
  49. defaultBackend := &Backend{
  50. Backend: "discovery",
  51. Config: map[string]interface{}{
  52. "url": "http://api.bilibili.co",
  53. },
  54. }
  55. defaultConfig = Config{
  56. Backend: defaultBackend,
  57. HTTP: defaultHTTPServer,
  58. DNS: defaultDNSServer,
  59. }
  60. }
  61. // LoadConfig from source
  62. func LoadConfig(source string) (*Config, error) {
  63. cfg := defaultConfig
  64. var err error
  65. if strings.HasPrefix(source, "remote://") {
  66. var u *url.URL
  67. if u, err = url.Parse(source); err != nil {
  68. return nil, err
  69. }
  70. err = loadRemoteConfig(u.Path, &cfg)
  71. } else if source != "" {
  72. err = loadLocalConfig(source, &cfg)
  73. }
  74. if err != nil {
  75. return nil, err
  76. }
  77. overwriteByEnv(&cfg)
  78. return &cfg, nil
  79. }
  80. func loadRemoteConfig(key string, pcfg *Config) error {
  81. client, err := conf.New()
  82. if err != nil {
  83. return err
  84. }
  85. data, ok := client.Value(key)
  86. if !ok {
  87. return errors.New("load config center error")
  88. }
  89. if _, err = toml.Decode(data, pcfg); err != nil {
  90. return errors.New("could not decode config")
  91. }
  92. go func() {
  93. for range client.Event() {
  94. log.Warn("ignore config reload")
  95. }
  96. }()
  97. return nil
  98. }
  99. func loadLocalConfig(fpath string, pcfg *Config) error {
  100. _, err := toml.DecodeFile(fpath, pcfg)
  101. return err
  102. }
  103. // Config config struct
  104. type Config struct {
  105. Log *log.Config
  106. Backend *Backend
  107. HTTP *HTTPServer
  108. DNS *DNSServer
  109. }
  110. // overwrite config from env
  111. func overwriteByEnv(pcfg *Config) {
  112. if addr := os.Getenv(BNSDNSAddr); addr != "" {
  113. pcfg.DNS.Addr = addr
  114. }
  115. if portStr := os.Getenv(BNSDNSPort); portStr != "" {
  116. if port, err := strconv.Atoi(portStr); err != nil {
  117. log.Warn("parse port from env error: %s", err)
  118. } else {
  119. pcfg.DNS.Port = port
  120. }
  121. }
  122. if addr := os.Getenv(BNSHTTPAddr); addr != "" {
  123. pcfg.HTTP.Addr = addr
  124. }
  125. if portStr := os.Getenv(BNSHTTPPort); portStr != "" {
  126. if port, err := strconv.Atoi(portStr); err != nil {
  127. log.Warn("parse port from env error: %s", err)
  128. } else {
  129. pcfg.HTTP.Port = port
  130. }
  131. }
  132. }
  133. // Backend Config
  134. type Backend struct {
  135. Backend string
  136. Config map[string]interface{}
  137. }
  138. // HTTPServer http server config
  139. type HTTPServer struct {
  140. Addr string
  141. Port int
  142. }
  143. // DNSServer dns server config
  144. type DNSServer struct {
  145. Addr string
  146. Port int
  147. Config *DNSConfig
  148. }
  149. // DNSConfig dns config
  150. type DNSConfig struct {
  151. // TTL provides the TTL value for a easyns path query for given path.
  152. // The "*" wildcard can be used to set a default to a highlevel path, such as project level path.
  153. TTL xtime.Duration `toml:"ttl"`
  154. // AllowStale is used to enable lookups with stale
  155. // data. This gives horizontal read scalability since
  156. // any easyns server can service the query instead of
  157. // only the leader.
  158. AllowStale bool
  159. // EnableTruncate is used to enable setting the truncate
  160. // flag for UDP DNS queries. This allows unmodified
  161. // clients to re-query the easyns server using TCP
  162. // when the total number of records exceeds the number
  163. // returned by default for UDP.
  164. EnableTruncate bool
  165. // UDPAnswerLimit is used to limit the maximum number of DNS Resource
  166. // Records returned in the ANSWER section of a DNS response. This is
  167. // not normally useful and will be limited based on the querying
  168. // protocol, however systems that implemented §6 Rule 9 in RFC3484
  169. // may want to set this to `1` in order to subvert §6 Rule 9 and
  170. // re-obtain the effect of randomized resource records (i.e. each
  171. // answer contains only one IP, but the IP changes every request).
  172. // RFC3484 sorts answers in a deterministic order, which defeats the
  173. // purpose of randomized DNS responses. This RFC has been obsoleted
  174. // by RFC6724 and restores the desired behavior of randomized
  175. // responses, however a large number of Linux hosts using glibc(3)
  176. // implemented §6 Rule 9 and may need this option (e.g. CentOS 5-6,
  177. // Debian Squeeze, etc).
  178. UDPAnswerLimit int `toml:"udpAnswerLimit"`
  179. // MaxStale is used to bound how stale of a result is
  180. // accepted for a DNS lookup. This can be used with
  181. // AllowStale to limit how old of a value is served up.
  182. // If the stale result exceeds this, another non-stale
  183. // stale read is performed.
  184. MaxStale xtime.Duration
  185. // DisableCompression is used to control whether DNS responses are
  186. // compressed. This was turned on by default and this
  187. // config was added as an opt-out.
  188. DisableCompression bool
  189. // RecursorTimeout specifies the timeout in seconds
  190. // for Easyns agent's internal dns client used for recursion.
  191. // This value is used for the connection, read and write timeout.
  192. // Default: 2s
  193. RecursorTimeout xtime.Duration
  194. // Managed domain suffix
  195. Domain string
  196. // Upstream recursor dns servers
  197. Recursors []string
  198. }