// extendMaster attempts to extend ownership of a master lock for TTL seconds. // returns "", nil if extension failed // returns id, nil if extension succeeded // returns "", err if an error occurred func (e *etcdMasterElector) extendMaster(path, id string, ttl uint64, res *etcd.Response) (string, error) { // If it matches the passed in id, extend the lease by writing a new entry. // Uses compare and swap, so that if we TTL out in the meantime, the write will fail. // We don't handle the TTL delete w/o a write case here, it's handled in the next loop // iteration. _, err := e.etcd.CompareAndSwap(path, id, ttl, "", res.Node.ModifiedIndex) if err != nil && !tools.IsEtcdTestFailed(err) { return "", err } if err != nil && tools.IsEtcdTestFailed(err) { return "", nil } return id, nil }
// errToAPIStatus converts an error to an api.Status object. func errToAPIStatus(err error) *api.Status { switch t := err.(type) { case statusError: status := t.Status() status.Status = api.StatusFailure //TODO: check for invalid responses return &status default: status := http.StatusInternalServerError switch { //TODO: replace me with NewConflictErr case tools.IsEtcdTestFailed(err): status = http.StatusConflict } // Log errors that were not converted to an error status // by REST storage - these typically indicate programmer // error by not using pkg/api/errors, or unexpected failure // cases. glog.V(1).Infof("An unchecked error was received: %v", err) return &api.Status{ Status: api.StatusFailure, Code: status, Reason: api.StatusReasonUnknown, Message: err.Error(), } } }
// MakeAsync takes a function and executes it, delivering the result in the way required // by RESTStorage's Update, Delete, and Create methods. func MakeAsync(fn WorkFunc) <-chan interface{} { channel := make(chan interface{}) go func() { defer util.HandleCrash() obj, err := fn() if err != nil { status := http.StatusInternalServerError switch { case tools.IsEtcdTestFailed(err): status = http.StatusConflict } channel <- &api.Status{ Status: api.StatusFailure, Message: err.Error(), Code: status, } } else { channel <- obj } // 'close' is used to signal that no further values will // be written to the channel. Not strictly necessary, but // also won't hurt. close(channel) }() return channel }
// InterpretUpdateError converts a generic etcd error on a update // operation into the appropriate API error. func InterpretUpdateError(err error, kind, name string) error { switch { case tools.IsEtcdTestFailed(err), tools.IsEtcdNodeExist(err): return errors.NewConflict(kind, name, err) default: return err } }
// errToAPIStatus converts an error to an api.Status object. func errToAPIStatus(err error) *api.Status { switch t := err.(type) { case statusError: status := t.Status() if len(status.Status) == 0 { } switch status.Status { case api.StatusSuccess: if status.Code == 0 { status.Code = http.StatusOK } case "": status.Status = api.StatusFailure fallthrough case api.StatusFailure: if status.Code == 0 { status.Code = http.StatusInternalServerError } } //TODO: check for invalid responses return &status default: status := http.StatusInternalServerError switch { //TODO: replace me with NewConflictErr case tools.IsEtcdTestFailed(err): status = http.StatusConflict } // Log errors that were not converted to an error status // by REST storage - these typically indicate programmer // error by not using pkg/api/errors, or unexpected failure // cases. util.HandleError(fmt.Errorf("apiserver received an error that is not an api.Status: %v", err)) return &api.Status{ Status: api.StatusFailure, Code: status, Reason: api.StatusReasonUnknown, Message: err.Error(), } } }
// errToAPIStatus converts an error to an api.Status object. func errToAPIStatus(err error) *api.Status { switch t := err.(type) { case *apiServerError: status := t.Status status.Status = api.StatusFailure //TODO: check for invalid responses return &status default: status := http.StatusInternalServerError switch { //TODO: replace me with NewUpdateConflictErr case tools.IsEtcdTestFailed(err): status = http.StatusConflict } return &api.Status{ Status: api.StatusFailure, Code: status, Reason: api.ReasonTypeUnknown, Message: err.Error(), } } }