github.com/alibaba/ilogtail/pkg@v0.0.0-20250526110833-c53b480d046c/helper/k8smeta/k8s_meta_deferred_deletion_meta_store_test.go (about) 1 package k8smeta 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/stretchr/testify/assert" 8 corev1 "k8s.io/api/core/v1" 9 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 "k8s.io/client-go/tools/cache" 11 ) 12 13 func TestDeferredDeletion(t *testing.T) { 14 eventCh := make(chan *K8sMetaEvent) 15 stopCh := make(chan struct{}) 16 gracePeriod := 1 17 cache := NewDeferredDeletionMetaStore(eventCh, stopCh, int64(gracePeriod), cache.MetaNamespaceKeyFunc, generatePodIPKey) 18 cache.Start() 19 pod := &corev1.Pod{ 20 ObjectMeta: metav1.ObjectMeta{ 21 Name: "test", 22 Namespace: "default", 23 }, 24 Status: corev1.PodStatus{ 25 PodIP: "127.0.0.1", 26 }, 27 } 28 eventCh <- &K8sMetaEvent{ 29 EventType: EventTypeAdd, 30 Object: &ObjectWrapper{ 31 Raw: pod, 32 }, 33 } 34 cache.lock.RLock() 35 if _, ok := cache.Items["default/test"]; !ok { 36 t.Errorf("failed to add object to cache") 37 } 38 cache.lock.RUnlock() 39 assert.Equal(t, 1, len(cache.Get([]string{"127.0.0.1"}))) 40 eventCh <- &K8sMetaEvent{ 41 EventType: EventTypeDelete, 42 Object: &ObjectWrapper{ 43 Raw: pod, 44 }, 45 } 46 eventCh <- &K8sMetaEvent{ 47 EventType: EventTypeDelete, 48 Object: &ObjectWrapper{ 49 Raw: pod, 50 }, 51 } 52 time.Sleep(10 * time.Millisecond) 53 cache.lock.RLock() 54 if item, ok := cache.Items["default/test"]; !ok { 55 t.Error("failed to deferred delete object from cache") 56 } else { 57 assert.Equal(t, true, item.Deleted) 58 } 59 cache.lock.RUnlock() 60 assert.Equal(t, 1, len(cache.Get([]string{"127.0.0.1"}))) 61 time.Sleep(time.Duration(gracePeriod+1) * time.Second) 62 cache.lock.RLock() 63 if _, ok := cache.Items["default/test"]; ok { 64 t.Error("failed to delete object from cache") 65 } 66 cache.lock.RUnlock() 67 assert.Equal(t, 0, len(cache.Get([]string{"127.0.0.1"}))) 68 } 69 70 func TestDeferredDeletionWithAddEvent(t *testing.T) { 71 eventCh := make(chan *K8sMetaEvent) 72 stopCh := make(chan struct{}) 73 gracePeriod := 1 74 cache := NewDeferredDeletionMetaStore(eventCh, stopCh, int64(gracePeriod), cache.MetaNamespaceKeyFunc, generatePodIPKey) 75 cache.Start() 76 pod := &corev1.Pod{ 77 ObjectMeta: metav1.ObjectMeta{ 78 Name: "test", 79 Namespace: "default", 80 }, 81 Status: corev1.PodStatus{ 82 PodIP: "127.0.0.1", 83 }, 84 } 85 eventCh <- &K8sMetaEvent{ 86 EventType: EventTypeAdd, 87 Object: &ObjectWrapper{ 88 Raw: pod, 89 }, 90 } 91 cache.lock.RLock() 92 if _, ok := cache.Items["default/test"]; !ok { 93 t.Errorf("failed to add object to cache") 94 } 95 cache.lock.RUnlock() 96 eventCh <- &K8sMetaEvent{ 97 EventType: EventTypeDelete, 98 Object: &ObjectWrapper{ 99 Raw: pod, 100 }, 101 } 102 // add again 103 pod2 := &corev1.Pod{ 104 ObjectMeta: metav1.ObjectMeta{ 105 Name: "test", 106 Namespace: "default", 107 }, 108 Status: corev1.PodStatus{ 109 PodIP: "127.0.0.2", 110 }, 111 } 112 eventCh <- &K8sMetaEvent{ 113 EventType: EventTypeAdd, 114 Object: &ObjectWrapper{ 115 Raw: pod2, 116 }, 117 } 118 time.Sleep(10 * time.Millisecond) 119 cache.lock.RLock() 120 if item, ok := cache.Items["default/test"]; !ok { 121 t.Error("failed to deferred delete object from cache") 122 } else { 123 assert.Equal(t, false, item.Deleted) 124 } 125 cache.lock.RUnlock() 126 assert.Equal(t, 0, len(cache.Get([]string{"127.0.0.1"}))) 127 assert.Equal(t, 1, len(cache.Get([]string{"127.0.0.2"}))) 128 time.Sleep(time.Duration(gracePeriod+1) * time.Second) 129 cache.lock.RLock() 130 if _, ok := cache.Items["default/test"]; !ok { 131 t.Error("should not delete object from cache") 132 } 133 cache.lock.RUnlock() 134 assert.Equal(t, 1, len(cache.Get([]string{"127.0.0.2"}))) 135 } 136 137 func TestRegisterWaitManagerReady(t *testing.T) { 138 eventCh := make(chan *K8sMetaEvent) 139 stopCh := make(chan struct{}) 140 gracePeriod := 1 141 cache := NewDeferredDeletionMetaStore(eventCh, stopCh, int64(gracePeriod), cache.MetaNamespaceKeyFunc) 142 manager := GetMetaManagerInstance() 143 cache.RegisterSendFunc("test", func(kme []*K8sMetaEvent) {}, 100) 144 select { 145 case <-cache.eventCh: 146 t.Error("should not receive event before manager is ready") 147 case <-time.After(2 * time.Second): 148 } 149 manager.ready.Store(true) 150 select { 151 case <-cache.eventCh: 152 case <-time.After(2 * time.Second): 153 t.Error("should receive timer event immediately after manager is ready") 154 } 155 } 156 157 func TestTimerSend(t *testing.T) { 158 eventCh := make(chan *K8sMetaEvent) 159 stopCh := make(chan struct{}) 160 manager := GetMetaManagerInstance() 161 manager.ready.Store(true) 162 gracePeriod := 1 163 cache := NewDeferredDeletionMetaStore(eventCh, stopCh, int64(gracePeriod), cache.MetaNamespaceKeyFunc) 164 cache.Items["default/test"] = &ObjectWrapper{ 165 Raw: &corev1.Pod{ 166 ObjectMeta: metav1.ObjectMeta{ 167 Name: "test", 168 Namespace: "default", 169 }, 170 }, 171 } 172 cache.Start() 173 resultCh := make(chan struct{}) 174 cache.RegisterSendFunc("test", func(kmes []*K8sMetaEvent) { 175 resultCh <- struct{}{} 176 }, 1) 177 go func() { 178 time.Sleep(3 * time.Second) 179 close(stopCh) 180 }() 181 count := 0 182 for { 183 select { 184 case <-resultCh: 185 count++ 186 case <-stopCh: 187 if count < 3 { 188 t.Errorf("should receive 3 timer events, but got %d", count) 189 } 190 return 191 } 192 } 193 } 194 195 func TestFilter(t *testing.T) { 196 eventCh := make(chan *K8sMetaEvent) 197 stopCh := make(chan struct{}) 198 gracePeriod := 1 199 cache := NewDeferredDeletionMetaStore(eventCh, stopCh, int64(gracePeriod), cache.MetaNamespaceKeyFunc) 200 cache.Items["default/test"] = &ObjectWrapper{ 201 Raw: &corev1.Pod{ 202 ObjectMeta: metav1.ObjectMeta{ 203 Name: "test", 204 Namespace: "default", 205 Labels: map[string]string{ 206 "app": "test", 207 }, 208 }, 209 }, 210 } 211 cache.Items["default/test2"] = &ObjectWrapper{ 212 Raw: &corev1.Pod{ 213 ObjectMeta: metav1.ObjectMeta{ 214 Name: "test2", 215 Namespace: "default", 216 Labels: map[string]string{ 217 "app": "test2", 218 }, 219 }, 220 }, 221 } 222 cache.Items["default/test3"] = &ObjectWrapper{ 223 Raw: &corev1.Pod{ 224 ObjectMeta: metav1.ObjectMeta{ 225 Name: "test3", 226 Namespace: "default", 227 Labels: map[string]string{ 228 "app": "test2", 229 }, 230 }, 231 }, 232 } 233 objs := cache.Filter(func(obj *ObjectWrapper) bool { 234 return obj.Raw.(*corev1.Pod).Labels["app"] == "test2" 235 }, 1) 236 assert.Len(t, objs, 1) 237 assert.Equal(t, "test2", objs[0].Raw.(*corev1.Pod).Labels["app"]) 238 239 objs = cache.Filter(nil, 10) 240 assert.Len(t, objs, 3) 241 } 242 243 func TestGet(t *testing.T) { 244 eventCh := make(chan *K8sMetaEvent) 245 stopCh := make(chan struct{}) 246 gracePeriod := 1 247 cache := NewDeferredDeletionMetaStore(eventCh, stopCh, int64(gracePeriod), cache.MetaNamespaceKeyFunc, generateCommonKey) 248 cache.Start() 249 eventCh <- &K8sMetaEvent{ 250 EventType: EventTypeAdd, 251 Object: &ObjectWrapper{ 252 Raw: &corev1.Pod{ 253 ObjectMeta: metav1.ObjectMeta{ 254 Name: "test", 255 Namespace: "default", 256 }, 257 }, 258 }, 259 } 260 eventCh <- &K8sMetaEvent{ 261 EventType: EventTypeAdd, 262 Object: &ObjectWrapper{ 263 Raw: &corev1.Pod{ 264 ObjectMeta: metav1.ObjectMeta{ 265 Name: "test2", 266 Namespace: "default", 267 }, 268 }, 269 }, 270 } 271 eventCh <- &K8sMetaEvent{ 272 EventType: EventTypeAdd, 273 Object: &ObjectWrapper{ 274 Raw: nil, 275 }, 276 } 277 // nil object in cache 278 cache.Items["default/test3"] = &ObjectWrapper{ 279 Raw: nil, 280 } 281 cache.Index["default/test3"] = IndexItem{ 282 Keys: map[string]struct{}{ 283 "default/test3": {}, 284 }, 285 } 286 // in index but not in cache 287 cache.Index["default/test4"] = IndexItem{ 288 Keys: map[string]struct{}{ 289 "default/test4": {}, 290 }, 291 } 292 293 time.Sleep(10 * time.Millisecond) 294 objs := cache.Get([]string{"default/test", "default/test2", "default/test3", "default/test4", "default/test5"}) 295 assert.Len(t, objs, 2) 296 assert.Equal(t, "test", objs["default/test"][0].Raw.(*corev1.Pod).Name) 297 assert.Equal(t, "test2", objs["default/test2"][0].Raw.(*corev1.Pod).Name) 298 } 299 300 func TestIndex(t *testing.T) { 301 eventCh := make(chan *K8sMetaEvent) 302 stopCh := make(chan struct{}) 303 gracePeriod := 1 304 cache := NewDeferredDeletionMetaStore(eventCh, stopCh, int64(gracePeriod), cache.MetaNamespaceKeyFunc, generateCommonKey) 305 cache.Start() 306 // add 307 pod := &corev1.Pod{ 308 ObjectMeta: metav1.ObjectMeta{ 309 Name: "test", 310 Namespace: "default", 311 }, 312 } 313 eventCh <- &K8sMetaEvent{ 314 EventType: EventTypeAdd, 315 Object: &ObjectWrapper{ 316 Raw: pod, 317 }, 318 } 319 pod2 := &corev1.Pod{ 320 ObjectMeta: metav1.ObjectMeta{ 321 Name: "test2", 322 Namespace: "default", 323 }, 324 } 325 eventCh <- &K8sMetaEvent{ 326 EventType: EventTypeAdd, 327 Object: &ObjectWrapper{ 328 Raw: pod2, 329 }, 330 } 331 time.Sleep(time.Millisecond * 10) 332 cache.lock.RLock() 333 assert.Equal(t, 2, len(cache.Items)) 334 assert.Equal(t, 2, len(cache.Index)) 335 for _, idx := range cache.Index { 336 assert.Equal(t, 1, len(idx.Keys)) 337 } 338 cache.lock.RUnlock() 339 340 // update 341 eventCh <- &K8sMetaEvent{ 342 EventType: EventTypeUpdate, 343 Object: &ObjectWrapper{ 344 Raw: pod, 345 }, 346 } 347 eventCh <- &K8sMetaEvent{ 348 EventType: EventTypeUpdate, 349 Object: &ObjectWrapper{ 350 Raw: pod2, 351 }, 352 } 353 time.Sleep(time.Millisecond * 10) 354 cache.lock.RLock() 355 assert.Equal(t, 2, len(cache.Items)) 356 assert.Equal(t, 2, len(cache.Index)) 357 for _, idx := range cache.Index { 358 assert.Equal(t, 1, len(idx.Keys)) 359 } 360 cache.lock.RUnlock() 361 362 // delete 363 eventCh <- &K8sMetaEvent{ 364 EventType: EventTypeDelete, 365 Object: &ObjectWrapper{ 366 Raw: pod, 367 }, 368 } 369 eventCh <- &K8sMetaEvent{ 370 EventType: EventTypeDelete, 371 Object: &ObjectWrapper{ 372 Raw: pod2, 373 }, 374 } 375 time.Sleep(time.Duration(gracePeriod) * time.Second) 376 time.Sleep(time.Millisecond * 10) 377 cache.lock.RLock() 378 assert.Equal(t, 0, len(cache.Items)) 379 assert.Equal(t, 0, len(cache.Index)) 380 cache.lock.RUnlock() 381 } 382 383 func TestRegisterAndUnRegisterSendFunc(t *testing.T) { 384 eventCh := make(chan *K8sMetaEvent) 385 stopCh := make(chan struct{}) 386 gracePeriod := 1 387 cache := NewDeferredDeletionMetaStore(eventCh, stopCh, int64(gracePeriod), cache.MetaNamespaceKeyFunc) 388 cache.Start() 389 counter := 0 390 interval := 1 391 cache.RegisterSendFunc("test", func(kme []*K8sMetaEvent) { 392 counter++ 393 }, interval) 394 pod := &corev1.Pod{ 395 ObjectMeta: metav1.ObjectMeta{ 396 Name: "test", 397 Namespace: "default", 398 }, 399 } 400 eventCh <- &K8sMetaEvent{ 401 EventType: EventTypeAdd, 402 Object: &ObjectWrapper{ 403 Raw: pod, 404 }, 405 } 406 eventCh <- &K8sMetaEvent{ 407 EventType: EventTypeDelete, 408 Object: &ObjectWrapper{ 409 Raw: pod, 410 }, 411 } 412 eventCh <- &K8sMetaEvent{ 413 EventType: "not exist", 414 Object: &ObjectWrapper{ 415 Raw: pod, 416 }, 417 } 418 time.Sleep(10 * time.Millisecond) 419 assert.Equal(t, 3, counter) // 1 for add event, 1 for timer event, 1 for delete event 420 cache.UnRegisterSendFunc("test") 421 time.Sleep(10 * time.Millisecond) 422 pod2 := &corev1.Pod{ 423 ObjectMeta: metav1.ObjectMeta{ 424 Name: "test2", 425 Namespace: "default", 426 }, 427 } 428 eventCh <- &K8sMetaEvent{ 429 EventType: EventTypeAdd, 430 Object: &ObjectWrapper{ 431 Raw: pod2, 432 }, 433 } 434 time.Sleep(time.Duration(interval) * time.Second) 435 assert.Equal(t, 3, counter) 436 }