pkg/k8score/dynamic_cache_bounded_test.go
Rama main · réplica de lectura del repositorio original.
package k8score
import (
"fmt"
"testing"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/tools/cache"
)
type namespaceReadInformer struct {
cache.SharedIndexInformer
indexer cache.Indexer
synced bool
}
func (i namespaceReadInformer) GetIndexer() cache.Indexer { return i.indexer }
func (i namespaceReadInformer) HasSynced() bool { return i.synced }
type namespaceOnlyIndexer struct {
cache.Indexer
namespaces []string
}
func (i *namespaceOnlyIndexer) List() []any {
panic("bounded namespace read must not materialize global cache")
}
func (i *namespaceOnlyIndexer) ByIndex(index, value string) ([]any, error) {
if index != cache.NamespaceIndex {
panic("expected namespace index")
}
i.namespaces = append(i.namespaces, value)
return i.Indexer.ByIndex(index, value)
}
func TestListWatchedNamespaceReadOnlyScopesBeforeLimiting(t *testing.T) {
gvr := schema.GroupVersionResource{Group: "example.com", Version: "v1", Resource: "widgets"}
idx := &namespaceOnlyIndexer{Indexer: cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})}
seed := func(ns, name string) {
t.Helper()
u := &unstructured.Unstructured{Object: map[string]any{"apiVersion": "example.com/v1", "kind": "Widget", "metadata": map[string]any{"namespace": ns, "name": name}}}
if err := idx.Add(u); err != nil {
t.Fatal(err)
}
}
for n := 0; n < 2000; n++ {
seed("foreign", fmt.Sprintf("x%d", n))
}
seed("target", "one")
d := &DynamicResourceCache{informers: map[informerKey]*informerEntry{{gvr: gvr}: {informer: namespaceReadInformer{indexer: idx, synced: true}}}}
got, truncated, err := d.ListWatchedNamespaceReadOnly(gvr, "target", 500)
if err != nil || truncated || len(got) != 1 || got[0].GetNamespace() != "target" {
t.Fatalf("foreign cache affected result: %v %v %v", got, truncated, err)
}
for n := 0; n < 600; n++ {
seed("target", fmt.Sprintf("x%d", n))
}
got, truncated, err = d.ListWatchedNamespaceReadOnly(gvr, "target", 500)
if err != nil || !truncated || len(got) != 0 {
t.Fatalf("candidate limit lost: %d %v %v", len(got), truncated, err)
}
again, againTruncated, againErr := d.ListWatchedNamespaceReadOnly(gvr, "target", 500)
if againErr != nil || !againTruncated || len(again) != 0 {
t.Fatal("large namespace produced unstable sample")
}
for _, ns := range idx.namespaces {
if ns != "target" {
t.Fatalf("read unrelated namespace %q", ns)
}
}
if _, _, err = d.ListWatchedNamespaceReadOnly(gvr, "", 500); err == nil {
t.Fatal("unscoped read accepted")
}
if _, _, err = d.ListWatchedNamespaceReadOnly(gvr, "target", 0); err == nil {
t.Fatal("unbounded read accepted")
}
if len(d.informers) != 1 {
t.Fatal("read started informer")
}
}
func TestListWatchedNamespaceReadOnlyDoesNotStartOrUseUnsyncedWatch(t *testing.T) {
gvr := schema.GroupVersionResource{Group: "example.com", Version: "v1", Resource: "widgets"}
d := &DynamicResourceCache{informers: map[informerKey]*informerEntry{}}
if _, _, err := d.ListWatchedNamespaceReadOnly(gvr, "target", 5); err == nil {
t.Fatal("missing watch accepted")
}
if len(d.informers) != 0 {
t.Fatal("watch created")
}
d.informers[informerKey{gvr: gvr, ns: "target"}] = &informerEntry{informer: namespaceReadInformer{synced: false}}
if _, _, err := d.ListWatchedNamespaceReadOnly(gvr, "target", 5); err == nil {
t.Fatal("unsynced watch accepted")
}
}
func TestListWatchedNamespaceReadOnlyRejectsStoppedCache(t *testing.T) {
gvr := schema.GroupVersionResource{Group: "example.com", Version: "v1", Resource: "widgets"}
idx := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
d := &DynamicResourceCache{stopped: true, informers: map[informerKey]*informerEntry{{gvr: gvr}: {informer: namespaceReadInformer{indexer: idx, synced: true}}}}
if rows, truncated, err := d.ListWatchedNamespaceReadOnly(gvr, "target", 500); err == nil || rows != nil || truncated {
t.Fatalf("stopped cache returned evidence: rows=%v truncated=%v err=%v", rows, truncated, err)
}
}