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