1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package clientv3
16
17 import (
18 "context"
19
20 pb "go.etcd.io/etcd/api/v3/etcdserverpb"
21 "go.etcd.io/etcd/client/pkg/v3/types"
22
23 "google.golang.org/grpc"
24 )
25
26 type (
27 Member pb.Member
28 MemberListResponse pb.MemberListResponse
29 MemberAddResponse pb.MemberAddResponse
30 MemberRemoveResponse pb.MemberRemoveResponse
31 MemberUpdateResponse pb.MemberUpdateResponse
32 MemberPromoteResponse pb.MemberPromoteResponse
33 )
34
35 type Cluster interface {
36
37 MemberList(ctx context.Context) (*MemberListResponse, error)
38
39
40 MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error)
41
42
43 MemberAddAsLearner(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error)
44
45
46 MemberRemove(ctx context.Context, id uint64) (*MemberRemoveResponse, error)
47
48
49 MemberUpdate(ctx context.Context, id uint64, peerAddrs []string) (*MemberUpdateResponse, error)
50
51
52 MemberPromote(ctx context.Context, id uint64) (*MemberPromoteResponse, error)
53 }
54
55 type cluster struct {
56 remote pb.ClusterClient
57 callOpts []grpc.CallOption
58 }
59
60 func NewCluster(c *Client) Cluster {
61 api := &cluster{remote: RetryClusterClient(c)}
62 if c != nil {
63 api.callOpts = c.callOpts
64 }
65 return api
66 }
67
68 func NewClusterFromClusterClient(remote pb.ClusterClient, c *Client) Cluster {
69 api := &cluster{remote: remote}
70 if c != nil {
71 api.callOpts = c.callOpts
72 }
73 return api
74 }
75
76 func (c *cluster) MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) {
77 return c.memberAdd(ctx, peerAddrs, false)
78 }
79
80 func (c *cluster) MemberAddAsLearner(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) {
81 return c.memberAdd(ctx, peerAddrs, true)
82 }
83
84 func (c *cluster) memberAdd(ctx context.Context, peerAddrs []string, isLearner bool) (*MemberAddResponse, error) {
85
86 if _, err := types.NewURLs(peerAddrs); err != nil {
87 return nil, err
88 }
89
90 r := &pb.MemberAddRequest{
91 PeerURLs: peerAddrs,
92 IsLearner: isLearner,
93 }
94 resp, err := c.remote.MemberAdd(ctx, r, c.callOpts...)
95 if err != nil {
96 return nil, toErr(ctx, err)
97 }
98 return (*MemberAddResponse)(resp), nil
99 }
100
101 func (c *cluster) MemberRemove(ctx context.Context, id uint64) (*MemberRemoveResponse, error) {
102 r := &pb.MemberRemoveRequest{ID: id}
103 resp, err := c.remote.MemberRemove(ctx, r, c.callOpts...)
104 if err != nil {
105 return nil, toErr(ctx, err)
106 }
107 return (*MemberRemoveResponse)(resp), nil
108 }
109
110 func (c *cluster) MemberUpdate(ctx context.Context, id uint64, peerAddrs []string) (*MemberUpdateResponse, error) {
111
112 if _, err := types.NewURLs(peerAddrs); err != nil {
113 return nil, err
114 }
115
116
117 r := &pb.MemberUpdateRequest{ID: id, PeerURLs: peerAddrs}
118 resp, err := c.remote.MemberUpdate(ctx, r, c.callOpts...)
119 if err == nil {
120 return (*MemberUpdateResponse)(resp), nil
121 }
122 return nil, toErr(ctx, err)
123 }
124
125 func (c *cluster) MemberList(ctx context.Context) (*MemberListResponse, error) {
126
127 resp, err := c.remote.MemberList(ctx, &pb.MemberListRequest{Linearizable: true}, c.callOpts...)
128 if err == nil {
129 return (*MemberListResponse)(resp), nil
130 }
131 return nil, toErr(ctx, err)
132 }
133
134 func (c *cluster) MemberPromote(ctx context.Context, id uint64) (*MemberPromoteResponse, error) {
135 r := &pb.MemberPromoteRequest{ID: id}
136 resp, err := c.remote.MemberPromote(ctx, r, c.callOpts...)
137 if err != nil {
138 return nil, toErr(ctx, err)
139 }
140 return (*MemberPromoteResponse)(resp), nil
141 }
142
View as plain text