From 48e144ae2e41050f51e3d78e5e517da8d9699a5d Mon Sep 17 00:00:00 2001 From: Chance Zibolski Date: Wed, 6 May 2015 16:09:59 -0700 Subject: [PATCH] client: Support creating directory through KeysAPI Creating a directory is done using the Set() method and a SetOptions struct with it's Dir field set to true. --- client/keys.go | 31 ++++++++++++++++++++++++------- client/keys_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/client/keys.go b/client/keys.go index 1ac2e9fc8..32379b51d 100644 --- a/client/keys.go +++ b/client/keys.go @@ -95,7 +95,8 @@ type KeysAPI interface { 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 - // 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) // 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 // ignore the current value of the Node. This cannot be used // to compare the Node's current value to an empty string. + // + // PrevValue is ignored if Dir=true PrevValue string // 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 // a TTL of 0. TTL time.Duration + + // Dir specifies whether or not this Node should be created as a directory. + Dir bool } type GetOptions struct { @@ -296,6 +302,7 @@ func (k *httpKeysAPI) Set(ctx context.Context, key, val string, opts *SetOptions act.PrevIndex = opts.PrevIndex act.PrevExist = opts.PrevExist act.TTL = opts.TTL + act.Dir = opts.Dir } resp, body, err := k.client.Do(ctx, act) @@ -468,28 +475,38 @@ type setAction struct { PrevIndex uint64 PrevExist PrevExistType TTL time.Duration + Dir bool } func (a *setAction) HTTPRequest(ep url.URL) *http.Request { u := v2KeysURL(ep, a.Prefix, a.Key) params := u.Query() - if a.PrevValue != "" { - params.Set("prevValue", a.PrevValue) + form := url.Values{} + + // 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 { params.Set("prevIndex", strconv.FormatUint(a.PrevIndex, 10)) } if a.PrevExist != PrevIgnore { params.Set("prevExist", string(a.PrevExist)) } - u.RawQuery = params.Encode() - - form := url.Values{} - form.Add("value", a.Value) if a.TTL > 0 { form.Add("ttl", strconv.FormatUint(uint64(a.TTL.Seconds()), 10)) } + + u.RawQuery = params.Encode() body := strings.NewReader(form.Encode()) req, _ := http.NewRequest("PUT", u.String(), body) diff --git a/client/keys_test.go b/client/keys_test.go index 56070d528..037121cc0 100644 --- a/client/keys_test.go +++ b/client/keys_test.go @@ -330,6 +330,45 @@ func TestSetAction(t *testing.T) { wantURL: "http://example.com/foo", 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 { @@ -967,6 +1006,7 @@ func TestHTTPKeysAPISetAction(t *testing.T) { PrevIndex: 13, PrevExist: PrevExist, TTL: time.Minute, + Dir: true, }, wantAction: &setAction{ Key: "/foo", @@ -975,6 +1015,7 @@ func TestHTTPKeysAPISetAction(t *testing.T) { PrevIndex: 13, PrevExist: PrevExist, TTL: time.Minute, + Dir: true, }, }, }