Skip to content

Commit

Permalink
Create Config struct to configure Server
Browse files Browse the repository at this point in the history
  • Loading branch information
aalda committed Dec 3, 2018
1 parent 808f84a commit 0d6c560
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 113 deletions.
52 changes: 16 additions & 36 deletions cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,7 @@ import (
func newStartCommand() *cobra.Command {
const defaultKeyPath = "~/.ssh/id_ed25519"

var (
nodeId, httpAddr, raftAddr, mgmtAddr, joinAddr string
dbPath, raftPath, privateKeyPath string
gossipAddr string
gossipJoinAddr []string
profiling, tampering bool
)
conf := server.DefaultConfig()

cmd := &cobra.Command{
Use: "start",
Expand All @@ -46,26 +40,12 @@ func newStartCommand() *cobra.Command {

Run: func(cmd *cobra.Command, args []string) {

if privateKeyPath == defaultKeyPath {
if conf.PrivateKeyPath == defaultKeyPath {
usr, _ := user.Current()
privateKeyPath = fmt.Sprintf("%s/.ssh/id_ed25519", usr.HomeDir)
conf.PrivateKeyPath = fmt.Sprintf("%s/.ssh/id_ed25519", usr.HomeDir)
}

srv, err := server.NewServer(
nodeId,
httpAddr,
raftAddr,
mgmtAddr,
joinAddr,
dbPath,
raftPath,
gossipAddr,
gossipJoinAddr,
privateKeyPath,
apiKey,
profiling,
tampering,
)
srv, err := server.NewServer(conf)

if err != nil {
log.Fatalf("Can't start QED server: %v", err)
Expand All @@ -80,20 +60,20 @@ func newStartCommand() *cobra.Command {
}

hostname, _ := os.Hostname()
cmd.Flags().StringVarP(&nodeId, "node-id", "", hostname, "Unique name for node. If not set, fallback to hostname")
cmd.Flags().StringVarP(&httpAddr, "http-addr", "", ":8080", "Endpoint for REST requests on (host:port)")
cmd.Flags().StringVarP(&raftAddr, "raft-addr", "", ":9000", "Raft bind address (host:port)")
cmd.Flags().StringVarP(&mgmtAddr, "mgmt-addr", "", ":8090", "Management endpoint bind address (host:port)")
cmd.Flags().StringVarP(&joinAddr, "join-addr", "", "", "Raft: Comma-delimited list of nodes ([host]:port), through which a cluster can be joined")
cmd.Flags().StringVarP(&gossipAddr, "gossip-addr", "", ":9100", "Gossip: management endpoint bind address (host:port)")
cmd.Flags().StringSliceVarP(&gossipJoinAddr, "gossip-join-addr", "", []string{}, "Gossip: Comma-delimited list of nodes ([host]:port), through which a cluster can be joined")
cmd.Flags().StringVarP(&dbPath, "dbpath", "p", "/var/tmp/qed/data", "Set default storage path")
cmd.Flags().StringVarP(&raftPath, "raftpath", "", "/var/tmp/qed/raft", "Set raft storage path")
cmd.Flags().StringVarP(&privateKeyPath, "keypath", "y", defaultKeyPath, "Path to the ed25519 key file")
cmd.Flags().BoolVarP(&profiling, "profiling", "f", false, "Allow a pprof url (localhost:6060) for profiling purposes")
cmd.Flags().StringVar(&conf.NodeID, "node-id", hostname, "Unique name for node. If not set, fallback to hostname")
cmd.Flags().StringVar(&conf.HttpAddr, "http-addr", ":8080", "Endpoint for REST requests on (host:port)")
cmd.Flags().StringVar(&conf.RaftAddr, "raft-addr", ":9000", "Raft bind address (host:port)")
cmd.Flags().StringVar(&conf.MgmtAddr, "mgmt-addr", ":8090", "Management endpoint bind address (host:port)")
cmd.Flags().StringSliceVar(&conf.RaftJoinAddr, "join-addr", []string{}, "Raft: Comma-delimited list of nodes ([host]:port), through which a cluster can be joined")
cmd.Flags().StringVar(&conf.GossipAddr, "gossip-addr", ":9100", "Gossip: management endpoint bind address (host:port)")
cmd.Flags().StringSliceVar(&conf.GossipJoinAddr, "gossip-join-addr", []string{}, "Gossip: Comma-delimited list of nodes ([host]:port), through which a cluster can be joined")
cmd.Flags().StringVarP(&conf.DBPath, "dbpath", "p", "/var/tmp/qed/data", "Set default storage path")
cmd.Flags().StringVar(&conf.RaftPath, "raftpath", "/var/tmp/qed/raft", "Set raft storage path")
cmd.Flags().StringVarP(&conf.PrivateKeyPath, "keypath", "y", defaultKeyPath, "Path to the ed25519 key file")
cmd.Flags().BoolVarP(&conf.EnableProfiling, "profiling", "f", false, "Allow a pprof url (localhost:6060) for profiling purposes")

// INFO: testing purposes
cmd.Flags().BoolVar(&tampering, "tampering", false, "Allow tampering api for proof demostrations")
cmd.Flags().BoolVar(&conf.EnableTampering, "tampering", false, "Allow tampering api for proof demostrations")
cmd.Flags().MarkHidden("tampering")

return cmd
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ cloud.google.com/go v0.28.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/VictoriaMetrics/fastcache v1.0.2 h1:dj179vXczNtKDLjmiOHRasMMv437rPpUtX/bpojmyyc=
github.com/VictoriaMetrics/fastcache v1.0.2/go.mod h1:4zLf+tCNHtaJzQfIkJ+vBXS1O98gXA/KbKtUv/W1Tdo=
github.com/allegro/bigcache v1.1.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/armon/go-metrics v0.0.0-20180713145231-3c58d8115a78 h1:mdRSArcFLfW0VoL34LZAKSz6LkkK4jFxVx2xYavACMg=
Expand Down
2 changes: 1 addition & 1 deletion gossip/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ type Config struct {
// we leave.
LeavePropagateDelay time.Duration

// MemberlistConfig is the memberlist configuration that Aidotpr will
// MemberlistConfig is the memberlist configuration that Agent will
// use to do the underlying membership management and gossip. Some
// fields in the MemberlistConfig will be overwritten by Auditor no
// matter what:
Expand Down
106 changes: 106 additions & 0 deletions server/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
Copyright 2018 Banco Bilbao Vizcaya Argentaria, S.A.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package server

import (
"net"
"os"
"path/filepath"
)

type Config struct {
// Unique name for this node. It identifies itself both in raft and
// gossip clusters. If not set, fallback to hostname.
NodeID string

// HTTP server bind address/port.
HttpAddr string

// Raft communication bind address/port.
RaftAddr string

// Raft management server bind address/port. Useful to join the cluster
// and get cluster information.
MgmtAddr string

// List of raft nodes, through which a cluster can be joined
// (protocol://host:port).
RaftJoinAddr []string

// Path to storage directory.
DBPath string

// Path to Raft storage directory.
RaftPath string

// Gossip management server bind address/port.
GossipAddr string

// List of nodes, through which a gossip cluster can be joined (protocol://host:port).
GossipJoinAddr []string

// Path to the private key file used to sign snapshots.
PrivateKeyPath string

// Enables profiling endpoint.
EnableProfiling bool

// Enables tampering endpoint.
EnableTampering bool
}

func DefaultConfig() *Config {
hostname, _ := os.Hostname()
currentDir := getCurrentDir()
return &Config{
NodeID: hostname,
HttpAddr: "127.0.0.1:8080",
RaftAddr: "127.0.0.1:9000",
MgmtAddr: "127.0.0.1:8090",
RaftJoinAddr: []string{},
GossipAddr: "127.0.0.1:9100",
GossipJoinAddr: []string{},
DBPath: currentDir + "/data",
RaftPath: currentDir + "/raft",
EnableProfiling: false,
EnableTampering: false,
}
}

func getCurrentDir() string {
ex, err := os.Executable()
if err != nil {
panic(err)
}
exPath := filepath.Dir(ex)
return exPath
}

// AddrParts returns the parts of and address/port.
func addrParts(address string) (string, int, error) {
_, _, err := net.SplitHostPort(address)
if err != nil {
return "", 0, err
}

addr, err := net.ResolveTCPAddr("tcp", address)
if err != nil {
return "", 0, err
}

return addr.IP.String(), addr.Port, nil
}
94 changes: 27 additions & 67 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,10 @@ import (
"github.com/bbva/qed/storage/badger"
)

type Store interface {
Add(key []byte, value []byte) error
GetRange(start, end []byte) [][]byte
Get(key []byte) ([]byte, error)
Close() error
}

// Server encapsulates the data and login to start/stop a QED server
type Server struct {
nodeID string // unique name for node. If not set, fallback to hostname
httpAddr string // HTTP server bind address
raftAddr string // Raft communication bind address
mgmtAddr string // Raft: management server bind address
joinAddr string // Comma-delimited list of nodes, through which a cluster can be joined (protocol://host:port)
dbPath string // Path to storage directory
raftPath string // Path to Raft storage directory
gossipAddr string // Gossip: management server bind address
gossipJoinAddr []string // Gossip: Comma-delimited list of nodes, through which a cluster can be joined (protocol://host:port)
privateKeyPath string // Path to the private key file used to sign snapshot
apiKey string
bootstrap bool // Set bootstrap to true when bringing up the first node as a master
conf *Config
bootstrap bool // Set bootstrap to true when bringing up the first node as a master

httpServer *http.Server
mgmtServer *http.Server
Expand All @@ -77,75 +60,52 @@ type Server struct {
agentsQueue chan *protocol.Snapshot
}

// NewServer synthesizes a new Server based on the parameters it receives.
func NewServer(
nodeID string,
httpAddr string,
raftAddr string,
mgmtAddr string,
joinAddr string,
dbPath string,
raftPath string,
gossipAddr string,
gossipJoinAddr []string,
privateKeyPath string,
apiKey string,
enableProfiling bool,
enableTampering bool,
) (*Server, error) {
// NewServer creates a new Server based on the parameters it receives.
func NewServer(conf *Config) (*Server, error) {

bootstrap := false
if joinAddr == "" {
if len(conf.RaftJoinAddr) <= 0 {
bootstrap = true
}

server := &Server{
nodeID: nodeID,
httpAddr: httpAddr,
raftAddr: raftAddr,
mgmtAddr: mgmtAddr,
joinAddr: joinAddr,
dbPath: dbPath,
raftPath: raftPath,
gossipAddr: gossipAddr,
gossipJoinAddr: gossipJoinAddr,
apiKey: apiKey,
bootstrap: bootstrap,
conf: conf,
bootstrap: bootstrap,
}

log.Infof("ensuring directory at %s exists", dbPath)
if err := os.MkdirAll(dbPath, 0755); err != nil {
log.Infof("ensuring directory at %s exists", conf.DBPath)
if err := os.MkdirAll(conf.DBPath, 0755); err != nil {
return nil, err
}

log.Infof("ensuring directory at %s exists", raftPath)
if err := os.MkdirAll(raftPath, 0755); err != nil {
log.Infof("ensuring directory at %s exists", conf.RaftPath)
if err := os.MkdirAll(conf.RaftPath, 0755); err != nil {
return nil, err
}

// Open badger store
store, err := badger.NewBadgerStoreOpts(&badger.Options{Path: dbPath, ValueLogGC: true})
store, err := badger.NewBadgerStoreOpts(&badger.Options{Path: conf.DBPath, ValueLogGC: true})
if err != nil {
return nil, err
}

// Create signer
server.signer, err = sign.NewEd25519SignerFromFile(privateKeyPath)
server.signer, err = sign.NewEd25519SignerFromFile(conf.PrivateKeyPath)
if err != nil {
return nil, err
}

// Create gossip agent
config := gossip.DefaultConfig()
config.BindAddr = gossipAddr
config.BindAddr = conf.GossipAddr
config.Role = member.Server
server.agent, err = gossip.NewAgent(config, nil)
if err != nil {
return nil, err
}

if len(gossipJoinAddr) > 0 {
server.agent.Join(gossipJoinAddr)
if len(conf.GossipJoinAddr) > 0 {
server.agent.Join(conf.GossipJoinAddr)
}

// TODO: add queue size to config
Expand All @@ -155,21 +115,21 @@ func NewServer(
server.sender = sender.NewSender(server.agent, sender.DefaultConfig(), server.signer)

// Create RaftBalloon
server.raftBalloon, err = raftwal.NewRaftBalloon(raftPath, raftAddr, nodeID, store, server.agentsQueue)
server.raftBalloon, err = raftwal.NewRaftBalloon(conf.RaftPath, conf.RaftAddr, conf.NodeID, store, server.agentsQueue)
if err != nil {
return nil, err
}

// Create http endpoints
server.httpServer = newHTTPServer(server.httpAddr, server.raftBalloon)
server.httpServer = newHTTPServer(conf.HttpAddr, server.raftBalloon)

// Create management endpoints
server.mgmtServer = newMgmtServer(server.mgmtAddr, server.raftBalloon)
server.mgmtServer = newMgmtServer(conf.MgmtAddr, server.raftBalloon)

if enableTampering {
if conf.EnableTampering {
server.tamperingServer = newTamperingServer("localhost:8081", store, hashing.NewSha256Hasher())
}
if enableProfiling {
if conf.EnableProfiling {
server.profilingServer = newProfilingServer("localhost:6060")
}

Expand Down Expand Up @@ -219,25 +179,25 @@ func (s *Server) Start() error {
}

go func() {
log.Debug(" * Starting QED API HTTP server in addr: ", s.httpAddr)
log.Debug(" * Starting QED API HTTP server in addr: ", s.conf.HttpAddr)
if err := s.httpServer.ListenAndServe(); err != http.ErrServerClosed {
log.Errorf("Can't start QED API HTTP Server: %s", err)
}
}()

go func() {
log.Debug(" * Starting QED MGMT HTTP server in addr: ", s.mgmtAddr)
log.Debug(" * Starting QED MGMT HTTP server in addr: ", s.conf.MgmtAddr)
if err := s.mgmtServer.ListenAndServe(); err != http.ErrServerClosed {
log.Errorf("Can't start QED MGMT HTTP Server: %s", err)
}
}()

log.Debugf(" ready on %s and %s\n", s.httpAddr, s.mgmtAddr)
log.Debugf(" ready on %s and %s\n", s.conf.HttpAddr, s.conf.MgmtAddr)

if !s.bootstrap {
log.Debug(" * Joining existent cluster QED MGMT HTTP server in addr: ", s.mgmtAddr)
if err := join(s.joinAddr, s.raftAddr, s.nodeID); err != nil {
log.Fatalf("failed to join node at %s: %s", s.joinAddr, err.Error())
log.Debug(" * Joining existent cluster QED MGMT HTTP server in addr: ", s.conf.MgmtAddr)
if err := join(s.conf.RaftJoinAddr[0], s.conf.RaftAddr, s.conf.NodeID); err != nil {
log.Fatalf("failed to join node at %s: %s", s.conf.RaftJoinAddr[0], err.Error())
}
}

Expand Down
Loading

0 comments on commit 0d6c560

Please sign in to comment.