mirror of
https://github.com/EchoVault/SugarDB.git
synced 2025-10-19 22:34:40 +08:00
169 lines
6.4 KiB
Go
169 lines
6.4 KiB
Go
package utils
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"flag"
|
|
"log"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type Config struct {
|
|
TLS bool `json:"TLS" yaml:"TLS"`
|
|
MTLS bool `json:"MTLS" yaml:"MTLS"`
|
|
CertKeyPairs [][]string `json:"CertKeyPairs" yaml:"CertKeyPairs"`
|
|
ClientCAs []string `json:"ClientCAs" yaml:"ClientCAs"`
|
|
Port uint16 `json:"Port" yaml:"Port"`
|
|
PluginDir string `json:"Plugins" yaml:"Plugins"`
|
|
ServerID string `json:"ServerId" yaml:"ServerId"`
|
|
JoinAddr string `json:"JoinAddr" yaml:"JoinAddr"`
|
|
BindAddr string `json:"BindAddr" yaml:"BindAddr"`
|
|
RaftBindPort uint16 `json:"RaftPort" yaml:"RaftPort"`
|
|
MemberListBindPort uint16 `json:"MlPort" yaml:"MlPort"`
|
|
InMemory bool `json:"InMemory" yaml:"InMemory"`
|
|
DataDir string `json:"DataDir" yaml:"DataDir"`
|
|
BootstrapCluster bool `json:"BootstrapCluster" yaml:"BootstrapCluster"`
|
|
AclConfig string `json:"AclConfig" yaml:"AclConfig"`
|
|
ForwardCommand bool `json:"ForwardCommand" yaml:"ForwardCommand"`
|
|
RequirePass bool `json:"RequirePass" yaml:"RequirePass"`
|
|
Password string `json:"Password" yaml:"Password"`
|
|
SnapShotThreshold uint64 `json:"SnapshotThreshold" yaml:"SnapshotThreshold"`
|
|
SnapshotInterval time.Duration `json:"SnapshotInterval" yaml:"SnapshotInterval"`
|
|
RestoreSnapshot bool `json:"RestoreSnapshot" yaml:"RestoreSnapshot"`
|
|
RestoreAOF bool `json:"RestoreAOF" yaml:"RestoreAOF"`
|
|
}
|
|
|
|
func GetConfig() (Config, error) {
|
|
var certKeyPairs [][]string
|
|
var clientCAs []string
|
|
|
|
flag.Func("certKeyPair",
|
|
"A pair of file paths representing the signed certificate and it's corresponding key separated by a comma.",
|
|
func(s string) error {
|
|
pair := strings.Split(strings.TrimSpace(s), ",")
|
|
for i := 0; i < len(pair); i++ {
|
|
pair[i] = strings.TrimSpace(pair[i])
|
|
}
|
|
if len(pair) != 2 {
|
|
return errors.New("certKeyPair must be 2 comma separated strings")
|
|
}
|
|
certKeyPairs = append(certKeyPairs, pair)
|
|
return nil
|
|
})
|
|
|
|
flag.Func("clientCA", "Path to certificate authority used to verify client certificates.", func(s string) error {
|
|
clientCAs = append(clientCAs, s)
|
|
return nil
|
|
})
|
|
|
|
tls := flag.Bool("tls", false, "Start the server in TLS mode. Default is false")
|
|
mtls := flag.Bool("mtls", false, "Use mTLS to verify the client.")
|
|
port := flag.Int("port", 7480, "Port to use. Default is 7480")
|
|
pluginDir := flag.String("pluginDir", "", "Directory where plugins are located.")
|
|
serverId := flag.String("serverId", "1", "Server ID in raft cluster. Leave empty for client.")
|
|
joinAddr := flag.String("joinAddr", "", "Address of cluster member in a cluster to you want to join.")
|
|
bindAddr := flag.String("bindAddr", "", "Address to bind the server to.")
|
|
raftBindPort := flag.Uint("raftPort", 7481, "Port to use for intra-cluster communication. Leave on the client.")
|
|
mlBindPort := flag.Uint("mlPort", 7946, "Port to use for memberlist communication.")
|
|
inMemory := flag.Bool("inMemory", false, "Whether to use memory or persistent storage for raft logs and snapshots.")
|
|
dataDir := flag.String("dataDir", "/var/lib/memstore", "Directory to store raft snapshots and logs.")
|
|
bootstrapCluster := flag.Bool("bootstrapCluster", false, "Whether this instance should bootstrap a new cluster.")
|
|
aclConfig := flag.String("aclConfig", "", "ACL config file path.")
|
|
snapshotThreshold := flag.Uint64("snapshotThreshold", 1000, "The number of entries that trigger a snapshot. Default is 1000.")
|
|
snapshotInterval := flag.Duration("snapshotInterval", 5*time.Minute, "The time interval between snapshots (in seconds). Default is 5 minutes.")
|
|
restoreSnapshot := flag.Bool("restoreSnapshot", false, "This flag prompts the server to restore state from snapshot when set to true. Only works in standalone mode. Higher priority than restoreAOF.")
|
|
restoreAOF := flag.Bool("restoreAOF", false, "This flag prompts the server to restore state from append-only logs. Only works in standalone mode. Lower priority than restoreSnapshot.")
|
|
forwardCommand := flag.Bool(
|
|
"forwardCommand",
|
|
false,
|
|
"If the node is a follower, this flag forwards mutation command to the leader when set to true")
|
|
requirePass := flag.Bool(
|
|
"requirePass",
|
|
false,
|
|
"Whether the server should require a password before allowing commands. Default is false.",
|
|
)
|
|
password := flag.String(
|
|
"password",
|
|
"",
|
|
`The password for the default user. ACL config file will overwrite this value.
|
|
It is a plain text value by default but you can provide a SHA256 hash by adding a '#' before the hash.`,
|
|
)
|
|
|
|
config := flag.String(
|
|
"config",
|
|
"",
|
|
`File path to a JSON or YAML config file.The values in this config file will override the flag values.`,
|
|
)
|
|
|
|
flag.Parse()
|
|
|
|
conf := Config{
|
|
CertKeyPairs: certKeyPairs,
|
|
ClientCAs: clientCAs,
|
|
TLS: *tls,
|
|
MTLS: *mtls,
|
|
PluginDir: *pluginDir,
|
|
Port: uint16(*port),
|
|
ServerID: *serverId,
|
|
JoinAddr: *joinAddr,
|
|
BindAddr: *bindAddr,
|
|
RaftBindPort: uint16(*raftBindPort),
|
|
MemberListBindPort: uint16(*mlBindPort),
|
|
InMemory: *inMemory,
|
|
DataDir: *dataDir,
|
|
BootstrapCluster: *bootstrapCluster,
|
|
AclConfig: *aclConfig,
|
|
ForwardCommand: *forwardCommand,
|
|
RequirePass: *requirePass,
|
|
Password: *password,
|
|
SnapShotThreshold: *snapshotThreshold,
|
|
SnapshotInterval: *snapshotInterval,
|
|
RestoreSnapshot: *restoreSnapshot,
|
|
RestoreAOF: *restoreAOF,
|
|
}
|
|
|
|
if len(*config) > 0 {
|
|
// Override configurations from file
|
|
if f, err := os.Open(*config); err != nil {
|
|
panic(err)
|
|
} else {
|
|
defer func() {
|
|
if err = f.Close(); err != nil {
|
|
log.Println(err)
|
|
}
|
|
}()
|
|
|
|
ext := path.Ext(f.Name())
|
|
|
|
if ext == ".json" {
|
|
err := json.NewDecoder(f).Decode(&conf)
|
|
if err != nil {
|
|
return Config{}, nil
|
|
}
|
|
}
|
|
|
|
if ext == ".yaml" || ext == ".yml" {
|
|
err := yaml.NewDecoder(f).Decode(&conf)
|
|
if err != nil {
|
|
return Config{}, err
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// If requirePass is set to true, then password must be provided as well
|
|
var err error = nil
|
|
|
|
if conf.RequirePass && conf.Password == "" {
|
|
err = errors.New("password cannot be empty if requirePass is etc to true")
|
|
}
|
|
|
|
return conf, err
|
|
}
|