Make generic etcd more powerful and return operations from etcd
When we complete an operation, etcd usually provides a response object. Return that object up instead of querying etcd twice.
This commit is contained in:
@@ -236,7 +236,19 @@ func (h *EtcdHelper) bodyAndExtractObj(key string, objPtr runtime.Object, ignore
|
||||
if err != nil && !IsEtcdNotFound(err) {
|
||||
return "", 0, err
|
||||
}
|
||||
if err != nil || response.Node == nil || len(response.Node.Value) == 0 {
|
||||
return h.extractObj(response, err, objPtr, ignoreNotFound, false)
|
||||
}
|
||||
|
||||
func (h *EtcdHelper) extractObj(response *etcd.Response, inErr error, objPtr runtime.Object, ignoreNotFound, prevNode bool) (body string, modifiedIndex uint64, err error) {
|
||||
var node *etcd.Node
|
||||
if response != nil {
|
||||
if prevNode {
|
||||
node = response.PrevNode
|
||||
} else {
|
||||
node = response.Node
|
||||
}
|
||||
}
|
||||
if inErr != nil || node == nil || len(node.Value) == 0 {
|
||||
if ignoreNotFound {
|
||||
v, err := conversion.EnforcePtr(objPtr)
|
||||
if err != nil {
|
||||
@@ -244,18 +256,18 @@ func (h *EtcdHelper) bodyAndExtractObj(key string, objPtr runtime.Object, ignore
|
||||
}
|
||||
v.Set(reflect.Zero(v.Type()))
|
||||
return "", 0, nil
|
||||
} else if err != nil {
|
||||
return "", 0, err
|
||||
} else if inErr != nil {
|
||||
return "", 0, inErr
|
||||
}
|
||||
return "", 0, fmt.Errorf("key '%v' found no nodes field: %#v", key, response)
|
||||
return "", 0, fmt.Errorf("unable to locate a value on the response: %#v", response)
|
||||
}
|
||||
body = response.Node.Value
|
||||
body = node.Value
|
||||
err = h.Codec.DecodeInto([]byte(body), objPtr)
|
||||
if h.ResourceVersioner != nil {
|
||||
_ = h.ResourceVersioner.SetResourceVersion(objPtr, response.Node.ModifiedIndex)
|
||||
_ = h.ResourceVersioner.SetResourceVersion(objPtr, node.ModifiedIndex)
|
||||
// being unable to set the version does not prevent the object from being extracted
|
||||
}
|
||||
return body, response.Node.ModifiedIndex, err
|
||||
return body, node.ModifiedIndex, err
|
||||
}
|
||||
|
||||
// CreateObj adds a new object at a key unless it already exists. 'ttl' is time-to-live in seconds,
|
||||
@@ -275,12 +287,50 @@ func (h *EtcdHelper) CreateObj(key string, obj runtime.Object, ttl uint64) error
|
||||
return err
|
||||
}
|
||||
|
||||
// Create adds a new object at a key unless it already exists. 'ttl' is time-to-live in seconds,
|
||||
// and 0 means forever. If no error is returned, out will be set to the read value from etcd.
|
||||
func (h *EtcdHelper) Create(key string, obj, out runtime.Object, ttl uint64) error {
|
||||
data, err := h.Codec.Encode(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if h.ResourceVersioner != nil {
|
||||
if version, err := h.ResourceVersioner.ResourceVersion(obj); err == nil && version != 0 {
|
||||
return errors.New("resourceVersion may not be set on objects to be created")
|
||||
}
|
||||
}
|
||||
response, err := h.Client.Create(key, string(data), ttl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := conversion.EnforcePtr(out); err != nil {
|
||||
panic("unable to convert output object to pointer")
|
||||
}
|
||||
_, _, err = h.extractObj(response, err, out, false, false)
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete removes the specified key.
|
||||
func (h *EtcdHelper) Delete(key string, recursive bool) error {
|
||||
_, err := h.Client.Delete(key, recursive)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteObj removes the specified key and returns the value that existed at that spot.
|
||||
func (h *EtcdHelper) DeleteObj(key string, out runtime.Object) error {
|
||||
if _, err := conversion.EnforcePtr(out); err != nil {
|
||||
panic("unable to convert output object to pointer")
|
||||
}
|
||||
response, err := h.Client.Delete(key, false)
|
||||
if !IsEtcdNotFound(err) {
|
||||
// if the object that existed prior to the delete is returned by etcd, update out.
|
||||
if err != nil || response.PrevNode != nil {
|
||||
_, _, err = h.extractObj(response, err, out, false, true)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SetObj marshals obj via json, and stores under key. Will do an atomic update if obj's ResourceVersion
|
||||
// field is set. 'ttl' is time-to-live in seconds, and 0 means forever.
|
||||
func (h *EtcdHelper) SetObj(key string, obj runtime.Object, ttl uint64) error {
|
||||
@@ -359,10 +409,11 @@ func (h *EtcdHelper) AtomicUpdate(key string, ptrToType runtime.Object, ignoreNo
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = h.Client.CompareAndSwap(key, string(data), 0, origBody, index)
|
||||
response, err := h.Client.CompareAndSwap(key, string(data), 0, origBody, index)
|
||||
if IsEtcdTestFailed(err) {
|
||||
continue
|
||||
}
|
||||
_, _, err = h.extractObj(response, err, ptrToType, false, false)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user