github.com/cilium/cilium@v1.16.2/pkg/k8s/watchers/cilium_endpoint_slice.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package watchers
     5  
     6  import (
     7  	"context"
     8  	"sync"
     9  	"sync/atomic"
    10  
    11  	cilium_api_v2a1 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1"
    12  	"github.com/cilium/cilium/pkg/k8s/resource"
    13  	"github.com/cilium/cilium/pkg/k8s/watchers/subscriber"
    14  	"github.com/cilium/cilium/pkg/kvstore"
    15  )
    16  
    17  var cesNotify = subscriber.NewCES()
    18  
    19  func (k *K8sCiliumEndpointsWatcher) ciliumEndpointSliceInit(ctx context.Context, asyncControllers *sync.WaitGroup) {
    20  	log.Info("Initializing CES controller")
    21  
    22  	var once sync.Once
    23  	apiGroup := k8sAPIGroupCiliumEndpointSliceV2Alpha1
    24  
    25  	// Register for all ces updates.
    26  	cesNotify.Register(newCESSubscriber(k))
    27  
    28  	for {
    29  		var synced atomic.Bool
    30  		stop := make(chan struct{})
    31  
    32  		k.k8sResourceSynced.BlockWaitGroupToSyncResources(
    33  			stop,
    34  			nil,
    35  			func() bool { return synced.Load() },
    36  			apiGroup,
    37  		)
    38  		k.k8sAPIGroups.AddAPI(apiGroup)
    39  
    40  		// Signalize that we have put node controller in the wait group to sync resources.
    41  		once.Do(asyncControllers.Done)
    42  
    43  		// derive another context to signal Events() in case of kvstore connection
    44  		eventsCtx, cancel := context.WithCancel(ctx)
    45  
    46  		go func() {
    47  			defer close(stop)
    48  
    49  			events := k.resources.CiliumEndpointSlice.Events(eventsCtx)
    50  			cache := make(map[resource.Key]*cilium_api_v2a1.CiliumEndpointSlice)
    51  			for event := range events {
    52  				var err error
    53  				switch event.Kind {
    54  				case resource.Sync:
    55  					synced.Store(true)
    56  				case resource.Upsert:
    57  					var needUpdate bool
    58  					oldObj, ok := cache[event.Key]
    59  					if !ok {
    60  						cesNotify.NotifyAdd(event.Object)
    61  						needUpdate = true
    62  					} else if !oldObj.DeepEqual(event.Object) {
    63  						cesNotify.NotifyUpdate(oldObj, event.Object)
    64  						needUpdate = true
    65  					}
    66  					if needUpdate {
    67  						cache[event.Key] = event.Object
    68  					}
    69  				case resource.Delete:
    70  					cesNotify.NotifyDelete(event.Object)
    71  					delete(cache, event.Key)
    72  				}
    73  				event.Done(err)
    74  			}
    75  		}()
    76  
    77  		select {
    78  		case <-kvstore.Connected():
    79  			log.Info("Connected to key-value store, stopping CiliumEndpointSlice watcher")
    80  			cancel()
    81  			k.k8sResourceSynced.CancelWaitGroupToSyncResources(apiGroup)
    82  			k.k8sAPIGroups.RemoveAPI(apiGroup)
    83  			<-stop
    84  		case <-ctx.Done():
    85  			cancel()
    86  			<-stop
    87  			return
    88  		}
    89  
    90  		select {
    91  		case <-ctx.Done():
    92  			return
    93  		case <-kvstore.Client().Disconnected():
    94  			log.Info("Disconnected from key-value store, restarting CiliumEndpointSlice watcher")
    95  		}
    96  	}
    97  }