From c66176b5387472cc420839677156ba64c010abdc Mon Sep 17 00:00:00 2001 From: Barak Michener Date: Fri, 30 Jan 2015 19:23:19 -0500 Subject: [PATCH 1/2] etcdctl: give more helpful suggestions on removal --- etcdctl/command/member_commands.go | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/etcdctl/command/member_commands.go b/etcdctl/command/member_commands.go index 9bf55b1da..508e3277b 100644 --- a/etcdctl/command/member_commands.go +++ b/etcdctl/command/member_commands.go @@ -156,16 +156,40 @@ func actionMemberRemove(c *cli.Context) { fmt.Fprintln(os.Stderr, "Provide a single member ID") os.Exit(1) } + removalID := args[0] mAPI := mustNewMembersAPI(c) - mID := args[0] + // Get the list of members. + listctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout) + members, err := mAPI.List(listctx) + if err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) + } + // Sanity check the input. + foundID := false + for _, m := range members { + if m.ID == removalID { + foundID = true + } + if m.Name == removalID { + // Note that, so long as it's not ambiguous, we *could* do the right thing by name here. + fmt.Fprintf(os.Stderr, "Found a member named %s; if this is correct, please use its ID, eg:\n\tetcdctl member remove %s\n\n", m.Name, m.ID) + } + } + if !foundID { + fmt.Fprintf(os.Stderr, "Couldn't find a member in the cluster with an ID of %s.\n", removalID) + os.Exit(1) + } + + // Actually attempt to remove the member. ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout) - err := mAPI.Remove(ctx, mID) + err = mAPI.Remove(ctx, removalID) cancel() if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } - fmt.Printf("Removed member %s from cluster\n", mID) + fmt.Printf("Removed member %s from cluster\n", removalID) } From 37e8d608b37b0c4551cd5a1fc8d78ad73e2ee803 Mon Sep 17 00:00:00 2001 From: Barak Michener Date: Fri, 30 Jan 2015 19:41:44 -0500 Subject: [PATCH 2/2] add documentation link and describe the 404/500 errors better --- etcdctl/command/member_commands.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/etcdctl/command/member_commands.go b/etcdctl/command/member_commands.go index 508e3277b..4172c1b25 100644 --- a/etcdctl/command/member_commands.go +++ b/etcdctl/command/member_commands.go @@ -163,7 +163,7 @@ func actionMemberRemove(c *cli.Context) { listctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout) members, err := mAPI.List(listctx) if err != nil { - fmt.Fprintln(os.Stderr, err.Error()) + fmt.Fprintln(os.Stderr, "Error while verifying ID against known members:", err.Error()) os.Exit(1) } // Sanity check the input. @@ -174,7 +174,8 @@ func actionMemberRemove(c *cli.Context) { } if m.Name == removalID { // Note that, so long as it's not ambiguous, we *could* do the right thing by name here. - fmt.Fprintf(os.Stderr, "Found a member named %s; if this is correct, please use its ID, eg:\n\tetcdctl member remove %s\n\n", m.Name, m.ID) + fmt.Fprintf(os.Stderr, "Found a member named %s; if this is correct, please use its ID, eg:\n\tetcdctl member remove %s\n", m.Name, m.ID) + fmt.Fprintf(os.Stderr, "For more details, read the documentation at https://github.com/coreos/etcd/blob/master/Documentation/runtime-configuration.md#remove-a-member\n\n") } } if !foundID { @@ -187,7 +188,7 @@ func actionMemberRemove(c *cli.Context) { err = mAPI.Remove(ctx, removalID) cancel() if err != nil { - fmt.Fprintln(os.Stderr, err.Error()) + fmt.Fprintf(os.Stderr, "Recieved an error trying to remove member %s: %s", removalID, err.Error()) os.Exit(1) }