go.etcd.io/etcd@v3.3.27+incompatible/clientv3/cluster.go (about) 1 // Copyright 2016 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package clientv3 16 17 import ( 18 "context" 19 20 pb "github.com/coreos/etcd/etcdserver/etcdserverpb" 21 "github.com/coreos/etcd/pkg/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 ) 33 34 type Cluster interface { 35 // MemberList lists the current cluster membership. 36 MemberList(ctx context.Context) (*MemberListResponse, error) 37 38 // MemberAdd adds a new member into the cluster. 39 MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) 40 41 // MemberRemove removes an existing member from the cluster. 42 MemberRemove(ctx context.Context, id uint64) (*MemberRemoveResponse, error) 43 44 // MemberUpdate updates the peer addresses of the member. 45 MemberUpdate(ctx context.Context, id uint64, peerAddrs []string) (*MemberUpdateResponse, error) 46 } 47 48 type cluster struct { 49 remote pb.ClusterClient 50 callOpts []grpc.CallOption 51 } 52 53 func NewCluster(c *Client) Cluster { 54 api := &cluster{remote: RetryClusterClient(c)} 55 if c != nil { 56 api.callOpts = c.callOpts 57 } 58 return api 59 } 60 61 func NewClusterFromClusterClient(remote pb.ClusterClient, c *Client) Cluster { 62 api := &cluster{remote: remote} 63 if c != nil { 64 api.callOpts = c.callOpts 65 } 66 return api 67 } 68 69 func (c *cluster) MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) { 70 // fail-fast before panic in rafthttp 71 if _, err := types.NewURLs(peerAddrs); err != nil { 72 return nil, err 73 } 74 75 r := &pb.MemberAddRequest{PeerURLs: peerAddrs} 76 resp, err := c.remote.MemberAdd(ctx, r, c.callOpts...) 77 if err != nil { 78 return nil, toErr(ctx, err) 79 } 80 return (*MemberAddResponse)(resp), nil 81 } 82 83 func (c *cluster) MemberRemove(ctx context.Context, id uint64) (*MemberRemoveResponse, error) { 84 r := &pb.MemberRemoveRequest{ID: id} 85 resp, err := c.remote.MemberRemove(ctx, r, c.callOpts...) 86 if err != nil { 87 return nil, toErr(ctx, err) 88 } 89 return (*MemberRemoveResponse)(resp), nil 90 } 91 92 func (c *cluster) MemberUpdate(ctx context.Context, id uint64, peerAddrs []string) (*MemberUpdateResponse, error) { 93 // fail-fast before panic in rafthttp 94 if _, err := types.NewURLs(peerAddrs); err != nil { 95 return nil, err 96 } 97 98 // it is safe to retry on update. 99 r := &pb.MemberUpdateRequest{ID: id, PeerURLs: peerAddrs} 100 resp, err := c.remote.MemberUpdate(ctx, r, c.callOpts...) 101 if err == nil { 102 return (*MemberUpdateResponse)(resp), nil 103 } 104 return nil, toErr(ctx, err) 105 } 106 107 func (c *cluster) MemberList(ctx context.Context) (*MemberListResponse, error) { 108 // it is safe to retry on list. 109 resp, err := c.remote.MemberList(ctx, &pb.MemberListRequest{}, c.callOpts...) 110 if err == nil { 111 return (*MemberListResponse)(resp), nil 112 } 113 return nil, toErr(ctx, err) 114 }