istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/model/controller.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package model 16 17 import ( 18 "sync" 19 20 "istio.io/istio/pkg/cluster" 21 ) 22 23 type ServiceHandler func(*Service, *Service, Event) 24 25 // Controller defines an event controller loop. Proxy agent registers itself 26 // with the controller loop and receives notifications on changes to the 27 // service topology or changes to the configuration artifacts. 28 // 29 // The controller guarantees the following consistency requirement: registry 30 // view in the controller is as AT LEAST as fresh as the moment notification 31 // arrives, but MAY BE more fresh (e.g. "delete" cancels an "add" event). For 32 // example, an event for a service creation will see a service registry without 33 // the service if the event is immediately followed by the service deletion 34 // event. 35 // 36 // Handlers execute on the single worker queue in the order they are appended. 37 // Handlers receive the notification event and the associated object. Note 38 // that all handlers must be appended before starting the controller. 39 type Controller interface { 40 // Note: AppendXXXHandler is used to register high level handlers. 41 // For per cluster handlers, they should be registered by the `AppendXXXHandlerForCluster` interface. 42 43 // AppendServiceHandler notifies about changes to the service catalog. 44 AppendServiceHandler(f ServiceHandler) 45 46 // AppendWorkloadHandler notifies about changes to workloads. This differs from InstanceHandler, 47 // which deals with service instances (the result of a merge of Service and Workload) 48 AppendWorkloadHandler(f func(*WorkloadInstance, Event)) 49 50 // Run until a signal is received 51 Run(stop <-chan struct{}) 52 53 // HasSynced returns true after initial cache synchronization is complete 54 HasSynced() bool 55 } 56 57 // AggregateController is a wrapper of Controller, it supports registering handlers of a specific cluster。 58 type AggregateController interface { 59 Controller 60 // AppendServiceHandlerForCluster is similar to Controller.AppendServiceHandler, 61 // but it is used to store the handler from a specific cluster. 62 AppendServiceHandlerForCluster(clusterID cluster.ID, f ServiceHandler) 63 UnRegisterHandlersForCluster(clusterID cluster.ID) 64 } 65 66 // ControllerHandlers is a utility to help Controller implementations manage their lists of handlers. 67 type ControllerHandlers struct { 68 mutex sync.RWMutex 69 serviceHandlers []ServiceHandler 70 workloadHandlers []func(*WorkloadInstance, Event) 71 } 72 73 func (c *ControllerHandlers) AppendServiceHandler(f ServiceHandler) { 74 // Copy on write. 75 c.mutex.Lock() 76 handlers := make([]ServiceHandler, 0, len(c.serviceHandlers)+1) 77 handlers = append(handlers, c.serviceHandlers...) 78 handlers = append(handlers, f) 79 c.serviceHandlers = handlers 80 c.mutex.Unlock() 81 } 82 83 func (c *ControllerHandlers) AppendWorkloadHandler(f func(*WorkloadInstance, Event)) { 84 // Copy on write. 85 c.mutex.Lock() 86 handlers := make([]func(*WorkloadInstance, Event), 0, len(c.workloadHandlers)+1) 87 handlers = append(handlers, c.workloadHandlers...) 88 handlers = append(handlers, f) 89 c.workloadHandlers = handlers 90 c.mutex.Unlock() 91 } 92 93 func (c *ControllerHandlers) GetServiceHandlers() []ServiceHandler { 94 c.mutex.RLock() 95 defer c.mutex.RUnlock() 96 // Return a shallow copy of the array 97 return c.serviceHandlers 98 } 99 100 func (c *ControllerHandlers) GetWorkloadHandlers() []func(*WorkloadInstance, Event) { 101 c.mutex.RLock() 102 defer c.mutex.RUnlock() 103 // Return a shallow copy of the array 104 return c.workloadHandlers 105 } 106 107 func (c *ControllerHandlers) NotifyServiceHandlers(prev, curr *Service, event Event) { 108 for _, f := range c.GetServiceHandlers() { 109 f(prev, curr, event) 110 } 111 } 112 113 func (c *ControllerHandlers) NotifyWorkloadHandlers(w *WorkloadInstance, event Event) { 114 for _, f := range c.GetWorkloadHandlers() { 115 f(w, event) 116 } 117 } 118 119 // Event represents a registry update event 120 type Event int 121 122 const ( 123 // EventAdd is sent when an object is added 124 EventAdd Event = iota 125 126 // EventUpdate is sent when an object is modified 127 // Captures the modified object 128 EventUpdate 129 130 // EventDelete is sent when an object is deleted 131 // Captures the object at the last known state 132 EventDelete 133 ) 134 135 func (event Event) String() string { 136 out := "unknown" 137 switch event { 138 case EventAdd: 139 out = "add" 140 case EventUpdate: 141 out = "update" 142 case EventDelete: 143 out = "delete" 144 } 145 return out 146 }