test: add integration test for NSWatcher with fake Kubernetes client
TestStartManagedNamespaceWatcherIntegration проверяет полный маршрут горячей регистрации namespace без real cluster: 1. RunManagedNamespaceWatcher запускается с k8sfake.NewSimpleClientset() 2. В fake client создаётся Namespace с label fission.io/managed=true 3. Kubernetes informer детектирует событие (без polling, через Watch) 4. SubscriberFuncs.OnNamespaceAdd вызывается 5. NamespaceManager содержит запись со статусом Active Тест доказывает, что вся цепочка fake k8s event → informer → AddFunc → subscriber → manager работает корректно без rolling restart процесса. Также добавлен import metav1 в test file (требовался для CreateOptions).
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zaptest/observer"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
k8sfake "k8s.io/client-go/kubernetes/fake"
|
||||
k8sCache "k8s.io/client-go/tools/cache"
|
||||
|
||||
@@ -818,6 +819,76 @@ func TestNamespaceManagerDispatchRemoveFailure(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestStartManagedNamespaceWatcherIntegration проверяет полный маршрут:
|
||||
// fake k8s client → информер → AddFunc → subscriber.OnNamespaceAdd.
|
||||
// Это интеграционный тест без real cluster — использует k8sfake.
|
||||
func TestStartManagedNamespaceWatcherIntegration(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
fakeClient := k8sfake.NewSimpleClientset()
|
||||
mgr := managerPkg.New()
|
||||
router := &testNamespaceSubscriber{name: "router"}
|
||||
|
||||
// Запускаем watcher — не Bootstrap, только informer.
|
||||
// config.Namespaces пусто, чтобы не было pre-loaded namespace-ов.
|
||||
manager, err := RunManagedNamespaceWatcher(ctx, zap.NewNop(), fakeClient, mgr, ManagedNamespaceWatcherConfig{
|
||||
Component: "router.NSWatcher",
|
||||
Namespaces: nil,
|
||||
RemovalStrategy: NamespaceRemovalStrategyTrackOnly,
|
||||
Subscriber: router,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("RunManagedNamespaceWatcher failed: %v", err)
|
||||
}
|
||||
|
||||
// Создаём namespace с managed label в fake client.
|
||||
ns := &corev1.Namespace{}
|
||||
ns.Name = "tenant-integration-a"
|
||||
ns.Labels = map[string]string{ManagedNamespaceLabelKey: ManagedNamespaceLabelValue}
|
||||
if _, err := fakeClient.CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{}); err != nil {
|
||||
t.Fatalf("failed to create test namespace in fake client: %v", err)
|
||||
}
|
||||
|
||||
// Ждём, пока informer обработает event и subscriber получит вызов.
|
||||
// Timeout намеренно короткий (3 секунды) — fake client синхронный.
|
||||
deadline := time.Now().Add(3 * time.Second)
|
||||
for time.Now().Before(deadline) {
|
||||
if router.addCalls >= 1 {
|
||||
break
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
if router.addCalls == 0 {
|
||||
t.Fatalf("expected subscriber.OnNamespaceAdd to be called after namespace creation, got 0 calls")
|
||||
}
|
||||
if router.addCalls != 1 {
|
||||
t.Fatalf("expected exactly 1 add call (namespace is new), got %d", router.addCalls)
|
||||
}
|
||||
|
||||
// Namespace должен быть в manager snapshot.
|
||||
snapshot := manager.Snapshot()
|
||||
found := false
|
||||
for _, name := range snapshot {
|
||||
if name == ns.Name {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("expected %s in manager snapshot after informer event, got %v", ns.Name, snapshot)
|
||||
}
|
||||
|
||||
record, ok := manager.Get(ns.Name)
|
||||
if !ok {
|
||||
t.Fatalf("expected record for %s in manager", ns.Name)
|
||||
}
|
||||
if record.Phase != NamespacePhaseActive {
|
||||
t.Fatalf("expected active phase after informer add, got %s", record.Phase)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceSubscriberFuncs(t *testing.T) {
|
||||
addCalls := 0
|
||||
removeCalls := 0
|
||||
|
||||
Reference in New Issue
Block a user