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  }