Skip to content

Commit 607a854

Browse files
authored
Merge pull request #52 from sttts/sttts-cluster-less-informer
🐛 UPSTREAM: <carry>: only call cluster-aware keyFunc for cluster-aware cache
2 parents 2605363 + 7ec6b61 commit 607a854

File tree

3 files changed

+105
-54
lines changed

3 files changed

+105
-54
lines changed

Diff for: pkg/cache/cache.go

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"fmt"
2222
"net/http"
23+
"strings"
2324
"time"
2425

2526
"golang.org/x/exp/maps"
@@ -390,6 +391,7 @@ func newCache(restConfig *rest.Config, opts Options) newCacheFunc {
390391
NewInformer: opts.NewInformerFunc,
391392
}),
392393
readerFailOnMissingInformer: opts.ReaderFailOnMissingInformer,
394+
clusterIndexes: strings.HasSuffix(restConfig.Host, "/clusters/*"),
393395
}
394396
}
395397
}

Diff for: pkg/cache/informer_cache.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ type informerCache struct {
7070
scheme *runtime.Scheme
7171
*internal.Informers
7272
readerFailOnMissingInformer bool
73+
clusterIndexes bool
7374
}
7475

7576
// Get implements Reader.
@@ -219,10 +220,10 @@ func (ic *informerCache) IndexField(ctx context.Context, obj client.Object, fiel
219220
if err != nil {
220221
return err
221222
}
222-
return indexByField(informer, field, extractValue)
223+
return indexByField(informer, field, extractValue, ic.clusterIndexes)
223224
}
224225

225-
func indexByField(informer Informer, field string, extractValue client.IndexerFunc) error {
226+
func indexByField(informer Informer, field string, extractValue client.IndexerFunc, clusterIndexes bool) error {
226227
indexFunc := func(objRaw interface{}) ([]string, error) {
227228
// TODO(directxman12): check if this is the correct type?
228229
obj, isObj := objRaw.(client.Object)
@@ -236,7 +237,7 @@ func indexByField(informer Informer, field string, extractValue client.IndexerFu
236237
ns := meta.GetNamespace()
237238

238239
keyFunc := internal.KeyToNamespacedKey
239-
if clusterName := logicalcluster.From(obj); !clusterName.Empty() {
240+
if clusterName := logicalcluster.From(obj); clusterIndexes && !clusterName.Empty() {
240241
keyFunc = func(ns, val string) string {
241242
return internal.KeyToClusteredKey(clusterName.String(), ns, val)
242243
}

Diff for: pkg/cache/kcp_test.go

+99-51
Original file line numberDiff line numberDiff line change
@@ -22,69 +22,117 @@ import (
2222
. "github.com/onsi/ginkgo/v2"
2323
. "github.com/onsi/gomega"
2424
corev1 "k8s.io/api/core/v1"
25+
"k8s.io/apimachinery/pkg/fields"
2526
"sigs.k8s.io/controller-runtime/pkg/cache"
2627
"sigs.k8s.io/controller-runtime/pkg/client"
2728
)
2829

29-
var _ = Describe("KCP cluster-unaware informer cache", func() {
30-
// Test whether we can have a cluster-unaware informer cache against a single workspace.
31-
// I.e. every object has a kcp.io/cluster annotation, but it should not be taken
32-
// into consideration by the cache to compute the key.
33-
It("should be able to get the default namespace despite kcp.io/cluster annotation", func() {
34-
ctx, cancel := context.WithCancel(context.Background())
35-
defer cancel()
36-
37-
c, err := cache.New(cfg, cache.Options{})
38-
Expect(err).NotTo(HaveOccurred())
39-
30+
var _ = Describe("informer cache against a kube cluster", func() {
31+
BeforeEach(func() {
4032
By("Annotating the default namespace with kcp.io/cluster")
4133
cl, err := client.New(cfg, client.Options{})
4234
Expect(err).NotTo(HaveOccurred())
4335
ns := &corev1.Namespace{}
44-
err = cl.Get(ctx, client.ObjectKey{Name: "default"}, ns)
36+
err = cl.Get(context.Background(), client.ObjectKey{Name: "default"}, ns)
4537
Expect(err).NotTo(HaveOccurred())
4638
ns.Annotations = map[string]string{"kcp.io/cluster": "cluster1"}
47-
err = cl.Update(ctx, ns)
48-
Expect(err).NotTo(HaveOccurred())
49-
50-
go c.Start(ctx) //nolint:errcheck // Start is blocking, and error not relevant here.
51-
c.WaitForCacheSync(ctx)
52-
53-
By("By getting the default namespace with the informer")
54-
err = c.Get(ctx, client.ObjectKey{Name: "default"}, ns)
39+
err = cl.Update(context.Background(), ns)
5540
Expect(err).NotTo(HaveOccurred())
5641
})
57-
})
58-
59-
// TODO: get envtest in place with kcp
60-
/*
61-
var _ = Describe("KCP cluster-aware informer cache", func() {
62-
It("should be able to get the default namespace with kcp.io/cluster annotation", func() {
63-
ctx, cancel := context.WithCancel(context.Background())
64-
defer cancel()
6542

66-
c, err := kcp.NewClusterAwareCache(cfg, cache.Options{})
67-
Expect(err).NotTo(HaveOccurred())
68-
69-
By("Annotating the default namespace with kcp.io/cluster")
70-
cl, err := client.New(cfg, client.Options{})
71-
Expect(err).NotTo(HaveOccurred())
72-
ns := &corev1.Namespace{}
73-
err = cl.Get(ctx, client.ObjectKey{Name: "default"}, ns)
74-
Expect(err).NotTo(HaveOccurred())
75-
ns.Annotations = map[string]string{"kcp.io/cluster": "cluster1"}
76-
err = cl.Update(ctx, ns)
77-
Expect(err).NotTo(HaveOccurred())
78-
79-
go c.Start(ctx) //nolint:errcheck // Start is blocking, and error not relevant here.
80-
c.WaitForCacheSync(ctx)
81-
82-
By("By getting the default namespace with the informer, but cluster-less key should fail")
83-
err = c.Get(ctx, client.ObjectKey{Name: "default"}, ns)
84-
Expect(err).To(HaveOccurred())
85-
86-
By("By getting the default namespace with the informer, but cluster-aware key should succeed")
87-
err = c.Get(kontext.WithCluster(ctx, "cluster1"), client.ObjectKey{Name: "default", Namespace: "cluster1"}, ns)
43+
Describe("KCP cluster-unaware informer cache", func() {
44+
// Test whether we can have a cluster-unaware informer cache against a single workspace.
45+
// I.e. every object has a kcp.io/cluster annotation, but it should not be taken
46+
// into consideration by the cache to compute the key.
47+
It("should be able to get the default namespace despite kcp.io/cluster annotation", func() {
48+
ctx, cancel := context.WithCancel(context.Background())
49+
defer cancel()
50+
51+
c, err := cache.New(cfg, cache.Options{})
52+
Expect(err).NotTo(HaveOccurred())
53+
54+
go c.Start(ctx) //nolint:errcheck // Start is blocking, and error not relevant here.
55+
c.WaitForCacheSync(ctx)
56+
57+
By("By getting the default namespace with the informer")
58+
ns := &corev1.Namespace{}
59+
err = c.Get(ctx, client.ObjectKey{Name: "default"}, ns)
60+
Expect(err).NotTo(HaveOccurred())
61+
})
62+
63+
It("should support indexes with cluster-less keys", func() {
64+
ctx, cancel := context.WithCancel(context.Background())
65+
defer cancel()
66+
67+
c, err := cache.New(cfg, cache.Options{})
68+
Expect(err).NotTo(HaveOccurred())
69+
70+
By("Indexing the default namespace by name")
71+
err = c.IndexField(ctx, &corev1.Namespace{}, "name-clusterless", func(obj client.Object) []string {
72+
return []string{"key-" + obj.GetName()}
73+
})
74+
Expect(err).NotTo(HaveOccurred())
75+
76+
go c.Start(ctx) //nolint:errcheck // Start is blocking, and error not relevant here.
77+
c.WaitForCacheSync(ctx)
78+
79+
By("By getting the default namespace via the custom index")
80+
nss := &corev1.NamespaceList{}
81+
err = c.List(ctx, nss, client.MatchingFieldsSelector{
82+
Selector: fields.OneTermEqualSelector("name-clusterless", "key-default"),
83+
})
84+
Expect(err).NotTo(HaveOccurred())
85+
Expect(nss.Items).To(HaveLen(1))
86+
})
8887
})
88+
89+
// TODO: get envtest in place with kcp
90+
/*
91+
Describe("KCP cluster-aware informer cache", func() {
92+
It("should be able to get the default namespace with kcp.io/cluster annotation", func() {
93+
ctx, cancel := context.WithCancel(context.Background())
94+
defer cancel()
95+
96+
c, err := kcp.NewClusterAwareCache(cfg, cache.Options{})
97+
Expect(err).NotTo(HaveOccurred())
98+
99+
go c.Start(ctx) //nolint:errcheck // Start is blocking, and error not relevant here.
100+
c.WaitForCacheSync(ctx)
101+
102+
By("By getting the default namespace with the informer, but cluster-less key should fail")
103+
ns := &corev1.Namespace{}
104+
err = c.Get(ctx, client.ObjectKey{Name: "default"}, ns)
105+
Expect(err).To(HaveOccurred())
106+
107+
By("By getting the default namespace with the informer, but cluster-aware key should succeed")
108+
err = c.Get(kontext.WithCluster(ctx, "cluster1"), client.ObjectKey{Name: "default", Namespace: "cluster1"}, ns)
109+
Expect(err).NotTo(HaveOccurred())
110+
})
111+
112+
It("should support indexes with cluster-aware keys", func() {
113+
ctx, cancel := context.WithCancel(context.Background())
114+
defer cancel()
115+
116+
c, err := kcp.NewClusterAwareCache(cfg, cache.Options{})
117+
Expect(err).NotTo(HaveOccurred())
118+
119+
By("Indexing the default namespace by name")
120+
err = c.IndexField(ctx, &corev1.Namespace{}, "name-clusteraware", func(obj client.Object) []string {
121+
return []string{"key-" + obj.GetName()}
122+
})
123+
Expect(err).NotTo(HaveOccurred())
124+
125+
go c.Start(ctx) //nolint:errcheck // Start is blocking, and error not relevant here.
126+
c.WaitForCacheSync(ctx)
127+
128+
By("By getting the default namespace via the custom index")
129+
nss := &corev1.NamespaceList{}
130+
err = c.List(ctx, nss, client.MatchingFieldsSelector{
131+
Selector: fields.OneTermEqualSelector("name-clusteraware", "key-default"),
132+
})
133+
Expect(err).NotTo(HaveOccurred())
134+
Expect(nss.Items).To(HaveLen(1))
135+
})
136+
})
137+
*/
89138
})
90-
*/

0 commit comments

Comments
 (0)