Merge pull request #126875 from serathius/watchcache-test-indexers
Adding tests for using indexers in tests Kubernetes-commit: a0e5e244b3fcfc60d2bf2296c63a72e015f5884b
This commit is contained in:
commit
28f9eed685
|
@ -256,6 +256,12 @@ func TestListResourceVersionMatch(t *testing.T) {
|
|||
// TODO(#109831): Enable use of this test and run it.
|
||||
}
|
||||
|
||||
func TestNamespaceScopedList(t *testing.T) {
|
||||
ctx, cacher, terminate := testSetup(t, withSpecNodeNameIndexerFuncs)
|
||||
t.Cleanup(terminate)
|
||||
storagetesting.RunTestNamespaceScopedList(ctx, t, cacher)
|
||||
}
|
||||
|
||||
func TestGuaranteedUpdate(t *testing.T) {
|
||||
// TODO(#109831): Enable use of this test and run it.
|
||||
}
|
||||
|
|
|
@ -2943,3 +2943,149 @@ func forceRequestWatchProgressSupport(t *testing.T) {
|
|||
t.Fatalf("failed to wait for required %v storage feature to initialize", storage.RequestWatchProgress)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListIndexer(t *testing.T) {
|
||||
ctx, cacher, terminate := testSetup(t, withSpecNodeNameIndexerFuncs)
|
||||
t.Cleanup(terminate)
|
||||
tests := []struct {
|
||||
name string
|
||||
requestedNamespace string
|
||||
recursive bool
|
||||
fieldSelector fields.Selector
|
||||
indexFields []string
|
||||
expectIndex string
|
||||
}{
|
||||
{
|
||||
name: "request without namespace, without field selector",
|
||||
recursive: true,
|
||||
fieldSelector: fields.Everything(),
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with metadata.namespace",
|
||||
recursive: true,
|
||||
fieldSelector: fields.ParseSelectorOrDie("metadata.namespace=namespace"),
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with spec.nodename",
|
||||
recursive: true,
|
||||
fieldSelector: fields.ParseSelectorOrDie("spec.nodeName=node"),
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
expectIndex: "f:spec.nodeName",
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with spec.nodename to filter out",
|
||||
recursive: true,
|
||||
fieldSelector: fields.ParseSelectorOrDie("spec.nodeName!=node"),
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
},
|
||||
{
|
||||
name: "request with namespace, without field selector",
|
||||
requestedNamespace: "namespace",
|
||||
recursive: true,
|
||||
fieldSelector: fields.Everything(),
|
||||
},
|
||||
{
|
||||
name: "request with namespace, field selector with matched metadata.namespace",
|
||||
requestedNamespace: "namespace",
|
||||
recursive: true,
|
||||
fieldSelector: fields.ParseSelectorOrDie("metadata.namespace=namespace"),
|
||||
},
|
||||
{
|
||||
name: "request with namespace, field selector with non-matched metadata.namespace",
|
||||
requestedNamespace: "namespace",
|
||||
recursive: true,
|
||||
fieldSelector: fields.ParseSelectorOrDie("metadata.namespace=namespace"),
|
||||
},
|
||||
{
|
||||
name: "request with namespace, field selector with spec.nodename",
|
||||
requestedNamespace: "namespace",
|
||||
recursive: true,
|
||||
fieldSelector: fields.ParseSelectorOrDie("spec.nodeName=node"),
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
expectIndex: "f:spec.nodeName",
|
||||
},
|
||||
{
|
||||
name: "request with namespace, field selector with spec.nodename to filter out",
|
||||
requestedNamespace: "namespace",
|
||||
recursive: true,
|
||||
fieldSelector: fields.ParseSelectorOrDie("spec.nodeName!=node"),
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with metadata.name",
|
||||
recursive: true,
|
||||
fieldSelector: fields.ParseSelectorOrDie("metadata.name=name"),
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with metadata.name and metadata.namespace",
|
||||
recursive: true,
|
||||
fieldSelector: fields.SelectorFromSet(fields.Set{
|
||||
"metadata.name": "name",
|
||||
"metadata.namespace": "namespace",
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with metadata.name and spec.nodeName",
|
||||
recursive: true,
|
||||
fieldSelector: fields.SelectorFromSet(fields.Set{
|
||||
"metadata.name": "name",
|
||||
"spec.nodeName": "node",
|
||||
}),
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
expectIndex: "f:spec.nodeName",
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with metadata.name, and with spec.nodeName to filter out watch",
|
||||
recursive: true,
|
||||
fieldSelector: fields.AndSelectors(
|
||||
fields.ParseSelectorOrDie("spec.nodeName!=node"),
|
||||
fields.SelectorFromSet(fields.Set{"metadata.name": "name"}),
|
||||
),
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
},
|
||||
{
|
||||
name: "request with namespace, with field selector metadata.name",
|
||||
requestedNamespace: "namespace",
|
||||
fieldSelector: fields.ParseSelectorOrDie("metadata.name=name"),
|
||||
},
|
||||
{
|
||||
name: "request with namespace, with field selector metadata.name and metadata.namespace",
|
||||
requestedNamespace: "namespace",
|
||||
fieldSelector: fields.SelectorFromSet(fields.Set{
|
||||
"metadata.name": "name",
|
||||
"metadata.namespace": "namespace",
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "request with namespace, with field selector metadata.name, metadata.namespace and spec.nodename",
|
||||
requestedNamespace: "namespace",
|
||||
fieldSelector: fields.SelectorFromSet(fields.Set{
|
||||
"metadata.name": "name",
|
||||
"metadata.namespace": "namespace",
|
||||
"spec.nodeName": "node",
|
||||
}),
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
},
|
||||
{
|
||||
name: "request with namespace, with field selector metadata.name, metadata.namespace, and with spec.nodename to filter out",
|
||||
requestedNamespace: "namespace",
|
||||
fieldSelector: fields.AndSelectors(
|
||||
fields.ParseSelectorOrDie("spec.nodeName!=node"),
|
||||
fields.SelectorFromSet(fields.Set{"metadata.name": "name", "metadata.namespace": "namespace"}),
|
||||
),
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
pred := storagetesting.CreatePodPredicate(tt.fieldSelector, true, tt.indexFields)
|
||||
_, _, usedIndex, err := cacher.listItems(ctx, 0, "/pods/"+tt.requestedNamespace, pred, tt.recursive)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if usedIndex != tt.expectIndex {
|
||||
t.Errorf("Index doesn't match, expected: %q, got: %q", tt.expectIndex, usedIndex)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -285,6 +285,11 @@ func TestListContinuationWithFilter(t *testing.T) {
|
|||
storagetesting.RunTestListContinuationWithFilter(ctx, t, store, validation)
|
||||
}
|
||||
|
||||
func TestNamespaceScopedList(t *testing.T) {
|
||||
ctx, store, _ := testSetup(t)
|
||||
storagetesting.RunTestNamespaceScopedList(ctx, t, store)
|
||||
}
|
||||
|
||||
func compactStorage(etcdClient *clientv3.Client) storagetesting.Compaction {
|
||||
return func(ctx context.Context, t *testing.T, resourceVersion string) {
|
||||
versioner := storage.APIObjectVersioner{}
|
||||
|
|
|
@ -2761,3 +2761,403 @@ func RunTestListPaging(ctx context.Context, t *testing.T, store storage.Interfac
|
|||
t.Errorf("unexpected items: %#v", names)
|
||||
}
|
||||
}
|
||||
|
||||
func RunTestNamespaceScopedList(ctx context.Context, t *testing.T, store storage.Interface) {
|
||||
tests := []struct {
|
||||
name string
|
||||
requestedNamespace string
|
||||
recursive bool
|
||||
indexFields []string
|
||||
fieldSelector func(namespace string) fields.Selector
|
||||
inputPods func(namespace string) []example.Pod
|
||||
expectPods func(namespace string) []example.Pod
|
||||
}{
|
||||
{
|
||||
name: "request without namespace, without field selector",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector { return fields.Everything() },
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", "ns1"),
|
||||
*baseNamespacedPod("foo2", "ns2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", "ns1"),
|
||||
*baseNamespacedPod("foo2", "ns2"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with metadata.namespace",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector {
|
||||
return fields.SelectorFromSet(fields.Set{"metadata.namespace": namespace + "ns1"})
|
||||
},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo1", namespace+"ns2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with spec.nodename",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector {
|
||||
return fields.ParseSelectorOrDie("spec.nodeName=bar1")
|
||||
},
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns1", "bar1"),
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns2", "bar2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns1", "bar1"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with spec.nodename to filter out",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector { return fields.ParseSelectorOrDie("spec.nodeName!=bar1") },
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns1", "bar1"),
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns2", "bar2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns2", "bar2"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request with namespace, without field selector",
|
||||
requestedNamespace: "ns1",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector { return fields.Everything() },
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo1", namespace+"ns2"),
|
||||
*baseNamespacedPod("foo2", namespace+"ns1"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo2", namespace+"ns1"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request with namespace, field selector with matched metadata.namespace",
|
||||
requestedNamespace: "ns1",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector {
|
||||
return fields.SelectorFromSet(fields.Set{"metadata.namespace": namespace + "ns1"})
|
||||
},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo1", namespace+"ns2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request with namespace, field selector with non-matched metadata.namespace",
|
||||
requestedNamespace: "ns1",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector {
|
||||
return fields.SelectorFromSet(fields.Set{"metadata.namespace": namespace + "ns2"})
|
||||
},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo1", namespace+"ns2"),
|
||||
*baseNamespacedPodUpdated("foo2", namespace+"ns1"),
|
||||
*baseNamespacedPodUpdated("foo2", namespace+"ns2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod { return []example.Pod{} },
|
||||
},
|
||||
{
|
||||
name: "request with namespace, field selector with spec.nodename",
|
||||
requestedNamespace: "ns1",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector { return fields.ParseSelectorOrDie("spec.nodeName=bar2") },
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns1", "bar1"),
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns2", "bar2"),
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns1", "bar2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns1", "bar2"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request with namespace, field selector with spec.nodename to filter out",
|
||||
requestedNamespace: "ns2",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector { return fields.ParseSelectorOrDie("spec.nodeName!=bar1") },
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo1", namespace+"ns2"),
|
||||
*baseNamespacedPodAssigned("foo3", namespace+"ns2", "bar1"),
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns2", "bar2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns2"),
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns2", "bar2"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with metadata.name",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector { return fields.ParseSelectorOrDie("metadata.name=foo1") },
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo1", namespace+"ns2"),
|
||||
*baseNamespacedPod("foo2", namespace+"ns1"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo1", namespace+"ns2"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with metadata.name and metadata.namespace",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector {
|
||||
return fields.SelectorFromSet(fields.Set{
|
||||
"metadata.name": "foo1",
|
||||
"metadata.namespace": namespace + "ns1",
|
||||
})
|
||||
},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo2", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo1", namespace+"ns2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with metadata.name and spec.nodeName",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector {
|
||||
return fields.SelectorFromSet(fields.Set{
|
||||
"metadata.name": "foo1",
|
||||
"spec.nodeName": "bar1",
|
||||
})
|
||||
},
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns1", "bar1"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns1", "bar1"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request without namespace, field selector with metadata.name, and with spec.nodeName to filter out watch",
|
||||
recursive: true,
|
||||
fieldSelector: func(namespace string) fields.Selector {
|
||||
return fields.AndSelectors(
|
||||
fields.ParseSelectorOrDie("spec.nodeName!=bar1"),
|
||||
fields.SelectorFromSet(fields.Set{"metadata.name": "foo1"}),
|
||||
)
|
||||
},
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo2", namespace+"ns1"),
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns2", "bar1"),
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns2", "bar1"),
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns3", "bar2"),
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns3", "bar2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns3", "bar2"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request with namespace, with field selector metadata.name",
|
||||
requestedNamespace: "ns1",
|
||||
fieldSelector: func(namespace string) fields.Selector { return fields.ParseSelectorOrDie("metadata.name=foo1") },
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo2", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo1", namespace+"ns2"),
|
||||
*baseNamespacedPod("foo2", namespace+"ns2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request with namespace, with field selector metadata.name and metadata.namespace",
|
||||
requestedNamespace: "ns1",
|
||||
fieldSelector: func(namespace string) fields.Selector {
|
||||
return fields.SelectorFromSet(fields.Set{
|
||||
"metadata.name": "foo1",
|
||||
"metadata.namespace": namespace + "ns1",
|
||||
})
|
||||
},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo2", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo1", namespace+"ns2"),
|
||||
*baseNamespacedPod("foo2", namespace+"ns2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request with namespace, with field selector metadata.name, metadata.namespace and spec.nodename",
|
||||
requestedNamespace: "ns2",
|
||||
fieldSelector: func(namespace string) fields.Selector {
|
||||
return fields.SelectorFromSet(fields.Set{
|
||||
"metadata.name": "foo2",
|
||||
"metadata.namespace": namespace + "ns2",
|
||||
"spec.nodeName": "bar1",
|
||||
})
|
||||
},
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo2", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo1", namespace+"ns2"),
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns2", "bar1"),
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns3", "bar1"),
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns3", "bar1"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns2", "bar1"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "request with namespace, with field selector metadata.name, metadata.namespace, and with spec.nodename to filter out",
|
||||
requestedNamespace: "ns2",
|
||||
fieldSelector: func(namespace string) fields.Selector {
|
||||
return fields.AndSelectors(
|
||||
fields.ParseSelectorOrDie("spec.nodeName!=bar2"),
|
||||
fields.SelectorFromSet(fields.Set{"metadata.name": "foo1", "metadata.namespace": namespace + "ns2"}),
|
||||
)
|
||||
},
|
||||
indexFields: []string{"spec.nodeName"},
|
||||
inputPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPod("foo1", namespace+"ns1"),
|
||||
*baseNamespacedPod("foo2", namespace+"ns1"),
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns2", "bar1"),
|
||||
*baseNamespacedPodAssigned("foo2", namespace+"ns2", "bar2"),
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns3", "bar2"),
|
||||
}
|
||||
},
|
||||
expectPods: func(namespace string) []example.Pod {
|
||||
return []example.Pod{
|
||||
*baseNamespacedPodAssigned("foo1", namespace+"ns2", "bar1"),
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
podNames := map[string]struct{}{}
|
||||
namespace := fmt.Sprintf("t%d-", i)
|
||||
for _, pod := range tt.inputPods(namespace) {
|
||||
out := &example.Pod{}
|
||||
key := computePodKey(&pod)
|
||||
podNames[key] = struct{}{}
|
||||
err := store.Create(ctx, key, &pod, out, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("GuaranteedUpdate failed: %v", err)
|
||||
}
|
||||
}
|
||||
opts := storage.ListOptions{
|
||||
ResourceVersion: "",
|
||||
Predicate: CreatePodPredicate(tt.fieldSelector(namespace), true, tt.indexFields),
|
||||
Recursive: true,
|
||||
}
|
||||
listOut := &example.PodList{}
|
||||
path := "/pods/"
|
||||
if tt.requestedNamespace != "" {
|
||||
path += namespace + tt.requestedNamespace
|
||||
}
|
||||
if err := store.GetList(ctx, path, opts, listOut); err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
i := 0
|
||||
for _, pod := range listOut.Items {
|
||||
if _, found := podNames[computePodKey(&pod)]; !found {
|
||||
continue
|
||||
}
|
||||
pod.ResourceVersion = ""
|
||||
listOut.Items[i] = pod
|
||||
i++
|
||||
}
|
||||
listOut.Items = listOut.Items[:i]
|
||||
|
||||
expectNoDiff(t, "incorrect list pods", tt.expectPods(namespace), listOut.Items)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ import (
|
|||
"github.com/google/go-cmp/cmp"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
@ -389,3 +391,42 @@ func (s sortablePodList) Less(i, j int) bool {
|
|||
func (s sortablePodList) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func CreatePodPredicate(field fields.Selector, namespaceScoped bool, indexField []string) storage.SelectionPredicate {
|
||||
return storage.SelectionPredicate{
|
||||
Label: labels.Everything(),
|
||||
Field: field,
|
||||
GetAttrs: determinePodGetAttrFunc(namespaceScoped, indexField),
|
||||
IndexFields: indexField,
|
||||
}
|
||||
}
|
||||
|
||||
func determinePodGetAttrFunc(namespaceScoped bool, indexField []string) storage.AttrFunc {
|
||||
if indexField != nil {
|
||||
if namespaceScoped {
|
||||
return namespacedScopedNodeNameAttrFunc
|
||||
}
|
||||
return clusterScopedNodeNameAttrFunc
|
||||
}
|
||||
if namespaceScoped {
|
||||
return storage.DefaultNamespaceScopedAttr
|
||||
}
|
||||
return storage.DefaultClusterScopedAttr
|
||||
}
|
||||
|
||||
func namespacedScopedNodeNameAttrFunc(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
pod := obj.(*example.Pod)
|
||||
return nil, fields.Set{
|
||||
"spec.nodeName": pod.Spec.NodeName,
|
||||
"metadata.name": pod.ObjectMeta.Name,
|
||||
"metadata.namespace": pod.ObjectMeta.Namespace,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func clusterScopedNodeNameAttrFunc(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
pod := obj.(*example.Pod)
|
||||
return nil, fields.Set{
|
||||
"spec.nodeName": pod.Spec.NodeName,
|
||||
"metadata.name": pod.ObjectMeta.Name,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -674,7 +674,7 @@ func RunTestClusterScopedWatch(ctx context.Context, t *testing.T, store storage.
|
|||
watchKey += "/" + tt.requestedName
|
||||
}
|
||||
|
||||
predicate := createPodPredicate(tt.fieldSelector, false, tt.indexFields)
|
||||
predicate := CreatePodPredicate(tt.fieldSelector, false, tt.indexFields)
|
||||
|
||||
list := &example.PodList{}
|
||||
opts := storage.ListOptions{
|
||||
|
@ -988,7 +988,7 @@ func RunTestNamespaceScopedWatch(ctx context.Context, t *testing.T, store storag
|
|||
}
|
||||
}
|
||||
|
||||
predicate := createPodPredicate(tt.fieldSelector, true, tt.indexFields)
|
||||
predicate := CreatePodPredicate(tt.fieldSelector, true, tt.indexFields)
|
||||
|
||||
list := &example.PodList{}
|
||||
opts := storage.ListOptions{
|
||||
|
@ -1656,45 +1656,6 @@ type testWatchStruct struct {
|
|||
watchType watch.EventType
|
||||
}
|
||||
|
||||
func createPodPredicate(field fields.Selector, namespaceScoped bool, indexField []string) storage.SelectionPredicate {
|
||||
return storage.SelectionPredicate{
|
||||
Label: labels.Everything(),
|
||||
Field: field,
|
||||
GetAttrs: determinePodGetAttrFunc(namespaceScoped, indexField),
|
||||
IndexFields: indexField,
|
||||
}
|
||||
}
|
||||
|
||||
func determinePodGetAttrFunc(namespaceScoped bool, indexField []string) storage.AttrFunc {
|
||||
if indexField != nil {
|
||||
if namespaceScoped {
|
||||
return namespacedScopedNodeNameAttrFunc
|
||||
}
|
||||
return clusterScopedNodeNameAttrFunc
|
||||
}
|
||||
if namespaceScoped {
|
||||
return storage.DefaultNamespaceScopedAttr
|
||||
}
|
||||
return storage.DefaultClusterScopedAttr
|
||||
}
|
||||
|
||||
func namespacedScopedNodeNameAttrFunc(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
pod := obj.(*example.Pod)
|
||||
return nil, fields.Set{
|
||||
"spec.nodeName": pod.Spec.NodeName,
|
||||
"metadata.name": pod.ObjectMeta.Name,
|
||||
"metadata.namespace": pod.ObjectMeta.Namespace,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func clusterScopedNodeNameAttrFunc(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
pod := obj.(*example.Pod)
|
||||
return nil, fields.Set{
|
||||
"spec.nodeName": pod.Spec.NodeName,
|
||||
"metadata.name": pod.ObjectMeta.Name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func basePod(podName string) *example.Pod {
|
||||
return baseNamespacedPod(podName, "")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue