github.com/cilium/cilium@v1.16.2/pkg/clustermesh/operator/remote_cluster.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package operator
     5  
     6  import (
     7  	"context"
     8  	"path"
     9  
    10  	"github.com/cilium/cilium/api/v1/models"
    11  	"github.com/cilium/cilium/pkg/clustermesh/common"
    12  	"github.com/cilium/cilium/pkg/clustermesh/types"
    13  	"github.com/cilium/cilium/pkg/clustermesh/wait"
    14  	"github.com/cilium/cilium/pkg/kvstore"
    15  	"github.com/cilium/cilium/pkg/kvstore/store"
    16  	"github.com/cilium/cilium/pkg/lock"
    17  	serviceStore "github.com/cilium/cilium/pkg/service/store"
    18  )
    19  
    20  // remoteCluster implements the clustermesh business logic on top of
    21  // common.RemoteCluster.
    22  type remoteCluster struct {
    23  	// name is the name of the cluster
    24  	name string
    25  
    26  	globalServices *common.GlobalServiceCache
    27  
    28  	// remoteServices is the shared store representing services in remote clusters
    29  	remoteServices store.WatchStore
    30  
    31  	storeFactory store.Factory
    32  
    33  	clusterAddHooks    []func(string)
    34  	clusterDeleteHooks []func(string)
    35  
    36  	// status is the function which fills the common part of the status.
    37  	status common.StatusFunc
    38  
    39  	// synced tracks the initial synchronization with the remote cluster.
    40  	synced synced
    41  }
    42  
    43  func (rc *remoteCluster) Run(ctx context.Context, backend kvstore.BackendOperations, config types.CiliumClusterConfig, ready chan<- error) {
    44  	var mgr store.WatchStoreManager
    45  	if config.Capabilities.SyncedCanaries {
    46  		mgr = rc.storeFactory.NewWatchStoreManager(backend, rc.name)
    47  	} else {
    48  		mgr = store.NewWatchStoreManagerImmediate(rc.name)
    49  	}
    50  
    51  	adapter := func(prefix string) string { return prefix }
    52  	if config.Capabilities.Cached {
    53  		adapter = kvstore.StateToCachePrefix
    54  	}
    55  
    56  	mgr.Register(adapter(serviceStore.ServiceStorePrefix), func(ctx context.Context) {
    57  		rc.remoteServices.Watch(ctx, backend, path.Join(adapter(serviceStore.ServiceStorePrefix), rc.name))
    58  	})
    59  
    60  	close(ready)
    61  	for _, clusterAddHook := range rc.clusterAddHooks {
    62  		clusterAddHook(rc.name)
    63  	}
    64  	mgr.Run(ctx)
    65  }
    66  
    67  func (rc *remoteCluster) Stop() {
    68  	rc.synced.Stop()
    69  }
    70  
    71  func (rc *remoteCluster) Remove(context.Context) {
    72  	for _, clusterDeleteHook := range rc.clusterDeleteHooks {
    73  		clusterDeleteHook(rc.name)
    74  	}
    75  	// Draining shall occur only when the configuration for the remote cluster
    76  	// is removed, and not in case the operator is shutting down, otherwise we
    77  	// would break existing connections on restart.
    78  	rc.remoteServices.Drain()
    79  }
    80  
    81  type synced struct {
    82  	wait.SyncedCommon
    83  	services *lock.StoppableWaitGroup
    84  }
    85  
    86  func newSynced() synced {
    87  	return synced{
    88  		SyncedCommon: wait.NewSyncedCommon(),
    89  		services:     lock.NewStoppableWaitGroup(),
    90  	}
    91  }
    92  
    93  // Services returns after that the initial list of shared services has been
    94  // received from the remote cluster, the remote cluster is disconnected,
    95  // or the given context is canceled.
    96  func (s *synced) Services(ctx context.Context) error {
    97  	return s.Wait(ctx, s.services.WaitChannel())
    98  }
    99  
   100  func (rc *remoteCluster) Status() *models.RemoteCluster {
   101  	status := rc.status()
   102  
   103  	status.NumSharedServices = int64(rc.remoteServices.NumEntries())
   104  
   105  	status.Synced = &models.RemoteClusterSynced{
   106  		Services: rc.remoteServices.Synced(),
   107  		// The operator does not watch nodes, endpoints and identities, hence
   108  		// let's pretend them to be synchronized by default.
   109  		Nodes:      true,
   110  		Endpoints:  true,
   111  		Identities: true,
   112  	}
   113  
   114  	status.Ready = status.Ready &&
   115  		status.Synced.Nodes && status.Synced.Services &&
   116  		status.Synced.Identities && status.Synced.Endpoints
   117  
   118  	return status
   119  }