Skip to content

Commit

Permalink
api: support delete member by id. (#695)
Browse files Browse the repository at this point in the history
  • Loading branch information
disksing authored Aug 4, 2017
1 parent 2710f22 commit 30115ae
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 26 deletions.
2 changes: 1 addition & 1 deletion pdctl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ show the pd members status
"addr": "http://192.168.199.229:2379",
"id": 9724873857558226554
}
>> member delete pd2
>> member delete name pd2
Success!
```

Expand Down
2 changes: 1 addition & 1 deletion pdctl/command/cluster_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func NewClusterCommand() *cobra.Command {
func showClusterCommandFunc(cmd *cobra.Command, args []string) {
r, err := doRequest(cmd, clusterPrefix, http.MethodGet)
if err != nil {
fmt.Printf("Failed to get the cluster information: %s", err)
fmt.Printf("Failed to get the cluster information: %s\n", err)
return
}
fmt.Println(r)
Expand Down
6 changes: 3 additions & 3 deletions pdctl/command/config_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func NewSetConfigCommand() *cobra.Command {
func showConfigCommandFunc(cmd *cobra.Command, args []string) {
r, err := doRequest(cmd, schedulePrefix, http.MethodGet)
if err != nil {
fmt.Printf("Failed to get config: %s", err)
fmt.Printf("Failed to get config: %s\n", err)
return
}
fmt.Println(r)
Expand All @@ -83,7 +83,7 @@ func showConfigCommandFunc(cmd *cobra.Command, args []string) {
func showAllConfigCommandFunc(cmd *cobra.Command, args []string) {
r, err := doRequest(cmd, configPrefix, http.MethodGet)
if err != nil {
fmt.Printf("Failed to get config: %s", err)
fmt.Printf("Failed to get config: %s\n", err)
return
}
fmt.Println(r)
Expand Down Expand Up @@ -117,7 +117,7 @@ func setConfigCommandFunc(cmd *cobra.Command, args []string) {
opt, val := args[0], args[1]
err := postConfigDataWithPath(cmd, opt, val, configPrefix)
if err != nil {
fmt.Printf("Failed to set config: %s", err)
fmt.Printf("Failed to set config: %s\n", err)
return
}
fmt.Println("Success!")
Expand Down
4 changes: 2 additions & 2 deletions pdctl/command/hot_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func NewHotRegionCommand() *cobra.Command {
func showHotRegionsCommandFunc(cmd *cobra.Command, args []string) {
r, err := doRequest(cmd, hotRegionsPrefix, http.MethodGet)
if err != nil {
fmt.Printf("Failed to get hotspot: %s", err)
fmt.Printf("Failed to get hotspot: %s\n", err)
return
}
fmt.Println(r)
Expand All @@ -68,7 +68,7 @@ func NewHotStoreCommand() *cobra.Command {
func showHotStoresCommandFunc(cmd *cobra.Command, args []string) {
r, err := doRequest(cmd, hotStoresPrefix, http.MethodGet)
if err != nil {
fmt.Printf("Failed to get hotspot: %s", err)
fmt.Printf("Failed to get hotspot: %s\n", err)
return
}
fmt.Println(r)
Expand Down
4 changes: 2 additions & 2 deletions pdctl/command/label_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func NewLabelListStoresCommand() *cobra.Command {
func showLabelsCommandFunc(cmd *cobra.Command, args []string) {
r, err := doRequest(cmd, labelsPrefix, http.MethodGet)
if err != nil {
fmt.Printf("Failed to get labels: %s", err)
fmt.Printf("Failed to get labels: %s\n", err)
return
}
fmt.Println(r)
Expand All @@ -72,7 +72,7 @@ func showLabelListStoresCommandFunc(cmd *cobra.Command, args []string) {
prefix := fmt.Sprintf("%s?%s&%s", labelsStorePrefix, namePrefix, valuePrefix)
r, err := doRequest(cmd, prefix, http.MethodGet)
if err != nil {
fmt.Printf("Failed to get stores through label: %s", err)
fmt.Printf("Failed to get stores through label: %s\n", err)
return
}
fmt.Println(r)
Expand Down
40 changes: 31 additions & 9 deletions pdctl/command/member_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (

var (
membersPrefix = "pd/api/v1/members"
memberPrefix = "pd/api/v1/members/%s"
leaderMemberPrefix = "pd/api/v1/leader"
)

Expand All @@ -41,10 +40,19 @@ func NewMemberCommand() *cobra.Command {
// NewDeleteMemberCommand return a delete subcommand of memberCmd
func NewDeleteMemberCommand() *cobra.Command {
d := &cobra.Command{
Use: "delete <member_name>",
Short: "delete the member",
Run: deleteMemberCommandFunc,
Use: "delete <subcommand>",
Short: "delete a member",
}
d.AddCommand(&cobra.Command{
Use: "name <member_name>",
Short: "delete a member by name",
Run: deleteMemberByNameCommandFunc,
})
d.AddCommand(&cobra.Command{
Use: "id <member_id>",
Short: "delete a member by id",
Run: deleteMemberByIDCommandFunc,
})
return d
}

Expand All @@ -61,21 +69,35 @@ func NewLeaderMemberCommand() *cobra.Command {
func showMemberCommandFunc(cmd *cobra.Command, args []string) {
r, err := doRequest(cmd, membersPrefix, http.MethodGet)
if err != nil {
fmt.Printf("Failed to get pd members: %s", err)
fmt.Printf("Failed to get pd members: %s\n", err)
return
}
fmt.Println(r)
}

func deleteMemberCommandFunc(cmd *cobra.Command, args []string) {
func deleteMemberByNameCommandFunc(cmd *cobra.Command, args []string) {
if len(args) != 1 {
fmt.Println("Usage: member delete <member_name>")
return
}
prefix := fmt.Sprintf(memberPrefix, args[0])
prefix := membersPrefix + "/name/" + args[0]
_, err := doRequest(cmd, prefix, http.MethodDelete)
if err != nil {
fmt.Printf("Failed to delete member %s: %s", args[0], err)
fmt.Printf("Failed to delete member %s: %s\n", args[0], err)
return
}
fmt.Println("Success!")
}

func deleteMemberByIDCommandFunc(cmd *cobra.Command, args []string) {
if len(args) != 1 {
fmt.Println("Usage: member delete id <member_id>")
return
}
prefix := membersPrefix + "/id/" + args[0]
_, err := doRequest(cmd, prefix, http.MethodDelete)
if err != nil {
fmt.Printf("Failed to delete member %s: %s\n", args[0], err)
return
}
fmt.Println("Success!")
Expand All @@ -84,7 +106,7 @@ func deleteMemberCommandFunc(cmd *cobra.Command, args []string) {
func getLeaderMemberCommandFunc(cmd *cobra.Command, args []string) {
r, err := doRequest(cmd, leaderMemberPrefix, http.MethodGet)
if err != nil {
fmt.Printf("Failed to get the leader of pd members: %s", err)
fmt.Printf("Failed to get the leader of pd members: %s\n", err)
return
}
fmt.Println(r)
Expand Down
4 changes: 2 additions & 2 deletions pdctl/command/region_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func showRegionCommandFunc(cmd *cobra.Command, args []string) {
}
r, err := doRequest(cmd, prefix, http.MethodGet)
if err != nil {
fmt.Printf("Failed to get region: %s", err)
fmt.Printf("Failed to get region: %s\n", err)
return
}
fmt.Println(r)
Expand Down Expand Up @@ -104,7 +104,7 @@ func showRegionWithTableCommandFunc(cmd *cobra.Command, args []string) {
prefix := regionKeyPrefix + "/" + key
r, err := doRequest(cmd, prefix, http.MethodGet)
if err != nil {
fmt.Printf("Failed to get region: %s", err)
fmt.Printf("Failed to get region: %s\n", err)
return
}
fmt.Println(r)
Expand Down
4 changes: 2 additions & 2 deletions pdctl/command/store_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func showStoreCommandFunc(cmd *cobra.Command, args []string) {
}
r, err := doRequest(cmd, prefix, http.MethodGet)
if err != nil {
fmt.Printf("Failed to get store: %s", err)
fmt.Printf("Failed to get store: %s\n", err)
return
}
fmt.Println(r)
Expand All @@ -89,7 +89,7 @@ func deleteStoreCommandFunc(cmd *cobra.Command, args []string) {
prefix := fmt.Sprintf(storePrefix, args[0])
_, err := doRequest(cmd, prefix, http.MethodDelete)
if err != nil {
fmt.Printf("Failed to delete store %s: %s", args[0], err)
fmt.Printf("Failed to delete store %s: %s\n", args[0], err)
return
}
fmt.Println("Success!")
Expand Down
2 changes: 1 addition & 1 deletion pdctl/command/tso_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func showTSOCommandFunc(cmd *cobra.Command, args []string) {
}
ts, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
fmt.Printf("Failed to parse TSO: %s", err)
fmt.Printf("Failed to parse TSO: %s\n", err)
return
}
logical := ts & logicalBits
Expand Down
20 changes: 19 additions & 1 deletion server/api/member.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package api
import (
"fmt"
"net/http"
"strconv"
"time"

"github.com/gorilla/mux"
Expand Down Expand Up @@ -64,7 +65,7 @@ func newMemberDeleteHandler(svr *server.Server, rd *render.Render) *memberDelete
}
}

func (h *memberDeleteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func (h *memberDeleteHandler) DeleteByName(w http.ResponseWriter, r *http.Request) {
client := h.svr.GetClient()

// step 1. get etcd id
Expand Down Expand Up @@ -96,6 +97,23 @@ func (h *memberDeleteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
h.rd.JSON(w, http.StatusOK, fmt.Sprintf("removed, pd: %s", name))
}

func (h *memberDeleteHandler) DeleteByID(w http.ResponseWriter, r *http.Request) {
idStr := mux.Vars(r)["id"]
id, err := strconv.ParseUint(idStr, 10, 64)
if err != nil {
h.rd.JSON(w, http.StatusInternalServerError, err.Error())
return
}

client := h.svr.GetClient()
_, err = etcdutil.RemoveEtcdMember(client, id)
if err != nil {
h.rd.JSON(w, http.StatusInternalServerError, err.Error())
return
}
h.rd.JSON(w, http.StatusOK, fmt.Sprintf("removed, pd: %v", id))
}

type leaderHandler struct {
svr *server.Server
rd *render.Render
Expand Down
16 changes: 15 additions & 1 deletion server/api/member_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"math/rand"
"net/http"
"sort"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -83,6 +84,11 @@ func (s *testMemberAPISuite) TestMemberList(c *C) {
}

func (s *testMemberAPISuite) TestMemberDelete(c *C) {
s.testMemberDelete(c, true)
s.testMemberDelete(c, false)
}

func (s *testMemberAPISuite) testMemberDelete(c *C, byName bool) {
cfgs, svrs, clean := mustNewCluster(c, 3)
defer clean()

Expand All @@ -109,6 +115,7 @@ func (s *testMemberAPISuite) TestMemberDelete(c *C) {

var table = []struct {
name string
id uint64
checker Checker
status int
}{
Expand All @@ -121,19 +128,26 @@ func (s *testMemberAPISuite) TestMemberDelete(c *C) {
{
// delete a pd randomly
name: server.Name(),
id: server.ID(),
checker: Equals,
status: http.StatusOK,
},
{
// delete it again
name: server.Name(),
id: server.ID(),
checker: Equals,
status: http.StatusNotFound,
},
}

for _, t := range table {
addr := clientURL + apiPrefix + "/api/v1/members/" + t.name
var addr string
if byName {
addr = clientURL + apiPrefix + "/api/v1/members/name/" + t.name
} else {
addr = clientURL + apiPrefix + "/api/v1/members/id/" + strconv.FormatUint(t.id, 10)
}
req, err := http.NewRequest("DELETE", addr, nil)
c.Assert(err, IsNil)
resp, err := s.hc.Do(req)
Expand Down
4 changes: 3 additions & 1 deletion server/api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ func createRouter(prefix string, svr *server.Server) *mux.Router {
router.Handle("/api/v1/status", newStatusHandler(rd)).Methods("GET")

router.Handle("/api/v1/members", newMemberListHandler(svr, rd)).Methods("GET")
router.Handle("/api/v1/members/{name}", newMemberDeleteHandler(svr, rd)).Methods("DELETE")
memberDeleteHandler := newMemberDeleteHandler(svr, rd)
router.HandleFunc("/api/v1/members/name/{name}", memberDeleteHandler.DeleteByName).Methods("DELETE")
router.HandleFunc("/api/v1/members/id/{id}", memberDeleteHandler.DeleteByID).Methods("DELETE")
router.Handle("/api/v1/leader", newLeaderHandler(svr, rd)).Methods("GET")

router.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {}).Methods("GET")
Expand Down

0 comments on commit 30115ae

Please sign in to comment.