github.com/elfadel/cilium@v1.6.12/pkg/health/server/prober_test.go (about)

     1  // Copyright 2019 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // +build !privileged_tests
    16  
    17  package server
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"net"
    23  	"sort"
    24  	"testing"
    25  
    26  	"github.com/cilium/cilium/api/v1/models"
    27  	"github.com/cilium/cilium/pkg/checker"
    28  
    29  	"gopkg.in/check.v1"
    30  )
    31  
    32  func Test(t *testing.T) { check.TestingT(t) }
    33  
    34  type HealthServerTestSuite struct{}
    35  
    36  var _ = check.Suite(&HealthServerTestSuite{})
    37  
    38  func makeHealthNode(nodeIdx, healthIdx int) (healthNode, net.IP, net.IP) {
    39  	nodeIP := fmt.Sprintf("192.0.2.%d", nodeIdx)
    40  	healthIP := fmt.Sprintf("10.0.2.%d", healthIdx)
    41  	return healthNode{
    42  		NodeElement: &models.NodeElement{
    43  			Name: fmt.Sprintf("node-%d", nodeIdx),
    44  			PrimaryAddress: &models.NodeAddressing{
    45  				IPV4: &models.NodeAddressingElement{
    46  					IP:      nodeIP,
    47  					Enabled: true,
    48  				},
    49  				IPV6: &models.NodeAddressingElement{
    50  					Enabled: false,
    51  				},
    52  			},
    53  			HealthEndpointAddress: &models.NodeAddressing{
    54  				IPV4: &models.NodeAddressingElement{
    55  					IP:      healthIP,
    56  					Enabled: true,
    57  				},
    58  				IPV6: &models.NodeAddressingElement{
    59  					Enabled: false,
    60  				},
    61  			},
    62  		},
    63  	}, net.ParseIP(nodeIP), net.ParseIP(healthIP)
    64  }
    65  
    66  func sortNodes(nodes map[string][]*net.IPAddr) map[string][]*net.IPAddr {
    67  	for _, slice := range nodes {
    68  		sort.Slice(slice, func(i, j int) bool {
    69  			iLength := len(slice[i].IP)
    70  			jLength := len(slice[j].IP)
    71  			if iLength == jLength {
    72  				return bytes.Compare(slice[i].IP, slice[j].IP) < 0
    73  			}
    74  			return iLength < jLength
    75  		})
    76  	}
    77  	return nodes
    78  }
    79  
    80  func (s *HealthServerTestSuite) TestProbersetNodes(c *check.C) {
    81  	node1, node1IP, node1HealthIP := makeHealthNode(1, 1)
    82  	newNodes := nodeMap{
    83  		ipString(node1.Name): node1,
    84  	}
    85  
    86  	// First up: Just create a prober with some nodes.
    87  	prober := newProber(&Server{}, newNodes)
    88  	nodes := prober.getIPsByNode()
    89  	expected := map[string][]*net.IPAddr{
    90  		node1.Name: {{
    91  			IP: node1IP,
    92  		}, {
    93  			IP: node1HealthIP,
    94  		}},
    95  	}
    96  	c.Assert(sortNodes(nodes), checker.DeepEquals, sortNodes(expected))
    97  
    98  	// Update the health IP and observe that it is updated.
    99  	// Note that update consists of delete and add in setNodes().
   100  	node1, node1IP, node1HealthIP = makeHealthNode(1, 2)
   101  	modifiedNodes := nodeMap{
   102  		ipString(node1.Name): node1,
   103  	}
   104  	prober.setNodes(modifiedNodes, newNodes)
   105  	nodes = prober.getIPsByNode()
   106  	expected = map[string][]*net.IPAddr{
   107  		node1.Name: {{
   108  			IP: node1IP,
   109  		}, {
   110  			IP: node1HealthIP,
   111  		}},
   112  	}
   113  	c.Assert(sortNodes(nodes), checker.DeepEquals, sortNodes(expected))
   114  
   115  	// Remove the nodes; they shouldn't be there any more
   116  	prober.setNodes(nil, modifiedNodes)
   117  	nodes = prober.getIPsByNode()
   118  	expected = map[string][]*net.IPAddr{}
   119  	c.Assert(sortNodes(nodes), checker.DeepEquals, sortNodes(expected))
   120  
   121  	// Add back two nodes
   122  	node2, node2IP, node2HealthIP := makeHealthNode(2, 20)
   123  	updatedNodes := nodeMap{
   124  		ipString(node1.Name): node1,
   125  		ipString(node2.Name): node2,
   126  	}
   127  	prober.setNodes(updatedNodes, nil)
   128  	nodes = prober.getIPsByNode()
   129  	expected = map[string][]*net.IPAddr{
   130  		node1.Name: {{
   131  			IP: node1IP,
   132  		}, {
   133  			IP: node1HealthIP,
   134  		}},
   135  		node2.Name: {{
   136  			IP: node2IP,
   137  		}, {
   138  			IP: node2HealthIP,
   139  		}},
   140  	}
   141  	c.Assert(sortNodes(nodes), checker.DeepEquals, sortNodes(expected))
   142  
   143  	// Update node 1. Node 2 should remain unaffected.
   144  	modifiedNodesOld := nodeMap{
   145  		ipString(node1.Name): node1,
   146  	}
   147  	node1, node1IP, node1HealthIP = makeHealthNode(1, 5)
   148  	modifiedNodesNew := nodeMap{
   149  		ipString(node1.Name): node1,
   150  	}
   151  	prober.setNodes(modifiedNodesNew, modifiedNodesOld)
   152  	nodes = prober.getIPsByNode()
   153  	expected[node1.Name] = []*net.IPAddr{{
   154  		IP: node1IP,
   155  	}, {
   156  		IP: node1HealthIP,
   157  	}}
   158  	c.Assert(sortNodes(nodes), checker.DeepEquals, sortNodes(expected))
   159  
   160  	// Remove node 1. Again, Node 2 should remain.
   161  	removedNodes := nodeMap{
   162  		ipString(node1.Name): node1,
   163  	}
   164  	prober.setNodes(nil, removedNodes)
   165  	nodes = prober.getIPsByNode()
   166  	expected = map[string][]*net.IPAddr{
   167  		node2.Name: {{
   168  			IP: node2IP,
   169  		}, {
   170  			IP: node2HealthIP,
   171  		}},
   172  	}
   173  	c.Assert(sortNodes(nodes), checker.DeepEquals, sortNodes(expected))
   174  }