1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 16:06:56 +00:00
kyverno/pkg/engine/factories/contextloaderfactory.go
Charles-Edouard Brétéché 441641515a
feat: add lazy loading feature flag (#7680)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
2023-06-27 13:44:15 +08:00

112 lines
3.3 KiB
Go

package factories
import (
"context"
"fmt"
"github.com/go-logr/logr"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/context/loaders"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/toggle"
)
type ContextLoaderFactoryOptions func(*contextLoader)
func DefaultContextLoaderFactory(cmResolver engineapi.ConfigmapResolver, opts ...ContextLoaderFactoryOptions) engineapi.ContextLoaderFactory {
return func(_ kyvernov1.PolicyInterface, _ kyvernov1.Rule) engineapi.ContextLoader {
cl := &contextLoader{
logger: logging.WithName("DefaultContextLoaderFactory"),
cmResolver: cmResolver,
}
for _, o := range opts {
o(cl)
}
return cl
}
}
func WithInitializer(initializer engineapi.Initializer) ContextLoaderFactoryOptions {
return func(cl *contextLoader) {
cl.initializers = append(cl.initializers, initializer)
}
}
type contextLoader struct {
logger logr.Logger
cmResolver engineapi.ConfigmapResolver
initializers []engineapi.Initializer
}
func (l *contextLoader) Load(
ctx context.Context,
jp jmespath.Interface,
client engineapi.RawClient,
rclientFactory engineapi.RegistryClientFactory,
contextEntries []kyvernov1.ContextEntry,
jsonContext enginecontext.Interface,
) error {
for _, init := range l.initializers {
if err := init(jsonContext); err != nil {
return err
}
}
for _, entry := range contextEntries {
loader, err := l.newLoader(ctx, jp, client, rclientFactory, entry, jsonContext)
if err != nil {
return fmt.Errorf("failed to create deferred loader for context entry %s", entry.Name)
}
if loader != nil {
if toggle.FromContext(ctx).EnableDeferredLoading() {
if err := jsonContext.AddDeferredLoader(entry.Name, loader); err != nil {
return err
}
} else {
return loader.LoadData()
}
}
}
return nil
}
func (l *contextLoader) newLoader(
ctx context.Context,
jp jmespath.Interface,
client engineapi.RawClient,
rclientFactory engineapi.RegistryClientFactory,
entry kyvernov1.ContextEntry,
jsonContext enginecontext.Interface,
) (enginecontext.Loader, error) {
if entry.ConfigMap != nil {
if l.cmResolver != nil {
l := loaders.NewConfigMapLoader(ctx, l.logger, entry, l.cmResolver, jsonContext)
return l, nil
} else {
l.logger.Info("disabled loading of ConfigMap context entry %s", entry.Name)
return nil, nil
}
} else if entry.APICall != nil {
if client != nil {
l := loaders.NewAPILoader(ctx, l.logger, entry, jsonContext, jp, client)
return l, nil
} else {
l.logger.Info("disabled loading of APICall context entry %s", entry.Name)
return nil, nil
}
} else if entry.ImageRegistry != nil {
if rclientFactory != nil {
l := loaders.NewImageDataLoader(ctx, l.logger, entry, jsonContext, jp, rclientFactory)
return l, nil
} else {
l.logger.Info("disabled loading of ImageRegistry context entry %s", entry.Name)
return nil, nil
}
} else if entry.Variable != nil {
l := loaders.NewVariableLoader(l.logger, entry, jsonContext, jp)
return l, nil
}
return nil, fmt.Errorf("missing ConfigMap|APICall|ImageRegistry|Variable in context entry %s", entry.Name)
}