Files
kube-vip/pkg/networkinterface/networkinterface_instance_test.go
Marcel Fest d6129c8299 fix(vip): synchronize shared datapath state
Serialize the interface link cache, route tracker and address configuration so
concurrent Services cannot corrupt shared state or deadlock on nested address
locks.

Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2026-09-18 14:20:22 +02:00

66 lines
1.8 KiB
Go

package networkinterface_test
import (
"context"
"sync"
"testing"
"time"
"github.com/kube-vip/kube-vip/pkg/arp"
"github.com/kube-vip/kube-vip/pkg/instance"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/networkinterface"
"github.com/kube-vip/kube-vip/pkg/node/noop"
"github.com/kube-vip/kube-vip/pkg/route"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestManagerReconstructsProductionInstanceConcurrently(t *testing.T) {
config := &kubevip.Config{Interface: "lo", ServicesInterface: "lo", VIPSubnet: "32", DisableServiceUpdates: true}
manager := networkinterface.NewManager()
service := &v1.Service{
ObjectMeta: metav1.ObjectMeta{Name: "service", Namespace: "default", UID: "service"},
Spec: v1.ServiceSpec{LoadBalancerIP: "192.0.2.10"},
}
start := make(chan struct{})
var ready sync.WaitGroup
ready.Add(2)
results := make(chan struct {
instance *instance.Instance
err error
}, 2)
for range 2 {
go func() {
ready.Done()
<-start
instanceConfig := *config
created, err := instance.NewInstance(context.Background(), service.DeepCopy(), &instanceConfig, manager,
arp.NewManager(&instanceConfig), route.NewManager(), noop.NewManager(), &sync.WaitGroup{})
results <- struct {
instance *instance.Instance
err error
}{created, err}
}()
}
ready.Wait()
close(start)
for range 2 {
select {
case result := <-results:
if result.err != nil {
t.Fatalf("NewInstance() error = %v", result.err)
}
if len(result.instance.Clusters) != 1 {
t.Fatalf("cluster count = %d, want 1", len(result.instance.Clusters))
}
case <-time.After(3 * time.Second):
t.Fatal("timed out waiting for concurrent NewInstance calls")
}
}
if got := manager.Len(); got != 1 {
t.Fatalf("cached link count = %d, want 1", got)
}
}