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 }