@@ -22,6 +22,7 @@ import (
22
22
"reflect"
23
23
"sort"
24
24
"strconv"
25
+ "time"
25
26
26
27
. "github.com/onsi/ginkgo"
27
28
. "github.com/onsi/ginkgo/extensions/table"
@@ -121,6 +122,237 @@ var _ = Describe("Multi-Namespace Informer Cache", func() {
121
122
var _ = Describe ("Informer Cache without DeepCopy" , func () {
122
123
CacheTest (cache .New , cache.Options {UnsafeDisableDeepCopyByObject : cache.DisableDeepCopyByObject {cache.ObjectAll {}: true }})
123
124
})
125
+
126
+ var _ = Describe ("Cache with transformers" , func () {
127
+ var (
128
+ informerCache cache.Cache
129
+ informerCacheCtx context.Context
130
+ informerCacheCancel context.CancelFunc
131
+ clien client.Client
132
+ transformerHits map [string ]int
133
+ )
134
+
135
+ pod := & corev1.Pod {
136
+ TypeMeta : metav1.TypeMeta {},
137
+ ObjectMeta : metav1.ObjectMeta {
138
+ Name : "test.pod" ,
139
+ Namespace : testNamespaceOne ,
140
+ },
141
+ Spec : corev1.PodSpec {
142
+ Containers : []corev1.Container {
143
+ {
144
+ Name : "my-cool-container" ,
145
+ Image : "nginx" ,
146
+ },
147
+ },
148
+ },
149
+ Status : corev1.PodStatus {},
150
+ }
151
+ pod .SetGroupVersionKind (schema.GroupVersionKind {
152
+ Kind : "Pod" ,
153
+ Version : "v1" ,
154
+ })
155
+
156
+ BeforeEach (func () {
157
+ var err error
158
+ var transform = func (s string , i interface {}) (interface {}, error ) {
159
+ if obj , ok := i .(client.Object ); ok {
160
+ annos := obj .GetAnnotations ()
161
+ if annos == nil {
162
+ annos = map [string ]string {}
163
+ }
164
+
165
+ k := "gotype"
166
+
167
+ // If the key does not exist, then this is the first time the
168
+ // object is being transformed. Therefore it is safe to modify
169
+ // the instance directly without copying
170
+ if _ , exists := annos [k ]; ! exists {
171
+ typ := reflect .TypeOf (i )
172
+ for typ .Kind () == reflect .Ptr {
173
+ typ = typ .Elem ()
174
+ }
175
+ annos [k ] = typ .PkgPath () + "." + typ .Name ()
176
+ obj .SetAnnotations (annos )
177
+ }
178
+ }
179
+
180
+ if transformerHits == nil {
181
+ transformerHits = map [string ]int {}
182
+ }
183
+
184
+ if exist , ok := transformerHits [s ]; ok {
185
+ transformerHits [s ] = exist + 1
186
+ } else {
187
+ transformerHits [s ] = 1
188
+ }
189
+ return i , nil
190
+ }
191
+
192
+ clien , err = client .New (cfg , client.Options {})
193
+ Expect (err ).NotTo (HaveOccurred ())
194
+ err = ensureNamespace (testNamespaceOne , clien )
195
+ Expect (err ).NotTo (HaveOccurred ())
196
+
197
+ pod := pod .DeepCopy ()
198
+
199
+ unstructuredPod := & unstructured.Unstructured {}
200
+ unstructuredPod .SetGroupVersionKind (pod .GroupVersionKind ())
201
+
202
+ metadataPod := & metav1.PartialObjectMetadata {}
203
+ metadataPod .SetGroupVersionKind (pod .GroupVersionKind ())
204
+
205
+ By ("creating the informer cache" )
206
+ informerCache , err = cache .New (cfg , cache.Options {
207
+ TransformFuncByObject : cache.TransformFuncByObject {
208
+ unstructuredPod : func (i interface {}) (interface {}, error ) {
209
+ return transform ("unstructured" , i )
210
+ },
211
+ metadataPod : func (i interface {}) (interface {}, error ) {
212
+ return transform ("metadata" , i )
213
+ },
214
+ pod : func (i interface {}) (interface {}, error ) {
215
+ return transform ("structured" , i )
216
+ },
217
+ },
218
+ })
219
+ Expect (err ).NotTo (HaveOccurred ())
220
+
221
+ informerCacheCtx , informerCacheCancel = context .WithCancel (context .Background ())
222
+ Expect (cfg ).NotTo (BeNil ())
223
+
224
+ err = clien .Create (informerCacheCtx , pod )
225
+ Expect (err ).ToNot (HaveOccurred ())
226
+
227
+ By ("running the cache" )
228
+ go func (ctx context.Context ) {
229
+ defer GinkgoRecover ()
230
+ Expect (informerCache .Start (ctx )).To (Succeed ())
231
+ }(informerCacheCtx )
232
+ Expect (informerCache .WaitForCacheSync (informerCacheCtx )).To (BeTrue ())
233
+ })
234
+
235
+ AfterEach (func () {
236
+ unstructuredPod := & unstructured.Unstructured {}
237
+ unstructuredPod .SetGroupVersionKind (pod .GroupVersionKind ())
238
+ unstructuredPod .SetName ("test.pod" )
239
+ unstructuredPod .SetNamespace (pod .Namespace )
240
+
241
+ clien .Delete (informerCacheCtx , unstructuredPod )
242
+ informerCacheCancel ()
243
+ })
244
+
245
+ It ("should transform unstructured objects" , func () {
246
+ By ("making sure transform is applied to initial cache listing" )
247
+ podsList := & unstructured.UnstructuredList {
248
+ Object : map [string ]interface {}{
249
+ "apiVersion" : "v1" ,
250
+ "kind" : "PodList" ,
251
+ },
252
+ }
253
+
254
+ err := informerCache .List (informerCacheCtx , podsList )
255
+ Expect (err ).ToNot (HaveOccurred ())
256
+
257
+ // Make sure transformer is applied on create
258
+ Expect (transformerHits ["unstructured" ]).To (Equal (1 ))
259
+
260
+ By ("making sure transform is applied to updated cache listings" )
261
+ unstructuredPod := & podsList .Items [0 ]
262
+ unstructuredPod .SetAnnotations (map [string ]string {
263
+ "test" : "hello" ,
264
+ })
265
+
266
+ err = clien .Update (informerCacheCtx , unstructuredPod )
267
+ Expect (err ).ToNot (HaveOccurred ())
268
+
269
+ podsList = & unstructured.UnstructuredList {
270
+ Object : map [string ]interface {}{
271
+ "apiVersion" : "v1" ,
272
+ "kind" : "PodList" ,
273
+ },
274
+ }
275
+
276
+ err = informerCache .List (informerCacheCtx , podsList )
277
+ Expect (err ).ToNot (HaveOccurred ())
278
+
279
+ //!TODO: I do not know a way to force the underlying listerwatcher
280
+ // to update. Please advise. Sleep here temporarily since it is required
281
+ // to reliably pass.
282
+ time .Sleep (1 * time .Second )
283
+ Expect (informerCache .WaitForCacheSync (informerCacheCtx )).To (BeTrue ())
284
+ Expect (transformerHits ["unstructured" ]).To (Equal (2 ))
285
+ })
286
+ It ("should transform structured objects" , func () {
287
+ podsList := & corev1.PodList {}
288
+ err := informerCache .List (informerCacheCtx , podsList )
289
+ Expect (err ).ToNot (HaveOccurred ())
290
+
291
+ // Make sure transformer is applied on create
292
+ Expect (transformerHits ["structured" ]).To (Equal (1 ))
293
+
294
+ By ("making sure transform is applied to updated cache listings" )
295
+ pod := & podsList .Items [0 ]
296
+ pod .SetAnnotations (map [string ]string {
297
+ "test" : "hello" ,
298
+ })
299
+
300
+ err = clien .Update (informerCacheCtx , pod )
301
+ Expect (err ).ToNot (HaveOccurred ())
302
+
303
+ podsList = & corev1.PodList {}
304
+ err = informerCache .List (informerCacheCtx , podsList )
305
+ Expect (err ).ToNot (HaveOccurred ())
306
+
307
+ //!TODO: I do not know a way to force the underlying listerwatcher
308
+ // to update. Please advise. Sleep here temporarily since it is required
309
+ // to reliably pass.
310
+ time .Sleep (1 * time .Second )
311
+ Expect (informerCache .WaitForCacheSync (informerCacheCtx )).To (BeTrue ())
312
+ Expect (transformerHits ["structured" ]).To (Equal (2 ))
313
+ })
314
+ It ("should transform metadata objects" , func () {
315
+ podsList := & metav1.PartialObjectMetadataList {
316
+ TypeMeta : metav1.TypeMeta {
317
+ APIVersion : "v1" ,
318
+ Kind : "PodList" ,
319
+ },
320
+ }
321
+
322
+ err := informerCache .List (informerCacheCtx , podsList )
323
+ Expect (err ).ToNot (HaveOccurred ())
324
+
325
+ // Make sure transformer is applied on create
326
+ Expect (transformerHits ["metadata" ]).To (Equal (1 ))
327
+
328
+ By ("making sure transform is applied to updated cache listings" )
329
+ pod := pod .DeepCopy ()
330
+ pod .SetAnnotations (map [string ]string {
331
+ "test" : "hello" ,
332
+ })
333
+
334
+ err = clien .Update (informerCacheCtx , pod )
335
+ Expect (err ).ToNot (HaveOccurred ())
336
+
337
+ podsList = & metav1.PartialObjectMetadataList {
338
+ TypeMeta : metav1.TypeMeta {
339
+ APIVersion : "v1" ,
340
+ Kind : "PodList" ,
341
+ },
342
+ }
343
+
344
+ err = informerCache .List (informerCacheCtx , podsList )
345
+ Expect (err ).ToNot (HaveOccurred ())
346
+
347
+ //!TODO: I do not know a way to force the underlying listerwatcher
348
+ // to update. Please advise. Sleep here temporarily since it is required
349
+ // to reliably pass.
350
+ time .Sleep (1 * time .Second )
351
+ Expect (informerCache .WaitForCacheSync (informerCacheCtx )).To (BeTrue ())
352
+ Expect (transformerHits ["metadata" ]).To (Equal (2 ))
353
+ })
354
+ })
355
+
124
356
var _ = Describe ("Cache with selectors" , func () {
125
357
defer GinkgoRecover ()
126
358
var (
0 commit comments