From 83bd37f18208c829a4ef293818f99f19401b71a5 Mon Sep 17 00:00:00 2001 From: Kelvin Clement Mwinuka Date: Sat, 22 Jul 2023 01:12:44 +0800 Subject: [PATCH] Moved server and client configs into their separate folders instead of in a shared utils folder --- client/config.go | 66 ++++++++++++++++++++++++++++++++++ client/main.go | 2 +- server/config.go | 78 ++++++++++++++++++++++++++++++++++++++++ server/main.go | 47 ++++-------------------- server/memberlist.go | 23 ++++++++++++ server/raft.go | 52 +++++++++++++++++++++++++++ utils/utils.go | 85 -------------------------------------------- 7 files changed, 226 insertions(+), 127 deletions(-) create mode 100644 client/config.go create mode 100644 server/config.go create mode 100644 server/memberlist.go create mode 100644 server/raft.go diff --git a/client/config.go b/client/config.go new file mode 100644 index 0000000..fe1b8b9 --- /dev/null +++ b/client/config.go @@ -0,0 +1,66 @@ +package main + +import ( + "encoding/json" + "flag" + "os" + "path" + + "gopkg.in/yaml.v3" +) + +type Config struct { + TLS bool `json:"tls" yaml:"tls"` + Key string `json:"key" yaml:"key"` + Cert string `json:"cert" yaml:"cert"` + Port uint16 `json:"port" yaml:"port"` + Addr string `json:"addr" yaml:"addr"` +} + +func GetConfig() Config { + // Shared + tls := flag.Bool("tls", false, "Start the server in TLS mode. Default is false") + key := flag.String("key", "", "The private key file path.") + cert := flag.String("cert", "", "The signed certificate file path.") + port := flag.Int("port", 7480, "Port to use. Default is 7480") + config := flag.String( + "config", + "", + `File path to a JSON or YAML config file.The values in this config file will override the flag values.`, + ) + addr := flag.String("addr", "127.0.0.1", "On client, this is the address of a server node to connect to.") + + flag.Parse() + + var conf Config + + if len(*config) > 0 { + // Load config from config file + if f, err := os.Open(*config); err != nil { + panic(err) + } else { + defer f.Close() + + ext := path.Ext(f.Name()) + + if ext == ".json" { + json.NewDecoder(f).Decode(&conf) + } + + if ext == ".yaml" || ext == ".yml" { + yaml.NewDecoder(f).Decode(&conf) + } + } + + } else { + conf = Config{ + TLS: *tls, + Key: *key, + Cert: *cert, + Addr: *addr, + Port: uint16(*port), + } + } + + return conf +} diff --git a/client/main.go b/client/main.go index c4e7a11..5c79b7e 100644 --- a/client/main.go +++ b/client/main.go @@ -14,7 +14,7 @@ import ( ) func main() { - conf := utils.GetConfig() + conf := GetConfig() var conn net.Conn var err error diff --git a/server/config.go b/server/config.go new file mode 100644 index 0000000..723a253 --- /dev/null +++ b/server/config.go @@ -0,0 +1,78 @@ +package main + +import ( + "encoding/json" + "flag" + "os" + "path" + + "gopkg.in/yaml.v3" +) + +type Config struct { + TLS bool `json:"tls" yaml:"tls"` + Key string `json:"key" yaml:"key"` + Cert string `json:"cert" yaml:"cert"` + Port uint16 `json:"port" yaml:"port"` + HTTP bool `json:"http" yaml:"http"` + Plugins string `json:"plugins" yaml:"plugins"` + ClusterPort uint16 `json:"clusterPort" yaml:"clusterPort"` + ServerID string `json:"serverId" yaml:"serverId"` + JoinAddr string `json:"joinAddr" yaml:"joinAddr"` + Addr string +} + +func GetConfig() Config { + tls := flag.Bool("tls", false, "Start the server in TLS mode. Default is false") + key := flag.String("key", "", "The private key file path.") + cert := flag.String("cert", "", "The signed certificate file path.") + port := flag.Int("port", 7480, "Port to use. Default is 7480") + http := flag.Bool("http", false, "Use HTTP protocol instead of raw TCP. Default is false") + plugins := flag.String("plugins", ".", "The path to the plugins folder.") + clusterPort := flag.Int("clusterPort", 7481, "Port to use for intra-cluster communication. Leave on the client.") + 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.") + 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() + + var conf Config + + if len(*config) > 0 { + // Load config from config file + if f, err := os.Open(*config); err != nil { + panic(err) + } else { + defer f.Close() + + ext := path.Ext(f.Name()) + + if ext == ".json" { + json.NewDecoder(f).Decode(&conf) + } + + if ext == ".yaml" || ext == ".yml" { + yaml.NewDecoder(f).Decode(&conf) + } + } + + } else { + conf = Config{ + TLS: *tls, + Key: *key, + Cert: *cert, + HTTP: *http, + Port: uint16(*port), + ClusterPort: uint16(*clusterPort), + ServerID: *serverId, + Plugins: *plugins, + JoinAddr: *joinAddr, + } + } + + return conf +} diff --git a/server/main.go b/server/main.go index 3d153a1..8474b2a 100644 --- a/server/main.go +++ b/server/main.go @@ -34,7 +34,7 @@ type Data struct { } type Server struct { - config utils.Config + config Config data Data plugins []Plugin raft *raft.Raft @@ -221,40 +221,9 @@ func (server *Server) LoadPlugins() { } } -// Implement raft.FSM interface -func (server *Server) Apply(log *raft.Log) interface{} { - return nil -} - -func (server *Server) Snapshot() (raft.FSMSnapshot, error) { - return nil, nil -} - -func (server *Server) Restore(snapshot io.ReadCloser) error { - return nil -} - -// Implement raft.StableStore interface -func (server *Server) Set(key []byte, value []byte) error { - return nil -} - -func (server *Server) Get(key []byte) ([]byte, error) { - return []byte{}, nil -} - -func (server *Server) SetUint64(key []byte, val uint64) error { - return nil -} - -func (server *Server) GetUint64(key []byte) (uint64, error) { - return 0, nil -} - func (server *Server) Start() { server.data.data = make(map[string]interface{}) - server.config = utils.GetConfig() conf := server.config server.LoadPlugins() @@ -313,14 +282,6 @@ func (server *Server) Start() { server.raft = raftServer if conf.JoinAddr == "" { - // Start memberlist cluster - memberList, err := memberlist.Create(memberlist.DefaultLocalConfig()) - if err != nil { - log.Fatal("Could not start memberlist cluster.") - } - - server.memberList = memberList - // Bootstrap raft cluster if err := server.raft.BootstrapCluster(raft.Configuration{ Servers: []raft.Server{ @@ -360,6 +321,10 @@ func getServerAddresses() (string, error) { } func main() { - server := &Server{} + config := GetConfig() + + server := &Server{ + config: config, + } server.Start() } diff --git a/server/memberlist.go b/server/memberlist.go new file mode 100644 index 0000000..d6e1761 --- /dev/null +++ b/server/memberlist.go @@ -0,0 +1,23 @@ +package main + +import ( + "log" + + "github.com/hashicorp/memberlist" +) + +func (server *Server) MemberListInit() { + // Triggered before RaftInit + memberList, err := memberlist.Create(memberlist.DefaultLocalConfig()) + if err != nil { + log.Fatal("Could not start memberlist cluster.") + } + + server.memberList = memberList +} + +func (server *Server) ShutdownMemberList() { + // Triggered after RaftShutdown + // Gracefully leave memberlist cluster + // Broadcast message to remove current node from raft cluster +} diff --git a/server/raft.go b/server/raft.go new file mode 100644 index 0000000..57c279f --- /dev/null +++ b/server/raft.go @@ -0,0 +1,52 @@ +package main + +import ( + "io" + + "github.com/hashicorp/raft" +) + +func (server *Server) RaftInit() { + // Triggered after MemberList init +} + +func (server *Server) RaftShutdown() { + // Triggered before MemberListShutdown + // Leadership transfer if current node is the leader + // Shutdown of the raft server +} + +// Implement raft.FSM interface +func (server *Server) Apply(log *raft.Log) interface{} { + return nil +} + +// Implement raft.FSM interface +func (server *Server) Snapshot() (raft.FSMSnapshot, error) { + return nil, nil +} + +// Implement raft.FSM interface +func (server *Server) Restore(snapshot io.ReadCloser) error { + return nil +} + +// Implements raft.StableStore interface +func (server *Server) Set(key []byte, value []byte) error { + return nil +} + +// Implements raft.StableStore interface +func (server *Server) Get(key []byte) ([]byte, error) { + return []byte{}, nil +} + +// Implements raft.StableStore interface +func (server *Server) SetUint64(key []byte, val uint64) error { + return nil +} + +// Implements raft.StableStore interface +func (server *Server) GetUint64(key []byte) (uint64, error) { + return 0, nil +} diff --git a/utils/utils.go b/utils/utils.go index d37c30d..90f4966 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -4,101 +4,16 @@ import ( "bufio" "bytes" "encoding/csv" - "encoding/json" "errors" - "flag" "fmt" "math" "math/big" - "os" - "path" "reflect" "strings" "github.com/tidwall/resp" - "gopkg.in/yaml.v3" ) -type Config struct { - // Shared - TLS bool `json:"tls" yaml:"tls"` - Key string `json:"key" yaml:"key"` - Cert string `json:"cert" yaml:"cert"` - Port uint16 `json:"port" yaml:"port"` - - // Server Only - HTTP bool `json:"http" yaml:"http"` - Plugins string `json:"plugins" yaml:"plugins"` - ClusterPort uint16 `json:"clusterPort" yaml:"clusterPort"` - ServerID string `json:"serverId" yaml:"serverId"` - JoinAddr string `json:"joinAddr" yaml:"joinAddr"` - - // Client Only - Addr string `json:"addr" yaml:"addr"` -} - -func GetConfig() Config { - // Shared - tls := flag.Bool("tls", false, "Start the server in TLS mode. Default is false") - key := flag.String("key", "", "The private key file path.") - cert := flag.String("cert", "", "The signed certificate file path.") - port := flag.Int("port", 7480, "Port to use. Default is 7480") - config := flag.String( - "config", - "", - `File path to a JSON or YAML config file.The values in this config file will override the flag values.`, - ) - - // Server Only - http := flag.Bool("http", false, "Use HTTP protocol instead of raw TCP. Default is false") - plugins := flag.String("plugins", ".", "The path to the plugins folder.") - clusterPort := flag.Int("clusterPort", 7481, "Port to use for intra-cluster communication. Leave on the client.") - 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.") - - // Client Only - addr := flag.String("addr", "127.0.0.1", "On client, this is the address of a server node to connect to.") - - flag.Parse() - - var conf Config - - if len(*config) > 0 { - // Load config from config file - if f, err := os.Open(*config); err != nil { - panic(err) - } else { - defer f.Close() - - ext := path.Ext(f.Name()) - - if ext == ".json" { - json.NewDecoder(f).Decode(&conf) - } - - if ext == ".yaml" || ext == ".yml" { - yaml.NewDecoder(f).Decode(&conf) - } - } - - } else { - conf = Config{ - TLS: *tls, - Key: *key, - Cert: *cert, - HTTP: *http, - Addr: *addr, - Port: uint16(*port), - ClusterPort: uint16(*clusterPort), - ServerID: *serverId, - Plugins: *plugins, - JoinAddr: *joinAddr, - } - } - - return conf -} - func Contains[T comparable](arr []T, elem T) bool { for _, v := range arr { if v == elem {