123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- /*
- Copyright 2014 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package watch
- import (
- "fmt"
- "sync"
- "github.com/golang/glog"
- "k8s.io/apimachinery/pkg/runtime"
- )
- // Interface can be implemented by anything that knows how to watch and report changes.
- type Interface interface {
- // Stops watching. Will close the channel returned by ResultChan(). Releases
- // any resources used by the watch.
- Stop()
- // Returns a chan which will receive all the events. If an error occurs
- // or Stop() is called, this channel will be closed, in which case the
- // watch should be completely cleaned up.
- ResultChan() <-chan Event
- }
- // EventType defines the possible types of events.
- type EventType string
- const (
- Added EventType = "ADDED"
- Modified EventType = "MODIFIED"
- Deleted EventType = "DELETED"
- Error EventType = "ERROR"
- DefaultChanSize int32 = 100
- )
- // Event represents a single event to a watched resource.
- // +k8s:deepcopy-gen=true
- type Event struct {
- Type EventType
- // Object is:
- // * If Type is Added or Modified: the new state of the object.
- // * If Type is Deleted: the state of the object immediately before deletion.
- // * If Type is Error: *api.Status is recommended; other types may make sense
- // depending on context.
- Object runtime.Object
- }
- type emptyWatch chan Event
- // NewEmptyWatch returns a watch interface that returns no results and is closed.
- // May be used in certain error conditions where no information is available but
- // an error is not warranted.
- func NewEmptyWatch() Interface {
- ch := make(chan Event)
- close(ch)
- return emptyWatch(ch)
- }
- // Stop implements Interface
- func (w emptyWatch) Stop() {
- }
- // ResultChan implements Interface
- func (w emptyWatch) ResultChan() <-chan Event {
- return chan Event(w)
- }
- // FakeWatcher lets you test anything that consumes a watch.Interface; threadsafe.
- type FakeWatcher struct {
- result chan Event
- Stopped bool
- sync.Mutex
- }
- func NewFake() *FakeWatcher {
- return &FakeWatcher{
- result: make(chan Event),
- }
- }
- func NewFakeWithChanSize(size int, blocking bool) *FakeWatcher {
- return &FakeWatcher{
- result: make(chan Event, size),
- }
- }
- // Stop implements Interface.Stop().
- func (f *FakeWatcher) Stop() {
- f.Lock()
- defer f.Unlock()
- if !f.Stopped {
- glog.V(4).Infof("Stopping fake watcher.")
- close(f.result)
- f.Stopped = true
- }
- }
- func (f *FakeWatcher) IsStopped() bool {
- f.Lock()
- defer f.Unlock()
- return f.Stopped
- }
- // Reset prepares the watcher to be reused.
- func (f *FakeWatcher) Reset() {
- f.Lock()
- defer f.Unlock()
- f.Stopped = false
- f.result = make(chan Event)
- }
- func (f *FakeWatcher) ResultChan() <-chan Event {
- return f.result
- }
- // Add sends an add event.
- func (f *FakeWatcher) Add(obj runtime.Object) {
- f.result <- Event{Added, obj}
- }
- // Modify sends a modify event.
- func (f *FakeWatcher) Modify(obj runtime.Object) {
- f.result <- Event{Modified, obj}
- }
- // Delete sends a delete event.
- func (f *FakeWatcher) Delete(lastValue runtime.Object) {
- f.result <- Event{Deleted, lastValue}
- }
- // Error sends an Error event.
- func (f *FakeWatcher) Error(errValue runtime.Object) {
- f.result <- Event{Error, errValue}
- }
- // Action sends an event of the requested type, for table-based testing.
- func (f *FakeWatcher) Action(action EventType, obj runtime.Object) {
- f.result <- Event{action, obj}
- }
- // RaceFreeFakeWatcher lets you test anything that consumes a watch.Interface; threadsafe.
- type RaceFreeFakeWatcher struct {
- result chan Event
- Stopped bool
- sync.Mutex
- }
- func NewRaceFreeFake() *RaceFreeFakeWatcher {
- return &RaceFreeFakeWatcher{
- result: make(chan Event, DefaultChanSize),
- }
- }
- // Stop implements Interface.Stop().
- func (f *RaceFreeFakeWatcher) Stop() {
- f.Lock()
- defer f.Unlock()
- if !f.Stopped {
- glog.V(4).Infof("Stopping fake watcher.")
- close(f.result)
- f.Stopped = true
- }
- }
- func (f *RaceFreeFakeWatcher) IsStopped() bool {
- f.Lock()
- defer f.Unlock()
- return f.Stopped
- }
- // Reset prepares the watcher to be reused.
- func (f *RaceFreeFakeWatcher) Reset() {
- f.Lock()
- defer f.Unlock()
- f.Stopped = false
- f.result = make(chan Event, DefaultChanSize)
- }
- func (f *RaceFreeFakeWatcher) ResultChan() <-chan Event {
- f.Lock()
- defer f.Unlock()
- return f.result
- }
- // Add sends an add event.
- func (f *RaceFreeFakeWatcher) Add(obj runtime.Object) {
- f.Lock()
- defer f.Unlock()
- if !f.Stopped {
- select {
- case f.result <- Event{Added, obj}:
- return
- default:
- panic(fmt.Errorf("channel full"))
- }
- }
- }
- // Modify sends a modify event.
- func (f *RaceFreeFakeWatcher) Modify(obj runtime.Object) {
- f.Lock()
- defer f.Unlock()
- if !f.Stopped {
- select {
- case f.result <- Event{Modified, obj}:
- return
- default:
- panic(fmt.Errorf("channel full"))
- }
- }
- }
- // Delete sends a delete event.
- func (f *RaceFreeFakeWatcher) Delete(lastValue runtime.Object) {
- f.Lock()
- defer f.Unlock()
- if !f.Stopped {
- select {
- case f.result <- Event{Deleted, lastValue}:
- return
- default:
- panic(fmt.Errorf("channel full"))
- }
- }
- }
- // Error sends an Error event.
- func (f *RaceFreeFakeWatcher) Error(errValue runtime.Object) {
- f.Lock()
- defer f.Unlock()
- if !f.Stopped {
- select {
- case f.result <- Event{Error, errValue}:
- return
- default:
- panic(fmt.Errorf("channel full"))
- }
- }
- }
- // Action sends an event of the requested type, for table-based testing.
- func (f *RaceFreeFakeWatcher) Action(action EventType, obj runtime.Object) {
- f.Lock()
- defer f.Unlock()
- if !f.Stopped {
- select {
- case f.result <- Event{action, obj}:
- return
- default:
- panic(fmt.Errorf("channel full"))
- }
- }
- }
|