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/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
clientv2 "go.etcd.io/etcd/client"
pb "go.etcd.io/etcd/etcdserver/etcdserverpb" pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
"go.etcd.io/etcd/pkg/testutil" "go.etcd.io/etcd/pkg/testutil"
) )
@ -51,7 +52,7 @@ func TestConnectionMultiplexing(t *testing.T) {
} { } {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
ctx := context.Background() ctx := context.Background()
cfg := etcdProcessClusterConfig{clusterSize: 1, clientTLS: tc.serverTLS} cfg := etcdProcessClusterConfig{clusterSize: 1, clientTLS: tc.serverTLS, enableV2: true}
clus, err := newEtcdProcessCluster(&cfg) clus, err := newEtcdProcessCluster(&cfg)
require.NoError(t, err) require.NoError(t, err)
defer clus.Close() 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)) panic(fmt.Sprintf("Unsupported conn type %v", connType))
} }
t.Run("etcdctl", func(t *testing.T) { t.Run("etcdctl", func(t *testing.T) {
etcdctl := NewEtcdctl([]string{endpoint}, connType, false) t.Run("v2", func(t *testing.T) {
_, err := etcdctl.Get("a") 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) assert.NoError(t, err)
}) })
t.Run("clientv3", func(t *testing.T) { t.Run("clientv3", func(t *testing.T) {

View File

@ -19,6 +19,7 @@ package e2e
import ( import (
"os" "os"
"strings"
"go.etcd.io/etcd/pkg/expect" "go.etcd.io/etcd/pkg/expect"
) )
@ -26,9 +27,14 @@ import (
const noOutputLineCount = 0 // regular binaries emit no extra lines const noOutputLineCount = 0 // regular binaries emit no extra lines
func spawnCmd(args []string) (*expect.ExpectProcess, error) { func spawnCmd(args []string) (*expect.ExpectProcess, error) {
if args[0] == ctlBinPath+"3" { env := os.Environ()
env := append(os.Environ(), "ETCDCTL_API=3") switch {
return expect.NewExpectWithEnv(ctlBinPath, args[1:], env) 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" "go.etcd.io/etcd/clientv3"
) )
type EtcdctlV3 struct { type Etcdctl struct {
connType clientConnType connType clientConnType
isAutoTLS bool isAutoTLS bool
endpoints []string endpoints []string
v2 bool
} }
func NewEtcdctl(endpoints []string, connType clientConnType, isAutoTLS bool) *EtcdctlV3 { func NewEtcdctl(endpoints []string, connType clientConnType, isAutoTLS bool, v2 bool) *Etcdctl {
return &EtcdctlV3{ return &Etcdctl{
endpoints: endpoints, endpoints: endpoints,
connType: connType, connType: connType,
isAutoTLS: isAutoTLS, 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 var resp clientv3.GetResponse
err := ctl.spawnJsonCmd(&resp, "get", key) err := ctl.spawnJsonCmd(&resp, "get", key)
return &resp, err 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 := ctl.cmdArgs()
args = append(args, "put", key, value) args = append(args, "put", key, value)
return spawnWithExpect(args, "OK") 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 var resp clientv3.AlarmResponse
err := ctl.spawnJsonCmd(&resp, "alarm", "list") err := ctl.spawnJsonCmd(&resp, "alarm", "list")
return &resp, err 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 var resp clientv3.MemberListResponse
err := ctl.spawnJsonCmd(&resp, "member", "list") err := ctl.spawnJsonCmd(&resp, "member", "list")
return &resp, err 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)) args := ctl.cmdArgs("compact", fmt.Sprint(rev))
return nil, spawnWithExpect(args, fmt.Sprintf("compacted revision %v", 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") args = append(args, "-w", "json")
cmd, err := spawnCmd(append(ctl.cmdArgs(), args...)) cmd, err := spawnCmd(append(ctl.cmdArgs(), args...))
if err != nil { if err != nil {
@ -78,24 +101,38 @@ func (ctl *EtcdctlV3) spawnJsonCmd(output interface{}, args ...string) error {
return json.Unmarshal([]byte(line), output) return json.Unmarshal([]byte(line), output)
} }
func (ctl *EtcdctlV3) cmdArgs(args ...string) []string { func (ctl *Etcdctl) cmdArgs(args ...string) []string {
cmdArgs := []string{ctlBinPath + "3"} var cmdArgs []string
binPath := ctlBinPath
if ctl.v2 {
cmdArgs = []string{binPath + "2"}
} else {
cmdArgs = []string{binPath + "3"}
}
for k, v := range ctl.flags() { for k, v := range ctl.flags() {
cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%s", k, v)) cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%s", k, v))
} }
return append(cmdArgs, args...) return append(cmdArgs, args...)
} }
func (ctl *EtcdctlV3) flags() map[string]string { func (ctl *Etcdctl) flags() map[string]string {
fmap := make(map[string]string) fmap := make(map[string]string)
if ctl.connType == clientTLS { if ctl.v2 {
if ctl.isAutoTLS { if ctl.connType == clientTLS {
fmap["insecure-transport"] = "false" fmap["ca-file"] = testTLSInfo.TrustedCAFile
fmap["insecure-skip-tls-verify"] = "true" fmap["cert-file"] = testTLSInfo.CertFile
} else { fmap["key-file"] = testTLSInfo.KeyFile
fmap["cacert"] = testTLSInfo.TrustedCAFile }
fmap["cert"] = testTLSInfo.CertFile } else {
fmap["key"] = testTLSInfo.KeyFile 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, ",") fmap["endpoints"] = strings.Join(ctl.endpoints, ",")

View File

@ -24,6 +24,7 @@ import (
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"google.golang.org/grpc" "google.golang.org/grpc"
clientv2 "go.etcd.io/etcd/client"
"go.etcd.io/etcd/clientv3" "go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/pkg/stringutil" "go.etcd.io/etcd/pkg/stringutil"
"go.etcd.io/etcd/pkg/transport" "go.etcd.io/etcd/pkg/transport"
@ -73,6 +74,23 @@ func newClient(t *testing.T, entpoints []string, connType clientConnType, isAuto
return c 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) { func tlsInfo(t testing.TB, connType clientConnType, isAutoTLS bool) (*transport.TLSInfo, error) {
switch connType { switch connType {
case clientNonTLS, clientTLSAndNonTLS: case clientNonTLS, clientTLSAndNonTLS: