Skip to content

Commit 50dcc32

Browse files
andrewsykimmurali-reddy
authored andcommitted
Unit Tests for Node Update Events (#265)
* activeNodes should not be a global variable for better testability * OnNodeUpdate unit tests
1 parent 4eca430 commit 50dcc32

File tree

2 files changed

+178
-6
lines changed

2 files changed

+178
-6
lines changed

app/controllers/network_routes_controller.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type NetworkRoutingController struct {
3939
nodeHostName string
4040
nodeSubnet net.IPNet
4141
nodeInterface string
42+
activeNodes map[string]bool
4243
mu sync.Mutex
4344
clientset kubernetes.Interface
4445
bgpServer *gobgp.BgpServer
@@ -61,7 +62,6 @@ type NetworkRoutingController struct {
6162
}
6263

6364
var (
64-
activeNodes = make(map[string]bool)
6565
podEgressArgs = []string{"-m", "set", "--match-set", podSubnetsIPSetName, "src",
6666
"-m", "set", "!", "--match-set", podSubnetsIPSetName, "dst",
6767
"-m", "set", "!", "--match-set", nodeAddrsIPSetName, "dst",
@@ -1004,7 +1004,9 @@ func (nrc *NetworkRoutingController) syncInternalPeers() {
10041004
}
10051005

10061006
currentNodes = append(currentNodes, nodeIP.String())
1007-
activeNodes[nodeIP.String()] = true
1007+
nrc.mu.Lock()
1008+
nrc.activeNodes[nodeIP.String()] = true
1009+
nrc.mu.Unlock()
10081010
n := &config.Neighbor{
10091011
Config: config.NeighborConfig{
10101012
NeighborAddress: nodeIP.String(),
@@ -1047,7 +1049,9 @@ func (nrc *NetworkRoutingController) syncInternalPeers() {
10471049

10481050
// find the list of the node removed, from the last known list of active nodes
10491051
removedNodes := make([]string, 0)
1050-
for ip := range activeNodes {
1052+
nrc.mu.Lock()
1053+
defer nrc.mu.Unlock()
1054+
for ip := range nrc.activeNodes {
10511055
stillActive := false
10521056
for _, node := range currentNodes {
10531057
if ip == node {
@@ -1071,7 +1075,7 @@ func (nrc *NetworkRoutingController) syncInternalPeers() {
10711075
if err := nrc.bgpServer.DeleteNeighbor(n); err != nil {
10721076
glog.Errorf("Failed to remove node %s as peer due to %s", ip, err)
10731077
}
1074-
delete(activeNodes, ip)
1078+
delete(nrc.activeNodes, ip)
10751079
}
10761080
}
10771081

@@ -1220,7 +1224,7 @@ func (nrc *NetworkRoutingController) OnNodeUpdate(nodeUpdate *watchers.NodeUpdat
12201224
if err := nrc.bgpServer.AddNeighbor(n); err != nil {
12211225
glog.Errorf("Failed to add node %s as peer due to %s", nodeIP, err)
12221226
}
1223-
activeNodes[nodeIP.String()] = true
1227+
nrc.activeNodes[nodeIP.String()] = true
12241228
} else if nodeUpdate.Op == watchers.REMOVE {
12251229
glog.Infof("Received node %s removed update from watch API, so remove node from peer", nodeIP)
12261230
n := &config.Neighbor{
@@ -1232,7 +1236,7 @@ func (nrc *NetworkRoutingController) OnNodeUpdate(nodeUpdate *watchers.NodeUpdat
12321236
if err := nrc.bgpServer.DeleteNeighbor(n); err != nil {
12331237
glog.Errorf("Failed to remove node %s as peer due to %s", nodeIP, err)
12341238
}
1235-
delete(activeNodes, nodeIP.String())
1239+
delete(nrc.activeNodes, nodeIP.String())
12361240
}
12371241
nrc.disableSourceDestinationCheck()
12381242
}
@@ -1414,6 +1418,7 @@ func NewNetworkRoutingController(clientset *kubernetes.Clientset,
14141418
nrc.enablePodEgress = kubeRouterConfig.EnablePodEgress
14151419
nrc.syncPeriod = kubeRouterConfig.RoutesSyncPeriod
14161420
nrc.clientset = clientset
1421+
nrc.activeNodes = make(map[string]bool)
14171422

14181423
nrc.ipSetHandler, err = utils.NewIPSet()
14191424
if err != nil {

app/controllers/network_routes_controller_test.go

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,173 @@ func Test_advertiseRoute(t *testing.T) {
525525
}
526526
}
527527

528+
func Test_OnNodeUpdate(t *testing.T) {
529+
testcases := []struct {
530+
name string
531+
nrc *NetworkRoutingController
532+
nodeEvents []*watchers.NodeUpdate
533+
activeNodes map[string]bool
534+
}{
535+
{
536+
"node add event",
537+
&NetworkRoutingController{
538+
activeNodes: make(map[string]bool),
539+
bgpServer: gobgp.NewBgpServer(),
540+
defaultNodeAsnNumber: 1,
541+
clientset: fake.NewSimpleClientset(),
542+
},
543+
[]*watchers.NodeUpdate{
544+
{
545+
Node: &v1core.Node{
546+
ObjectMeta: metav1.ObjectMeta{
547+
Name: "node-1",
548+
},
549+
Status: v1core.NodeStatus{
550+
Addresses: []v1core.NodeAddress{
551+
{
552+
Type: v1core.NodeInternalIP,
553+
Address: "10.0.0.1",
554+
},
555+
},
556+
},
557+
},
558+
Op: watchers.ADD,
559+
},
560+
},
561+
map[string]bool{
562+
"10.0.0.1": true,
563+
},
564+
},
565+
{
566+
"add multiple nodes",
567+
&NetworkRoutingController{
568+
activeNodes: make(map[string]bool),
569+
bgpServer: gobgp.NewBgpServer(),
570+
defaultNodeAsnNumber: 1,
571+
clientset: fake.NewSimpleClientset(),
572+
},
573+
[]*watchers.NodeUpdate{
574+
{
575+
Node: &v1core.Node{
576+
ObjectMeta: metav1.ObjectMeta{
577+
Name: "node-1",
578+
},
579+
Status: v1core.NodeStatus{
580+
Addresses: []v1core.NodeAddress{
581+
{
582+
Type: v1core.NodeInternalIP,
583+
Address: "10.0.0.1",
584+
},
585+
},
586+
},
587+
},
588+
Op: watchers.ADD,
589+
},
590+
{
591+
Node: &v1core.Node{
592+
ObjectMeta: metav1.ObjectMeta{
593+
Name: "node-2",
594+
},
595+
Status: v1core.NodeStatus{
596+
Addresses: []v1core.NodeAddress{
597+
{
598+
Type: v1core.NodeExternalIP,
599+
Address: "1.1.1.1",
600+
},
601+
},
602+
},
603+
},
604+
Op: watchers.ADD,
605+
},
606+
},
607+
map[string]bool{
608+
"10.0.0.1": true,
609+
"1.1.1.1": true,
610+
},
611+
},
612+
{
613+
"add and then delete nodes",
614+
&NetworkRoutingController{
615+
activeNodes: make(map[string]bool),
616+
bgpServer: gobgp.NewBgpServer(),
617+
defaultNodeAsnNumber: 1,
618+
clientset: fake.NewSimpleClientset(),
619+
},
620+
[]*watchers.NodeUpdate{
621+
{
622+
Node: &v1core.Node{
623+
ObjectMeta: metav1.ObjectMeta{
624+
Name: "node-1",
625+
},
626+
Status: v1core.NodeStatus{
627+
Addresses: []v1core.NodeAddress{
628+
{
629+
Type: v1core.NodeInternalIP,
630+
Address: "10.0.0.1",
631+
},
632+
},
633+
},
634+
},
635+
Op: watchers.ADD,
636+
},
637+
{
638+
Node: &v1core.Node{
639+
ObjectMeta: metav1.ObjectMeta{
640+
Name: "node-1",
641+
},
642+
Status: v1core.NodeStatus{
643+
Addresses: []v1core.NodeAddress{
644+
{
645+
Type: v1core.NodeInternalIP,
646+
Address: "10.0.0.1",
647+
},
648+
},
649+
},
650+
},
651+
Op: watchers.REMOVE,
652+
},
653+
},
654+
map[string]bool{},
655+
},
656+
}
657+
658+
for _, testcase := range testcases {
659+
t.Run(testcase.name, func(t *testing.T) {
660+
t.Log(testcase.name)
661+
go testcase.nrc.bgpServer.Serve()
662+
err := testcase.nrc.bgpServer.Start(&config.Global{
663+
Config: config.GlobalConfig{
664+
As: 1,
665+
RouterId: "10.0.0.0",
666+
Port: 10000,
667+
},
668+
})
669+
if err != nil {
670+
t.Fatalf("failed to start BGP server: %v", err)
671+
}
672+
defer testcase.nrc.bgpServer.Stop()
673+
674+
for _, nodeEvent := range testcase.nodeEvents {
675+
testcase.nrc.OnNodeUpdate(nodeEvent)
676+
}
677+
678+
neighbors := testcase.nrc.bgpServer.GetNeighbor("", false)
679+
for _, neighbor := range neighbors {
680+
_, exists := testcase.activeNodes[neighbor.Config.NeighborAddress]
681+
if !exists {
682+
t.Errorf("expected neighbor: %v doesn't exist", neighbor.Config.NeighborAddress)
683+
}
684+
}
685+
686+
if !reflect.DeepEqual(testcase.nrc.activeNodes, testcase.activeNodes) {
687+
t.Logf("actual active nodes: %v", testcase.nrc.activeNodes)
688+
t.Logf("expected active nodes: %v", testcase.activeNodes)
689+
t.Errorf("did not get expected activeNodes")
690+
}
691+
})
692+
}
693+
}
694+
528695
func createServices(clientset kubernetes.Interface, svcs []*v1core.Service) error {
529696
for _, svc := range svcs {
530697
_, err := clientset.CoreV1().Services("default").Create(svc)

0 commit comments

Comments
 (0)