Skip to content

Commit 60dddc0

Browse files
committed
multiNamespaceCache: support custom newCache funcs per namespace
Signed-off-by: Joe Lanford <[email protected]>
1 parent 15b6689 commit 60dddc0

File tree

3 files changed

+352
-34
lines changed

3 files changed

+352
-34
lines changed

pkg/cache/cache_test.go

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,186 @@ var _ = Describe("Multi-Namespace Informer Cache", func() {
121121
var _ = Describe("Informer Cache without DeepCopy", func() {
122122
CacheTest(cache.New, cache.Options{UnsafeDisableDeepCopyByObject: cache.DisableDeepCopyByObject{cache.ObjectAll{}: true}})
123123
})
124+
var _ = Describe("ByNamespace Cache", func() {
125+
defer GinkgoRecover()
126+
var (
127+
informerCache cache.Cache
128+
informerCacheCtx context.Context
129+
informerCacheCancel context.CancelFunc
130+
pod1a client.Object
131+
pod1b client.Object
132+
pod2a client.Object
133+
pod2b client.Object
134+
pod2c client.Object
135+
pod3a client.Object
136+
pod3b client.Object
137+
)
138+
BeforeEach(func() {
139+
informerCacheCtx, informerCacheCancel = context.WithCancel(context.Background())
140+
Expect(cfg).NotTo(BeNil())
141+
cl, err := client.New(cfg, client.Options{})
142+
Expect(err).NotTo(HaveOccurred())
143+
err = ensureNamespace(testNamespaceOne, cl)
144+
Expect(err).NotTo(HaveOccurred())
145+
err = ensureNamespace(testNamespaceTwo, cl)
146+
Expect(err).NotTo(HaveOccurred())
147+
err = ensureNamespace(testNamespaceThree, cl)
148+
Expect(err).NotTo(HaveOccurred())
149+
err = ensureNode(testNodeOne, cl)
150+
Expect(err).NotTo(HaveOccurred())
151+
// namespace 1 stuff
152+
pod1a = createPod("pod-1a", testNamespaceOne, corev1.RestartPolicyNever) // matches (everything matches)
153+
pod1b = createPodWithLabels("pod-1b", testNamespaceOne, corev1.RestartPolicyNever, map[string]string{"other-match": "true"}) // matches (everything matches)
154+
// namespace 2 stuff
155+
pod2a = createPodWithLabels("pod-2a", testNamespaceTwo, corev1.RestartPolicyNever, map[string]string{"ns2-match": "false"}) // no match (does not match ns2 label selector)
156+
pod2b = createPodWithLabels("pod-2b", testNamespaceTwo, corev1.RestartPolicyNever, map[string]string{"ns2-match": "true"}) // matches (matches ns2 label selector)
157+
pod2c = createPodWithLabels("pod-2c", testNamespaceTwo, corev1.RestartPolicyNever, map[string]string{"other-match": "true"}) // no match (does not match ns2 label selector)
158+
// namespace 3 stuff
159+
pod3a = createPodWithLabels("pod-3a", testNamespaceThree, corev1.RestartPolicyNever, map[string]string{"other-match": "false"}) // no match (does not match default cache label selector)
160+
pod3b = createPodWithLabels("pod-3b", testNamespaceThree, corev1.RestartPolicyNever, map[string]string{"other-match": "true"}) // matches (matches default cache label selector)
161+
By("creating the informer cache")
162+
informerCache, err = cache.MultiNamespacedCacheWithOptionsBuilder(
163+
cache.WithNamespaceCache(testNamespaceOne, cache.New),
164+
cache.WithNamespaceCache(testNamespaceTwo, cache.BuilderWithOptions(cache.Options{
165+
DefaultSelector: cache.ObjectSelector{
166+
Label: labels.Set{"ns2-match": "true"}.AsSelector(),
167+
},
168+
})),
169+
cache.WithDefaultNamespacedCache(cache.BuilderWithOptions(cache.Options{
170+
DefaultSelector: cache.ObjectSelector{
171+
Label: labels.Set{"other-match": "true"}.AsSelector(),
172+
},
173+
})),
174+
cache.WithClusterScopedCache(cache.BuilderWithOptions(cache.Options{
175+
DefaultSelector: cache.ObjectSelector{
176+
Field: fields.OneTermEqualSelector("metadata.name", testNodeOne),
177+
},
178+
})),
179+
)(cfg, cache.Options{})
180+
Expect(err).NotTo(HaveOccurred())
181+
By("running the cache and waiting for it to sync")
182+
// pass as an arg so that we don't race between close and re-assign
183+
go func(ctx context.Context) {
184+
defer GinkgoRecover()
185+
Expect(informerCache.Start(ctx)).To(Succeed())
186+
}(informerCacheCtx)
187+
Expect(informerCache.WaitForCacheSync(informerCacheCtx)).To(BeTrue())
188+
})
189+
Describe("Get", func() {
190+
It("should get an item from a namespace cache", func() {
191+
pod := &corev1.Pod{}
192+
err := informerCache.Get(informerCacheCtx, client.ObjectKeyFromObject(pod1a), pod)
193+
Expect(err).NotTo(HaveOccurred())
194+
})
195+
It("should get an item from the default namespace cache", func() {
196+
pod := &corev1.Pod{}
197+
err := informerCache.Get(informerCacheCtx, client.ObjectKeyFromObject(pod3b), pod)
198+
Expect(err).NotTo(HaveOccurred())
199+
})
200+
It("should get a cluster-scoped item", func() {
201+
node := &corev1.Node{}
202+
err := informerCache.Get(informerCacheCtx, client.ObjectKey{Name: testNodeOne}, node)
203+
Expect(err).NotTo(HaveOccurred())
204+
})
205+
It("should not find an item from a namespace-specific cache if it is not matched", func() {
206+
pod := &corev1.Pod{}
207+
err := informerCache.Get(informerCacheCtx, client.ObjectKeyFromObject(pod2a), pod)
208+
Expect(apierrors.IsNotFound(err)).To(BeTrue())
209+
})
210+
It("should not find an item from the default namespace cache if it is not matched", func() {
211+
pod := &corev1.Pod{}
212+
err := informerCache.Get(informerCacheCtx, client.ObjectKeyFromObject(pod3a), pod)
213+
Expect(apierrors.IsNotFound(err)).To(BeTrue())
214+
})
215+
It("should not find an item at the cluster-scope if it is not matched", func() {
216+
ns := &corev1.Namespace{}
217+
err := informerCache.Get(informerCacheCtx, client.ObjectKey{Name: testNamespaceOne}, ns)
218+
Expect(apierrors.IsNotFound(err)).To(BeTrue())
219+
})
220+
})
221+
Describe("List", func() {
222+
When("Request is cluster-scoped", func() {
223+
It("Should list all pods and find exactly four", func() {
224+
var pods corev1.PodList
225+
err := informerCache.List(informerCacheCtx, &pods)
226+
Expect(err).NotTo(HaveOccurred())
227+
sort.Slice(pods.Items, func(i, j int) bool {
228+
if pods.Items[i].Namespace != pods.Items[j].Namespace {
229+
return pods.Items[i].Namespace < pods.Items[j].Namespace
230+
}
231+
return pods.Items[i].Name < pods.Items[j].Name
232+
})
233+
Expect(pods.Items).To(HaveLen(4))
234+
Expect(pods.Items[0].Namespace).To(Equal(testNamespaceOne))
235+
Expect(pods.Items[0].Name).To(Equal("pod-1a"))
236+
Expect(pods.Items[1].Namespace).To(Equal(testNamespaceOne))
237+
Expect(pods.Items[1].Name).To(Equal("pod-1b"))
238+
Expect(pods.Items[2].Namespace).To(Equal(testNamespaceTwo))
239+
Expect(pods.Items[2].Name).To(Equal("pod-2b"))
240+
Expect(pods.Items[3].Namespace).To(Equal(testNamespaceThree))
241+
Expect(pods.Items[3].Name).To(Equal("pod-3b"))
242+
})
243+
It("Should list nodes and find exactly one", func() {
244+
var nodes corev1.NodeList
245+
err := informerCache.List(informerCacheCtx, &nodes)
246+
Expect(err).NotTo(HaveOccurred())
247+
Expect(nodes.Items).To(HaveLen(1))
248+
Expect(nodes.Items[0].Namespace).To(Equal(""))
249+
Expect(nodes.Items[0].Name).To(Equal(testNodeOne))
250+
})
251+
It("Should list namespaces and find none", func() {
252+
var namespaces corev1.NamespaceList
253+
err := informerCache.List(informerCacheCtx, &namespaces)
254+
Expect(err).NotTo(HaveOccurred())
255+
Expect(namespaces.Items).To(HaveLen(0))
256+
})
257+
})
258+
When("Request is namespace-scoped", func() {
259+
It("Should list pods in namespace one", func() {
260+
var pods corev1.PodList
261+
err := informerCache.List(informerCacheCtx, &pods, client.InNamespace(testNamespaceOne))
262+
Expect(err).NotTo(HaveOccurred())
263+
sort.Slice(pods.Items, func(i, j int) bool {
264+
if pods.Items[i].Namespace != pods.Items[j].Namespace {
265+
return pods.Items[i].Namespace < pods.Items[j].Namespace
266+
}
267+
return pods.Items[i].Name < pods.Items[j].Name
268+
})
269+
Expect(pods.Items).To(HaveLen(2))
270+
Expect(pods.Items[0].Namespace).To(Equal(testNamespaceOne))
271+
Expect(pods.Items[0].Name).To(Equal("pod-1a"))
272+
Expect(pods.Items[1].Namespace).To(Equal(testNamespaceOne))
273+
Expect(pods.Items[1].Name).To(Equal("pod-1b"))
274+
})
275+
It("Should list pods in namespace two", func() {
276+
var pods corev1.PodList
277+
err := informerCache.List(informerCacheCtx, &pods, client.InNamespace(testNamespaceTwo))
278+
Expect(err).NotTo(HaveOccurred())
279+
Expect(pods.Items).To(HaveLen(1))
280+
Expect(pods.Items[0].Namespace).To(Equal(testNamespaceTwo))
281+
Expect(pods.Items[0].Name).To(Equal("pod-2b"))
282+
})
283+
It("Should list pods in namespace three", func() {
284+
var pods corev1.PodList
285+
err := informerCache.List(informerCacheCtx, &pods, client.InNamespace(testNamespaceThree))
286+
Expect(err).NotTo(HaveOccurred())
287+
Expect(pods.Items).To(HaveLen(1))
288+
Expect(pods.Items[0].Namespace).To(Equal(testNamespaceThree))
289+
Expect(pods.Items[0].Name).To(Equal("pod-3b"))
290+
})
291+
})
292+
})
293+
AfterEach(func() {
294+
deletePod(pod1a)
295+
deletePod(pod1b)
296+
deletePod(pod2a)
297+
deletePod(pod2b)
298+
deletePod(pod2c)
299+
deletePod(pod3a)
300+
deletePod(pod3b)
301+
informerCacheCancel()
302+
})
303+
})
124304

125305
var _ = Describe("Cache with transformers", func() {
126306
var (

0 commit comments

Comments
 (0)