mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 02:18:15 +00:00
refactor: move resolvers into engine api package (#6162)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
f93995e812
commit
0237cc5c71
19 changed files with 246 additions and 142 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
52
pkg/engine/api/resolver.go
Normal file
52
pkg/engine/api/resolver.go
Normal file
|
@ -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
|
||||
}
|
135
pkg/engine/api/resolver_test.go
Normal file
135
pkg/engine/api/resolver_test.go
Normal file
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
package resolvers
|
||||
|
||||
const (
|
||||
TEST_NAMESPACE = "default"
|
||||
TEST_CONFIGMAP = "myconfigmap"
|
||||
LabelCacheKey = "cache.kyverno.io/enabled"
|
||||
LabelCacheKey = "cache.kyverno.io/enabled"
|
||||
)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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{
|
||||
|
|
Loading…
Add table
Reference in a new issue