Skip to content

Commit

Permalink
Merge pull request kubernetes#23295 from hongchaodeng/error
Browse files Browse the repository at this point in the history
Auto commit by PR queue bot
  • Loading branch information
k8s-merge-robot committed Mar 23, 2016
2 parents da58256 + 189ce6e commit 2777cd7
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 26 deletions.
3 changes: 1 addition & 2 deletions pkg/registry/pod/etcd/etcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"strings"
"testing"

etcd "github.com/coreos/etcd/client"
"golang.org/x/net/context"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
Expand Down Expand Up @@ -140,7 +139,7 @@ type FailDeletionStorage struct {

func (f FailDeletionStorage) Delete(ctx context.Context, key string, out runtime.Object) error {
*f.Called = true
return etcd.Error{Code: etcd.ErrorCodeKeyNotFound}
return storage.NewKeyNotFoundError(key, 0)
}

func newFailDeleteStorage(t *testing.T, called *bool) (*REST, *etcdtesting.EtcdTestServer) {
Expand Down
81 changes: 71 additions & 10 deletions pkg/storage/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,91 @@ limitations under the License.

package storage

import (
etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util"
import "fmt"

const (
ErrCodeKeyNotFound int = iota + 1
ErrCodeKeyExists
ErrCodeResourceVersionConflicts
ErrCodeUnreachable
)

var errCodeToMessage = map[int]string{
ErrCodeKeyNotFound: "key not found",
ErrCodeKeyExists: "key exists",
ErrCodeResourceVersionConflicts: "resource version conflicts",
ErrCodeUnreachable: "server unreachable",
}

func NewKeyNotFoundError(key string, rv int64) *StorageError {
return &StorageError{
Code: ErrCodeKeyNotFound,
Key: key,
ResourceVersion: rv,
}
}

func NewKeyExistsError(key string, rv int64) *StorageError {
return &StorageError{
Code: ErrCodeKeyExists,
Key: key,
ResourceVersion: rv,
}
}

func NewResourceVersionConflictsError(key string, rv int64) *StorageError {
return &StorageError{
Code: ErrCodeResourceVersionConflicts,
Key: key,
ResourceVersion: rv,
}
}

func NewUnreachableError(key string, rv int64) *StorageError {
return &StorageError{
Code: ErrCodeUnreachable,
Key: key,
ResourceVersion: rv,
}
}

type StorageError struct {
Code int
Key string
ResourceVersion int64
}

func (e *StorageError) Error() string {
return fmt.Sprintf("StorageError: %s, Code: %d, Key: %s, ResourceVersion: %d",
errCodeToMessage[e.Code], e.Code, e.Key, e.ResourceVersion)
}

// IsNotFound returns true if and only if err is "key" not found error.
func IsNotFound(err error) bool {
// TODO: add alternate storage error here
return etcdutil.IsEtcdNotFound(err)
return isErrCode(err, ErrCodeKeyNotFound)
}

// IsNodeExist returns true if and only if err is an node already exist error.
func IsNodeExist(err error) bool {
// TODO: add alternate storage error here
return etcdutil.IsEtcdNodeExist(err)
return isErrCode(err, ErrCodeKeyExists)
}

// IsUnreachable returns true if and only if err indicates the server could not be reached.
func IsUnreachable(err error) bool {
// TODO: add alternate storage error here
return etcdutil.IsEtcdUnreachable(err)
return isErrCode(err, ErrCodeUnreachable)
}

// IsTestFailed returns true if and only if err is a write conflict.
func IsTestFailed(err error) bool {
// TODO: add alternate storage error here
return etcdutil.IsEtcdTestFailed(err)
return isErrCode(err, ErrCodeResourceVersionConflicts)
}

func isErrCode(err error, code int) bool {
if err == nil {
return false
}
if e, ok := err.(*StorageError); ok {
return e.Code == code
}
return false
}
39 changes: 28 additions & 11 deletions pkg/storage/etcd/etcd_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ func (h *etcdHelper) Create(ctx context.Context, key string, obj, out runtime.Ob
metrics.RecordEtcdRequestLatency("create", getTypeName(obj), startTime)
trace.Step("Object created")
if err != nil {
return err
return toStorageErr(err, key, 0)
}
if out != nil {
if _, err := conversion.EnforcePtr(out); err != nil {
Expand Down Expand Up @@ -264,7 +264,7 @@ func (h *etcdHelper) Set(ctx context.Context, key string, obj, out runtime.Objec
response, err = h.etcdKeysAPI.Set(ctx, key, string(data), &opts)
metrics.RecordEtcdRequestLatency("compareAndSwap", getTypeName(obj), startTime)
if err != nil {
return err
return toStorageErr(err, key, int64(version))
}
}
if create {
Expand All @@ -276,7 +276,7 @@ func (h *etcdHelper) Set(ctx context.Context, key string, obj, out runtime.Objec
}
response, err = h.etcdKeysAPI.Set(ctx, key, string(data), &opts)
if err != nil {
return err
return toStorageErr(err, key, 0)
}
metrics.RecordEtcdRequestLatency("create", getTypeName(obj), startTime)
}
Expand Down Expand Up @@ -310,7 +310,7 @@ func (h *etcdHelper) Delete(ctx context.Context, key string, out runtime.Object)
_, _, err = h.extractObj(response, err, out, false, true)
}
}
return err
return toStorageErr(err, key, 0)
}

// Implements storage.Interface.
Expand Down Expand Up @@ -367,12 +367,11 @@ func (h *etcdHelper) bodyAndExtractObj(ctx context.Context, key string, objPtr r

response, err := h.etcdKeysAPI.Get(ctx, key, opts)
metrics.RecordEtcdRequestLatency("get", getTypeName(objPtr), startTime)

if err != nil && !etcdutil.IsEtcdNotFound(err) {
return "", nil, nil, err
return "", nil, nil, toStorageErr(err, key, 0)
}
body, node, err = h.extractObj(response, err, objPtr, ignoreNotFound, false)
return body, node, response, err
return body, node, response, toStorageErr(err, key, 0)
}

func (h *etcdHelper) extractObj(response *etcd.Response, inErr error, objPtr runtime.Object, ignoreNotFound, prevNode bool) (body string, node *etcd.Node, err error) {
Expand Down Expand Up @@ -434,7 +433,7 @@ func (h *etcdHelper) GetToList(ctx context.Context, key string, filter storage.F
if etcdutil.IsEtcdNotFound(err) {
return nil
}
return err
return toStorageErr(err, key, 0)
}

nodes := make([]*etcd.Node, 0)
Expand Down Expand Up @@ -541,7 +540,7 @@ func (h *etcdHelper) listEtcdNode(ctx context.Context, key string) ([]*etcd.Node
if etcdutil.IsEtcdNotFound(err) {
return nodes, index, nil
} else {
return nodes, index, err
return nodes, index, toStorageErr(err, key, 0)
}
}
return result.Node.Nodes, result.Index, nil
Expand Down Expand Up @@ -623,7 +622,7 @@ func (h *etcdHelper) GuaranteedUpdate(ctx context.Context, key string, ptrToType
continue
}
_, _, err = h.extractObj(response, err, ptrToType, false, false)
return err
return toStorageErr(err, key, 0)
}

if string(data) == origBody {
Expand All @@ -647,7 +646,7 @@ func (h *etcdHelper) GuaranteedUpdate(ctx context.Context, key string, ptrToType
continue
}
_, _, err = h.extractObj(response, err, ptrToType, false, false)
return err
return toStorageErr(err, key, int64(index))
}
}

Expand Down Expand Up @@ -712,3 +711,21 @@ func (h *etcdHelper) addToCache(index uint64, obj runtime.Object) {
metrics.ObserveNewEntry()
}
}

func toStorageErr(err error, key string, rv int64) error {
if err == nil {
return nil
}
switch {
case etcdutil.IsEtcdNotFound(err):
return storage.NewKeyNotFoundError(key, rv)
case etcdutil.IsEtcdNodeExist(err):
return storage.NewKeyExistsError(key, rv)
case etcdutil.IsEtcdTestFailed(err):
return storage.NewResourceVersionConflictsError(key, rv)
case etcdutil.IsEtcdUnreachable(err):
return storage.NewUnreachableError(key, rv)
default:
return err
}
}
3 changes: 1 addition & 2 deletions pkg/storage/etcd/etcd_helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import (
"k8s.io/kubernetes/pkg/storage"
"k8s.io/kubernetes/pkg/storage/etcd/etcdtest"
etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util"
storagetesting "k8s.io/kubernetes/pkg/storage/testing"
)

Expand Down Expand Up @@ -251,7 +250,7 @@ func TestGetNotFoundErr(t *testing.T) {

var got api.Pod
err := helper.Get(context.TODO(), boguskey, &got, false)
if !etcdutil.IsEtcdNotFound(err) {
if !storage.IsNotFound(err) {
t.Errorf("Unexpected reponse on key=%v, err=%v", key, err)
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/storage/etcd/etcd_watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ func etcdGetInitialWatchState(ctx context.Context, client etcd.KeysAPI, key stri
if err != nil {
if !etcdutil.IsEtcdNotFound(err) {
utilruntime.HandleError(fmt.Errorf("watch was unable to retrieve the current index for the provided key (%q): %v", key, err))
return resourceVersion, err
return resourceVersion, toStorageErr(err, key, 0)
}
if etcdError, ok := err.(etcd.Error); ok {
resourceVersion = etcdError.Index
Expand Down

0 comments on commit 2777cd7

Please sign in to comment.