Merge pull request #2792 from ecnahc515/client_create_dir

client: Support creating directory through KeysAPI
release-2.1
Xiang Li 2015-05-07 11:13:49 -07:00
commit b24dd8e4e6
2 changed files with 65 additions and 7 deletions

View File

@ -95,7 +95,8 @@ type KeysAPI interface {
Get(ctx context.Context, key string, opts *GetOptions) (*Response, error) Get(ctx context.Context, key string, opts *GetOptions) (*Response, error)
// Set assigns a new value to a Node identified by a given key. The caller // Set assigns a new value to a Node identified by a given key. The caller
// may define a set of conditions in the SetOptions. // may define a set of conditions in the SetOptions. If SetOptions.Dir=true
// than value is ignored.
Set(ctx context.Context, key, value string, opts *SetOptions) (*Response, error) Set(ctx context.Context, key, value string, opts *SetOptions) (*Response, error)
// Delete removes a Node identified by the given key, optionally destroying // Delete removes a Node identified by the given key, optionally destroying
@ -151,6 +152,8 @@ type SetOptions struct {
// Leaving this field empty means that the caller wishes to // Leaving this field empty means that the caller wishes to
// ignore the current value of the Node. This cannot be used // ignore the current value of the Node. This cannot be used
// to compare the Node's current value to an empty string. // to compare the Node's current value to an empty string.
//
// PrevValue is ignored if Dir=true
PrevValue string PrevValue string
// PrevIndex indicates what the current ModifiedIndex of the // PrevIndex indicates what the current ModifiedIndex of the
@ -170,6 +173,9 @@ type SetOptions struct {
// that the zero-value is ignored, TTL cannot be used to set // that the zero-value is ignored, TTL cannot be used to set
// a TTL of 0. // a TTL of 0.
TTL time.Duration TTL time.Duration
// Dir specifies whether or not this Node should be created as a directory.
Dir bool
} }
type GetOptions struct { type GetOptions struct {
@ -296,6 +302,7 @@ func (k *httpKeysAPI) Set(ctx context.Context, key, val string, opts *SetOptions
act.PrevIndex = opts.PrevIndex act.PrevIndex = opts.PrevIndex
act.PrevExist = opts.PrevExist act.PrevExist = opts.PrevExist
act.TTL = opts.TTL act.TTL = opts.TTL
act.Dir = opts.Dir
} }
resp, body, err := k.client.Do(ctx, act) resp, body, err := k.client.Do(ctx, act)
@ -468,28 +475,38 @@ type setAction struct {
PrevIndex uint64 PrevIndex uint64
PrevExist PrevExistType PrevExist PrevExistType
TTL time.Duration TTL time.Duration
Dir bool
} }
func (a *setAction) HTTPRequest(ep url.URL) *http.Request { func (a *setAction) HTTPRequest(ep url.URL) *http.Request {
u := v2KeysURL(ep, a.Prefix, a.Key) u := v2KeysURL(ep, a.Prefix, a.Key)
params := u.Query() params := u.Query()
if a.PrevValue != "" { form := url.Values{}
params.Set("prevValue", a.PrevValue)
// we're either creating a directory or setting a key
if a.Dir {
params.Set("dir", strconv.FormatBool(a.Dir))
} else {
// These options are only valid for setting a key
if a.PrevValue != "" {
params.Set("prevValue", a.PrevValue)
}
form.Add("value", a.Value)
} }
// Options which apply to both setting a key and creating a dir
if a.PrevIndex != 0 { if a.PrevIndex != 0 {
params.Set("prevIndex", strconv.FormatUint(a.PrevIndex, 10)) params.Set("prevIndex", strconv.FormatUint(a.PrevIndex, 10))
} }
if a.PrevExist != PrevIgnore { if a.PrevExist != PrevIgnore {
params.Set("prevExist", string(a.PrevExist)) params.Set("prevExist", string(a.PrevExist))
} }
u.RawQuery = params.Encode()
form := url.Values{}
form.Add("value", a.Value)
if a.TTL > 0 { if a.TTL > 0 {
form.Add("ttl", strconv.FormatUint(uint64(a.TTL.Seconds()), 10)) form.Add("ttl", strconv.FormatUint(uint64(a.TTL.Seconds()), 10))
} }
u.RawQuery = params.Encode()
body := strings.NewReader(form.Encode()) body := strings.NewReader(form.Encode())
req, _ := http.NewRequest("PUT", u.String(), body) req, _ := http.NewRequest("PUT", u.String(), body)

View File

@ -330,6 +330,45 @@ func TestSetAction(t *testing.T) {
wantURL: "http://example.com/foo", wantURL: "http://example.com/foo",
wantBody: "ttl=180&value=", wantBody: "ttl=180&value=",
}, },
// Dir is set
{
act: setAction{
Key: "foo",
Dir: true,
},
wantURL: "http://example.com/foo?dir=true",
wantBody: "",
},
// Dir is set with a value
{
act: setAction{
Key: "foo",
Value: "bar",
Dir: true,
},
wantURL: "http://example.com/foo?dir=true",
wantBody: "",
},
// Dir is set with PrevExist set to true
{
act: setAction{
Key: "foo",
PrevExist: PrevExist,
Dir: true,
},
wantURL: "http://example.com/foo?dir=true&prevExist=true",
wantBody: "",
},
// Dir is set with PrevValue
{
act: setAction{
Key: "foo",
PrevValue: "bar",
Dir: true,
},
wantURL: "http://example.com/foo?dir=true",
wantBody: "",
},
} }
for i, tt := range tests { for i, tt := range tests {
@ -967,6 +1006,7 @@ func TestHTTPKeysAPISetAction(t *testing.T) {
PrevIndex: 13, PrevIndex: 13,
PrevExist: PrevExist, PrevExist: PrevExist,
TTL: time.Minute, TTL: time.Minute,
Dir: true,
}, },
wantAction: &setAction{ wantAction: &setAction{
Key: "/foo", Key: "/foo",
@ -975,6 +1015,7 @@ func TestHTTPKeysAPISetAction(t *testing.T) {
PrevIndex: 13, PrevIndex: 13,
PrevExist: PrevExist, PrevExist: PrevExist,
TTL: time.Minute, TTL: time.Minute,
Dir: true,
}, },
}, },
} }