layer1: add namespace tombstone helper step 34

This commit is contained in:
Naeel
2026-04-26 10:39:11 +03:00
parent d09bee3431
commit b6f3640bbe
3 changed files with 84 additions and 0 deletions
@@ -0,0 +1,19 @@
# 2026-04-26 — NamespaceManager rewrite, step 34
## Цель шага
Подготовить безопасный helper для delete/tombstone событий Namespace informer-а.
## Что меняем
1. Добавляем `NamespaceFromObject()`.
2. Helper поддерживает:
- `*corev1.Namespace`
- `cache.DeletedFinalStateUnknown`
3. Добавляем `NamespaceEventFromObject()`.
4. Добавляем unit tests.
## Что НЕ меняем
- не подключаем delete handling в watcher-ы на этом шаге;
- не меняем runtime behavior.
+27
View File
@@ -4,6 +4,7 @@ import (
"time" "time"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
k8sCache "k8s.io/client-go/tools/cache"
) )
const ( const (
@@ -88,6 +89,32 @@ func NamespaceEventFromNamespace(eventType NamespaceEventType, namespace *corev1
return NewNamespaceEvent(eventType, namespace.Name, namespace.Labels, source, observedAt) return NewNamespaceEvent(eventType, namespace.Name, namespace.Labels, source, observedAt)
} }
func NamespaceFromObject(obj interface{}) (*corev1.Namespace, bool) {
switch typed := obj.(type) {
case *corev1.Namespace:
return typed, true
case k8sCache.DeletedFinalStateUnknown:
namespace, ok := typed.Obj.(*corev1.Namespace)
return namespace, ok
case *k8sCache.DeletedFinalStateUnknown:
if typed == nil {
return nil, false
}
namespace, ok := typed.Obj.(*corev1.Namespace)
return namespace, ok
default:
return nil, false
}
}
func NamespaceEventFromObject(eventType NamespaceEventType, obj interface{}, source NamespaceSource, observedAt time.Time) NamespaceEvent {
namespace, ok := NamespaceFromObject(obj)
if !ok {
return NewNamespaceEvent(eventType, "", nil, source, observedAt)
}
return NamespaceEventFromNamespace(eventType, namespace, source, observedAt)
}
func (nr NamespaceRecord) Clone() NamespaceRecord { func (nr NamespaceRecord) Clone() NamespaceRecord {
clone := nr clone := nr
clone.Labels = cloneStringMap(nr.Labels) clone.Labels = cloneStringMap(nr.Labels)
+38
View File
@@ -5,6 +5,7 @@ import (
"time" "time"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
k8sCache "k8s.io/client-go/tools/cache"
) )
func TestNamespaceRecordClone(t *testing.T) { func TestNamespaceRecordClone(t *testing.T) {
@@ -107,3 +108,40 @@ func TestNamespaceEventFromNamespace(t *testing.T) {
t.Fatalf("expected event labels to stay detached from original namespace") t.Fatalf("expected event labels to stay detached from original namespace")
} }
} }
func TestNamespaceFromObject(t *testing.T) {
namespace := &corev1.Namespace{}
namespace.Name = "tenant-a"
extracted, ok := NamespaceFromObject(namespace)
if !ok || extracted.Name != "tenant-a" {
t.Fatalf("expected namespace object to be extracted directly")
}
extracted, ok = NamespaceFromObject(k8sCache.DeletedFinalStateUnknown{Obj: namespace})
if !ok || extracted.Name != "tenant-a" {
t.Fatalf("expected namespace tombstone to be extracted")
}
}
func TestNamespaceEventFromObject(t *testing.T) {
namespace := &corev1.Namespace{}
namespace.Name = "tenant-a"
namespace.Labels = map[string]string{ManagedNamespaceLabelKey: ManagedNamespaceLabelValue}
event := NamespaceEventFromObject(NamespaceEventRemove, k8sCache.DeletedFinalStateUnknown{Obj: namespace}, NamespaceSourceWatcher, time.Now().UTC())
if event.Type != NamespaceEventRemove {
t.Fatalf("expected remove event type")
}
if event.Name != "tenant-a" {
t.Fatalf("expected tenant-a event name")
}
if event.Labels[ManagedNamespaceLabelKey] != ManagedNamespaceLabelValue {
t.Fatalf("expected labels copied from tombstone namespace")
}
emptyEvent := NamespaceEventFromObject(NamespaceEventRemove, "not-a-namespace", NamespaceSourceWatcher, time.Now().UTC())
if emptyEvent.Name != "" {
t.Fatalf("expected empty name for unsupported object")
}
}