Skip to content

Commit 5d1307f

Browse files
author
maksim.konovalov
committed
Add tests for etcd v2 provider
1 parent d936797 commit 5d1307f

File tree

3 files changed

+137
-3
lines changed

3 files changed

+137
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
BUG FIXES:
44
- Fixed go.mod and go.sum files with go mod tidy.
55

6+
TESTS:
7+
8+
- Added etcd v2 provider tests.
9+
610
## v2.0.1
711

812
in the v2.0.0 release there was a bug that did not allow go-get. Updating to v2 requires changing the module name

providers/etcd/provider.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ import (
1010
"go.etcd.io/etcd/client/v2"
1111
)
1212

13+
var (
14+
ErrNodesError = fmt.Errorf("etcd nodes err")
15+
ErrClusterError = fmt.Errorf("etcd cluster err")
16+
ErrInstancesError = fmt.Errorf("etcd instances err")
17+
)
18+
1319
// Check that provider implements TopologyProvider interface
1420
var _ vshardrouter.TopologyProvider = (*Provider)(nil)
1521

@@ -63,6 +69,7 @@ func mapCluster2Instances(replicasets []vshardrouter.ReplicasetInfo,
6369
return currentTopology
6470
}
6571

72+
// nolint:contextcheck
6673
func (p *Provider) GetTopology() (map[vshardrouter.ReplicasetInfo][]vshardrouter.InstanceInfo, error) {
6774
resp, err := p.kapi.Get(context.TODO(), p.path, &client.GetOptions{Recursive: true})
6875
if err != nil {
@@ -71,7 +78,7 @@ func (p *Provider) GetTopology() (map[vshardrouter.ReplicasetInfo][]vshardrouter
7178
nodes := resp.Node.Nodes
7279

7380
if nodes.Len() < 2 {
74-
return nil, fmt.Errorf("etcd path %s subnodes <2; minimum 2 (/clusters & /instances)", p.path)
81+
return nil, fmt.Errorf("%w: etcd path %s subnodes <2; minimum 2 (/clusters & /instances)", ErrNodesError, p.path)
7582
}
7683

7784
var replicasets []vshardrouter.ReplicasetInfo
@@ -83,7 +90,7 @@ func (p *Provider) GetTopology() (map[vshardrouter.ReplicasetInfo][]vshardrouter
8390
switch filepath.Base(node.Key) {
8491
case "clusters":
8592
if len(node.Nodes) < 1 {
86-
return nil, fmt.Errorf("etcd path %s has no clusters", node.Key)
93+
return nil, fmt.Errorf("%w: etcd path %s has no clusters", ErrClusterError, node.Key)
8794
}
8895

8996
for _, rsNode := range node.Nodes {
@@ -109,7 +116,7 @@ func (p *Provider) GetTopology() (map[vshardrouter.ReplicasetInfo][]vshardrouter
109116
}
110117
case "instances":
111118
if len(node.Nodes) < 1 {
112-
return nil, fmt.Errorf("etcd path %s has no instances", node.Key)
119+
return nil, fmt.Errorf("%w: etcd path %s has no instances", ErrInstancesError, node.Key)
113120
}
114121

115122
for _, instanceNode := range node.Nodes {

providers/etcd/provider_test.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package etcd
2+
3+
import (
4+
"context"
5+
"errors"
6+
"log"
7+
"net/url"
8+
"testing"
9+
"time"
10+
11+
"github.com/stretchr/testify/require"
12+
"go.etcd.io/etcd/client/v2"
13+
"go.etcd.io/etcd/server/v3/embed"
14+
)
15+
16+
func parseEtcdUrls(strs []string) []url.URL {
17+
urls := make([]url.URL, 0, len(strs))
18+
19+
for _, str := range strs {
20+
u, err := url.Parse(str)
21+
if err != nil {
22+
log.Printf("Invalid url %s, error: %s", str, err.Error())
23+
continue
24+
25+
}
26+
urls = append(urls, *u)
27+
}
28+
29+
return urls
30+
31+
}
32+
33+
func TestProvider_Init(t *testing.T) {
34+
ctx := context.Background()
35+
config := embed.NewConfig()
36+
37+
config.Name = "localhost"
38+
config.Dir = "/tmp/my-embedded-ectd-cluster"
39+
40+
config.ListenPeerUrls = parseEtcdUrls([]string{"http://0.0.0.0:2380"})
41+
config.ListenClientUrls = parseEtcdUrls([]string{"http://0.0.0.0:2379"})
42+
config.AdvertisePeerUrls = parseEtcdUrls([]string{"http://localhost:2380"})
43+
config.AdvertiseClientUrls = parseEtcdUrls([]string{"http://localhost:2379"})
44+
config.InitialCluster = "localhost=http://localhost:2380"
45+
config.LogLevel = "panic"
46+
47+
// enable v2
48+
config.EnableV2 = true
49+
50+
etcd, err := embed.StartEtcd(config)
51+
require.NoError(t, err)
52+
53+
defer etcd.Close()
54+
55+
clientConfig := client.Config{Endpoints: []string{"http://127.0.0.1:2379"}}
56+
57+
c, err := client.New(clientConfig)
58+
require.NoError(t, err)
59+
60+
kapi := client.NewKeysAPI(c)
61+
require.NotNil(t, kapi)
62+
63+
time.Sleep(1 * time.Second)
64+
65+
t.Run("provider creates ok", func(t *testing.T) {
66+
t.Parallel()
67+
68+
p, err := NewProvider(ctx, Config{EtcdConfig: clientConfig})
69+
require.NoError(t, err)
70+
require.NotNil(t, p)
71+
})
72+
73+
t.Run("provider invalid config error", func(t *testing.T) {
74+
t.Parallel()
75+
76+
invalidClientConfig := client.Config{Endpoints: []string{"http://0.0.0.0:23803"}}
77+
78+
p, err := NewProvider(ctx, Config{EtcdConfig: invalidClientConfig})
79+
require.NoError(t, err)
80+
require.NotNil(t, p)
81+
82+
_, err = p.GetTopology()
83+
require.Error(t, err)
84+
})
85+
86+
t.Run("nodes error", func(t *testing.T) {
87+
88+
nodesErrorPath := "/no-nodes"
89+
90+
p, err := NewProvider(ctx, Config{EtcdConfig: clientConfig, Path: nodesErrorPath})
91+
require.NoError(t, err)
92+
require.NotNil(t, p)
93+
94+
_, err = kapi.Set(ctx, nodesErrorPath, "test", &client.SetOptions{})
95+
require.NoError(t, err)
96+
97+
_, err = p.GetTopology()
98+
require.ErrorIs(t, err, ErrNodesError)
99+
})
100+
101+
t.Run("no clusters or instances nodes error", func(t *testing.T) {
102+
nodesClusterErrPath := "/test-nodes-cluster-instances-error"
103+
104+
p, err := NewProvider(ctx, Config{EtcdConfig: clientConfig, Path: nodesClusterErrPath})
105+
require.NoError(t, err)
106+
require.NotNil(t, p)
107+
108+
_, err = kapi.Set(ctx, nodesClusterErrPath, "", &client.SetOptions{Dir: true})
109+
require.NoError(t, err)
110+
111+
_, err = kapi.Set(ctx, nodesClusterErrPath+"/clusters", "test", &client.SetOptions{})
112+
113+
require.NoError(t, err)
114+
115+
_, err = kapi.Set(ctx, nodesClusterErrPath+"/instances", "test", &client.SetOptions{})
116+
117+
require.NoError(t, err)
118+
119+
_, err = p.GetTopology()
120+
require.NotErrorIs(t, err, ErrNodesError)
121+
require.True(t, errors.Is(err, ErrClusterError) || errors.Is(err, ErrInstancesError))
122+
})
123+
}

0 commit comments

Comments
 (0)