diff --git a/CHANGELOG.md b/CHANGELOG.md index 67bd2499..9675164d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Fixed +- Propagate `bgp_attach_ip_to_interface` into per-service config so it attaches BGP-mode Service VIPs to the interface as configured. - Add a configurable kube-vip instance name and use it to isolate internal nftables egress tables, persist table ownership on Services, and migrate per-Service chains without affecting other deployments. Fixes #1634. - Retry on 403 Forbidden and 401 Unauthorized in `ServicesWatcher` at startup with exponential backoff. Fixes #1464. - Reintroduce BGP config via node annotations. Fixes #1488. diff --git a/pkg/instance/instance.go b/pkg/instance/instance.go index ccebfc3d..0b8340e8 100644 --- a/pkg/instance/instance.go +++ b/pkg/instance/instance.go @@ -203,6 +203,7 @@ func NewInstance(ctx context.Context, svc *v1.Service, config *kubevip.Config, SingleNode: true, EnableARP: config.EnableARP, EnableBGP: config.EnableBGP, + BGPAttachIPToInterface: config.BGPAttachIPToInterface, VIPSubnet: subnet, EnableRoutingTable: config.EnableRoutingTable, RoutingTableID: config.RoutingTableID, @@ -269,6 +270,7 @@ func NewInstance(ctx context.Context, svc *v1.Service, config *kubevip.Config, SingleNode: true, EnableARP: config.EnableARP, EnableBGP: config.EnableBGP, + BGPAttachIPToInterface: config.BGPAttachIPToInterface, VIPSubnet: config.VIPSubnet, EnableRoutingTable: config.EnableRoutingTable, RoutingTableID: config.RoutingTableID, diff --git a/pkg/instance/instance_bgp_attach_test.go b/pkg/instance/instance_bgp_attach_test.go new file mode 100644 index 00000000..781cc9c1 --- /dev/null +++ b/pkg/instance/instance_bgp_attach_test.go @@ -0,0 +1,62 @@ +package instance_test + +import ( + "context" + "sync" + "testing" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "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/route" +) + +func TestNewInstance_PropagatesBGPAttachIPToInterface(t *testing.T) { + tests := []struct { + name string + attach bool + }{ + {name: "attach enabled is propagated", attach: true}, + {name: "attach disabled is propagated", attach: false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + globalConfig := &kubevip.Config{ + Interface: "lo", + VIPSubnet: "32", + EnableBGP: true, + BGPAttachIPToInterface: tt.attach, + } + + svc := &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-svc", + Namespace: "default", + Annotations: map[string]string{ + kubevip.LoadbalancerIPAnnotation: "10.0.1.2", + }, + }, + } + + inst, err := instance.NewInstance(context.Background(), svc, globalConfig, + networkinterface.NewManager(), arp.NewManager(globalConfig), route.NewManager(), + nil, &sync.WaitGroup{}) + if err != nil { + t.Fatalf("NewInstance() error = %v", err) + } + + if len(inst.VIPConfigs) != 1 { + t.Fatalf("VIPConfigs len = %d, want 1", len(inst.VIPConfigs)) + } + + if got := inst.VIPConfigs[0].BGPAttachIPToInterface; got != tt.attach { + t.Fatalf("BGPAttachIPToInterface = %t, want %t", got, tt.attach) + } + }) + } +}