Files
frontier/pkg/frontlas/config/config.go
T
2024-05-08 16:35:49 +08:00

238 lines
7.3 KiB
Go

package config
import (
"flag"
"io"
"os"
armio "github.com/jumboframes/armorigo/io"
"github.com/singchia/frontier/pkg/config"
"github.com/spf13/pflag"
"gopkg.in/yaml.v2"
"k8s.io/klog/v2"
)
// daemon related
type RLimit struct {
Enable bool `yaml:"enable"`
NumFile int `yaml:"nofile"`
}
type PProf struct {
Enable bool `yaml:"enable"`
Addr string `yaml:"addr"`
CPUProfileRate int `yaml:"cpu_profile_rate"`
}
type Daemon struct {
RLimit RLimit `yaml:"rlimit"`
PProf PProf `yaml:"pprof"`
}
// for rest and grpc
type ControlPlane struct {
Listen config.Listen `yaml:"listen"`
}
// TODO tls support
type Redis struct {
Mode string `yaml:"mode"` // standalone, sentinel or cluster
// Use the specified Username to authenticate the current connection
// with one of the connections defined in the ACL list when connecting
// to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
Username string `yaml:"username,omitempty"`
// Optional password. Must match the password specified in the
// requirepass server configuration option (if connecting to a Redis 5.0 instance, or lower),
// or the User Password when connecting to a Redis 6.0 instance, or greater,
// that is using the Redis ACL system.
Password string `yaml:"password,omitempty"`
// Protocol 2 or 3. Use the version to negotiate RESP version with redis-server.
// Default is 3.
Protocol int `yaml:"protocol,omitempty"`
// ClientName will execute the `CLIENT SETNAME ClientName` command for each conn.
ClientName string `yaml:"clientname,omitempty"`
// connection retry settings
MaxRetries int `yaml:"max_retries,omitempty"`
MinRetryBackoff int `yaml:"min_retry_backoff,omitempty"`
MaxRetryBackoff int `yaml:"max_retry_backoff,omitempty"`
// connection r/w settings
DialTimeout int `yaml:"dial_timeout,omitempty"`
ReadTimeout int `yaml:"read_timeout,omitempty"`
WriteTimeout int `yaml:"write_timeout,omitempty"`
// connection pool settings
PoolFIFO bool `yaml:"pool_fifo,omitempty"`
PoolSize int `yaml:"pool_size,omitempty"` // applies per cluster node and not for the whole cluster
PoolTimeout int `yaml:"pool_timeout,omitempty"`
MinIdleConns int `yaml:"min_idle_conns,omitempty"`
MaxIdleConns int `yaml:"max_idle,omitempty"`
MaxActiveConns int `yaml:"max_active_conns,omitempty"` // applies per cluster node and not for the whole cluster
ConnMaxIdleTime int `yaml:"conn_max_idle_time,omitempty"`
ConnMaxLifetime int `yaml:"conn_max_life_time,omitempty"`
DisableIndentity bool `yaml:"disable_identity,omitempty"` // Disable set-lib on connect. Default is false.
IdentitySuffix string `yaml:"identity_suffix,omitempty"` // Add suffix to client name. Default is empty.
Standalone struct {
// The network type, either tcp or unix.
// Default is tcp.
Network string `yaml:"network"`
// host:port address.
Addr string `yaml:"addr"`
// CredentialsProvider allows the username and password to be updated
// before reconnecting. It should return the current username and password.
DB int `yaml:"db"`
} `yaml:"standalone,omitempty"`
Sentinel struct {
Addrs []string `yaml:"addrs"`
MasterName string `yaml:"master_name"`
DB int `yaml:"db"`
// route settings
// Allows routing read-only commands to the closest master or replica node.
// This option only works with NewFailoverClusterClient.
RouteByLatency bool `yaml:"route_by_latency,omitempty"`
// Allows routing read-only commands to the random master or replica node.
// This option only works with NewFailoverClusterClient.
RouteRandomly bool `yaml:"route_randomly,omitempty"`
// Route all commands to replica read-only nodes.
ReplicaOnly bool `yaml:"replica_only,omitempty"`
// Use replicas disconnected with master when cannot get connected replicas
// Now, this option only works in RandomReplicaAddr function.
UseDisconnectedReplicas bool `yaml:"use_disconnected_replicas,omitempty"`
} `yaml:"sentinel,omitempty"`
Cluster struct {
Addrs []string `yaml:"addrs"`
// The maximum number of retries before giving up. Command is retried
// on network errors and MOVED/ASK redirects.
// Default is 3 retries.
MaxRedirects int `yaml:"max_redirects,omitempty"`
// Allows routing read-only commands to the closest master or slave node.
// It automatically enables ReadOnly.
RouteByLatency bool `yaml:"route_by_latency,omitempty"`
// Allows routing read-only commands to the random master or slave node.
// It automatically enables ReadOnly.
RouteRandomly bool `yaml:"route_randomly,omitempty"`
} `yaml:"cluster,omitempty"`
}
type FrontierManager struct {
Listen config.Listen `yaml:"listen"`
Expiration struct {
ServiceMeta int `yaml:"service_meta"` // service meta expiration in redis, in seconds, default 86400s
EdgeMeta int `yaml:"edge_meta"` // edge meta expiration in redis, in seconds, default 86400s
} `yaml:"expiration,omitempty"`
}
type Configuration struct {
Daemon Daemon `yaml:"daemon"`
ControlPlane ControlPlane `yaml:"control_plane"`
FrontierManager FrontierManager `yaml:"frontier_plane"`
Redis Redis `yaml:"redis"`
}
func Parse() (*Configuration, error) {
var (
argConfigFile = pflag.String("config", "", "config file, default not configured")
argDaemonRLimitNofile = pflag.Int("daemon-rlimit-nofile", -1, "SetRLimit for number of file of this daemon, default: -1 means ignore")
// TODO more command-line args
config *Configuration
)
pflag.Lookup("daemon-rlimit-nofile").NoOptDefVal = "1048576"
// set klog
klogFlags := flag.NewFlagSet("klog", flag.ExitOnError)
klog.InitFlags(klogFlags)
// sync the glog and klog flags.
pflag.CommandLine.VisitAll(func(f1 *pflag.Flag) {
f2 := klogFlags.Lookup(f1.Name)
if f2 != nil {
value := f1.Value.String()
if err := f2.Value.Set(value); err != nil {
klog.Fatal(err, "failed to set flag")
return
}
}
})
pflag.CommandLine.AddGoFlagSet(klogFlags)
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()
// config file
if *argConfigFile != "" {
// TODO the command-line is prior to config file
data, err := os.ReadFile(*argConfigFile)
if err != nil {
return nil, err
}
config = &Configuration{}
if err = yaml.Unmarshal(data, config); err != nil {
return nil, err
}
}
if config == nil {
config = &Configuration{}
}
// daemon
config.Daemon.RLimit.NumFile = *argDaemonRLimitNofile
if config.Daemon.PProf.CPUProfileRate == 0 {
config.Daemon.PProf.CPUProfileRate = 10000
}
return config, nil
}
func genDefaultConfig(writer io.Writer) error {
conf := &Configuration{
Daemon: Daemon{
RLimit: RLimit{
NumFile: 1024,
},
PProf: PProf{
Enable: true,
Addr: "0.0.0.0:6061",
},
},
ControlPlane: ControlPlane{
Listen: config.Listen{
Network: "tcp",
Addr: "0.0.0.0:30020",
},
},
FrontierManager: FrontierManager{
Listen: config.Listen{
Network: "tcp",
Addr: "0.0.0.0:30021",
},
},
Redis: Redis{
Mode: "standalone",
},
}
conf.Redis.Standalone.Network = "tcp"
conf.Redis.Standalone.Addr = "127.0.0.1:6379"
conf.Redis.Standalone.DB = 0
conf.FrontierManager.Expiration.EdgeMeta = 30
conf.FrontierManager.Expiration.ServiceMeta = 30
data, err := yaml.Marshal(conf)
if err != nil {
return err
}
_, err = armio.WriteAll(data, writer)
if err != nil {
return err
}
return nil
}