client: explicitly carry API prefix around
parent
dee912f2fd
commit
7c1f4a9baf
|
@ -55,8 +55,6 @@ func newHTTPKeysAPIWithPrefix(tr *http.Transport, ep string, to time.Duration, p
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
u.Path = path.Join(u.Path, prefix)
|
|
||||||
|
|
||||||
c := &httpClient{
|
c := &httpClient{
|
||||||
transport: tr,
|
transport: tr,
|
||||||
endpoint: *u,
|
endpoint: *u,
|
||||||
|
@ -65,6 +63,7 @@ func newHTTPKeysAPIWithPrefix(tr *http.Transport, ep string, to time.Duration, p
|
||||||
|
|
||||||
kAPI := httpKeysAPI{
|
kAPI := httpKeysAPI{
|
||||||
client: c,
|
client: c,
|
||||||
|
prefix: prefix,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &kAPI, nil
|
return &kAPI, nil
|
||||||
|
@ -102,10 +101,12 @@ func (n *Node) String() string {
|
||||||
|
|
||||||
type httpKeysAPI struct {
|
type httpKeysAPI struct {
|
||||||
client *httpClient
|
client *httpClient
|
||||||
|
prefix string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *httpKeysAPI) Create(key, val string, ttl time.Duration) (*Response, error) {
|
func (k *httpKeysAPI) Create(key, val string, ttl time.Duration) (*Response, error) {
|
||||||
create := &createAction{
|
create := &createAction{
|
||||||
|
Prefix: k.prefix,
|
||||||
Key: key,
|
Key: key,
|
||||||
Value: val,
|
Value: val,
|
||||||
}
|
}
|
||||||
|
@ -124,6 +125,7 @@ func (k *httpKeysAPI) Create(key, val string, ttl time.Duration) (*Response, err
|
||||||
|
|
||||||
func (k *httpKeysAPI) Get(key string) (*Response, error) {
|
func (k *httpKeysAPI) Get(key string) (*Response, error) {
|
||||||
get := &getAction{
|
get := &getAction{
|
||||||
|
Prefix: k.prefix,
|
||||||
Key: key,
|
Key: key,
|
||||||
Recursive: false,
|
Recursive: false,
|
||||||
}
|
}
|
||||||
|
@ -140,6 +142,7 @@ func (k *httpKeysAPI) Watch(key string, idx uint64) Watcher {
|
||||||
return &httpWatcher{
|
return &httpWatcher{
|
||||||
client: k.client,
|
client: k.client,
|
||||||
nextWait: waitAction{
|
nextWait: waitAction{
|
||||||
|
Prefix: k.prefix,
|
||||||
Key: key,
|
Key: key,
|
||||||
WaitIndex: idx,
|
WaitIndex: idx,
|
||||||
Recursive: false,
|
Recursive: false,
|
||||||
|
@ -151,6 +154,7 @@ func (k *httpKeysAPI) RecursiveWatch(key string, idx uint64) Watcher {
|
||||||
return &httpWatcher{
|
return &httpWatcher{
|
||||||
client: k.client,
|
client: k.client,
|
||||||
nextWait: waitAction{
|
nextWait: waitAction{
|
||||||
|
Prefix: k.prefix,
|
||||||
Key: key,
|
Key: key,
|
||||||
WaitIndex: idx,
|
WaitIndex: idx,
|
||||||
Recursive: true,
|
Recursive: true,
|
||||||
|
@ -179,21 +183,24 @@ func (hw *httpWatcher) Next() (*Response, error) {
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// v2KeysURL forms a URL representing the location of a key. The provided
|
// v2KeysURL forms a URL representing the location of a key.
|
||||||
// endpoint must be the root of the etcd keys API. For example, a valid
|
// The endpoint argument represents the base URL of an etcd
|
||||||
// endpoint probably has the path "/v2/keys".
|
// server. The prefix is the path needed to route from the
|
||||||
func v2KeysURL(ep url.URL, key string) *url.URL {
|
// provided endpoint's path to the root of the keys API
|
||||||
ep.Path = path.Join(ep.Path, key)
|
// (typically "/v2/keys").
|
||||||
|
func v2KeysURL(ep url.URL, prefix, key string) *url.URL {
|
||||||
|
ep.Path = path.Join(ep.Path, prefix, key)
|
||||||
return &ep
|
return &ep
|
||||||
}
|
}
|
||||||
|
|
||||||
type getAction struct {
|
type getAction struct {
|
||||||
|
Prefix string
|
||||||
Key string
|
Key string
|
||||||
Recursive bool
|
Recursive bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *getAction) httpRequest(ep url.URL) *http.Request {
|
func (g *getAction) httpRequest(ep url.URL) *http.Request {
|
||||||
u := v2KeysURL(ep, g.Key)
|
u := v2KeysURL(ep, g.Prefix, g.Key)
|
||||||
|
|
||||||
params := u.Query()
|
params := u.Query()
|
||||||
params.Set("recursive", strconv.FormatBool(g.Recursive))
|
params.Set("recursive", strconv.FormatBool(g.Recursive))
|
||||||
|
@ -204,13 +211,14 @@ func (g *getAction) httpRequest(ep url.URL) *http.Request {
|
||||||
}
|
}
|
||||||
|
|
||||||
type waitAction struct {
|
type waitAction struct {
|
||||||
|
Prefix string
|
||||||
Key string
|
Key string
|
||||||
WaitIndex uint64
|
WaitIndex uint64
|
||||||
Recursive bool
|
Recursive bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *waitAction) httpRequest(ep url.URL) *http.Request {
|
func (w *waitAction) httpRequest(ep url.URL) *http.Request {
|
||||||
u := v2KeysURL(ep, w.Key)
|
u := v2KeysURL(ep, w.Prefix, w.Key)
|
||||||
|
|
||||||
params := u.Query()
|
params := u.Query()
|
||||||
params.Set("wait", "true")
|
params.Set("wait", "true")
|
||||||
|
@ -223,13 +231,14 @@ func (w *waitAction) httpRequest(ep url.URL) *http.Request {
|
||||||
}
|
}
|
||||||
|
|
||||||
type createAction struct {
|
type createAction struct {
|
||||||
|
Prefix string
|
||||||
Key string
|
Key string
|
||||||
Value string
|
Value string
|
||||||
TTL *uint64
|
TTL *uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *createAction) httpRequest(ep url.URL) *http.Request {
|
func (c *createAction) httpRequest(ep url.URL) *http.Request {
|
||||||
u := v2KeysURL(ep, c.Key)
|
u := v2KeysURL(ep, c.Prefix, c.Key)
|
||||||
|
|
||||||
params := u.Query()
|
params := u.Query()
|
||||||
params.Set("prevExist", "false")
|
params.Set("prevExist", "false")
|
||||||
|
|
|
@ -29,12 +29,14 @@ import (
|
||||||
func TestV2KeysURLHelper(t *testing.T) {
|
func TestV2KeysURLHelper(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
endpoint url.URL
|
endpoint url.URL
|
||||||
|
prefix string
|
||||||
key string
|
key string
|
||||||
want url.URL
|
want url.URL
|
||||||
}{
|
}{
|
||||||
// key is empty, no problem
|
// key is empty, no problem
|
||||||
{
|
{
|
||||||
endpoint: url.URL{Scheme: "http", Host: "example.com", Path: "/v2/keys"},
|
endpoint: url.URL{Scheme: "http", Host: "example.com", Path: "/v2/keys"},
|
||||||
|
prefix: "",
|
||||||
key: "",
|
key: "",
|
||||||
want: url.URL{Scheme: "http", Host: "example.com", Path: "/v2/keys"},
|
want: url.URL{Scheme: "http", Host: "example.com", Path: "/v2/keys"},
|
||||||
},
|
},
|
||||||
|
@ -42,6 +44,7 @@ func TestV2KeysURLHelper(t *testing.T) {
|
||||||
// key is joined to path
|
// key is joined to path
|
||||||
{
|
{
|
||||||
endpoint: url.URL{Scheme: "http", Host: "example.com", Path: "/v2/keys"},
|
endpoint: url.URL{Scheme: "http", Host: "example.com", Path: "/v2/keys"},
|
||||||
|
prefix: "",
|
||||||
key: "/foo/bar",
|
key: "/foo/bar",
|
||||||
want: url.URL{Scheme: "http", Host: "example.com", Path: "/v2/keys/foo/bar"},
|
want: url.URL{Scheme: "http", Host: "example.com", Path: "/v2/keys/foo/bar"},
|
||||||
},
|
},
|
||||||
|
@ -49,6 +52,7 @@ func TestV2KeysURLHelper(t *testing.T) {
|
||||||
// key is joined to path when path is empty
|
// key is joined to path when path is empty
|
||||||
{
|
{
|
||||||
endpoint: url.URL{Scheme: "http", Host: "example.com", Path: ""},
|
endpoint: url.URL{Scheme: "http", Host: "example.com", Path: ""},
|
||||||
|
prefix: "",
|
||||||
key: "/foo/bar",
|
key: "/foo/bar",
|
||||||
want: url.URL{Scheme: "http", Host: "example.com", Path: "/foo/bar"},
|
want: url.URL{Scheme: "http", Host: "example.com", Path: "/foo/bar"},
|
||||||
},
|
},
|
||||||
|
@ -56,6 +60,7 @@ func TestV2KeysURLHelper(t *testing.T) {
|
||||||
// Host field carries through with port
|
// Host field carries through with port
|
||||||
{
|
{
|
||||||
endpoint: url.URL{Scheme: "http", Host: "example.com:8080", Path: "/v2/keys"},
|
endpoint: url.URL{Scheme: "http", Host: "example.com:8080", Path: "/v2/keys"},
|
||||||
|
prefix: "",
|
||||||
key: "",
|
key: "",
|
||||||
want: url.URL{Scheme: "http", Host: "example.com:8080", Path: "/v2/keys"},
|
want: url.URL{Scheme: "http", Host: "example.com:8080", Path: "/v2/keys"},
|
||||||
},
|
},
|
||||||
|
@ -63,13 +68,21 @@ func TestV2KeysURLHelper(t *testing.T) {
|
||||||
// Scheme carries through
|
// Scheme carries through
|
||||||
{
|
{
|
||||||
endpoint: url.URL{Scheme: "https", Host: "example.com", Path: "/v2/keys"},
|
endpoint: url.URL{Scheme: "https", Host: "example.com", Path: "/v2/keys"},
|
||||||
|
prefix: "",
|
||||||
key: "",
|
key: "",
|
||||||
want: url.URL{Scheme: "https", Host: "example.com", Path: "/v2/keys"},
|
want: url.URL{Scheme: "https", Host: "example.com", Path: "/v2/keys"},
|
||||||
},
|
},
|
||||||
|
// Prefix is applied
|
||||||
|
{
|
||||||
|
endpoint: url.URL{Scheme: "https", Host: "example.com", Path: "/foo"},
|
||||||
|
prefix: "/bar",
|
||||||
|
key: "/baz",
|
||||||
|
want: url.URL{Scheme: "https", Host: "example.com", Path: "/foo/bar/baz"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
got := v2KeysURL(tt.endpoint, tt.key)
|
got := v2KeysURL(tt.endpoint, tt.prefix, tt.key)
|
||||||
if tt.want != *got {
|
if tt.want != *got {
|
||||||
t.Errorf("#%d: want=%#v, got=%#v", i, tt.want, *got)
|
t.Errorf("#%d: want=%#v, got=%#v", i, tt.want, *got)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,6 @@ func NewMembersAPI(tr *http.Transport, ep string, to time.Duration) (MembersAPI,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
u.Path = path.Join(u.Path, DefaultV2MembersPrefix)
|
|
||||||
|
|
||||||
c := &httpClient{
|
c := &httpClient{
|
||||||
transport: tr,
|
transport: tr,
|
||||||
endpoint: *u,
|
endpoint: *u,
|
||||||
|
@ -65,7 +63,8 @@ type httpMembersAPI struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *httpMembersAPI) List() ([]httptypes.Member, error) {
|
func (m *httpMembersAPI) List() ([]httptypes.Member, error) {
|
||||||
code, body, err := m.client.doWithTimeout(&membersAPIActionList{})
|
req := &membersAPIActionList{}
|
||||||
|
code, body, err := m.client.doWithTimeout(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -119,6 +118,7 @@ func (m *httpMembersAPI) Remove(memberID string) error {
|
||||||
type membersAPIActionList struct{}
|
type membersAPIActionList struct{}
|
||||||
|
|
||||||
func (l *membersAPIActionList) httpRequest(ep url.URL) *http.Request {
|
func (l *membersAPIActionList) httpRequest(ep url.URL) *http.Request {
|
||||||
|
ep.Path = path.Join(ep.Path, DefaultV2MembersPrefix)
|
||||||
req, _ := http.NewRequest("GET", ep.String(), nil)
|
req, _ := http.NewRequest("GET", ep.String(), nil)
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ type membersAPIActionRemove struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *membersAPIActionRemove) httpRequest(ep url.URL) *http.Request {
|
func (d *membersAPIActionRemove) httpRequest(ep url.URL) *http.Request {
|
||||||
ep.Path = path.Join(ep.Path, d.memberID)
|
ep.Path = path.Join(ep.Path, DefaultV2MembersPrefix, d.memberID)
|
||||||
req, _ := http.NewRequest("DELETE", ep.String(), nil)
|
req, _ := http.NewRequest("DELETE", ep.String(), nil)
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
@ -138,6 +138,7 @@ type membersAPIActionAdd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *membersAPIActionAdd) httpRequest(ep url.URL) *http.Request {
|
func (a *membersAPIActionAdd) httpRequest(ep url.URL) *http.Request {
|
||||||
|
ep.Path = path.Join(ep.Path, DefaultV2MembersPrefix)
|
||||||
m := httptypes.MemberCreateRequest{PeerURLs: a.peerURLs}
|
m := httptypes.MemberCreateRequest{PeerURLs: a.peerURLs}
|
||||||
b, _ := json.Marshal(&m)
|
b, _ := json.Marshal(&m)
|
||||||
req, _ := http.NewRequest("POST", ep.String(), bytes.NewReader(b))
|
req, _ := http.NewRequest("POST", ep.String(), bytes.NewReader(b))
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMembersAPIActionList(t *testing.T) {
|
func TestMembersAPIActionList(t *testing.T) {
|
||||||
ep := url.URL{Scheme: "http", Host: "example.com/v2/members"}
|
ep := url.URL{Scheme: "http", Host: "example.com"}
|
||||||
act := &membersAPIActionList{}
|
act := &membersAPIActionList{}
|
||||||
|
|
||||||
wantURL := &url.URL{
|
wantURL := &url.URL{
|
||||||
|
@ -42,7 +42,7 @@ func TestMembersAPIActionList(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMembersAPIActionAdd(t *testing.T) {
|
func TestMembersAPIActionAdd(t *testing.T) {
|
||||||
ep := url.URL{Scheme: "http", Host: "example.com/v2/admin/members"}
|
ep := url.URL{Scheme: "http", Host: "example.com"}
|
||||||
act := &membersAPIActionAdd{
|
act := &membersAPIActionAdd{
|
||||||
peerURLs: types.URLs([]url.URL{
|
peerURLs: types.URLs([]url.URL{
|
||||||
url.URL{Scheme: "https", Host: "127.0.0.1:8081"},
|
url.URL{Scheme: "https", Host: "127.0.0.1:8081"},
|
||||||
|
@ -53,7 +53,7 @@ func TestMembersAPIActionAdd(t *testing.T) {
|
||||||
wantURL := &url.URL{
|
wantURL := &url.URL{
|
||||||
Scheme: "http",
|
Scheme: "http",
|
||||||
Host: "example.com",
|
Host: "example.com",
|
||||||
Path: "/v2/admin/members",
|
Path: "/v2/members",
|
||||||
}
|
}
|
||||||
wantHeader := http.Header{
|
wantHeader := http.Header{
|
||||||
"Content-Type": []string{"application/json"},
|
"Content-Type": []string{"application/json"},
|
||||||
|
@ -68,7 +68,7 @@ func TestMembersAPIActionAdd(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMembersAPIActionRemove(t *testing.T) {
|
func TestMembersAPIActionRemove(t *testing.T) {
|
||||||
ep := url.URL{Scheme: "http", Host: "example.com/v2/members"}
|
ep := url.URL{Scheme: "http", Host: "example.com"}
|
||||||
act := &membersAPIActionRemove{memberID: "XXX"}
|
act := &membersAPIActionRemove{memberID: "XXX"}
|
||||||
|
|
||||||
wantURL := &url.URL{
|
wantURL := &url.URL{
|
||||||
|
|
Loading…
Reference in New Issue