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

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package manager
     5  
     6  import (
     7  	"context"
     8  	"encoding/json"
     9  	"fmt"
    10  	"io/fs"
    11  	"net"
    12  	"net/netip"
    13  	"os"
    14  	"path/filepath"
    15  	"strings"
    16  	"sync"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/cilium/hive/cell"
    21  	"github.com/cilium/hive/hivetest"
    22  	"github.com/cilium/statedb"
    23  	"github.com/stretchr/testify/assert"
    24  	"github.com/stretchr/testify/require"
    25  
    26  	fakeTypes "github.com/cilium/cilium/pkg/datapath/fake/types"
    27  	"github.com/cilium/cilium/pkg/datapath/iptables/ipset"
    28  	datapath "github.com/cilium/cilium/pkg/datapath/types"
    29  	"github.com/cilium/cilium/pkg/hive"
    30  	"github.com/cilium/cilium/pkg/hive/health"
    31  	"github.com/cilium/cilium/pkg/hive/health/types"
    32  	"github.com/cilium/cilium/pkg/identity"
    33  	"github.com/cilium/cilium/pkg/inctimer"
    34  	"github.com/cilium/cilium/pkg/ipcache"
    35  	ipcacheTypes "github.com/cilium/cilium/pkg/ipcache/types"
    36  	"github.com/cilium/cilium/pkg/labels"
    37  	"github.com/cilium/cilium/pkg/lock"
    38  	"github.com/cilium/cilium/pkg/node"
    39  	"github.com/cilium/cilium/pkg/node/addressing"
    40  	nodeTypes "github.com/cilium/cilium/pkg/node/types"
    41  	"github.com/cilium/cilium/pkg/option"
    42  	"github.com/cilium/cilium/pkg/source"
    43  	testidentity "github.com/cilium/cilium/pkg/testutils/identity"
    44  )
    45  
    46  type nodeEvent struct {
    47  	event  string
    48  	prefix netip.Prefix
    49  }
    50  
    51  type ipcacheMock struct {
    52  	events chan nodeEvent
    53  }
    54  
    55  func newIPcacheMock() *ipcacheMock {
    56  	return &ipcacheMock{
    57  		events: make(chan nodeEvent, 1024),
    58  	}
    59  }
    60  
    61  func AddrOrPrefixToIP(ip string) (netip.Prefix, error) {
    62  	prefix, err := netip.ParsePrefix(ip)
    63  	if err != nil {
    64  		addr, err := netip.ParseAddr(ip)
    65  		if err != nil {
    66  			return netip.Prefix{}, err
    67  		}
    68  		return addr.Prefix(prefix.Bits())
    69  	}
    70  
    71  	return prefix, err
    72  }
    73  
    74  func (i *ipcacheMock) Upsert(ip string, hostIP net.IP, hostKey uint8, k8sMeta *ipcache.K8sMetadata, newIdentity ipcache.Identity) (bool, error) {
    75  	addr, err := AddrOrPrefixToIP(ip)
    76  	if err != nil {
    77  		i.events <- nodeEvent{fmt.Sprintf("upsert failed: %s", err), addr}
    78  		return false, err
    79  	}
    80  	i.events <- nodeEvent{"upsert", addr}
    81  	return false, nil
    82  }
    83  
    84  func (i *ipcacheMock) Delete(ip string, source source.Source) bool {
    85  	addr, err := AddrOrPrefixToIP(ip)
    86  	if err != nil {
    87  		i.events <- nodeEvent{fmt.Sprintf("delete failed: %s", err), addr}
    88  		return false
    89  	}
    90  	i.events <- nodeEvent{"delete", addr}
    91  	return false
    92  }
    93  
    94  func (i *ipcacheMock) GetMetadataSourceByPrefix(prefix netip.Prefix) source.Source {
    95  	return source.Unspec
    96  }
    97  func (i *ipcacheMock) UpsertMetadata(prefix netip.Prefix, src source.Source, resource ipcacheTypes.ResourceID, aux ...ipcache.IPMetadata) {
    98  	i.Upsert(prefix.String(), nil, 0, nil, ipcache.Identity{})
    99  }
   100  func (i *ipcacheMock) OverrideIdentity(prefix netip.Prefix, identityLabels labels.Labels, src source.Source, resource ipcacheTypes.ResourceID) {
   101  	i.UpsertMetadata(prefix, src, resource)
   102  }
   103  
   104  func (i *ipcacheMock) RemoveMetadata(prefix netip.Prefix, resource ipcacheTypes.ResourceID, aux ...ipcache.IPMetadata) {
   105  	i.Delete(prefix.String(), source.CustomResource)
   106  }
   107  
   108  func (i *ipcacheMock) RemoveIdentityOverride(prefix netip.Prefix, identityLabels labels.Labels, resource ipcacheTypes.ResourceID) {
   109  	i.Delete(prefix.String(), source.CustomResource)
   110  }
   111  
   112  type ipsetMock struct {
   113  	v4 map[string]struct{}
   114  	v6 map[string]struct{}
   115  }
   116  
   117  func newIPSetMock() *ipsetMock {
   118  	return &ipsetMock{
   119  		v4: make(map[string]struct{}),
   120  		v6: make(map[string]struct{}),
   121  	}
   122  }
   123  
   124  type ipsetInitializerMock struct{}
   125  
   126  func (i *ipsetInitializerMock) InitDone() {
   127  }
   128  
   129  func (i *ipsetMock) NewInitializer() ipset.Initializer {
   130  	return &ipsetInitializerMock{}
   131  }
   132  
   133  func (i *ipsetMock) AddToIPSet(name string, family ipset.Family, addrs ...netip.Addr) {
   134  	for _, addr := range addrs {
   135  		if name == ipset.CiliumNodeIPSetV4 && family == ipset.INetFamily {
   136  			i.v4[addr.String()] = struct{}{}
   137  		} else if name == ipset.CiliumNodeIPSetV6 && family == ipset.INet6Family {
   138  			i.v6[addr.String()] = struct{}{}
   139  		}
   140  	}
   141  }
   142  
   143  func (i *ipsetMock) RemoveFromIPSet(name string, addrs ...netip.Addr) {
   144  	for _, addr := range addrs {
   145  		if name == ipset.CiliumNodeIPSetV4 {
   146  			delete(i.v4, addr.String())
   147  		} else if name == ipset.CiliumNodeIPSetV6 {
   148  			delete(i.v6, addr.String())
   149  		}
   150  	}
   151  }
   152  
   153  func ipsetContains(ipsetMgr *ipsetMock, setName string, addr string) (bool, error) {
   154  	switch setName {
   155  	case ipset.CiliumNodeIPSetV4:
   156  		_, found := ipsetMgr.v4[addr]
   157  		return found, nil
   158  	case ipset.CiliumNodeIPSetV6:
   159  		_, found := ipsetMgr.v6[addr]
   160  		return found, nil
   161  	default:
   162  		return false, fmt.Errorf("unexpected ipset name %s", setName)
   163  	}
   164  }
   165  
   166  type signalNodeHandler struct {
   167  	EnableNodeAddEvent                    bool
   168  	NodeAddEvent                          chan nodeTypes.Node
   169  	NodeAddEventError                     error
   170  	NodeUpdateEvent                       chan nodeTypes.Node
   171  	NodeUpdateEventError                  error
   172  	EnableNodeUpdateEvent                 bool
   173  	NodeDeleteEvent                       chan nodeTypes.Node
   174  	NodeDeleteEventError                  error
   175  	EnableNodeDeleteEvent                 bool
   176  	NodeValidateImplementationEvent       chan nodeTypes.Node
   177  	NodeValidateImplementationEventError  error
   178  	EnableNodeValidateImplementationEvent bool
   179  }
   180  
   181  func newSignalNodeHandler() *signalNodeHandler {
   182  	return &signalNodeHandler{
   183  		NodeAddEvent:                    make(chan nodeTypes.Node, 10),
   184  		NodeUpdateEvent:                 make(chan nodeTypes.Node, 10),
   185  		NodeDeleteEvent:                 make(chan nodeTypes.Node, 10),
   186  		NodeValidateImplementationEvent: make(chan nodeTypes.Node, 4096),
   187  	}
   188  }
   189  
   190  func (s *signalNodeHandler) Name() string {
   191  	return "manager_test:signalNodeHandler"
   192  }
   193  
   194  func (n *signalNodeHandler) NodeAdd(newNode nodeTypes.Node) error {
   195  	if n.EnableNodeAddEvent {
   196  		n.NodeAddEvent <- newNode
   197  	}
   198  	return n.NodeAddEventError
   199  }
   200  
   201  func (n *signalNodeHandler) NodeUpdate(oldNode, newNode nodeTypes.Node) error {
   202  	if n.EnableNodeUpdateEvent {
   203  		n.NodeUpdateEvent <- newNode
   204  	}
   205  	return n.NodeUpdateEventError
   206  }
   207  
   208  func (n *signalNodeHandler) NodeDelete(node nodeTypes.Node) error {
   209  	if n.EnableNodeDeleteEvent {
   210  		n.NodeDeleteEvent <- node
   211  	}
   212  	return n.NodeDeleteEventError
   213  }
   214  
   215  func (n *signalNodeHandler) AllNodeValidateImplementation() {
   216  }
   217  
   218  func (n *signalNodeHandler) NodeValidateImplementation(node nodeTypes.Node) error {
   219  	if n.EnableNodeValidateImplementationEvent {
   220  		n.NodeValidateImplementationEvent <- node
   221  	}
   222  	return n.NodeValidateImplementationEventError
   223  }
   224  
   225  func (n *signalNodeHandler) NodeConfigurationChanged(config datapath.LocalNodeConfiguration) error {
   226  	return nil
   227  }
   228  
   229  func setup(tb testing.TB) {
   230  	node.SetTestLocalNodeStore()
   231  
   232  	tb.Cleanup(func() {
   233  		node.UnsetTestLocalNodeStore()
   234  	})
   235  }
   236  
   237  func TestNodeLifecycle(t *testing.T) {
   238  	setup(t)
   239  
   240  	dp := newSignalNodeHandler()
   241  	dp.EnableNodeAddEvent = true
   242  	dp.EnableNodeUpdateEvent = true
   243  	dp.EnableNodeDeleteEvent = true
   244  	ipcacheMock := newIPcacheMock()
   245  	h, _ := cell.NewSimpleHealth()
   246  	mngr, err := New(&option.DaemonConfig{ConfigPatchMutex: new(lock.RWMutex)}, ipcacheMock, newIPSetMock(), nil, NewNodeMetrics(), h)
   247  	mngr.Subscribe(dp)
   248  	require.NoError(t, err)
   249  
   250  	n1 := nodeTypes.Node{Name: "node1", Cluster: "c1", IPAddresses: []nodeTypes.Address{
   251  		{
   252  			Type: addressing.NodeInternalIP,
   253  			IP:   net.ParseIP("10.0.0.1"),
   254  		},
   255  	}}
   256  	mngr.NodeUpdated(n1)
   257  
   258  	select {
   259  	case nodeEvent := <-dp.NodeAddEvent:
   260  		require.Equal(t, n1, nodeEvent)
   261  	case nodeEvent := <-dp.NodeUpdateEvent:
   262  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   263  	case nodeEvent := <-dp.NodeDeleteEvent:
   264  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   265  	case <-time.After(3 * time.Second):
   266  		t.Errorf("timeout while waiting for NodeAdd() event for node1")
   267  	}
   268  
   269  	n2 := nodeTypes.Node{Name: "node2", Cluster: "c1", IPAddresses: []nodeTypes.Address{
   270  		{
   271  			Type: addressing.NodeInternalIP,
   272  			IP:   net.ParseIP("10.0.0.2"),
   273  		},
   274  	}}
   275  	mngr.NodeUpdated(n2)
   276  
   277  	select {
   278  	case nodeEvent := <-dp.NodeAddEvent:
   279  		require.Equal(t, n2, nodeEvent)
   280  	case nodeEvent := <-dp.NodeUpdateEvent:
   281  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   282  	case nodeEvent := <-dp.NodeDeleteEvent:
   283  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   284  	case <-time.After(3 * time.Second):
   285  		t.Errorf("timeout while waiting for NodeUpdate() event for node2")
   286  	}
   287  
   288  	nodes := mngr.GetNodes()
   289  	n, ok := nodes[n1.Identity()]
   290  	require.True(t, ok)
   291  	require.Equal(t, n1, n)
   292  
   293  	mngr.NodeDeleted(n1)
   294  	select {
   295  	case nodeEvent := <-dp.NodeDeleteEvent:
   296  		require.Equal(t, n1, nodeEvent)
   297  	case nodeEvent := <-dp.NodeAddEvent:
   298  		t.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
   299  	case nodeEvent := <-dp.NodeUpdateEvent:
   300  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   301  	case <-time.After(3 * time.Second):
   302  		t.Errorf("timeout while waiting for NodeDelete() event for node1")
   303  	}
   304  	nodes = mngr.GetNodes()
   305  	_, ok = nodes[n1.Identity()]
   306  	require.False(t, ok)
   307  
   308  	err = mngr.Stop(context.TODO())
   309  	require.NoError(t, err)
   310  }
   311  
   312  func TestMultipleSources(t *testing.T) {
   313  	setup(t)
   314  
   315  	dp := newSignalNodeHandler()
   316  	dp.EnableNodeAddEvent = true
   317  	dp.EnableNodeUpdateEvent = true
   318  	dp.EnableNodeDeleteEvent = true
   319  	ipcacheMock := newIPcacheMock()
   320  	h, _ := cell.NewSimpleHealth()
   321  	mngr, err := New(&option.DaemonConfig{ConfigPatchMutex: new(lock.RWMutex)}, ipcacheMock, newIPSetMock(), nil, NewNodeMetrics(), h)
   322  	require.NoError(t, err)
   323  	mngr.Subscribe(dp)
   324  	defer mngr.Stop(context.TODO())
   325  
   326  	n1k8s := nodeTypes.Node{Name: "node1", Cluster: "c1", Source: source.Kubernetes, IPAddresses: []nodeTypes.Address{
   327  		{
   328  			Type: addressing.NodeInternalIP,
   329  			IP:   net.ParseIP("10.0.0.1"),
   330  		},
   331  	}}
   332  	mngr.NodeUpdated(n1k8s)
   333  	select {
   334  	case nodeEvent := <-dp.NodeAddEvent:
   335  		require.Equal(t, n1k8s, nodeEvent)
   336  	case nodeEvent := <-dp.NodeUpdateEvent:
   337  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   338  	case nodeEvent := <-dp.NodeDeleteEvent:
   339  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   340  	case <-time.After(3 * time.Second):
   341  		t.Errorf("timeout while waiting for NodeAdd() event for node1")
   342  	}
   343  
   344  	// agent can overwrite kubernetes
   345  	n1agent := nodeTypes.Node{Name: "node1", Cluster: "c1", Source: source.Local, IPAddresses: []nodeTypes.Address{
   346  		{
   347  			Type: addressing.NodeInternalIP,
   348  			IP:   net.ParseIP("10.0.0.1"),
   349  		},
   350  	}}
   351  	mngr.NodeUpdated(n1agent)
   352  	select {
   353  	case nodeEvent := <-dp.NodeUpdateEvent:
   354  		require.Equal(t, n1agent, nodeEvent)
   355  	case nodeEvent := <-dp.NodeAddEvent:
   356  		t.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
   357  	case nodeEvent := <-dp.NodeDeleteEvent:
   358  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   359  	case <-time.After(3 * time.Second):
   360  		t.Errorf("timeout while waiting for NodeUpdate() event for node1")
   361  	}
   362  
   363  	// kubernetes cannot overwrite local node
   364  	mngr.NodeUpdated(n1k8s)
   365  	select {
   366  	case nodeEvent := <-dp.NodeAddEvent:
   367  		t.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
   368  	case nodeEvent := <-dp.NodeUpdateEvent:
   369  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   370  	case nodeEvent := <-dp.NodeDeleteEvent:
   371  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   372  	case <-time.After(100 * time.Millisecond):
   373  	}
   374  
   375  	// delete from kubernetes, should not remove local node
   376  	mngr.NodeDeleted(n1k8s)
   377  	select {
   378  	case nodeEvent := <-dp.NodeAddEvent:
   379  		t.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
   380  	case nodeEvent := <-dp.NodeUpdateEvent:
   381  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   382  	case nodeEvent := <-dp.NodeDeleteEvent:
   383  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   384  	case <-time.After(100 * time.Millisecond):
   385  	}
   386  
   387  	mngr.NodeDeleted(n1agent)
   388  	select {
   389  	case nodeEvent := <-dp.NodeAddEvent:
   390  		t.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
   391  	case nodeEvent := <-dp.NodeUpdateEvent:
   392  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   393  	case nodeEvent := <-dp.NodeDeleteEvent:
   394  		require.Equal(t, n1agent, nodeEvent)
   395  	case <-time.After(3 * time.Second):
   396  		t.Errorf("timeout while waiting for NodeDelete() event for node1")
   397  	}
   398  }
   399  
   400  func BenchmarkUpdateAndDeleteCycle(b *testing.B) {
   401  	ipcacheMock := newIPcacheMock()
   402  	dp := fakeTypes.NewNodeHandler()
   403  	h, _ := cell.NewSimpleHealth()
   404  	mngr, err := New(&option.DaemonConfig{ConfigPatchMutex: new(lock.RWMutex)}, ipcacheMock, newIPSetMock(), nil, NewNodeMetrics(), h)
   405  	require.NoError(b, err)
   406  	mngr.Subscribe(dp)
   407  	defer mngr.Stop(context.TODO())
   408  
   409  	b.ResetTimer()
   410  	for i := 0; i < b.N; i++ {
   411  		n := nodeTypes.Node{Name: fmt.Sprintf("%d", i), Source: source.Local}
   412  		mngr.NodeUpdated(n)
   413  	}
   414  
   415  	for i := 0; i < b.N; i++ {
   416  		n := nodeTypes.Node{Name: fmt.Sprintf("%d", i), Source: source.Local}
   417  		mngr.NodeDeleted(n)
   418  	}
   419  	b.StopTimer()
   420  }
   421  
   422  func TestClusterSizeDependantInterval(t *testing.T) {
   423  	setup(t)
   424  
   425  	ipcacheMock := newIPcacheMock()
   426  	dp := fakeTypes.NewNodeHandler()
   427  	h, _ := cell.NewSimpleHealth()
   428  	mngr, err := New(&option.DaemonConfig{ConfigPatchMutex: new(lock.RWMutex)}, ipcacheMock, newIPSetMock(), nil, NewNodeMetrics(), h)
   429  	require.NoError(t, err)
   430  	mngr.Subscribe(dp)
   431  	defer mngr.Stop(context.TODO())
   432  
   433  	prevInterval := time.Nanosecond
   434  
   435  	for i := 0; i < 1000; i++ {
   436  		n := nodeTypes.Node{Name: fmt.Sprintf("%d", i), Source: source.Local, IPAddresses: []nodeTypes.Address{
   437  			{
   438  				Type: addressing.NodeInternalIP,
   439  				IP:   net.ParseIP("10.0.0.1"),
   440  			},
   441  		}}
   442  		mngr.NodeUpdated(n)
   443  		newInterval := mngr.ClusterSizeDependantInterval(time.Minute)
   444  		assert.Greater(t, newInterval, prevInterval)
   445  	}
   446  }
   447  
   448  func TestBackgroundSync(t *testing.T) {
   449  	signalNodeHandler := newSignalNodeHandler()
   450  	signalNodeHandler.EnableNodeValidateImplementationEvent = true
   451  	ipcacheMock := newIPcacheMock()
   452  	h, _ := cell.NewSimpleHealth()
   453  	mngr, err := New(&option.DaemonConfig{ConfigPatchMutex: new(lock.RWMutex)}, ipcacheMock, newIPSetMock(), nil, NewNodeMetrics(), h)
   454  	mngr.Subscribe(signalNodeHandler)
   455  	require.NoError(t, err)
   456  	defer mngr.Stop(context.TODO())
   457  
   458  	numNodes := 128
   459  
   460  	allNodeValidateCallsReceived := &sync.WaitGroup{}
   461  	allNodeValidateCallsReceived.Add(1)
   462  
   463  	go func() {
   464  		nodeValidationsReceived := 0
   465  		timer, timerDone := inctimer.New()
   466  		defer timerDone()
   467  		for {
   468  			select {
   469  			case <-signalNodeHandler.NodeValidateImplementationEvent:
   470  				nodeValidationsReceived++
   471  				if nodeValidationsReceived >= numNodes {
   472  					allNodeValidateCallsReceived.Done()
   473  					return
   474  				}
   475  			case <-timer.After(time.Second * 1):
   476  				t.Errorf("Timeout while waiting for NodeValidateImplementation() to be called")
   477  				allNodeValidateCallsReceived.Done()
   478  				return
   479  			}
   480  		}
   481  	}()
   482  
   483  	for i := 0; i < numNodes; i++ {
   484  		n := nodeTypes.Node{Name: fmt.Sprintf("%d", i), Source: source.Kubernetes, IPAddresses: []nodeTypes.Address{
   485  			{
   486  				Type: addressing.NodeInternalIP,
   487  				IP:   net.ParseIP("10.0.0.1"),
   488  			},
   489  		}}
   490  		mngr.NodeUpdated(n)
   491  	}
   492  
   493  	mngr.singleBackgroundLoop(context.Background(), time.Millisecond)
   494  
   495  	allNodeValidateCallsReceived.Wait()
   496  }
   497  
   498  func TestIpcache(t *testing.T) {
   499  	ipcacheMock := newIPcacheMock()
   500  	dp := newSignalNodeHandler()
   501  	h, _ := cell.NewSimpleHealth()
   502  	mngr, err := New(&option.DaemonConfig{ConfigPatchMutex: new(lock.RWMutex)}, ipcacheMock, newIPSetMock(), nil, NewNodeMetrics(), h)
   503  	require.NoError(t, err)
   504  	mngr.Subscribe(dp)
   505  	defer mngr.Stop(context.TODO())
   506  
   507  	n1 := nodeTypes.Node{
   508  		Name:    "node1",
   509  		Cluster: "c1",
   510  		IPAddresses: []nodeTypes.Address{
   511  			{Type: addressing.NodeCiliumInternalIP, IP: net.ParseIP("1.1.1.1")},
   512  			{Type: addressing.NodeInternalIP, IP: net.ParseIP("10.0.0.2")},
   513  			{Type: addressing.NodeExternalIP, IP: net.ParseIP("f00d::1")},
   514  		},
   515  	}
   516  	mngr.NodeUpdated(n1)
   517  
   518  	select {
   519  	case event := <-ipcacheMock.events:
   520  		require.Equal(t, nodeEvent{event: "upsert", prefix: netip.PrefixFrom(netip.MustParseAddr("1.1.1.1"), 32)}, event)
   521  	case <-time.After(5 * time.Second):
   522  		t.Errorf("timeout while waiting for ipcache upsert for IP 1.1.1.1")
   523  	}
   524  
   525  	select {
   526  	case event := <-ipcacheMock.events:
   527  		require.Equal(t, nodeEvent{event: "upsert", prefix: netip.PrefixFrom(netip.MustParseAddr("10.0.0.2"), 32)}, event)
   528  	case <-time.After(5 * time.Second):
   529  		t.Errorf("timeout while waiting for ipcache upsert for IP 10.0.0.2")
   530  	}
   531  
   532  	select {
   533  	case event := <-ipcacheMock.events:
   534  		require.Equal(t, nodeEvent{event: "upsert", prefix: netip.PrefixFrom(netip.MustParseAddr("f00d::1"), 128)}, event)
   535  	case <-time.After(5 * time.Second):
   536  		t.Errorf("timeout while waiting for ipcache upsert for IP f00d::1")
   537  	}
   538  
   539  	select {
   540  	case event := <-ipcacheMock.events:
   541  		t.Errorf("unexected ipcache interaction %+v", event)
   542  	default:
   543  	}
   544  
   545  	mngr.NodeDeleted(n1)
   546  
   547  	select {
   548  	case event := <-ipcacheMock.events:
   549  		require.Equal(t, nodeEvent{event: "delete", prefix: netip.PrefixFrom(netip.MustParseAddr("1.1.1.1"), 32)}, event)
   550  	case <-time.After(5 * time.Second):
   551  		t.Errorf("timeout while waiting for ipcache delete for IP 1.1.1.1")
   552  	}
   553  
   554  	select {
   555  	case event := <-ipcacheMock.events:
   556  		require.Equal(t, nodeEvent{event: "delete", prefix: netip.PrefixFrom(netip.MustParseAddr("10.0.0.2"), 32)}, event)
   557  	case <-time.After(5 * time.Second):
   558  		t.Errorf("timeout while waiting for ipcache delete for IP 10.0.0.2")
   559  	}
   560  
   561  	select {
   562  	case event := <-ipcacheMock.events:
   563  		require.Equal(t, nodeEvent{event: "delete", prefix: netip.PrefixFrom(netip.MustParseAddr("f00d::1"), 128)}, event)
   564  	case <-time.After(5 * time.Second):
   565  		t.Errorf("timeout while waiting for ipcache delete for IP f00d::1")
   566  	}
   567  
   568  	select {
   569  	case event := <-ipcacheMock.events:
   570  		t.Errorf("unexected ipcache interaction %+v", event)
   571  	default:
   572  	}
   573  }
   574  
   575  func TestIpcacheHealthIP(t *testing.T) {
   576  	ipcacheMock := newIPcacheMock()
   577  	dp := newSignalNodeHandler()
   578  	h, _ := cell.NewSimpleHealth()
   579  	mngr, err := New(&option.DaemonConfig{ConfigPatchMutex: new(lock.RWMutex)}, ipcacheMock, newIPSetMock(), nil, NewNodeMetrics(), h)
   580  	require.NoError(t, err)
   581  	mngr.Subscribe(dp)
   582  	defer mngr.Stop(context.TODO())
   583  
   584  	n1 := nodeTypes.Node{
   585  		Name:    "node1",
   586  		Cluster: "c1",
   587  		IPAddresses: []nodeTypes.Address{
   588  			{Type: addressing.NodeCiliumInternalIP, IP: net.ParseIP("1.1.1.1").To4()},
   589  		},
   590  		IPv4HealthIP: net.ParseIP("10.0.0.4"),
   591  		IPv6HealthIP: net.ParseIP("f00d::4"),
   592  	}
   593  	mngr.NodeUpdated(n1)
   594  
   595  	select {
   596  	case event := <-ipcacheMock.events:
   597  		require.Equal(t, nodeEvent{event: "upsert", prefix: netip.PrefixFrom(netip.MustParseAddr("1.1.1.1"), 32)}, event)
   598  	case <-time.After(5 * time.Second):
   599  		t.Errorf("timeout while waiting for ipcache upsert for IP 1.1.1.1")
   600  	}
   601  
   602  	select {
   603  	case event := <-ipcacheMock.events:
   604  		require.Equal(t, nodeEvent{event: "upsert", prefix: netip.PrefixFrom(netip.MustParseAddr("10.0.0.4"), 32)}, event)
   605  	case <-time.After(5 * time.Second):
   606  		t.Errorf("timeout while waiting for ipcache upsert for IP 10.0.0.4")
   607  	}
   608  
   609  	select {
   610  	case event := <-ipcacheMock.events:
   611  		require.Equal(t, nodeEvent{event: "upsert", prefix: netip.PrefixFrom(netip.MustParseAddr("f00d::4"), 128)}, event)
   612  	case <-time.After(5 * time.Second):
   613  		t.Errorf("timeout while waiting for ipcache upsert for IP f00d::4")
   614  	}
   615  
   616  	select {
   617  	case event := <-ipcacheMock.events:
   618  		t.Errorf("unexected ipcache interaction %+v", event)
   619  	default:
   620  	}
   621  
   622  	mngr.NodeDeleted(n1)
   623  
   624  	select {
   625  	case event := <-ipcacheMock.events:
   626  		require.Equal(t, nodeEvent{event: "delete", prefix: netip.PrefixFrom(netip.MustParseAddr("1.1.1.1"), 32)}, event)
   627  	case <-time.After(5 * time.Second):
   628  		t.Errorf("timeout while waiting for ipcache delete for IP 1.1.1.1")
   629  	}
   630  
   631  	select {
   632  	case event := <-ipcacheMock.events:
   633  		require.Equal(t, nodeEvent{event: "delete", prefix: netip.PrefixFrom(netip.MustParseAddr("10.0.0.4"), 32)}, event)
   634  	case <-time.After(5 * time.Second):
   635  		t.Errorf("timeout while waiting for ipcache delete for IP 10.0.0.4")
   636  	}
   637  
   638  	select {
   639  	case event := <-ipcacheMock.events:
   640  		require.Equal(t, nodeEvent{event: "delete", prefix: netip.PrefixFrom(netip.MustParseAddr("f00d::4"), 128)}, event)
   641  	case <-time.After(5 * time.Second):
   642  		t.Errorf("timeout while waiting for ipcache delete for IP f00d::4")
   643  	}
   644  
   645  	select {
   646  	case event := <-ipcacheMock.events:
   647  		t.Errorf("unexected ipcache interaction %+v", event)
   648  	default:
   649  	}
   650  }
   651  
   652  func TestNodeEncryption(t *testing.T) {
   653  	setup(t)
   654  
   655  	ipcacheMock := newIPcacheMock()
   656  	dp := newSignalNodeHandler()
   657  	h, _ := cell.NewSimpleHealth()
   658  	mngr, err := New(&option.DaemonConfig{
   659  		ConfigPatchMutex: new(lock.RWMutex),
   660  		EncryptNode:      true,
   661  		EnableIPSec:      true,
   662  	}, ipcacheMock, newIPSetMock(), nil, NewNodeMetrics(), h)
   663  	require.NoError(t, err)
   664  	mngr.Subscribe(dp)
   665  	defer mngr.Stop(context.TODO())
   666  
   667  	n1 := nodeTypes.Node{
   668  		Name:    "node1",
   669  		Cluster: "c1",
   670  		IPAddresses: []nodeTypes.Address{
   671  			{Type: addressing.NodeCiliumInternalIP, IP: net.ParseIP("1.1.1.1")},
   672  			{Type: addressing.NodeInternalIP, IP: net.ParseIP("10.0.0.2")},
   673  			{Type: addressing.NodeExternalIP, IP: net.ParseIP("f00d::1")},
   674  		},
   675  	}
   676  	mngr.NodeUpdated(n1)
   677  
   678  	select {
   679  	case event := <-ipcacheMock.events:
   680  		require.Equal(t, nodeEvent{event: "upsert", prefix: netip.PrefixFrom(netip.MustParseAddr("1.1.1.1"), 32)}, event)
   681  	case <-time.After(5 * time.Second):
   682  		t.Errorf("timeout while waiting for ipcache upsert for IP 1.1.1.1")
   683  	}
   684  
   685  	select {
   686  	case event := <-ipcacheMock.events:
   687  		require.Equal(t, nodeEvent{event: "upsert", prefix: netip.PrefixFrom(netip.MustParseAddr("10.0.0.2"), 32)}, event)
   688  	case <-time.After(5 * time.Second):
   689  		t.Errorf("timeout while waiting for ipcache upsert for IP 10.0.0.2")
   690  	}
   691  
   692  	select {
   693  	case event := <-ipcacheMock.events:
   694  		require.Equal(t, nodeEvent{event: "upsert", prefix: netip.PrefixFrom(netip.MustParseAddr("f00d::1"), 128)}, event)
   695  	case <-time.After(5 * time.Second):
   696  		t.Errorf("timeout while waiting for ipcache upsert for IP f00d::1")
   697  	}
   698  
   699  	select {
   700  	case event := <-ipcacheMock.events:
   701  		t.Errorf("unexected ipcache interaction %+v", event)
   702  	default:
   703  	}
   704  
   705  	mngr.NodeDeleted(n1)
   706  
   707  	select {
   708  	case event := <-ipcacheMock.events:
   709  		require.Equal(t, nodeEvent{event: "delete", prefix: netip.PrefixFrom(netip.MustParseAddr("1.1.1.1"), 32)}, event)
   710  	case <-time.After(5 * time.Second):
   711  		t.Errorf("timeout while waiting for ipcache delete for IP 1.1.1.1")
   712  	}
   713  
   714  	select {
   715  	case event := <-ipcacheMock.events:
   716  		require.Equal(t, nodeEvent{event: "delete", prefix: netip.PrefixFrom(netip.MustParseAddr("10.0.0.2"), 32)}, event)
   717  	case <-time.After(5 * time.Second):
   718  		t.Errorf("timeout while waiting for ipcache delete for IP 10.0.0.2")
   719  	}
   720  
   721  	select {
   722  	case event := <-ipcacheMock.events:
   723  		require.Equal(t, nodeEvent{event: "delete", prefix: netip.PrefixFrom(netip.MustParseAddr("f00d::1"), 128)}, event)
   724  	case <-time.After(5 * time.Second):
   725  		t.Errorf("timeout while waiting for ipcache delete for IP f00d::1")
   726  	}
   727  
   728  	select {
   729  	case event := <-ipcacheMock.events:
   730  		t.Errorf("unexected ipcache interaction %+v", event)
   731  	default:
   732  	}
   733  }
   734  
   735  func TestNode(t *testing.T) {
   736  	ipcacheMock := newIPcacheMock()
   737  	ipcacheExpect := func(eventType, ipStr string) {
   738  		select {
   739  		case event := <-ipcacheMock.events:
   740  			b := 32
   741  			if strings.Contains(ipStr, ":") {
   742  				b = 128
   743  			}
   744  			require.Equal(t, nodeEvent{event: eventType, prefix: netip.PrefixFrom(netip.MustParseAddr(ipStr), b)}, event)
   745  		case <-time.After(5 * time.Second):
   746  			t.Errorf("timeout while waiting for ipcache upsert for IP %s", ipStr)
   747  		}
   748  	}
   749  
   750  	dp := newSignalNodeHandler()
   751  	dp.EnableNodeAddEvent = true
   752  	dp.EnableNodeUpdateEvent = true
   753  	dp.EnableNodeDeleteEvent = true
   754  	h, _ := cell.NewSimpleHealth()
   755  	mngr, err := New(&option.DaemonConfig{ConfigPatchMutex: new(lock.RWMutex)}, ipcacheMock, newIPSetMock(), nil, NewNodeMetrics(), h)
   756  	require.NoError(t, err)
   757  	mngr.Subscribe(dp)
   758  	defer mngr.Stop(context.TODO())
   759  
   760  	n1 := nodeTypes.Node{
   761  		Name:    "node1",
   762  		Cluster: "c1",
   763  		IPAddresses: []nodeTypes.Address{
   764  			{
   765  				Type: addressing.NodeCiliumInternalIP,
   766  				IP:   net.ParseIP("192.0.2.1"),
   767  			},
   768  			{
   769  				Type: addressing.NodeCiliumInternalIP,
   770  				IP:   net.ParseIP("2001:DB8::1"),
   771  			},
   772  		},
   773  		IPv4HealthIP: net.ParseIP("192.0.2.2"),
   774  		IPv6HealthIP: net.ParseIP("2001:DB8::2"),
   775  		Source:       source.KVStore,
   776  	}
   777  	mngr.NodeUpdated(n1)
   778  
   779  	select {
   780  	case nodeEvent := <-dp.NodeAddEvent:
   781  		require.Equal(t, n1, nodeEvent)
   782  	case nodeEvent := <-dp.NodeUpdateEvent:
   783  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   784  	case nodeEvent := <-dp.NodeDeleteEvent:
   785  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   786  	case <-time.After(3 * time.Second):
   787  		t.Errorf("timeout while waiting for NodeAdd() event for node1")
   788  	}
   789  
   790  	ipcacheExpect("upsert", "192.0.2.1")
   791  	ipcacheExpect("upsert", "2001:DB8::1")
   792  	ipcacheExpect("upsert", "192.0.2.2")
   793  	ipcacheExpect("upsert", "2001:DB8::2")
   794  
   795  	n1V2 := n1.DeepCopy()
   796  	n1V2.IPAddresses = []nodeTypes.Address{
   797  		{
   798  			Type: addressing.NodeCiliumInternalIP,
   799  			IP:   net.ParseIP("192.0.2.10"),
   800  		},
   801  		{
   802  			// We will keep the IPv6 the same to make sure we will not delete it
   803  			Type: addressing.NodeCiliumInternalIP,
   804  			IP:   net.ParseIP("2001:DB8::1"),
   805  		},
   806  	}
   807  	n1V2.IPv4HealthIP = net.ParseIP("192.0.2.20")
   808  	n1V2.IPv6HealthIP = net.ParseIP("2001:DB8::20")
   809  	mngr.NodeUpdated(*n1V2)
   810  
   811  	select {
   812  	case nodeEvent := <-dp.NodeAddEvent:
   813  		t.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
   814  	case nodeEvent := <-dp.NodeUpdateEvent:
   815  		require.Equal(t, *n1V2, nodeEvent)
   816  	case nodeEvent := <-dp.NodeDeleteEvent:
   817  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   818  	case <-time.After(3 * time.Second):
   819  		t.Errorf("timeout while waiting for NodeUpdate() event for node2")
   820  	}
   821  
   822  	ipcacheExpect("upsert", "192.0.2.10")
   823  	ipcacheExpect("upsert", "2001:DB8::1")
   824  	ipcacheExpect("upsert", "192.0.2.20")
   825  	ipcacheExpect("upsert", "2001:DB8::20")
   826  
   827  	ipcacheExpect("delete", "192.0.2.1")
   828  	ipcacheExpect("delete", "192.0.2.2")
   829  	ipcacheExpect("delete", "2001:DB8::2")
   830  
   831  	select {
   832  	case event := <-ipcacheMock.events:
   833  		t.Errorf("Received unexpected event %+v", event)
   834  	case <-time.After(1 * time.Second):
   835  	}
   836  
   837  	nodes := mngr.GetNodes()
   838  	require.Len(t, nodes, 1)
   839  	n, ok := nodes[n1.Identity()]
   840  	require.True(t, ok)
   841  	// Needs to be the same as n2
   842  	require.Equal(t, *n1V2, n)
   843  }
   844  
   845  func TestNodeManagerEmitStatus(t *testing.T) {
   846  	// Tests health reporting on node manager.
   847  	assert := assert.New(t)
   848  
   849  	baseBackgroundSyncInterval = 1 * time.Millisecond
   850  	fn := func(m *manager, sh hive.Shutdowner, statusTable statedb.Table[types.Status], db *statedb.DB) {
   851  		defer sh.Shutdown()
   852  		m.nodes[nodeTypes.Identity{
   853  			Name:    "node1",
   854  			Cluster: "c1",
   855  		}] = &nodeEntry{node: nodeTypes.Node{Name: "node1", Cluster: "c1"}}
   856  		m.nodeHandlers = make(map[datapath.NodeHandler]struct{})
   857  		nh1 := newSignalNodeHandler()
   858  		nh1.EnableNodeValidateImplementationEvent = true
   859  		// By default this is a buffered channel, by making it a non-buffered
   860  		// channel we can sync up iterations of background sync.
   861  		nh1.NodeValidateImplementationEvent = make(chan nodeTypes.Node)
   862  		nh1.NodeValidateImplementationEventError = fmt.Errorf("test error")
   863  		m.nodeHandlers[nh1] = struct{}{}
   864  
   865  		done := make(chan struct{})
   866  		reattempt := make(chan struct{})
   867  		checkStatus := func(old statedb.Revision) (types.Status, <-chan struct{}, statedb.Revision) {
   868  			tx := db.ReadTxn()
   869  
   870  			id := types.Identifier{
   871  				Module:    cell.FullModuleID{"node_manager"},
   872  				Component: []string{"background-sync"},
   873  			}
   874  			for {
   875  				ss, cur, watch, _ := statusTable.GetWatch(tx, health.PrimaryIndex.Query(id.HealthID()))
   876  				if cur != old {
   877  					return ss, watch, cur
   878  				}
   879  				<-watch
   880  			}
   881  		}
   882  		go func() {
   883  			status, watch, rev := checkStatus(99)
   884  			assert.Equal(types.Level(""), status.Level)
   885  			<-watch
   886  			status, watch, rev = checkStatus(rev)
   887  			assert.Equal(types.LevelDegraded, string(status.Level))
   888  			close(reattempt)
   889  			<-watch
   890  			status, _, _ = checkStatus(rev)
   891  			assert.Equal(types.LevelOK, string(status.Level))
   892  		}()
   893  		go func() {
   894  			<-nh1.NodeValidateImplementationEvent
   895  			<-reattempt
   896  			nh1.NodeValidateImplementationEventError = nil
   897  			<-nh1.NodeValidateImplementationEvent
   898  			close(done)
   899  		}()
   900  		// Start the manager
   901  		assert.NoError(m.Start(context.Background()))
   902  		<-done
   903  	}
   904  	ipcacheMock := newIPcacheMock()
   905  	config := &option.DaemonConfig{ConfigPatchMutex: new(lock.RWMutex)}
   906  	err := hive.New(
   907  		cell.Provide(func() testParams {
   908  			return testParams{
   909  				Config:        config,
   910  				IPCache:       ipcacheMock,
   911  				IPSet:         newIPSetMock(),
   912  				NodeMetrics:   NewNodeMetrics(),
   913  				IPSetFilterFn: func(no *nodeTypes.Node) bool { return false },
   914  			}
   915  		}),
   916  		cell.Module("node_manager", "Node Manager", cell.Provide(New)),
   917  		cell.Invoke(fn),
   918  	).Run(hivetest.Logger(t))
   919  	assert.NoError(err)
   920  }
   921  
   922  type testParams struct {
   923  	cell.Out
   924  	Config        *option.DaemonConfig
   925  	IPCache       IPCache
   926  	IPSet         ipset.Manager
   927  	NodeMetrics   *nodeMetrics
   928  	IPSetFilterFn IPSetFilterFn
   929  }
   930  
   931  type mockUpdater struct{}
   932  
   933  func (m *mockUpdater) UpdateIdentities(_, _ identity.IdentityMap, _ *sync.WaitGroup) {}
   934  
   935  type mockTriggerer struct{}
   936  
   937  func (m *mockTriggerer) UpdatePolicyMaps(ctx context.Context, wg *sync.WaitGroup) *sync.WaitGroup {
   938  	return wg
   939  }
   940  
   941  func TestNodeWithSameInternalIP(t *testing.T) {
   942  	ctx, cancel := context.WithCancel(context.Background())
   943  	allocator := testidentity.NewMockIdentityAllocator(nil)
   944  	ipcache := ipcache.NewIPCache(&ipcache.Configuration{
   945  		Context:           ctx,
   946  		IdentityAllocator: allocator,
   947  		PolicyHandler:     &mockUpdater{},
   948  		DatapathHandler:   &mockTriggerer{},
   949  	})
   950  	defer cancel()
   951  	dp := newSignalNodeHandler()
   952  	dp.EnableNodeAddEvent = true
   953  	dp.EnableNodeUpdateEvent = true
   954  	dp.EnableNodeDeleteEvent = true
   955  	h, _ := cell.NewSimpleHealth()
   956  	mngr, err := New(&option.DaemonConfig{
   957  		ConfigPatchMutex: new(lock.RWMutex),
   958  		LocalRouterIPv4:  "169.254.4.6",
   959  	}, ipcache, newIPSetMock(), nil, NewNodeMetrics(), h)
   960  	require.NoError(t, err)
   961  	mngr.Subscribe(dp)
   962  	defer mngr.Stop(context.TODO())
   963  
   964  	n1 := nodeTypes.Node{
   965  		Name:    "node1",
   966  		Cluster: "c1",
   967  		IPAddresses: []nodeTypes.Address{
   968  			{
   969  				Type: addressing.NodeInternalIP,
   970  				IP:   net.ParseIP("10.128.0.40"),
   971  			},
   972  			{
   973  				Type: addressing.NodeExternalIP,
   974  				IP:   net.ParseIP("34.171.135.203"),
   975  			},
   976  			{
   977  				Type: addressing.NodeCiliumInternalIP,
   978  				IP:   net.ParseIP("169.254.4.6"),
   979  			},
   980  		},
   981  		Source: source.Local,
   982  	}
   983  	mngr.NodeUpdated(n1)
   984  
   985  	select {
   986  	case nodeEvent := <-dp.NodeAddEvent:
   987  		require.Equal(t, n1, nodeEvent)
   988  	case nodeEvent := <-dp.NodeUpdateEvent:
   989  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
   990  	case nodeEvent := <-dp.NodeDeleteEvent:
   991  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
   992  	case <-time.After(3 * time.Second):
   993  		t.Errorf("timeout while waiting for NodeAdd() event for node1")
   994  	}
   995  
   996  	n2 := nodeTypes.Node{
   997  		Name:    "node2",
   998  		Cluster: "c1",
   999  		IPAddresses: []nodeTypes.Address{
  1000  			{
  1001  				Type: addressing.NodeInternalIP,
  1002  				IP:   net.ParseIP("10.128.0.110"),
  1003  			},
  1004  			{
  1005  				Type: addressing.NodeExternalIP,
  1006  				IP:   net.ParseIP("34.170.71.139"),
  1007  			},
  1008  			{
  1009  				Type: addressing.NodeCiliumInternalIP,
  1010  				IP:   net.ParseIP("169.254.4.6"),
  1011  			},
  1012  		},
  1013  		Source: source.CustomResource,
  1014  	}
  1015  	mngr.NodeUpdated(n2)
  1016  
  1017  	select {
  1018  	case nodeEvent := <-dp.NodeAddEvent:
  1019  		require.Equal(t, n2, nodeEvent)
  1020  	case nodeEvent := <-dp.NodeUpdateEvent:
  1021  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
  1022  	case nodeEvent := <-dp.NodeDeleteEvent:
  1023  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
  1024  	case <-time.After(3 * time.Second):
  1025  		t.Errorf("timeout while waiting for NodeAdd() event for node1")
  1026  	}
  1027  }
  1028  
  1029  // TestNodeIpset tests that the ipset entries on the node are updated correctly
  1030  // when a node is updated or removed.
  1031  // It is inspired from TestNode() in manager_test.go.
  1032  func TestNodeIpset(t *testing.T) {
  1033  	ipsetExpect := func(ipsetMgr *ipsetMock, ip string, expected bool) {
  1034  		setName := ipset.CiliumNodeIPSetV6
  1035  		if v4 := net.ParseIP(ip).To4(); v4 != nil {
  1036  			setName = ipset.CiliumNodeIPSetV4
  1037  		}
  1038  
  1039  		found, err := ipsetContains(ipsetMgr, setName, strings.ToLower(ip))
  1040  		require.NoError(t, err)
  1041  
  1042  		if found && !expected {
  1043  			t.Errorf("ipset %s contains IP %s but it should not", setName, ip)
  1044  		}
  1045  		if !found && expected {
  1046  			t.Errorf("ipset %s does not contain expected IP %s", setName, ip)
  1047  		}
  1048  	}
  1049  
  1050  	dp := newSignalNodeHandler()
  1051  	dp.EnableNodeAddEvent = true
  1052  	dp.EnableNodeUpdateEvent = true
  1053  	dp.EnableNodeDeleteEvent = true
  1054  	filter := func(no *nodeTypes.Node) bool { return no.Name != "node1" }
  1055  	h, _ := cell.NewSimpleHealth()
  1056  	mngr, err := New(&option.DaemonConfig{
  1057  		ConfigPatchMutex:     new(lock.RWMutex),
  1058  		RoutingMode:          option.RoutingModeNative,
  1059  		EnableIPv4Masquerade: true,
  1060  	}, newIPcacheMock(), newIPSetMock(), filter, NewNodeMetrics(), h)
  1061  	mngr.Subscribe(dp)
  1062  	require.NoError(t, err)
  1063  	defer mngr.Stop(context.TODO())
  1064  
  1065  	n1 := nodeTypes.Node{
  1066  		Name:    "node1",
  1067  		Cluster: "c1",
  1068  		IPAddresses: []nodeTypes.Address{
  1069  			{
  1070  				Type: addressing.NodeCiliumInternalIP,
  1071  				IP:   net.ParseIP("192.0.2.1"),
  1072  			},
  1073  			{
  1074  				Type: addressing.NodeCiliumInternalIP,
  1075  				IP:   net.ParseIP("2001:DB8::1"),
  1076  			},
  1077  			{
  1078  				Type: addressing.NodeInternalIP,
  1079  				IP:   net.ParseIP("10.0.0.1"),
  1080  			},
  1081  			{
  1082  				Type: addressing.NodeInternalIP,
  1083  				IP:   net.ParseIP("2001:ABCD::1"),
  1084  			},
  1085  		},
  1086  		IPv4HealthIP: net.ParseIP("192.0.2.2"),
  1087  		IPv6HealthIP: net.ParseIP("2001:DB8::2"),
  1088  		Source:       source.KVStore,
  1089  	}
  1090  	mngr.NodeUpdated(n1)
  1091  
  1092  	select {
  1093  	case nodeEvent := <-dp.NodeAddEvent:
  1094  		require.Equal(t, n1, nodeEvent)
  1095  	case nodeEvent := <-dp.NodeUpdateEvent:
  1096  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
  1097  	case nodeEvent := <-dp.NodeDeleteEvent:
  1098  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
  1099  	case <-time.After(3 * time.Second):
  1100  		t.Errorf("timeout while waiting for NodeAdd() event")
  1101  	}
  1102  
  1103  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "192.0.2.1", false)
  1104  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "2001:DB8::1", false)
  1105  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "10.0.0.1", true)
  1106  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "2001:ABCD::1", true)
  1107  
  1108  	n2 := nodeTypes.Node{
  1109  		Name:    "node2",
  1110  		Cluster: "c1",
  1111  		IPAddresses: []nodeTypes.Address{
  1112  			{
  1113  				Type: addressing.NodeInternalIP,
  1114  				IP:   net.ParseIP("10.1.0.1"),
  1115  			},
  1116  			{
  1117  				Type: addressing.NodeInternalIP,
  1118  				IP:   net.ParseIP("2001:ABCE::1"),
  1119  			},
  1120  		},
  1121  		Source: source.CustomResource,
  1122  	}
  1123  	mngr.NodeUpdated(n2)
  1124  
  1125  	select {
  1126  	case nodeEvent := <-dp.NodeAddEvent:
  1127  		require.Equal(t, n2, nodeEvent)
  1128  	case nodeEvent := <-dp.NodeUpdateEvent:
  1129  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
  1130  	case nodeEvent := <-dp.NodeDeleteEvent:
  1131  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
  1132  	case <-time.After(3 * time.Second):
  1133  		t.Errorf("timeout while waiting for NodeAdd() event")
  1134  	}
  1135  
  1136  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "10.0.0.1", true)
  1137  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "2001:ABCD::1", true)
  1138  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "10.1.0.1", false)
  1139  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "2001:ABCE::1", false)
  1140  
  1141  	n1.IPv4HealthIP = net.ParseIP("192.0.2.20")
  1142  	mngr.NodeUpdated(n1)
  1143  
  1144  	select {
  1145  	case nodeEvent := <-dp.NodeAddEvent:
  1146  		t.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
  1147  	case nodeEvent := <-dp.NodeUpdateEvent:
  1148  		require.Equal(t, n1, nodeEvent)
  1149  	case nodeEvent := <-dp.NodeDeleteEvent:
  1150  		t.Errorf("Unexpected NodeDelete() event %#v", nodeEvent)
  1151  	case <-time.After(3 * time.Second):
  1152  		t.Errorf("timeout while waiting for NodeUpdate() event")
  1153  	}
  1154  
  1155  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "192.0.2.1", false)
  1156  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "2001:DB8::1", false)
  1157  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "10.0.0.1", true)
  1158  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "2001:ABCD::1", true)
  1159  
  1160  	mngr.NodeDeleted(n1)
  1161  	select {
  1162  	case nodeEvent := <-dp.NodeDeleteEvent:
  1163  		require.Equal(t, n1, nodeEvent)
  1164  	case nodeEvent := <-dp.NodeAddEvent:
  1165  		t.Errorf("Unexpected NodeAdd() event %#v", nodeEvent)
  1166  	case nodeEvent := <-dp.NodeUpdateEvent:
  1167  		t.Errorf("Unexpected NodeUpdate() event %#v", nodeEvent)
  1168  	case <-time.After(3 * time.Second):
  1169  		t.Errorf("timeout while waiting for NodeDelete() event")
  1170  	}
  1171  
  1172  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "192.0.2.1", false)
  1173  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "2001:DB8::1", false)
  1174  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "10.0.0.1", false)
  1175  	ipsetExpect(mngr.ipsetMgr.(*ipsetMock), "2001:ABCD::1", false)
  1176  }
  1177  
  1178  // Tests that the node manager calls delete on nodes to be pruned.
  1179  func TestNodesStartupPruning(t *testing.T) {
  1180  	n1 := nodeTypes.Node{Name: "node1", Cluster: "c1", IPAddresses: []nodeTypes.Address{
  1181  		{
  1182  			Type: addressing.NodeInternalIP,
  1183  			IP:   net.ParseIP("10.0.0.1"),
  1184  		},
  1185  	}}
  1186  
  1187  	n2 := nodeTypes.Node{Name: "node2", Cluster: "c1", IPAddresses: []nodeTypes.Address{
  1188  		{
  1189  			Type: addressing.NodeInternalIP,
  1190  			IP:   net.ParseIP("10.0.0.2"),
  1191  		},
  1192  	}}
  1193  
  1194  	n3 := nodeTypes.Node{Name: "node3", Cluster: "c2", IPAddresses: []nodeTypes.Address{
  1195  		{
  1196  			Type: addressing.NodeInternalIP,
  1197  			IP:   net.ParseIP("10.0.0.3"),
  1198  		},
  1199  	}}
  1200  
  1201  	// Create a nodes.json file from the above two nodes, simulating a previous instance of the agent.
  1202  	tmp, err := os.MkdirTemp("", "nodes")
  1203  	require.NoError(t, err)
  1204  	path := filepath.Join(tmp, nodesFilename)
  1205  	nf, err := os.Create(path)
  1206  	require.NoError(t, err)
  1207  	t.Cleanup(func() {
  1208  		nf.Close()
  1209  		os.Remove(path)
  1210  	})
  1211  	e := json.NewEncoder(nf)
  1212  	require.NoError(t, e.Encode([]nodeTypes.Node{n3, n2, n1}))
  1213  	require.NoError(t, nf.Sync())
  1214  	require.NoError(t, nf.Close())
  1215  
  1216  	checkNodeFileMatches := func(path string, node nodeTypes.Node) {
  1217  		// Wait until the file exists. The node deletion triggers the write, hence
  1218  		// this shouldn't take long.
  1219  		for range 10 {
  1220  			_, err := os.Stat(path)
  1221  			if err == nil {
  1222  				break
  1223  			}
  1224  			require.ErrorIs(t, err, fs.ErrNotExist)
  1225  			time.Sleep(time.Millisecond)
  1226  		}
  1227  		nwf, err := os.Open(path)
  1228  		require.NoError(t, err)
  1229  		t.Cleanup(func() {
  1230  			nwf.Close()
  1231  		})
  1232  		var nl []nodeTypes.Node
  1233  		assert.NoError(t, json.NewDecoder(nwf).Decode(&nl))
  1234  		assert.Len(t, nl, 1)
  1235  		assert.Equal(t, node, nl[0])
  1236  		require.NoError(t, os.Remove(path))
  1237  	}
  1238  
  1239  	// Create a node manager and add only node1.
  1240  	ipcacheMock := newIPcacheMock()
  1241  	dp := newSignalNodeHandler()
  1242  	dp.EnableNodeDeleteEvent = true
  1243  	h, _ := cell.NewSimpleHealth()
  1244  	mngr, err := New(&option.DaemonConfig{
  1245  		StateDir:    tmp,
  1246  		ClusterName: "c1",
  1247  	}, ipcacheMock, newIPSetMock(), nil, NewNodeMetrics(), h)
  1248  	require.NoError(t, err)
  1249  	t.Cleanup(func() {
  1250  		mngr.Stop(context.TODO())
  1251  	})
  1252  	mngr.Subscribe(dp)
  1253  	mngr.NodeUpdated(n1)
  1254  
  1255  	// Load the nodes from disk and initiate pruning. This should prune node 2
  1256  	// (since it's present in the file but not in our current view).
  1257  	mngr.restoreNodeCheckpoint()
  1258  	require.NoError(t, mngr.initNodeCheckpointer(time.Microsecond))
  1259  	// We remove our test file here to be able to tell once the nodemanager has
  1260  	// written one itself.
  1261  	require.NoError(t, os.Remove(path))
  1262  	// Declare cluster nodes synced (but not clustermesh nodes)
  1263  	mngr.NodeSync()
  1264  
  1265  	select {
  1266  	case dn := <-dp.NodeDeleteEvent:
  1267  		n2r := n2
  1268  		n2r.Source = source.Restored
  1269  		assert.Equal(t, n2r, dn, "should have deleted node 2 and (with source=Restored)")
  1270  	case <-time.After(time.Second * 5):
  1271  		t.Fatal("should have received a node deletion event for node 2")
  1272  	}
  1273  
  1274  	checkNodeFileMatches(path, n1)
  1275  
  1276  	// Allow pruning the clustermesh node.
  1277  	mngr.MeshNodeSync()
  1278  
  1279  	select {
  1280  	case dn := <-dp.NodeDeleteEvent:
  1281  		n3r := n3
  1282  		n3r.Source = source.Restored
  1283  		assert.Equal(t, n3r, dn, "should have deleted node 3 and (with source=Restored)")
  1284  	case <-time.After(time.Second * 5):
  1285  		t.Fatal("should have received a node deletion event for node 3")
  1286  	}
  1287  
  1288  	checkNodeFileMatches(path, n1)
  1289  }