1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 02:18:15 +00:00

fix: report deletion fighting with garbage collection (#5486)

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2022-11-29 11:24:17 +01:00 committed by GitHub
parent 8f6c3e648c
commit dd4f1fb995
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 17 deletions

View file

@ -29,6 +29,7 @@ const (
Workers = 2
ControllerName = "admission-report-controller"
maxRetries = 10
deletionGrace = time.Minute * 2
)
type controller struct {
@ -61,7 +62,14 @@ func NewController(
queue: queue,
metadataCache: metadataCache,
}
c.metadataCache.AddEventHandler(func(uid types.UID, _ schema.GroupVersionKind, _ resource.Resource) { queue.Add(cache.ExplicitKey(uid)) })
c.metadataCache.AddEventHandler(func(eventType resource.EventType, uid types.UID, _ schema.GroupVersionKind, _ resource.Resource) {
// if it's a deletion, give some time to native garbage collection
if eventType == resource.Deleted {
queue.AddAfter(cache.ExplicitKey(uid), time.Minute)
} else {
queue.Add(cache.ExplicitKey(uid))
}
})
controllerutils.AddEventHandlersT(
admrInformer.Informer(),
func(obj metav1.Object) { queue.Add(cache.ExplicitKey(reportutils.GetResourceUid(obj))) },
@ -205,10 +213,10 @@ func (c *controller) cleanupReports(ctx context.Context, uid types.UID, hash str
var toDelete []metav1.Object
for _, report := range reports {
if report.GetName() != string(uid) {
if reportutils.GetResourceHash(report) == hash || report.GetCreationTimestamp().Add(time.Minute*2).Before(time.Now()) {
if reportutils.GetResourceHash(report) == hash || report.GetCreationTimestamp().Add(deletionGrace).Before(time.Now()) {
toDelete = append(toDelete, report)
} else {
c.queue.AddAfter(cache.ExplicitKey(uid), time.Minute*2)
c.queue.AddAfter(cache.ExplicitKey(uid), deletionGrace)
}
}
}

View file

@ -85,7 +85,11 @@ func NewController(
}
controllerutils.AddEventHandlersT(polInformer.Informer(), c.addPolicy, c.updatePolicy, c.deletePolicy)
controllerutils.AddEventHandlersT(cpolInformer.Informer(), c.addPolicy, c.updatePolicy, c.deletePolicy)
c.metadataCache.AddEventHandler(func(uid types.UID, _ schema.GroupVersionKind, resource resource.Resource) {
c.metadataCache.AddEventHandler(func(eventType resource.EventType, uid types.UID, _ schema.GroupVersionKind, res resource.Resource) {
// if it's a deletion, nothing to do
if eventType == resource.Deleted {
return
}
selector, err := reportutils.SelectorResourceUidEquals(uid)
if err != nil {
logger.Error(err, "failed to create label selector")
@ -93,10 +97,10 @@ func NewController(
if err := c.enqueue(selector); err != nil {
logger.Error(err, "failed to enqueue")
}
if resource.Namespace == "" {
if res.Namespace == "" {
c.queue.Add(string(uid))
} else {
c.queue.Add(resource.Namespace + "/" + string(uid))
c.queue.Add(res.Namespace + "/" + string(uid))
}
})
return &c

View file

@ -40,7 +40,16 @@ type Resource struct {
Hash string
}
type EventHandler func(types.UID, schema.GroupVersionKind, Resource)
type EventType string
const (
Added EventType = "ADDED"
Modified EventType = "MODIFIED"
Deleted EventType = "DELETED"
Stopped EventType = "STOPPED"
)
type EventHandler func(EventType, types.UID, schema.GroupVersionKind, Resource)
type MetadataCache interface {
GetResourceHash(uid types.UID) (Resource, schema.GroupVersionKind, bool)
@ -118,7 +127,7 @@ func (c *controller) AddEventHandler(eventHandler EventHandler) {
c.eventHandlers = append(c.eventHandlers, eventHandler)
for _, watcher := range c.dynamicWatchers {
for uid, resource := range watcher.hashes {
eventHandler(uid, watcher.gvk, resource)
eventHandler(Added, uid, watcher.gvk, resource)
}
}
}
@ -176,7 +185,7 @@ func (c *controller) updateDynamicWatchers(ctx context.Context) error {
Namespace: obj.GetNamespace(),
Name: obj.GetName(),
}
c.notify(uid, gvk, hashes[uid])
c.notify(Added, uid, gvk, hashes[uid])
}
logger := logger.WithValues("resourceVersion", resourceVersion)
logger.Info("start watcher ...")
@ -202,9 +211,9 @@ func (c *controller) updateDynamicWatchers(ctx context.Context) error {
for event := range watchInterface.ResultChan() {
switch event.Type {
case watch.Added:
c.updateHash(event.Object.(*unstructured.Unstructured), gvr)
c.updateHash(Added, event.Object.(*unstructured.Unstructured), gvr)
case watch.Modified:
c.updateHash(event.Object.(*unstructured.Unstructured), gvr)
c.updateHash(Modified, event.Object.(*unstructured.Unstructured), gvr)
case watch.Deleted:
c.deleteHash(event.Object.(*unstructured.Unstructured), gvr)
}
@ -222,7 +231,7 @@ func (c *controller) updateDynamicWatchers(ctx context.Context) error {
watcher.watcher.Stop()
delete(oldDynamicWatcher, gvr)
for uid, resource := range watcher.hashes {
c.notify(uid, watcher.gvk, resource)
c.notify(Stopped, uid, watcher.gvk, resource)
}
}
return nil
@ -237,13 +246,13 @@ func (c *controller) stopDynamicWatchers() {
c.dynamicWatchers = map[schema.GroupVersionResource]*watcher{}
}
func (c *controller) notify(uid types.UID, gvk schema.GroupVersionKind, obj Resource) {
func (c *controller) notify(eventType EventType, uid types.UID, gvk schema.GroupVersionKind, obj Resource) {
for _, handler := range c.eventHandlers {
handler(uid, gvk, obj)
handler(eventType, uid, gvk, obj)
}
}
func (c *controller) updateHash(obj *unstructured.Unstructured, gvr schema.GroupVersionResource) {
func (c *controller) updateHash(eventType EventType, obj *unstructured.Unstructured, gvr schema.GroupVersionResource) {
c.lock.Lock()
defer c.lock.Unlock()
watcher, exists := c.dynamicWatchers[gvr]
@ -256,7 +265,7 @@ func (c *controller) updateHash(obj *unstructured.Unstructured, gvr schema.Group
Namespace: obj.GetNamespace(),
Name: obj.GetName(),
}
c.notify(uid, watcher.gvk, watcher.hashes[uid])
c.notify(eventType, uid, watcher.gvk, watcher.hashes[uid])
}
}
}
@ -269,7 +278,7 @@ func (c *controller) deleteHash(obj *unstructured.Unstructured, gvr schema.Group
uid := obj.GetUID()
hash := watcher.hashes[uid]
delete(watcher.hashes, uid)
c.notify(uid, watcher.gvk, hash)
c.notify(Deleted, uid, watcher.gvk, hash)
}
}