mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 12:43:23 +00:00
Adding Unit tests for windows-dsr and overlay support
This commit is contained in:
parent
22ff6b4918
commit
6186303580
@ -49,6 +49,7 @@ type HcnService interface {
|
|||||||
DsrSupported() error
|
DsrSupported() error
|
||||||
// Policy functions
|
// Policy functions
|
||||||
DeleteAllHnsLoadBalancerPolicy()
|
DeleteAllHnsLoadBalancerPolicy()
|
||||||
|
RemoteSubnetSupported() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type hcnImpl struct{}
|
type hcnImpl struct{}
|
||||||
@ -139,3 +140,7 @@ func (hcnObj hcnImpl) DeleteAllHnsLoadBalancerPolicy() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hcnObj hcnImpl) RemoteSubnetSupported() error {
|
||||||
|
return hcn.RemoteSubnetSupported()
|
||||||
|
}
|
||||||
|
@ -59,6 +59,10 @@ type KernelCompatTester interface {
|
|||||||
IsCompatible() error
|
IsCompatible() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HostMacProvider interface {
|
||||||
|
GetHostMac(nodeIP net.IP) string
|
||||||
|
}
|
||||||
|
|
||||||
// CanUseWinKernelProxier returns true if we should use the Kernel Proxier
|
// CanUseWinKernelProxier returns true if we should use the Kernel Proxier
|
||||||
// instead of the "classic" userspace Proxier. This is determined by checking
|
// instead of the "classic" userspace Proxier. This is determined by checking
|
||||||
// the windows kernel version and for the existence of kernel features.
|
// the windows kernel version and for the existence of kernel features.
|
||||||
@ -723,6 +727,41 @@ func NewProxier(
|
|||||||
}
|
}
|
||||||
|
|
||||||
hcnImpl := newHcnImpl()
|
hcnImpl := newHcnImpl()
|
||||||
|
proxier, err := newProxierInternal(
|
||||||
|
ipFamily,
|
||||||
|
hostname,
|
||||||
|
nodeIP,
|
||||||
|
serviceHealthServer,
|
||||||
|
healthzServer,
|
||||||
|
healthzPort,
|
||||||
|
hcnImpl,
|
||||||
|
&localHostMacProvider{},
|
||||||
|
config,
|
||||||
|
true, // waitForHNSOverlay
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
burstSyncs := 2
|
||||||
|
klog.V(3).InfoS("Record sync param", "minSyncPeriod", minSyncPeriod, "syncPeriod", syncPeriod, "burstSyncs", burstSyncs)
|
||||||
|
proxier.syncRunner = async.NewBoundedFrequencyRunner("sync-runner", proxier.syncProxyRules, minSyncPeriod, syncPeriod, burstSyncs)
|
||||||
|
return proxier, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// allow internal testing of proxier
|
||||||
|
func newProxierInternal(
|
||||||
|
ipFamily v1.IPFamily,
|
||||||
|
hostname string,
|
||||||
|
nodeIP net.IP,
|
||||||
|
serviceHealthServer healthcheck.ServiceHealthServer,
|
||||||
|
healthzServer *healthcheck.ProxyHealthServer,
|
||||||
|
healthzPort int,
|
||||||
|
hcnImpl HcnService,
|
||||||
|
hostMacProvider HostMacProvider,
|
||||||
|
config config.KubeProxyWinkernelConfiguration,
|
||||||
|
waitForHNSOverlay bool,
|
||||||
|
) (*Proxier, error) {
|
||||||
hns, supportedFeatures := newHostNetworkService(hcnImpl)
|
hns, supportedFeatures := newHostNetworkService(hcnImpl)
|
||||||
hnsNetworkName, err := getNetworkName(config.NetworkName)
|
hnsNetworkName, err := getNetworkName(config.NetworkName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -741,7 +780,10 @@ func NewProxier(
|
|||||||
// Network could have been detected before Remote Subnet Routes are applied or ManagementIP is updated
|
// Network could have been detected before Remote Subnet Routes are applied or ManagementIP is updated
|
||||||
// Sleep and update the network to include new information
|
// Sleep and update the network to include new information
|
||||||
if isOverlay(hnsNetworkInfo) {
|
if isOverlay(hnsNetworkInfo) {
|
||||||
time.Sleep(10 * time.Second)
|
if waitForHNSOverlay {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
hnsNetworkInfo, err = hns.getNetworkByName(hnsNetworkName)
|
hnsNetworkInfo, err = hns.getNetworkByName(hnsNetworkName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not find HNS network %s", hnsNetworkName)
|
return nil, fmt.Errorf("could not find HNS network %s", hnsNetworkName)
|
||||||
@ -765,7 +807,7 @@ func NewProxier(
|
|||||||
if !utilfeature.DefaultFeatureGate.Enabled(kubefeatures.WinOverlay) {
|
if !utilfeature.DefaultFeatureGate.Enabled(kubefeatures.WinOverlay) {
|
||||||
return nil, fmt.Errorf("WinOverlay feature gate not enabled")
|
return nil, fmt.Errorf("WinOverlay feature gate not enabled")
|
||||||
}
|
}
|
||||||
err = hcn.RemoteSubnetSupported()
|
err = hcnImpl.RemoteSubnetSupported()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -783,17 +825,8 @@ func NewProxier(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interfaces, _ := net.Interfaces() //TODO create interfaces
|
hostMac = hostMacProvider.GetHostMac(nodeIP)
|
||||||
for _, inter := range interfaces {
|
|
||||||
addresses, _ := inter.Addrs()
|
|
||||||
for _, addr := range addresses {
|
|
||||||
addrIP, _, _ := netutils.ParseCIDRSloppy(addr.String())
|
|
||||||
if addrIP.String() == nodeIP.String() {
|
|
||||||
klog.V(2).InfoS("Record Host MAC address", "addr", inter.HardwareAddr)
|
|
||||||
hostMac = inter.HardwareAddr.String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(hostMac) == 0 {
|
if len(hostMac) == 0 {
|
||||||
return nil, fmt.Errorf("could not find host mac address for %s", nodeIP)
|
return nil, fmt.Errorf("could not find host mac address for %s", nodeIP)
|
||||||
}
|
}
|
||||||
@ -827,9 +860,6 @@ func NewProxier(
|
|||||||
proxier.endpointsChanges = endPointChangeTracker
|
proxier.endpointsChanges = endPointChangeTracker
|
||||||
proxier.serviceChanges = serviceChanges
|
proxier.serviceChanges = serviceChanges
|
||||||
|
|
||||||
burstSyncs := 2
|
|
||||||
klog.V(3).InfoS("Record sync param", "minSyncPeriod", minSyncPeriod, "syncPeriod", syncPeriod, "burstSyncs", burstSyncs)
|
|
||||||
proxier.syncRunner = async.NewBoundedFrequencyRunner("sync-runner", proxier.syncProxyRules, minSyncPeriod, syncPeriod, burstSyncs)
|
|
||||||
return proxier, nil
|
return proxier, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1785,3 +1815,21 @@ func (proxier *Proxier) deleteLoadBalancer(hns HostNetworkService, lbHnsID *stri
|
|||||||
*lbHnsID = ""
|
*lbHnsID = ""
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type localHostMacProvider struct{}
|
||||||
|
|
||||||
|
func (r *localHostMacProvider) GetHostMac(nodeIP net.IP) string {
|
||||||
|
var hostMac string
|
||||||
|
interfaces, _ := net.Interfaces()
|
||||||
|
for _, inter := range interfaces {
|
||||||
|
addresses, _ := inter.Addrs()
|
||||||
|
for _, addr := range addresses {
|
||||||
|
addrIP, _, _ := netutils.ParseCIDRSloppy(addr.String())
|
||||||
|
if addrIP.String() == nodeIP.String() {
|
||||||
|
klog.V(2).InfoS("Record Host MAC address", "addr", inter.HardwareAddr)
|
||||||
|
hostMac = inter.HardwareAddr.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hostMac
|
||||||
|
}
|
||||||
|
@ -25,7 +25,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/Microsoft/hnslib/hcn"
|
"github.com/Microsoft/hnslib/hcn"
|
||||||
|
|
||||||
@ -34,7 +33,11 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
|
kubefeatures "k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/proxy"
|
"k8s.io/kubernetes/pkg/proxy"
|
||||||
|
"k8s.io/kubernetes/pkg/proxy/apis/config"
|
||||||
"k8s.io/kubernetes/pkg/proxy/healthcheck"
|
"k8s.io/kubernetes/pkg/proxy/healthcheck"
|
||||||
fakehcn "k8s.io/kubernetes/pkg/proxy/winkernel/testing"
|
fakehcn "k8s.io/kubernetes/pkg/proxy/winkernel/testing"
|
||||||
netutils "k8s.io/utils/net"
|
netutils "k8s.io/utils/net"
|
||||||
@ -84,8 +87,38 @@ func newHnsNetwork(networkInfo *hnsNetworkInfo) *hcn.HostComputeNetwork {
|
|||||||
return network
|
return network
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFakeProxier(syncPeriod time.Duration, minSyncPeriod time.Duration, hostname string, nodeIP net.IP, networkType string) *Proxier {
|
func NewFakeProxier(t *testing.T, hostname string, nodeIP net.IP, networkType string, enableDSR bool) *Proxier {
|
||||||
sourceVip := "192.168.1.2"
|
sourceVip := "192.168.1.2"
|
||||||
|
|
||||||
|
// enable `WinDSR` feature gate
|
||||||
|
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, kubefeatures.WinDSR, true)
|
||||||
|
|
||||||
|
config := config.KubeProxyWinkernelConfiguration{
|
||||||
|
SourceVip: sourceVip,
|
||||||
|
EnableDSR: enableDSR,
|
||||||
|
NetworkName: testNetwork,
|
||||||
|
ForwardHealthCheckVip: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
hcnMock := getHcnMock(networkType)
|
||||||
|
|
||||||
|
proxier, _ := newProxierInternal(
|
||||||
|
v1.IPv4Protocol,
|
||||||
|
hostname,
|
||||||
|
nodeIP,
|
||||||
|
healthcheck.NewFakeServiceHealthServer(),
|
||||||
|
nil,
|
||||||
|
0,
|
||||||
|
hcnMock,
|
||||||
|
&testHostMacProvider{macAddress: macAddress},
|
||||||
|
config,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
|
||||||
|
return proxier
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHcnMock(networkType string) *fakehcn.HcnMock {
|
||||||
var remoteSubnets []*remoteSubnetInfo
|
var remoteSubnets []*remoteSubnetInfo
|
||||||
rs := &remoteSubnetInfo{
|
rs := &remoteSubnetInfo{
|
||||||
destinationPrefix: destinationPrefix,
|
destinationPrefix: destinationPrefix,
|
||||||
@ -102,37 +135,11 @@ func NewFakeProxier(syncPeriod time.Duration, minSyncPeriod time.Duration, hostn
|
|||||||
}
|
}
|
||||||
hnsNetwork := newHnsNetwork(hnsNetworkInfo)
|
hnsNetwork := newHnsNetwork(hnsNetworkInfo)
|
||||||
hcnMock := fakehcn.NewHcnMock(hnsNetwork)
|
hcnMock := fakehcn.NewHcnMock(hnsNetwork)
|
||||||
proxier := &Proxier{
|
return hcnMock
|
||||||
svcPortMap: make(proxy.ServicePortMap),
|
|
||||||
endpointsMap: make(proxy.EndpointsMap),
|
|
||||||
hostname: testHostName,
|
|
||||||
nodeIP: nodeIP,
|
|
||||||
serviceHealthServer: healthcheck.NewFakeServiceHealthServer(),
|
|
||||||
network: *hnsNetworkInfo,
|
|
||||||
sourceVip: sourceVip,
|
|
||||||
hostMac: macAddress,
|
|
||||||
isDSR: false,
|
|
||||||
hns: &hns{
|
|
||||||
hcn: hcnMock,
|
|
||||||
},
|
|
||||||
hcn: hcnMock,
|
|
||||||
endPointsRefCount: make(endPointsReferenceCountMap),
|
|
||||||
forwardHealthCheckVip: true,
|
|
||||||
mapStaleLoadbalancers: make(map[string]bool),
|
|
||||||
terminatedEndpoints: make(map[string]bool),
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceChanges := proxy.NewServiceChangeTracker(v1.IPv4Protocol, proxier.newServiceInfo, proxier.serviceMapChange)
|
|
||||||
endpointChangeTracker := proxy.NewEndpointsChangeTracker(v1.IPv4Protocol, hostname, proxier.newEndpointInfo, proxier.endpointsMapChange)
|
|
||||||
proxier.endpointsChanges = endpointChangeTracker
|
|
||||||
proxier.serviceChanges = serviceChanges
|
|
||||||
|
|
||||||
return proxier
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateServiceVip(t *testing.T) {
|
func TestCreateServiceVip(t *testing.T) {
|
||||||
syncPeriod := 30 * time.Second
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, true)
|
||||||
proxier := NewFakeProxier(syncPeriod, syncPeriod, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY)
|
|
||||||
if proxier == nil {
|
if proxier == nil {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
@ -185,8 +192,7 @@ func TestCreateServiceVip(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateRemoteEndpointOverlay(t *testing.T) {
|
func TestCreateRemoteEndpointOverlay(t *testing.T) {
|
||||||
syncPeriod := 30 * time.Second
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, false)
|
||||||
proxier := NewFakeProxier(syncPeriod, syncPeriod, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY)
|
|
||||||
if proxier == nil {
|
if proxier == nil {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
@ -250,8 +256,7 @@ func TestCreateRemoteEndpointOverlay(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateRemoteEndpointL2Bridge(t *testing.T) {
|
func TestCreateRemoteEndpointL2Bridge(t *testing.T) {
|
||||||
syncPeriod := 30 * time.Second
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), "L2Bridge", false)
|
||||||
proxier := NewFakeProxier(syncPeriod, syncPeriod, "testhost", netutils.ParseIPSloppy("10.0.0.1"), "L2Bridge")
|
|
||||||
if proxier == nil {
|
if proxier == nil {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
@ -311,9 +316,104 @@ func TestCreateRemoteEndpointL2Bridge(t *testing.T) {
|
|||||||
t.Errorf("Global refCount: %v does not match endpoint refCount: %v", *proxier.endPointsRefCount[endpointGuid1], *epInfo.refCount)
|
t.Errorf("Global refCount: %v does not match endpoint refCount: %v", *proxier.endPointsRefCount[endpointGuid1], *epInfo.refCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDsrEndpointsAreCreatedCorrectly(t *testing.T) {
|
||||||
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, true)
|
||||||
|
if proxier == nil {
|
||||||
|
t.Fatal("Failed to create proxier")
|
||||||
|
}
|
||||||
|
|
||||||
|
svcIP := "10.20.30.41"
|
||||||
|
svcPort := 80
|
||||||
|
svcPortName := proxy.ServicePortName{
|
||||||
|
NamespacedName: makeNSN("ns1", "svc1"),
|
||||||
|
Port: "p80",
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
}
|
||||||
|
|
||||||
|
makeServiceMap(proxier,
|
||||||
|
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
|
||||||
|
svc.Spec.Type = "ClusterIP"
|
||||||
|
svc.Spec.ClusterIP = svcIP
|
||||||
|
svc.Spec.Ports = []v1.ServicePort{{
|
||||||
|
Name: svcPortName.Port,
|
||||||
|
Port: int32(svcPort),
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
populateEndpointSlices(proxier,
|
||||||
|
makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) {
|
||||||
|
eps.AddressType = discovery.AddressTypeIPv4
|
||||||
|
eps.Endpoints = []discovery.Endpoint{{
|
||||||
|
Addresses: []string{epIpAddressRemote},
|
||||||
|
}}
|
||||||
|
eps.Ports = []discovery.EndpointPort{{
|
||||||
|
Name: ptr.To(svcPortName.Port),
|
||||||
|
Port: ptr.To(int32(svcPort)),
|
||||||
|
Protocol: ptr.To(v1.ProtocolTCP),
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
proxier.setInitialized(true)
|
||||||
|
proxier.syncProxyRules()
|
||||||
|
|
||||||
|
ep := proxier.endpointsMap[svcPortName][0]
|
||||||
|
epInfo, ok := ep.(*endpointInfo)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Failed to cast endpointInfo %q", svcPortName.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if epInfo.hnsID == "" {
|
||||||
|
t.Errorf("Expected HNS ID to be set for endpoint %s, but got empty value", epIpAddressRemote)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDsrNotAppliedToClusterTrafficPolicy(t *testing.T) {
|
||||||
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, true)
|
||||||
|
if proxier == nil {
|
||||||
|
t.Fatal("Failed to create proxier")
|
||||||
|
}
|
||||||
|
|
||||||
|
svcIP := "10.20.30.41"
|
||||||
|
svcPort := 80
|
||||||
|
svcPortName := proxy.ServicePortName{
|
||||||
|
NamespacedName: makeNSN("ns1", "svc1"),
|
||||||
|
Port: "p80",
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
}
|
||||||
|
|
||||||
|
makeServiceMap(proxier,
|
||||||
|
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
|
||||||
|
svc.Spec.Type = "ClusterIP"
|
||||||
|
svc.Spec.ClusterIP = svcIP
|
||||||
|
svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyCluster
|
||||||
|
svc.Spec.Ports = []v1.ServicePort{{
|
||||||
|
Name: svcPortName.Port,
|
||||||
|
Port: int32(svcPort),
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
proxier.setInitialized(true)
|
||||||
|
proxier.syncProxyRules()
|
||||||
|
|
||||||
|
svc := proxier.svcPortMap[svcPortName]
|
||||||
|
svcInfo, ok := svc.(*serviceInfo)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Failed to cast serviceInfo %q", svcPortName.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if svcInfo.localTrafficDSR {
|
||||||
|
t.Errorf("Expected localTrafficDSR to be false for ExternalTrafficPolicy=Cluster, but got true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSharedRemoteEndpointDelete(t *testing.T) {
|
func TestSharedRemoteEndpointDelete(t *testing.T) {
|
||||||
syncPeriod := 30 * time.Second
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), "L2Bridge", true)
|
||||||
proxier := NewFakeProxier(syncPeriod, syncPeriod, "testhost", netutils.ParseIPSloppy("10.0.0.1"), "L2Bridge")
|
|
||||||
if proxier == nil {
|
if proxier == nil {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
@ -454,8 +554,7 @@ func TestSharedRemoteEndpointDelete(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestSharedRemoteEndpointUpdate(t *testing.T) {
|
func TestSharedRemoteEndpointUpdate(t *testing.T) {
|
||||||
syncPeriod := 30 * time.Second
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), "L2Bridge", true)
|
||||||
proxier := NewFakeProxier(syncPeriod, syncPeriod, "testhost", netutils.ParseIPSloppy("10.0.0.1"), "L2Bridge")
|
|
||||||
if proxier == nil {
|
if proxier == nil {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
@ -627,9 +726,9 @@ func TestSharedRemoteEndpointUpdate(t *testing.T) {
|
|||||||
t.Errorf("Global refCount: %v does not match endpoint refCount: %v", *proxier.endPointsRefCount[endpointGuid1], *epInfo.refCount)
|
t.Errorf("Global refCount: %v does not match endpoint refCount: %v", *proxier.endPointsRefCount[endpointGuid1], *epInfo.refCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestCreateLoadBalancer(t *testing.T) {
|
|
||||||
syncPeriod := 30 * time.Second
|
func TestCreateLoadBalancerWithoutDSR(t *testing.T) {
|
||||||
proxier := NewFakeProxier(syncPeriod, syncPeriod, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY)
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, false)
|
||||||
if proxier == nil {
|
if proxier == nil {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
@ -677,16 +776,97 @@ func TestCreateLoadBalancer(t *testing.T) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("Failed to cast serviceInfo %q", svcPortName.String())
|
t.Errorf("Failed to cast serviceInfo %q", svcPortName.String())
|
||||||
|
|
||||||
} else {
|
}
|
||||||
if svcInfo.hnsID != loadbalancerGuid1 {
|
|
||||||
t.Errorf("%v does not match %v", svcInfo.hnsID, loadbalancerGuid1)
|
if svcInfo.hnsID != loadbalancerGuid1 {
|
||||||
}
|
t.Errorf("%v does not match %v", svcInfo.hnsID, loadbalancerGuid1)
|
||||||
|
}
|
||||||
|
|
||||||
|
lb, err := proxier.hcn.GetLoadBalancerByID(svcInfo.hnsID)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to fetch loadbalancer: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if lb == nil {
|
||||||
|
t.Errorf("Failed to fetch loadbalancer: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if lb.Flags != hcn.LoadBalancerFlagsNone {
|
||||||
|
t.Errorf("Incorrect loadbalancer flags. Current value: %v", lb.Flags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateLoadBalancerWithDSR(t *testing.T) {
|
||||||
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, true)
|
||||||
|
if proxier == nil {
|
||||||
|
t.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
svcIP := "10.20.30.41"
|
||||||
|
svcPort := 80
|
||||||
|
svcNodePort := 3001
|
||||||
|
svcPortName := proxy.ServicePortName{
|
||||||
|
NamespacedName: makeNSN("ns1", "svc1"),
|
||||||
|
Port: "p80",
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
}
|
||||||
|
|
||||||
|
makeServiceMap(proxier,
|
||||||
|
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
|
||||||
|
svc.Spec.Type = "NodePort"
|
||||||
|
svc.Spec.ClusterIP = svcIP
|
||||||
|
svc.Spec.Ports = []v1.ServicePort{{
|
||||||
|
Name: svcPortName.Port,
|
||||||
|
Port: int32(svcPort),
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
NodePort: int32(svcNodePort),
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
populateEndpointSlices(proxier,
|
||||||
|
makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) {
|
||||||
|
eps.AddressType = discovery.AddressTypeIPv4
|
||||||
|
eps.Endpoints = []discovery.Endpoint{{
|
||||||
|
Addresses: []string{epIpAddressRemote},
|
||||||
|
}}
|
||||||
|
eps.Ports = []discovery.EndpointPort{{
|
||||||
|
Name: ptr.To(svcPortName.Port),
|
||||||
|
Port: ptr.To(int32(svcPort)),
|
||||||
|
Protocol: ptr.To(v1.ProtocolTCP),
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
proxier.setInitialized(true)
|
||||||
|
proxier.syncProxyRules()
|
||||||
|
|
||||||
|
svc := proxier.svcPortMap[svcPortName]
|
||||||
|
svcInfo, ok := svc.(*serviceInfo)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Failed to cast serviceInfo %q", svcPortName.String())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if svcInfo.hnsID != loadbalancerGuid1 {
|
||||||
|
t.Errorf("%v does not match %v", svcInfo.hnsID, loadbalancerGuid1)
|
||||||
|
}
|
||||||
|
|
||||||
|
lb, err := proxier.hcn.GetLoadBalancerByID(svcInfo.hnsID)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to fetch loadbalancer: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if lb == nil {
|
||||||
|
t.Errorf("Failed to fetch loadbalancer: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if lb.Flags != hcn.LoadBalancerFlagsDSR {
|
||||||
|
t.Errorf("Incorrect loadbalancer flags. Current value: %v", lb.Flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateLoadBalancerWhenSupported(t *testing.T) {
|
func TestUpdateLoadBalancerWhenSupported(t *testing.T) {
|
||||||
syncPeriod := 30 * time.Second
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, true)
|
||||||
proxier := NewFakeProxier(syncPeriod, syncPeriod, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY)
|
|
||||||
if proxier == nil {
|
if proxier == nil {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
@ -827,8 +1007,7 @@ func TestUpdateLoadBalancerWhenSupported(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateLoadBalancerWhenUnsupported(t *testing.T) {
|
func TestUpdateLoadBalancerWhenUnsupported(t *testing.T) {
|
||||||
syncPeriod := 30 * time.Second
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, true)
|
||||||
proxier := NewFakeProxier(syncPeriod, syncPeriod, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY)
|
|
||||||
if proxier == nil {
|
if proxier == nil {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
@ -970,8 +1149,7 @@ func TestUpdateLoadBalancerWhenUnsupported(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDsrLoadBalancer(t *testing.T) {
|
func TestCreateDsrLoadBalancer(t *testing.T) {
|
||||||
syncPeriod := 30 * time.Second
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, true)
|
||||||
proxier := NewFakeProxier(syncPeriod, syncPeriod, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY)
|
|
||||||
if proxier == nil {
|
if proxier == nil {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
@ -1038,7 +1216,8 @@ func TestCreateDsrLoadBalancer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
if len(svcInfo.loadBalancerIngressIPs) == 0 {
|
if len(svcInfo.loadBalancerIngressIPs) == 0 {
|
||||||
t.Errorf("svcInfo does not have any loadBalancerIngressIPs, %+v", svcInfo)
|
t.Errorf("svcInfo does not have any loadBalancerIngressIPs, %+v", svcInfo)
|
||||||
} else if svcInfo.loadBalancerIngressIPs[0].healthCheckHnsID != "LBID-4" {
|
}
|
||||||
|
if svcInfo.loadBalancerIngressIPs[0].healthCheckHnsID != "LBID-4" {
|
||||||
t.Errorf("The Hns Loadbalancer HealthCheck Id %v does not match %v. ServicePortName %q", svcInfo.loadBalancerIngressIPs[0].healthCheckHnsID, loadbalancerGuid1, svcPortName.String())
|
t.Errorf("The Hns Loadbalancer HealthCheck Id %v does not match %v. ServicePortName %q", svcInfo.loadBalancerIngressIPs[0].healthCheckHnsID, loadbalancerGuid1, svcPortName.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1048,8 +1227,7 @@ func TestCreateDsrLoadBalancer(t *testing.T) {
|
|||||||
// syncproxyrules only creates ClusterIP Loadbalancer and no NodePort, External IP or IngressIP
|
// syncproxyrules only creates ClusterIP Loadbalancer and no NodePort, External IP or IngressIP
|
||||||
// loadbalancers will be created.
|
// loadbalancers will be created.
|
||||||
func TestClusterIPLBInCreateDsrLoadBalancer(t *testing.T) {
|
func TestClusterIPLBInCreateDsrLoadBalancer(t *testing.T) {
|
||||||
syncPeriod := 30 * time.Second
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, false)
|
||||||
proxier := NewFakeProxier(syncPeriod, syncPeriod, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY)
|
|
||||||
|
|
||||||
if proxier == nil {
|
if proxier == nil {
|
||||||
t.Error()
|
t.Error()
|
||||||
@ -1129,8 +1307,7 @@ func TestClusterIPLBInCreateDsrLoadBalancer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestEndpointSlice(t *testing.T) {
|
func TestEndpointSlice(t *testing.T) {
|
||||||
syncPeriod := 30 * time.Second
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, true)
|
||||||
proxier := NewFakeProxier(syncPeriod, syncPeriod, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY)
|
|
||||||
if proxier == nil {
|
if proxier == nil {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
@ -1210,8 +1387,7 @@ func TestNoopEndpointSlice(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFindRemoteSubnetProviderAddress(t *testing.T) {
|
func TestFindRemoteSubnetProviderAddress(t *testing.T) {
|
||||||
syncPeriod := 30 * time.Second
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, true)
|
||||||
proxier := NewFakeProxier(syncPeriod, syncPeriod, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY)
|
|
||||||
if proxier == nil {
|
if proxier == nil {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
@ -1236,6 +1412,117 @@ func TestFindRemoteSubnetProviderAddress(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWinDSRWithOverlayEnabled(t *testing.T) {
|
||||||
|
proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY, true)
|
||||||
|
if proxier == nil {
|
||||||
|
t.Error("Failed to create proxier")
|
||||||
|
}
|
||||||
|
|
||||||
|
svcIP := "10.20.30.41"
|
||||||
|
svcPort := 80
|
||||||
|
svcNodePort := 3001
|
||||||
|
svcPortName := proxy.ServicePortName{
|
||||||
|
NamespacedName: makeNSN("ns1", "svc1"),
|
||||||
|
Port: "p80",
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
}
|
||||||
|
|
||||||
|
makeServiceMap(proxier,
|
||||||
|
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
|
||||||
|
svc.Spec.Type = "ClusterIP"
|
||||||
|
svc.Spec.ClusterIP = svcIP
|
||||||
|
svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyLocal
|
||||||
|
svc.Spec.Ports = []v1.ServicePort{{
|
||||||
|
Name: svcPortName.Port,
|
||||||
|
Port: int32(svcPort),
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
NodePort: int32(svcNodePort),
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
proxier.setInitialized(true)
|
||||||
|
proxier.syncProxyRules()
|
||||||
|
|
||||||
|
svc := proxier.svcPortMap[svcPortName]
|
||||||
|
svcInfo, ok := svc.(*serviceInfo)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Failed to cast serviceInfo %q", svcPortName.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !svcInfo.localTrafficDSR {
|
||||||
|
t.Errorf("Expected localTrafficDSR to be enabled but got false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDSRFeatureGateValidation(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
enableDSR bool
|
||||||
|
featureGate bool
|
||||||
|
expectFailure bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "DSR enabled but feature gate disabled",
|
||||||
|
enableDSR: true,
|
||||||
|
featureGate: false,
|
||||||
|
expectFailure: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "DSR enabled and feature gate enabled",
|
||||||
|
enableDSR: true,
|
||||||
|
featureGate: true,
|
||||||
|
expectFailure: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "DSR disabled, feature gate does not matter",
|
||||||
|
enableDSR: false,
|
||||||
|
featureGate: false,
|
||||||
|
expectFailure: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
// Mock feature gate
|
||||||
|
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, kubefeatures.WinDSR, tc.featureGate)
|
||||||
|
|
||||||
|
config := config.KubeProxyWinkernelConfiguration{
|
||||||
|
EnableDSR: tc.enableDSR,
|
||||||
|
NetworkName: testNetwork,
|
||||||
|
SourceVip: serviceVip,
|
||||||
|
}
|
||||||
|
|
||||||
|
hostMacProvider := &testHostMacProvider{macAddress: macAddress}
|
||||||
|
|
||||||
|
hcnMock := getHcnMock(NETWORK_TYPE_OVERLAY)
|
||||||
|
|
||||||
|
_, err := newProxierInternal(
|
||||||
|
v1.IPv4Protocol, // ipFamily
|
||||||
|
testHostName, // hostname
|
||||||
|
netutils.ParseIPSloppy("192.168.1.1"), // nodeIP
|
||||||
|
nil, // serviceHealthServer (not needed in this unit test)
|
||||||
|
nil, // healthzServer (not needed in this unit test)
|
||||||
|
0, // healthzPort
|
||||||
|
hcnMock, // hcnImpl
|
||||||
|
hostMacProvider, // hostMacProvider
|
||||||
|
config, // kube-proxy config
|
||||||
|
false, // waitForHNSOverlay
|
||||||
|
)
|
||||||
|
|
||||||
|
if tc.expectFailure {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Expected failure for case %q, but got success", tc.name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected success for case %q, but got error: %v", tc.name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func makeNSN(namespace, name string) types.NamespacedName {
|
func makeNSN(namespace, name string) types.NamespacedName {
|
||||||
return types.NamespacedName{Namespace: namespace, Name: name}
|
return types.NamespacedName{Namespace: namespace, Name: name}
|
||||||
}
|
}
|
||||||
@ -1300,3 +1587,11 @@ func makeTestEndpointSlice(namespace, name string, sliceNum int, epsFunc func(*d
|
|||||||
epsFunc(eps)
|
epsFunc(eps)
|
||||||
return eps
|
return eps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type testHostMacProvider struct {
|
||||||
|
macAddress string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *testHostMacProvider) GetHostMac(nodeIP net.IP) string {
|
||||||
|
return r.macAddress
|
||||||
|
}
|
||||||
|
@ -62,6 +62,7 @@ func NewHcnMock(hnsNetwork *hcn.HostComputeNetwork) *HcnMock {
|
|||||||
V2: true,
|
V2: true,
|
||||||
},
|
},
|
||||||
DSR: true,
|
DSR: true,
|
||||||
|
RemoteSubnet: true,
|
||||||
IPv6DualStack: true,
|
IPv6DualStack: true,
|
||||||
},
|
},
|
||||||
network: hnsNetwork,
|
network: hnsNetwork,
|
||||||
@ -223,3 +224,11 @@ func (hcnObj HcnMock) DeleteAllHnsLoadBalancerPolicy() {
|
|||||||
delete(loadbalancerMap, k)
|
delete(loadbalancerMap, k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hcnObj HcnMock) RemoteSubnetSupported() error {
|
||||||
|
if hcnObj.supportedFeatures.RemoteSubnet {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New("remote Subnet Not Supported")
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user