mirror of
https://github.com/cloudnativelabs/kube-router.git
synced 2025-09-27 11:01:11 +02:00
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
376 lines
11 KiB
Go
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)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|