mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 17:30:00 +00:00
List objects in deterministic order
This commit is contained in:
parent
60eba74c14
commit
d30da9a812
@ -147,7 +147,7 @@ func etcdErrorIndex(err error) (uint64, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *EtcdHelper) listEtcdNode(key string) ([]*etcd.Node, uint64, error) {
|
func (h *EtcdHelper) listEtcdNode(key string) ([]*etcd.Node, uint64, error) {
|
||||||
result, err := h.Client.Get(key, false, true)
|
result, err := h.Client.Get(key, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
index, ok := etcdErrorIndex(err)
|
index, ok := etcdErrorIndex(err)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -30,11 +30,6 @@ import (
|
|||||||
"github.com/coreos/go-etcd/etcd"
|
"github.com/coreos/go-etcd/etcd"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fakeClientGetSet struct {
|
|
||||||
get func(key string, sort, recursive bool) (*etcd.Response, error)
|
|
||||||
set func(key, value string, ttl uint64) (*etcd.Response, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestResource struct {
|
type TestResource struct {
|
||||||
api.TypeMeta `json:",inline"`
|
api.TypeMeta `json:",inline"`
|
||||||
api.ObjectMeta `json:"metadata"`
|
api.ObjectMeta `json:"metadata"`
|
||||||
@ -72,17 +67,24 @@ func TestExtractToList(t *testing.T) {
|
|||||||
R: &etcd.Response{
|
R: &etcd.Response{
|
||||||
EtcdIndex: 10,
|
EtcdIndex: 10,
|
||||||
Node: &etcd.Node{
|
Node: &etcd.Node{
|
||||||
|
Dir: true,
|
||||||
Nodes: []*etcd.Node{
|
Nodes: []*etcd.Node{
|
||||||
{
|
{
|
||||||
|
Key: "/foo",
|
||||||
Value: `{"id":"foo","kind":"Pod","apiVersion":"v1beta1"}`,
|
Value: `{"id":"foo","kind":"Pod","apiVersion":"v1beta1"}`,
|
||||||
|
Dir: false,
|
||||||
ModifiedIndex: 1,
|
ModifiedIndex: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Key: "/bar",
|
||||||
Value: `{"id":"bar","kind":"Pod","apiVersion":"v1beta1"}`,
|
Value: `{"id":"bar","kind":"Pod","apiVersion":"v1beta1"}`,
|
||||||
|
Dir: false,
|
||||||
ModifiedIndex: 2,
|
ModifiedIndex: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Key: "/baz",
|
||||||
Value: `{"id":"baz","kind":"Pod","apiVersion":"v1beta1"}`,
|
Value: `{"id":"baz","kind":"Pod","apiVersion":"v1beta1"}`,
|
||||||
|
Dir: false,
|
||||||
ModifiedIndex: 3,
|
ModifiedIndex: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -92,9 +94,10 @@ func TestExtractToList(t *testing.T) {
|
|||||||
expect := api.PodList{
|
expect := api.PodList{
|
||||||
ListMeta: api.ListMeta{ResourceVersion: "10"},
|
ListMeta: api.ListMeta{ResourceVersion: "10"},
|
||||||
Items: []api.Pod{
|
Items: []api.Pod{
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}},
|
// We expect items to be sorted by its name.
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "2"}},
|
{ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "2"}},
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "baz", ResourceVersion: "3"}},
|
{ObjectMeta: api.ObjectMeta{Name: "baz", ResourceVersion: "3"}},
|
||||||
|
{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,22 +119,34 @@ func TestExtractToListAcrossDirectories(t *testing.T) {
|
|||||||
R: &etcd.Response{
|
R: &etcd.Response{
|
||||||
EtcdIndex: 10,
|
EtcdIndex: 10,
|
||||||
Node: &etcd.Node{
|
Node: &etcd.Node{
|
||||||
|
Dir: true,
|
||||||
Nodes: []*etcd.Node{
|
Nodes: []*etcd.Node{
|
||||||
{
|
{
|
||||||
|
Key: "/directory1",
|
||||||
Value: `{"name": "directory1"}`,
|
Value: `{"name": "directory1"}`,
|
||||||
Dir: true,
|
Dir: true,
|
||||||
Nodes: []*etcd.Node{
|
Nodes: []*etcd.Node{
|
||||||
{
|
{
|
||||||
|
Key: "/foo",
|
||||||
Value: `{"id":"foo","kind":"Pod","apiVersion":"v1beta1"}`,
|
Value: `{"id":"foo","kind":"Pod","apiVersion":"v1beta1"}`,
|
||||||
|
Dir: false,
|
||||||
|
ModifiedIndex: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "/baz",
|
||||||
|
Value: `{"id":"baz","kind":"Pod","apiVersion":"v1beta1"}`,
|
||||||
|
Dir: false,
|
||||||
ModifiedIndex: 1,
|
ModifiedIndex: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Key: "/directory2",
|
||||||
Value: `{"name": "directory2"}`,
|
Value: `{"name": "directory2"}`,
|
||||||
Dir: true,
|
Dir: true,
|
||||||
Nodes: []*etcd.Node{
|
Nodes: []*etcd.Node{
|
||||||
{
|
{
|
||||||
|
Key: "/bar",
|
||||||
Value: `{"id":"bar","kind":"Pod","apiVersion":"v1beta1"}`,
|
Value: `{"id":"bar","kind":"Pod","apiVersion":"v1beta1"}`,
|
||||||
ModifiedIndex: 2,
|
ModifiedIndex: 2,
|
||||||
},
|
},
|
||||||
@ -144,6 +159,8 @@ func TestExtractToListAcrossDirectories(t *testing.T) {
|
|||||||
expect := api.PodList{
|
expect := api.PodList{
|
||||||
ListMeta: api.ListMeta{ResourceVersion: "10"},
|
ListMeta: api.ListMeta{ResourceVersion: "10"},
|
||||||
Items: []api.Pod{
|
Items: []api.Pod{
|
||||||
|
// We expect list to be sorted by directory (e.g. namespace) first, then by name.
|
||||||
|
{ObjectMeta: api.ObjectMeta{Name: "baz", ResourceVersion: "1"}},
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}},
|
{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}},
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "2"}},
|
{ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "2"}},
|
||||||
},
|
},
|
||||||
@ -166,20 +183,25 @@ func TestExtractToListExcludesDirectories(t *testing.T) {
|
|||||||
R: &etcd.Response{
|
R: &etcd.Response{
|
||||||
EtcdIndex: 10,
|
EtcdIndex: 10,
|
||||||
Node: &etcd.Node{
|
Node: &etcd.Node{
|
||||||
|
Dir: true,
|
||||||
Nodes: []*etcd.Node{
|
Nodes: []*etcd.Node{
|
||||||
{
|
{
|
||||||
|
Key: "/foo",
|
||||||
Value: `{"id":"foo","kind":"Pod","apiVersion":"v1beta1"}`,
|
Value: `{"id":"foo","kind":"Pod","apiVersion":"v1beta1"}`,
|
||||||
ModifiedIndex: 1,
|
ModifiedIndex: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Key: "/bar",
|
||||||
Value: `{"id":"bar","kind":"Pod","apiVersion":"v1beta1"}`,
|
Value: `{"id":"bar","kind":"Pod","apiVersion":"v1beta1"}`,
|
||||||
ModifiedIndex: 2,
|
ModifiedIndex: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Key: "/baz",
|
||||||
Value: `{"id":"baz","kind":"Pod","apiVersion":"v1beta1"}`,
|
Value: `{"id":"baz","kind":"Pod","apiVersion":"v1beta1"}`,
|
||||||
ModifiedIndex: 3,
|
ModifiedIndex: 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Key: "/directory",
|
||||||
Value: `{"name": "directory"}`,
|
Value: `{"name": "directory"}`,
|
||||||
Dir: true,
|
Dir: true,
|
||||||
},
|
},
|
||||||
@ -190,9 +212,9 @@ func TestExtractToListExcludesDirectories(t *testing.T) {
|
|||||||
expect := api.PodList{
|
expect := api.PodList{
|
||||||
ListMeta: api.ListMeta{ResourceVersion: "10"},
|
ListMeta: api.ListMeta{ResourceVersion: "10"},
|
||||||
Items: []api.Pod{
|
Items: []api.Pod{
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}},
|
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "2"}},
|
{ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "2"}},
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "baz", ResourceVersion: "3"}},
|
{ObjectMeta: api.ObjectMeta{Name: "baz", ResourceVersion: "3"}},
|
||||||
|
{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ package tools
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/coreos/go-etcd/etcd"
|
"github.com/coreos/go-etcd/etcd"
|
||||||
@ -132,9 +133,23 @@ func (f *FakeEtcdClient) Get(key string, sort, recursive bool) (*etcd.Response,
|
|||||||
return &etcd.Response{}, EtcdErrorNotFound
|
return &etcd.Response{}, EtcdErrorNotFound
|
||||||
}
|
}
|
||||||
f.t.Logf("returning %v: %#v %#v", key, result.R, result.E)
|
f.t.Logf("returning %v: %#v %#v", key, result.R, result.E)
|
||||||
|
|
||||||
|
// Sort response, note this will alter resutl.R.
|
||||||
|
if result.R.Node != nil && result.R.Node.Nodes != nil && sort {
|
||||||
|
f.sortResponse(result.R.Node.Nodes)
|
||||||
|
}
|
||||||
return result.R, result.E
|
return result.R, result.E
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FakeEtcdClient) sortResponse(nodes etcd.Nodes) {
|
||||||
|
for i := range nodes {
|
||||||
|
if nodes[i].Dir {
|
||||||
|
f.sortResponse(nodes[i].Nodes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Sort(nodes)
|
||||||
|
}
|
||||||
|
|
||||||
func (f *FakeEtcdClient) nodeExists(key string) bool {
|
func (f *FakeEtcdClient) nodeExists(key string) bool {
|
||||||
result, ok := f.Data[key]
|
result, ok := f.Data[key]
|
||||||
return ok && result.R != nil && result.R.Node != nil && result.E == nil
|
return ok && result.R != nil && result.R.Node != nil && result.E == nil
|
||||||
|
Loading…
Reference in New Issue
Block a user