Test atomic PUTs, and make them work.

Improve apiserver/logger.go's interface (it's pretty cool now).

Improve apiserver's error reporting to clients.

Improve client's handling of errors from apiserver.

Make failed PUTs return 409 (conflict)-- http status codes are amazingly
well defined for what we're doing!
This commit is contained in:
Daniel Smith
2014-07-02 13:51:27 -07:00
parent a6144f656c
commit 3b9735d787
8 changed files with 229 additions and 41 deletions

View File

@@ -118,14 +118,8 @@ func (h *EtcdHelper) ExtractList(key string, slicePtr interface{}) error {
// a zero object of the requested type, or an error, depending on ignoreNotFound. Treats
// empty responses and nil response nodes exactly like a not found error.
func (h *EtcdHelper) ExtractObj(key string, objPtr interface{}, ignoreNotFound bool) error {
_, index, err := h.bodyAndExtractObj(key, objPtr, ignoreNotFound)
if err != nil {
return err
}
if jsonBase, err := api.FindJSONBase(objPtr); err == nil {
jsonBase.ResourceVersion = index
}
return nil
_, _, err := h.bodyAndExtractObj(key, objPtr, ignoreNotFound)
return err
}
func (h *EtcdHelper) bodyAndExtractObj(key string, objPtr interface{}, ignoreNotFound bool) (body string, modifiedIndex uint64, err error) {
@@ -145,20 +139,30 @@ func (h *EtcdHelper) bodyAndExtractObj(key string, objPtr interface{}, ignoreNot
return "", 0, fmt.Errorf("key '%v' found no nodes field: %#v", key, response)
}
body = response.Node.Value
return body, response.Node.ModifiedIndex, json.Unmarshal([]byte(body), objPtr)
err = json.Unmarshal([]byte(body), objPtr)
if jsonBase, err := api.FindJSONBase(objPtr); err == nil {
jsonBase.ResourceVersion = response.Node.ModifiedIndex
// Note that err shadows the err returned below, so we won't
// return an error just because we failed to find a JSONBase.
// This is intentional.
}
return body, response.Node.ModifiedIndex, err
}
// SetObj marshals obj via json, and stores under key.
// SetObj marshals obj via json, and stores under key. Will do an
// atomic update if obj's ResourceVersion field is set.
func (h *EtcdHelper) SetObj(key string, obj interface{}) error {
data, err := json.Marshal(obj)
if err != nil {
return err
}
if jsonBase, err := api.FindJSONBase(obj); err == nil && jsonBase.ResourceVersion != 0 {
if jsonBase, err := api.FindJSONBaseRO(obj); err == nil && jsonBase.ResourceVersion != 0 {
_, err = h.Client.CompareAndSwap(key, string(data), 0, "", jsonBase.ResourceVersion)
} else {
_, err = h.Client.Set(key, string(data), 0)
return err // err is shadowed!
}
// TODO: when client supports atomic creation, integrate this with the above.
_, err = h.Client.Set(key, string(data), 0)
return err
}