1
2
3
4
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
761
762
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"),
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
822 if svcInfo.hnsID != loadbalancerGuid1 {
823 t.Errorf("%v does not match %v", svcInfo.hnsID, loadbalancerGuid1)
824 }
825
826 if svcInfo.nodePorthnsID != "" {
827 t.Errorf("NodePortHnsID %v is not empty.", svcInfo.nodePorthnsID)
828 }
829
830 for _, externalIP := range svcInfo.externalIPs {
831 if externalIP.hnsID != "" {
832 t.Errorf("ExternalLBID %v is not empty.", externalIP.hnsID)
833 }
834 }
835
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
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 }
1015
View as plain text