From ff192f3dc37090714f1e8f5fbe439279c9b3d810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Fri, 5 Jul 2024 12:33:45 +0200 Subject: [PATCH] feat: don't rely on events unicity in resource counters (#10613) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- cmd/kyverno/breaker.go | 47 +++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/cmd/kyverno/breaker.go b/cmd/kyverno/breaker.go index d85cc1f5bc..aff184410d 100644 --- a/cmd/kyverno/breaker.go +++ b/cmd/kyverno/breaker.go @@ -2,28 +2,50 @@ package main import ( "context" + "sync" reportsv1 "github.com/kyverno/kyverno/api/reports/v1" watchtools "github.com/kyverno/kyverno/cmd/kyverno/watch" "github.com/kyverno/kyverno/pkg/client/informers/externalversions/internalinterfaces" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/watch" metadataclient "k8s.io/client-go/metadata" "k8s.io/client-go/tools/cache" ) +type resourceUIDGetter interface { + GetUID() types.UID +} + type Counter interface { Count() (int, bool) } type counter struct { - count int + lock sync.RWMutex + entries sets.Set[types.UID] retryWatcher *watchtools.RetryWatcher } +func (c *counter) Record(uid types.UID) { + c.lock.Lock() + defer c.lock.Unlock() + c.entries.Insert(uid) +} + +func (c *counter) Forget(uid types.UID) { + c.lock.Lock() + defer c.lock.Unlock() + c.entries.Delete(uid) +} + func (c *counter) Count() (int, bool) { - return c.count, c.retryWatcher.IsRunning() + c.lock.RLock() + defer c.lock.RUnlock() + return c.entries.Len(), c.retryWatcher.IsRunning() } func StartResourceCounter(ctx context.Context, client metadataclient.Interface, gvr schema.GroupVersionResource, tweakListOptions internalinterfaces.TweakListOptionsFunc) (*counter, error) { @@ -43,17 +65,26 @@ func StartResourceCounter(ctx context.Context, client metadataclient.Interface, if err != nil { return nil, err } + entries := sets.New[types.UID]() + for _, entry := range objs.Items { + entries.Insert(entry.GetUID()) + } w := &counter{ - count: len(objs.Items), + entries: entries, retryWatcher: watchInterface, } go func() { for event := range watchInterface.ResultChan() { - switch event.Type { - case watch.Added: - w.count = w.count + 1 - case watch.Deleted: - w.count = w.count - 1 + getter, ok := event.Object.(resourceUIDGetter) + if ok { + switch event.Type { + case watch.Added: + w.Record(getter.GetUID()) + case watch.Modified: + w.Record(getter.GetUID()) + case watch.Deleted: + w.Forget(getter.GetUID()) + } } } }()