k8s.io/kubernetes@v1.29.3/pkg/proxy/winkernel/proxier_test.go (about) 1 //go:build windows 2 // +build windows 3 4 /* 5 Copyright 2021 The Kubernetes Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 package winkernel 21 22 import ( 23 "encoding/json" 24 "fmt" 25 "net" 26 "strings" 27 "testing" 28 "time" 29 30 "github.com/Microsoft/hcsshim/hcn" 31 v1 "k8s.io/api/core/v1" 32 discovery "k8s.io/api/discovery/v1" 33 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 34 "k8s.io/apimachinery/pkg/types" 35 "k8s.io/apimachinery/pkg/util/intstr" 36 "k8s.io/kubernetes/pkg/proxy" 37 "k8s.io/kubernetes/pkg/proxy/healthcheck" 38 fakehcn "k8s.io/kubernetes/pkg/proxy/winkernel/testing" 39 netutils "k8s.io/utils/net" 40 "k8s.io/utils/ptr" 41 ) 42 43 const ( 44 testHostName = "test-hostname" 45 testNetwork = "TestNetwork" 46 ipAddress = "10.0.0.1" 47 prefixLen = 24 48 macAddress = "00-11-22-33-44-55" 49 clusterCIDR = "192.168.1.0/24" 50 destinationPrefix = "192.168.2.0/24" 51 providerAddress = "10.0.0.3" 52 guid = "123ABC" 53 endpointGuid1 = "EPID-1" 54 loadbalancerGuid1 = "LBID-1" 55 endpointLocal = "EP-LOCAL" 56 endpointGw = "EP-GW" 57 epIpAddressGw = "192.168.2.1" 58 epMacAddressGw = "00-11-22-33-44-66" 59 ) 60 61 func newHnsNetwork(networkInfo *hnsNetworkInfo) *hcn.HostComputeNetwork { 62 var policies []hcn.NetworkPolicy 63 for _, remoteSubnet := range networkInfo.remoteSubnets { 64 policySettings := hcn.RemoteSubnetRoutePolicySetting{ 65 DestinationPrefix: remoteSubnet.destinationPrefix, 66 IsolationId: remoteSubnet.isolationID, 67 ProviderAddress: remoteSubnet.providerAddress, 68 DistributedRouterMacAddress: remoteSubnet.drMacAddress, 69 } 70 settings, _ := json.Marshal(policySettings) 71 policy := hcn.NetworkPolicy{ 72 Type: hcn.RemoteSubnetRoute, 73 Settings: settings, 74 } 75 policies = append(policies, policy) 76 } 77 78 network := &hcn.HostComputeNetwork{ 79 Id: networkInfo.id, 80 Name: networkInfo.name, 81 Type: hcn.NetworkType(networkInfo.networkType), 82 Policies: policies, 83 } 84 return network 85 } 86 87 func NewFakeProxier(syncPeriod time.Duration, minSyncPeriod time.Duration, clusterCIDR string, hostname string, nodeIP net.IP, networkType string) *Proxier { 88 sourceVip := "192.168.1.2" 89 var remoteSubnets []*remoteSubnetInfo 90 rs := &remoteSubnetInfo{ 91 destinationPrefix: destinationPrefix, 92 isolationID: 4096, 93 providerAddress: providerAddress, 94 drMacAddress: macAddress, 95 } 96 remoteSubnets = append(remoteSubnets, rs) 97 hnsNetworkInfo := &hnsNetworkInfo{ 98 id: strings.ToUpper(guid), 99 name: testNetwork, 100 networkType: networkType, 101 remoteSubnets: remoteSubnets, 102 } 103 hnsNetwork := newHnsNetwork(hnsNetworkInfo) 104 hcnMock := fakehcn.NewHcnMock(hnsNetwork) 105 proxier := &Proxier{ 106 svcPortMap: make(proxy.ServicePortMap), 107 endpointsMap: make(proxy.EndpointsMap), 108 clusterCIDR: clusterCIDR, 109 hostname: testHostName, 110 nodeIP: nodeIP, 111 serviceHealthServer: healthcheck.NewFakeServiceHealthServer(), 112 network: *hnsNetworkInfo, 113 sourceVip: sourceVip, 114 hostMac: macAddress, 115 isDSR: false, 116 hns: &hns{ 117 hcn: hcnMock, 118 }, 119 hcn: hcnMock, 120 endPointsRefCount: make(endPointsReferenceCountMap), 121 forwardHealthCheckVip: true, 122 mapStaleLoadbalancers: make(map[string]bool), 123 } 124 125 serviceChanges := proxy.NewServiceChangeTracker(proxier.newServiceInfo, v1.IPv4Protocol, nil, proxier.serviceMapChange) 126 endpointsChangeTracker := proxy.NewEndpointsChangeTracker(hostname, proxier.newEndpointInfo, v1.IPv4Protocol, nil, proxier.endpointsMapChange) 127 proxier.endpointsChanges = endpointsChangeTracker 128 proxier.serviceChanges = serviceChanges 129 130 return proxier 131 } 132 133 func TestCreateServiceVip(t *testing.T) { 134 syncPeriod := 30 * time.Second 135 proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY) 136 if proxier == nil { 137 t.Error() 138 } 139 140 svcIP := "10.20.30.41" 141 svcPort := 80 142 svcNodePort := 3001 143 svcExternalIPs := "50.60.70.81" 144 svcPortName := proxy.ServicePortName{ 145 NamespacedName: makeNSN("ns1", "svc1"), 146 Port: "p80", 147 Protocol: v1.ProtocolTCP, 148 } 149 150 makeServiceMap(proxier, 151 makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) { 152 svc.Spec.Type = "NodePort" 153 svc.Spec.ClusterIP = svcIP 154 svc.Spec.ExternalIPs = []string{svcExternalIPs} 155 svc.Spec.SessionAffinity = v1.ServiceAffinityClientIP 156 svc.Spec.SessionAffinityConfig = &v1.SessionAffinityConfig{ 157 ClientIP: &v1.ClientIPConfig{ 158 TimeoutSeconds: ptr.To[int32](v1.DefaultClientIPServiceAffinitySeconds), 159 }, 160 } 161 svc.Spec.Ports = []v1.ServicePort{{ 162 Name: svcPortName.Port, 163 Port: int32(svcPort), 164 Protocol: v1.ProtocolTCP, 165 NodePort: int32(svcNodePort), 166 }} 167 }), 168 ) 169 proxier.setInitialized(true) 170 proxier.syncProxyRules() 171 172 svc := proxier.svcPortMap[svcPortName] 173 svcInfo, ok := svc.(*serviceInfo) 174 if !ok { 175 t.Errorf("Failed to cast serviceInfo %q", svcPortName.String()) 176 177 } else { 178 if svcInfo.remoteEndpoint == nil { 179 t.Error() 180 } 181 if svcInfo.remoteEndpoint.ip != svcIP { 182 t.Error() 183 } 184 } 185 } 186 187 func TestCreateRemoteEndpointOverlay(t *testing.T) { 188 syncPeriod := 30 * time.Second 189 proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY) 190 if proxier == nil { 191 t.Error() 192 } 193 194 svcIP := "10.20.30.41" 195 svcPort := 80 196 svcNodePort := 3001 197 svcPortName := proxy.ServicePortName{ 198 NamespacedName: makeNSN("ns1", "svc1"), 199 Port: "p80", 200 Protocol: v1.ProtocolTCP, 201 } 202 203 makeServiceMap(proxier, 204 makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) { 205 svc.Spec.Type = "NodePort" 206 svc.Spec.ClusterIP = svcIP 207 svc.Spec.Ports = []v1.ServicePort{{ 208 Name: svcPortName.Port, 209 Port: int32(svcPort), 210 Protocol: v1.ProtocolTCP, 211 NodePort: int32(svcNodePort), 212 }} 213 }), 214 ) 215 populateEndpointSlices(proxier, 216 makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) { 217 eps.AddressType = discovery.AddressTypeIPv4 218 eps.Endpoints = []discovery.Endpoint{{ 219 Addresses: []string{epIpAddressRemote}, 220 }} 221 eps.Ports = []discovery.EndpointPort{{ 222 Name: ptr.To(svcPortName.Port), 223 Port: ptr.To(int32(svcPort)), 224 Protocol: ptr.To(v1.ProtocolTCP), 225 }} 226 }), 227 ) 228 229 proxier.setInitialized(true) 230 proxier.syncProxyRules() 231 232 ep := proxier.endpointsMap[svcPortName][0] 233 epInfo, ok := ep.(*endpointInfo) 234 if !ok { 235 t.Errorf("Failed to cast endpointInfo %q", svcPortName.String()) 236 237 } else { 238 if epInfo.hnsID != "EPID-3" { 239 t.Errorf("%v does not match %v", epInfo.hnsID, endpointGuid1) 240 } 241 } 242 243 if *proxier.endPointsRefCount["EPID-3"] <= 0 { 244 t.Errorf("RefCount not incremented. Current value: %v", *proxier.endPointsRefCount[endpointGuid1]) 245 } 246 247 if *proxier.endPointsRefCount["EPID-3"] != *epInfo.refCount { 248 t.Errorf("Global refCount: %v does not match endpoint refCount: %v", *proxier.endPointsRefCount[endpointGuid1], *epInfo.refCount) 249 } 250 } 251 252 func TestCreateRemoteEndpointL2Bridge(t *testing.T) { 253 syncPeriod := 30 * time.Second 254 proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", netutils.ParseIPSloppy("10.0.0.1"), "L2Bridge") 255 if proxier == nil { 256 t.Error() 257 } 258 259 svcIP := "10.20.30.41" 260 svcPort := 80 261 svcNodePort := 3001 262 svcPortName := proxy.ServicePortName{ 263 NamespacedName: makeNSN("ns1", "svc1"), 264 Port: "p80", 265 Protocol: v1.ProtocolTCP, 266 } 267 268 makeServiceMap(proxier, 269 makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) { 270 svc.Spec.Type = "NodePort" 271 svc.Spec.ClusterIP = svcIP 272 svc.Spec.Ports = []v1.ServicePort{{ 273 Name: svcPortName.Port, 274 Port: int32(svcPort), 275 Protocol: v1.ProtocolTCP, 276 NodePort: int32(svcNodePort), 277 }} 278 }), 279 ) 280 populateEndpointSlices(proxier, 281 makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) { 282 eps.AddressType = discovery.AddressTypeIPv4 283 eps.Endpoints = []discovery.Endpoint{{ 284 Addresses: []string{epIpAddressRemote}, 285 }} 286 eps.Ports = []discovery.EndpointPort{{ 287 Name: ptr.To(svcPortName.Port), 288 Port: ptr.To(int32(svcPort)), 289 Protocol: ptr.To(v1.ProtocolTCP), 290 }} 291 }), 292 ) 293 proxier.setInitialized(true) 294 proxier.syncProxyRules() 295 ep := proxier.endpointsMap[svcPortName][0] 296 epInfo, ok := ep.(*endpointInfo) 297 if !ok { 298 t.Errorf("Failed to cast endpointInfo %q", svcPortName.String()) 299 300 } else { 301 if epInfo.hnsID != endpointGuid1 { 302 t.Errorf("%v does not match %v", epInfo.hnsID, endpointGuid1) 303 } 304 } 305 306 if *proxier.endPointsRefCount[endpointGuid1] <= 0 { 307 t.Errorf("RefCount not incremented. Current value: %v", *proxier.endPointsRefCount[endpointGuid1]) 308 } 309 310 if *proxier.endPointsRefCount[endpointGuid1] != *epInfo.refCount { 311 t.Errorf("Global refCount: %v does not match endpoint refCount: %v", *proxier.endPointsRefCount[endpointGuid1], *epInfo.refCount) 312 } 313 } 314 func TestSharedRemoteEndpointDelete(t *testing.T) { 315 syncPeriod := 30 * time.Second 316 proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", netutils.ParseIPSloppy("10.0.0.1"), "L2Bridge") 317 if proxier == nil { 318 t.Error() 319 } 320 321 svcIP1 := "10.20.30.41" 322 svcPort1 := 80 323 svcNodePort1 := 3001 324 svcPortName1 := proxy.ServicePortName{ 325 NamespacedName: makeNSN("ns1", "svc1"), 326 Port: "p80", 327 Protocol: v1.ProtocolTCP, 328 } 329 330 svcIP2 := "10.20.30.42" 331 svcPort2 := 80 332 svcNodePort2 := 3002 333 svcPortName2 := proxy.ServicePortName{ 334 NamespacedName: makeNSN("ns1", "svc2"), 335 Port: "p80", 336 Protocol: v1.ProtocolTCP, 337 } 338 339 makeServiceMap(proxier, 340 makeTestService(svcPortName1.Namespace, svcPortName1.Name, func(svc *v1.Service) { 341 svc.Spec.Type = "NodePort" 342 svc.Spec.ClusterIP = svcIP1 343 svc.Spec.Ports = []v1.ServicePort{{ 344 Name: svcPortName1.Port, 345 Port: int32(svcPort1), 346 Protocol: v1.ProtocolTCP, 347 NodePort: int32(svcNodePort1), 348 }} 349 }), 350 makeTestService(svcPortName2.Namespace, svcPortName2.Name, func(svc *v1.Service) { 351 svc.Spec.Type = "NodePort" 352 svc.Spec.ClusterIP = svcIP2 353 svc.Spec.Ports = []v1.ServicePort{{ 354 Name: svcPortName2.Port, 355 Port: int32(svcPort2), 356 Protocol: v1.ProtocolTCP, 357 NodePort: int32(svcNodePort2), 358 }} 359 }), 360 ) 361 populateEndpointSlices(proxier, 362 makeTestEndpointSlice(svcPortName1.Namespace, svcPortName1.Name, 1, func(eps *discovery.EndpointSlice) { 363 eps.AddressType = discovery.AddressTypeIPv4 364 eps.Endpoints = []discovery.Endpoint{{ 365 Addresses: []string{epIpAddressRemote}, 366 }} 367 eps.Ports = []discovery.EndpointPort{{ 368 Name: ptr.To(svcPortName1.Port), 369 Port: ptr.To(int32(svcPort1)), 370 Protocol: ptr.To(v1.ProtocolTCP), 371 }} 372 }), 373 makeTestEndpointSlice(svcPortName2.Namespace, svcPortName2.Name, 1, func(eps *discovery.EndpointSlice) { 374 eps.AddressType = discovery.AddressTypeIPv4 375 eps.Endpoints = []discovery.Endpoint{{ 376 Addresses: []string{epIpAddressRemote}, 377 }} 378 eps.Ports = []discovery.EndpointPort{{ 379 Name: ptr.To(svcPortName2.Port), 380 Port: ptr.To(int32(svcPort2)), 381 Protocol: ptr.To(v1.ProtocolTCP), 382 }} 383 }), 384 ) 385 proxier.setInitialized(true) 386 proxier.syncProxyRules() 387 ep := proxier.endpointsMap[svcPortName1][0] 388 epInfo, ok := ep.(*endpointInfo) 389 if !ok { 390 t.Errorf("Failed to cast endpointInfo %q", svcPortName1.String()) 391 392 } else { 393 if epInfo.hnsID != endpointGuid1 { 394 t.Errorf("%v does not match %v", epInfo.hnsID, endpointGuid1) 395 } 396 } 397 398 if *proxier.endPointsRefCount[endpointGuid1] != 2 { 399 t.Errorf("RefCount not incremented. Current value: %v", *proxier.endPointsRefCount[endpointGuid1]) 400 } 401 402 if *proxier.endPointsRefCount[endpointGuid1] != *epInfo.refCount { 403 t.Errorf("Global refCount: %v does not match endpoint refCount: %v", *proxier.endPointsRefCount[endpointGuid1], *epInfo.refCount) 404 } 405 406 proxier.setInitialized(false) 407 deleteServices(proxier, 408 makeTestService(svcPortName2.Namespace, svcPortName2.Name, func(svc *v1.Service) { 409 svc.Spec.Type = "NodePort" 410 svc.Spec.ClusterIP = svcIP2 411 svc.Spec.Ports = []v1.ServicePort{{ 412 Name: svcPortName2.Port, 413 Port: int32(svcPort2), 414 Protocol: v1.ProtocolTCP, 415 NodePort: int32(svcNodePort2), 416 }} 417 }), 418 ) 419 420 deleteEndpointSlices(proxier, 421 makeTestEndpointSlice(svcPortName2.Namespace, svcPortName2.Name, 1, func(eps *discovery.EndpointSlice) { 422 eps.AddressType = discovery.AddressTypeIPv4 423 eps.Endpoints = []discovery.Endpoint{{ 424 Addresses: []string{epIpAddressRemote}, 425 }} 426 eps.Ports = []discovery.EndpointPort{{ 427 Name: ptr.To(svcPortName2.Port), 428 Port: ptr.To(int32(svcPort2)), 429 Protocol: ptr.To(v1.ProtocolTCP), 430 }} 431 }), 432 ) 433 434 proxier.setInitialized(true) 435 proxier.syncProxyRules() 436 437 ep = proxier.endpointsMap[svcPortName1][0] 438 epInfo, ok = ep.(*endpointInfo) 439 if !ok { 440 t.Errorf("Failed to cast endpointInfo %q", svcPortName1.String()) 441 442 } else { 443 if epInfo.hnsID != endpointGuid1 { 444 t.Errorf("%v does not match %v", epInfo.hnsID, endpointGuid1) 445 } 446 } 447 448 if *epInfo.refCount != 1 { 449 t.Errorf("Incorrect Refcount. Current value: %v", *epInfo.refCount) 450 } 451 452 if *proxier.endPointsRefCount[endpointGuid1] != *epInfo.refCount { 453 t.Errorf("Global refCount: %v does not match endpoint refCount: %v", *proxier.endPointsRefCount[endpointGuid1], *epInfo.refCount) 454 } 455 } 456 func TestSharedRemoteEndpointUpdate(t *testing.T) { 457 syncPeriod := 30 * time.Second 458 proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", netutils.ParseIPSloppy("10.0.0.1"), "L2Bridge") 459 if proxier == nil { 460 t.Error() 461 } 462 463 svcIP1 := "10.20.30.41" 464 svcPort1 := 80 465 svcNodePort1 := 3001 466 svcPortName1 := proxy.ServicePortName{ 467 NamespacedName: makeNSN("ns1", "svc1"), 468 Port: "p80", 469 Protocol: v1.ProtocolTCP, 470 } 471 472 svcIP2 := "10.20.30.42" 473 svcPort2 := 80 474 svcNodePort2 := 3002 475 svcPortName2 := proxy.ServicePortName{ 476 NamespacedName: makeNSN("ns1", "svc2"), 477 Port: "p80", 478 Protocol: v1.ProtocolTCP, 479 } 480 481 makeServiceMap(proxier, 482 makeTestService(svcPortName1.Namespace, svcPortName1.Name, func(svc *v1.Service) { 483 svc.Spec.Type = "NodePort" 484 svc.Spec.ClusterIP = svcIP1 485 svc.Spec.Ports = []v1.ServicePort{{ 486 Name: svcPortName1.Port, 487 Port: int32(svcPort1), 488 Protocol: v1.ProtocolTCP, 489 NodePort: int32(svcNodePort1), 490 }} 491 }), 492 makeTestService(svcPortName2.Namespace, svcPortName2.Name, func(svc *v1.Service) { 493 svc.Spec.Type = "NodePort" 494 svc.Spec.ClusterIP = svcIP2 495 svc.Spec.Ports = []v1.ServicePort{{ 496 Name: svcPortName2.Port, 497 Port: int32(svcPort2), 498 Protocol: v1.ProtocolTCP, 499 NodePort: int32(svcNodePort2), 500 }} 501 }), 502 ) 503 504 populateEndpointSlices(proxier, 505 makeTestEndpointSlice(svcPortName1.Namespace, svcPortName1.Name, 1, func(eps *discovery.EndpointSlice) { 506 eps.AddressType = discovery.AddressTypeIPv4 507 eps.Endpoints = []discovery.Endpoint{{ 508 Addresses: []string{epIpAddressRemote}, 509 }} 510 eps.Ports = []discovery.EndpointPort{{ 511 Name: ptr.To(svcPortName1.Port), 512 Port: ptr.To(int32(svcPort1)), 513 Protocol: ptr.To(v1.ProtocolTCP), 514 }} 515 }), 516 makeTestEndpointSlice(svcPortName2.Namespace, svcPortName2.Name, 1, func(eps *discovery.EndpointSlice) { 517 eps.AddressType = discovery.AddressTypeIPv4 518 eps.Endpoints = []discovery.Endpoint{{ 519 Addresses: []string{epIpAddressRemote}, 520 }} 521 eps.Ports = []discovery.EndpointPort{{ 522 Name: ptr.To(svcPortName2.Port), 523 Port: ptr.To(int32(svcPort2)), 524 Protocol: ptr.To(v1.ProtocolTCP), 525 }} 526 }), 527 ) 528 529 proxier.setInitialized(true) 530 proxier.syncProxyRules() 531 ep := proxier.endpointsMap[svcPortName1][0] 532 epInfo, ok := ep.(*endpointInfo) 533 if !ok { 534 t.Errorf("Failed to cast endpointInfo %q", svcPortName1.String()) 535 536 } else { 537 if epInfo.hnsID != endpointGuid1 { 538 t.Errorf("%v does not match %v", epInfo.hnsID, endpointGuid1) 539 } 540 } 541 542 if *proxier.endPointsRefCount[endpointGuid1] != 2 { 543 t.Errorf("RefCount not incremented. Current value: %v", *proxier.endPointsRefCount[endpointGuid1]) 544 } 545 546 if *proxier.endPointsRefCount[endpointGuid1] != *epInfo.refCount { 547 t.Errorf("Global refCount: %v does not match endpoint refCount: %v", *proxier.endPointsRefCount[endpointGuid1], *epInfo.refCount) 548 } 549 550 proxier.setInitialized(false) 551 552 proxier.OnServiceUpdate( 553 makeTestService(svcPortName1.Namespace, svcPortName1.Name, func(svc *v1.Service) { 554 svc.Spec.Type = "NodePort" 555 svc.Spec.ClusterIP = svcIP1 556 svc.Spec.Ports = []v1.ServicePort{{ 557 Name: svcPortName1.Port, 558 Port: int32(svcPort1), 559 Protocol: v1.ProtocolTCP, 560 NodePort: int32(svcNodePort1), 561 }} 562 }), 563 makeTestService(svcPortName1.Namespace, svcPortName1.Name, func(svc *v1.Service) { 564 svc.Spec.Type = "NodePort" 565 svc.Spec.ClusterIP = svcIP1 566 svc.Spec.Ports = []v1.ServicePort{{ 567 Name: svcPortName1.Port, 568 Port: int32(svcPort1), 569 Protocol: v1.ProtocolTCP, 570 NodePort: int32(3003), 571 }} 572 })) 573 574 proxier.OnEndpointSliceUpdate( 575 makeTestEndpointSlice(svcPortName1.Namespace, svcPortName1.Name, 1, func(eps *discovery.EndpointSlice) { 576 eps.AddressType = discovery.AddressTypeIPv4 577 eps.Endpoints = []discovery.Endpoint{{ 578 Addresses: []string{epIpAddressRemote}, 579 }} 580 eps.Ports = []discovery.EndpointPort{{ 581 Name: ptr.To(svcPortName1.Port), 582 Port: ptr.To(int32(svcPort1)), 583 Protocol: ptr.To(v1.ProtocolTCP), 584 }} 585 }), 586 makeTestEndpointSlice(svcPortName1.Namespace, svcPortName1.Name, 1, func(eps *discovery.EndpointSlice) { 587 eps.AddressType = discovery.AddressTypeIPv4 588 eps.Endpoints = []discovery.Endpoint{{ 589 Addresses: []string{epIpAddressRemote}, 590 }} 591 eps.Ports = []discovery.EndpointPort{{ 592 Name: ptr.To(svcPortName1.Port), 593 Port: ptr.To(int32(svcPort1)), 594 Protocol: ptr.To(v1.ProtocolTCP), 595 }, 596 { 597 Name: ptr.To("p443"), 598 Port: ptr.To[int32](443), 599 Protocol: ptr.To(v1.ProtocolTCP), 600 }} 601 })) 602 603 proxier.mu.Lock() 604 proxier.endpointSlicesSynced = true 605 proxier.mu.Unlock() 606 607 proxier.setInitialized(true) 608 proxier.syncProxyRules() 609 610 ep = proxier.endpointsMap[svcPortName1][0] 611 epInfo, ok = ep.(*endpointInfo) 612 613 if !ok { 614 t.Errorf("Failed to cast endpointInfo %q", svcPortName1.String()) 615 616 } else { 617 if epInfo.hnsID != endpointGuid1 { 618 t.Errorf("%v does not match %v", epInfo.hnsID, endpointGuid1) 619 } 620 } 621 622 if *epInfo.refCount != 2 { 623 t.Errorf("Incorrect refcount. Current value: %v", *epInfo.refCount) 624 } 625 626 if *proxier.endPointsRefCount[endpointGuid1] != *epInfo.refCount { 627 t.Errorf("Global refCount: %v does not match endpoint refCount: %v", *proxier.endPointsRefCount[endpointGuid1], *epInfo.refCount) 628 } 629 } 630 func TestCreateLoadBalancer(t *testing.T) { 631 syncPeriod := 30 * time.Second 632 proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY) 633 if proxier == nil { 634 t.Error() 635 } 636 637 svcIP := "10.20.30.41" 638 svcPort := 80 639 svcNodePort := 3001 640 svcPortName := proxy.ServicePortName{ 641 NamespacedName: makeNSN("ns1", "svc1"), 642 Port: "p80", 643 Protocol: v1.ProtocolTCP, 644 } 645 646 makeServiceMap(proxier, 647 makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) { 648 svc.Spec.Type = "NodePort" 649 svc.Spec.ClusterIP = svcIP 650 svc.Spec.Ports = []v1.ServicePort{{ 651 Name: svcPortName.Port, 652 Port: int32(svcPort), 653 Protocol: v1.ProtocolTCP, 654 NodePort: int32(svcNodePort), 655 }} 656 }), 657 ) 658 populateEndpointSlices(proxier, 659 makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) { 660 eps.AddressType = discovery.AddressTypeIPv4 661 eps.Endpoints = []discovery.Endpoint{{ 662 Addresses: []string{epIpAddressRemote}, 663 }} 664 eps.Ports = []discovery.EndpointPort{{ 665 Name: ptr.To(svcPortName.Port), 666 Port: ptr.To(int32(svcPort)), 667 Protocol: ptr.To(v1.ProtocolTCP), 668 }} 669 }), 670 ) 671 672 proxier.setInitialized(true) 673 proxier.syncProxyRules() 674 675 svc := proxier.svcPortMap[svcPortName] 676 svcInfo, ok := svc.(*serviceInfo) 677 if !ok { 678 t.Errorf("Failed to cast serviceInfo %q", svcPortName.String()) 679 680 } else { 681 if svcInfo.hnsID != loadbalancerGuid1 { 682 t.Errorf("%v does not match %v", svcInfo.hnsID, loadbalancerGuid1) 683 } 684 } 685 } 686 687 func TestCreateDsrLoadBalancer(t *testing.T) { 688 syncPeriod := 30 * time.Second 689 proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY) 690 if proxier == nil { 691 t.Error() 692 } 693 694 svcIP := "10.20.30.41" 695 svcPort := 80 696 svcNodePort := 3001 697 svcPortName := proxy.ServicePortName{ 698 NamespacedName: makeNSN("ns1", "svc1"), 699 Port: "p80", 700 Protocol: v1.ProtocolTCP, 701 } 702 lbIP := "11.21.31.41" 703 704 makeServiceMap(proxier, 705 makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) { 706 svc.Spec.Type = "NodePort" 707 svc.Spec.ClusterIP = svcIP 708 svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyLocal 709 svc.Spec.Ports = []v1.ServicePort{{ 710 Name: svcPortName.Port, 711 Port: int32(svcPort), 712 Protocol: v1.ProtocolTCP, 713 NodePort: int32(svcNodePort), 714 }} 715 svc.Status.LoadBalancer.Ingress = []v1.LoadBalancerIngress{{ 716 IP: lbIP, 717 }} 718 }), 719 ) 720 populateEndpointSlices(proxier, 721 makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) { 722 eps.AddressType = discovery.AddressTypeIPv4 723 eps.Endpoints = []discovery.Endpoint{{ 724 Addresses: []string{epIpAddressRemote}, 725 NodeName: ptr.To("testhost"), 726 }} 727 eps.Ports = []discovery.EndpointPort{{ 728 Name: ptr.To(svcPortName.Port), 729 Port: ptr.To(int32(svcPort)), 730 Protocol: ptr.To(v1.ProtocolTCP), 731 }} 732 }), 733 ) 734 735 hcn := (proxier.hcn).(*fakehcn.HcnMock) 736 proxier.rootHnsEndpointName = endpointGw 737 hcn.PopulateQueriedEndpoints(endpointLocal, guid, epIpAddressRemote, macAddress, prefixLen) 738 hcn.PopulateQueriedEndpoints(endpointGw, guid, epIpAddressGw, epMacAddressGw, prefixLen) 739 proxier.setInitialized(true) 740 proxier.syncProxyRules() 741 742 svc := proxier.svcPortMap[svcPortName] 743 svcInfo, ok := svc.(*serviceInfo) 744 if !ok { 745 t.Errorf("Failed to cast serviceInfo %q", svcPortName.String()) 746 747 } else { 748 if svcInfo.hnsID != loadbalancerGuid1 { 749 t.Errorf("%v does not match %v", svcInfo.hnsID, loadbalancerGuid1) 750 } 751 if svcInfo.localTrafficDSR != true { 752 t.Errorf("Failed to create DSR loadbalancer with local traffic policy") 753 } 754 if len(svcInfo.loadBalancerIngressIPs) == 0 { 755 t.Errorf("svcInfo does not have any loadBalancerIngressIPs, %+v", svcInfo) 756 } else if svcInfo.loadBalancerIngressIPs[0].healthCheckHnsID != "LBID-4" { 757 t.Errorf("The Hns Loadbalancer HealthCheck Id %v does not match %v. ServicePortName %q", svcInfo.loadBalancerIngressIPs[0].healthCheckHnsID, loadbalancerGuid1, svcPortName.String()) 758 } 759 } 760 } 761 762 // TestClusterIPLBInCreateDsrLoadBalancer tests, if the available endpoints are remote, 763 // syncproxyrules only creates ClusterIP Loadbalancer and no NodePort, External IP or IngressIP 764 // loadbalancers will be created. 765 func TestClusterIPLBInCreateDsrLoadBalancer(t *testing.T) { 766 syncPeriod := 30 * time.Second 767 proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY) 768 769 if proxier == nil { 770 t.Error() 771 } 772 773 svcIP := "10.20.30.41" 774 svcPort := 80 775 svcNodePort := 3001 776 svcPortName := proxy.ServicePortName{ 777 NamespacedName: makeNSN("ns1", "svc1"), 778 Port: "p80", 779 Protocol: v1.ProtocolTCP, 780 } 781 lbIP := "11.21.31.41" 782 783 makeServiceMap(proxier, 784 makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) { 785 svc.Spec.Type = "NodePort" 786 svc.Spec.ClusterIP = svcIP 787 svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyLocal 788 svc.Spec.Ports = []v1.ServicePort{{ 789 Name: svcPortName.Port, 790 Port: int32(svcPort), 791 Protocol: v1.ProtocolTCP, 792 NodePort: int32(svcNodePort), 793 }} 794 svc.Status.LoadBalancer.Ingress = []v1.LoadBalancerIngress{{ 795 IP: lbIP, 796 }} 797 }), 798 ) 799 populateEndpointSlices(proxier, 800 makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) { 801 eps.AddressType = discovery.AddressTypeIPv4 802 eps.Endpoints = []discovery.Endpoint{{ 803 Addresses: []string{epIpAddressRemote}, 804 NodeName: ptr.To("testhost2"), // This will make this endpoint as a remote endpoint 805 }} 806 eps.Ports = []discovery.EndpointPort{{ 807 Name: ptr.To(svcPortName.Port), 808 Port: ptr.To(int32(svcPort)), 809 Protocol: ptr.To(v1.ProtocolTCP), 810 }} 811 }), 812 ) 813 814 proxier.setInitialized(true) 815 proxier.syncProxyRules() 816 817 svc := proxier.svcPortMap[svcPortName] 818 svcInfo, ok := svc.(*serviceInfo) 819 if !ok { 820 t.Errorf("Failed to cast serviceInfo %q", svcPortName.String()) 821 822 } else { 823 // Checking ClusterIP Loadbalancer is created 824 if svcInfo.hnsID != loadbalancerGuid1 { 825 t.Errorf("%v does not match %v", svcInfo.hnsID, loadbalancerGuid1) 826 } 827 // Verifying NodePort Loadbalancer is not created 828 if svcInfo.nodePorthnsID != "" { 829 t.Errorf("NodePortHnsID %v is not empty.", svcInfo.nodePorthnsID) 830 } 831 // Verifying ExternalIP Loadbalancer is not created 832 for _, externalIP := range svcInfo.externalIPs { 833 if externalIP.hnsID != "" { 834 t.Errorf("ExternalLBID %v is not empty.", externalIP.hnsID) 835 } 836 } 837 // Verifying IngressIP Loadbalancer is not created 838 for _, ingressIP := range svcInfo.loadBalancerIngressIPs { 839 if ingressIP.hnsID != "" { 840 t.Errorf("IngressLBID %v is not empty.", ingressIP.hnsID) 841 } 842 } 843 } 844 } 845 846 func TestEndpointSlice(t *testing.T) { 847 syncPeriod := 30 * time.Second 848 proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY) 849 if proxier == nil { 850 t.Error() 851 } 852 853 proxier.servicesSynced = true 854 proxier.endpointSlicesSynced = true 855 856 svcPortName := proxy.ServicePortName{ 857 NamespacedName: makeNSN("ns1", "svc1"), 858 Port: "p80", 859 Protocol: v1.ProtocolTCP, 860 } 861 862 proxier.OnServiceAdd(&v1.Service{ 863 ObjectMeta: metav1.ObjectMeta{Name: svcPortName.Name, Namespace: svcPortName.Namespace}, 864 Spec: v1.ServiceSpec{ 865 ClusterIP: "172.20.1.1", 866 Selector: map[string]string{"foo": "bar"}, 867 Ports: []v1.ServicePort{{Name: svcPortName.Port, TargetPort: intstr.FromInt32(80), Protocol: v1.ProtocolTCP}}, 868 }, 869 }) 870 871 // Add initial endpoint slice 872 endpointSlice := &discovery.EndpointSlice{ 873 ObjectMeta: metav1.ObjectMeta{ 874 Name: fmt.Sprintf("%s-1", svcPortName.Name), 875 Namespace: svcPortName.Namespace, 876 Labels: map[string]string{discovery.LabelServiceName: svcPortName.Name}, 877 }, 878 Ports: []discovery.EndpointPort{{ 879 Name: &svcPortName.Port, 880 Port: ptr.To[int32](80), 881 Protocol: ptr.To(v1.ProtocolTCP), 882 }}, 883 AddressType: discovery.AddressTypeIPv4, 884 Endpoints: []discovery.Endpoint{{ 885 Addresses: []string{"192.168.2.3"}, 886 Conditions: discovery.EndpointConditions{Ready: ptr.To(true)}, 887 NodeName: ptr.To("testhost2"), 888 }}, 889 } 890 891 proxier.OnEndpointSliceAdd(endpointSlice) 892 proxier.setInitialized(true) 893 proxier.syncProxyRules() 894 895 svc := proxier.svcPortMap[svcPortName] 896 svcInfo, ok := svc.(*serviceInfo) 897 if !ok { 898 t.Errorf("Failed to cast serviceInfo %q", svcPortName.String()) 899 900 } else { 901 if svcInfo.hnsID != loadbalancerGuid1 { 902 t.Errorf("The Hns Loadbalancer Id %v does not match %v. ServicePortName %q", svcInfo.hnsID, loadbalancerGuid1, svcPortName.String()) 903 } 904 } 905 906 ep := proxier.endpointsMap[svcPortName][0] 907 epInfo, ok := ep.(*endpointInfo) 908 if !ok { 909 t.Errorf("Failed to cast endpointInfo %q", svcPortName.String()) 910 911 } else { 912 if epInfo.hnsID != "EPID-3" { 913 t.Errorf("Hns EndpointId %v does not match %v. ServicePortName %q", epInfo.hnsID, endpointGuid1, svcPortName.String()) 914 } 915 } 916 } 917 918 func TestNoopEndpointSlice(t *testing.T) { 919 p := Proxier{} 920 p.OnEndpointSliceAdd(&discovery.EndpointSlice{}) 921 p.OnEndpointSliceUpdate(&discovery.EndpointSlice{}, &discovery.EndpointSlice{}) 922 p.OnEndpointSliceDelete(&discovery.EndpointSlice{}) 923 p.OnEndpointSlicesSynced() 924 } 925 926 func TestFindRemoteSubnetProviderAddress(t *testing.T) { 927 syncPeriod := 30 * time.Second 928 proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", netutils.ParseIPSloppy("10.0.0.1"), NETWORK_TYPE_OVERLAY) 929 if proxier == nil { 930 t.Error() 931 } 932 933 networkInfo, _ := proxier.hns.getNetworkByName(testNetwork) 934 pa := networkInfo.findRemoteSubnetProviderAddress(providerAddress) 935 936 if pa != providerAddress { 937 t.Errorf("%v does not match %v", pa, providerAddress) 938 } 939 940 pa = networkInfo.findRemoteSubnetProviderAddress(epIpAddressRemote) 941 942 if pa != providerAddress { 943 t.Errorf("%v does not match %v", pa, providerAddress) 944 } 945 946 pa = networkInfo.findRemoteSubnetProviderAddress(serviceVip) 947 948 if len(pa) != 0 { 949 t.Errorf("Provider address is not empty as expected") 950 } 951 } 952 953 func makeNSN(namespace, name string) types.NamespacedName { 954 return types.NamespacedName{Namespace: namespace, Name: name} 955 } 956 957 func makeServiceMap(proxier *Proxier, allServices ...*v1.Service) { 958 for i := range allServices { 959 proxier.OnServiceAdd(allServices[i]) 960 } 961 962 proxier.mu.Lock() 963 defer proxier.mu.Unlock() 964 proxier.servicesSynced = true 965 } 966 func deleteServices(proxier *Proxier, allServices ...*v1.Service) { 967 for i := range allServices { 968 proxier.OnServiceDelete(allServices[i]) 969 } 970 971 proxier.mu.Lock() 972 defer proxier.mu.Unlock() 973 proxier.servicesSynced = true 974 } 975 976 func makeTestService(namespace, name string, svcFunc func(*v1.Service)) *v1.Service { 977 svc := &v1.Service{ 978 ObjectMeta: metav1.ObjectMeta{ 979 Name: name, 980 Namespace: namespace, 981 Annotations: map[string]string{}, 982 }, 983 Spec: v1.ServiceSpec{}, 984 Status: v1.ServiceStatus{}, 985 } 986 svcFunc(svc) 987 return svc 988 } 989 990 func deleteEndpointSlices(proxier *Proxier, allEndpointSlices ...*discovery.EndpointSlice) { 991 for i := range allEndpointSlices { 992 proxier.OnEndpointSliceDelete(allEndpointSlices[i]) 993 } 994 995 proxier.mu.Lock() 996 defer proxier.mu.Unlock() 997 proxier.endpointSlicesSynced = true 998 } 999 1000 func populateEndpointSlices(proxier *Proxier, allEndpointSlices ...*discovery.EndpointSlice) { 1001 for i := range allEndpointSlices { 1002 proxier.OnEndpointSliceAdd(allEndpointSlices[i]) 1003 } 1004 } 1005 1006 func makeTestEndpointSlice(namespace, name string, sliceNum int, epsFunc func(*discovery.EndpointSlice)) *discovery.EndpointSlice { 1007 eps := &discovery.EndpointSlice{ 1008 ObjectMeta: metav1.ObjectMeta{ 1009 Name: fmt.Sprintf("%s-%d", name, sliceNum), 1010 Namespace: namespace, 1011 Labels: map[string]string{discovery.LabelServiceName: name}, 1012 }, 1013 } 1014 epsFunc(eps) 1015 return eps 1016 }