github.com/zhyoulun/cilium@v1.6.12/pkg/node/manager/manager_test.go (about)

     1  // Copyright 2018-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 manager
    18  
    19  import (
    20  	"fmt"
    21  	"sync"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/cilium/cilium/pkg/checker"
    26  	"github.com/cilium/cilium/pkg/datapath"
    27  	"github.com/cilium/cilium/pkg/datapath/fake"
    28  	"github.com/cilium/cilium/pkg/node"
    29  	"github.com/cilium/cilium/pkg/source"
    30  
    31  	"gopkg.in/check.v1"
    32  )
    33  
    34  func Test(t *testing.T) {
    35  	check.TestingT(t)
    36  }
    37  
    38  type managerTestSuite struct{}
    39  
    40  var _ = check.Suite(&managerTestSuite{})
    41  
    42  type signalNodeHandler struct {
    43  	EnableNodeAddEvent                    bool
    44  	NodeAddEvent                          chan node.Node
    45  	NodeUpdateEvent                       chan node.Node
    46  	EnableNodeUpdateEvent                 bool
    47  	NodeDeleteEvent                       chan node.Node
    48  	EnableNodeDeleteEvent                 bool
    49  	NodeValidateImplementationEvent       chan node.Node
    50  	EnableNodeValidateImplementationEvent bool
    51  }
    52  
    53  func newSignalNodeHandler() *signalNodeHandler {
    54  	return &signalNodeHandler{
    55  		NodeAddEvent:                    make(chan node.Node, 10),
    56  		NodeUpdateEvent:                 make(chan node.Node, 10),
    57  		NodeDeleteEvent:                 make(chan node.Node, 10),
    58  		NodeValidateImplementationEvent: make(chan node.Node, 4096),
    59  	}
    60  }
    61  
    62  func (n *signalNodeHandler) NodeAdd(newNode node.Node) error {
    63  	if n.EnableNodeAddEvent {
    64  		n.NodeAddEvent <- newNode
    65  	}
    66  	return nil
    67  }
    68  
    69  func (n *signalNodeHandler) NodeUpdate(oldNode, newNode node.Node) error {
    70  	if n.EnableNodeUpdateEvent {
    71  		n.NodeUpdateEvent <- newNode
    72  	}
    73  	return nil
    74  }
    75  
    76  func (n *signalNodeHandler) NodeDelete(node node.Node) error {
    77  	if n.EnableNodeDeleteEvent {
    78  		n.NodeDeleteEvent <- node
    79  	}
    80  	return nil
    81  }
    82  
    83  func (n *signalNodeHandler) NodeValidateImplementation(node node.Node) error {
    84  	if n.EnableNodeValidateImplementationEvent {
    85  		n.NodeValidateImplementationEvent <- node
    86  	}
    87  	return nil
    88  }
    89  
    90  func (n *signalNodeHandler) NodeConfigurationChanged(config datapath.LocalNodeConfiguration) error {
    91  	return nil
    92  }
    93  
    94  func (s *managerTestSuite) TestNodeLifecycle(c *check.C) {
    95  	dp := newSignalNodeHandler()
    96  	dp.EnableNodeAddEvent = true
    97  	dp.EnableNodeUpdateEvent = true
    98  	dp.EnableNodeDeleteEvent = true
    99  	mngr, err := NewManager("test", dp)
   100  	c.Assert(err, check.IsNil)
   101  
   102  	n1 := node.Node{Name: "node1", Cluster: "c1"}
   103  	mngr.NodeUpdated(n1)
   104  
   105  	select {
   106  	case nodeEvent := <-dp.NodeAddEvent:
   107  		c.Assert(nodeEvent, checker.DeepEquals, n1)
   108  	case nodeEvent := <-dp.NodeUpdateEvent:
   109  		c.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   110  	case nodeEvent := <-dp.NodeDeleteEvent:
   111  		c.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   112  	case <-time.After(3 * time.Second):
   113  		c.Errorf("timeout while waiting for NodeAdd() event for node1")
   114  	}
   115  
   116  	n2 := node.Node{Name: "node2", Cluster: "c1"}
   117  	mngr.NodeUpdated(n2)
   118  
   119  	select {
   120  	case nodeEvent := <-dp.NodeAddEvent:
   121  		c.Assert(nodeEvent, checker.DeepEquals, n2)
   122  	case nodeEvent := <-dp.NodeUpdateEvent:
   123  		c.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   124  	case nodeEvent := <-dp.NodeDeleteEvent:
   125  		c.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   126  	case <-time.After(3 * time.Second):
   127  		c.Errorf("timeout while waiting for NodeUpdate() event for node2")
   128  	}
   129  
   130  	nodes := mngr.GetNodes()
   131  	n, ok := nodes[n1.Identity()]
   132  	c.Assert(ok, check.Equals, true)
   133  	c.Assert(n, checker.DeepEquals, n1)
   134  
   135  	mngr.NodeDeleted(n1)
   136  	select {
   137  	case nodeEvent := <-dp.NodeDeleteEvent:
   138  		c.Assert(nodeEvent, checker.DeepEquals, n1)
   139  	case nodeEvent := <-dp.NodeAddEvent:
   140  		c.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
   141  	case nodeEvent := <-dp.NodeUpdateEvent:
   142  		c.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   143  	case <-time.After(3 * time.Second):
   144  		c.Errorf("timeout while waiting for NodeDelete() event for node1")
   145  	}
   146  	nodes = mngr.GetNodes()
   147  	_, ok = nodes[n1.Identity()]
   148  	c.Assert(ok, check.Equals, false)
   149  
   150  	mngr.Close()
   151  	select {
   152  	case nodeEvent := <-dp.NodeDeleteEvent:
   153  		c.Assert(nodeEvent, checker.DeepEquals, n2)
   154  	case nodeEvent := <-dp.NodeAddEvent:
   155  		c.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
   156  	case nodeEvent := <-dp.NodeUpdateEvent:
   157  		c.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   158  	case <-time.After(3 * time.Second):
   159  		c.Errorf("timeout while waiting for NodeDelete() event for node2")
   160  	}
   161  }
   162  
   163  func (s *managerTestSuite) TestMultipleSources(c *check.C) {
   164  	dp := newSignalNodeHandler()
   165  	dp.EnableNodeAddEvent = true
   166  	dp.EnableNodeUpdateEvent = true
   167  	dp.EnableNodeDeleteEvent = true
   168  	mngr, err := NewManager("test", dp)
   169  	c.Assert(err, check.IsNil)
   170  	defer mngr.Close()
   171  
   172  	n1k8s := node.Node{Name: "node1", Cluster: "c1", Source: source.Kubernetes}
   173  	mngr.NodeUpdated(n1k8s)
   174  	select {
   175  	case nodeEvent := <-dp.NodeAddEvent:
   176  		c.Assert(nodeEvent, checker.DeepEquals, n1k8s)
   177  	case nodeEvent := <-dp.NodeUpdateEvent:
   178  		c.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   179  	case nodeEvent := <-dp.NodeDeleteEvent:
   180  		c.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   181  	case <-time.After(3 * time.Second):
   182  		c.Errorf("timeout while waiting for NodeAdd() event for node1")
   183  	}
   184  
   185  	// agent can overwrite kubernetes
   186  	n1agent := node.Node{Name: "node1", Cluster: "c1", Source: source.Local}
   187  	mngr.NodeUpdated(n1agent)
   188  	select {
   189  	case nodeEvent := <-dp.NodeUpdateEvent:
   190  		c.Assert(nodeEvent, checker.DeepEquals, n1agent)
   191  	case nodeEvent := <-dp.NodeAddEvent:
   192  		c.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
   193  	case nodeEvent := <-dp.NodeDeleteEvent:
   194  		c.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   195  	case <-time.After(3 * time.Second):
   196  		c.Errorf("timeout while waiting for NodeUpdate() event for node1")
   197  	}
   198  
   199  	// kubernetes cannot overwrite local node
   200  	mngr.NodeUpdated(n1k8s)
   201  	select {
   202  	case nodeEvent := <-dp.NodeAddEvent:
   203  		c.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
   204  	case nodeEvent := <-dp.NodeUpdateEvent:
   205  		c.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   206  	case nodeEvent := <-dp.NodeDeleteEvent:
   207  		c.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   208  	case <-time.After(100 * time.Millisecond):
   209  	}
   210  
   211  	// delete from kubernetes, should not remove local node
   212  	mngr.NodeDeleted(n1k8s)
   213  	select {
   214  	case nodeEvent := <-dp.NodeAddEvent:
   215  		c.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
   216  	case nodeEvent := <-dp.NodeUpdateEvent:
   217  		c.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   218  	case nodeEvent := <-dp.NodeDeleteEvent:
   219  		c.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   220  	case <-time.After(100 * time.Millisecond):
   221  	}
   222  
   223  	mngr.NodeDeleted(n1agent)
   224  	select {
   225  	case nodeEvent := <-dp.NodeAddEvent:
   226  		c.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
   227  	case nodeEvent := <-dp.NodeUpdateEvent:
   228  		c.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   229  	case nodeEvent := <-dp.NodeDeleteEvent:
   230  		c.Assert(nodeEvent, checker.DeepEquals, n1agent)
   231  	case <-time.After(3 * time.Second):
   232  		c.Errorf("timeout while waiting for NodeDelete() event for node1")
   233  	}
   234  }
   235  
   236  func (s *managerTestSuite) BenchmarkUpdateAndDeleteCycle(c *check.C) {
   237  	mngr, err := NewManager("test", fake.NewNodeHandler())
   238  	c.Assert(err, check.IsNil)
   239  	defer mngr.Close()
   240  
   241  	c.ResetTimer()
   242  	for i := 0; i < c.N; i++ {
   243  		n := node.Node{Name: fmt.Sprintf("%d", i), Source: source.Local}
   244  		mngr.NodeUpdated(n)
   245  	}
   246  
   247  	for i := 0; i < c.N; i++ {
   248  		n := node.Node{Name: fmt.Sprintf("%d", i), Source: source.Local}
   249  		mngr.NodeDeleted(n)
   250  	}
   251  	c.StopTimer()
   252  }
   253  
   254  func (s *managerTestSuite) TestClusterSizeDependantInterval(c *check.C) {
   255  	mngr, err := NewManager("test", fake.NewNodeHandler())
   256  	c.Assert(err, check.IsNil)
   257  	defer mngr.Close()
   258  
   259  	prevInterval := time.Nanosecond
   260  
   261  	for i := 0; i < 1000; i++ {
   262  		n := node.Node{Name: fmt.Sprintf("%d", i), Source: source.Local}
   263  		mngr.NodeUpdated(n)
   264  		newInterval := mngr.ClusterSizeDependantInterval(time.Minute)
   265  		c.Assert(newInterval > prevInterval, check.Equals, true)
   266  	}
   267  }
   268  
   269  func (s *managerTestSuite) TestBackgroundSync(c *check.C) {
   270  	c.Skip("GH-6751 Test is disabled due to being unstable")
   271  
   272  	// set the base background sync interval to a very low value so the
   273  	// background sync runs aggressively
   274  	baseBackgroundSyncIntervalBackup := baseBackgroundSyncInterval
   275  	baseBackgroundSyncInterval = 10 * time.Millisecond
   276  	defer func() { baseBackgroundSyncInterval = baseBackgroundSyncIntervalBackup }()
   277  
   278  	signalNodeHandler := newSignalNodeHandler()
   279  	signalNodeHandler.EnableNodeValidateImplementationEvent = true
   280  	mngr, err := NewManager("test", signalNodeHandler)
   281  	c.Assert(err, check.IsNil)
   282  	defer mngr.Close()
   283  
   284  	numNodes := 4096
   285  
   286  	allNodeValidateCallsReceived := &sync.WaitGroup{}
   287  	allNodeValidateCallsReceived.Add(1)
   288  
   289  	go func() {
   290  		nodeValidationsReceived := 0
   291  		for {
   292  			select {
   293  			case <-signalNodeHandler.NodeValidateImplementationEvent:
   294  				nodeValidationsReceived++
   295  				if nodeValidationsReceived >= numNodes {
   296  					allNodeValidateCallsReceived.Done()
   297  					return
   298  				}
   299  			case <-time.After(time.Second * 5):
   300  				c.Errorf("Timeout while waiting for NodeValidateImplementation() to be called")
   301  			}
   302  		}
   303  	}()
   304  
   305  	for i := 0; i < numNodes; i++ {
   306  		n := node.Node{Name: fmt.Sprintf("%d", i), Source: source.Kubernetes}
   307  		mngr.NodeUpdated(n)
   308  	}
   309  
   310  	allNodeValidateCallsReceived.Wait()
   311  }