230 lines
5.5 KiB
Go
230 lines
5.5 KiB
Go
package conf
|
|
|
|
import (
|
|
"errors"
|
|
"net/url"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/BurntSushi/toml"
|
|
|
|
"go-common/library/conf"
|
|
"go-common/library/log"
|
|
xtime "go-common/library/time"
|
|
)
|
|
|
|
// ENV Key
|
|
const (
|
|
BNSDNSAddr = "BNS_DNS_HOST"
|
|
BNSDNSPort = "BNS_DNS_PORT"
|
|
BNSHTTPAddr = "BNS_HTTP_ADDR"
|
|
BNSHTTPPort = "BNS_HTTP_PORT"
|
|
)
|
|
|
|
// default value
|
|
const (
|
|
defaultBNSDNSAddr = "0.0.0.0"
|
|
defaultBNSDNSPort = 15353
|
|
defaultBNSHTTPAddr = "0.0.0.0"
|
|
defaultBNSHTTPPort = 15380
|
|
)
|
|
|
|
var defaultConfig Config
|
|
|
|
func init() {
|
|
// default dns config
|
|
defaultDNSConfig := DNSConfig{
|
|
TTL: 0,
|
|
AllowStale: true,
|
|
UDPAnswerLimit: 3,
|
|
MaxStale: xtime.Duration(time.Second * 87600),
|
|
Domain: "bili.",
|
|
RecursorTimeout: xtime.Duration(time.Second),
|
|
}
|
|
defaultDNSServer := &DNSServer{
|
|
Addr: defaultBNSDNSAddr,
|
|
Port: defaultBNSDNSPort,
|
|
Config: &defaultDNSConfig,
|
|
}
|
|
|
|
// default http config
|
|
defaultHTTPServer := &HTTPServer{
|
|
Addr: defaultBNSHTTPAddr,
|
|
Port: defaultBNSHTTPPort,
|
|
}
|
|
|
|
defaultBackend := &Backend{
|
|
Backend: "discovery",
|
|
Config: map[string]interface{}{
|
|
"url": "http://api.bilibili.co",
|
|
},
|
|
}
|
|
|
|
defaultConfig = Config{
|
|
Backend: defaultBackend,
|
|
HTTP: defaultHTTPServer,
|
|
DNS: defaultDNSServer,
|
|
}
|
|
}
|
|
|
|
// LoadConfig from source
|
|
func LoadConfig(source string) (*Config, error) {
|
|
cfg := defaultConfig
|
|
var err error
|
|
if strings.HasPrefix(source, "remote://") {
|
|
var u *url.URL
|
|
if u, err = url.Parse(source); err != nil {
|
|
return nil, err
|
|
}
|
|
err = loadRemoteConfig(u.Path, &cfg)
|
|
} else if source != "" {
|
|
err = loadLocalConfig(source, &cfg)
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
overwriteByEnv(&cfg)
|
|
return &cfg, nil
|
|
}
|
|
|
|
func loadRemoteConfig(key string, pcfg *Config) error {
|
|
client, err := conf.New()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
data, ok := client.Value(key)
|
|
if !ok {
|
|
return errors.New("load config center error")
|
|
}
|
|
|
|
if _, err = toml.Decode(data, pcfg); err != nil {
|
|
return errors.New("could not decode config")
|
|
}
|
|
|
|
go func() {
|
|
for range client.Event() {
|
|
log.Warn("ignore config reload")
|
|
}
|
|
}()
|
|
return nil
|
|
}
|
|
|
|
func loadLocalConfig(fpath string, pcfg *Config) error {
|
|
_, err := toml.DecodeFile(fpath, pcfg)
|
|
return err
|
|
}
|
|
|
|
// Config config struct
|
|
type Config struct {
|
|
Log *log.Config
|
|
Backend *Backend
|
|
HTTP *HTTPServer
|
|
DNS *DNSServer
|
|
}
|
|
|
|
// overwrite config from env
|
|
func overwriteByEnv(pcfg *Config) {
|
|
if addr := os.Getenv(BNSDNSAddr); addr != "" {
|
|
pcfg.DNS.Addr = addr
|
|
}
|
|
if portStr := os.Getenv(BNSDNSPort); portStr != "" {
|
|
if port, err := strconv.Atoi(portStr); err != nil {
|
|
log.Warn("parse port from env error: %s", err)
|
|
} else {
|
|
pcfg.DNS.Port = port
|
|
}
|
|
}
|
|
|
|
if addr := os.Getenv(BNSHTTPAddr); addr != "" {
|
|
pcfg.HTTP.Addr = addr
|
|
}
|
|
if portStr := os.Getenv(BNSHTTPPort); portStr != "" {
|
|
if port, err := strconv.Atoi(portStr); err != nil {
|
|
log.Warn("parse port from env error: %s", err)
|
|
} else {
|
|
pcfg.HTTP.Port = port
|
|
}
|
|
}
|
|
}
|
|
|
|
// Backend Config
|
|
type Backend struct {
|
|
Backend string
|
|
Config map[string]interface{}
|
|
}
|
|
|
|
// HTTPServer http server config
|
|
type HTTPServer struct {
|
|
Addr string
|
|
Port int
|
|
}
|
|
|
|
// DNSServer dns server config
|
|
type DNSServer struct {
|
|
Addr string
|
|
Port int
|
|
Config *DNSConfig
|
|
}
|
|
|
|
// DNSConfig dns config
|
|
type DNSConfig struct {
|
|
// TTL provides the TTL value for a easyns path query for given path.
|
|
// The "*" wildcard can be used to set a default to a highlevel path, such as project level path.
|
|
TTL xtime.Duration `toml:"ttl"`
|
|
|
|
// AllowStale is used to enable lookups with stale
|
|
// data. This gives horizontal read scalability since
|
|
// any easyns server can service the query instead of
|
|
// only the leader.
|
|
AllowStale bool
|
|
|
|
// EnableTruncate is used to enable setting the truncate
|
|
// flag for UDP DNS queries. This allows unmodified
|
|
// clients to re-query the easyns server using TCP
|
|
// when the total number of records exceeds the number
|
|
// returned by default for UDP.
|
|
EnableTruncate bool
|
|
|
|
// UDPAnswerLimit is used to limit the maximum number of DNS Resource
|
|
// Records returned in the ANSWER section of a DNS response. This is
|
|
// not normally useful and will be limited based on the querying
|
|
// protocol, however systems that implemented §6 Rule 9 in RFC3484
|
|
// may want to set this to `1` in order to subvert §6 Rule 9 and
|
|
// re-obtain the effect of randomized resource records (i.e. each
|
|
// answer contains only one IP, but the IP changes every request).
|
|
// RFC3484 sorts answers in a deterministic order, which defeats the
|
|
// purpose of randomized DNS responses. This RFC has been obsoleted
|
|
// by RFC6724 and restores the desired behavior of randomized
|
|
// responses, however a large number of Linux hosts using glibc(3)
|
|
// implemented §6 Rule 9 and may need this option (e.g. CentOS 5-6,
|
|
// Debian Squeeze, etc).
|
|
UDPAnswerLimit int `toml:"udpAnswerLimit"`
|
|
|
|
// MaxStale is used to bound how stale of a result is
|
|
// accepted for a DNS lookup. This can be used with
|
|
// AllowStale to limit how old of a value is served up.
|
|
// If the stale result exceeds this, another non-stale
|
|
// stale read is performed.
|
|
MaxStale xtime.Duration
|
|
|
|
// DisableCompression is used to control whether DNS responses are
|
|
// compressed. This was turned on by default and this
|
|
// config was added as an opt-out.
|
|
DisableCompression bool
|
|
|
|
// RecursorTimeout specifies the timeout in seconds
|
|
// for Easyns agent's internal dns client used for recursion.
|
|
// This value is used for the connection, read and write timeout.
|
|
// Default: 2s
|
|
RecursorTimeout xtime.Duration
|
|
|
|
// Managed domain suffix
|
|
Domain string
|
|
|
|
// Upstream recursor dns servers
|
|
Recursors []string
|
|
}
|