k8s.io/kubernetes@v1.29.3/pkg/proxy/config/config.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package config
    18  
    19  import (
    20  	"fmt"
    21  	"time"
    22  
    23  	v1 "k8s.io/api/core/v1"
    24  	discovery "k8s.io/api/discovery/v1"
    25  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    26  	coreinformers "k8s.io/client-go/informers/core/v1"
    27  	discoveryinformers "k8s.io/client-go/informers/discovery/v1"
    28  	"k8s.io/client-go/tools/cache"
    29  	"k8s.io/klog/v2"
    30  )
    31  
    32  // ServiceHandler is an abstract interface of objects which receive
    33  // notifications about service object changes.
    34  type ServiceHandler interface {
    35  	// OnServiceAdd is called whenever creation of new service object
    36  	// is observed.
    37  	OnServiceAdd(service *v1.Service)
    38  	// OnServiceUpdate is called whenever modification of an existing
    39  	// service object is observed.
    40  	OnServiceUpdate(oldService, service *v1.Service)
    41  	// OnServiceDelete is called whenever deletion of an existing service
    42  	// object is observed.
    43  	OnServiceDelete(service *v1.Service)
    44  	// OnServiceSynced is called once all the initial event handlers were
    45  	// called and the state is fully propagated to local cache.
    46  	OnServiceSynced()
    47  }
    48  
    49  // EndpointSliceHandler is an abstract interface of objects which receive
    50  // notifications about endpoint slice object changes.
    51  type EndpointSliceHandler interface {
    52  	// OnEndpointSliceAdd is called whenever creation of new endpoint slice
    53  	// object is observed.
    54  	OnEndpointSliceAdd(endpointSlice *discovery.EndpointSlice)
    55  	// OnEndpointSliceUpdate is called whenever modification of an existing
    56  	// endpoint slice object is observed.
    57  	OnEndpointSliceUpdate(oldEndpointSlice, newEndpointSlice *discovery.EndpointSlice)
    58  	// OnEndpointSliceDelete is called whenever deletion of an existing
    59  	// endpoint slice object is observed.
    60  	OnEndpointSliceDelete(endpointSlice *discovery.EndpointSlice)
    61  	// OnEndpointSlicesSynced is called once all the initial event handlers were
    62  	// called and the state is fully propagated to local cache.
    63  	OnEndpointSlicesSynced()
    64  }
    65  
    66  // EndpointSliceConfig tracks a set of endpoints configurations.
    67  type EndpointSliceConfig struct {
    68  	listerSynced  cache.InformerSynced
    69  	eventHandlers []EndpointSliceHandler
    70  }
    71  
    72  // NewEndpointSliceConfig creates a new EndpointSliceConfig.
    73  func NewEndpointSliceConfig(endpointSliceInformer discoveryinformers.EndpointSliceInformer, resyncPeriod time.Duration) *EndpointSliceConfig {
    74  	result := &EndpointSliceConfig{
    75  		listerSynced: endpointSliceInformer.Informer().HasSynced,
    76  	}
    77  
    78  	endpointSliceInformer.Informer().AddEventHandlerWithResyncPeriod(
    79  		cache.ResourceEventHandlerFuncs{
    80  			AddFunc:    result.handleAddEndpointSlice,
    81  			UpdateFunc: result.handleUpdateEndpointSlice,
    82  			DeleteFunc: result.handleDeleteEndpointSlice,
    83  		},
    84  		resyncPeriod,
    85  	)
    86  
    87  	return result
    88  }
    89  
    90  // RegisterEventHandler registers a handler which is called on every endpoint slice change.
    91  func (c *EndpointSliceConfig) RegisterEventHandler(handler EndpointSliceHandler) {
    92  	c.eventHandlers = append(c.eventHandlers, handler)
    93  }
    94  
    95  // Run waits for cache synced and invokes handlers after syncing.
    96  func (c *EndpointSliceConfig) Run(stopCh <-chan struct{}) {
    97  	klog.InfoS("Starting endpoint slice config controller")
    98  
    99  	if !cache.WaitForNamedCacheSync("endpoint slice config", stopCh, c.listerSynced) {
   100  		return
   101  	}
   102  
   103  	for _, h := range c.eventHandlers {
   104  		klog.V(3).InfoS("Calling handler.OnEndpointSlicesSynced()")
   105  		h.OnEndpointSlicesSynced()
   106  	}
   107  }
   108  
   109  func (c *EndpointSliceConfig) handleAddEndpointSlice(obj interface{}) {
   110  	endpointSlice, ok := obj.(*discovery.EndpointSlice)
   111  	if !ok {
   112  		utilruntime.HandleError(fmt.Errorf("unexpected object type: %T", obj))
   113  		return
   114  	}
   115  	for _, h := range c.eventHandlers {
   116  		klog.V(4).InfoS("Calling handler.OnEndpointSliceAdd", "endpoints", klog.KObj(endpointSlice))
   117  		h.OnEndpointSliceAdd(endpointSlice)
   118  	}
   119  }
   120  
   121  func (c *EndpointSliceConfig) handleUpdateEndpointSlice(oldObj, newObj interface{}) {
   122  	oldEndpointSlice, ok := oldObj.(*discovery.EndpointSlice)
   123  	if !ok {
   124  		utilruntime.HandleError(fmt.Errorf("unexpected object type: %T", newObj))
   125  		return
   126  	}
   127  	newEndpointSlice, ok := newObj.(*discovery.EndpointSlice)
   128  	if !ok {
   129  		utilruntime.HandleError(fmt.Errorf("unexpected object type: %T", newObj))
   130  		return
   131  	}
   132  	for _, h := range c.eventHandlers {
   133  		klog.V(4).InfoS("Calling handler.OnEndpointSliceUpdate")
   134  		h.OnEndpointSliceUpdate(oldEndpointSlice, newEndpointSlice)
   135  	}
   136  }
   137  
   138  func (c *EndpointSliceConfig) handleDeleteEndpointSlice(obj interface{}) {
   139  	endpointSlice, ok := obj.(*discovery.EndpointSlice)
   140  	if !ok {
   141  		tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
   142  		if !ok {
   143  			utilruntime.HandleError(fmt.Errorf("unexpected object type: %T", obj))
   144  			return
   145  		}
   146  		if endpointSlice, ok = tombstone.Obj.(*discovery.EndpointSlice); !ok {
   147  			utilruntime.HandleError(fmt.Errorf("unexpected object type: %T", obj))
   148  			return
   149  		}
   150  	}
   151  	for _, h := range c.eventHandlers {
   152  		klog.V(4).InfoS("Calling handler.OnEndpointsDelete")
   153  		h.OnEndpointSliceDelete(endpointSlice)
   154  	}
   155  }
   156  
   157  // ServiceConfig tracks a set of service configurations.
   158  type ServiceConfig struct {
   159  	listerSynced  cache.InformerSynced
   160  	eventHandlers []ServiceHandler
   161  }
   162  
   163  // NewServiceConfig creates a new ServiceConfig.
   164  func NewServiceConfig(serviceInformer coreinformers.ServiceInformer, resyncPeriod time.Duration) *ServiceConfig {
   165  	result := &ServiceConfig{
   166  		listerSynced: serviceInformer.Informer().HasSynced,
   167  	}
   168  
   169  	serviceInformer.Informer().AddEventHandlerWithResyncPeriod(
   170  		cache.ResourceEventHandlerFuncs{
   171  			AddFunc:    result.handleAddService,
   172  			UpdateFunc: result.handleUpdateService,
   173  			DeleteFunc: result.handleDeleteService,
   174  		},
   175  		resyncPeriod,
   176  	)
   177  
   178  	return result
   179  }
   180  
   181  // RegisterEventHandler registers a handler which is called on every service change.
   182  func (c *ServiceConfig) RegisterEventHandler(handler ServiceHandler) {
   183  	c.eventHandlers = append(c.eventHandlers, handler)
   184  }
   185  
   186  // Run waits for cache synced and invokes handlers after syncing.
   187  func (c *ServiceConfig) Run(stopCh <-chan struct{}) {
   188  	klog.InfoS("Starting service config controller")
   189  
   190  	if !cache.WaitForNamedCacheSync("service config", stopCh, c.listerSynced) {
   191  		return
   192  	}
   193  
   194  	for i := range c.eventHandlers {
   195  		klog.V(3).InfoS("Calling handler.OnServiceSynced()")
   196  		c.eventHandlers[i].OnServiceSynced()
   197  	}
   198  }
   199  
   200  func (c *ServiceConfig) handleAddService(obj interface{}) {
   201  	service, ok := obj.(*v1.Service)
   202  	if !ok {
   203  		utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", obj))
   204  		return
   205  	}
   206  	for i := range c.eventHandlers {
   207  		klog.V(4).InfoS("Calling handler.OnServiceAdd")
   208  		c.eventHandlers[i].OnServiceAdd(service)
   209  	}
   210  }
   211  
   212  func (c *ServiceConfig) handleUpdateService(oldObj, newObj interface{}) {
   213  	oldService, ok := oldObj.(*v1.Service)
   214  	if !ok {
   215  		utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", oldObj))
   216  		return
   217  	}
   218  	service, ok := newObj.(*v1.Service)
   219  	if !ok {
   220  		utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", newObj))
   221  		return
   222  	}
   223  	for i := range c.eventHandlers {
   224  		klog.V(4).InfoS("Calling handler.OnServiceUpdate")
   225  		c.eventHandlers[i].OnServiceUpdate(oldService, service)
   226  	}
   227  }
   228  
   229  func (c *ServiceConfig) handleDeleteService(obj interface{}) {
   230  	service, ok := obj.(*v1.Service)
   231  	if !ok {
   232  		tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
   233  		if !ok {
   234  			utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", obj))
   235  			return
   236  		}
   237  		if service, ok = tombstone.Obj.(*v1.Service); !ok {
   238  			utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", obj))
   239  			return
   240  		}
   241  	}
   242  	for i := range c.eventHandlers {
   243  		klog.V(4).InfoS("Calling handler.OnServiceDelete")
   244  		c.eventHandlers[i].OnServiceDelete(service)
   245  	}
   246  }
   247  
   248  // NodeHandler is an abstract interface of objects which receive
   249  // notifications about node object changes.
   250  type NodeHandler interface {
   251  	// OnNodeAdd is called whenever creation of new node object
   252  	// is observed.
   253  	OnNodeAdd(node *v1.Node)
   254  	// OnNodeUpdate is called whenever modification of an existing
   255  	// node object is observed.
   256  	OnNodeUpdate(oldNode, node *v1.Node)
   257  	// OnNodeDelete is called whenever deletion of an existing node
   258  	// object is observed.
   259  	OnNodeDelete(node *v1.Node)
   260  	// OnNodeSynced is called once all the initial event handlers were
   261  	// called and the state is fully propagated to local cache.
   262  	OnNodeSynced()
   263  }
   264  
   265  // NoopNodeHandler is a noop handler for proxiers that have not yet
   266  // implemented a full NodeHandler.
   267  type NoopNodeHandler struct{}
   268  
   269  // OnNodeAdd is a noop handler for Node creates.
   270  func (*NoopNodeHandler) OnNodeAdd(node *v1.Node) {}
   271  
   272  // OnNodeUpdate is a noop handler for Node updates.
   273  func (*NoopNodeHandler) OnNodeUpdate(oldNode, node *v1.Node) {}
   274  
   275  // OnNodeDelete is a noop handler for Node deletes.
   276  func (*NoopNodeHandler) OnNodeDelete(node *v1.Node) {}
   277  
   278  // OnNodeSynced is a noop handler for Node syncs.
   279  func (*NoopNodeHandler) OnNodeSynced() {}
   280  
   281  var _ NodeHandler = &NoopNodeHandler{}
   282  
   283  // NodeConfig tracks a set of node configurations.
   284  // It accepts "set", "add" and "remove" operations of node via channels, and invokes registered handlers on change.
   285  type NodeConfig struct {
   286  	listerSynced  cache.InformerSynced
   287  	eventHandlers []NodeHandler
   288  }
   289  
   290  // NewNodeConfig creates a new NodeConfig.
   291  func NewNodeConfig(nodeInformer coreinformers.NodeInformer, resyncPeriod time.Duration) *NodeConfig {
   292  	result := &NodeConfig{
   293  		listerSynced: nodeInformer.Informer().HasSynced,
   294  	}
   295  
   296  	nodeInformer.Informer().AddEventHandlerWithResyncPeriod(
   297  		cache.ResourceEventHandlerFuncs{
   298  			AddFunc:    result.handleAddNode,
   299  			UpdateFunc: result.handleUpdateNode,
   300  			DeleteFunc: result.handleDeleteNode,
   301  		},
   302  		resyncPeriod,
   303  	)
   304  
   305  	return result
   306  }
   307  
   308  // RegisterEventHandler registers a handler which is called on every node change.
   309  func (c *NodeConfig) RegisterEventHandler(handler NodeHandler) {
   310  	c.eventHandlers = append(c.eventHandlers, handler)
   311  }
   312  
   313  // Run starts the goroutine responsible for calling registered handlers.
   314  func (c *NodeConfig) Run(stopCh <-chan struct{}) {
   315  	klog.InfoS("Starting node config controller")
   316  
   317  	if !cache.WaitForNamedCacheSync("node config", stopCh, c.listerSynced) {
   318  		return
   319  	}
   320  
   321  	for i := range c.eventHandlers {
   322  		klog.V(3).InfoS("Calling handler.OnNodeSynced()")
   323  		c.eventHandlers[i].OnNodeSynced()
   324  	}
   325  }
   326  
   327  func (c *NodeConfig) handleAddNode(obj interface{}) {
   328  	node, ok := obj.(*v1.Node)
   329  	if !ok {
   330  		utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", obj))
   331  		return
   332  	}
   333  	for i := range c.eventHandlers {
   334  		klog.V(4).InfoS("Calling handler.OnNodeAdd")
   335  		c.eventHandlers[i].OnNodeAdd(node)
   336  	}
   337  }
   338  
   339  func (c *NodeConfig) handleUpdateNode(oldObj, newObj interface{}) {
   340  	oldNode, ok := oldObj.(*v1.Node)
   341  	if !ok {
   342  		utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", oldObj))
   343  		return
   344  	}
   345  	node, ok := newObj.(*v1.Node)
   346  	if !ok {
   347  		utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", newObj))
   348  		return
   349  	}
   350  	for i := range c.eventHandlers {
   351  		klog.V(5).InfoS("Calling handler.OnNodeUpdate")
   352  		c.eventHandlers[i].OnNodeUpdate(oldNode, node)
   353  	}
   354  }
   355  
   356  func (c *NodeConfig) handleDeleteNode(obj interface{}) {
   357  	node, ok := obj.(*v1.Node)
   358  	if !ok {
   359  		tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
   360  		if !ok {
   361  			utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", obj))
   362  			return
   363  		}
   364  		if node, ok = tombstone.Obj.(*v1.Node); !ok {
   365  			utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", obj))
   366  			return
   367  		}
   368  	}
   369  	for i := range c.eventHandlers {
   370  		klog.V(4).InfoS("Calling handler.OnNodeDelete")
   371  		c.eventHandlers[i].OnNodeDelete(node)
   372  	}
   373  }