mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
* use mainline etcd-io dependencies, not forks
this commit does lots of things around clustering with goal of increasing stability.
- upgrades from molecula/etcd to go.etcd.io/etcd@v3.5.4
- upgrades from seebs/bbolt to go.etcd.io/bbolt@v1.3.6
- update tests to use unix sockets for etcd cluster communication
- this is what etcd uses for a lot of internal testing, so if their devs think
it's a valid test, we can probably accept that
- cleanup etcd node-watcher shutdown process
Co-authored-by: tgruben <tgruben@gmail.com>
* moved random query to another repo
it had weird dependency issues with upgrading to mainline etcd bc of the vegeta dep
so we removed it bc no one really uses it anyway
we got this error message:
```
github.com/molecula/featurebase/v3/cmd/random-query imports
github.com/tsenart/vegeta/v12/lib tested by
github.com/tsenart/vegeta/v12/lib.test imports
github.com/streadway/quantile tested by
github.com/streadway/quantile.test imports
.: "." is relative, but relative import paths are not supported in module mode
```
* add cleanup to EtcdUnixSocket test util
Co-authored-by: reesporte <reesedporter@gmail.com>
165 lines
4 KiB
Go
165 lines
4 KiB
Go
// Copyright 2021 Molecula Corp. All rights reserved.
|
|
package test
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
"testing"
|
|
|
|
pilosa "github.com/molecula/featurebase/v3"
|
|
"github.com/molecula/featurebase/v3/etcd"
|
|
"github.com/molecula/featurebase/v3/server"
|
|
"github.com/molecula/featurebase/v3/testhook"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type Ports struct {
|
|
LsnC *net.TCPListener
|
|
PortC int
|
|
|
|
LsnP *net.TCPListener
|
|
PortP int
|
|
|
|
LsnG *net.TCPListener
|
|
Grpc int
|
|
}
|
|
|
|
func (ports *Ports) Close() error {
|
|
err := ports.LsnC.Close()
|
|
err2 := ports.LsnP.Close()
|
|
err3 := ports.LsnG.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err2 != nil {
|
|
return err2
|
|
}
|
|
return err3
|
|
}
|
|
|
|
// listenerWithURL builds a TCP listener and corresponding http://localhost:%d
|
|
// URL, and returns those.
|
|
func listenerWithURL() (listener *net.TCPListener, url string, err error) {
|
|
l, err := net.Listen("tcp", "localhost:0")
|
|
if err != nil {
|
|
return listener, url, err
|
|
}
|
|
listener = l.(*net.TCPListener)
|
|
port := listener.Addr().(*net.TCPAddr).Port
|
|
url = fmt.Sprintf("http://localhost:%d", port)
|
|
return listener, url, err
|
|
}
|
|
|
|
// GetPortsGenConfigs creates listener ports, and updates the configurations
|
|
// of servers to match these created ports, including cross-references
|
|
// like updating the InitCluster values in the Etcd configs.
|
|
func GetPortsGenConfigs(tb testing.TB, nodes []*Command) error {
|
|
peerUrls := make([]string, len(nodes))
|
|
for i := range nodes {
|
|
if nodes[i].Config == nil {
|
|
nodes[i].Config = &server.Config{}
|
|
}
|
|
config := nodes[i].Config
|
|
name := fmt.Sprintf("server%d", i)
|
|
clusterName := fmt.Sprintf("cluster-%s", tb.Name())
|
|
discoDir, err := testhook.TempDir(tb, "disco.")
|
|
if err != nil {
|
|
return errors.Wrap(err, "creating temp directory")
|
|
}
|
|
grpcListener, grpcUrl, err := listenerWithURL()
|
|
if err != nil {
|
|
return errors.Wrap(err, "creating gRPC listener")
|
|
}
|
|
// for grpc, we don't want the http part...
|
|
colon := strings.LastIndexByte(grpcUrl, ':')
|
|
if colon != -1 {
|
|
grpcUrl = grpcUrl[colon:]
|
|
}
|
|
config.Name = name
|
|
config.Cluster.Name = clusterName
|
|
config.BindGRPC = grpcUrl
|
|
config.GRPCListener = grpcListener
|
|
clientURL := pilosa.EtcdUnixSocket(tb)
|
|
peerURL := pilosa.EtcdUnixSocket(tb)
|
|
config.Etcd = etcd.Options{
|
|
Dir: discoDir,
|
|
LClientURL: clientURL,
|
|
AClientURL: clientURL,
|
|
LPeerURL: peerURL,
|
|
APeerURL: peerURL,
|
|
HeartbeatTTL: 60,
|
|
UnsafeNoFsync: true,
|
|
}
|
|
peerUrls[i] = fmt.Sprintf("%s=%s", name, peerURL)
|
|
}
|
|
allPeerUrls := strings.Join(peerUrls, ",")
|
|
for i := range nodes {
|
|
nodes[i].Config.Etcd.InitCluster = allPeerUrls
|
|
}
|
|
return nil
|
|
}
|
|
|
|
//GenPortsConfig creates specific configuration for etcd.
|
|
func GenPortsConfig(tb testing.TB, ports []Ports) []*server.Config {
|
|
cfgs := make([]*server.Config, len(ports))
|
|
clusterURLs := make([]string, len(ports))
|
|
for i := range cfgs {
|
|
name := fmt.Sprintf("server%d", i)
|
|
clusterName := "cluster-abc123"
|
|
|
|
lClientURL := pilosa.EtcdUnixSocket(tb)
|
|
lPeerURL := pilosa.EtcdUnixSocket(tb)
|
|
|
|
discoDir := ""
|
|
if d, err := testhook.TempDir(tb, "disco."); err == nil {
|
|
discoDir = d
|
|
}
|
|
|
|
cfgs[i] = &server.Config{
|
|
Name: name,
|
|
BindGRPC: fmt.Sprintf(":%d", ports[i].Grpc),
|
|
GRPCListener: ports[i].LsnG,
|
|
Etcd: etcd.Options{
|
|
Dir: discoDir,
|
|
LClientURL: lClientURL,
|
|
AClientURL: lClientURL,
|
|
LPeerURL: lPeerURL,
|
|
APeerURL: lPeerURL,
|
|
HeartbeatTTL: 5,
|
|
UnsafeNoFsync: true,
|
|
},
|
|
}
|
|
cfgs[i].Cluster.Name = clusterName
|
|
|
|
clusterURLs[i] = fmt.Sprintf("%s=%s", name, lPeerURL)
|
|
}
|
|
for i := range cfgs {
|
|
cfgs[i].Etcd.InitCluster = strings.Join(clusterURLs, ",")
|
|
}
|
|
|
|
return cfgs
|
|
}
|
|
|
|
func NewPorts(lsn []*net.TCPListener) []Ports {
|
|
var out []Ports
|
|
|
|
n := len(lsn)
|
|
ports := make([]int, n)
|
|
for i := 0; i < n; i++ {
|
|
ports[i] = lsn[i].Addr().(*net.TCPAddr).Port
|
|
}
|
|
|
|
for i := 0; i < n; i = i + 3 {
|
|
out = append(out, Ports{
|
|
LsnC: lsn[i],
|
|
PortC: ports[i],
|
|
LsnP: lsn[i+1],
|
|
PortP: ports[i+1],
|
|
Grpc: ports[i+2],
|
|
LsnG: lsn[i+2],
|
|
})
|
|
}
|
|
|
|
return out
|
|
}
|