mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-31 08:36:16 +00:00
Extract list must flatten nodes across directories
This commit is contained in:
@@ -164,6 +164,12 @@ func (h *EtcdHelper) ExtractList(key string, slicePtr interface{}, resourceVersi
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.decodeNodeList(nodes, slicePtr)
|
||||
return nil
|
||||
}
|
||||
|
||||
// decodeNodeList walks the tree of each node in the list and decodes into the specified object
|
||||
func (h *EtcdHelper) decodeNodeList(nodes []*etcd.Node, slicePtr interface{}) error {
|
||||
pv := reflect.ValueOf(slicePtr)
|
||||
if pv.Type().Kind() != reflect.Ptr || pv.Type().Elem().Kind() != reflect.Slice {
|
||||
// This should not happen at runtime.
|
||||
@@ -171,16 +177,20 @@ func (h *EtcdHelper) ExtractList(key string, slicePtr interface{}, resourceVersi
|
||||
}
|
||||
v := pv.Elem()
|
||||
for _, node := range nodes {
|
||||
obj := reflect.New(v.Type().Elem())
|
||||
err = h.Codec.DecodeInto([]byte(node.Value), obj.Interface().(runtime.Object))
|
||||
if h.ResourceVersioner != nil {
|
||||
_ = h.ResourceVersioner.SetResourceVersion(obj.Interface().(runtime.Object), node.ModifiedIndex)
|
||||
// being unable to set the version does not prevent the object from being extracted
|
||||
if node.Dir {
|
||||
h.decodeNodeList(node.Nodes, slicePtr)
|
||||
} else {
|
||||
obj := reflect.New(v.Type().Elem())
|
||||
err := h.Codec.DecodeInto([]byte(node.Value), obj.Interface().(runtime.Object))
|
||||
if h.ResourceVersioner != nil {
|
||||
_ = h.ResourceVersioner.SetResourceVersion(obj.Interface().(runtime.Object), node.ModifiedIndex)
|
||||
// being unable to set the version does not prevent the object from being extracted
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.Set(reflect.Append(v, obj.Elem()))
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.Set(reflect.Append(v, obj.Elem()))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -108,6 +108,104 @@ func TestExtractToList(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestExtractToListAcrossDirectories ensures that the client excludes directories and flattens tree-response - simulates cross-namespace query
|
||||
func TestExtractToListAcrossDirectories(t *testing.T) {
|
||||
fakeClient := NewFakeEtcdClient(t)
|
||||
fakeClient.Data["/some/key"] = EtcdResponseWithError{
|
||||
R: &etcd.Response{
|
||||
EtcdIndex: 10,
|
||||
Node: &etcd.Node{
|
||||
Nodes: []*etcd.Node{
|
||||
{
|
||||
Value: `{"id": "directory1"}`,
|
||||
Dir: true,
|
||||
Nodes: []*etcd.Node{
|
||||
{
|
||||
Value: `{"id":"foo"}`,
|
||||
ModifiedIndex: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Value: `{"id": "directory2"}`,
|
||||
Dir: true,
|
||||
Nodes: []*etcd.Node{
|
||||
{
|
||||
Value: `{"id":"bar"}`,
|
||||
ModifiedIndex: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
expect := api.PodList{
|
||||
JSONBase: api.JSONBase{ResourceVersion: 10},
|
||||
Items: []api.Pod{
|
||||
{JSONBase: api.JSONBase{ID: "foo", ResourceVersion: 1}},
|
||||
{JSONBase: api.JSONBase{ID: "bar", ResourceVersion: 2}},
|
||||
},
|
||||
}
|
||||
|
||||
var got api.PodList
|
||||
helper := EtcdHelper{fakeClient, latest.Codec, versioner}
|
||||
err := helper.ExtractToList("/some/key", &got)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error %v", err)
|
||||
}
|
||||
if e, a := expect, got; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("Expected %#v, got %#v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractToListExcludesDirectories(t *testing.T) {
|
||||
fakeClient := NewFakeEtcdClient(t)
|
||||
fakeClient.Data["/some/key"] = EtcdResponseWithError{
|
||||
R: &etcd.Response{
|
||||
EtcdIndex: 10,
|
||||
Node: &etcd.Node{
|
||||
Nodes: []*etcd.Node{
|
||||
{
|
||||
Value: `{"id":"foo"}`,
|
||||
ModifiedIndex: 1,
|
||||
},
|
||||
{
|
||||
Value: `{"id":"bar"}`,
|
||||
ModifiedIndex: 2,
|
||||
},
|
||||
{
|
||||
Value: `{"id":"baz"}`,
|
||||
ModifiedIndex: 3,
|
||||
},
|
||||
{
|
||||
Value: `{"id": "directory"}`,
|
||||
Dir: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
expect := api.PodList{
|
||||
JSONBase: api.JSONBase{ResourceVersion: 10},
|
||||
Items: []api.Pod{
|
||||
{JSONBase: api.JSONBase{ID: "foo", ResourceVersion: 1}},
|
||||
{JSONBase: api.JSONBase{ID: "bar", ResourceVersion: 2}},
|
||||
{JSONBase: api.JSONBase{ID: "baz", ResourceVersion: 3}},
|
||||
},
|
||||
}
|
||||
|
||||
var got api.PodList
|
||||
helper := EtcdHelper{fakeClient, latest.Codec, versioner}
|
||||
err := helper.ExtractToList("/some/key", &got)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error %v", err)
|
||||
}
|
||||
if e, a := expect, got; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("Expected %#v, got %#v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractObj(t *testing.T) {
|
||||
fakeClient := NewFakeEtcdClient(t)
|
||||
expect := api.Pod{TypeMeta: api.TypeMeta{ID: "foo"}}
|
||||
|
Reference in New Issue
Block a user