/
client.go
141 lines (124 loc) · 3.63 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package pdutil
import (
"bytes"
"encoding/json"
"net/http"
"net/url"
"strconv"
"github.com/pingcap/errors"
"github.com/pingcap/kvproto/pkg/metapb"
httputil "github.com/pingcap/tipocket/pkg/util/http"
)
const (
schedulersPrefix = "/pd/api/v1/schedulers"
regionKeyPrefix = "/pd/api/v1/region/key/"
regionsSiblingPrefix = "/pd/api/v1/regions/sibling/"
operatorsPrefix = "/pd/api/v1/operators"
storesPrefix = "/pd/api/v1/stores"
regionsPrefix = "/pd/api/v1/regions"
contentJSON = "application/json"
)
// RegionInfo represents PD region info.
type RegionInfo struct {
ID uint64 `json:"id"`
StartKey string `json:"start_key"`
EndKey string `json:"end_key"`
Peers []*metapb.Peer `json:"peers,omitempty"`
Leader *metapb.Peer `json:"leader,omitempty"`
}
// Stores represents PD store response.
type Stores struct {
Count uint64 `json:"count"`
Stores []*StoreInfo `json:"stores"`
}
// StoreInfo represents PD store info.
type StoreInfo struct {
*metapb.Store `json:"store"`
}
// Client is a HTTP Client for PD.
type Client struct {
c *httputil.Client
pdAddr string
}
// NewPDClient creates a HTTP Client for PD.
func NewPDClient(c *http.Client, pdAddr string) *Client {
return &Client{c: httputil.NewHTTPClient(c), pdAddr: pdAddr}
}
// AddScheduler adds the specified scheduler to PD.
func (p *Client) AddScheduler(schedulerName string) error {
input := map[string]string{"name": schedulerName}
data, err := json.Marshal(input)
if err != nil {
return err
}
_, err = p.c.Post(p.pdAddr+schedulersPrefix, "application/json", bytes.NewBuffer(data))
return err
}
// RemoveScheduler removes the specified scheduler from PD.
func (p *Client) RemoveScheduler(schedulerName string) error {
return p.c.Delete(p.pdAddr + schedulersPrefix + "/" + schedulerName)
}
// ListRegions lists region infos.
func (p *Client) ListRegions() ([]*RegionInfo, error) {
resp, err := p.c.Get(p.pdAddr + regionsPrefix)
if err != nil {
return nil, err
}
var body struct {
Regions []*RegionInfo `json:"regions"`
}
err = json.Unmarshal(resp, &body)
if err != nil {
return nil, errors.Wrap(err, "Unmarshal `[]RegionInfo` failed")
}
return body.Regions, nil
}
// GetStores gets PD stores information.
func (p *Client) GetStores() (*Stores, error) {
resp, err := p.c.Get(p.pdAddr + storesPrefix)
if err != nil {
return nil, err
}
stores := &Stores{}
err = json.Unmarshal(resp, stores)
if err != nil {
return nil, errors.Wrap(err, "Unmarshal `Stores` failed")
}
return stores, nil
}
// GetRegionByKey gets the region info by region key.
func (p *Client) GetRegionByKey(key string) (*RegionInfo, error) {
resp, err := p.c.Get(p.pdAddr + regionKeyPrefix + url.QueryEscape(key))
if err != nil {
return nil, err
}
region := &RegionInfo{}
err = json.Unmarshal(resp, region)
if err != nil {
return nil, errors.Wrap(err, "Unmarshal `RegionInfo` failed")
}
return region, nil
}
// Operators sends PD operators request.
func (p *Client) Operators(input map[string]interface{}) error {
body, err := json.Marshal(input)
if err != nil {
return err
}
_, err = p.c.Post(p.pdAddr+operatorsPrefix, contentJSON, bytes.NewBuffer(body))
return err
}
// GetSiblingRegions gets the siblings' region info.
func (p *Client) GetSiblingRegions(id uint64) ([]*RegionInfo, error) {
resp, err := p.c.Get(p.pdAddr + regionsSiblingPrefix + strconv.FormatUint(id, 10))
if err != nil {
return nil, err
}
var body struct {
Regions []*RegionInfo `json:"regions"`
}
if err = json.Unmarshal(resp, &body); err != nil {
return nil, errors.Wrap(err, "Unmarshal `[]RegionInfo` failed")
}
return body.Regions, nil
}