Bläddra i källkod

config: make config a self-contained pkg

Xiang Li 11 år sedan
förälder
incheckning
02c854717b
6 ändrade filer med 176 tillägg och 29 borttagningar
  1. 25 0
      config/cluster_config.go
  2. 14 15
      config/config.go
  3. 32 0
      config/default.go
  4. 0 9
      config/timeout.go
  5. 105 0
      config/tls_config.go
  6. 0 5
      server/listener.go

+ 25 - 0
config/cluster_config.go

@@ -0,0 +1,25 @@
+package config
+
+// ClusterConfig represents cluster-wide configuration settings.
+type ClusterConfig struct {
+	// ActiveSize is the maximum number of node that can join as Raft followers.
+	// Nodes that join the cluster after the limit is reached are standbys.
+	ActiveSize int `json:"activeSize"`
+
+	// RemoveDelay is the amount of time, in seconds, after a node is
+	// unreachable that it will be swapped out as a standby node.
+	RemoveDelay float64 `json:"removeDelay"`
+
+	// SyncInterval is the amount of time, in seconds, between
+	// cluster sync when it runs in standby mode.
+	SyncInterval float64 `json:"syncInterval"`
+}
+
+// NewClusterConfig returns a cluster configuration with default settings.
+func NewClusterConfig() *ClusterConfig {
+	return &ClusterConfig{
+		ActiveSize:   DefaultActiveSize,
+		RemoveDelay:  DefaultRemoveDelay,
+		SyncInterval: DefaultSyncInterval,
+	}
+}

+ 14 - 15
config/config.go

@@ -18,7 +18,6 @@ import (
 
 	"github.com/coreos/etcd/log"
 	ustrings "github.com/coreos/etcd/pkg/strings"
-	"github.com/coreos/etcd/server"
 )
 
 // The default location for the etcd configuration file.
@@ -100,22 +99,22 @@ func New() *Config {
 	c := new(Config)
 	c.SystemPath = DefaultSystemConfigPath
 	c.Addr = "127.0.0.1:4001"
-	c.HTTPReadTimeout = server.DefaultReadTimeout
-	c.HTTPWriteTimeout = server.DefaultWriteTimeout
+	c.HTTPReadTimeout = DefaultReadTimeout
+	c.HTTPWriteTimeout = DefaultWriteTimeout
 	c.MaxResultBuffer = 1024
 	c.MaxRetryAttempts = 3
 	c.RetryInterval = 10.0
 	c.Snapshot = true
 	c.SnapshotCount = 10000
 	c.Peer.Addr = "127.0.0.1:7001"
-	c.Peer.HeartbeatInterval = defaultHeartbeatInterval
-	c.Peer.ElectionTimeout = defaultElectionTimeout
+	c.Peer.HeartbeatInterval = DefaultHeartbeatInterval
+	c.Peer.ElectionTimeout = DefaultElectionTimeout
 	rand.Seed(time.Now().UTC().UnixNano())
 	// Make maximum twice as minimum.
-	c.RetryInterval = float64(50+rand.Int()%50) * defaultHeartbeatInterval / 1000
-	c.Cluster.ActiveSize = server.DefaultActiveSize
-	c.Cluster.RemoveDelay = server.DefaultRemoveDelay
-	c.Cluster.SyncInterval = server.DefaultSyncInterval
+	c.RetryInterval = float64(50+rand.Int()%50) * DefaultHeartbeatInterval / 1000
+	c.Cluster.ActiveSize = DefaultActiveSize
+	c.Cluster.RemoveDelay = DefaultRemoveDelay
+	c.Cluster.SyncInterval = DefaultSyncInterval
 	return c
 }
 
@@ -386,8 +385,8 @@ func (c *Config) Sanitize() error {
 }
 
 // EtcdTLSInfo retrieves a TLSInfo object for the etcd server
-func (c *Config) EtcdTLSInfo() *server.TLSInfo {
-	return &server.TLSInfo{
+func (c *Config) EtcdTLSInfo() *TLSInfo {
+	return &TLSInfo{
 		CAFile:   c.CAFile,
 		CertFile: c.CertFile,
 		KeyFile:  c.KeyFile,
@@ -395,8 +394,8 @@ func (c *Config) EtcdTLSInfo() *server.TLSInfo {
 }
 
 // PeerRaftInfo retrieves a TLSInfo object for the peer server.
-func (c *Config) PeerTLSInfo() *server.TLSInfo {
-	return &server.TLSInfo{
+func (c *Config) PeerTLSInfo() *TLSInfo {
+	return &TLSInfo{
 		CAFile:   c.Peer.CAFile,
 		CertFile: c.Peer.CertFile,
 		KeyFile:  c.Peer.KeyFile,
@@ -414,8 +413,8 @@ func (c *Config) Trace() bool {
 	return c.strTrace == "*"
 }
 
-func (c *Config) ClusterConfig() *server.ClusterConfig {
-	return &server.ClusterConfig{
+func (c *Config) ClusterConfig() *ClusterConfig {
+	return &ClusterConfig{
 		ActiveSize:   c.Cluster.ActiveSize,
 		RemoveDelay:  c.Cluster.RemoveDelay,
 		SyncInterval: c.Cluster.SyncInterval,

+ 32 - 0
config/default.go

@@ -0,0 +1,32 @@
+package config
+
+import "time"
+
+const (
+	// The amount of time (in ms) to elapse without a heartbeat before becoming a candidate
+	DefaultElectionTimeout = 200
+
+	// The frequency (in ms) by which heartbeats are sent to followers.
+	DefaultHeartbeatInterval = 50
+
+	// DefaultActiveSize is the default number of active followers allowed.
+	DefaultActiveSize = 9
+
+	// MinActiveSize is the minimum active size allowed.
+	MinActiveSize = 3
+
+	// DefaultRemoveDelay is the default elapsed time before removal.
+	DefaultRemoveDelay = float64((30 * time.Minute) / time.Second)
+
+	// MinRemoveDelay is the minimum remove delay allowed.
+	MinRemoveDelay = float64((2 * time.Second) / time.Second)
+
+	// DefaultSyncInterval is the default interval for cluster sync.
+	DefaultSyncInterval = float64((5 * time.Second) / time.Second)
+
+	// MinSyncInterval is the minimum sync interval allowed.
+	MinSyncInterval = float64((1 * time.Second) / time.Second)
+
+	DefaultReadTimeout  = float64((5 * time.Minute) / time.Second)
+	DefaultWriteTimeout = float64((5 * time.Minute) / time.Second)
+)

+ 0 - 9
config/timeout.go

@@ -1,9 +0,0 @@
-package config
-
-const (
-	// The amount of time (in ms) to elapse without a heartbeat before becoming a candidate
-	defaultElectionTimeout = 200
-
-	// The frequency (in ms) by which heartbeats are sent to followers.
-	defaultHeartbeatInterval = 50
-)

+ 105 - 0
config/tls_config.go

@@ -0,0 +1,105 @@
+package config
+
+import (
+	"crypto/tls"
+	"crypto/x509"
+	"encoding/pem"
+	"fmt"
+	"io/ioutil"
+)
+
+// TLSInfo holds the SSL certificates paths.
+type TLSInfo struct {
+	CertFile string `json:"CertFile"`
+	KeyFile  string `json:"KeyFile"`
+	CAFile   string `json:"CAFile"`
+}
+
+func (info TLSInfo) Scheme() string {
+	if info.KeyFile != "" && info.CertFile != "" {
+		return "https"
+	} else {
+		return "http"
+	}
+}
+
+// Generates a tls.Config object for a server from the given files.
+func (info TLSInfo) ServerConfig() (*tls.Config, error) {
+	// Both the key and cert must be present.
+	if info.KeyFile == "" || info.CertFile == "" {
+		return nil, fmt.Errorf("KeyFile and CertFile must both be present[key: %v, cert: %v]", info.KeyFile, info.CertFile)
+	}
+
+	var cfg tls.Config
+
+	tlsCert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile)
+	if err != nil {
+		return nil, err
+	}
+
+	cfg.Certificates = []tls.Certificate{tlsCert}
+
+	if info.CAFile != "" {
+		cfg.ClientAuth = tls.RequireAndVerifyClientCert
+		cp, err := newCertPool(info.CAFile)
+		if err != nil {
+			return nil, err
+		}
+
+		cfg.RootCAs = cp
+		cfg.ClientCAs = cp
+	} else {
+		cfg.ClientAuth = tls.NoClientCert
+	}
+
+	return &cfg, nil
+}
+
+// Generates a tls.Config object for a client from the given files.
+func (info TLSInfo) ClientConfig() (*tls.Config, error) {
+	var cfg tls.Config
+
+	if info.KeyFile == "" || info.CertFile == "" {
+		return &cfg, nil
+	}
+
+	tlsCert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile)
+	if err != nil {
+		return nil, err
+	}
+
+	cfg.Certificates = []tls.Certificate{tlsCert}
+
+	if info.CAFile != "" {
+		cp, err := newCertPool(info.CAFile)
+		if err != nil {
+			return nil, err
+		}
+
+		cfg.RootCAs = cp
+	}
+
+	return &cfg, nil
+}
+
+// newCertPool creates x509 certPool with provided CA file
+func newCertPool(CAFile string) (*x509.CertPool, error) {
+	certPool := x509.NewCertPool()
+	pemByte, err := ioutil.ReadFile(CAFile)
+	if err != nil {
+		return nil, err
+	}
+
+	for {
+		var block *pem.Block
+		block, pemByte = pem.Decode(pemByte)
+		if block == nil {
+			return certPool, nil
+		}
+		cert, err := x509.ParseCertificate(block.Bytes)
+		if err != nil {
+			return nil, err
+		}
+		certPool.AddCert(cert)
+	}
+}

+ 0 - 5
server/listener.go

@@ -8,11 +8,6 @@ import (
 	"github.com/coreos/etcd/log"
 )
 
-const (
-	DefaultReadTimeout  = float64((5 * time.Minute) / time.Second)
-	DefaultWriteTimeout = float64((5 * time.Minute) / time.Second)
-)
-
 // TLSServerConfig generates tls configuration based on TLSInfo
 // If any error happens, this function will call log.Fatal
 func TLSServerConfig(info *TLSInfo) *tls.Config {