mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-24 06:47:44 +01:00
In this commit we add an extra config for enabling logging to an external file when using embedded etcd. This can be useful when running integration tests to see more details about etcd related issues.
116 lines
3 KiB
Go
116 lines
3 KiB
Go
// +build kvdb_etcd
|
|
|
|
package etcd
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"net/url"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"go.etcd.io/etcd/server/v3/embed"
|
|
)
|
|
|
|
const (
|
|
// readyTimeout is the time until the embedded etcd instance should start.
|
|
readyTimeout = 10 * time.Second
|
|
|
|
// defaultEtcdPort is the start of the range for listening ports of
|
|
// embedded etcd servers. Ports are monotonically increasing starting
|
|
// from this number and are determined by the results of getFreePort().
|
|
defaultEtcdPort = 2379
|
|
|
|
// defaultNamespace is the namespace we'll use in our embedded etcd
|
|
// instance. Since it is only used for testing, we'll use the namespace
|
|
// name "test/" for this. Note that the namespace can be any string,
|
|
// the trailing / is not required.
|
|
defaultNamespace = "test/"
|
|
)
|
|
|
|
var (
|
|
// lastPort is the last port determined to be free for use by a new
|
|
// embedded etcd server. It should be used atomically.
|
|
lastPort uint32 = defaultEtcdPort
|
|
)
|
|
|
|
// getFreePort returns the first port that is available for listening by a new
|
|
// embedded etcd server. It panics if no port is found and the maximum available
|
|
// TCP port is reached.
|
|
func getFreePort() int {
|
|
port := atomic.AddUint32(&lastPort, 1)
|
|
for port < 65535 {
|
|
// If there are no errors while attempting to listen on this
|
|
// port, close the socket and return it as available.
|
|
addr := fmt.Sprintf("127.0.0.1:%d", port)
|
|
l, err := net.Listen("tcp4", addr)
|
|
if err == nil {
|
|
err := l.Close()
|
|
if err == nil {
|
|
return int(port)
|
|
}
|
|
}
|
|
port = atomic.AddUint32(&lastPort, 1)
|
|
}
|
|
|
|
// No ports available? Must be a mistake.
|
|
panic("no ports available for listening")
|
|
}
|
|
|
|
// NewEmbeddedEtcdInstance creates an embedded etcd instance for testing,
|
|
// listening on random open ports. Returns the backend config and a cleanup
|
|
// func that will stop the etcd instance.
|
|
func NewEmbeddedEtcdInstance(path string, clientPort, peerPort uint16,
|
|
logFile string) (*Config, func(), error) {
|
|
|
|
cfg := embed.NewConfig()
|
|
cfg.Dir = path
|
|
|
|
// To ensure that we can submit large transactions.
|
|
cfg.MaxTxnOps = 8192
|
|
cfg.MaxRequestBytes = 16384 * 1024
|
|
cfg.Logger = "zap"
|
|
if logFile != "" {
|
|
cfg.LogLevel = "info"
|
|
cfg.LogOutputs = []string{logFile}
|
|
} else {
|
|
cfg.LogLevel = "error"
|
|
}
|
|
|
|
// Listen on random free ports if no ports were specified.
|
|
if clientPort == 0 {
|
|
clientPort = uint16(getFreePort())
|
|
}
|
|
|
|
if peerPort == 0 {
|
|
peerPort = uint16(getFreePort())
|
|
}
|
|
|
|
clientURL := fmt.Sprintf("127.0.0.1:%d", clientPort)
|
|
peerURL := fmt.Sprintf("127.0.0.1:%d", peerPort)
|
|
cfg.LCUrls = []url.URL{{Host: clientURL}}
|
|
cfg.LPUrls = []url.URL{{Host: peerURL}}
|
|
|
|
etcd, err := embed.StartEtcd(cfg)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
select {
|
|
case <-etcd.Server.ReadyNotify():
|
|
case <-time.After(readyTimeout):
|
|
etcd.Close()
|
|
return nil, nil,
|
|
fmt.Errorf("etcd failed to start after: %v", readyTimeout)
|
|
}
|
|
|
|
connConfig := &Config{
|
|
Host: "http://" + clientURL,
|
|
InsecureSkipVerify: true,
|
|
Namespace: defaultNamespace,
|
|
}
|
|
|
|
return connConfig, func() {
|
|
etcd.Close()
|
|
}, nil
|
|
}
|