Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Commit 189ce6e

Browse files
committed
storage: add custom storage error
1 parent 4b1b291 commit 189ce6e

File tree

5 files changed

+102
-26
lines changed

5 files changed

+102
-26
lines changed

pkg/registry/pod/etcd/etcd_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"strings"
2121
"testing"
2222

23-
etcd "github.com/coreos/etcd/client"
2423
"golang.org/x/net/context"
2524
"k8s.io/kubernetes/pkg/api"
2625
"k8s.io/kubernetes/pkg/api/errors"
@@ -140,7 +139,7 @@ type FailDeletionStorage struct {
140139

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

146145
func newFailDeleteStorage(t *testing.T, called *bool) (*REST, *etcdtesting.EtcdTestServer) {

pkg/storage/errors.go

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,91 @@ limitations under the License.
1616

1717
package storage
1818

19-
import (
20-
etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util"
19+
import "fmt"
20+
21+
const (
22+
ErrCodeKeyNotFound int = iota + 1
23+
ErrCodeKeyExists
24+
ErrCodeResourceVersionConflicts
25+
ErrCodeUnreachable
2126
)
2227

28+
var errCodeToMessage = map[int]string{
29+
ErrCodeKeyNotFound: "key not found",
30+
ErrCodeKeyExists: "key exists",
31+
ErrCodeResourceVersionConflicts: "resource version conflicts",
32+
ErrCodeUnreachable: "server unreachable",
33+
}
34+
35+
func NewKeyNotFoundError(key string, rv int64) *StorageError {
36+
return &StorageError{
37+
Code: ErrCodeKeyNotFound,
38+
Key: key,
39+
ResourceVersion: rv,
40+
}
41+
}
42+
43+
func NewKeyExistsError(key string, rv int64) *StorageError {
44+
return &StorageError{
45+
Code: ErrCodeKeyExists,
46+
Key: key,
47+
ResourceVersion: rv,
48+
}
49+
}
50+
51+
func NewResourceVersionConflictsError(key string, rv int64) *StorageError {
52+
return &StorageError{
53+
Code: ErrCodeResourceVersionConflicts,
54+
Key: key,
55+
ResourceVersion: rv,
56+
}
57+
}
58+
59+
func NewUnreachableError(key string, rv int64) *StorageError {
60+
return &StorageError{
61+
Code: ErrCodeUnreachable,
62+
Key: key,
63+
ResourceVersion: rv,
64+
}
65+
}
66+
67+
type StorageError struct {
68+
Code int
69+
Key string
70+
ResourceVersion int64
71+
}
72+
73+
func (e *StorageError) Error() string {
74+
return fmt.Sprintf("StorageError: %s, Code: %d, Key: %s, ResourceVersion: %d",
75+
errCodeToMessage[e.Code], e.Code, e.Key, e.ResourceVersion)
76+
}
77+
2378
// IsNotFound returns true if and only if err is "key" not found error.
2479
func IsNotFound(err error) bool {
25-
// TODO: add alternate storage error here
26-
return etcdutil.IsEtcdNotFound(err)
80+
return isErrCode(err, ErrCodeKeyNotFound)
2781
}
2882

2983
// IsNodeExist returns true if and only if err is an node already exist error.
3084
func IsNodeExist(err error) bool {
31-
// TODO: add alternate storage error here
32-
return etcdutil.IsEtcdNodeExist(err)
85+
return isErrCode(err, ErrCodeKeyExists)
3386
}
3487

3588
// IsUnreachable returns true if and only if err indicates the server could not be reached.
3689
func IsUnreachable(err error) bool {
37-
// TODO: add alternate storage error here
38-
return etcdutil.IsEtcdUnreachable(err)
90+
return isErrCode(err, ErrCodeUnreachable)
3991
}
4092

4193
// IsTestFailed returns true if and only if err is a write conflict.
4294
func IsTestFailed(err error) bool {
43-
// TODO: add alternate storage error here
44-
return etcdutil.IsEtcdTestFailed(err)
95+
return isErrCode(err, ErrCodeResourceVersionConflicts)
96+
}
97+
98+
func isErrCode(err error, code int) bool {
99+
if err == nil {
100+
return false
101+
}
102+
if e, ok := err.(*StorageError); ok {
103+
return e.Code == code
104+
}
105+
return false
45106
}

pkg/storage/etcd/etcd_helper.go

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ func (h *etcdHelper) Create(ctx context.Context, key string, obj, out runtime.Ob
216216
metrics.RecordEtcdRequestLatency("create", getTypeName(obj), startTime)
217217
trace.Step("Object created")
218218
if err != nil {
219-
return err
219+
return toStorageErr(err, key, 0)
220220
}
221221
if out != nil {
222222
if _, err := conversion.EnforcePtr(out); err != nil {
@@ -263,7 +263,7 @@ func (h *etcdHelper) Set(ctx context.Context, key string, obj, out runtime.Objec
263263
response, err = h.etcdKeysAPI.Set(ctx, key, string(data), &opts)
264264
metrics.RecordEtcdRequestLatency("compareAndSwap", getTypeName(obj), startTime)
265265
if err != nil {
266-
return err
266+
return toStorageErr(err, key, int64(version))
267267
}
268268
}
269269
if create {
@@ -275,7 +275,7 @@ func (h *etcdHelper) Set(ctx context.Context, key string, obj, out runtime.Objec
275275
}
276276
response, err = h.etcdKeysAPI.Set(ctx, key, string(data), &opts)
277277
if err != nil {
278-
return err
278+
return toStorageErr(err, key, 0)
279279
}
280280
metrics.RecordEtcdRequestLatency("create", getTypeName(obj), startTime)
281281
}
@@ -309,7 +309,7 @@ func (h *etcdHelper) Delete(ctx context.Context, key string, out runtime.Object)
309309
_, _, err = h.extractObj(response, err, out, false, true)
310310
}
311311
}
312-
return err
312+
return toStorageErr(err, key, 0)
313313
}
314314

315315
// Implements storage.Interface.
@@ -366,12 +366,11 @@ func (h *etcdHelper) bodyAndExtractObj(ctx context.Context, key string, objPtr r
366366

367367
response, err := h.etcdKeysAPI.Get(ctx, key, opts)
368368
metrics.RecordEtcdRequestLatency("get", getTypeName(objPtr), startTime)
369-
370369
if err != nil && !etcdutil.IsEtcdNotFound(err) {
371-
return "", nil, nil, err
370+
return "", nil, nil, toStorageErr(err, key, 0)
372371
}
373372
body, node, err = h.extractObj(response, err, objPtr, ignoreNotFound, false)
374-
return body, node, response, err
373+
return body, node, response, toStorageErr(err, key, 0)
375374
}
376375

377376
func (h *etcdHelper) extractObj(response *etcd.Response, inErr error, objPtr runtime.Object, ignoreNotFound, prevNode bool) (body string, node *etcd.Node, err error) {
@@ -433,7 +432,7 @@ func (h *etcdHelper) GetToList(ctx context.Context, key string, filter storage.F
433432
if etcdutil.IsEtcdNotFound(err) {
434433
return nil
435434
}
436-
return err
435+
return toStorageErr(err, key, 0)
437436
}
438437

439438
nodes := make([]*etcd.Node, 0)
@@ -540,7 +539,7 @@ func (h *etcdHelper) listEtcdNode(ctx context.Context, key string) ([]*etcd.Node
540539
if etcdutil.IsEtcdNotFound(err) {
541540
return nodes, index, nil
542541
} else {
543-
return nodes, index, err
542+
return nodes, index, toStorageErr(err, key, 0)
544543
}
545544
}
546545
return result.Node.Nodes, result.Index, nil
@@ -622,7 +621,7 @@ func (h *etcdHelper) GuaranteedUpdate(ctx context.Context, key string, ptrToType
622621
continue
623622
}
624623
_, _, err = h.extractObj(response, err, ptrToType, false, false)
625-
return err
624+
return toStorageErr(err, key, 0)
626625
}
627626

628627
if string(data) == origBody {
@@ -646,7 +645,7 @@ func (h *etcdHelper) GuaranteedUpdate(ctx context.Context, key string, ptrToType
646645
continue
647646
}
648647
_, _, err = h.extractObj(response, err, ptrToType, false, false)
649-
return err
648+
return toStorageErr(err, key, int64(index))
650649
}
651650
}
652651

@@ -711,3 +710,21 @@ func (h *etcdHelper) addToCache(index uint64, obj runtime.Object) {
711710
metrics.ObserveNewEntry()
712711
}
713712
}
713+
714+
func toStorageErr(err error, key string, rv int64) error {
715+
if err == nil {
716+
return nil
717+
}
718+
switch {
719+
case etcdutil.IsEtcdNotFound(err):
720+
return storage.NewKeyNotFoundError(key, rv)
721+
case etcdutil.IsEtcdNodeExist(err):
722+
return storage.NewKeyExistsError(key, rv)
723+
case etcdutil.IsEtcdTestFailed(err):
724+
return storage.NewResourceVersionConflictsError(key, rv)
725+
case etcdutil.IsEtcdUnreachable(err):
726+
return storage.NewUnreachableError(key, rv)
727+
default:
728+
return err
729+
}
730+
}

pkg/storage/etcd/etcd_helper_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import (
3535
"k8s.io/kubernetes/pkg/storage"
3636
"k8s.io/kubernetes/pkg/storage/etcd/etcdtest"
3737
etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
38-
etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util"
3938
storagetesting "k8s.io/kubernetes/pkg/storage/testing"
4039
)
4140

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

252251
var got api.Pod
253252
err := helper.Get(context.TODO(), boguskey, &got, false)
254-
if !etcdutil.IsEtcdNotFound(err) {
253+
if !storage.IsNotFound(err) {
255254
t.Errorf("Unexpected reponse on key=%v, err=%v", key, err)
256255
}
257256
}

pkg/storage/etcd/etcd_watcher.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ func etcdGetInitialWatchState(ctx context.Context, client etcd.KeysAPI, key stri
221221
if err != nil {
222222
if !etcdutil.IsEtcdNotFound(err) {
223223
utilruntime.HandleError(fmt.Errorf("watch was unable to retrieve the current index for the provided key (%q): %v", key, err))
224-
return resourceVersion, err
224+
return resourceVersion, toStorageErr(err, key, 0)
225225
}
226226
if etcdError, ok := err.(etcd.Error); ok {
227227
resourceVersion = etcdError.Index

0 commit comments

Comments
 (0)