github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/watch/watch.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 watch
    18  
    19  import (
    20  	"fmt"
    21  	"sync"
    22  
    23  	"k8s.io/klog/v2"
    24  
    25  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime"
    26  )
    27  
    28  // Interface can be implemented by anything that knows how to watch and report changes.
    29  type Interface interface {
    30  	// Stop stops watching. Will close the channel returned by ResultChan(). Releases
    31  	// any resources used by the watch.
    32  	Stop()
    33  
    34  	// ResultChan returns a chan which will receive all the events. If an error occurs
    35  	// or Stop() is called, the implementation will close this channel and
    36  	// release any resources used by the watch.
    37  	ResultChan() <-chan Event
    38  }
    39  
    40  // EventType defines the possible types of events.
    41  type EventType string
    42  
    43  const (
    44  	Added    EventType = "ADDED"
    45  	Modified EventType = "MODIFIED"
    46  	Deleted  EventType = "DELETED"
    47  	Bookmark EventType = "BOOKMARK"
    48  	Error    EventType = "ERROR"
    49  )
    50  
    51  var (
    52  	DefaultChanSize int32 = 100
    53  )
    54  
    55  // Event represents a single event to a watched resource.
    56  // +k8s:deepcopy-gen=true
    57  type Event struct {
    58  	Type EventType
    59  
    60  	// Object is:
    61  	//  * If Type is Added or Modified: the new state of the object.
    62  	//  * If Type is Deleted: the state of the object immediately before deletion.
    63  	//  * If Type is Bookmark: the object (instance of a type being watched) where
    64  	//    only ResourceVersion field is set. On successful restart of watch from a
    65  	//    bookmark resourceVersion, client is guaranteed to not get repeat event
    66  	//    nor miss any events.
    67  	//  * If Type is Error: *api.Status is recommended; other types may make sense
    68  	//    depending on context.
    69  	Object runtime.Object
    70  }
    71  
    72  type emptyWatch chan Event
    73  
    74  // NewEmptyWatch returns a watch interface that returns no results and is closed.
    75  // May be used in certain error conditions where no information is available but
    76  // an error is not warranted.
    77  func NewEmptyWatch() Interface {
    78  	ch := make(chan Event)
    79  	close(ch)
    80  	return emptyWatch(ch)
    81  }
    82  
    83  // Stop implements Interface
    84  func (w emptyWatch) Stop() {
    85  }
    86  
    87  // ResultChan implements Interface
    88  func (w emptyWatch) ResultChan() <-chan Event {
    89  	return chan Event(w)
    90  }
    91  
    92  // FakeWatcher lets you test anything that consumes a watch.Interface; threadsafe.
    93  type FakeWatcher struct {
    94  	result  chan Event
    95  	stopped bool
    96  	sync.Mutex
    97  }
    98  
    99  func NewFake() *FakeWatcher {
   100  	return &FakeWatcher{
   101  		result: make(chan Event),
   102  	}
   103  }
   104  
   105  func NewFakeWithChanSize(size int, blocking bool) *FakeWatcher {
   106  	return &FakeWatcher{
   107  		result: make(chan Event, size),
   108  	}
   109  }
   110  
   111  // Stop implements Interface.Stop().
   112  func (f *FakeWatcher) Stop() {
   113  	f.Lock()
   114  	defer f.Unlock()
   115  	if !f.stopped {
   116  		klog.V(4).Infof("Stopping fake watcher.")
   117  		close(f.result)
   118  		f.stopped = true
   119  	}
   120  }
   121  
   122  func (f *FakeWatcher) IsStopped() bool {
   123  	f.Lock()
   124  	defer f.Unlock()
   125  	return f.stopped
   126  }
   127  
   128  // Reset prepares the watcher to be reused.
   129  func (f *FakeWatcher) Reset() {
   130  	f.Lock()
   131  	defer f.Unlock()
   132  	f.stopped = false
   133  	f.result = make(chan Event)
   134  }
   135  
   136  func (f *FakeWatcher) ResultChan() <-chan Event {
   137  	return f.result
   138  }
   139  
   140  // Add sends an add event.
   141  func (f *FakeWatcher) Add(obj runtime.Object) {
   142  	f.result <- Event{Added, obj}
   143  }
   144  
   145  // Modify sends a modify event.
   146  func (f *FakeWatcher) Modify(obj runtime.Object) {
   147  	f.result <- Event{Modified, obj}
   148  }
   149  
   150  // Delete sends a delete event.
   151  func (f *FakeWatcher) Delete(lastValue runtime.Object) {
   152  	f.result <- Event{Deleted, lastValue}
   153  }
   154  
   155  // Error sends an Error event.
   156  func (f *FakeWatcher) Error(errValue runtime.Object) {
   157  	f.result <- Event{Error, errValue}
   158  }
   159  
   160  // Action sends an event of the requested type, for table-based testing.
   161  func (f *FakeWatcher) Action(action EventType, obj runtime.Object) {
   162  	f.result <- Event{action, obj}
   163  }
   164  
   165  // RaceFreeFakeWatcher lets you test anything that consumes a watch.Interface; threadsafe.
   166  type RaceFreeFakeWatcher struct {
   167  	result  chan Event
   168  	Stopped bool
   169  	sync.Mutex
   170  }
   171  
   172  func NewRaceFreeFake() *RaceFreeFakeWatcher {
   173  	return &RaceFreeFakeWatcher{
   174  		result: make(chan Event, DefaultChanSize),
   175  	}
   176  }
   177  
   178  // Stop implements Interface.Stop().
   179  func (f *RaceFreeFakeWatcher) Stop() {
   180  	f.Lock()
   181  	defer f.Unlock()
   182  	if !f.Stopped {
   183  		klog.V(4).Infof("Stopping fake watcher.")
   184  		close(f.result)
   185  		f.Stopped = true
   186  	}
   187  }
   188  
   189  func (f *RaceFreeFakeWatcher) IsStopped() bool {
   190  	f.Lock()
   191  	defer f.Unlock()
   192  	return f.Stopped
   193  }
   194  
   195  // Reset prepares the watcher to be reused.
   196  func (f *RaceFreeFakeWatcher) Reset() {
   197  	f.Lock()
   198  	defer f.Unlock()
   199  	f.Stopped = false
   200  	f.result = make(chan Event, DefaultChanSize)
   201  }
   202  
   203  func (f *RaceFreeFakeWatcher) ResultChan() <-chan Event {
   204  	f.Lock()
   205  	defer f.Unlock()
   206  	return f.result
   207  }
   208  
   209  // Add sends an add event.
   210  func (f *RaceFreeFakeWatcher) Add(obj runtime.Object) {
   211  	f.Lock()
   212  	defer f.Unlock()
   213  	if !f.Stopped {
   214  		select {
   215  		case f.result <- Event{Added, obj}:
   216  			return
   217  		default:
   218  			panic(fmt.Errorf("channel full"))
   219  		}
   220  	}
   221  }
   222  
   223  // Modify sends a modify event.
   224  func (f *RaceFreeFakeWatcher) Modify(obj runtime.Object) {
   225  	f.Lock()
   226  	defer f.Unlock()
   227  	if !f.Stopped {
   228  		select {
   229  		case f.result <- Event{Modified, obj}:
   230  			return
   231  		default:
   232  			panic(fmt.Errorf("channel full"))
   233  		}
   234  	}
   235  }
   236  
   237  // Delete sends a delete event.
   238  func (f *RaceFreeFakeWatcher) Delete(lastValue runtime.Object) {
   239  	f.Lock()
   240  	defer f.Unlock()
   241  	if !f.Stopped {
   242  		select {
   243  		case f.result <- Event{Deleted, lastValue}:
   244  			return
   245  		default:
   246  			panic(fmt.Errorf("channel full"))
   247  		}
   248  	}
   249  }
   250  
   251  // Error sends an Error event.
   252  func (f *RaceFreeFakeWatcher) Error(errValue runtime.Object) {
   253  	f.Lock()
   254  	defer f.Unlock()
   255  	if !f.Stopped {
   256  		select {
   257  		case f.result <- Event{Error, errValue}:
   258  			return
   259  		default:
   260  			panic(fmt.Errorf("channel full"))
   261  		}
   262  	}
   263  }
   264  
   265  // Action sends an event of the requested type, for table-based testing.
   266  func (f *RaceFreeFakeWatcher) Action(action EventType, obj runtime.Object) {
   267  	f.Lock()
   268  	defer f.Unlock()
   269  	if !f.Stopped {
   270  		select {
   271  		case f.result <- Event{action, obj}:
   272  			return
   273  		default:
   274  			panic(fmt.Errorf("channel full"))
   275  		}
   276  	}
   277  }
   278  
   279  // ProxyWatcher lets you wrap your channel in watch Interface. threadsafe.
   280  type ProxyWatcher struct {
   281  	result chan Event
   282  	stopCh chan struct{}
   283  
   284  	mutex   sync.Mutex
   285  	stopped bool
   286  }
   287  
   288  var _ Interface = &ProxyWatcher{}
   289  
   290  // NewProxyWatcher creates new ProxyWatcher by wrapping a channel
   291  func NewProxyWatcher(ch chan Event) *ProxyWatcher {
   292  	return &ProxyWatcher{
   293  		result:  ch,
   294  		stopCh:  make(chan struct{}),
   295  		stopped: false,
   296  	}
   297  }
   298  
   299  // Stop implements Interface
   300  func (pw *ProxyWatcher) Stop() {
   301  	pw.mutex.Lock()
   302  	defer pw.mutex.Unlock()
   303  	if !pw.stopped {
   304  		pw.stopped = true
   305  		close(pw.stopCh)
   306  	}
   307  }
   308  
   309  // Stopping returns true if Stop() has been called
   310  func (pw *ProxyWatcher) Stopping() bool {
   311  	pw.mutex.Lock()
   312  	defer pw.mutex.Unlock()
   313  	return pw.stopped
   314  }
   315  
   316  // ResultChan implements Interface
   317  func (pw *ProxyWatcher) ResultChan() <-chan Event {
   318  	return pw.result
   319  }
   320  
   321  // StopChan returns stop channel
   322  func (pw *ProxyWatcher) StopChan() <-chan struct{} {
   323  	return pw.stopCh
   324  }