http-add-on/pkg/k8s/watch_test.go

145 lines
3.2 KiB
Go

package k8s
import (
"context"
"fmt"
"sync"
"github.com/google/uuid"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch"
)
// closeableWatcher is a watch.Interface that can be closed
// and optionally reopened
type closeableWatcher struct {
uid uuid.UUID
mut *sync.RWMutex
ch chan watch.Event
events []watch.Event
closed bool
allowReopen bool
}
func newCloseableWatcher() *closeableWatcher {
return &closeableWatcher{
uid: uuid.New(),
mut: new(sync.RWMutex),
ch: make(chan watch.Event),
closed: false,
allowReopen: true,
}
}
func (w *closeableWatcher) String() string {
return fmt.Sprintf(
"closeableWatcher %s. events = %v",
w.uid.String(),
w.events,
)
}
func (w *closeableWatcher) Stop() {
w.mut.RLock()
defer w.mut.RUnlock()
close(w.ch)
}
func (w *closeableWatcher) ResultChan() <-chan watch.Event {
w.mut.Lock()
defer w.mut.Unlock()
if w.closed && w.allowReopen {
w.ch = make(chan watch.Event)
w.closed = false
}
return w.ch
}
func (w *closeableWatcher) closeOpenChans(allowReopen bool) {
w.mut.Lock()
defer w.mut.Unlock()
close(w.ch)
w.closed = true
w.allowReopen = allowReopen
}
func (w *closeableWatcher) Add(d *appsv1.Deployment) {
w.mut.RLock()
defer w.mut.RUnlock()
evt := watch.Event{
Type: watch.Added,
Object: d,
}
w.ch <- evt
w.events = append(w.events, evt)
}
func (w *closeableWatcher) Modify(d *appsv1.Deployment) {
w.mut.RLock()
defer w.mut.RUnlock()
evt := watch.Event{
Type: watch.Modified,
Object: d,
}
w.ch <- evt
w.events = append(w.events, evt)
}
func (w *closeableWatcher) getEvents() []watch.Event {
w.mut.RLock()
defer w.mut.RUnlock()
return w.events
}
type fakeDeploymentListerWatcher struct {
mut *sync.RWMutex
watcher *closeableWatcher
items map[string]appsv1.Deployment
}
func newFakeDeploymentListerWatcher() *fakeDeploymentListerWatcher {
w := newCloseableWatcher()
return &fakeDeploymentListerWatcher{
mut: new(sync.RWMutex),
watcher: w,
items: map[string]appsv1.Deployment{},
}
}
func (lw *fakeDeploymentListerWatcher) List(ctx context.Context, options metav1.ListOptions) (*appsv1.DeploymentList, error) {
lw.mut.Lock()
defer lw.mut.Unlock()
lst := []appsv1.Deployment{}
for _, depl := range lw.items {
lst = append(lst, depl)
}
return &appsv1.DeploymentList{Items: lst}, nil
}
func (lw *fakeDeploymentListerWatcher) Watch(ctx context.Context, options metav1.ListOptions) (watch.Interface, error) {
return lw.watcher, nil
}
func (lw *fakeDeploymentListerWatcher) getWatcher() *closeableWatcher {
return lw.watcher
}
// addDeployment adds d to the internal deployments list, or overwrites it if it
// already existed. in either case, it will be returned by a future call to List.
// in the former case, an ADD event if sent if sendEvent is true, and in the latter
// case, a MODIFY event is sent if sendEvent is true
func (lw *fakeDeploymentListerWatcher) addDeployment(d appsv1.Deployment, sendEvent bool) {
lw.mut.Lock()
defer lw.mut.Unlock()
_, existed := lw.items[d.ObjectMeta.Name]
lw.items[d.ObjectMeta.Name] = d
if sendEvent {
if existed {
lw.watcher.Modify(&d)
} else {
lw.watcher.Add(&d)
}
}
}