From 7d62b4d64a219e3aad7c39d7d3461e7d0e18e51e Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Thu, 16 Mar 2023 17:24:15 +0100 Subject: [PATCH] tests: Add v2 API to connection multiplexing test Signed-off-by: Marek Siarkowicz --- tests/e2e/cmux_test.go | 21 ++++++++-- tests/e2e/etcd_spawn_nocov.go | 14 +++++-- tests/e2e/etcdctl.go | 77 ++++++++++++++++++++++++++--------- tests/e2e/utils.go | 18 ++++++++ 4 files changed, 103 insertions(+), 27 deletions(-) diff --git a/tests/e2e/cmux_test.go b/tests/e2e/cmux_test.go index c05ccc329..471c36d06 100644 --- a/tests/e2e/cmux_test.go +++ b/tests/e2e/cmux_test.go @@ -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) { diff --git a/tests/e2e/etcd_spawn_nocov.go b/tests/e2e/etcd_spawn_nocov.go index 3f19ff0ea..a5760078a 100644 --- a/tests/e2e/etcd_spawn_nocov.go +++ b/tests/e2e/etcd_spawn_nocov.go @@ -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) } diff --git a/tests/e2e/etcdctl.go b/tests/e2e/etcdctl.go index 390ce50fc..f5330fa3f 100644 --- a/tests/e2e/etcdctl.go +++ b/tests/e2e/etcdctl.go @@ -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, ",") diff --git a/tests/e2e/utils.go b/tests/e2e/utils.go index aca2a779a..543ed8bba 100644 --- a/tests/e2e/utils.go +++ b/tests/e2e/utils.go @@ -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: