tests: Add v2 API to connection multiplexing test

Signed-off-by: Marek Siarkowicz <siarkowicz@google.com>
This commit is contained in:
Marek Siarkowicz 2023-03-16 17:24:15 +01:00
parent 7bb5f1f58c
commit 7d62b4d64a
4 changed files with 103 additions and 27 deletions

View File

@ -26,6 +26,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
clientv2 "go.etcd.io/etcd/client"
pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
"go.etcd.io/etcd/pkg/testutil"
)
@ -51,7 +52,7 @@ func TestConnectionMultiplexing(t *testing.T) {
} {
t.Run(tc.name, func(t *testing.T) {
ctx := context.Background()
cfg := etcdProcessClusterConfig{clusterSize: 1, clientTLS: tc.serverTLS}
cfg := etcdProcessClusterConfig{clusterSize: 1, clientTLS: tc.serverTLS, enableV2: true}
clus, err := newEtcdProcessCluster(&cfg)
require.NoError(t, err)
defer clus.Close()
@ -89,8 +90,22 @@ func testConnectionMultiplexing(ctx context.Context, t *testing.T, endpoint stri
panic(fmt.Sprintf("Unsupported conn type %v", connType))
}
t.Run("etcdctl", func(t *testing.T) {
etcdctl := NewEtcdctl([]string{endpoint}, connType, false)
_, err := etcdctl.Get("a")
t.Run("v2", func(t *testing.T) {
etcdctl := NewEtcdctl([]string{endpoint}, connType, false, true)
err := etcdctl.Set("a", "1")
assert.NoError(t, err)
})
t.Run("v3", func(t *testing.T) {
etcdctl := NewEtcdctl([]string{endpoint}, connType, false, false)
err := etcdctl.Put("a", "1")
assert.NoError(t, err)
})
})
t.Run("clientv2", func(t *testing.T) {
c, err := newClientV2(t, []string{endpoint}, connType, false)
require.NoError(t, err)
kv := clientv2.NewKeysAPI(c)
_, err = kv.Set(ctx, "a", "1", nil)
assert.NoError(t, err)
})
t.Run("clientv3", func(t *testing.T) {

View File

@ -19,6 +19,7 @@ package e2e
import (
"os"
"strings"
"go.etcd.io/etcd/pkg/expect"
)
@ -26,9 +27,14 @@ import (
const noOutputLineCount = 0 // regular binaries emit no extra lines
func spawnCmd(args []string) (*expect.ExpectProcess, error) {
if args[0] == ctlBinPath+"3" {
env := append(os.Environ(), "ETCDCTL_API=3")
return expect.NewExpectWithEnv(ctlBinPath, args[1:], env)
env := os.Environ()
switch {
case strings.HasSuffix(args[0], ctlBinPath+"2"):
env = append(env, "ETCDCTL_API=2")
args[0] = ctlBinPath
case strings.HasSuffix(args[0], ctlBinPath+"3"):
env = append(env, "ETCDCTL_API=3")
args[0] = ctlBinPath
}
return expect.NewExpect(args[0], args[1:]...)
return expect.NewExpectWithEnv(args[0], args[1:], env)
}

View File

@ -22,50 +22,73 @@ import (
"go.etcd.io/etcd/clientv3"
)
type EtcdctlV3 struct {
type Etcdctl struct {
connType clientConnType
isAutoTLS bool
endpoints []string
v2 bool
}
func NewEtcdctl(endpoints []string, connType clientConnType, isAutoTLS bool) *EtcdctlV3 {
return &EtcdctlV3{
func NewEtcdctl(endpoints []string, connType clientConnType, isAutoTLS bool, v2 bool) *Etcdctl {
return &Etcdctl{
endpoints: endpoints,
connType: connType,
isAutoTLS: isAutoTLS,
v2: v2,
}
}
func (ctl *EtcdctlV3) Get(key string) (*clientv3.GetResponse, error) {
func (ctl *Etcdctl) Get(key string) (*clientv3.GetResponse, error) {
var resp clientv3.GetResponse
err := ctl.spawnJsonCmd(&resp, "get", key)
return &resp, err
}
func (ctl *EtcdctlV3) Put(key, value string) error {
func (ctl *Etcdctl) Put(key, value string) error {
if ctl.v2 {
panic("Unsupported method for v2")
}
args := ctl.cmdArgs()
args = append(args, "put", key, value)
return spawnWithExpect(args, "OK")
}
func (ctl *EtcdctlV3) AlarmList() (*clientv3.AlarmResponse, error) {
func (ctl *Etcdctl) Set(key, value string) error {
if !ctl.v2 {
panic("Unsupported method for v3")
}
args := ctl.cmdArgs()
args = append(args, "set", key, value)
return spawnWithExpect(args, value)
}
func (ctl *Etcdctl) AlarmList() (*clientv3.AlarmResponse, error) {
if ctl.v2 {
panic("Unsupported method for v2")
}
var resp clientv3.AlarmResponse
err := ctl.spawnJsonCmd(&resp, "alarm", "list")
return &resp, err
}
func (ctl *EtcdctlV3) MemberList() (*clientv3.MemberListResponse, error) {
func (ctl *Etcdctl) MemberList() (*clientv3.MemberListResponse, error) {
if ctl.v2 {
panic("Unsupported method for v2")
}
var resp clientv3.MemberListResponse
err := ctl.spawnJsonCmd(&resp, "member", "list")
return &resp, err
}
func (ctl *EtcdctlV3) Compact(rev int64) (*clientv3.CompactResponse, error) {
func (ctl *Etcdctl) Compact(rev int64) (*clientv3.CompactResponse, error) {
if ctl.v2 {
panic("Unsupported method for v2")
}
args := ctl.cmdArgs("compact", fmt.Sprint(rev))
return nil, spawnWithExpect(args, fmt.Sprintf("compacted revision %v", rev))
}
func (ctl *EtcdctlV3) spawnJsonCmd(output interface{}, args ...string) error {
func (ctl *Etcdctl) spawnJsonCmd(output interface{}, args ...string) error {
args = append(args, "-w", "json")
cmd, err := spawnCmd(append(ctl.cmdArgs(), args...))
if err != nil {
@ -78,24 +101,38 @@ func (ctl *EtcdctlV3) spawnJsonCmd(output interface{}, args ...string) error {
return json.Unmarshal([]byte(line), output)
}
func (ctl *EtcdctlV3) cmdArgs(args ...string) []string {
cmdArgs := []string{ctlBinPath + "3"}
func (ctl *Etcdctl) cmdArgs(args ...string) []string {
var cmdArgs []string
binPath := ctlBinPath
if ctl.v2 {
cmdArgs = []string{binPath + "2"}
} else {
cmdArgs = []string{binPath + "3"}
}
for k, v := range ctl.flags() {
cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%s", k, v))
}
return append(cmdArgs, args...)
}
func (ctl *EtcdctlV3) flags() map[string]string {
func (ctl *Etcdctl) flags() map[string]string {
fmap := make(map[string]string)
if ctl.connType == clientTLS {
if ctl.isAutoTLS {
fmap["insecure-transport"] = "false"
fmap["insecure-skip-tls-verify"] = "true"
} else {
fmap["cacert"] = testTLSInfo.TrustedCAFile
fmap["cert"] = testTLSInfo.CertFile
fmap["key"] = testTLSInfo.KeyFile
if ctl.v2 {
if ctl.connType == clientTLS {
fmap["ca-file"] = testTLSInfo.TrustedCAFile
fmap["cert-file"] = testTLSInfo.CertFile
fmap["key-file"] = testTLSInfo.KeyFile
}
} else {
if ctl.connType == clientTLS {
if ctl.isAutoTLS {
fmap["insecure-transport"] = "false"
fmap["insecure-skip-tls-verify"] = "true"
} else {
fmap["cacert"] = testTLSInfo.TrustedCAFile
fmap["cert"] = testTLSInfo.CertFile
fmap["key"] = testTLSInfo.KeyFile
}
}
}
fmap["endpoints"] = strings.Join(ctl.endpoints, ",")

View File

@ -24,6 +24,7 @@ import (
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"
clientv2 "go.etcd.io/etcd/client"
"go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/pkg/stringutil"
"go.etcd.io/etcd/pkg/transport"
@ -73,6 +74,23 @@ func newClient(t *testing.T, entpoints []string, connType clientConnType, isAuto
return c
}
func newClientV2(t *testing.T, endpoints []string, connType clientConnType, isAutoTLS bool) (clientv2.Client, error) {
tls, err := tlsInfo(t, connType, isAutoTLS)
if err != nil {
t.Fatal(err)
}
cfg := clientv2.Config{
Endpoints: endpoints,
}
if tls != nil {
cfg.Transport, err = transport.NewTransport(*tls, 5*time.Second)
if err != nil {
t.Fatal(err)
}
}
return clientv2.New(cfg)
}
func tlsInfo(t testing.TB, connType clientConnType, isAutoTLS bool) (*transport.TLSInfo, error) {
switch connType {
case clientNonTLS, clientTLSAndNonTLS: