diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go index 2dbc7ea1de..1667f312cc 100644 --- a/cmd/kyverno/main.go +++ b/cmd/kyverno/main.go @@ -30,6 +30,7 @@ import ( webhookcontroller "github.com/kyverno/kyverno/pkg/controllers/webhook" "github.com/kyverno/kyverno/pkg/cosign" "github.com/kyverno/kyverno/pkg/engine" + engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/engine/context/resolvers" "github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/leaderelection" @@ -113,7 +114,7 @@ func createNonLeaderControllers( policyCache policycache.Cache, eventGenerator event.Interface, manager openapi.Manager, - informerCacheResolvers resolvers.ConfigmapResolver, + informerCacheResolvers engineapi.ConfigmapResolver, ) ([]internal.Controller, func() error) { policyCacheController := policycachecontroller.NewController( dynamicClient, @@ -170,7 +171,7 @@ func createrLeaderControllers( eventGenerator event.Interface, certRenewer tls.CertRenewer, runtime runtimeutils.Runtime, - configMapResolver resolvers.ConfigmapResolver, + configMapResolver engineapi.ConfigmapResolver, servicePort int32, ) ([]internal.Controller, func(context.Context) error, error) { policyCtrl, err := policy.NewPolicyController( @@ -353,7 +354,7 @@ func main() { logger.Error(err, "failed to create client based resolver") os.Exit(1) } - configMapResolver, err := resolvers.NewResolverChain(informerBasedResolver, clientBasedResolver) + configMapResolver, err := engineapi.NewNamespacedResourceResolver(informerBasedResolver, clientBasedResolver) if err != nil { logger.Error(err, "failed to create config map resolver") os.Exit(1) diff --git a/cmd/reports-controller/main.go b/cmd/reports-controller/main.go index 38d882f5e6..6fd5f2aa09 100644 --- a/cmd/reports-controller/main.go +++ b/cmd/reports-controller/main.go @@ -24,6 +24,7 @@ import ( backgroundscancontroller "github.com/kyverno/kyverno/pkg/controllers/report/background" resourcereportcontroller "github.com/kyverno/kyverno/pkg/controllers/report/resource" "github.com/kyverno/kyverno/pkg/cosign" + engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/engine/context/resolvers" "github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/leaderelection" @@ -75,7 +76,7 @@ func createReportControllers( metadataFactory metadatainformers.SharedInformerFactory, kubeInformer kubeinformers.SharedInformerFactory, kyvernoInformer kyvernoinformer.SharedInformerFactory, - configMapResolver resolvers.ConfigmapResolver, + configMapResolver engineapi.ConfigmapResolver, backgroundScanInterval time.Duration, configuration config.Configuration, eventGenerator event.Interface, @@ -166,7 +167,7 @@ func createrLeaderControllers( rclient registryclient.Client, configuration config.Configuration, eventGenerator event.Interface, - configMapResolver resolvers.ConfigmapResolver, + configMapResolver engineapi.ConfigmapResolver, backgroundScanInterval time.Duration, ) ([]internal.Controller, func(context.Context) error, error) { reportControllers, warmup := createReportControllers( @@ -271,7 +272,7 @@ func main() { logger.Error(err, "failed to create client based resolver") os.Exit(1) } - configMapResolver, err := resolvers.NewResolverChain(informerBasedResolver, clientBasedResolver) + configMapResolver, err := engineapi.NewNamespacedResourceResolver(informerBasedResolver, clientBasedResolver) if err != nil { logger.Error(err, "failed to create config map resolver") os.Exit(1) diff --git a/cmd/updaterequest-controller/main.go b/cmd/updaterequest-controller/main.go index ee884d51f3..39bf6df7b3 100644 --- a/cmd/updaterequest-controller/main.go +++ b/cmd/updaterequest-controller/main.go @@ -21,6 +21,7 @@ import ( "github.com/kyverno/kyverno/pkg/config" policymetricscontroller "github.com/kyverno/kyverno/pkg/controllers/metrics/policy" "github.com/kyverno/kyverno/pkg/cosign" + engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/engine/context/resolvers" "github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/leaderelection" @@ -71,7 +72,7 @@ func createNonLeaderControllers( rclient registryclient.Client, configuration config.Configuration, eventGenerator event.Interface, - informerCacheResolvers resolvers.ConfigmapResolver, + informerCacheResolvers engineapi.ConfigmapResolver, ) []internal.Controller { updateRequestController := background.NewController( kyvernoClient, @@ -98,7 +99,7 @@ func createrLeaderControllers( configuration config.Configuration, metricsConfig metrics.MetricsConfigManager, eventGenerator event.Interface, - configMapResolver resolvers.ConfigmapResolver, + configMapResolver engineapi.ConfigmapResolver, ) ([]internal.Controller, error) { policyCtrl, err := policy.NewPolicyController( kyvernoClient, @@ -199,7 +200,7 @@ func main() { logger.Error(err, "failed to create client based resolver") os.Exit(1) } - configMapResolver, err := resolvers.NewResolverChain(informerBasedResolver, clientBasedResolver) + configMapResolver, err := engineapi.NewNamespacedResourceResolver(informerBasedResolver, clientBasedResolver) if err != nil { logger.Error(err, "failed to create config map resolver") os.Exit(1) diff --git a/pkg/background/common/context.go b/pkg/background/common/context.go index b7b557f46d..d1936214c3 100644 --- a/pkg/background/common/context.go +++ b/pkg/background/common/context.go @@ -10,8 +10,8 @@ import ( "github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/engine" + engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/engine/context" - "github.com/kyverno/kyverno/pkg/engine/context/resolvers" admissionutils "github.com/kyverno/kyverno/pkg/utils/admission" "github.com/pkg/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -21,7 +21,7 @@ func NewBackgroundContext(dclient dclient.Interface, ur *kyvernov1beta1.UpdateRe policy kyvernov1.PolicyInterface, trigger *unstructured.Unstructured, cfg config.Configuration, - informerCacheResolvers resolvers.ConfigmapResolver, + informerCacheResolvers engineapi.ConfigmapResolver, namespaceLabels map[string]string, logger logr.Logger, ) (*engine.PolicyContext, bool, error) { diff --git a/pkg/background/generate/generate.go b/pkg/background/generate/generate.go index 47b5bbb66d..ded322a1f1 100644 --- a/pkg/background/generate/generate.go +++ b/pkg/background/generate/generate.go @@ -23,7 +23,6 @@ import ( "github.com/kyverno/kyverno/pkg/engine" engineapi "github.com/kyverno/kyverno/pkg/engine/api" enginecontext "github.com/kyverno/kyverno/pkg/engine/context" - "github.com/kyverno/kyverno/pkg/engine/context/resolvers" "github.com/kyverno/kyverno/pkg/engine/variables" "github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/registryclient" @@ -53,7 +52,7 @@ type GenerateController struct { npolicyLister kyvernov1listers.PolicyLister configuration config.Configuration - informerCacheResolvers resolvers.ConfigmapResolver + informerCacheResolvers engineapi.ConfigmapResolver eventGen event.Interface log logr.Logger @@ -70,7 +69,7 @@ func NewGenerateController( urLister kyvernov1beta1listers.UpdateRequestNamespaceLister, nsLister corev1listers.NamespaceLister, dynamicConfig config.Configuration, - informerCacheResolvers resolvers.ConfigmapResolver, + informerCacheResolvers engineapi.ConfigmapResolver, eventGen event.Interface, log logr.Logger, ) *GenerateController { diff --git a/pkg/background/mutate/mutate.go b/pkg/background/mutate/mutate.go index 6b7e6cb39c..5159893893 100644 --- a/pkg/background/mutate/mutate.go +++ b/pkg/background/mutate/mutate.go @@ -14,7 +14,6 @@ import ( "github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/engine" engineapi "github.com/kyverno/kyverno/pkg/engine/api" - "github.com/kyverno/kyverno/pkg/engine/context/resolvers" "github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/utils" @@ -37,7 +36,7 @@ type MutateExistingController struct { npolicyLister kyvernov1listers.PolicyLister configuration config.Configuration - informerCacheResolvers resolvers.ConfigmapResolver + informerCacheResolvers engineapi.ConfigmapResolver eventGen event.Interface log logr.Logger @@ -51,7 +50,7 @@ func NewMutateExistingController( policyLister kyvernov1listers.ClusterPolicyLister, npolicyLister kyvernov1listers.PolicyLister, dynamicConfig config.Configuration, - informerCacheResolvers resolvers.ConfigmapResolver, + informerCacheResolvers engineapi.ConfigmapResolver, eventGen event.Interface, log logr.Logger, ) *MutateExistingController { diff --git a/pkg/background/update_request_controller.go b/pkg/background/update_request_controller.go index 92acd5f6ce..698515c52b 100644 --- a/pkg/background/update_request_controller.go +++ b/pkg/background/update_request_controller.go @@ -18,7 +18,7 @@ import ( kyvernov1beta1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1" "github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/config" - "github.com/kyverno/kyverno/pkg/engine/context/resolvers" + engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/registryclient" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" @@ -65,7 +65,7 @@ type controller struct { eventGen event.Interface configuration config.Configuration - informerCacheResolvers resolvers.ConfigmapResolver + informerCacheResolvers engineapi.ConfigmapResolver } // NewController returns an instance of the Generate-Request Controller @@ -80,7 +80,7 @@ func NewController( podInformer corev1informers.PodInformer, eventGen event.Interface, dynamicConfig config.Configuration, - informerCacheResolvers resolvers.ConfigmapResolver, + informerCacheResolvers engineapi.ConfigmapResolver, ) Controller { urLister := urInformer.Lister().UpdateRequests(config.KyvernoNamespace()) c := controller{ diff --git a/pkg/controllers/report/background/controller.go b/pkg/controllers/report/background/controller.go index b64ba65535..f6182d18c8 100644 --- a/pkg/controllers/report/background/controller.go +++ b/pkg/controllers/report/background/controller.go @@ -18,7 +18,7 @@ import ( "github.com/kyverno/kyverno/pkg/controllers/report/resource" "github.com/kyverno/kyverno/pkg/controllers/report/utils" "github.com/kyverno/kyverno/pkg/engine" - "github.com/kyverno/kyverno/pkg/engine/context/resolvers" + engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/registryclient" controllerutils "github.com/kyverno/kyverno/pkg/utils/controller" @@ -63,7 +63,7 @@ type controller struct { // cache metadataCache resource.MetadataCache - informerCacheResolvers resolvers.ConfigmapResolver + informerCacheResolvers engineapi.ConfigmapResolver forceDelay time.Duration // config @@ -81,7 +81,7 @@ func NewController( nsInformer corev1informers.NamespaceInformer, polexLister engine.PolicyExceptionLister, metadataCache resource.MetadataCache, - informerCacheResolvers resolvers.ConfigmapResolver, + informerCacheResolvers engineapi.ConfigmapResolver, forceDelay time.Duration, config config.Configuration, eventGen event.Interface, diff --git a/pkg/controllers/report/utils/scanner.go b/pkg/controllers/report/utils/scanner.go index 1e0f8b2bc9..b9d7cf8910 100644 --- a/pkg/controllers/report/utils/scanner.go +++ b/pkg/controllers/report/utils/scanner.go @@ -10,7 +10,6 @@ import ( "github.com/kyverno/kyverno/pkg/engine" engineapi "github.com/kyverno/kyverno/pkg/engine/api" enginecontext "github.com/kyverno/kyverno/pkg/engine/context" - "github.com/kyverno/kyverno/pkg/engine/context/resolvers" "github.com/kyverno/kyverno/pkg/registryclient" "go.uber.org/multierr" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -20,7 +19,7 @@ type scanner struct { logger logr.Logger client dclient.Interface rclient registryclient.Client - informerCacheResolvers resolvers.ConfigmapResolver + informerCacheResolvers engineapi.ConfigmapResolver polexLister engine.PolicyExceptionLister excludeGroupRole []string config config.Configuration @@ -39,7 +38,7 @@ func NewScanner( logger logr.Logger, client dclient.Interface, rclient registryclient.Client, - informerCacheResolvers resolvers.ConfigmapResolver, + informerCacheResolvers engineapi.ConfigmapResolver, polexLister engine.PolicyExceptionLister, config config.Configuration, excludeGroupRole ...string, diff --git a/pkg/engine/api/resolver.go b/pkg/engine/api/resolver.go new file mode 100644 index 0000000000..d10e43b9c8 --- /dev/null +++ b/pkg/engine/api/resolver.go @@ -0,0 +1,52 @@ +package api + +import ( + "context" + "errors" + + corev1 "k8s.io/api/core/v1" +) + +// NamespacedResourceResolver is an abstract interface used to resolve namespaced resources +// Any implementation might exist, cache based, file based, client based etc... +type NamespacedResourceResolver[T any] interface { + // Get is used to resolve a resource given a namespace and name + Get( + ctx context.Context, + namespace string, + name string, + ) (T, error) +} + +// ConfigmapResolver is an abstract interface used to resolve configmaps +type ConfigmapResolver = NamespacedResourceResolver[*corev1.ConfigMap] + +// namespacedResourceResolverChain represents a chain of NamespacedResourceResolver +type namespacedResourceResolverChain[T any] []NamespacedResourceResolver[T] + +// NewNamespacedResourceResolver creates a NamespacedResourceResolver from a NamespacedResourceResolver chain +// It will try to resolve resources by iterating over individual resolvers until one finds the requested resource +func NewNamespacedResourceResolver[T any](resolvers ...NamespacedResourceResolver[T]) (NamespacedResourceResolver[T], error) { + if len(resolvers) == 0 { + return nil, errors.New("no resolvers") + } + for _, resolver := range resolvers { + if resolver == nil { + return nil, errors.New("at least one resolver is nil") + } + } + return namespacedResourceResolverChain[T](resolvers), nil +} + +func (chain namespacedResourceResolverChain[T]) Get(ctx context.Context, namespace, name string) (T, error) { + var lastErr error + for _, resolver := range chain { + r, err := resolver.Get(ctx, namespace, name) + if err == nil { + return r, nil + } + lastErr = err + } + var notFound T + return notFound, lastErr +} diff --git a/pkg/engine/api/resolver_test.go b/pkg/engine/api/resolver_test.go new file mode 100644 index 0000000000..a9e9fab3f5 --- /dev/null +++ b/pkg/engine/api/resolver_test.go @@ -0,0 +1,135 @@ +package api + +import ( + "context" + "errors" + "reflect" + "testing" + + corev1 "k8s.io/api/core/v1" +) + +type dummyResolver struct { + err error + cm *corev1.ConfigMap +} + +func (c dummyResolver) Get(context.Context, string, string) (*corev1.ConfigMap, error) { + return c.cm, c.err +} + +func TestNewNamespacedResourceResolver(t *testing.T) { + type args struct { + resolvers []ConfigmapResolver + } + tests := []struct { + name string + args args + want ConfigmapResolver + wantErr bool + }{{ + name: "nil shoud return an error", + wantErr: true, + }, { + name: "empty list shoud return an error", + args: args{[]ConfigmapResolver{}}, + wantErr: true, + }, { + name: "one nil in the list shoud return an error", + args: args{[]ConfigmapResolver{dummyResolver{}, nil}}, + wantErr: true, + }, { + name: "no nil", + args: args{[]ConfigmapResolver{dummyResolver{}, dummyResolver{}, dummyResolver{}}}, + want: namespacedResourceResolverChain[*corev1.ConfigMap]{dummyResolver{}, dummyResolver{}, dummyResolver{}}, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := NewNamespacedResourceResolver(tt.args.resolvers...) + if (err != nil) != tt.wantErr { + t.Errorf("NewResolverChain() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewResolverChain() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_namespacedResourceResolverChain_Get(t *testing.T) { + type fields struct { + resolvers []ConfigmapResolver + } + type args struct { + namespace string + name string + } + tests := []struct { + name string + fields fields + args args + wantErr error + wantCm *corev1.ConfigMap + }{{ + fields: fields{ + resolvers: []ConfigmapResolver{ + dummyResolver{}, + dummyResolver{}, + dummyResolver{}, + }, + }, + }, { + fields: fields{ + resolvers: []ConfigmapResolver{ + dummyResolver{ + err: errors.New("1"), + }, + dummyResolver{ + err: errors.New("2"), + }, + dummyResolver{ + err: errors.New("3"), + }, + }, + }, + wantErr: errors.New("3"), + }, { + fields: fields{ + resolvers: []ConfigmapResolver{ + dummyResolver{ + err: errors.New("1"), + }, + dummyResolver{}, + dummyResolver{ + err: errors.New("3"), + }, + }, + }, + }, { + fields: fields{ + resolvers: []ConfigmapResolver{ + dummyResolver{ + err: errors.New("1"), + }, + dummyResolver{ + err: errors.New("2"), + }, + dummyResolver{}, + }, + }, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resolver, _ := NewNamespacedResourceResolver(tt.fields.resolvers...) + got, err := resolver.Get(context.TODO(), tt.args.namespace, tt.args.name) + if !reflect.DeepEqual(err, tt.wantErr) { + t.Errorf("ConfigmapResolver.Get() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.wantCm) { + t.Errorf("ConfigmapResolver.Get() = %v, want %v", got, tt.wantCm) + } + }) + } +} diff --git a/pkg/engine/context/resolvers/constants.go b/pkg/engine/context/resolvers/constants.go index 2914debec3..eb0aba7229 100644 --- a/pkg/engine/context/resolvers/constants.go +++ b/pkg/engine/context/resolvers/constants.go @@ -1,7 +1,5 @@ package resolvers const ( - TEST_NAMESPACE = "default" - TEST_CONFIGMAP = "myconfigmap" - LabelCacheKey = "cache.kyverno.io/enabled" + LabelCacheKey = "cache.kyverno.io/enabled" ) diff --git a/pkg/engine/context/resolvers/resolvers.go b/pkg/engine/context/resolvers/resolvers.go index d79dc1ef61..34a5f8ffad 100644 --- a/pkg/engine/context/resolvers/resolvers.go +++ b/pkg/engine/context/resolvers/resolvers.go @@ -4,6 +4,7 @@ import ( "context" "errors" + "github.com/kyverno/kyverno/pkg/engine/api" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -14,7 +15,7 @@ type informerBasedResolver struct { lister corev1listers.ConfigMapLister } -func NewInformerBasedResolver(lister corev1listers.ConfigMapLister) (ConfigmapResolver, error) { +func NewInformerBasedResolver(lister corev1listers.ConfigMapLister) (api.ConfigmapResolver, error) { if lister == nil { return nil, errors.New("lister must not be nil") } @@ -29,7 +30,7 @@ type clientBasedResolver struct { kubeClient kubernetes.Interface } -func NewClientBasedResolver(client kubernetes.Interface) (ConfigmapResolver, error) { +func NewClientBasedResolver(client kubernetes.Interface) (api.ConfigmapResolver, error) { if client == nil { return nil, errors.New("client must not be nil") } @@ -39,32 +40,3 @@ func NewClientBasedResolver(client kubernetes.Interface) (ConfigmapResolver, err func (c *clientBasedResolver) Get(ctx context.Context, namespace, name string) (*corev1.ConfigMap, error) { return c.kubeClient.CoreV1().ConfigMaps(namespace).Get(ctx, name, metav1.GetOptions{}) } - -type resolverChain []ConfigmapResolver - -func NewResolverChain(resolvers ...ConfigmapResolver) (ConfigmapResolver, error) { - if len(resolvers) == 0 { - return nil, errors.New("no resolvers") - } - for _, resolver := range resolvers { - if resolver == nil { - return nil, errors.New("at least one resolver is nil") - } - } - return resolverChain(resolvers), nil -} - -func (chain resolverChain) Get(ctx context.Context, namespace, name string) (*corev1.ConfigMap, error) { - // if CM is not found in informer cache, error will be stored in - // lastErr variable and resolver chain will try to get CM using - // Kubernetes client - var lastErr error - for _, resolver := range chain { - cm, err := resolver.Get(ctx, namespace, name) - if err == nil { - return cm, nil - } - lastErr = err - } - return nil, lastErr -} diff --git a/pkg/engine/context/resolvers/resolvers_test.go b/pkg/engine/context/resolvers/resolvers_test.go index 2647553d67..1535ac331b 100644 --- a/pkg/engine/context/resolvers/resolvers_test.go +++ b/pkg/engine/context/resolvers/resolvers_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/kyverno/kyverno/pkg/engine/api" "gotest.tools/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -15,6 +16,11 @@ import ( corev1listers "k8s.io/client-go/listers/core/v1" ) +const ( + namespace = "default" + name = "myconfigmap" +) + func newEmptyFakeClient() *kubefake.Clientset { return kubefake.NewSimpleClientset() } @@ -22,15 +28,15 @@ func newEmptyFakeClient() *kubefake.Clientset { func createConfigMaps(ctx context.Context, client *kubefake.Clientset, addLabel bool) error { cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: TEST_CONFIGMAP, - Namespace: TEST_NAMESPACE, + Name: name, + Namespace: namespace, }, Data: map[string]string{"configmapkey": "key1"}, } if addLabel { cm.ObjectMeta.Labels = map[string]string{LabelCacheKey: "true"} } - _, err := client.CoreV1().ConfigMaps(TEST_NAMESPACE).Create( + _, err := client.CoreV1().ConfigMaps(namespace).Create( ctx, cm, metav1.CreateOptions{}) return err } @@ -57,7 +63,7 @@ func Test_InformerCacheSuccess(t *testing.T) { assert.NilError(t, err) informer.Start(make(<-chan struct{})) time.Sleep(10 * time.Second) - _, err = informerResolver.Get(ctx, TEST_NAMESPACE, TEST_CONFIGMAP) + _, err = informerResolver.Get(ctx, namespace, name) assert.NilError(t, err, "informer didn't have expected configmap") } @@ -71,7 +77,7 @@ func Test_InformerCacheFailure(t *testing.T) { assert.NilError(t, err) informer.Start(make(<-chan struct{})) time.Sleep(10 * time.Second) - _, err = resolver.Get(ctx, TEST_NAMESPACE, TEST_CONFIGMAP) + _, err = resolver.Get(ctx, namespace, name) assert.Equal(t, err.Error(), "configmap \"myconfigmap\" not found") } @@ -82,7 +88,7 @@ func Test_ClientBasedResolver(t *testing.T) { assert.NilError(t, err, "error while creating configmap") resolver, err := NewClientBasedResolver(client) assert.NilError(t, err) - _, err = resolver.Get(ctx, TEST_NAMESPACE, TEST_CONFIGMAP) + _, err = resolver.Get(ctx, namespace, name) assert.NilError(t, err, "error while getting configmap from client") } @@ -94,12 +100,12 @@ func Test_ResolverChainWithExistingConfigMap(t *testing.T) { assert.NilError(t, err) clientBasedResolver, err := NewClientBasedResolver(client) assert.NilError(t, err) - resolvers, err := NewResolverChain(informerBasedResolver, clientBasedResolver) + resolvers, err := api.NewNamespacedResourceResolver(informerBasedResolver, clientBasedResolver) assert.NilError(t, err) ctx := context.TODO() err = createConfigMaps(ctx, client, true) assert.NilError(t, err, "error while creating configmap") - _, err = resolvers.Get(ctx, TEST_NAMESPACE, TEST_CONFIGMAP) + _, err = resolvers.Get(ctx, namespace, name) assert.NilError(t, err, "error while getting configmap") } @@ -111,10 +117,10 @@ func Test_ResolverChainWithNonExistingConfigMap(t *testing.T) { assert.NilError(t, err) clientBasedResolver, err := NewClientBasedResolver(client) assert.NilError(t, err) - resolvers, err := NewResolverChain(informerBasedResolver, clientBasedResolver) + resolvers, err := api.NewNamespacedResourceResolver(informerBasedResolver, clientBasedResolver) assert.NilError(t, err) ctx := context.TODO() - _, err = resolvers.Get(ctx, TEST_NAMESPACE, TEST_CONFIGMAP) + _, err = resolvers.Get(ctx, namespace, name) assert.Error(t, err, "configmaps \"myconfigmap\" not found") } @@ -128,7 +134,7 @@ func TestNewInformerBasedResolver(t *testing.T) { tests := []struct { name string args args - want ConfigmapResolver + want api.ConfigmapResolver wantErr bool }{{ name: "nil shoud return an error", @@ -160,7 +166,7 @@ func TestNewClientBasedResolver(t *testing.T) { tests := []struct { name string args args - want ConfigmapResolver + want api.ConfigmapResolver wantErr bool }{{ name: "nil shoud return an error", @@ -183,48 +189,3 @@ func TestNewClientBasedResolver(t *testing.T) { }) } } - -type dummyResolver struct{} - -func (c dummyResolver) Get(context.Context, string, string) (*corev1.ConfigMap, error) { - return nil, nil -} - -func TestNewResolverChain(t *testing.T) { - type args struct { - resolvers []ConfigmapResolver - } - tests := []struct { - name string - args args - want ConfigmapResolver - wantErr bool - }{{ - name: "nil shoud return an error", - wantErr: true, - }, { - name: "empty list shoud return an error", - args: args{[]ConfigmapResolver{}}, - wantErr: true, - }, { - name: "one nil in the list shoud return an error", - args: args{[]ConfigmapResolver{dummyResolver{}, nil}}, - wantErr: true, - }, { - name: "no nil", - args: args{[]ConfigmapResolver{dummyResolver{}, dummyResolver{}, dummyResolver{}}}, - want: resolverChain{dummyResolver{}, dummyResolver{}, dummyResolver{}}, - }} - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := NewResolverChain(tt.args.resolvers...) - if (err != nil) != tt.wantErr { - t.Errorf("NewResolverChain() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("NewResolverChain() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/engine/context/resolvers/types.go b/pkg/engine/context/resolvers/types.go deleted file mode 100644 index 1db40ce5dc..0000000000 --- a/pkg/engine/context/resolvers/types.go +++ /dev/null @@ -1,13 +0,0 @@ -package resolvers - -import ( - "context" - - corev1 "k8s.io/api/core/v1" -) - -type NamespacedResourceResolver[T any] interface { - Get(context.Context, string, string) (T, error) -} - -type ConfigmapResolver = NamespacedResourceResolver[*corev1.ConfigMap] diff --git a/pkg/engine/policyContext.go b/pkg/engine/policyContext.go index 9498f5ae12..0d3454093b 100644 --- a/pkg/engine/policyContext.go +++ b/pkg/engine/policyContext.go @@ -6,8 +6,8 @@ import ( kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1" "github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/config" + "github.com/kyverno/kyverno/pkg/engine/api" enginectx "github.com/kyverno/kyverno/pkg/engine/context" - "github.com/kyverno/kyverno/pkg/engine/context/resolvers" admissionutils "github.com/kyverno/kyverno/pkg/utils/admission" "github.com/pkg/errors" admissionv1 "k8s.io/api/admission/v1" @@ -71,7 +71,7 @@ type PolicyContext struct { admissionOperation bool // informerCacheResolvers - used to get resources from informer cache - informerCacheResolvers resolvers.ConfigmapResolver + informerCacheResolvers api.ConfigmapResolver // subresource is the subresource being requested, if any (for example, "status" or "scale") subresource string @@ -205,7 +205,7 @@ func (c *PolicyContext) WithAdmissionOperation(admissionOperation bool) *PolicyC return copy } -func (c *PolicyContext) WithInformerCacheResolver(informerCacheResolver resolvers.ConfigmapResolver) *PolicyContext { +func (c *PolicyContext) WithInformerCacheResolver(informerCacheResolver api.ConfigmapResolver) *PolicyContext { copy := c.Copy() copy.informerCacheResolvers = informerCacheResolver return copy @@ -253,7 +253,7 @@ func NewPolicyContextFromAdmissionRequest( admissionInfo kyvernov1beta1.RequestInfo, configuration config.Configuration, client dclient.Interface, - informerCacheResolver resolvers.ConfigmapResolver, + informerCacheResolver api.ConfigmapResolver, polexLister PolicyExceptionLister, ) (*PolicyContext, error) { ctx, err := newVariablesContext(request, &admissionInfo) diff --git a/pkg/policy/policy_controller.go b/pkg/policy/policy_controller.go index 7850f92ad4..0e86e86a2e 100644 --- a/pkg/policy/policy_controller.go +++ b/pkg/policy/policy_controller.go @@ -23,7 +23,6 @@ import ( "github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/engine" engineapi "github.com/kyverno/kyverno/pkg/engine/api" - "github.com/kyverno/kyverno/pkg/engine/context/resolvers" "github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/metrics" "github.com/kyverno/kyverno/pkg/registryclient" @@ -82,7 +81,7 @@ type PolicyController struct { // nsLister can list/get namespaces from the shared informer's store nsLister corev1listers.NamespaceLister - informerCacheResolvers resolvers.ConfigmapResolver + informerCacheResolvers engineapi.ConfigmapResolver informersSynced []cache.InformerSynced @@ -107,7 +106,7 @@ func NewPolicyController( configHandler config.Configuration, eventGen event.Interface, namespaces corev1informers.NamespaceInformer, - informerCacheResolvers resolvers.ConfigmapResolver, + informerCacheResolvers engineapi.ConfigmapResolver, log logr.Logger, reconcilePeriod time.Duration, metricsConfig metrics.MetricsConfigManager, diff --git a/pkg/webhooks/resource/handlers.go b/pkg/webhooks/resource/handlers.go index 07ef85a73f..bf34962d0c 100644 --- a/pkg/webhooks/resource/handlers.go +++ b/pkg/webhooks/resource/handlers.go @@ -13,8 +13,8 @@ import ( "github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/engine" + engineapi "github.com/kyverno/kyverno/pkg/engine/api" enginectx "github.com/kyverno/kyverno/pkg/engine/context" - "github.com/kyverno/kyverno/pkg/engine/context/resolvers" "github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/metrics" "github.com/kyverno/kyverno/pkg/openapi" @@ -72,7 +72,7 @@ func NewHandlers( configuration config.Configuration, metricsConfig metrics.MetricsConfigManager, pCache policycache.Cache, - informerCacheResolvers resolvers.ConfigmapResolver, + informerCacheResolvers engineapi.ConfigmapResolver, nsLister corev1listers.NamespaceLister, rbLister rbacv1listers.RoleBindingLister, crbLister rbacv1listers.ClusterRoleBindingLister, diff --git a/pkg/webhooks/utils/policy_context_builder.go b/pkg/webhooks/utils/policy_context_builder.go index 6737566f27..4c8774193c 100644 --- a/pkg/webhooks/utils/policy_context_builder.go +++ b/pkg/webhooks/utils/policy_context_builder.go @@ -5,7 +5,7 @@ import ( "github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/engine" - "github.com/kyverno/kyverno/pkg/engine/context/resolvers" + engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/userinfo" "github.com/pkg/errors" admissionv1 "k8s.io/api/admission/v1" @@ -21,7 +21,7 @@ type policyContextBuilder struct { client dclient.Interface rbLister rbacv1listers.RoleBindingLister crbLister rbacv1listers.ClusterRoleBindingLister - informerCacheResolvers resolvers.ConfigmapResolver + informerCacheResolvers engineapi.ConfigmapResolver polexLister engine.PolicyExceptionLister } @@ -30,7 +30,7 @@ func NewPolicyContextBuilder( client dclient.Interface, rbLister rbacv1listers.RoleBindingLister, crbLister rbacv1listers.ClusterRoleBindingLister, - informerCacheResolvers resolvers.ConfigmapResolver, + informerCacheResolvers engineapi.ConfigmapResolver, polexLister engine.PolicyExceptionLister, ) PolicyContextBuilder { return &policyContextBuilder{