kube-router/pkg/controllers/routing/ecmp_vip_test.go
Aaron U'Ren 5d7189734e fix(NRC): withdraw advertised VIPs based on annotation
Annotations were taken into account during startup, but after they were
advertised the affect of annotations was only additive because we
were only tracking current state of VIPs that should be advertised and
not taking into account VIPs that should be withdrawn for anything other
than service locality.

Fixes #1491
2023-07-17 08:20:05 -05:00

376 lines
11 KiB
Go

package routing
import (
"context"
"testing"
v1core "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)
// Compare 2 string slices by value.
func Equal(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}
type ServiceAdvertisedIPs struct {
service *v1core.Service
advertisedIPs []string
withdrawnIPs []string
annotations map[string]string
}
func Test_getVIPsForService(t *testing.T) {
services := map[string]*v1core.Service{
"cluster": {
ObjectMeta: metav1.ObjectMeta{
Name: "svc-cluster",
},
Spec: v1core.ServiceSpec{
Type: ClusterIPST,
ClusterIP: "10.0.0.1",
},
},
"external": {
ObjectMeta: metav1.ObjectMeta{
Name: "svc-external",
},
Spec: v1core.ServiceSpec{
Type: ClusterIPST,
ClusterIP: "10.0.0.1",
ExternalIPs: []string{"1.1.1.1"},
},
},
"nodeport": {
ObjectMeta: metav1.ObjectMeta{
Name: "svc-nodeport",
},
Spec: v1core.ServiceSpec{
Type: NodePortST,
ClusterIP: "10.0.0.1",
ExternalIPs: []string{"1.1.1.1"},
},
},
"loadbalancer": {
ObjectMeta: metav1.ObjectMeta{
Name: "svc-loadbalancer",
},
Spec: v1core.ServiceSpec{
Type: LoadBalancerST,
ClusterIP: "10.0.0.1",
ExternalIPs: []string{"1.1.1.1"},
},
Status: v1core.ServiceStatus{
LoadBalancer: v1core.LoadBalancerStatus{
Ingress: []v1core.LoadBalancerIngress{
{
IP: "10.0.255.1",
},
{
IP: "10.0.255.2",
},
},
},
},
},
}
tests := []struct {
name string
// cluster, external, loadbalancer
advertiseSettings [3]bool
serviceAdvertisedIPs []*ServiceAdvertisedIPs
}{
{
name: "advertise all IPs",
advertiseSettings: [3]bool{true, true, true},
serviceAdvertisedIPs: []*ServiceAdvertisedIPs{
{
service: services["cluster"],
advertisedIPs: []string{"10.0.0.1"},
withdrawnIPs: []string{},
annotations: nil,
},
{
service: services["external"],
advertisedIPs: []string{"10.0.0.1", "1.1.1.1"},
withdrawnIPs: []string{},
annotations: nil,
},
{
service: services["nodeport"],
advertisedIPs: []string{"10.0.0.1", "1.1.1.1"},
withdrawnIPs: []string{},
annotations: nil,
},
{
service: services["loadbalancer"],
advertisedIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"},
withdrawnIPs: []string{},
annotations: nil,
},
},
},
{
name: "do not advertise any IPs",
advertiseSettings: [3]bool{false, false, false},
serviceAdvertisedIPs: []*ServiceAdvertisedIPs{
{
service: services["cluster"],
advertisedIPs: []string{},
withdrawnIPs: []string{"10.0.0.1"},
annotations: nil,
},
{
service: services["external"],
advertisedIPs: []string{},
withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"},
annotations: nil,
},
{
service: services["nodeport"],
advertisedIPs: []string{},
withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"},
annotations: nil,
},
{
service: services["loadbalancer"],
advertisedIPs: []string{},
withdrawnIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"},
annotations: nil,
},
},
},
{
name: "advertise cluster IPs",
advertiseSettings: [3]bool{true, false, false},
serviceAdvertisedIPs: []*ServiceAdvertisedIPs{
{
service: services["cluster"],
advertisedIPs: []string{"10.0.0.1"},
withdrawnIPs: []string{},
annotations: nil,
},
{
service: services["external"],
advertisedIPs: []string{"10.0.0.1"},
withdrawnIPs: []string{"1.1.1.1"},
annotations: nil,
},
{
service: services["nodeport"],
advertisedIPs: []string{"10.0.0.1"},
withdrawnIPs: []string{"1.1.1.1"},
annotations: nil,
},
{
service: services["loadbalancer"],
advertisedIPs: []string{"10.0.0.1"},
withdrawnIPs: []string{"1.1.1.1", "10.0.255.1", "10.0.255.2"},
annotations: nil,
},
},
},
{
name: "advertise external IPs",
advertiseSettings: [3]bool{false, true, false},
serviceAdvertisedIPs: []*ServiceAdvertisedIPs{
{
service: services["cluster"],
advertisedIPs: []string{},
withdrawnIPs: []string{"10.0.0.1"},
annotations: nil,
},
{
service: services["external"],
advertisedIPs: []string{"1.1.1.1"},
withdrawnIPs: []string{"10.0.0.1"},
annotations: nil,
},
{
service: services["nodeport"],
advertisedIPs: []string{"1.1.1.1"},
withdrawnIPs: []string{"10.0.0.1"},
annotations: nil,
},
{
service: services["loadbalancer"],
advertisedIPs: []string{"1.1.1.1"},
withdrawnIPs: []string{"10.0.0.1", "10.0.255.1", "10.0.255.2"},
annotations: nil,
},
},
},
{
name: "advertise loadbalancer IPs",
advertiseSettings: [3]bool{false, false, true},
serviceAdvertisedIPs: []*ServiceAdvertisedIPs{
{
service: services["cluster"],
advertisedIPs: []string{},
withdrawnIPs: []string{"10.0.0.1"},
annotations: nil,
},
{
service: services["external"],
advertisedIPs: []string{},
withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"},
annotations: nil,
},
{
service: services["nodeport"],
advertisedIPs: []string{},
withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"},
annotations: nil,
},
{
service: services["loadbalancer"],
advertisedIPs: []string{"10.0.255.1", "10.0.255.2"},
withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"},
annotations: nil,
},
},
},
{
name: "opt in to advertise all IPs via annotations",
advertiseSettings: [3]bool{false, false, false},
serviceAdvertisedIPs: []*ServiceAdvertisedIPs{
{
service: services["cluster"],
advertisedIPs: []string{"10.0.0.1"},
withdrawnIPs: []string{},
annotations: map[string]string{
svcAdvertiseClusterAnnotation: "true",
svcAdvertiseExternalAnnotation: "true",
svcAdvertiseLoadBalancerAnnotation: "true",
},
},
{
service: services["external"],
advertisedIPs: []string{"10.0.0.1", "1.1.1.1"},
withdrawnIPs: []string{},
annotations: map[string]string{
svcAdvertiseClusterAnnotation: "true",
svcAdvertiseExternalAnnotation: "true",
svcAdvertiseLoadBalancerAnnotation: "true",
},
},
{
service: services["nodeport"],
advertisedIPs: []string{"10.0.0.1", "1.1.1.1"},
withdrawnIPs: []string{},
annotations: map[string]string{
svcAdvertiseClusterAnnotation: "true",
svcAdvertiseExternalAnnotation: "true",
svcAdvertiseLoadBalancerAnnotation: "true",
},
},
{
service: services["loadbalancer"],
advertisedIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"},
withdrawnIPs: []string{},
annotations: map[string]string{
svcAdvertiseClusterAnnotation: "true",
svcAdvertiseExternalAnnotation: "true",
svcAdvertiseLoadBalancerAnnotation: "true",
},
},
{
// Special case to test svcAdvertiseLoadBalancerAnnotation vs legacy svcSkipLbIpsAnnotation
service: services["loadbalancer"],
advertisedIPs: []string{"10.0.0.1", "1.1.1.1"},
withdrawnIPs: []string{"10.0.255.1", "10.0.255.2"},
annotations: map[string]string{
svcAdvertiseClusterAnnotation: "true",
svcAdvertiseExternalAnnotation: "true",
svcAdvertiseLoadBalancerAnnotation: "true",
svcSkipLbIpsAnnotation: "true",
},
},
},
},
{
name: "opt out to advertise any IPs via annotations",
advertiseSettings: [3]bool{true, true, true},
serviceAdvertisedIPs: []*ServiceAdvertisedIPs{
{
service: services["cluster"],
advertisedIPs: []string{},
withdrawnIPs: []string{"10.0.0.1"},
annotations: map[string]string{
svcAdvertiseClusterAnnotation: "false",
svcAdvertiseExternalAnnotation: "false",
svcAdvertiseLoadBalancerAnnotation: "false",
},
},
{
service: services["external"],
advertisedIPs: []string{},
withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"},
annotations: map[string]string{
svcAdvertiseClusterAnnotation: "false",
svcAdvertiseExternalAnnotation: "false",
svcAdvertiseLoadBalancerAnnotation: "false",
},
},
{
service: services["nodeport"],
advertisedIPs: []string{},
withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"},
annotations: map[string]string{
svcAdvertiseClusterAnnotation: "false",
svcAdvertiseExternalAnnotation: "false",
svcAdvertiseLoadBalancerAnnotation: "false",
},
},
{
service: services["loadbalancer"],
advertisedIPs: []string{},
withdrawnIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"},
annotations: map[string]string{
svcAdvertiseClusterAnnotation: "false",
svcAdvertiseExternalAnnotation: "false",
svcAdvertiseLoadBalancerAnnotation: "false",
},
},
},
},
}
for _, test := range tests {
nrc := NetworkRoutingController{}
t.Run(test.name, func(t *testing.T) {
nrc.advertiseClusterIP = test.advertiseSettings[0]
nrc.advertiseExternalIP = test.advertiseSettings[1]
nrc.advertiseLoadBalancerIP = test.advertiseSettings[2]
for _, serviceAdvertisedIP := range test.serviceAdvertisedIPs {
clientset := fake.NewSimpleClientset()
if serviceAdvertisedIP.annotations != nil {
serviceAdvertisedIP.service.ObjectMeta.Annotations = serviceAdvertisedIP.annotations
}
svc, _ := clientset.CoreV1().Services("default").Create(context.Background(), serviceAdvertisedIP.service, metav1.CreateOptions{})
advertisedIPs, withdrawnIPs, _ := nrc.getVIPsForService(svc, false)
t.Logf("AdvertisedIPs: %v\n", advertisedIPs)
t.Logf("WithdrawnIPs: %v\n", withdrawnIPs)
if !Equal(serviceAdvertisedIP.advertisedIPs, advertisedIPs) {
t.Errorf("Advertised IPs are incorrect, got: %v, want: %v.", advertisedIPs, serviceAdvertisedIP.advertisedIPs)
}
if !Equal(serviceAdvertisedIP.withdrawnIPs, withdrawnIPs) {
t.Errorf("Withdrawn IPs are incorrect, got: %v, want: %v.", withdrawnIPs, serviceAdvertisedIP.withdrawnIPs)
}
}
})
}
}