mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
clientv3, etcdctl: MemberPromote for learner
This commit is contained in:
parent
bd7f42855b
commit
a039f2efb8
@ -202,6 +202,27 @@ func TestMemberAddForLearner(t *testing.T) {
|
||||
if !resp.Member.IsLearner {
|
||||
t.Errorf("Added a member as learner, got resp.Member.IsLearner = %v", resp.Member.IsLearner)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMemberPromoteForLearner(t *testing.T) {
|
||||
// TODO test not ready learner promotion.
|
||||
defer testutil.AfterTest(t)
|
||||
|
||||
clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3})
|
||||
defer clus.Terminate(t)
|
||||
// TODO change the random client to client that talk to leader directly.
|
||||
capi := clus.RandClient()
|
||||
|
||||
urls := []string{"http://127.0.0.1:1234"}
|
||||
isLearner := true
|
||||
resp, err := capi.MemberAddAsLearner(context.Background(), urls)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to add member %v", err)
|
||||
}
|
||||
|
||||
if !resp.Member.IsLearner {
|
||||
t.Errorf("Added a member as learner, got resp.Member.IsLearner = %v", resp.Member.IsLearner)
|
||||
}
|
||||
|
||||
learners, err := clus.GetLearnerMembers()
|
||||
if err != nil {
|
||||
@ -210,4 +231,18 @@ func TestMemberAddForLearner(t *testing.T) {
|
||||
if len(learners) != 1 {
|
||||
t.Errorf("Added 1 learner node to cluster, got %d", len(learners))
|
||||
}
|
||||
_, err = capi.MemberPromote(context.Background(), resp.Member.ID)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("failed to promote member error: %v", err)
|
||||
}
|
||||
|
||||
learners, err = clus.GetLearnerMembers()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get the number of learners in cluster: %v", err)
|
||||
}
|
||||
if len(learners) != 0 {
|
||||
t.Errorf("learner promoted, expect 0 learner, got %d", len(learners))
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ func NewMemberCommand() *cobra.Command {
|
||||
mc.AddCommand(NewMemberRemoveCommand())
|
||||
mc.AddCommand(NewMemberUpdateCommand())
|
||||
mc.AddCommand(NewMemberListCommand())
|
||||
mc.AddCommand(NewMemberPromoteCommand())
|
||||
|
||||
return mc
|
||||
}
|
||||
@ -100,6 +101,20 @@ The items in the lists are ID, Status, Name, Peer Addrs, Client Addrs, Is Learne
|
||||
return cc
|
||||
}
|
||||
|
||||
// NewMemberPromoteCommand returns the cobra command for "member promote".
|
||||
func NewMemberPromoteCommand() *cobra.Command {
|
||||
cc := &cobra.Command{
|
||||
Use: "promote <memberID>",
|
||||
Short: "Promotes a non-voting member in the cluster",
|
||||
Long: `Promotes a non-voting learner member to a voting one in the cluster.
|
||||
`,
|
||||
|
||||
Run: memberPromoteCommandFunc,
|
||||
}
|
||||
|
||||
return cc
|
||||
}
|
||||
|
||||
// memberAddCommandFunc executes the "member add" command.
|
||||
func memberAddCommandFunc(cmd *cobra.Command, args []string) {
|
||||
if len(args) < 1 {
|
||||
@ -238,3 +253,23 @@ func memberListCommandFunc(cmd *cobra.Command, args []string) {
|
||||
|
||||
display.MemberList(*resp)
|
||||
}
|
||||
|
||||
// memberPromoteCommandFunc executes the "member promote" command.
|
||||
func memberPromoteCommandFunc(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 1 {
|
||||
ExitWithError(ExitBadArgs, fmt.Errorf("member ID is not provided"))
|
||||
}
|
||||
|
||||
id, err := strconv.ParseUint(args[0], 16, 64)
|
||||
if err != nil {
|
||||
ExitWithError(ExitBadArgs, fmt.Errorf("bad member ID arg (%v), expecting ID in Hex", err))
|
||||
}
|
||||
|
||||
ctx, cancel := commandCtx(cmd)
|
||||
resp, err := mustClientFromCmd(cmd).MemberPromote(ctx, id)
|
||||
cancel()
|
||||
if err != nil {
|
||||
ExitWithError(ExitError, err)
|
||||
}
|
||||
display.MemberPromote(id, *resp)
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ type printer interface {
|
||||
MemberAdd(v3.MemberAddResponse)
|
||||
MemberRemove(id uint64, r v3.MemberRemoveResponse)
|
||||
MemberUpdate(id uint64, r v3.MemberUpdateResponse)
|
||||
MemberPromote(id uint64, r v3.MemberPromoteResponse)
|
||||
MemberList(v3.MemberListResponse)
|
||||
|
||||
EndpointHealth([]epHealth)
|
||||
|
@ -136,6 +136,10 @@ func (s *simplePrinter) MemberUpdate(id uint64, r v3.MemberUpdateResponse) {
|
||||
fmt.Printf("Member %16x updated in cluster %16x\n", id, r.Header.ClusterId)
|
||||
}
|
||||
|
||||
func (s *simplePrinter) MemberPromote(id uint64, r v3.MemberPromoteResponse) {
|
||||
fmt.Printf("Member %16x promoted in cluster %16x\n", id, r.Header.ClusterId)
|
||||
}
|
||||
|
||||
func (s *simplePrinter) MemberList(resp v3.MemberListResponse) {
|
||||
_, rows := makeMemberListTable(resp)
|
||||
for _, row := range rows {
|
||||
|
@ -40,8 +40,8 @@ var (
|
||||
ErrGRPCMemberNotEnoughStarted = status.New(codes.FailedPrecondition, "etcdserver: re-configuration failed due to not enough started members").Err()
|
||||
ErrGRPCMemberBadURLs = status.New(codes.InvalidArgument, "etcdserver: given member URLs are invalid").Err()
|
||||
ErrGRPCMemberNotFound = status.New(codes.NotFound, "etcdserver: member not found").Err()
|
||||
ErrGRPCMemberNotLearner = status.New(codes.FailedPrecondition, "etcdserver: can only promote a learner member which catches up with peers").Err()
|
||||
ErrGRPCLearnerNotReady = status.New(codes.FailedPrecondition, "etcdserver: can only promote a learner member").Err()
|
||||
ErrGRPCMemberNotLearner = status.New(codes.FailedPrecondition, "etcdserver: can only promote a learner member").Err()
|
||||
ErrGRPCLearnerNotReady = status.New(codes.FailedPrecondition, "etcdserver: can only promote a learner member which catches up with leader").Err()
|
||||
|
||||
ErrGRPCRequestTooLarge = status.New(codes.InvalidArgument, "etcdserver: request is too large").Err()
|
||||
ErrGRPCRequestTooManyRequests = status.New(codes.ResourceExhausted, "etcdserver: too many requests").Err()
|
||||
@ -95,6 +95,8 @@ var (
|
||||
ErrorDesc(ErrGRPCMemberNotEnoughStarted): ErrGRPCMemberNotEnoughStarted,
|
||||
ErrorDesc(ErrGRPCMemberBadURLs): ErrGRPCMemberBadURLs,
|
||||
ErrorDesc(ErrGRPCMemberNotFound): ErrGRPCMemberNotFound,
|
||||
ErrorDesc(ErrGRPCMemberNotLearner): ErrGRPCMemberNotLearner,
|
||||
ErrorDesc(ErrGRPCLearnerNotReady): ErrGRPCLearnerNotReady,
|
||||
|
||||
ErrorDesc(ErrGRPCRequestTooLarge): ErrGRPCRequestTooLarge,
|
||||
ErrorDesc(ErrGRPCRequestTooManyRequests): ErrGRPCRequestTooManyRequests,
|
||||
@ -149,6 +151,8 @@ var (
|
||||
ErrMemberNotEnoughStarted = Error(ErrGRPCMemberNotEnoughStarted)
|
||||
ErrMemberBadURLs = Error(ErrGRPCMemberBadURLs)
|
||||
ErrMemberNotFound = Error(ErrGRPCMemberNotFound)
|
||||
ErrMemberNotLearner = Error(ErrGRPCMemberNotLearner)
|
||||
ErrMemberLearnerNotReady = Error(ErrGRPCLearnerNotReady)
|
||||
|
||||
ErrRequestTooLarge = Error(ErrGRPCRequestTooLarge)
|
||||
ErrTooManyRequests = Error(ErrGRPCRequestTooManyRequests)
|
||||
|
Loading…
x
Reference in New Issue
Block a user