github.com/cilium/cilium@v1.16.2/operator/pkg/ciliumendpointslice/reconciler_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package ciliumendpointslice
     5  
     6  import (
     7  	"context"
     8  	"testing"
     9  
    10  	"github.com/cilium/hive/cell"
    11  	"github.com/cilium/hive/hivetest"
    12  	"github.com/stretchr/testify/assert"
    13  	"k8s.io/apimachinery/pkg/runtime"
    14  	k8sTesting "k8s.io/client-go/testing"
    15  
    16  	"github.com/cilium/cilium/operator/k8s"
    17  	tu "github.com/cilium/cilium/operator/pkg/ciliumendpointslice/testutils"
    18  	"github.com/cilium/cilium/pkg/hive"
    19  	cilium_v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2"
    20  	cilium_v2a1 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1"
    21  	k8sClient "github.com/cilium/cilium/pkg/k8s/client"
    22  	"github.com/cilium/cilium/pkg/k8s/resource"
    23  	"github.com/cilium/cilium/pkg/logging"
    24  	"github.com/cilium/cilium/pkg/logging/logfields"
    25  	"github.com/cilium/cilium/pkg/metrics"
    26  )
    27  
    28  var log = logging.DefaultLogger.WithField(logfields.LogSubsys, "ces-controller")
    29  
    30  func TestReconcileCreate(t *testing.T) {
    31  	var r *reconciler
    32  	var fakeClient k8sClient.FakeClientset
    33  	m := newCESManagerFcfs(2, log).(*cesManagerFcfs)
    34  	var ciliumEndpoint resource.Resource[*cilium_v2.CiliumEndpoint]
    35  	var ciliumEndpointSlice resource.Resource[*cilium_v2a1.CiliumEndpointSlice]
    36  	var cesMetrics *Metrics
    37  	hive := hive.New(
    38  		k8sClient.FakeClientCell,
    39  		k8s.ResourcesCell,
    40  		metrics.Metric(NewMetrics),
    41  		cell.Invoke(func(
    42  			c *k8sClient.FakeClientset,
    43  			cep resource.Resource[*cilium_v2.CiliumEndpoint],
    44  			ces resource.Resource[*cilium_v2a1.CiliumEndpointSlice],
    45  			metrics *Metrics,
    46  		) error {
    47  			fakeClient = *c
    48  			ciliumEndpoint = cep
    49  			ciliumEndpointSlice = ces
    50  			cesMetrics = metrics
    51  			return nil
    52  		}),
    53  	)
    54  	tlog := hivetest.Logger(t)
    55  	hive.Start(tlog, context.Background())
    56  	r = newReconciler(context.Background(), fakeClient.CiliumFakeClientset.CiliumV2alpha1(), m, log, ciliumEndpoint, ciliumEndpointSlice, cesMetrics)
    57  	cepStore, _ := ciliumEndpoint.Store(context.Background())
    58  
    59  	var createdSlice *cilium_v2a1.CiliumEndpointSlice
    60  	fakeClient.CiliumFakeClientset.PrependReactor("create", "*", func(action k8sTesting.Action) (handled bool, ret runtime.Object, err error) {
    61  		pa := action.(k8sTesting.CreateAction)
    62  		createdSlice = pa.GetObject().(*cilium_v2a1.CiliumEndpointSlice)
    63  		return true, nil, nil
    64  	})
    65  
    66  	cep1 := tu.CreateStoreEndpoint("cep1", "ns", 1)
    67  	cepStore.CacheStore().Add(cep1)
    68  	cep2 := tu.CreateStoreEndpoint("cep2", "ns", 2)
    69  	cepStore.CacheStore().Add(cep2)
    70  	cep3 := tu.CreateStoreEndpoint("cep3", "ns", 2)
    71  	cepStore.CacheStore().Add(cep3)
    72  	m.mapping.insertCES(NewCESName("ces1"), "ns")
    73  	m.mapping.insertCES(NewCESName("ces2"), "ns")
    74  	m.mapping.insertCEP(NewCEPName("cep1", "ns"), NewCESName("ces1"))
    75  	m.mapping.insertCEP(NewCEPName("cep2", "ns"), NewCESName("ces1"))
    76  	m.mapping.insertCEP(NewCEPName("cep3", "ns"), NewCESName("ces2"))
    77  	r.reconcileCES(NewCESName("ces1"))
    78  
    79  	assert.Equal(t, "ces1", createdSlice.Name)
    80  	assert.Equal(t, 2, len(createdSlice.Endpoints))
    81  	assert.Equal(t, "ns", createdSlice.Namespace)
    82  	eps := []string{createdSlice.Endpoints[0].Name, createdSlice.Endpoints[1].Name}
    83  	assert.Contains(t, eps, "cep1")
    84  	assert.Contains(t, eps, "cep2")
    85  
    86  	hive.Stop(tlog, context.Background())
    87  }
    88  
    89  func TestReconcileUpdate(t *testing.T) {
    90  	var r *reconciler
    91  	var fakeClient k8sClient.FakeClientset
    92  	m := newCESManagerFcfs(2, log).(*cesManagerFcfs)
    93  	var ciliumEndpoint resource.Resource[*cilium_v2.CiliumEndpoint]
    94  	var ciliumEndpointSlice resource.Resource[*cilium_v2a1.CiliumEndpointSlice]
    95  	var cesMetrics *Metrics
    96  	hive := hive.New(
    97  		k8sClient.FakeClientCell,
    98  		k8s.ResourcesCell,
    99  		metrics.Metric(NewMetrics),
   100  		cell.Invoke(func(
   101  			c *k8sClient.FakeClientset,
   102  			cep resource.Resource[*cilium_v2.CiliumEndpoint],
   103  			ces resource.Resource[*cilium_v2a1.CiliumEndpointSlice],
   104  			metrics *Metrics,
   105  		) error {
   106  			fakeClient = *c
   107  			ciliumEndpoint = cep
   108  			ciliumEndpointSlice = ces
   109  			cesMetrics = metrics
   110  			return nil
   111  		}),
   112  	)
   113  
   114  	tlog := hivetest.Logger(t)
   115  	hive.Start(tlog, context.Background())
   116  	r = newReconciler(context.Background(), fakeClient.CiliumFakeClientset.CiliumV2alpha1(), m, log, ciliumEndpoint, ciliumEndpointSlice, cesMetrics)
   117  	cepStore, _ := ciliumEndpoint.Store(context.Background())
   118  	cesStore, _ := ciliumEndpointSlice.Store(context.Background())
   119  
   120  	var updatedSlice *cilium_v2a1.CiliumEndpointSlice
   121  	fakeClient.CiliumFakeClientset.PrependReactor("update", "*", func(action k8sTesting.Action) (handled bool, ret runtime.Object, err error) {
   122  		pa := action.(k8sTesting.UpdateAction)
   123  		updatedSlice = pa.GetObject().(*cilium_v2a1.CiliumEndpointSlice)
   124  		return true, nil, nil
   125  	})
   126  
   127  	cep1 := tu.CreateStoreEndpoint("cep1", "ns", 1)
   128  	cepStore.CacheStore().Add(cep1)
   129  	cep2 := tu.CreateStoreEndpoint("cep2", "ns", 2)
   130  	cepStore.CacheStore().Add(cep2)
   131  	cep3 := tu.CreateStoreEndpoint("cep3", "ns", 2)
   132  	cepStore.CacheStore().Add(cep3)
   133  	ces1 := tu.CreateStoreEndpointSlice("ces1", "ns", []cilium_v2a1.CoreCiliumEndpoint{tu.CreateManagerEndpoint("cep1", 1), tu.CreateManagerEndpoint("cep3", 2)})
   134  	cesStore.CacheStore().Add(ces1)
   135  	m.mapping.insertCES(NewCESName("ces1"), "ns")
   136  	m.mapping.insertCES(NewCESName("ces2"), "ns")
   137  	m.mapping.insertCEP(NewCEPName("cep1", "ns"), NewCESName("ces1"))
   138  	m.mapping.insertCEP(NewCEPName("cep2", "ns"), NewCESName("ces1"))
   139  	m.mapping.insertCEP(NewCEPName("cep3", "ns"), NewCESName("ces2"))
   140  	// ces1 contains cep1 and cep3, but it's mapped to cep1 and cep2
   141  	// so it's expected that after update it would contain cep1 and cep2
   142  	r.reconcileCES(NewCESName("ces1"))
   143  
   144  	assert.Equal(t, "ces1", updatedSlice.Name)
   145  	assert.Equal(t, 2, len(updatedSlice.Endpoints))
   146  	assert.Equal(t, "ns", updatedSlice.Namespace)
   147  	eps := []string{updatedSlice.Endpoints[0].Name, updatedSlice.Endpoints[1].Name}
   148  	assert.Contains(t, eps, "cep1")
   149  	assert.Contains(t, eps, "cep2")
   150  
   151  	hive.Stop(tlog, context.Background())
   152  }
   153  
   154  func TestReconcileDelete(t *testing.T) {
   155  	var r *reconciler
   156  	var fakeClient k8sClient.FakeClientset
   157  	m := newCESManagerFcfs(2, log).(*cesManagerFcfs)
   158  	var ciliumEndpoint resource.Resource[*cilium_v2.CiliumEndpoint]
   159  	var ciliumEndpointSlice resource.Resource[*cilium_v2a1.CiliumEndpointSlice]
   160  	var cesMetrics *Metrics
   161  	hive := hive.New(
   162  		k8sClient.FakeClientCell,
   163  		k8s.ResourcesCell,
   164  		metrics.Metric(NewMetrics),
   165  		cell.Invoke(func(
   166  			c *k8sClient.FakeClientset,
   167  			cep resource.Resource[*cilium_v2.CiliumEndpoint],
   168  			ces resource.Resource[*cilium_v2a1.CiliumEndpointSlice],
   169  			metrics *Metrics,
   170  		) error {
   171  			fakeClient = *c
   172  			ciliumEndpoint = cep
   173  			ciliumEndpointSlice = ces
   174  			cesMetrics = metrics
   175  			return nil
   176  		}),
   177  	)
   178  
   179  	tlog := hivetest.Logger(t)
   180  	hive.Start(tlog, context.Background())
   181  	r = newReconciler(context.Background(), fakeClient.CiliumFakeClientset.CiliumV2alpha1(), m, log, ciliumEndpoint, ciliumEndpointSlice, cesMetrics)
   182  	cepStore, _ := ciliumEndpoint.Store(context.Background())
   183  	cesStore, _ := ciliumEndpointSlice.Store(context.Background())
   184  
   185  	var deletedSlice string
   186  	fakeClient.CiliumFakeClientset.PrependReactor("delete", "*", func(action k8sTesting.Action) (handled bool, ret runtime.Object, err error) {
   187  		pa := action.(k8sTesting.DeleteAction)
   188  		deletedSlice = pa.GetName()
   189  		return true, nil, nil
   190  	})
   191  
   192  	cep1 := tu.CreateStoreEndpoint("cep1", "ns", 1)
   193  	cepStore.CacheStore().Add(cep1)
   194  	cep2 := tu.CreateStoreEndpoint("cep2", "ns", 2)
   195  	cepStore.CacheStore().Add(cep2)
   196  	cep3 := tu.CreateStoreEndpoint("cep3", "ns", 2)
   197  	cepStore.CacheStore().Add(cep3)
   198  	ces1 := tu.CreateStoreEndpointSlice("ces1", "ns", []cilium_v2a1.CoreCiliumEndpoint{tu.CreateManagerEndpoint("cep1", 1), tu.CreateManagerEndpoint("cep3", 2)})
   199  	cesStore.CacheStore().Add(ces1)
   200  	m.mapping.insertCES(NewCESName("ces1"), "ns")
   201  	m.mapping.insertCES(NewCESName("ces2"), "ns")
   202  	m.mapping.insertCEP(NewCEPName("cep1", "ns"), NewCESName("ces2"))
   203  	m.mapping.insertCEP(NewCEPName("cep2", "ns"), NewCESName("ces2"))
   204  	m.mapping.insertCEP(NewCEPName("cep3", "ns"), NewCESName("ces2"))
   205  	// ces1 contains cep1 and cep3, but it's mapped to nothing so it should be deleted
   206  	r.reconcileCES(NewCESName("ces1"))
   207  
   208  	assert.Equal(t, "ces1", deletedSlice)
   209  
   210  	hive.Stop(tlog, context.Background())
   211  }
   212  
   213  func TestReconcileNoop(t *testing.T) {
   214  	var r *reconciler
   215  	var fakeClient k8sClient.FakeClientset
   216  	m := newCESManagerFcfs(2, log).(*cesManagerFcfs)
   217  	var ciliumEndpoint resource.Resource[*cilium_v2.CiliumEndpoint]
   218  	var ciliumEndpointSlice resource.Resource[*cilium_v2a1.CiliumEndpointSlice]
   219  	var cesMetrics *Metrics
   220  	hive := hive.New(
   221  		k8sClient.FakeClientCell,
   222  		k8s.ResourcesCell,
   223  		metrics.Metric(NewMetrics),
   224  		cell.Invoke(func(
   225  			c *k8sClient.FakeClientset,
   226  			cep resource.Resource[*cilium_v2.CiliumEndpoint],
   227  			ces resource.Resource[*cilium_v2a1.CiliumEndpointSlice],
   228  			metrics *Metrics,
   229  		) error {
   230  			fakeClient = *c
   231  			ciliumEndpoint = cep
   232  			ciliumEndpointSlice = ces
   233  			cesMetrics = metrics
   234  			return nil
   235  		}),
   236  	)
   237  	tlog := hivetest.Logger(t)
   238  	hive.Start(tlog, context.Background())
   239  	r = newReconciler(context.Background(), fakeClient.CiliumFakeClientset.CiliumV2alpha1(), m, log, ciliumEndpoint, ciliumEndpointSlice, cesMetrics)
   240  	cepStore, _ := ciliumEndpoint.Store(context.Background())
   241  
   242  	noRequest := true
   243  	fakeClient.CiliumFakeClientset.PrependReactor("*", "*", func(action k8sTesting.Action) (handled bool, ret runtime.Object, err error) {
   244  		noRequest = false
   245  		return true, nil, nil
   246  	})
   247  
   248  	cep1 := tu.CreateStoreEndpoint("cep1", "ns", 1)
   249  	cepStore.CacheStore().Add(cep1)
   250  	cep2 := tu.CreateStoreEndpoint("cep2", "ns", 2)
   251  	cepStore.CacheStore().Add(cep2)
   252  	cep3 := tu.CreateStoreEndpoint("cep3", "ns", 2)
   253  	cepStore.CacheStore().Add(cep3)
   254  	m.mapping.insertCES(NewCESName("ces1"), "ns")
   255  	m.mapping.insertCES(NewCESName("ces2"), "ns")
   256  	m.mapping.insertCEP(NewCEPName("cep1", "ns"), NewCESName("ces2"))
   257  	m.mapping.insertCEP(NewCEPName("cep2", "ns"), NewCESName("ces2"))
   258  	m.mapping.insertCEP(NewCEPName("cep3", "ns"), NewCESName("ces2"))
   259  	// ces1 contains cep1 and cep3, but it's mapped to nothing so it should be deleted
   260  	r.reconcileCES(NewCESName("ces1"))
   261  
   262  	assert.Equal(t, true, noRequest)
   263  
   264  	hive.Stop(tlog, context.Background())
   265  }