-
Notifications
You must be signed in to change notification settings - Fork 8
/
cache.go
125 lines (97 loc) · 2.83 KB
/
cache.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package events
import (
"sync"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/pborman/uuid"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/util/workqueue"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)
// Go's "union type"
type eventType interface {
meta() metav1.Object
isEvent()
}
type createEvent event.CreateEvent
func (e createEvent) meta() metav1.Object {
return e.Meta
}
func (e createEvent) isEvent() {}
type updateEvent event.UpdateEvent
func (e updateEvent) meta() metav1.Object {
return e.MetaNew
}
func (e updateEvent) isEvent() {}
type deleteEvent event.DeleteEvent
func (e deleteEvent) meta() metav1.Object {
return e.Meta
}
func (e deleteEvent) isEvent() {}
type genericEvent event.GenericEvent
func (e genericEvent) meta() metav1.Object {
return e.Meta
}
func (e genericEvent) isEvent() {}
// Cache caches k8s resource events
// It implements handler.eventHandler,
// emitting reconcile Requests for its cached
// events. This allows a Reconciler to
// claim and process these custom events
type Cache interface {
// handler that receives events from controller-runtime
handler.EventHandler
// retrieve an event from the cache
Get(key string) eventType
// remove an event from the cache
Forget(key string)
}
type cache struct {
lock sync.RWMutex
// cache keys will be mapped to the reconcile.Request.Name
cache map[string]eventType
}
func NewCache() *cache {
return &cache{cache: make(map[string]eventType)}
}
func (c *cache) handleEvent(evt eventType, q workqueue.RateLimitingInterface) {
// use a UUID so the reconciler can claim this event with
// the reconcile request
key := uuid.New()
log.Log.V(1).Info("storing event", "key", key, "event", evt)
c.lock.Lock()
c.cache[key] = evt
c.lock.Unlock()
// add a request the event to the queue
// the controller will Pop() it when the request reaches the reconcile function
q.Add(reconcile.Request{NamespacedName: types.NamespacedName{
Name: key,
Namespace: "", // no namespace required
}})
}
func (c *cache) Create(evt event.CreateEvent, q workqueue.RateLimitingInterface) {
c.handleEvent(createEvent(evt), q)
}
func (c *cache) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
c.handleEvent(updateEvent(evt), q)
}
func (c *cache) Delete(evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
c.handleEvent(deleteEvent(evt), q)
}
func (c *cache) Generic(evt event.GenericEvent, q workqueue.RateLimitingInterface) {
c.handleEvent(genericEvent(evt), q)
}
// pops the event with the key
func (c *cache) Get(key string) eventType {
c.lock.RLock()
evt := c.cache[key]
c.lock.RUnlock()
return evt
}
func (c *cache) Forget(key string) {
c.lock.Lock()
delete(c.cache, key)
c.lock.Unlock()
}