From 4438b24b695e02f0002324945525b0cc3d841065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= <charles.edouard@nirmata.com> Date: Thu, 28 Mar 2024 09:03:01 +0100 Subject: [PATCH] refactor: exception selector interface (#9907) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: exception selector interface Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> --------- Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> Co-authored-by: shuting <shuting@nirmata.com> --- .../processor/policy_processor.go | 3 +- cmd/internal/engine.go | 8 +++-- pkg/engine/api/selector.go | 15 +++----- pkg/engine/exceptions.go | 9 ++--- pkg/exceptions/selector.go | 34 +++++++++++++++++++ pkg/webhooks/resource/fake.go | 3 +- 6 files changed, 51 insertions(+), 21 deletions(-) create mode 100644 pkg/exceptions/selector.go diff --git a/cmd/cli/kubectl-kyverno/processor/policy_processor.go b/cmd/cli/kubectl-kyverno/processor/policy_processor.go index 32e245b328..34663a75cd 100644 --- a/cmd/cli/kubectl-kyverno/processor/policy_processor.go +++ b/cmd/cli/kubectl-kyverno/processor/policy_processor.go @@ -26,6 +26,7 @@ import ( "github.com/kyverno/kyverno/pkg/engine/jmespath" "github.com/kyverno/kyverno/pkg/engine/mutate/patch" "github.com/kyverno/kyverno/pkg/engine/policycontext" + "github.com/kyverno/kyverno/pkg/exceptions" "github.com/kyverno/kyverno/pkg/imageverifycache" "github.com/kyverno/kyverno/pkg/registryclient" jsonutils "github.com/kyverno/kyverno/pkg/utils/json" @@ -80,7 +81,7 @@ func (p *PolicyProcessor) ApplyPoliciesOnResource() ([]engineapi.EngineResponse, factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), nil), imageverifycache.DisabledImageVerifyCache(), store.ContextLoaderFactory(p.Store, nil), - policyExceptionLister, + exceptions.New(policyExceptionLister), ) gvk, subresource := resource.GroupVersionKind(), "" // If --cluster flag is not set, then we need to find the top level resource GVK and subresource diff --git a/cmd/internal/engine.go b/cmd/internal/engine.go index 1fd5e99564..13ff1e9062 100644 --- a/cmd/internal/engine.go +++ b/cmd/internal/engine.go @@ -18,6 +18,7 @@ import ( "github.com/kyverno/kyverno/pkg/engine/context/resolvers" "github.com/kyverno/kyverno/pkg/engine/factories" "github.com/kyverno/kyverno/pkg/engine/jmespath" + "github.com/kyverno/kyverno/pkg/exceptions" "github.com/kyverno/kyverno/pkg/imageverifycache" "github.com/kyverno/kyverno/pkg/registryclient" "k8s.io/client-go/kubernetes" @@ -66,16 +67,17 @@ func NewExceptionSelector( var exceptionsLister engineapi.PolicyExceptionSelector if enablePolicyException { factory := kyvernoinformer.NewSharedInformerFactory(kyvernoClient, resyncPeriod) - lister := factory.Kyverno().V2beta1().PolicyExceptions().Lister() + var lister exceptions.Lister if exceptionNamespace != "" { - exceptionsLister = lister.PolicyExceptions(exceptionNamespace) + lister = factory.Kyverno().V2beta1().PolicyExceptions().Lister().PolicyExceptions(exceptionNamespace) } else { - exceptionsLister = lister + lister = factory.Kyverno().V2beta1().PolicyExceptions().Lister() } // start informers and wait for cache sync if !StartInformersAndWaitForCacheSync(ctx, logger, factory) { checkError(logger, errors.New("failed to wait for cache sync"), "failed to wait for cache sync") } + exceptionsLister = exceptions.New(lister) } return exceptionsLister } diff --git a/pkg/engine/api/selector.go b/pkg/engine/api/selector.go index 44435680a9..2727b06d75 100644 --- a/pkg/engine/api/selector.go +++ b/pkg/engine/api/selector.go @@ -2,16 +2,11 @@ package api import ( kyvernov2beta1 "github.com/kyverno/kyverno/api/kyverno/v2beta1" - "k8s.io/apimachinery/pkg/labels" ) -// NamespacedResourceSelector is an abstract interface used to list namespaced resources given a label selector -// Any implementation might exist, cache based, file based, client based etc... -type NamespacedResourceSelector[T any] interface { - // List selects resources based on label selector. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []T, err error) -} - // PolicyExceptionSelector is an abstract interface used to resolve poliicy exceptions -type PolicyExceptionSelector = NamespacedResourceSelector[*kyvernov2beta1.PolicyException] +type PolicyExceptionSelector interface { + // Find returns policy exceptions matching a given policy name and rule name. + // Objects returned here must be treated as read-only. + Find(string, string) ([]*kyvernov2beta1.PolicyException, error) +} diff --git a/pkg/engine/exceptions.go b/pkg/engine/exceptions.go index 8683753c70..c925891e4d 100644 --- a/pkg/engine/exceptions.go +++ b/pkg/engine/exceptions.go @@ -3,7 +3,6 @@ package engine import ( kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov2beta1 "github.com/kyverno/kyverno/api/kyverno/v2beta1" - "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" ) @@ -16,15 +15,13 @@ func (e *engine) GetPolicyExceptions( if e.exceptionSelector == nil { return exceptions, nil } - polexs, err := e.exceptionSelector.List(labels.Everything()) + policyName := cache.MetaObjectToName(policy).String() + polexs, err := e.exceptionSelector.Find(policyName, rule) if err != nil { return exceptions, err } - policyName := cache.MetaObjectToName(policy).String() for _, polex := range polexs { - if polex.Contains(policyName, rule) { - exceptions = append(exceptions, *polex) - } + exceptions = append(exceptions, *polex) } return exceptions, nil } diff --git a/pkg/exceptions/selector.go b/pkg/exceptions/selector.go new file mode 100644 index 0000000000..486e69691b --- /dev/null +++ b/pkg/exceptions/selector.go @@ -0,0 +1,34 @@ +package exceptions + +import ( + kyvernov2beta1 "github.com/kyverno/kyverno/api/kyverno/v2beta1" + "k8s.io/apimachinery/pkg/labels" +) + +type Lister interface { + List(labels.Selector) ([]*kyvernov2beta1.PolicyException, error) +} + +type selector struct { + lister Lister +} + +func New(lister Lister) selector { + return selector{ + lister: lister, + } +} + +func (s selector) Find(policyName string, ruleName string) ([]*kyvernov2beta1.PolicyException, error) { + polexs, err := s.lister.List(labels.Everything()) + if err != nil { + return nil, err + } + var results []*kyvernov2beta1.PolicyException + for _, polex := range polexs { + if polex.Contains(policyName, ruleName) { + results = append(results, polex) + } + } + return results, nil +} diff --git a/pkg/webhooks/resource/fake.go b/pkg/webhooks/resource/fake.go index 09d78c440e..67569def92 100644 --- a/pkg/webhooks/resource/fake.go +++ b/pkg/webhooks/resource/fake.go @@ -13,6 +13,7 @@ import ( "github.com/kyverno/kyverno/pkg/engine/factories" "github.com/kyverno/kyverno/pkg/engine/jmespath" "github.com/kyverno/kyverno/pkg/event" + "github.com/kyverno/kyverno/pkg/exceptions" "github.com/kyverno/kyverno/pkg/imageverifycache" "github.com/kyverno/kyverno/pkg/metrics" "github.com/kyverno/kyverno/pkg/policycache" @@ -61,7 +62,7 @@ func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhook factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), nil), imageverifycache.DisabledImageVerifyCache(), factories.DefaultContextLoaderFactory(configMapResolver), - peLister, + exceptions.New(peLister), ), } }