mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 22:17:14 +00:00
Fix incorrectly set resource version in List
This commit is contained in:
parent
a0036fcae1
commit
a3578c864e
@ -347,7 +347,10 @@ func (h *etcdHelper) GetToList(ctx context.Context, key string, resourceVersion
|
|||||||
metrics.RecordEtcdRequestLatency("get", getTypeName(listPtr), startTime)
|
metrics.RecordEtcdRequestLatency("get", getTypeName(listPtr), startTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if etcdutil.IsEtcdNotFound(err) {
|
if etcdutil.IsEtcdNotFound(err) {
|
||||||
return nil
|
if etcdErr, ok := err.(etcd.Error); ok {
|
||||||
|
return h.versioner.UpdateList(listObj, etcdErr.Index, "")
|
||||||
|
}
|
||||||
|
return fmt.Errorf("unexpected error from storage: %#v", err)
|
||||||
}
|
}
|
||||||
return toStorageErr(err, key, 0)
|
return toStorageErr(err, key, 0)
|
||||||
}
|
}
|
||||||
|
@ -329,6 +329,66 @@ func TestGet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetToList(t *testing.T) {
|
||||||
|
_, codecs := testScheme(t)
|
||||||
|
codec := apitesting.TestCodec(codecs, examplev1.SchemeGroupVersion)
|
||||||
|
server := etcdtesting.NewEtcdTestClientServer(t)
|
||||||
|
defer server.Terminate(t)
|
||||||
|
key := "/some/key"
|
||||||
|
helper := newEtcdHelper(server.Client, codec, etcdtest.PathPrefix())
|
||||||
|
|
||||||
|
storedObj := &example.Pod{}
|
||||||
|
if err := helper.Create(context.TODO(), key, &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, storedObj, 0); err != nil {
|
||||||
|
t.Errorf("Unexpected error %#v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
key string
|
||||||
|
pred storage.SelectionPredicate
|
||||||
|
expectedOut []*example.Pod
|
||||||
|
}{{ // test GetToList on existing key
|
||||||
|
key: key,
|
||||||
|
pred: storage.Everything,
|
||||||
|
expectedOut: []*example.Pod{storedObj},
|
||||||
|
}, { // test GetToList on non-existing key
|
||||||
|
key: "/non-existing",
|
||||||
|
pred: storage.Everything,
|
||||||
|
expectedOut: nil,
|
||||||
|
}, { // test GetToList with matching pod name
|
||||||
|
key: "/non-existing",
|
||||||
|
pred: storage.SelectionPredicate{
|
||||||
|
Label: labels.Everything(),
|
||||||
|
Field: fields.ParseSelectorOrDie("metadata.name!=" + storedObj.Name),
|
||||||
|
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||||
|
pod := obj.(*example.Pod)
|
||||||
|
return nil, fields.Set{"metadata.name": pod.Name}, pod.Initializers != nil, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedOut: nil,
|
||||||
|
}}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
out := &example.PodList{}
|
||||||
|
err := helper.GetToList(context.TODO(), tt.key, "", tt.pred, out)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetToList failed: %v", err)
|
||||||
|
}
|
||||||
|
if len(out.ResourceVersion) == 0 {
|
||||||
|
t.Errorf("#%d: unset resourceVersion", i)
|
||||||
|
}
|
||||||
|
if len(out.Items) != len(tt.expectedOut) {
|
||||||
|
t.Errorf("#%d: length of list want=%d, get=%d", i, len(tt.expectedOut), len(out.Items))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for j, wantPod := range tt.expectedOut {
|
||||||
|
getPod := &out.Items[j]
|
||||||
|
if !reflect.DeepEqual(wantPod, getPod) {
|
||||||
|
t.Errorf("#%d: pod want=%#v, get=%#v", i, wantPod, getPod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetNotFoundErr(t *testing.T) {
|
func TestGetNotFoundErr(t *testing.T) {
|
||||||
_, codecs := testScheme(t)
|
_, codecs := testScheme(t)
|
||||||
codec := apitesting.TestCodec(codecs, schema.GroupVersion{Version: "v1"})
|
codec := apitesting.TestCodec(codecs, schema.GroupVersion{Version: "v1"})
|
||||||
|
@ -388,26 +388,26 @@ func (s *store) GetToList(ctx context.Context, key string, resourceVersion strin
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
key = path.Join(s.pathPrefix, key)
|
|
||||||
|
|
||||||
getResp, err := s.client.KV.Get(ctx, key, s.getOps...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(getResp.Kvs) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data, _, err := s.transformer.TransformFromStorage(getResp.Kvs[0].Value, authenticatedDataString(key))
|
|
||||||
if err != nil {
|
|
||||||
return storage.NewInternalError(err.Error())
|
|
||||||
}
|
|
||||||
v, err := conversion.EnforcePtr(listPtr)
|
v, err := conversion.EnforcePtr(listPtr)
|
||||||
if err != nil || v.Kind() != reflect.Slice {
|
if err != nil || v.Kind() != reflect.Slice {
|
||||||
panic("need ptr to slice")
|
panic("need ptr to slice")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
key = path.Join(s.pathPrefix, key)
|
||||||
|
getResp, err := s.client.KV.Get(ctx, key, s.getOps...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(getResp.Kvs) > 0 {
|
||||||
|
data, _, err := s.transformer.TransformFromStorage(getResp.Kvs[0].Value, authenticatedDataString(key))
|
||||||
|
if err != nil {
|
||||||
|
return storage.NewInternalError(err.Error())
|
||||||
|
}
|
||||||
if err := appendListItem(v, data, uint64(getResp.Kvs[0].ModRevision), pred, s.codec, s.versioner); err != nil {
|
if err := appendListItem(v, data, uint64(getResp.Kvs[0].ModRevision), pred, s.codec, s.versioner); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// update version with cluster level revision
|
// update version with cluster level revision
|
||||||
return s.versioner.UpdateList(listObj, uint64(getResp.Header.Revision), "")
|
return s.versioner.UpdateList(listObj, uint64(getResp.Header.Revision), "")
|
||||||
}
|
}
|
||||||
|
@ -326,6 +326,9 @@ func TestGetToList(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("GetToList failed: %v", err)
|
t.Fatalf("GetToList failed: %v", err)
|
||||||
}
|
}
|
||||||
|
if len(out.ResourceVersion) == 0 {
|
||||||
|
t.Errorf("#%d: unset resourceVersion", i)
|
||||||
|
}
|
||||||
if len(out.Items) != len(tt.expectedOut) {
|
if len(out.Items) != len(tt.expectedOut) {
|
||||||
t.Errorf("#%d: length of list want=%d, get=%d", i, len(tt.expectedOut), len(out.Items))
|
t.Errorf("#%d: length of list want=%d, get=%d", i, len(tt.expectedOut), len(out.Items))
|
||||||
continue
|
continue
|
||||||
|
@ -166,6 +166,62 @@ func TestGet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetToList(t *testing.T) {
|
||||||
|
server, etcdStorage := newEtcdTestStorage(t, etcdtest.PathPrefix())
|
||||||
|
defer server.Terminate(t)
|
||||||
|
cacher, _ := newTestCacher(etcdStorage, 10)
|
||||||
|
defer cacher.Stop()
|
||||||
|
|
||||||
|
storedObj := updatePod(t, etcdStorage, makeTestPod("foo"), nil)
|
||||||
|
key := "pods/" + storedObj.Namespace + "/" + storedObj.Name
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
key string
|
||||||
|
pred storage.SelectionPredicate
|
||||||
|
expectedOut []*example.Pod
|
||||||
|
}{{ // test GetToList on existing key
|
||||||
|
key: key,
|
||||||
|
pred: storage.Everything,
|
||||||
|
expectedOut: []*example.Pod{storedObj},
|
||||||
|
}, { // test GetToList on non-existing key
|
||||||
|
key: "/non-existing",
|
||||||
|
pred: storage.Everything,
|
||||||
|
expectedOut: nil,
|
||||||
|
}, { // test GetToList with matching pod name
|
||||||
|
key: "/non-existing",
|
||||||
|
pred: storage.SelectionPredicate{
|
||||||
|
Label: labels.Everything(),
|
||||||
|
Field: fields.ParseSelectorOrDie("metadata.name!=" + storedObj.Name),
|
||||||
|
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||||
|
pod := obj.(*example.Pod)
|
||||||
|
return nil, fields.Set{"metadata.name": pod.Name}, pod.Initializers != nil, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedOut: nil,
|
||||||
|
}}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
out := &example.PodList{}
|
||||||
|
err := cacher.GetToList(context.TODO(), tt.key, "", tt.pred, out)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetToList failed: %v", err)
|
||||||
|
}
|
||||||
|
if len(out.ResourceVersion) == 0 {
|
||||||
|
t.Errorf("#%d: unset resourceVersion", i)
|
||||||
|
}
|
||||||
|
if len(out.Items) != len(tt.expectedOut) {
|
||||||
|
t.Errorf("#%d: length of list want=%d, get=%d", i, len(tt.expectedOut), len(out.Items))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for j, wantPod := range tt.expectedOut {
|
||||||
|
getPod := &out.Items[j]
|
||||||
|
if !reflect.DeepEqual(wantPod, getPod) {
|
||||||
|
t.Errorf("#%d: pod want=%#v, get=%#v", i, wantPod, getPod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestList(t *testing.T) {
|
func TestList(t *testing.T) {
|
||||||
server, etcdStorage := newEtcdTestStorage(t, etcdtest.PathPrefix())
|
server, etcdStorage := newEtcdTestStorage(t, etcdtest.PathPrefix())
|
||||||
defer server.Terminate(t)
|
defer server.Terminate(t)
|
||||||
|
Loading…
Reference in New Issue
Block a user