1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-15 12:17:56 +00:00

refactor: introduce jmespath interface (#6882)

* refactor: introduce jmespath 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>

* 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>

* 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>
This commit is contained in:
Charles-Edouard Brétéché 2023-04-13 13:29:40 +02:00 committed by GitHub
parent 3ca6311947
commit 544fe04508
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 482 additions and 315 deletions

View file

@ -18,6 +18,7 @@ import (
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
policymetricscontroller "github.com/kyverno/kyverno/pkg/controllers/metrics/policy" policymetricscontroller "github.com/kyverno/kyverno/pkg/controllers/metrics/policy"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/leaderelection" "github.com/kyverno/kyverno/pkg/leaderelection"
"github.com/kyverno/kyverno/pkg/logging" "github.com/kyverno/kyverno/pkg/logging"
@ -43,6 +44,7 @@ func createrLeaderControllers(
configuration config.Configuration, configuration config.Configuration,
metricsConfig metrics.MetricsConfigManager, metricsConfig metrics.MetricsConfigManager,
eventGenerator event.Interface, eventGenerator event.Interface,
jp jmespath.Interface,
) ([]internal.Controller, error) { ) ([]internal.Controller, error) {
policyCtrl, err := policy.NewPolicyController( policyCtrl, err := policy.NewPolicyController(
kyvernoClient, kyvernoClient,
@ -57,6 +59,7 @@ func createrLeaderControllers(
logging.WithName("PolicyController"), logging.WithName("PolicyController"),
time.Hour, time.Hour,
metricsConfig, metricsConfig,
jp,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@ -71,6 +74,7 @@ func createrLeaderControllers(
kubeInformer.Core().V1().Namespaces(), kubeInformer.Core().V1().Namespaces(),
eventGenerator, eventGenerator,
configuration, configuration,
jp,
) )
return []internal.Controller{ return []internal.Controller{
internal.NewController("policy-controller", policyCtrl, 2), internal.NewController("policy-controller", policyCtrl, 2),
@ -137,6 +141,7 @@ func main() {
setup.Logger, setup.Logger,
setup.Configuration, setup.Configuration,
setup.MetricsConfiguration, setup.MetricsConfiguration,
setup.Jp,
dClient, dClient,
setup.RegistryClient, setup.RegistryClient,
setup.KubeClient, setup.KubeClient,
@ -174,6 +179,7 @@ func main() {
setup.Configuration, setup.Configuration,
setup.MetricsManager, setup.MetricsManager,
eventGenerator, eventGenerator,
setup.Jp,
) )
if err != nil { if err != nil {
logger.Error(err, "failed to create leader controllers") logger.Error(err, "failed to create leader controllers")

View file

@ -5,13 +5,17 @@ import (
"github.com/go-logr/logr" "github.com/go-logr/logr"
kyvernov2beta1 "github.com/kyverno/kyverno/api/kyverno/v2beta1" kyvernov2beta1 "github.com/kyverno/kyverno/api/kyverno/v2beta1"
"github.com/kyverno/kyverno/pkg/config"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/logging" "github.com/kyverno/kyverno/pkg/logging"
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
) )
var jp = jmespath.New(config.NewDefaultConfiguration(false))
func Test_checkCondition(t *testing.T) { func Test_checkCondition(t *testing.T) {
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
ctx.AddResource(map[string]interface{}{ ctx.AddResource(map[string]interface{}{
"name": "dummy", "name": "dummy",
}) })

View file

@ -11,6 +11,7 @@ import (
"github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/clients/dclient"
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/metrics" "github.com/kyverno/kyverno/pkg/metrics"
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller" controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
@ -34,6 +35,7 @@ type handlers struct {
polLister kyvernov2alpha1listers.CleanupPolicyLister polLister kyvernov2alpha1listers.CleanupPolicyLister
nsLister corev1listers.NamespaceLister nsLister corev1listers.NamespaceLister
recorder record.EventRecorder recorder record.EventRecorder
jp jmespath.Interface
metrics cleanupMetrics metrics cleanupMetrics
} }
@ -65,11 +67,12 @@ func newCleanupMetrics(logger logr.Logger) cleanupMetrics {
} }
func New( func New(
logger logr.Logger,
client dclient.Interface, client dclient.Interface,
cpolLister kyvernov2alpha1listers.ClusterCleanupPolicyLister, cpolLister kyvernov2alpha1listers.ClusterCleanupPolicyLister,
polLister kyvernov2alpha1listers.CleanupPolicyLister, polLister kyvernov2alpha1listers.CleanupPolicyLister,
nsLister corev1listers.NamespaceLister, nsLister corev1listers.NamespaceLister,
logger logr.Logger, jp jmespath.Interface,
) *handlers { ) *handlers {
return &handlers{ return &handlers{
client: client, client: client,
@ -78,6 +81,7 @@ func New(
nsLister: nsLister, nsLister: nsLister,
recorder: event.NewRecorder(event.CleanupController, client.GetEventsInterface()), recorder: event.NewRecorder(event.CleanupController, client.GetEventsInterface()),
metrics: newCleanupMetrics(logger), metrics: newCleanupMetrics(logger),
jp: jp,
} }
} }
@ -181,7 +185,7 @@ func (h *handlers) executePolicy(ctx context.Context, logger logr.Logger, policy
} }
// check conditions // check conditions
if spec.Conditions != nil { if spec.Conditions != nil {
enginectx := enginecontext.NewContext() enginectx := enginecontext.NewContext(h.jp)
if err := enginectx.AddTargetResource(resource.Object); err != nil { if err := enginectx.AddTargetResource(resource.Object); err != nil {
debug.Error(err, "failed to add resource in context") debug.Error(err, "failed to add resource in context")
errs = append(errs, err) errs = append(errs, err)

View file

@ -199,7 +199,7 @@ func main() {
} }
// create handlers // create handlers
admissionHandlers := admissionhandlers.New(dClient) admissionHandlers := admissionhandlers.New(dClient)
cleanupHandlers := cleanuphandlers.New(dClient, cpolLister, polLister, nsLister, setup.Logger.WithName("cleanup-handler")) cleanupHandlers := cleanuphandlers.New(setup.Logger.WithName("cleanup-handler"), dClient, cpolLister, polLister, nsLister, setup.Jp)
// create server // create server
server := NewServer( server := NewServer(
func() ([]byte, []byte, error) { func() ([]byte, []byte, error) {

View file

@ -10,6 +10,7 @@ import (
"strings" "strings"
gojmespath "github.com/jmespath/go-jmespath" gojmespath "github.com/jmespath/go-jmespath"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine/jmespath" "github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
@ -162,11 +163,12 @@ func loadInput(file string) (interface{}, error) {
} }
func evaluate(input interface{}, query string) (interface{}, error) { func evaluate(input interface{}, query string) (interface{}, error) {
jp, err := jmespath.New(query) jp := jmespath.New(config.NewDefaultConfiguration(false))
q, err := jp.Query(query)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to compile JMESPath: %s, error: %v", query, err) return nil, fmt.Errorf("failed to compile JMESPath: %s, error: %v", query, err)
} }
result, err := jp.Search(input) result, err := q.Search(input)
if err != nil { if err != nil {
if syntaxError, ok := err.(gojmespath.SyntaxError); ok { if syntaxError, ok := err.(gojmespath.SyntaxError); ok {
return nil, fmt.Errorf("%s\n%s", syntaxError, syntaxError.HighlightLocation()) return nil, fmt.Errorf("%s\n%s", syntaxError, syntaxError.HighlightLocation())

View file

@ -23,6 +23,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine" "github.com/kyverno/kyverno/pkg/engine"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
engineContext "github.com/kyverno/kyverno/pkg/engine/context" engineContext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/engine/variables/regex" "github.com/kyverno/kyverno/pkg/engine/variables/regex"
"github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/registryclient"
datautils "github.com/kyverno/kyverno/pkg/utils/data" datautils "github.com/kyverno/kyverno/pkg/utils/data"
@ -369,6 +370,8 @@ func GetVariable(variablesString, valuesFile string, fs billy.Filesystem, isGit
// ApplyPolicyOnResource - function to apply policy on resource // ApplyPolicyOnResource - function to apply policy on resource
func ApplyPolicyOnResource(c ApplyPolicyConfig) ([]engineapi.EngineResponse, error) { func ApplyPolicyOnResource(c ApplyPolicyConfig) ([]engineapi.EngineResponse, error) {
jp := jmespath.New(config.NewDefaultConfiguration(false))
var engineResponses []engineapi.EngineResponse var engineResponses []engineapi.EngineResponse
namespaceLabels := make(map[string]string) namespaceLabels := make(map[string]string)
operationIsDelete := false operationIsDelete := false
@ -431,7 +434,7 @@ OuterLoop:
if err != nil { if err != nil {
log.Log.Error(err, "unable to convert raw resource to unstructured") log.Log.Error(err, "unable to convert raw resource to unstructured")
} }
ctx := engineContext.NewContext() ctx := engineContext.NewContext(jp)
if operationIsDelete { if operationIsDelete {
err = engineContext.AddOldResource(ctx, resourceRaw) err = engineContext.AddOldResource(ctx, resourceRaw)
@ -478,6 +481,7 @@ OuterLoop:
eng := engine.NewEngine( eng := engine.NewEngine(
cfg, cfg,
config.NewDefaultMetricsConfiguration(), config.NewDefaultMetricsConfiguration(),
jmespath.New(cfg),
c.Client, c.Client,
registryclient.NewOrDie(), registryclient.NewOrDie(),
store.ContextLoaderFactory(nil), store.ContextLoaderFactory(nil),
@ -1025,9 +1029,11 @@ func initializeMockController(objects []runtime.Object) (*generate.GenerateContr
} }
client.SetDiscovery(dclient.NewFakeDiscoveryClient(nil)) client.SetDiscovery(dclient.NewFakeDiscoveryClient(nil))
cfg := config.NewDefaultConfiguration(false)
c := generate.NewGenerateControllerWithOnlyClient(client, engine.NewEngine( c := generate.NewGenerateControllerWithOnlyClient(client, engine.NewEngine(
config.NewDefaultConfiguration(false), cfg,
config.NewDefaultMetricsConfiguration(), config.NewDefaultMetricsConfiguration(),
jmespath.New(cfg),
client, client,
nil, nil,
store.ContextLoaderFactory(nil), store.ContextLoaderFactory(nil),

View file

@ -8,6 +8,7 @@ import (
"github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/clients/dclient"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/logging" "github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/registryclient"
) )
@ -37,6 +38,7 @@ type mockContextLoader struct {
func (l *mockContextLoader) Load( func (l *mockContextLoader) Load(
ctx context.Context, ctx context.Context,
jp jmespath.Interface,
client dclient.Interface, client dclient.Interface,
_ registryclient.Client, _ registryclient.Client,
contextEntries []kyvernov1.ContextEntry, contextEntries []kyvernov1.ContextEntry,
@ -56,15 +58,15 @@ func (l *mockContextLoader) Load(
for _, entry := range contextEntries { for _, entry := range contextEntries {
if entry.ImageRegistry != nil && hasRegistryAccess { if entry.ImageRegistry != nil && hasRegistryAccess {
rclient := GetRegistryClient() rclient := GetRegistryClient()
if err := engineapi.LoadImageData(ctx, rclient, l.logger, entry, jsonContext); err != nil { if err := engineapi.LoadImageData(ctx, jp, rclient, l.logger, entry, jsonContext); err != nil {
return err return err
} }
} else if entry.Variable != nil { } else if entry.Variable != nil {
if err := engineapi.LoadVariable(l.logger, entry, jsonContext); err != nil { if err := engineapi.LoadVariable(l.logger, jp, entry, jsonContext); err != nil {
return err return err
} }
} else if entry.APICall != nil && IsApiCallAllowed() { } else if entry.APICall != nil && IsApiCallAllowed() {
if err := engineapi.LoadAPIData(ctx, l.logger, entry, jsonContext, client); err != nil { if err := engineapi.LoadAPIData(ctx, jp, l.logger, entry, jsonContext, client); err != nil {
return err return err
} }
} }

View file

@ -13,6 +13,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine" "github.com/kyverno/kyverno/pkg/engine"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/context/resolvers" "github.com/kyverno/kyverno/pkg/engine/context/resolvers"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/registryclient"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
) )
@ -22,6 +23,7 @@ func NewEngine(
logger logr.Logger, logger logr.Logger,
configuration config.Configuration, configuration config.Configuration,
metricsConfiguration config.MetricsConfiguration, metricsConfiguration config.MetricsConfiguration,
jp jmespath.Interface,
client dclient.Interface, client dclient.Interface,
rclient registryclient.Client, rclient registryclient.Client,
kubeClient kubernetes.Interface, kubeClient kubernetes.Interface,
@ -34,6 +36,7 @@ func NewEngine(
return engine.NewEngine( return engine.NewEngine(
configuration, configuration,
metricsConfiguration, metricsConfiguration,
jp,
client, client,
rclient, rclient,
engineapi.DefaultContextLoaderFactory(configMapResolver), engineapi.DefaultContextLoaderFactory(configMapResolver),

View file

@ -6,6 +6,7 @@ import (
"github.com/go-logr/logr" "github.com/go-logr/logr"
kubeclient "github.com/kyverno/kyverno/pkg/clients/kube" kubeclient "github.com/kyverno/kyverno/pkg/clients/kube"
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/metrics" "github.com/kyverno/kyverno/pkg/metrics"
"github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/registryclient"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
@ -27,6 +28,7 @@ type SetupResult struct {
Configuration config.Configuration Configuration config.Configuration
MetricsConfiguration config.MetricsConfiguration MetricsConfiguration config.MetricsConfiguration
MetricsManager metrics.MetricsConfigManager MetricsManager metrics.MetricsConfigManager
Jp jmespath.Interface
KubeClient kubernetes.Interface KubeClient kubernetes.Interface
LeaderElectionClient kubernetes.Interface LeaderElectionClient kubernetes.Interface
RegistryClient registryclient.Client RegistryClient registryclient.Client
@ -59,6 +61,7 @@ func Setup(config Configuration, name string, skipResourceFilters bool) (context
Configuration: configuration, Configuration: configuration,
MetricsConfiguration: metricsConfiguration, MetricsConfiguration: metricsConfiguration,
MetricsManager: metricsManager, MetricsManager: metricsManager,
Jp: jmespath.New(configuration),
KubeClient: client, KubeClient: client,
LeaderElectionClient: leaderElectionClient, LeaderElectionClient: leaderElectionClient,
RegistryClient: registryClient, RegistryClient: registryClient,

View file

@ -303,6 +303,7 @@ func main() {
setup.Logger, setup.Logger,
setup.Configuration, setup.Configuration,
setup.MetricsConfiguration, setup.MetricsConfiguration,
setup.Jp,
dClient, dClient,
setup.RegistryClient, setup.RegistryClient,
setup.KubeClient, setup.KubeClient,
@ -426,8 +427,6 @@ func main() {
setup.MetricsManager, setup.MetricsManager,
policyCache, policyCache,
kubeInformer.Core().V1().Namespaces().Lister(), kubeInformer.Core().V1().Namespaces().Lister(),
kubeInformer.Rbac().V1().RoleBindings().Lister(),
kubeInformer.Rbac().V1().ClusterRoleBindings().Lister(),
kyvernoInformer.Kyverno().V1beta1().UpdateRequests().Lister().UpdateRequests(config.KyvernoNamespace()), kyvernoInformer.Kyverno().V1beta1().UpdateRequests().Lister().UpdateRequests(config.KyvernoNamespace()),
kyvernoInformer.Kyverno().V1().ClusterPolicies(), kyvernoInformer.Kyverno().V1().ClusterPolicies(),
kyvernoInformer.Kyverno().V1().Policies(), kyvernoInformer.Kyverno().V1().Policies(),
@ -436,6 +435,7 @@ func main() {
openApiManager, openApiManager,
admissionReports, admissionReports,
backgroundServiceAccountName, backgroundServiceAccountName,
setup.Jp,
) )
exceptionHandlers := webhooksexception.NewHandlers(exception.ValidationOptions{ exceptionHandlers := webhooksexception.NewHandlers(exception.ValidationOptions{
Enabled: internal.PolicyExceptionEnabled(), Enabled: internal.PolicyExceptionEnabled(),

View file

@ -21,6 +21,7 @@ import (
backgroundscancontroller "github.com/kyverno/kyverno/pkg/controllers/report/background" backgroundscancontroller "github.com/kyverno/kyverno/pkg/controllers/report/background"
resourcereportcontroller "github.com/kyverno/kyverno/pkg/controllers/report/resource" resourcereportcontroller "github.com/kyverno/kyverno/pkg/controllers/report/resource"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/leaderelection" "github.com/kyverno/kyverno/pkg/leaderelection"
"github.com/kyverno/kyverno/pkg/logging" "github.com/kyverno/kyverno/pkg/logging"
@ -49,6 +50,7 @@ func createReportControllers(
kyvernoInformer kyvernoinformer.SharedInformerFactory, kyvernoInformer kyvernoinformer.SharedInformerFactory,
backgroundScanInterval time.Duration, backgroundScanInterval time.Duration,
configuration config.Configuration, configuration config.Configuration,
jp jmespath.Interface,
eventGenerator event.Interface, eventGenerator event.Interface,
) ([]internal.Controller, func(context.Context) error) { ) ([]internal.Controller, func(context.Context) error) {
var ctrls []internal.Controller var ctrls []internal.Controller
@ -105,6 +107,7 @@ func createReportControllers(
resourceReportController, resourceReportController,
backgroundScanInterval, backgroundScanInterval,
configuration, configuration,
jp,
eventGenerator, eventGenerator,
), ),
backgroundScanWorkers, backgroundScanWorkers,
@ -134,6 +137,7 @@ func createrLeaderControllers(
dynamicClient dclient.Interface, dynamicClient dclient.Interface,
rclient registryclient.Client, rclient registryclient.Client,
configuration config.Configuration, configuration config.Configuration,
jp jmespath.Interface,
eventGenerator event.Interface, eventGenerator event.Interface,
backgroundScanInterval time.Duration, backgroundScanInterval time.Duration,
) ([]internal.Controller, func(context.Context) error, error) { ) ([]internal.Controller, func(context.Context) error, error) {
@ -151,6 +155,7 @@ func createrLeaderControllers(
kyvernoInformer, kyvernoInformer,
backgroundScanInterval, backgroundScanInterval,
configuration, configuration,
jp,
eventGenerator, eventGenerator,
) )
return reportControllers, warmup, nil return reportControllers, warmup, nil
@ -223,6 +228,7 @@ func main() {
setup.Logger, setup.Logger,
setup.Configuration, setup.Configuration,
setup.MetricsConfiguration, setup.MetricsConfiguration,
setup.Jp,
dClient, dClient,
setup.RegistryClient, setup.RegistryClient,
setup.KubeClient, setup.KubeClient,
@ -265,6 +271,7 @@ func main() {
dClient, dClient,
setup.RegistryClient, setup.RegistryClient,
setup.Configuration, setup.Configuration,
setup.Jp,
eventGenerator, eventGenerator,
backgroundScanInterval, backgroundScanInterval,
) )

View file

@ -10,18 +10,22 @@ import (
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine" "github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission" admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
) )
func NewBackgroundContext(dclient dclient.Interface, ur *kyvernov1beta1.UpdateRequest, func NewBackgroundContext(
logger logr.Logger,
dclient dclient.Interface,
ur *kyvernov1beta1.UpdateRequest,
policy kyvernov1.PolicyInterface, policy kyvernov1.PolicyInterface,
trigger *unstructured.Unstructured, trigger *unstructured.Unstructured,
cfg config.Configuration, cfg config.Configuration,
jp jmespath.Interface,
namespaceLabels map[string]string, namespaceLabels map[string]string,
logger logr.Logger,
) (*engine.PolicyContext, error) { ) (*engine.PolicyContext, error) {
ctx := context.NewContext() ctx := context.NewContext(jp)
var new, old unstructured.Unstructured var new, old unstructured.Unstructured
var err error var err error

View file

@ -20,6 +20,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine" "github.com/kyverno/kyverno/pkg/engine"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/engine/variables" "github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/event"
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission" admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
@ -55,6 +56,7 @@ type GenerateController struct {
eventGen event.Interface eventGen event.Interface
log logr.Logger log logr.Logger
jp jmespath.Interface
} }
// NewGenerateController returns an instance of the Generate-Request Controller // NewGenerateController returns an instance of the Generate-Request Controller
@ -70,6 +72,7 @@ func NewGenerateController(
dynamicConfig config.Configuration, dynamicConfig config.Configuration,
eventGen event.Interface, eventGen event.Interface,
log logr.Logger, log logr.Logger,
jp jmespath.Interface,
) *GenerateController { ) *GenerateController {
c := GenerateController{ c := GenerateController{
client: client, client: client,
@ -83,6 +86,7 @@ func NewGenerateController(
configuration: dynamicConfig, configuration: dynamicConfig,
eventGen: eventGen, eventGen: eventGen,
log: log, log: log,
jp: jp,
} }
return &c return &c
} }
@ -198,7 +202,7 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, u
return nil, err return nil, err
} }
policyContext, err := common.NewBackgroundContext(c.client, &ur, policy, &resource, c.configuration, namespaceLabels, logger) policyContext, err := common.NewBackgroundContext(logger, c.client, &ur, policy, &resource, c.configuration, c.jp, namespaceLabels)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -13,6 +13,7 @@ import (
"github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/clients/dclient"
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/utils" "github.com/kyverno/kyverno/pkg/utils"
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission" admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
@ -28,7 +29,7 @@ import (
var ErrEmptyPatch error = fmt.Errorf("empty resource to patch") var ErrEmptyPatch error = fmt.Errorf("empty resource to patch")
type MutateExistingController struct { type mutateExistingController struct {
// clients // clients
client dclient.Interface client dclient.Interface
statusControl common.StatusControlInterface statusControl common.StatusControlInterface
@ -43,6 +44,7 @@ type MutateExistingController struct {
eventGen event.Interface eventGen event.Interface
log logr.Logger log logr.Logger
jp jmespath.Interface
} }
// NewMutateExistingController returns an instance of the MutateExistingController // NewMutateExistingController returns an instance of the MutateExistingController
@ -56,8 +58,9 @@ func NewMutateExistingController(
dynamicConfig config.Configuration, dynamicConfig config.Configuration,
eventGen event.Interface, eventGen event.Interface,
log logr.Logger, log logr.Logger,
) *MutateExistingController { jp jmespath.Interface,
c := MutateExistingController{ ) *mutateExistingController {
c := mutateExistingController{
client: client, client: client,
statusControl: statusControl, statusControl: statusControl,
engine: engine, engine: engine,
@ -67,11 +70,12 @@ func NewMutateExistingController(
configuration: dynamicConfig, configuration: dynamicConfig,
eventGen: eventGen, eventGen: eventGen,
log: log, log: log,
jp: jp,
} }
return &c return &c
} }
func (c *MutateExistingController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) error { func (c *mutateExistingController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) error {
logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.GetPolicyKey(), "resource", ur.Spec.GetResource().String()) logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.GetPolicyKey(), "resource", ur.Spec.GetResource().String())
var errs []error var errs []error
@ -130,7 +134,7 @@ func (c *MutateExistingController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) e
} }
namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(trigger.GetKind(), trigger.GetNamespace(), c.nsLister, logger) namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(trigger.GetKind(), trigger.GetNamespace(), c.nsLister, logger)
policyContext, err := common.NewBackgroundContext(c.client, ur, policy, trigger, c.configuration, namespaceLabels, logger) policyContext, err := common.NewBackgroundContext(logger, c.client, ur, policy, trigger, c.configuration, c.jp, namespaceLabels)
if err != nil { if err != nil {
logger.WithName(rule.Name).Error(err, "failed to build policy context") logger.WithName(rule.Name).Error(err, "failed to build policy context")
errs = append(errs, err) errs = append(errs, err)
@ -210,7 +214,7 @@ func (c *MutateExistingController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) e
return updateURStatus(c.statusControl, *ur, err) return updateURStatus(c.statusControl, *ur, err)
} }
func (c *MutateExistingController) getPolicy(key string) (kyvernov1.PolicyInterface, error) { func (c *mutateExistingController) getPolicy(key string) (kyvernov1.PolicyInterface, error) {
pNamespace, pName, err := cache.SplitMetaNamespaceKey(key) pNamespace, pName, err := cache.SplitMetaNamespaceKey(key)
if err != nil { if err != nil {
return nil, err return nil, err
@ -223,7 +227,7 @@ func (c *MutateExistingController) getPolicy(key string) (kyvernov1.PolicyInterf
return c.policyLister.Get(pName) return c.policyLister.Get(pName)
} }
func (c *MutateExistingController) report(err error, policy, rule string, target *unstructured.Unstructured) { func (c *mutateExistingController) report(err error, policy, rule string, target *unstructured.Unstructured) {
var events []event.Info var events []event.Info
if target == nil { if target == nil {

View file

@ -18,6 +18,7 @@ import (
"github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/clients/dclient"
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/event"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -58,6 +59,7 @@ type controller struct {
eventGen event.Interface eventGen event.Interface
configuration config.Configuration configuration config.Configuration
jp jmespath.Interface
} }
// NewController returns an instance of the Generate-Request Controller // NewController returns an instance of the Generate-Request Controller
@ -70,7 +72,8 @@ func NewController(
urInformer kyvernov1beta1informers.UpdateRequestInformer, urInformer kyvernov1beta1informers.UpdateRequestInformer,
namespaceInformer corev1informers.NamespaceInformer, namespaceInformer corev1informers.NamespaceInformer,
eventGen event.Interface, eventGen event.Interface,
dynamicConfig config.Configuration, configuration config.Configuration,
jp jmespath.Interface,
) Controller { ) Controller {
urLister := urInformer.Lister().UpdateRequests(config.KyvernoNamespace()) urLister := urInformer.Lister().UpdateRequests(config.KyvernoNamespace())
c := controller{ c := controller{
@ -83,7 +86,8 @@ func NewController(
nsLister: namespaceInformer.Lister(), nsLister: namespaceInformer.Lister(),
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "background"), queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "background"),
eventGen: eventGen, eventGen: eventGen,
configuration: dynamicConfig, configuration: configuration,
jp: jp,
} }
_, _ = urInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ _, _ = urInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: c.addUR, AddFunc: c.addUR,
@ -216,10 +220,10 @@ func (c *controller) processUR(ur *kyvernov1beta1.UpdateRequest) error {
statusControl := common.NewStatusControl(c.kyvernoClient, c.urLister) statusControl := common.NewStatusControl(c.kyvernoClient, c.urLister)
switch ur.Spec.GetRequestType() { switch ur.Spec.GetRequestType() {
case kyvernov1beta1.Mutate: case kyvernov1beta1.Mutate:
ctrl := mutate.NewMutateExistingController(c.client, statusControl, c.engine, c.cpolLister, c.polLister, c.nsLister, c.configuration, c.eventGen, logger) ctrl := mutate.NewMutateExistingController(c.client, statusControl, c.engine, c.cpolLister, c.polLister, c.nsLister, c.configuration, c.eventGen, logger, c.jp)
return ctrl.ProcessUR(ur) return ctrl.ProcessUR(ur)
case kyvernov1beta1.Generate: case kyvernov1beta1.Generate:
ctrl := generate.NewGenerateController(c.client, c.kyvernoClient, statusControl, c.engine, c.cpolLister, c.polLister, c.urLister, c.nsLister, c.configuration, c.eventGen, logger) ctrl := generate.NewGenerateController(c.client, c.kyvernoClient, statusControl, c.engine, c.cpolLister, c.polLister, c.urLister, c.nsLister, c.configuration, c.eventGen, logger, c.jp)
return ctrl.ProcessUR(ur) return ctrl.ProcessUR(ur)
} }
return nil return nil

View file

@ -17,6 +17,7 @@ import (
"github.com/kyverno/kyverno/pkg/controllers/report/resource" "github.com/kyverno/kyverno/pkg/controllers/report/resource"
"github.com/kyverno/kyverno/pkg/controllers/report/utils" "github.com/kyverno/kyverno/pkg/controllers/report/utils"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/event"
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller" controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
datautils "github.com/kyverno/kyverno/pkg/utils/data" datautils "github.com/kyverno/kyverno/pkg/utils/data"
@ -64,6 +65,7 @@ type controller struct {
// config // config
config config.Configuration config config.Configuration
jp jmespath.Interface
eventGen event.Interface eventGen event.Interface
} }
@ -78,6 +80,7 @@ func NewController(
metadataCache resource.MetadataCache, metadataCache resource.MetadataCache,
forceDelay time.Duration, forceDelay time.Duration,
config config.Configuration, config config.Configuration,
jp jmespath.Interface,
eventGen event.Interface, eventGen event.Interface,
) controllers.Controller { ) controllers.Controller {
bgscanr := metadataFactory.ForResource(kyvernov1alpha2.SchemeGroupVersion.WithResource("backgroundscanreports")) bgscanr := metadataFactory.ForResource(kyvernov1alpha2.SchemeGroupVersion.WithResource("backgroundscanreports"))
@ -96,6 +99,7 @@ func NewController(
metadataCache: metadataCache, metadataCache: metadataCache,
forceDelay: forceDelay, forceDelay: forceDelay,
config: config, config: config,
jp: jp,
eventGen: eventGen, eventGen: eventGen,
} }
controllerutils.AddDefaultEventHandlers(logger, bgscanr.Informer(), queue) controllerutils.AddDefaultEventHandlers(logger, bgscanr.Informer(), queue)
@ -301,7 +305,7 @@ func (c *controller) reconcileReport(
// calculate necessary results // calculate necessary results
for _, policy := range backgroundPolicies { for _, policy := range backgroundPolicies {
if full || actual[reportutils.PolicyLabel(policy)] != policy.GetResourceVersion() { if full || actual[reportutils.PolicyLabel(policy)] != policy.GetResourceVersion() {
scanner := utils.NewScanner(logger, c.engine, c.config) scanner := utils.NewScanner(logger, c.engine, c.config, c.jp)
for _, result := range scanner.ScanResource(ctx, *target, nsLabels, policy) { for _, result := range scanner.ScanResource(ctx, *target, nsLabels, policy) {
if result.Error != nil { if result.Error != nil {
return result.Error return result.Error

View file

@ -9,6 +9,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine" "github.com/kyverno/kyverno/pkg/engine"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"go.uber.org/multierr" "go.uber.org/multierr"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
) )
@ -17,6 +18,7 @@ type scanner struct {
logger logr.Logger logger logr.Logger
engine engineapi.Engine engine engineapi.Engine
config config.Configuration config config.Configuration
jp jmespath.Interface
} }
type ScanResult struct { type ScanResult struct {
@ -32,11 +34,13 @@ func NewScanner(
logger logr.Logger, logger logr.Logger,
engine engineapi.Engine, engine engineapi.Engine,
config config.Configuration, config config.Configuration,
jp jmespath.Interface,
) Scanner { ) Scanner {
return &scanner{ return &scanner{
logger: logger, logger: logger,
engine: engine, engine: engine,
config: config, config: config,
jp: jp,
} }
} }
@ -68,7 +72,7 @@ func (s *scanner) ScanResource(ctx context.Context, resource unstructured.Unstru
} }
func (s *scanner) validateResource(ctx context.Context, resource unstructured.Unstructured, nsLabels map[string]string, policy kyvernov1.PolicyInterface) (*engineapi.EngineResponse, error) { func (s *scanner) validateResource(ctx context.Context, resource unstructured.Unstructured, nsLabels map[string]string, policy kyvernov1.PolicyInterface) (*engineapi.EngineResponse, error) {
enginectx := enginecontext.NewContext() enginectx := enginecontext.NewContext(s.jp)
if err := enginectx.AddResource(resource.Object); err != nil { if err := enginectx.AddResource(resource.Object); err != nil {
return nil, err return nil, err
} }
@ -90,7 +94,7 @@ func (s *scanner) validateResource(ctx context.Context, resource unstructured.Un
} }
func (s *scanner) validateImages(ctx context.Context, resource unstructured.Unstructured, nsLabels map[string]string, policy kyvernov1.PolicyInterface) (*engineapi.EngineResponse, error) { func (s *scanner) validateImages(ctx context.Context, resource unstructured.Unstructured, nsLabels map[string]string, policy kyvernov1.PolicyInterface) (*engineapi.EngineResponse, error) {
enginectx := enginecontext.NewContext() enginectx := enginecontext.NewContext(s.jp)
if err := enginectx.AddResource(resource.Object); err != nil { if err := enginectx.AddResource(resource.Object); err != nil {
return nil, err return nil, err
} }

View file

@ -15,7 +15,7 @@ import (
"github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/registryclient"
) )
func LoadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx enginecontext.Interface) (err error) { func LoadVariable(logger logr.Logger, jp jmespath.Interface, entry kyvernov1.ContextEntry, ctx enginecontext.Interface) (err error) {
path := "" path := ""
if entry.Variable.JMESPath != "" { if entry.Variable.JMESPath != "" {
jp, err := variables.SubstituteAll(logger, ctx, entry.Variable.JMESPath) jp, err := variables.SubstituteAll(logger, ctx, entry.Variable.JMESPath)
@ -45,7 +45,7 @@ func LoadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx engineco
return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.Variable.Value, err) return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.Variable.Value, err)
} }
if path != "" { if path != "" {
variable, err := applyJMESPath(path, variable) variable, err := applyJMESPath(jp, path, variable)
if err == nil { if err == nil {
output = variable output = variable
} else if defaultValue == nil { } else if defaultValue == nil {
@ -74,8 +74,8 @@ func LoadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx engineco
} }
} }
func LoadImageData(ctx context.Context, rclient registryclient.Client, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface) error { func LoadImageData(ctx context.Context, jp jmespath.Interface, rclient registryclient.Client, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface) error {
imageData, err := fetchImageData(ctx, rclient, logger, entry, enginectx) imageData, err := fetchImageData(ctx, jp, rclient, logger, entry, enginectx)
if err != nil { if err != nil {
return err return err
} }
@ -89,8 +89,8 @@ func LoadImageData(ctx context.Context, rclient registryclient.Client, logger lo
return nil return nil
} }
func LoadAPIData(ctx context.Context, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, client dclient.Interface) error { func LoadAPIData(ctx context.Context, jp jmespath.Interface, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, client dclient.Interface) error {
executor, err := apicall.New(logger, entry, enginectx, client) executor, err := apicall.New(logger, jp, entry, enginectx, client)
if err != nil { if err != nil {
return fmt.Errorf("failed to initialize APICall: %w", err) return fmt.Errorf("failed to initialize APICall: %w", err)
} }
@ -112,7 +112,7 @@ func LoadConfigMap(ctx context.Context, logger logr.Logger, entry kyvernov1.Cont
return nil return nil
} }
func fetchImageData(ctx context.Context, rclient registryclient.Client, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface) (interface{}, error) { func fetchImageData(ctx context.Context, jp jmespath.Interface, rclient registryclient.Client, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface) (interface{}, error) {
ref, err := variables.SubstituteAll(logger, enginectx, entry.ImageRegistry.Reference) ref, err := variables.SubstituteAll(logger, enginectx, entry.ImageRegistry.Reference)
if err != nil { if err != nil {
return nil, fmt.Errorf("ailed to substitute variables in context entry %s %s: %v", entry.Name, entry.ImageRegistry.Reference, err) return nil, fmt.Errorf("ailed to substitute variables in context entry %s %s: %v", entry.Name, entry.ImageRegistry.Reference, err)
@ -130,7 +130,7 @@ func fetchImageData(ctx context.Context, rclient registryclient.Client, logger l
return nil, err return nil, err
} }
if path != "" { if path != "" {
imageData, err = applyJMESPath(path.(string), imageData) imageData, err = applyJMESPath(jp, path.(string), imageData)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to apply JMESPath (%s) results to context entry %s, error: %v", entry.ImageRegistry.JMESPath, entry.Name, err) return nil, fmt.Errorf("failed to apply JMESPath (%s) results to context entry %s, error: %v", entry.ImageRegistry.JMESPath, entry.Name, err)
} }
@ -193,12 +193,12 @@ func fetchImageDataMap(ctx context.Context, rclient registryclient.Client, ref s
return untyped, nil return untyped, nil
} }
func applyJMESPath(jmesPath string, data interface{}) (interface{}, error) { func applyJMESPath(jp jmespath.Interface, query string, data interface{}) (interface{}, error) {
jp, err := jmespath.New(jmesPath) q, err := jp.Query(query)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to compile JMESPath: %s, error: %v", jmesPath, err) return nil, fmt.Errorf("failed to compile JMESPath: %s, error: %v", query, err)
} }
return jp.Search(data) return q.Search(data)
} }
func fetchConfigMap(ctx context.Context, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, resolver ConfigmapResolver) ([]byte, error) { func fetchConfigMap(ctx context.Context, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, resolver ConfigmapResolver) ([]byte, error) {

View file

@ -7,6 +7,7 @@ import (
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/clients/dclient"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/logging" "github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/registryclient"
) )
@ -18,6 +19,7 @@ type ContextLoaderFactory = func(policy kyvernov1.PolicyInterface, rule kyvernov
type ContextLoader interface { type ContextLoader interface {
Load( Load(
ctx context.Context, ctx context.Context,
jp jmespath.Interface,
client dclient.Interface, client dclient.Interface,
rclient registryclient.Client, rclient registryclient.Client,
contextEntries []kyvernov1.ContextEntry, contextEntries []kyvernov1.ContextEntry,
@ -43,6 +45,7 @@ type contextLoader struct {
func (l *contextLoader) Load( func (l *contextLoader) Load(
ctx context.Context, ctx context.Context,
jp jmespath.Interface,
client dclient.Interface, client dclient.Interface,
rclient registryclient.Client, rclient registryclient.Client,
contextEntries []kyvernov1.ContextEntry, contextEntries []kyvernov1.ContextEntry,
@ -54,15 +57,15 @@ func (l *contextLoader) Load(
return err return err
} }
} else if entry.APICall != nil { } else if entry.APICall != nil {
if err := LoadAPIData(ctx, l.logger, entry, jsonContext, client); err != nil { if err := LoadAPIData(ctx, jp, l.logger, entry, jsonContext, client); err != nil {
return err return err
} }
} else if entry.ImageRegistry != nil { } else if entry.ImageRegistry != nil {
if err := LoadImageData(ctx, rclient, l.logger, entry, jsonContext); err != nil { if err := LoadImageData(ctx, jp, rclient, l.logger, entry, jsonContext); err != nil {
return err return err
} }
} else if entry.Variable != nil { } else if entry.Variable != nil {
if err := LoadVariable(l.logger, entry, jsonContext); err != nil { if err := LoadVariable(l.logger, jp, entry, jsonContext); err != nil {
return err return err
} }
} }

View file

@ -21,13 +21,15 @@ import (
type apiCall struct { type apiCall struct {
logger logr.Logger logger logr.Logger
jp jmespath.Interface
entry kyvernov1.ContextEntry entry kyvernov1.ContextEntry
jsonCtx enginecontext.Interface jsonCtx enginecontext.Interface
client dclient.Interface client dclient.Interface
} }
func New( func New(
log logr.Logger, logger logr.Logger,
jp jmespath.Interface,
entry kyvernov1.ContextEntry, entry kyvernov1.ContextEntry,
jsonCtx enginecontext.Interface, jsonCtx enginecontext.Interface,
client dclient.Interface, client dclient.Interface,
@ -36,10 +38,11 @@ func New(
return nil, fmt.Errorf("missing APICall in context entry %v", entry) return nil, fmt.Errorf("missing APICall in context entry %v", entry)
} }
return &apiCall{ return &apiCall{
logger: logger,
jp: jp,
entry: entry, entry: entry,
jsonCtx: jsonCtx, jsonCtx: jsonCtx,
client: client, client: client,
logger: log,
}, nil }, nil
} }
@ -205,7 +208,7 @@ func (a *apiCall) transformAndStore(jsonData []byte) ([]byte, error) {
return nil, fmt.Errorf("failed to substitute variables in context entry %s JMESPath %s: %w", a.entry.Name, a.entry.APICall.JMESPath, err) return nil, fmt.Errorf("failed to substitute variables in context entry %s JMESPath %s: %w", a.entry.Name, a.entry.APICall.JMESPath, err)
} }
results, err := applyJMESPathJSON(path.(string), jsonData) results, err := a.applyJMESPathJSON(path.(string), jsonData)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to apply JMESPath %s for context entry %s: %w", path, a.entry.Name, err) return nil, fmt.Errorf("failed to apply JMESPath %s for context entry %s: %w", path, a.entry.Name, err)
} }
@ -224,17 +227,11 @@ func (a *apiCall) transformAndStore(jsonData []byte) ([]byte, error) {
return contextData, nil return contextData, nil
} }
func applyJMESPathJSON(jmesPath string, jsonData []byte) (interface{}, error) { func (a *apiCall) applyJMESPathJSON(jmesPath string, jsonData []byte) (interface{}, error) {
var data interface{} var data interface{}
err := json.Unmarshal(jsonData, &data) err := json.Unmarshal(jsonData, &data)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to unmarshal JSON: %s, error: %w", string(jsonData), err) return nil, fmt.Errorf("failed to unmarshal JSON: %s, error: %w", string(jsonData), err)
} }
return a.jp.Search(jmesPath, data)
jp, err := jmespath.New(jmesPath)
if err != nil {
return nil, fmt.Errorf("failed to compile JMESPath: %s, error: %v", jmesPath, err)
}
return jp.Search(data)
} }

View file

@ -9,11 +9,15 @@ import (
"github.com/go-logr/logr" "github.com/go-logr/logr"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/config"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"gotest.tools/assert" "gotest.tools/assert"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
) )
var jp = jmespath.New(config.NewDefaultConfiguration(false))
func buildTestServer(responseData []byte) *httptest.Server { func buildTestServer(responseData []byte) *httptest.Server {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc("/resource", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/resource", func(w http.ResponseWriter, r *http.Request) {
@ -38,9 +42,9 @@ func Test_serviceGetRequest(t *testing.T) {
defer s.Close() defer s.Close()
entry := kyvernov1.ContextEntry{} entry := kyvernov1.ContextEntry{}
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
_, err := New(logr.Discard(), entry, ctx, nil) _, err := New(logr.Discard(), jp, entry, ctx, nil)
assert.ErrorContains(t, err, "missing APICall") assert.ErrorContains(t, err, "missing APICall")
entry.Name = "test" entry.Name = "test"
@ -50,19 +54,19 @@ func Test_serviceGetRequest(t *testing.T) {
}, },
} }
call, err := New(logr.Discard(), entry, ctx, nil) call, err := New(logr.Discard(), jp, entry, ctx, nil)
assert.NilError(t, err) assert.NilError(t, err)
_, err = call.Execute(context.TODO()) _, err = call.Execute(context.TODO())
assert.ErrorContains(t, err, "invalid request type") assert.ErrorContains(t, err, "invalid request type")
entry.APICall.Service.Method = "GET" entry.APICall.Service.Method = "GET"
call, err = New(logr.Discard(), entry, ctx, nil) call, err = New(logr.Discard(), jp, entry, ctx, nil)
assert.NilError(t, err) assert.NilError(t, err)
_, err = call.Execute(context.TODO()) _, err = call.Execute(context.TODO())
assert.ErrorContains(t, err, "HTTP 404") assert.ErrorContains(t, err, "HTTP 404")
entry.APICall.Service.URL = s.URL + "/resource" entry.APICall.Service.URL = s.URL + "/resource"
call, err = New(logr.Discard(), entry, ctx, nil) call, err = New(logr.Discard(), jp, entry, ctx, nil)
assert.NilError(t, err) assert.NilError(t, err)
data, err := call.Execute(context.TODO()) data, err := call.Execute(context.TODO())
@ -86,8 +90,8 @@ func Test_servicePostRequest(t *testing.T) {
}, },
} }
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
call, err := New(logr.Discard(), entry, ctx, nil) call, err := New(logr.Discard(), jp, entry, ctx, nil)
assert.NilError(t, err) assert.NilError(t, err)
data, err := call.Execute(context.TODO()) data, err := call.Execute(context.TODO())
assert.NilError(t, err) assert.NilError(t, err)
@ -135,7 +139,7 @@ func Test_servicePostRequest(t *testing.T) {
}, },
} }
call, err = New(logr.Discard(), entry, ctx, nil) call, err = New(logr.Discard(), jp, entry, ctx, nil)
assert.NilError(t, err) assert.NilError(t, err)
data, err = call.Execute(context.TODO()) data, err = call.Execute(context.TODO())
assert.NilError(t, err) assert.NilError(t, err)

View file

@ -6,8 +6,10 @@ import (
"github.com/go-logr/logr" "github.com/go-logr/logr"
v1 "github.com/kyverno/kyverno/api/kyverno/v1" v1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/internal" "github.com/kyverno/kyverno/pkg/engine/internal"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/utils/api" "github.com/kyverno/kyverno/pkg/utils/api"
"github.com/kyverno/kyverno/pkg/utils/image" "github.com/kyverno/kyverno/pkg/utils/image"
"gotest.tools/assert" "gotest.tools/assert"
@ -245,7 +247,7 @@ func Test_Conditions(t *testing.T) {
}, },
} }
ctx := context.NewContext() ctx := context.NewContext(jmespath.New(config.NewDefaultConfiguration(false)))
img := api.ImageInfo{Pointer: "/spec/containers/0/image"} img := api.ImageInfo{Pointer: "/spec/containers/0/image"}
img.ImageInfo = image.ImageInfo{ img.ImageInfo = image.ImageInfo{
Registry: "docker.io", Registry: "docker.io",

View file

@ -10,6 +10,7 @@ import (
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1" kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/logging" "github.com/kyverno/kyverno/pkg/logging"
apiutils "github.com/kyverno/kyverno/pkg/utils/api" apiutils "github.com/kyverno/kyverno/pkg/utils/api"
admissionv1 "k8s.io/api/admission/v1" admissionv1 "k8s.io/api/admission/v1"
@ -98,6 +99,7 @@ type Interface interface {
// Context stores the data resources as JSON // Context stores the data resources as JSON
type context struct { type context struct {
jp jmespath.Interface
mutex sync.RWMutex mutex sync.RWMutex
jsonRaw []byte jsonRaw []byte
jsonRawCheckpoints [][]byte jsonRawCheckpoints [][]byte
@ -105,17 +107,17 @@ type context struct {
} }
// NewContext returns a new context // NewContext returns a new context
func NewContext() Interface { func NewContext(jp jmespath.Interface) Interface {
return NewContextFromRaw([]byte(`{}`)) return NewContextFromRaw(jp, []byte(`{}`))
} }
// NewContextFromRaw returns a new context initialized with raw data // NewContextFromRaw returns a new context initialized with raw data
func NewContextFromRaw(raw []byte) Interface { func NewContextFromRaw(jp jmespath.Interface, raw []byte) Interface {
ctx := context{ return &context{
jp: jp,
jsonRaw: raw, jsonRaw: raw,
jsonRawCheckpoints: make([][]byte, 0), jsonRawCheckpoints: make([][]byte, 0),
} }
return &ctx
} }
// addJSON merges json data // addJSON merges json data

View file

@ -5,9 +5,13 @@ import (
"testing" "testing"
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1" urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
authenticationv1 "k8s.io/api/authentication/v1" authenticationv1 "k8s.io/api/authentication/v1"
) )
var jp = jmespath.New(config.NewDefaultConfiguration(false))
func Test_addResourceAndUserContext(t *testing.T) { func Test_addResourceAndUserContext(t *testing.T) {
var err error var err error
rawResource := []byte(` rawResource := []byte(`
@ -55,7 +59,7 @@ func Test_addResourceAndUserContext(t *testing.T) {
} }
var expectedResult string var expectedResult string
ctx := NewContext() ctx := NewContext(jp)
err = AddResource(ctx, rawResource) err = AddResource(ctx, rawResource)
if err != nil { if err != nil {
t.Error(err) t.Error(err)

View file

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
datautils "github.com/kyverno/kyverno/pkg/utils/data" datautils "github.com/kyverno/kyverno/pkg/utils/data"
) )
@ -16,7 +15,7 @@ func (ctx *context) Query(query string) (interface{}, error) {
return nil, fmt.Errorf("invalid query (nil)") return nil, fmt.Errorf("invalid query (nil)")
} }
// compile the query // compile the query
queryPath, err := jmespath.New(query) queryPath, err := ctx.jp.Query(query)
if err != nil { if err != nil {
logger.Error(err, "incorrect query", "query", query) logger.Error(err, "incorrect query", "query", query)
return nil, fmt.Errorf("incorrect query %s: %v", query, err) return nil, fmt.Errorf("incorrect query %s: %v", query, err)

View file

@ -28,7 +28,7 @@ func TestHasChanged(t *testing.T) {
func TestRequestNotInitialize(t *testing.T) { func TestRequestNotInitialize(t *testing.T) {
request := admissionv1.AdmissionRequest{} request := admissionv1.AdmissionRequest{}
ctx := NewContext() ctx := NewContext(jp)
ctx.AddRequest(request) ctx.AddRequest(request)
_, err := ctx.HasChanged("x.y.z") _, err := ctx.HasChanged("x.y.z")
@ -37,7 +37,7 @@ func TestRequestNotInitialize(t *testing.T) {
func TestMissingOldObject(t *testing.T) { func TestMissingOldObject(t *testing.T) {
request := admissionv1.AdmissionRequest{} request := admissionv1.AdmissionRequest{}
ctx := NewContext() ctx := NewContext(jp)
ctx.AddRequest(request) ctx.AddRequest(request)
request.Object.Raw = []byte(`{"a": {"b": 1, "c": 2}, "d": 3}`) request.Object.Raw = []byte(`{"a": {"b": 1, "c": 2}, "d": 3}`)
@ -47,7 +47,7 @@ func TestMissingOldObject(t *testing.T) {
func TestMissingObject(t *testing.T) { func TestMissingObject(t *testing.T) {
request := admissionv1.AdmissionRequest{} request := admissionv1.AdmissionRequest{}
ctx := NewContext() ctx := NewContext(jp)
ctx.AddRequest(request) ctx.AddRequest(request)
request.OldObject.Raw = []byte(`{"a": {"b": 1, "c": 2}, "d": 3}`) request.OldObject.Raw = []byte(`{"a": {"b": 1, "c": 2}, "d": 3}`)
@ -61,7 +61,7 @@ func createTestContext(obj, oldObj string) Interface {
request.Object.Raw = []byte(obj) request.Object.Raw = []byte(obj)
request.OldObject.Raw = []byte(oldObj) request.OldObject.Raw = []byte(oldObj)
ctx := NewContext() ctx := NewContext(jp)
ctx.AddRequest(request) ctx.AddRequest(request)
return ctx return ctx
} }

View file

@ -6,6 +6,7 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine/jmespath" "github.com/kyverno/kyverno/pkg/engine/jmespath"
wildcard "github.com/kyverno/kyverno/pkg/utils/wildcard" wildcard "github.com/kyverno/kyverno/pkg/utils/wildcard"
) )
@ -41,7 +42,8 @@ func (ctx *MockContext) Query(query string) (interface{}, error) {
var emptyResult interface{} var emptyResult interface{}
// compile the query // compile the query
if _, err := jmespath.New(query); err != nil { jp := jmespath.New(config.NewDefaultConfiguration(false))
if _, err := jp.Query(query); err != nil {
return emptyResult, fmt.Errorf("invalid JMESPath query %s: %v", query, err) return emptyResult, fmt.Errorf("invalid JMESPath query %s: %v", query, err)
} }

View file

@ -14,6 +14,7 @@ import (
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/handlers" "github.com/kyverno/kyverno/pkg/engine/handlers"
"github.com/kyverno/kyverno/pkg/engine/internal" "github.com/kyverno/kyverno/pkg/engine/internal"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils" engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
"github.com/kyverno/kyverno/pkg/logging" "github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/metrics" "github.com/kyverno/kyverno/pkg/metrics"
@ -28,6 +29,7 @@ import (
type engine struct { type engine struct {
configuration config.Configuration configuration config.Configuration
metricsConfiguration config.MetricsConfiguration metricsConfiguration config.MetricsConfiguration
jp jmespath.Interface
client dclient.Interface client dclient.Interface
rclient registryclient.Client rclient registryclient.Client
contextLoader engineapi.ContextLoaderFactory contextLoader engineapi.ContextLoaderFactory
@ -42,6 +44,7 @@ type handlerFactory = func() (handlers.Handler, error)
func NewEngine( func NewEngine(
configuration config.Configuration, configuration config.Configuration,
metricsConfiguration config.MetricsConfiguration, metricsConfiguration config.MetricsConfiguration,
jp jmespath.Interface,
client dclient.Interface, client dclient.Interface,
rclient registryclient.Client, rclient registryclient.Client,
contextLoader engineapi.ContextLoaderFactory, contextLoader engineapi.ContextLoaderFactory,
@ -50,7 +53,7 @@ func NewEngine(
meter := global.MeterProvider().Meter(metrics.MeterName) meter := global.MeterProvider().Meter(metrics.MeterName)
resultCounter, err := meter.Int64Counter( resultCounter, err := meter.Int64Counter(
"kyverno_policy_results", "kyverno_policy_results",
instrument.WithDescription("can be used to track the results associated with the policies applied in the users cluster, at the level from rule to policy to admission requests"), instrument.WithDescription("can be used to track the results associated with the policies applied in the user's cluster, at the level from rule to policy to admission requests"),
) )
if err != nil { if err != nil {
logging.Error(err, "failed to register metric kyverno_policy_results") logging.Error(err, "failed to register metric kyverno_policy_results")
@ -65,6 +68,7 @@ func NewEngine(
return &engine{ return &engine{
configuration: configuration, configuration: configuration,
metricsConfiguration: metricsConfiguration, metricsConfiguration: metricsConfiguration,
jp: jp,
client: client, client: client,
rclient: rclient, rclient: rclient,
contextLoader: contextLoader, contextLoader: contextLoader,
@ -165,6 +169,7 @@ func (e *engine) ContextLoader(
return func(ctx context.Context, contextEntries []kyvernov1.ContextEntry, jsonContext enginecontext.Interface) error { return func(ctx context.Context, contextEntries []kyvernov1.ContextEntry, jsonContext enginecontext.Interface) error {
return loader.Load( return loader.Load(
ctx, ctx,
e.jp,
e.client, e.client,
e.rclient, e.rclient,
contextEntries, contextEntries,

View file

@ -6,7 +6,9 @@ import (
"github.com/go-logr/logr" "github.com/go-logr/logr"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1" kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
"gotest.tools/assert" "gotest.tools/assert"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@ -100,7 +102,8 @@ func Test_ForceMutateSubstituteVars(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() jp := jmespath.New(config.NewDefaultConfiguration(false))
ctx := context.NewContext(jp)
err = context.AddResource(ctx, rawResource) err = context.AddResource(ctx, rawResource)
assert.NilError(t, err) assert.NilError(t, err)
@ -205,7 +208,8 @@ func Test_ForceMutateSubstituteVarsWithPatchesJson6902(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() jp := jmespath.New(config.NewDefaultConfiguration(false))
ctx := context.NewContext(jp)
err = context.AddResource(ctx, rawResource) err = context.AddResource(ctx, rawResource)
assert.NilError(t, err) assert.NilError(t, err)
@ -291,7 +295,8 @@ func Test_ForceMutateSubstituteVarsWithPatchStrategicMerge(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() jp := jmespath.New(config.NewDefaultConfiguration(false))
ctx := context.NewContext(jp)
err = context.AddResource(ctx, rawResource) err = context.AddResource(ctx, rawResource)
assert.NilError(t, err) assert.NilError(t, err)

View file

@ -10,6 +10,7 @@ import (
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/engine/policycontext" "github.com/kyverno/kyverno/pkg/engine/policycontext"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
"gotest.tools/assert" "gotest.tools/assert"
@ -17,6 +18,8 @@ import (
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
) )
var jp = jmespath.New(config.NewDefaultConfiguration(false))
var test_policy = `{}` var test_policy = `{}`
var signed_resource = `{ var signed_resource = `{
@ -785,7 +788,7 @@ func buildContext(t *testing.T, policy, resource string, oldResource string) eng
resourceUnstructured, err := kubeutils.BytesToUnstructured([]byte(resource)) resourceUnstructured, err := kubeutils.BytesToUnstructured([]byte(resource))
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, []byte(resource)) err = enginecontext.AddResource(ctx, []byte(resource))
assert.NilError(t, err) assert.NilError(t, err)

View file

@ -15,6 +15,7 @@ import (
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/context/resolvers" "github.com/kyverno/kyverno/pkg/engine/context/resolvers"
"github.com/kyverno/kyverno/pkg/engine/internal" "github.com/kyverno/kyverno/pkg/engine/internal"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/engine/policycontext" "github.com/kyverno/kyverno/pkg/engine/policycontext"
"github.com/kyverno/kyverno/pkg/engine/utils" "github.com/kyverno/kyverno/pkg/engine/utils"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils" engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
@ -164,6 +165,7 @@ var signaturePayloads = [][]byte{
var ( var (
cfg = config.NewDefaultConfiguration(false) cfg = config.NewDefaultConfiguration(false)
metricsCfg = config.NewDefaultMetricsConfiguration() metricsCfg = config.NewDefaultMetricsConfiguration()
jp = jmespath.New(cfg)
) )
func testVerifyAndPatchImages( func testVerifyAndPatchImages(
@ -176,6 +178,7 @@ func testVerifyAndPatchImages(
e := NewEngine( e := NewEngine(
cfg, cfg,
metricsCfg, metricsCfg,
jp,
nil, nil,
rclient, rclient,
engineapi.DefaultContextLoaderFactory(cmResolver), engineapi.DefaultContextLoaderFactory(cmResolver),
@ -219,7 +222,7 @@ func buildContext(t *testing.T, policy, resource string, oldResource string) *Po
resourceUnstructured, err := kubeutils.BytesToUnstructured([]byte(resource)) resourceUnstructured, err := kubeutils.BytesToUnstructured([]byte(resource))
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, []byte(resource)) err = enginecontext.AddResource(ctx, []byte(resource))
assert.NilError(t, err) assert.NilError(t, err)

View file

@ -10,7 +10,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
) )
type Operand interface { type operand interface {
Add(interface{}, string) (interface{}, error) Add(interface{}, string) (interface{}, error)
Subtract(interface{}) (interface{}, error) Subtract(interface{}) (interface{}, error)
Multiply(interface{}) (interface{}, error) Multiply(interface{}) (interface{}, error)
@ -18,30 +18,30 @@ type Operand interface {
Modulo(interface{}) (interface{}, error) Modulo(interface{}) (interface{}, error)
} }
type Quantity struct { type quantity struct {
resource.Quantity resource.Quantity
} }
type Duration struct { type duration struct {
time.Duration time.Duration
} }
type Scalar struct { type scalar struct {
float64 float64
} }
func ParseArithemticOperands(arguments []interface{}, operator string) (Operand, Operand, error) { func parseArithemticOperands(arguments []interface{}, operator string) (operand, operand, error) {
op := [2]Operand{nil, nil} op := [2]operand{nil, nil}
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
if tmp, err := validateArg(divide, arguments, i, reflect.Float64); err == nil { if tmp, err := validateArg(divide, arguments, i, reflect.Float64); err == nil {
var sc Scalar var sc scalar
sc.float64 = tmp.Float() sc.float64 = tmp.Float()
op[i] = sc op[i] = sc
} else if tmp, err = validateArg(divide, arguments, i, reflect.String); err == nil { } else if tmp, err = validateArg(divide, arguments, i, reflect.String); err == nil {
if q, err := resource.ParseQuantity(tmp.String()); err == nil { if q, err := resource.ParseQuantity(tmp.String()); err == nil {
op[i] = Quantity{Quantity: q} op[i] = quantity{Quantity: q}
} else if d, err := time.ParseDuration(tmp.String()); err == nil { } else if d, err := time.ParseDuration(tmp.String()); err == nil {
op[i] = Duration{Duration: d} op[i] = duration{Duration: d}
} }
} }
} }
@ -58,9 +58,9 @@ func ParseArithemticOperands(arguments []interface{}, operator string) (Operand,
// Scalar +|- Scalar -> Scalar // Scalar +|- Scalar -> Scalar
// Scalar +|- Quantity|Duration -> error // Scalar +|- Quantity|Duration -> error
func (op1 Quantity) Add(op2 interface{}, operator string) (interface{}, error) { func (op1 quantity) Add(op2 interface{}, operator string) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Quantity: case quantity:
op1.Quantity.Add(v.Quantity) op1.Quantity.Add(v.Quantity)
return op1.String(), nil return op1.String(), nil
default: default:
@ -68,27 +68,27 @@ func (op1 Quantity) Add(op2 interface{}, operator string) (interface{}, error) {
} }
} }
func (op1 Duration) Add(op2 interface{}, operator string) (interface{}, error) { func (op1 duration) Add(op2 interface{}, operator string) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Duration: case duration:
return (op1.Duration + v.Duration).String(), nil return (op1.Duration + v.Duration).String(), nil
default: default:
return nil, formatError(typeMismatchError, operator) return nil, formatError(typeMismatchError, operator)
} }
} }
func (op1 Scalar) Add(op2 interface{}, operator string) (interface{}, error) { func (op1 scalar) Add(op2 interface{}, operator string) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Scalar: case scalar:
return op1.float64 + v.float64, nil return op1.float64 + v.float64, nil
default: default:
return nil, formatError(typeMismatchError, operator) return nil, formatError(typeMismatchError, operator)
} }
} }
func (op1 Quantity) Subtract(op2 interface{}) (interface{}, error) { func (op1 quantity) Subtract(op2 interface{}) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Quantity: case quantity:
op1.Quantity.Sub(v.Quantity) op1.Quantity.Sub(v.Quantity)
return op1.String(), nil return op1.String(), nil
default: default:
@ -96,18 +96,18 @@ func (op1 Quantity) Subtract(op2 interface{}) (interface{}, error) {
} }
} }
func (op1 Duration) Subtract(op2 interface{}) (interface{}, error) { func (op1 duration) Subtract(op2 interface{}) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Duration: case duration:
return (op1.Duration - v.Duration).String(), nil return (op1.Duration - v.Duration).String(), nil
default: default:
return nil, formatError(typeMismatchError, subtract) return nil, formatError(typeMismatchError, subtract)
} }
} }
func (op1 Scalar) Subtract(op2 interface{}) (interface{}, error) { func (op1 scalar) Subtract(op2 interface{}) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Scalar: case scalar:
return op1.float64 - v.float64, nil return op1.float64 - v.float64, nil
default: default:
return nil, formatError(typeMismatchError, subtract) return nil, formatError(typeMismatchError, subtract)
@ -124,9 +124,9 @@ func (op1 Scalar) Subtract(op2 interface{}) (interface{}, error) {
// Scalar * Quantity -> Quantity // Scalar * Quantity -> Quantity
// Scalar * Duration -> Duration // Scalar * Duration -> Duration
func (op1 Quantity) Multiply(op2 interface{}) (interface{}, error) { func (op1 quantity) Multiply(op2 interface{}) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Scalar: case scalar:
q, err := resource.ParseQuantity(fmt.Sprintf("%v", v.float64)) q, err := resource.ParseQuantity(fmt.Sprintf("%v", v.float64))
if err != nil { if err != nil {
return nil, err return nil, err
@ -139,9 +139,9 @@ func (op1 Quantity) Multiply(op2 interface{}) (interface{}, error) {
} }
} }
func (op1 Duration) Multiply(op2 interface{}) (interface{}, error) { func (op1 duration) Multiply(op2 interface{}) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Scalar: case scalar:
seconds := op1.Seconds() * v.float64 seconds := op1.Seconds() * v.float64
return time.Duration(seconds * float64(time.Second)).String(), nil return time.Duration(seconds * float64(time.Second)).String(), nil
default: default:
@ -149,13 +149,13 @@ func (op1 Duration) Multiply(op2 interface{}) (interface{}, error) {
} }
} }
func (op1 Scalar) Multiply(op2 interface{}) (interface{}, error) { func (op1 scalar) Multiply(op2 interface{}) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Scalar: case scalar:
return op1.float64 * v.float64, nil return op1.float64 * v.float64, nil
case Quantity: case quantity:
return v.Multiply(op1) return v.Multiply(op1)
case Duration: case duration:
return v.Multiply(op1) return v.Multiply(op1)
default: default:
return nil, formatError(typeMismatchError, multiply) return nil, formatError(typeMismatchError, multiply)
@ -174,16 +174,16 @@ func (op1 Scalar) Multiply(op2 interface{}) (interface{}, error) {
// Scalar / Quantity -> error // Scalar / Quantity -> error
// Scalar / Duration -> error // Scalar / Duration -> error
func (op1 Quantity) Divide(op2 interface{}) (interface{}, error) { func (op1 quantity) Divide(op2 interface{}) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Quantity: case quantity:
divisor := v.AsApproximateFloat64() divisor := v.AsApproximateFloat64()
if divisor == 0 { if divisor == 0 {
return nil, formatError(zeroDivisionError, divide) return nil, formatError(zeroDivisionError, divide)
} }
dividend := op1.AsApproximateFloat64() dividend := op1.AsApproximateFloat64()
return dividend / divisor, nil return dividend / divisor, nil
case Scalar: case scalar:
if v.float64 == 0 { if v.float64 == 0 {
return nil, formatError(zeroDivisionError, divide) return nil, formatError(zeroDivisionError, divide)
} }
@ -200,14 +200,14 @@ func (op1 Quantity) Divide(op2 interface{}) (interface{}, error) {
} }
} }
func (op1 Duration) Divide(op2 interface{}) (interface{}, error) { func (op1 duration) Divide(op2 interface{}) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Duration: case duration:
if v.Seconds() == 0 { if v.Seconds() == 0 {
return nil, formatError(zeroDivisionError, divide) return nil, formatError(zeroDivisionError, divide)
} }
return op1.Seconds() / v.Seconds(), nil return op1.Seconds() / v.Seconds(), nil
case Scalar: case scalar:
if v.float64 == 0 { if v.float64 == 0 {
return nil, formatError(zeroDivisionError, divide) return nil, formatError(zeroDivisionError, divide)
} }
@ -218,9 +218,9 @@ func (op1 Duration) Divide(op2 interface{}) (interface{}, error) {
} }
} }
func (op1 Scalar) Divide(op2 interface{}) (interface{}, error) { func (op1 scalar) Divide(op2 interface{}) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Scalar: case scalar:
if v.float64 == 0 { if v.float64 == 0 {
return nil, formatError(zeroDivisionError, divide) return nil, formatError(zeroDivisionError, divide)
} }
@ -239,9 +239,9 @@ func (op1 Scalar) Divide(op2 interface{}) (interface{}, error) {
// Scalar % Quantity|Duration -> error // Scalar % Quantity|Duration -> error
// Scalar % Scalar -> Scalar // Scalar % Scalar -> Scalar
func (op1 Quantity) Modulo(op2 interface{}) (interface{}, error) { func (op1 quantity) Modulo(op2 interface{}) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Quantity: case quantity:
f1 := op1.ToDec().AsApproximateFloat64() f1 := op1.ToDec().AsApproximateFloat64()
f2 := v.ToDec().AsApproximateFloat64() f2 := v.ToDec().AsApproximateFloat64()
i1 := int64(f1) i1 := int64(f1)
@ -261,9 +261,9 @@ func (op1 Quantity) Modulo(op2 interface{}) (interface{}, error) {
} }
} }
func (op1 Duration) Modulo(op2 interface{}) (interface{}, error) { func (op1 duration) Modulo(op2 interface{}) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Duration: case duration:
if v.Duration == 0 { if v.Duration == 0 {
return nil, formatError(zeroDivisionError, modulo) return nil, formatError(zeroDivisionError, modulo)
} }
@ -273,9 +273,9 @@ func (op1 Duration) Modulo(op2 interface{}) (interface{}, error) {
} }
} }
func (op1 Scalar) Modulo(op2 interface{}) (interface{}, error) { func (op1 scalar) Modulo(op2 interface{}) (interface{}, error) {
switch v := op2.(type) { switch v := op2.(type) {
case Scalar: case scalar:
val1 := int64(op1.float64) val1 := int64(op1.float64)
val2 := int64(v.float64) val2 := int64(v.float64)
if op1.float64 != float64(val1) { if op1.float64 != float64(val1) {

View file

@ -82,7 +82,7 @@ func Test_Add(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
jp, err := New(tc.test) jp, err := newJMESPath(tc.test)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -228,7 +228,7 @@ func Test_Sum(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
jp, err := New(tc.test) jp, err := newJMESPath(tc.test)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -327,7 +327,7 @@ func Test_Subtract(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
jp, err := New(tc.test) jp, err := newJMESPath(tc.test)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -426,7 +426,7 @@ func Test_Multiply(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
jp, err := New(tc.test) jp, err := newJMESPath(tc.test)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -588,7 +588,7 @@ func Test_Divide(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
jp, err := New(tc.test) jp, err := newJMESPath(tc.test)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -744,7 +744,7 @@ func Test_Modulo(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
jp, err := New(tc.test) jp, err := newJMESPath(tc.test)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -792,7 +792,7 @@ func TestScalar_Multiply(t *testing.T) {
}} }}
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
op1 := Scalar{ op1 := scalar{
float64: tt.fields.float64, float64: tt.fields.float64,
} }
got, err := op1.Multiply(tt.args.op2) got, err := op1.Multiply(tt.args.op2)
@ -815,8 +815,8 @@ func TestParseArithemticOperands(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
args args args args
want Operand want operand
want1 Operand want1 operand
wantErr bool wantErr bool
}{{ }{{
args: args{ args: args{
@ -837,7 +837,7 @@ func TestParseArithemticOperands(t *testing.T) {
}} }}
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got, got1, err := ParseArithemticOperands(tt.args.arguments, tt.args.operator) got, got1, err := parseArithemticOperands(tt.args.arguments, tt.args.operator)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("ParseArithemticOperands() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("ParseArithemticOperands() error = %v, wantErr %v", err, tt.wantErr)
return return

View file

@ -773,7 +773,7 @@ func jpToBoolean(arguments []interface{}) (interface{}, error) {
} }
func _jpAdd(arguments []interface{}, operator string) (interface{}, error) { func _jpAdd(arguments []interface{}, operator string) (interface{}, error) {
op1, op2, err := ParseArithemticOperands(arguments, operator) op1, op2, err := parseArithemticOperands(arguments, operator)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -804,7 +804,7 @@ func jpSum(arguments []interface{}) (interface{}, error) {
} }
func jpSubtract(arguments []interface{}) (interface{}, error) { func jpSubtract(arguments []interface{}) (interface{}, error) {
op1, op2, err := ParseArithemticOperands(arguments, subtract) op1, op2, err := parseArithemticOperands(arguments, subtract)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -813,7 +813,7 @@ func jpSubtract(arguments []interface{}) (interface{}, error) {
} }
func jpMultiply(arguments []interface{}) (interface{}, error) { func jpMultiply(arguments []interface{}) (interface{}, error) {
op1, op2, err := ParseArithemticOperands(arguments, multiply) op1, op2, err := parseArithemticOperands(arguments, multiply)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -822,7 +822,7 @@ func jpMultiply(arguments []interface{}) (interface{}, error) {
} }
func jpDivide(arguments []interface{}) (interface{}, error) { func jpDivide(arguments []interface{}) (interface{}, error) {
op1, op2, err := ParseArithemticOperands(arguments, divide) op1, op2, err := parseArithemticOperands(arguments, divide)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -831,7 +831,7 @@ func jpDivide(arguments []interface{}) (interface{}, error) {
} }
func jpModulo(arguments []interface{}) (interface{}, error) { func jpModulo(arguments []interface{}) (interface{}, error) {
op1, op2, err := ParseArithemticOperands(arguments, modulo) op1, op2, err := parseArithemticOperands(arguments, modulo)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -30,7 +30,7 @@ func Test_Compare(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.jmesPath, func(t *testing.T) { t.Run(tc.jmesPath, func(t *testing.T) {
jp, err := New(tc.jmesPath) jp, err := newJMESPath(tc.jmesPath)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -57,7 +57,7 @@ func Test_ParseJsonSerde(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc, func(t *testing.T) { t.Run(tc, func(t *testing.T) {
jp, err := New(fmt.Sprintf(`to_string(parse_json('%s'))`, tc)) jp, err := newJMESPath(fmt.Sprintf(`to_string(parse_json('%s'))`, tc))
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -88,7 +88,7 @@ func Test_ParseJsonComplex(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.input, func(t *testing.T) { t.Run(tc.input, func(t *testing.T) {
jp, err := New(tc.input) jp, err := newJMESPath(tc.input)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -165,7 +165,7 @@ bar: null
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.input, func(t *testing.T) { t.Run(tc.input, func(t *testing.T) {
jp, err := New(fmt.Sprintf(`parse_yaml('%s')`, tc.input)) jp, err := newJMESPath(fmt.Sprintf(`parse_yaml('%s')`, tc.input))
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
assert.NilError(t, err) assert.NilError(t, err)
@ -194,7 +194,7 @@ func Test_EqualFold(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.jmesPath, func(t *testing.T) { t.Run(tc.jmesPath, func(t *testing.T) {
jp, err := New(tc.jmesPath) jp, err := newJMESPath(tc.jmesPath)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -231,7 +231,7 @@ func Test_Replace(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.jmesPath, func(t *testing.T) { t.Run(tc.jmesPath, func(t *testing.T) {
jp, err := New(tc.jmesPath) jp, err := newJMESPath(tc.jmesPath)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -245,7 +245,7 @@ func Test_Replace(t *testing.T) {
} }
func Test_ReplaceAll(t *testing.T) { func Test_ReplaceAll(t *testing.T) {
jp, err := New("replace_all('Lorem ipsum dolor sit amet', 'ipsum', 'muspi')") jp, err := newJMESPath("replace_all('Lorem ipsum dolor sit amet', 'ipsum', 'muspi')")
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -276,7 +276,7 @@ func Test_ToUpper(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.jmesPath, func(t *testing.T) { t.Run(tc.jmesPath, func(t *testing.T) {
jp, err := New(tc.jmesPath) jp, err := newJMESPath(tc.jmesPath)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -309,7 +309,7 @@ func Test_ToLower(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.jmesPath, func(t *testing.T) { t.Run(tc.jmesPath, func(t *testing.T) {
jp, err := New(tc.jmesPath) jp, err := newJMESPath(tc.jmesPath)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -323,7 +323,7 @@ func Test_ToLower(t *testing.T) {
} }
func Test_Trim(t *testing.T) { func Test_Trim(t *testing.T) {
jp, err := New("trim('¡¡¡Hello, Gophers!!!', '!¡')") jp, err := newJMESPath("trim('¡¡¡Hello, Gophers!!!', '!¡')")
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -394,7 +394,7 @@ func Test_TrimPrefix(t *testing.T) {
} }
func Test_Split(t *testing.T) { func Test_Split(t *testing.T) {
jp, err := New("split('Hello, Gophers', ', ')") jp, err := newJMESPath("split('Hello, Gophers', ', ')")
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -407,7 +407,7 @@ func Test_Split(t *testing.T) {
} }
func Test_HasPrefix(t *testing.T) { func Test_HasPrefix(t *testing.T) {
jp, err := New("starts_with('Gophers', 'Go')") jp, err := newJMESPath("starts_with('Gophers', 'Go')")
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -419,7 +419,7 @@ func Test_HasPrefix(t *testing.T) {
} }
func Test_HasSuffix(t *testing.T) { func Test_HasSuffix(t *testing.T) {
jp, err := New("ends_with('Amigo', 'go')") jp, err := newJMESPath("ends_with('Amigo', 'go')")
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -434,7 +434,7 @@ func Test_RegexMatch(t *testing.T) {
data := make(map[string]interface{}) data := make(map[string]interface{})
data["foo"] = "hgf'b1a2r'b12g" data["foo"] = "hgf'b1a2r'b12g"
query, err := New("regex_match('12.*', foo)") query, err := newJMESPath("regex_match('12.*', foo)")
assert.NilError(t, err) assert.NilError(t, err)
result, err := query.Search(data) result, err := query.Search(data)
@ -446,7 +446,7 @@ func Test_RegexMatchWithNumber(t *testing.T) {
data := make(map[string]interface{}) data := make(map[string]interface{})
data["foo"] = -12.0 data["foo"] = -12.0
query, err := New("regex_match('12.*', abs(foo))") query, err := newJMESPath("regex_match('12.*', abs(foo))")
assert.NilError(t, err) assert.NilError(t, err)
result, err := query.Search(data) result, err := query.Search(data)
@ -458,7 +458,7 @@ func Test_PatternMatch(t *testing.T) {
data := make(map[string]interface{}) data := make(map[string]interface{})
data["foo"] = "prefix-foo" data["foo"] = "prefix-foo"
query, err := New("pattern_match('prefix-*', foo)") query, err := newJMESPath("pattern_match('prefix-*', foo)")
assert.NilError(t, err) assert.NilError(t, err)
result, err := query.Search(data) result, err := query.Search(data)
@ -470,7 +470,7 @@ func Test_PatternMatchWithNumber(t *testing.T) {
data := make(map[string]interface{}) data := make(map[string]interface{})
data["foo"] = -12.0 data["foo"] = -12.0
query, err := New("pattern_match('12*', abs(foo))") query, err := newJMESPath("pattern_match('12*', abs(foo))")
assert.NilError(t, err) assert.NilError(t, err)
result, err := query.Search(data) result, err := query.Search(data)
@ -497,7 +497,7 @@ func Test_RegexReplaceAll(t *testing.T) {
var resource interface{} var resource interface{}
err := json.Unmarshal(resourceRaw, &resource) err := json.Unmarshal(resourceRaw, &resource)
assert.NilError(t, err) assert.NilError(t, err)
query, err := New(`regex_replace_all('([Hh]e|G)l', spec.field, '${2}G')`) query, err := newJMESPath(`regex_replace_all('([Hh]e|G)l', spec.field, '${2}G')`)
assert.NilError(t, err) assert.NilError(t, err)
res, err := query.Search(resource) res, err := query.Search(resource)
@ -528,7 +528,7 @@ func Test_RegexReplaceAllLiteral(t *testing.T) {
err := json.Unmarshal(resourceRaw, &resource) err := json.Unmarshal(resourceRaw, &resource)
assert.NilError(t, err) assert.NilError(t, err)
query, err := New(`regex_replace_all_literal('[Hh]el?', spec.field, 'G')`) query, err := newJMESPath(`regex_replace_all_literal('[Hh]el?', spec.field, 'G')`)
assert.NilError(t, err) assert.NilError(t, err)
res, err := query.Search(resource) res, err := query.Search(resource)
@ -583,7 +583,7 @@ func Test_LabelMatch(t *testing.T) {
err := json.Unmarshal(tc.resource, &resource) err := json.Unmarshal(tc.resource, &resource)
assert.NilError(t, err) assert.NilError(t, err)
query, err := New("label_match(`" + tc.test + "`, metadata.labels)") query, err := newJMESPath("label_match(`" + tc.test + "`, metadata.labels)")
assert.NilError(t, err) assert.NilError(t, err)
res, err := query.Search(resource) res, err := query.Search(resource)
@ -627,7 +627,7 @@ func Test_JpToBoolean(t *testing.T) {
} }
func Test_Base64Decode(t *testing.T) { func Test_Base64Decode(t *testing.T) {
jp, err := New("base64_decode('SGVsbG8sIHdvcmxkIQ==')") jp, err := newJMESPath("base64_decode('SGVsbG8sIHdvcmxkIQ==')")
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -639,7 +639,7 @@ func Test_Base64Decode(t *testing.T) {
} }
func Test_Base64Encode(t *testing.T) { func Test_Base64Encode(t *testing.T) {
jp, err := New("base64_encode('Hello, world!')") jp, err := newJMESPath("base64_encode('Hello, world!')")
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -669,7 +669,7 @@ func Test_Base64Decode_Secret(t *testing.T) {
err := json.Unmarshal(resourceRaw, &resource) err := json.Unmarshal(resourceRaw, &resource)
assert.NilError(t, err) assert.NilError(t, err)
query, err := New(`base64_decode(data.example1)`) query, err := newJMESPath(`base64_decode(data.example1)`)
assert.NilError(t, err) assert.NilError(t, err)
res, err := query.Search(resource) res, err := query.Search(resource)
@ -744,7 +744,7 @@ func Test_PathCanonicalize(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.jmesPath, func(t *testing.T) { t.Run(tc.jmesPath, func(t *testing.T) {
jp, err := New(tc.jmesPath) jp, err := newJMESPath(tc.jmesPath)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -793,7 +793,7 @@ func Test_Truncate(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.jmesPath, func(t *testing.T) { t.Run(tc.jmesPath, func(t *testing.T) {
jp, err := New(tc.jmesPath) jp, err := newJMESPath(tc.jmesPath)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -830,7 +830,7 @@ func Test_SemverCompare(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.jmesPath, func(t *testing.T) { t.Run(tc.jmesPath, func(t *testing.T) {
jp, err := New(tc.jmesPath) jp, err := newJMESPath(tc.jmesPath)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")
@ -877,7 +877,7 @@ func Test_Items(t *testing.T) {
} }
for i, tc := range testCases { for i, tc := range testCases {
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
query, err := New("items(`" + tc.object + "`,`" + tc.keyName + "`,`" + tc.valName + "`)") query, err := newJMESPath("items(`" + tc.object + "`,`" + tc.keyName + "`,`" + tc.valName + "`)")
assert.NilError(t, err) assert.NilError(t, err)
res, err := query.Search("") res, err := query.Search("")
@ -928,7 +928,7 @@ func Test_ObjectFromLists(t *testing.T) {
} }
for i, tc := range testCases { for i, tc := range testCases {
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
query, err := New("object_from_lists(`" + tc.keys + "`,`" + tc.values + "`)") query, err := newJMESPath("object_from_lists(`" + tc.keys + "`,`" + tc.values + "`)")
assert.NilError(t, err) assert.NilError(t, err)
res, err := query.Search("") res, err := query.Search("")
assert.NilError(t, err) assert.NilError(t, err)
@ -1022,7 +1022,7 @@ UFOZZVoELaasWS559wy8og39Eq21dDMynb8Bndn/
}} }}
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.jmesPath, func(t *testing.T) { t.Run(tc.jmesPath, func(t *testing.T) {
jp, err := New(tc.jmesPath) jp, err := newJMESPath(tc.jmesPath)
assert.NilError(t, err) assert.NilError(t, err)
result, err := jp.Search("") result, err := jp.Search("")

View file

@ -0,0 +1,34 @@
package jmespath
import "github.com/kyverno/kyverno/pkg/config"
type Query interface {
Search(interface{}) (interface{}, error)
}
type Interface interface {
Query(string) (Query, error)
Search(string, interface{}) (interface{}, error)
}
type implementation struct {
configuration config.Configuration
}
func New(configuration config.Configuration) Interface {
return implementation{
configuration: configuration,
}
}
func (i implementation) Query(query string) (Query, error) {
return newJMESPath(query)
}
func (i implementation) Search(query string, data interface{}) (interface{}, error) {
if query, err := i.Query(query); err != nil {
return nil, err
} else {
return query.Search(data)
}
}

View file

@ -4,7 +4,7 @@ import (
gojmespath "github.com/jmespath/go-jmespath" gojmespath "github.com/jmespath/go-jmespath"
) )
func New(query string) (*gojmespath.JMESPath, error) { func newJMESPath(query string) (*gojmespath.JMESPath, error) {
jp, err := gojmespath.Compile(query) jp, err := gojmespath.Compile(query)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -25,7 +25,7 @@ func TestNew(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
_, err := New(tt.args.query) _, err := newJMESPath(tt.args.query)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr)
return return

View file

@ -25,7 +25,7 @@ func Test_TimeSince(t *testing.T) {
} }
for i, tc := range testCases { for i, tc := range testCases {
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
query, err := New(tc.test) query, err := newJMESPath(tc.test)
assert.NilError(t, err) assert.NilError(t, err)
res, err := query.Search("") res, err := query.Search("")
@ -55,7 +55,7 @@ func Test_TimeToCron(t *testing.T) {
} }
for i, tc := range testCases { for i, tc := range testCases {
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
query, err := New(tc.test) query, err := newJMESPath(tc.test)
assert.NilError(t, err) assert.NilError(t, err)
res, err := query.Search("") res, err := query.Search("")
@ -85,7 +85,7 @@ func Test_TimeAdd(t *testing.T) {
} }
for i, tc := range testCases { for i, tc := range testCases {
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
query, err := New(tc.test) query, err := newJMESPath(tc.test)
assert.NilError(t, err) assert.NilError(t, err)
res, err := query.Search("") res, err := query.Search("")
@ -115,7 +115,7 @@ func Test_TimeParse(t *testing.T) {
} }
for i, tc := range testCases { for i, tc := range testCases {
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
query, err := New(tc.test) query, err := newJMESPath(tc.test)
assert.NilError(t, err) assert.NilError(t, err)
res, err := query.Search("") res, err := query.Search("")
@ -145,7 +145,7 @@ func Test_TimeUtc(t *testing.T) {
} }
for i, tc := range testCases { for i, tc := range testCases {
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
query, err := New(tc.test) query, err := newJMESPath(tc.test)
assert.NilError(t, err) assert.NilError(t, err)
res, err := query.Search("") res, err := query.Search("")
@ -171,7 +171,7 @@ func Test_TimeDiff(t *testing.T) {
} }
for i, tc := range testCases { for i, tc := range testCases {
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
query, err := New(tc.test) query, err := newJMESPath(tc.test)
assert.NilError(t, err) assert.NilError(t, err)
res, err := query.Search("") res, err := query.Search("")

View file

@ -6,8 +6,10 @@ import (
"github.com/go-logr/logr" "github.com/go-logr/logr"
types "github.com/kyverno/kyverno/api/kyverno/v1" types "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/config"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
"gotest.tools/assert" "gotest.tools/assert"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
@ -47,7 +49,7 @@ const endpointsDocument string = `{
}` }`
func applyPatches(rule *types.Rule, resource unstructured.Unstructured) (*engineapi.RuleResponse, unstructured.Unstructured) { func applyPatches(rule *types.Rule, resource unstructured.Unstructured) (*engineapi.RuleResponse, unstructured.Unstructured) {
mutateResp := Mutate(rule, context.NewContext(), resource, logr.Discard()) mutateResp := Mutate(rule, context.NewContext(jmespath.New(config.NewDefaultConfiguration(false))), resource, logr.Discard())
if mutateResp.Status != engineapi.RuleStatusPass { if mutateResp.Status != engineapi.RuleStatusPass {
return engineapi.NewRuleResponse("", engineapi.Mutation, mutateResp.Message, mutateResp.Status), resource return engineapi.NewRuleResponse("", engineapi.Mutation, mutateResp.Message, mutateResp.Status), resource
} }

View file

@ -34,6 +34,7 @@ func testMutate(
e := NewEngine( e := NewEngine(
cfg, cfg,
config.NewDefaultMetricsConfiguration(), config.NewDefaultMetricsConfiguration(),
jp,
client, client,
rclient, rclient,
contextLoader, contextLoader,
@ -104,7 +105,7 @@ func Test_VariableSubstitutionPatchStrategicMerge(t *testing.T) {
} }
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -185,7 +186,7 @@ func Test_variableSubstitutionPathNotExist(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -262,7 +263,7 @@ func Test_variableSubstitutionCLI(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -382,7 +383,7 @@ func Test_chained_rules(t *testing.T) {
resource, err := kubeutils.BytesToUnstructured(resourceRaw) resource, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = ctx.AddResource(resource.Object) err = ctx.AddResource(resource.Object)
assert.NilError(t, err) assert.NilError(t, err)
@ -470,7 +471,7 @@ func Test_precondition(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -564,7 +565,7 @@ func Test_nonZeroIndexNumberPatchesJson6902(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -650,7 +651,7 @@ func Test_foreach(t *testing.T) {
resource, err := kubeutils.BytesToUnstructured(resourceRaw) resource, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = ctx.AddResource(resource.Object) err = ctx.AddResource(resource.Object)
assert.NilError(t, err) assert.NilError(t, err)
@ -752,7 +753,7 @@ func Test_foreach_element_mutation(t *testing.T) {
resource, err := kubeutils.BytesToUnstructured(resourceRaw) resource, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = ctx.AddResource(resource.Object) err = ctx.AddResource(resource.Object)
assert.NilError(t, err) assert.NilError(t, err)
@ -873,7 +874,7 @@ func Test_Container_InitContainer_foreach(t *testing.T) {
resource, err := kubeutils.BytesToUnstructured(resourceRaw) resource, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = ctx.AddResource(resource.Object) err = ctx.AddResource(resource.Object)
assert.NilError(t, err) assert.NilError(t, err)
@ -1018,7 +1019,7 @@ func testApplyPolicyToResource(t *testing.T, policyRaw, resourceRaw []byte) engi
resource, err := kubeutils.BytesToUnstructured(resourceRaw) resource, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = ctx.AddResource(resource.Object) err = ctx.AddResource(resource.Object)
assert.NilError(t, err) assert.NilError(t, err)
@ -1556,7 +1557,7 @@ func Test_mutate_existing_resources(t *testing.T) {
target, err := kubeutils.BytesToUnstructured(target) target, err := kubeutils.BytesToUnstructured(target)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = ctx.AddResource(trigger.Object) err = ctx.AddResource(trigger.Object)
assert.NilError(t, err) assert.NilError(t, err)
@ -1671,7 +1672,7 @@ func Test_RuleSelectorMutate(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -2052,7 +2053,7 @@ func Test_SpecialCharacters(t *testing.T) {
} }
// Create JSON context and add the resource. // Create JSON context and add the resource.
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = ctx.AddResource(resource.Object) err = ctx.AddResource(resource.Object)
if err != nil { if err != nil {
t.Fatalf("ctx.AddResource() error = %v", err) t.Fatalf("ctx.AddResource() error = %v", err)

View file

@ -8,6 +8,7 @@ import (
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginectx "github.com/kyverno/kyverno/pkg/engine/context" enginectx "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission" admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
admissionv1 "k8s.io/api/admission/v1" admissionv1 "k8s.io/api/admission/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -184,17 +185,18 @@ func NewPolicyContextWithJsonContext(operation kyvernov1.AdmissionOperation, jso
} }
} }
func NewPolicyContext(operation kyvernov1.AdmissionOperation) *PolicyContext { func NewPolicyContext(jp jmespath.Interface, operation kyvernov1.AdmissionOperation) *PolicyContext {
return NewPolicyContextWithJsonContext(operation, enginectx.NewContext()) return NewPolicyContextWithJsonContext(operation, enginectx.NewContext(jp))
} }
func NewPolicyContextFromAdmissionRequest( func NewPolicyContextFromAdmissionRequest(
jp jmespath.Interface,
request admissionv1.AdmissionRequest, request admissionv1.AdmissionRequest,
admissionInfo kyvernov1beta1.RequestInfo, admissionInfo kyvernov1beta1.RequestInfo,
gvk schema.GroupVersionKind, gvk schema.GroupVersionKind,
configuration config.Configuration, configuration config.Configuration,
) (*PolicyContext, error) { ) (*PolicyContext, error) {
ctx, err := newVariablesContext(request, &admissionInfo) ctx, err := newVariablesContext(jp, request, &admissionInfo)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create policy rule context: %w", err) return nil, fmt.Errorf("failed to create policy rule context: %w", err)
} }
@ -215,8 +217,12 @@ func NewPolicyContextFromAdmissionRequest(
return policyContext, nil return policyContext, nil
} }
func newVariablesContext(request admissionv1.AdmissionRequest, userRequestInfo *kyvernov1beta1.RequestInfo) (enginectx.Interface, error) { func newVariablesContext(
ctx := enginectx.NewContext() jp jmespath.Interface,
request admissionv1.AdmissionRequest,
userRequestInfo *kyvernov1beta1.RequestInfo,
) (enginectx.Interface, error) {
ctx := enginectx.NewContext(jp)
if err := ctx.AddRequest(request); err != nil { if err := ctx.AddRequest(request); err != nil {
return nil, fmt.Errorf("failed to load incoming request in context: %w", err) return nil, fmt.Errorf("failed to load incoming request in context: %w", err)
} }

View file

@ -8,6 +8,7 @@ import (
"github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/clients/dclient"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/logging" "github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/registryclient"
) )
@ -44,6 +45,7 @@ type mockContextLoader struct {
func (l *mockContextLoader) Load( func (l *mockContextLoader) Load(
ctx context.Context, ctx context.Context,
jp jmespath.Interface,
client dclient.Interface, client dclient.Interface,
rclient registryclient.Client, rclient registryclient.Client,
contextEntries []kyvernov1.ContextEntry, contextEntries []kyvernov1.ContextEntry,
@ -63,15 +65,15 @@ func (l *mockContextLoader) Load(
// Context Variable should be loaded after the values loaded from values file // Context Variable should be loaded after the values loaded from values file
for _, entry := range contextEntries { for _, entry := range contextEntries {
if entry.ImageRegistry != nil && rclient != nil { if entry.ImageRegistry != nil && rclient != nil {
if err := engineapi.LoadImageData(ctx, rclient, l.logger, entry, jsonContext); err != nil { if err := engineapi.LoadImageData(ctx, jp, rclient, l.logger, entry, jsonContext); err != nil {
return err return err
} }
} else if entry.Variable != nil { } else if entry.Variable != nil {
if err := engineapi.LoadVariable(l.logger, entry, jsonContext); err != nil { if err := engineapi.LoadVariable(l.logger, jp, entry, jsonContext); err != nil {
return err return err
} }
} else if entry.APICall != nil && l.allowApiCall { } else if entry.APICall != nil && l.allowApiCall {
if err := engineapi.LoadAPIData(ctx, l.logger, entry, jsonContext, client); err != nil { if err := engineapi.LoadAPIData(ctx, jp, l.logger, entry, jsonContext, client); err != nil {
return err return err
} }
} }

View file

@ -32,6 +32,7 @@ func testValidate(
e := NewEngine( e := NewEngine(
cfg, cfg,
config.NewDefaultMetricsConfiguration(), config.NewDefaultMetricsConfiguration(),
jp,
nil, nil,
rclient, rclient,
contextLoader, contextLoader,
@ -136,7 +137,7 @@ func TestValidate_image_tag_fail(t *testing.T) {
"validation error: imagePullPolicy 'Always' required with tag 'latest'. rule validate-latest failed at path /spec/containers/0/imagePullPolicy/", "validation error: imagePullPolicy 'Always' required with tag 'latest'. rule validate-latest failed at path /spec/containers/0/imagePullPolicy/",
} }
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
assert.Equal(t, r.Message(), msgs[index]) assert.Equal(t, r.Message(), msgs[index])
} }
@ -236,7 +237,7 @@ func TestValidate_image_tag_pass(t *testing.T) {
"validation rule 'validate-tag' passed.", "validation rule 'validate-tag' passed.",
"validation rule 'validate-latest' passed.", "validation rule 'validate-latest' passed.",
} }
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
assert.Equal(t, r.Message(), msgs[index]) assert.Equal(t, r.Message(), msgs[index])
} }
@ -310,7 +311,7 @@ func TestValidate_Fail_anyPattern(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
assert.Assert(t, !er.IsSuccessful()) assert.Assert(t, !er.IsSuccessful())
msgs := []string{"validation error: A namespace is required. rule check-default-namespace[0] failed at path /metadata/namespace/ rule check-default-namespace[1] failed at path /metadata/namespace/"} msgs := []string{"validation error: A namespace is required. rule check-default-namespace[0] failed at path /metadata/namespace/ rule check-default-namespace[1] failed at path /metadata/namespace/"}
@ -393,7 +394,7 @@ func TestValidate_host_network_port(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
msgs := []string{"validation error: Host network and port are not allowed. rule validate-host-network-port failed at path /spec/containers/0/ports/0/hostPort/"} msgs := []string{"validation error: Host network and port are not allowed. rule validate-host-network-port failed at path /spec/containers/0/ports/0/hostPort/"}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
@ -483,7 +484,7 @@ func TestValidate_anchor_arraymap_pass(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
msgs := []string{"validation rule 'validate-host-path' passed."} msgs := []string{"validation rule 'validate-host-path' passed."}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
@ -571,7 +572,7 @@ func TestValidate_anchor_arraymap_fail(t *testing.T) {
assert.NilError(t, err) assert.NilError(t, err)
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
msgs := []string{"validation error: Host path '/var/lib/' is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/path/"} msgs := []string{"validation error: Host path '/var/lib/' is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/path/"}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
@ -641,7 +642,7 @@ func TestValidate_anchor_map_notfound(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
msgs := []string{"validation rule 'pod rule 2' passed."} msgs := []string{"validation rule 'pod rule 2' passed."}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
@ -714,7 +715,7 @@ func TestValidate_anchor_map_found_valid(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
msgs := []string{"validation rule 'pod rule 2' passed."} msgs := []string{"validation rule 'pod rule 2' passed."}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
@ -788,7 +789,7 @@ func TestValidate_inequality_List_Processing(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
msgs := []string{"validation rule 'pod rule 2' passed."} msgs := []string{"validation rule 'pod rule 2' passed."}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
@ -868,7 +869,7 @@ func TestValidate_inequality_List_ProcessingBrackets(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
msgs := []string{"validation rule 'pod rule 2' passed."} msgs := []string{"validation rule 'pod rule 2' passed."}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
@ -942,7 +943,7 @@ func TestValidate_anchor_map_found_invalid(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
msgs := []string{"validation error: pod: validate run as non root user. rule pod rule 2 failed at path /spec/securityContext/runAsNonRoot/"} msgs := []string{"validation error: pod: validate run as non root user. rule pod rule 2 failed at path /spec/securityContext/runAsNonRoot/"}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
@ -1017,7 +1018,7 @@ func TestValidate_AnchorList_pass(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
msgs := []string{"validation rule 'pod image rule' passed."} msgs := []string{"validation rule 'pod image rule' passed."}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
@ -1092,7 +1093,7 @@ func TestValidate_AnchorList_fail(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
assert.Assert(t, !er.IsSuccessful()) assert.Assert(t, !er.IsSuccessful())
} }
@ -1162,7 +1163,7 @@ func TestValidate_existenceAnchor_fail(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
assert.Assert(t, !er.IsSuccessful()) assert.Assert(t, !er.IsSuccessful())
} }
@ -1232,7 +1233,7 @@ func TestValidate_existenceAnchor_pass(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
msgs := []string{"validation rule 'pod image rule' passed."} msgs := []string{"validation rule 'pod image rule' passed."}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
@ -1320,7 +1321,7 @@ func TestValidate_negationAnchor_deny(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
msgs := []string{"validation error: Host path is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/"} msgs := []string{"validation error: Host path is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/"}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
@ -1407,7 +1408,7 @@ func TestValidate_negationAnchor_pass(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
msgs := []string{"validation rule 'validate-host-path' passed."} msgs := []string{"validation rule 'validate-host-path' passed."}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
@ -1475,7 +1476,7 @@ func Test_VariableSubstitutionPathNotExistInPattern(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -1565,7 +1566,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_OnePatternStatisfiesButSu
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -1623,7 +1624,7 @@ func Test_VariableSubstitution_NotOperatorWithStringVariable(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -1711,7 +1712,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathNotPresent(t *test
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -1801,7 +1802,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathPresent_NonePatter
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -1903,7 +1904,7 @@ func Test_VariableSubstitutionValidate_VariablesInMessageAreResolved(t *testing.
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -1953,7 +1954,7 @@ func Test_Flux_Kustomization_PathNotPresent(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(test.resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(test.resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, test.resourceRaw) err = enginecontext.AddResource(ctx, test.resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -2095,7 +2096,7 @@ func executeTest(t *testing.T, test testCase) {
t.Fatal(err) t.Fatal(err)
} }
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = ctx.AddRequest(request) err = ctx.AddRequest(request)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -2205,7 +2206,7 @@ func TestValidate_context_variable_substitution_CLI(t *testing.T) {
er := testValidate( er := testValidate(
context.TODO(), context.TODO(),
registryclient.NewOrDie(), registryclient.NewOrDie(),
NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured),
cfg, cfg,
enginetest.ContextLoaderFactory( enginetest.ContextLoaderFactory(
nil, nil,
@ -2303,7 +2304,7 @@ func Test_EmptyStringInDenyCondition(t *testing.T) {
err := json.Unmarshal(policyRaw, &policy) err := json.Unmarshal(policyRaw, &policy)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -2396,7 +2397,7 @@ func Test_StringInDenyCondition(t *testing.T) {
err := json.Unmarshal(policyRaw, &policy) err := json.Unmarshal(policyRaw, &policy)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -3079,7 +3080,7 @@ func testForEach(t *testing.T, policyraw []byte, resourceRaw []byte, msg string,
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -3141,7 +3142,7 @@ func Test_delete_ignore_pattern(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
ctx := enginecontext.NewContext() ctx := enginecontext.NewContext(jp)
err = enginecontext.AddResource(ctx, resourceRaw) err = enginecontext.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -3216,7 +3217,7 @@ func Test_ValidatePattern_anyPattern(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(tc.rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(tc.rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil) er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext(jp)).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
if tc.expectedFailed { if tc.expectedFailed {
assert.Assert(t, er.IsFailed()) assert.Assert(t, er.IsFailed())
} else if tc.expectedSkipped { } else if tc.expectedSkipped {

View file

@ -6,7 +6,9 @@ import (
"github.com/go-logr/logr" "github.com/go-logr/logr"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1" kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -376,7 +378,7 @@ func TestEvaluate(t *testing.T) {
{kyverno.Condition{RawKey: kyverno.ToJSON([]interface{}{1, 5, 7}), Operator: kyverno.ConditionOperators["AnyNotIn"], RawValue: kyverno.ToJSON("0-10")}, false}, {kyverno.Condition{RawKey: kyverno.ToJSON([]interface{}{1, 5, 7}), Operator: kyverno.ConditionOperators["AnyNotIn"], RawValue: kyverno.ToJSON("0-10")}, false},
} }
ctx := context.NewContext() ctx := context.NewContext(jmespath.New(config.NewDefaultConfiguration(false)))
for _, tc := range testCases { for _, tc := range testCases {
if Evaluate(logr.Discard(), ctx, tc.Condition) != tc.Result { if Evaluate(logr.Discard(), ctx, tc.Condition) != tc.Result {
t.Errorf("%v - expected result to be %v", tc.Condition, tc.Result) t.Errorf("%v - expected result to be %v", tc.Condition, tc.Result)
@ -401,7 +403,7 @@ func Test_Eval_Equal_Var_Pass(t *testing.T) {
`) `)
// context // context
ctx := context.NewContext() ctx := context.NewContext(jmespath.New(config.NewDefaultConfiguration(false)))
err := context.AddResource(ctx, resourceRaw) err := context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -443,7 +445,7 @@ func Test_Eval_Equal_Var_Fail(t *testing.T) {
`) `)
// context // context
ctx := context.NewContext() ctx := context.NewContext(jmespath.New(config.NewDefaultConfiguration(false)))
err := context.AddResource(ctx, resourceRaw) err := context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)

View file

@ -7,11 +7,15 @@ import (
"github.com/go-logr/logr" "github.com/go-logr/logr"
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1" urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"gotest.tools/assert" "gotest.tools/assert"
authenticationv1 "k8s.io/api/authentication/v1" authenticationv1 "k8s.io/api/authentication/v1"
) )
var jp = jmespath.New(config.NewDefaultConfiguration(false))
func Test_variablesub1(t *testing.T) { func Test_variablesub1(t *testing.T) {
patternMap := []byte(` patternMap := []byte(`
{ {
@ -74,7 +78,7 @@ func Test_variablesub1(t *testing.T) {
t.Error(err) t.Error(err)
} }
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -164,7 +168,7 @@ func Test_variablesub_multiple(t *testing.T) {
} }
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -252,7 +256,7 @@ func Test_variablesubstitution(t *testing.T) {
} }
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -317,7 +321,7 @@ func Test_variableSubstitutionValue(t *testing.T) {
} }
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -374,7 +378,7 @@ func Test_variableSubstitutionValueOperatorNotEqual(t *testing.T) {
} }
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -432,7 +436,7 @@ func Test_variableSubstitutionValueFail(t *testing.T) {
} }
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -489,7 +493,7 @@ func Test_variableSubstitutionObject(t *testing.T) {
} }
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -553,7 +557,7 @@ func Test_variableSubstitutionObjectOperatorNotEqualFail(t *testing.T) {
} }
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -628,7 +632,7 @@ func Test_variableSubstitutionMultipleObject(t *testing.T) {
} }
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)

View file

@ -64,7 +64,7 @@ func Test_subVars_success(t *testing.T) {
t.Error(err) t.Error(err)
} }
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -125,7 +125,7 @@ func Test_subVars_failed(t *testing.T) {
t.Error(err) t.Error(err)
} }
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -219,7 +219,7 @@ func Test_subVars_with_JMESPath_At(t *testing.T) {
err = json.Unmarshal(resourceRaw, &resource) err = json.Unmarshal(resourceRaw, &resource)
assert.NilError(t, err) assert.NilError(t, err)
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -278,7 +278,7 @@ func Test_subVars_withRegexMatch(t *testing.T) {
err = json.Unmarshal(resourceRaw, &resource) err = json.Unmarshal(resourceRaw, &resource)
assert.NilError(t, err) assert.NilError(t, err)
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -308,7 +308,7 @@ func Test_subVars_withMerge(t *testing.T) {
err = json.Unmarshal(resourceRaw, &resource) err = json.Unmarshal(resourceRaw, &resource)
assert.NilError(t, err) assert.NilError(t, err)
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -351,7 +351,7 @@ func Test_subVars_withRegexReplaceAll(t *testing.T) {
err = json.Unmarshal(resourceRaw, &resource) err = json.Unmarshal(resourceRaw, &resource)
assert.NilError(t, err) assert.NilError(t, err)
// context // context
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, resourceRaw) err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -396,7 +396,7 @@ func Test_ReplacingPathWhenDeleting(t *testing.T) {
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
ctx := context.NewContextFromRaw(resourceRaw) ctx := context.NewContextFromRaw(jp, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
pattern, err = SubstituteAll(logr.Discard(), ctx, pattern) pattern, err = SubstituteAll(logr.Discard(), ctx, pattern)
@ -431,7 +431,7 @@ func Test_ReplacingNestedVariableWhenDeleting(t *testing.T) {
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
ctx := context.NewContextFromRaw(resourceRaw) ctx := context.NewContextFromRaw(jp, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
pattern, err = SubstituteAll(logr.Discard(), ctx, pattern) pattern, err = SubstituteAll(logr.Discard(), ctx, pattern)
@ -457,7 +457,7 @@ var resourceRaw = []byte(`
`) `)
func Test_SubstituteSuccess(t *testing.T) { func Test_SubstituteSuccess(t *testing.T) {
ctx := context.NewContext() ctx := context.NewContext(jp)
assert.Assert(t, context.AddResource(ctx, resourceRaw)) assert.Assert(t, context.AddResource(ctx, resourceRaw))
var pattern interface{} var pattern interface{}
@ -481,7 +481,7 @@ func Test_SubstituteSuccess(t *testing.T) {
} }
func Test_SubstituteRecursiveErrors(t *testing.T) { func Test_SubstituteRecursiveErrors(t *testing.T) {
ctx := context.NewContext() ctx := context.NewContext(jp)
assert.Assert(t, context.AddResource(ctx, resourceRaw)) assert.Assert(t, context.AddResource(ctx, resourceRaw))
var pattern interface{} var pattern interface{}
@ -515,7 +515,7 @@ func Test_SubstituteRecursiveErrors(t *testing.T) {
} }
func Test_SubstituteRecursive(t *testing.T) { func Test_SubstituteRecursive(t *testing.T) {
ctx := context.NewContext() ctx := context.NewContext(jp)
assert.Assert(t, context.AddResource(ctx, resourceRaw)) assert.Assert(t, context.AddResource(ctx, resourceRaw))
var pattern interface{} var pattern interface{}
@ -633,7 +633,7 @@ func Test_variableSubstitution_array(t *testing.T) {
err := json.Unmarshal(ruleRaw, &rule) err := json.Unmarshal(ruleRaw, &rule)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContextFromRaw(configmapRaw) ctx := context.NewContextFromRaw(jp, configmapRaw)
context.AddResource(ctx, resourceRaw) context.AddResource(ctx, resourceRaw)
vars, err := SubstituteAllInRule(logr.Discard(), ctx, rule) vars, err := SubstituteAllInRule(logr.Discard(), ctx, rule)
@ -679,7 +679,7 @@ func Test_SubstituteNull(t *testing.T) {
err = json.Unmarshal(variableObject, &resource) err = json.Unmarshal(variableObject, &resource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() ctx := context.NewContext(jp)
context.AddResource(ctx, variableObject) context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(logr.Discard(), ctx, pattern) resolved, err := SubstituteAll(logr.Discard(), ctx, pattern)
@ -708,7 +708,7 @@ func Test_SubstituteNullInString(t *testing.T) {
err = json.Unmarshal(variableObject, &resource) err = json.Unmarshal(variableObject, &resource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() ctx := context.NewContext(jp)
context.AddResource(ctx, variableObject) context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(logr.Discard(), ctx, pattern) resolved, err := SubstituteAll(logr.Discard(), ctx, pattern)
@ -737,7 +737,7 @@ func Test_SubstituteArray(t *testing.T) {
err = json.Unmarshal(variableObject, &resource) err = json.Unmarshal(variableObject, &resource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() ctx := context.NewContext(jp)
context.AddResource(ctx, variableObject) context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(logr.Discard(), ctx, pattern) resolved, err := SubstituteAll(logr.Discard(), ctx, pattern)
@ -766,7 +766,7 @@ func Test_SubstituteArrayInString(t *testing.T) {
err = json.Unmarshal(variableObject, &resource) err = json.Unmarshal(variableObject, &resource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() ctx := context.NewContext(jp)
context.AddResource(ctx, variableObject) context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(logr.Discard(), ctx, pattern) resolved, err := SubstituteAll(logr.Discard(), ctx, pattern)
@ -795,7 +795,7 @@ func Test_SubstituteInt(t *testing.T) {
err = json.Unmarshal(variableObject, &resource) err = json.Unmarshal(variableObject, &resource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() ctx := context.NewContext(jp)
context.AddResource(ctx, variableObject) context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(logr.Discard(), ctx, pattern) resolved, err := SubstituteAll(logr.Discard(), ctx, pattern)
@ -824,7 +824,7 @@ func Test_SubstituteIntInString(t *testing.T) {
err = json.Unmarshal(variableObject, &resource) err = json.Unmarshal(variableObject, &resource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() ctx := context.NewContext(jp)
context.AddResource(ctx, variableObject) context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(logr.Discard(), ctx, pattern) resolved, err := SubstituteAll(logr.Discard(), ctx, pattern)
@ -853,7 +853,7 @@ func Test_SubstituteBool(t *testing.T) {
err = json.Unmarshal(variableObject, &resource) err = json.Unmarshal(variableObject, &resource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() ctx := context.NewContext(jp)
context.AddResource(ctx, variableObject) context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(logr.Discard(), ctx, pattern) resolved, err := SubstituteAll(logr.Discard(), ctx, pattern)
@ -882,7 +882,7 @@ func Test_SubstituteBoolInString(t *testing.T) {
err = json.Unmarshal(variableObject, &resource) err = json.Unmarshal(variableObject, &resource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() ctx := context.NewContext(jp)
context.AddResource(ctx, variableObject) context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(logr.Discard(), ctx, pattern) resolved, err := SubstituteAll(logr.Discard(), ctx, pattern)
@ -911,7 +911,7 @@ func Test_SubstituteString(t *testing.T) {
err = json.Unmarshal(variableObject, &resource) err = json.Unmarshal(variableObject, &resource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() ctx := context.NewContext(jp)
context.AddResource(ctx, variableObject) context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(logr.Discard(), ctx, pattern) resolved, err := SubstituteAll(logr.Discard(), ctx, pattern)
@ -940,7 +940,7 @@ func Test_SubstituteStringInString(t *testing.T) {
err = json.Unmarshal(variableObject, &resource) err = json.Unmarshal(variableObject, &resource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() ctx := context.NewContext(jp)
context.AddResource(ctx, variableObject) context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(logr.Discard(), ctx, pattern) resolved, err := SubstituteAll(logr.Discard(), ctx, pattern)
@ -991,7 +991,7 @@ func Test_ReferenceSubstitution(t *testing.T) {
err = json.Unmarshal(expectedJSON, &expectedDocument) err = json.Unmarshal(expectedJSON, &expectedDocument)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, jsonRaw) err = context.AddResource(ctx, jsonRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -1135,7 +1135,7 @@ func Test_EscpReferenceSubstitution(t *testing.T) {
err = json.Unmarshal(expectedJSON, &expectedDocument) err = json.Unmarshal(expectedJSON, &expectedDocument)
assert.NilError(t, err) assert.NilError(t, err)
ctx := context.NewContext() ctx := context.NewContext(jp)
err = context.AddResource(ctx, jsonRaw) err = context.AddResource(ctx, jsonRaw)
assert.NilError(t, err) assert.NilError(t, err)
@ -1171,7 +1171,7 @@ func Test_ReplacingEscpNestedVariableWhenDeleting(t *testing.T) {
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
ctx := context.NewContextFromRaw(resourceRaw) ctx := context.NewContextFromRaw(jp, resourceRaw)
assert.NilError(t, err) assert.NilError(t, err)
pattern, err = SubstituteAll(logr.Discard(), ctx, pattern) pattern, err = SubstituteAll(logr.Discard(), ctx, pattern)

View file

@ -14,7 +14,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
func (pc *PolicyController) handleGenerate(policyKey string, policy kyvernov1.PolicyInterface) error { func (pc *policyController) handleGenerate(policyKey string, policy kyvernov1.PolicyInterface) error {
logger := pc.log.WithName("handleGenerate").WithName(policyKey) logger := pc.log.WithName("handleGenerate").WithName(policyKey)
logger.Info("update URs on policy event") logger.Info("update URs on policy event")
@ -41,7 +41,7 @@ func (pc *PolicyController) handleGenerate(policyKey string, policy kyvernov1.Po
return nil return nil
} }
func (pc *PolicyController) handleGenerateForExisting(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule) error { func (pc *policyController) handleGenerateForExisting(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule) error {
var errors []error var errors []error
ruleType := kyvernov1beta1.Generate ruleType := kyvernov1beta1.Generate
triggers := generateTriggers(pc.client, rule, pc.log) triggers := generateTriggers(pc.client, rule, pc.log)
@ -65,7 +65,7 @@ func (pc *PolicyController) handleGenerateForExisting(policy kyvernov1.PolicyInt
return multierr.Combine(errors...) return multierr.Combine(errors...)
} }
func (pc *PolicyController) createURForDownstreamDeletion(policy kyvernov1.PolicyInterface) error { func (pc *policyController) createURForDownstreamDeletion(policy kyvernov1.PolicyInterface) error {
var errs []error var errs []error
rules := autogen.ComputeRules(policy) rules := autogen.ComputeRules(policy)
for _, r := range rules { for _, r := range rules {
@ -79,7 +79,7 @@ func (pc *PolicyController) createURForDownstreamDeletion(policy kyvernov1.Polic
return multierr.Combine(errs...) return multierr.Combine(errs...)
} }
func (pc *PolicyController) createURForDataRule(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule, deleteDownstream bool) (bool, error) { func (pc *policyController) createURForDataRule(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule, deleteDownstream bool) (bool, error) {
downstreamExist := false downstreamExist := false
generate := rule.Generation generate := rule.Generation
if !generate.Synchronize { if !generate.Synchronize {

View file

@ -10,7 +10,7 @@ import (
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
) )
func (pc *PolicyController) handleMutate(policyKey string, policy kyvernov1.PolicyInterface) error { func (pc *policyController) handleMutate(policyKey string, policy kyvernov1.PolicyInterface) error {
logger := pc.log.WithName("handleMutate").WithName(policyKey) logger := pc.log.WithName("handleMutate").WithName(policyKey)
if !policy.GetSpec().MutateExistingOnPolicyUpdate { if !policy.GetSpec().MutateExistingOnPolicyUpdate {
logger.V(4).Info("skip policy application on policy event", "policyKey", policyKey, "mutateExiting", policy.GetSpec().MutateExistingOnPolicyUpdate) logger.V(4).Info("skip policy application on policy event", "policyKey", policyKey, "mutateExiting", policy.GetSpec().MutateExistingOnPolicyUpdate)
@ -49,7 +49,7 @@ func (pc *PolicyController) handleMutate(policyKey string, policy kyvernov1.Poli
return nil return nil
} }
func (pc *PolicyController) listMutateURs(policyKey string, trigger *unstructured.Unstructured) []*kyvernov1beta1.UpdateRequest { func (pc *policyController) listMutateURs(policyKey string, trigger *unstructured.Unstructured) []*kyvernov1beta1.UpdateRequest {
mutateURs, err := pc.urLister.List(labels.SelectorFromSet(backgroundcommon.MutateLabelsSet(policyKey, trigger))) mutateURs, err := pc.urLister.List(labels.SelectorFromSet(backgroundcommon.MutateLabelsSet(policyKey, trigger)))
if err != nil { if err != nil {
pc.log.Error(err, "failed to list update request for mutate policy") pc.log.Error(err, "failed to list update request for mutate policy")

View file

@ -18,6 +18,7 @@ import (
"github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/clients/dclient"
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/metrics" "github.com/kyverno/kyverno/pkg/metrics"
datautils "github.com/kyverno/kyverno/pkg/utils/data" datautils "github.com/kyverno/kyverno/pkg/utils/data"
@ -47,9 +48,9 @@ const (
maxRetries = 15 maxRetries = 15
) )
// PolicyController is responsible for synchronizing Policy objects stored // policyController is responsible for synchronizing Policy objects stored
// in the system with the corresponding policy violations // in the system with the corresponding policy violations
type PolicyController struct { type policyController struct {
client dclient.Interface client dclient.Interface
kyvernoClient versioned.Interface kyvernoClient versioned.Interface
engine engineapi.Engine engine engineapi.Engine
@ -78,13 +79,15 @@ type PolicyController struct {
informersSynced []cache.InformerSynced informersSynced []cache.InformerSynced
// helpers to validate against current loaded configuration // helpers to validate against current loaded configuration
configHandler config.Configuration configuration config.Configuration
reconcilePeriod time.Duration reconcilePeriod time.Duration
log logr.Logger log logr.Logger
metricsConfig metrics.MetricsConfigManager metricsConfig metrics.MetricsConfigManager
jp jmespath.Interface
} }
// NewPolicyController create a new PolicyController // NewPolicyController create a new PolicyController
@ -95,20 +98,21 @@ func NewPolicyController(
pInformer kyvernov1informers.ClusterPolicyInformer, pInformer kyvernov1informers.ClusterPolicyInformer,
npInformer kyvernov1informers.PolicyInformer, npInformer kyvernov1informers.PolicyInformer,
urInformer kyvernov1beta1informers.UpdateRequestInformer, urInformer kyvernov1beta1informers.UpdateRequestInformer,
configHandler config.Configuration, configuration config.Configuration,
eventGen event.Interface, eventGen event.Interface,
namespaces corev1informers.NamespaceInformer, namespaces corev1informers.NamespaceInformer,
log logr.Logger, log logr.Logger,
reconcilePeriod time.Duration, reconcilePeriod time.Duration,
metricsConfig metrics.MetricsConfigManager, metricsConfig metrics.MetricsConfigManager,
) (*PolicyController, error) { jp jmespath.Interface,
) (*policyController, error) {
// Event broad caster // Event broad caster
eventBroadcaster := record.NewBroadcaster() eventBroadcaster := record.NewBroadcaster()
eventBroadcaster.StartLogging(log.V(5).Info) eventBroadcaster.StartLogging(log.V(5).Info)
eventInterface := client.GetEventsInterface() eventInterface := client.GetEventsInterface()
eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: eventInterface}) eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: eventInterface})
pc := PolicyController{ pc := policyController{
client: client, client: client,
kyvernoClient: kyvernoClient, kyvernoClient: kyvernoClient,
engine: engine, engine: engine,
@ -117,10 +121,11 @@ func NewPolicyController(
eventGen: eventGen, eventGen: eventGen,
eventRecorder: eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: "policy_controller"}), eventRecorder: eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: "policy_controller"}),
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "policy"), queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "policy"),
configHandler: configHandler, configuration: configuration,
reconcilePeriod: reconcilePeriod, reconcilePeriod: reconcilePeriod,
metricsConfig: metricsConfig, metricsConfig: metricsConfig,
log: log, log: log,
jp: jp,
} }
pc.pLister = pInformer.Lister() pc.pLister = pInformer.Lister()
@ -133,7 +138,7 @@ func NewPolicyController(
return &pc, nil return &pc, nil
} }
func (pc *PolicyController) canBackgroundProcess(p kyvernov1.PolicyInterface) bool { func (pc *policyController) canBackgroundProcess(p kyvernov1.PolicyInterface) bool {
logger := pc.log.WithValues("policy", p.GetName()) logger := pc.log.WithValues("policy", p.GetName())
if !p.BackgroundProcessingEnabled() { if !p.BackgroundProcessingEnabled() {
if !p.GetSpec().HasGenerate() && !p.GetSpec().IsMutateExisting() { if !p.GetSpec().HasGenerate() && !p.GetSpec().IsMutateExisting() {
@ -150,7 +155,7 @@ func (pc *PolicyController) canBackgroundProcess(p kyvernov1.PolicyInterface) bo
return true return true
} }
func (pc *PolicyController) addPolicy(obj interface{}) { func (pc *policyController) addPolicy(obj interface{}) {
logger := pc.log logger := pc.log
var p kyvernov1.PolicyInterface var p kyvernov1.PolicyInterface
@ -173,7 +178,7 @@ func (pc *PolicyController) addPolicy(obj interface{}) {
pc.enqueuePolicy(p) pc.enqueuePolicy(p)
} }
func (pc *PolicyController) updatePolicy(old, cur interface{}) { func (pc *policyController) updatePolicy(old, cur interface{}) {
logger := pc.log logger := pc.log
var oldP, curP kyvernov1.PolicyInterface var oldP, curP kyvernov1.PolicyInterface
@ -214,7 +219,7 @@ func (pc *PolicyController) updatePolicy(old, cur interface{}) {
pc.enqueuePolicy(curP) pc.enqueuePolicy(curP)
} }
func (pc *PolicyController) deletePolicy(obj interface{}) { func (pc *policyController) deletePolicy(obj interface{}) {
logger := pc.log logger := pc.log
var p kyvernov1.PolicyInterface var p kyvernov1.PolicyInterface
@ -235,7 +240,7 @@ func (pc *PolicyController) deletePolicy(obj interface{}) {
} }
} }
func (pc *PolicyController) enqueuePolicy(policy kyvernov1.PolicyInterface) { func (pc *policyController) enqueuePolicy(policy kyvernov1.PolicyInterface) {
logger := pc.log logger := pc.log
key, err := cache.MetaNamespaceKeyFunc(policy) key, err := cache.MetaNamespaceKeyFunc(policy)
if err != nil { if err != nil {
@ -246,7 +251,7 @@ func (pc *PolicyController) enqueuePolicy(policy kyvernov1.PolicyInterface) {
} }
// Run begins watching and syncing. // Run begins watching and syncing.
func (pc *PolicyController) Run(ctx context.Context, workers int) { func (pc *policyController) Run(ctx context.Context, workers int) {
logger := pc.log logger := pc.log
defer utilruntime.HandleCrash() defer utilruntime.HandleCrash()
@ -282,12 +287,12 @@ func (pc *PolicyController) Run(ctx context.Context, workers int) {
// worker runs a worker thread that just dequeues items, processes them, and marks them done. // worker runs a worker thread that just dequeues items, processes them, and marks them done.
// It enforces that the syncHandler is never invoked concurrently with the same key. // It enforces that the syncHandler is never invoked concurrently with the same key.
func (pc *PolicyController) worker(ctx context.Context) { func (pc *policyController) worker(ctx context.Context) {
for pc.processNextWorkItem() { for pc.processNextWorkItem() {
} }
} }
func (pc *PolicyController) processNextWorkItem() bool { func (pc *policyController) processNextWorkItem() bool {
key, quit := pc.queue.Get() key, quit := pc.queue.Get()
if quit { if quit {
return false return false
@ -299,7 +304,7 @@ func (pc *PolicyController) processNextWorkItem() bool {
return true return true
} }
func (pc *PolicyController) handleErr(err error, key interface{}) { func (pc *policyController) handleErr(err error, key interface{}) {
logger := pc.log logger := pc.log
if err == nil { if err == nil {
pc.queue.Forget(key) pc.queue.Forget(key)
@ -317,7 +322,7 @@ func (pc *PolicyController) handleErr(err error, key interface{}) {
pc.queue.Forget(key) pc.queue.Forget(key)
} }
func (pc *PolicyController) syncPolicy(key string) error { func (pc *policyController) syncPolicy(key string) error {
logger := pc.log.WithName("syncPolicy") logger := pc.log.WithName("syncPolicy")
startTime := time.Now() startTime := time.Now()
logger.V(4).Info("started syncing policy", "key", key, "startTime", startTime) logger.V(4).Info("started syncing policy", "key", key, "startTime", startTime)
@ -345,7 +350,7 @@ func (pc *PolicyController) syncPolicy(key string) error {
return nil return nil
} }
func (pc *PolicyController) getPolicy(key string) (kyvernov1.PolicyInterface, error) { func (pc *policyController) getPolicy(key string) (kyvernov1.PolicyInterface, error) {
if ns, name, err := cache.SplitMetaNamespaceKey(key); err != nil { if ns, name, err := cache.SplitMetaNamespaceKey(key); err != nil {
pc.log.Error(err, "failed to parse policy name", "policyName", key) pc.log.Error(err, "failed to parse policy name", "policyName", key)
return nil, err return nil, err
@ -359,7 +364,7 @@ func (pc *PolicyController) getPolicy(key string) (kyvernov1.PolicyInterface, er
} }
// forceReconciliation forces a background scan by adding all policies to the workqueue // forceReconciliation forces a background scan by adding all policies to the workqueue
func (pc *PolicyController) forceReconciliation(ctx context.Context) { func (pc *policyController) forceReconciliation(ctx context.Context) {
logger := pc.log.WithName("forceReconciliation") logger := pc.log.WithName("forceReconciliation")
ticker := time.NewTicker(pc.reconcilePeriod) ticker := time.NewTicker(pc.reconcilePeriod)
@ -375,7 +380,7 @@ func (pc *PolicyController) forceReconciliation(ctx context.Context) {
} }
} }
func (pc *PolicyController) requeuePolicies() { func (pc *policyController) requeuePolicies() {
logger := pc.log.WithName("requeuePolicies") logger := pc.log.WithName("requeuePolicies")
if cpols, err := pc.pLister.List(labels.Everything()); err == nil { if cpols, err := pc.pLister.List(labels.Everything()); err == nil {
for _, cpol := range cpols { for _, cpol := range cpols {
@ -399,9 +404,9 @@ func (pc *PolicyController) requeuePolicies() {
} }
} }
func (pc *PolicyController) handleUpdateRequest(ur *kyvernov1beta1.UpdateRequest, triggerResource *unstructured.Unstructured, rule kyvernov1.Rule, policy kyvernov1.PolicyInterface) (skip bool, err error) { func (pc *policyController) handleUpdateRequest(ur *kyvernov1beta1.UpdateRequest, triggerResource *unstructured.Unstructured, rule kyvernov1.Rule, policy kyvernov1.PolicyInterface) (skip bool, err error) {
namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(triggerResource.GetKind(), triggerResource.GetNamespace(), pc.nsLister, pc.log) namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(triggerResource.GetKind(), triggerResource.GetNamespace(), pc.nsLister, pc.log)
policyContext, err := backgroundcommon.NewBackgroundContext(pc.client, ur, policy, triggerResource, pc.configHandler, namespaceLabels, pc.log) policyContext, err := backgroundcommon.NewBackgroundContext(pc.log, pc.client, ur, policy, triggerResource, pc.configuration, pc.jp, namespaceLabels)
if err != nil { if err != nil {
return false, fmt.Errorf("failed to build policy context for rule %s: %w", rule.Name, err) return false, fmt.Errorf("failed to build policy context for rule %s: %w", rule.Name, err)
} }

View file

@ -51,7 +51,16 @@ func (i *imageExtractor) ExtractFromResource(resource interface{}, cfg config.Co
return imageInfo, nil return imageInfo, nil
} }
func extract(obj interface{}, path []string, keyPath, valuePath string, fields []string, jmesPath string, imageInfos *map[string]ImageInfo, cfg config.Configuration) error { func extract(
obj interface{},
path []string,
keyPath string,
valuePath string,
fields []string,
jmesPath string,
imageInfos *map[string]ImageInfo,
cfg config.Configuration,
) error {
if obj == nil { if obj == nil {
return nil return nil
} }
@ -94,11 +103,13 @@ func extract(obj interface{}, path []string, keyPath, valuePath string, fields [
return nil return nil
} }
if jmesPath != "" { if jmesPath != "" {
jp, err := jmespath.New(jmesPath) // TODO: should be injected
jp := jmespath.New(cfg)
q, err := jp.Query(jmesPath)
if err != nil { if err != nil {
return fmt.Errorf("invalid jmespath %s: %v", jmesPath, err) return fmt.Errorf("invalid jmespath %s: %v", jmesPath, err)
} }
result, err := jp.Search(value) result, err := q.Search(value)
if err != nil { if err != nil {
return fmt.Errorf("failed to apply jmespath %s: %v", jmesPath, err) return fmt.Errorf("failed to apply jmespath %s: %v", jmesPath, err)
} }
@ -171,12 +182,10 @@ func lookupImageExtractor(kind string, configs kyvernov1.ImageExtractorConfigs)
func ExtractImagesFromResource(resource unstructured.Unstructured, configs kyvernov1.ImageExtractorConfigs, cfg config.Configuration) (map[string]map[string]ImageInfo, error) { func ExtractImagesFromResource(resource unstructured.Unstructured, configs kyvernov1.ImageExtractorConfigs, cfg config.Configuration) (map[string]map[string]ImageInfo, error) {
infos := map[string]map[string]ImageInfo{} infos := map[string]map[string]ImageInfo{}
extractors := lookupImageExtractor(resource.GetKind(), configs) extractors := lookupImageExtractor(resource.GetKind(), configs)
if extractors != nil && len(extractors) == 0 { if extractors != nil && len(extractors) == 0 {
return nil, fmt.Errorf("no extractors found for %s", resource.GetKind()) return nil, fmt.Errorf("no extractors found for %s", resource.GetKind())
} }
for _, extractor := range extractors { for _, extractor := range extractors {
if infoMap, err := extractor.ExtractFromResource(resource.Object, cfg); err != nil { if infoMap, err := extractor.ExtractFromResource(resource.Object, cfg); err != nil {
return nil, err return nil, err
@ -184,6 +193,5 @@ func ExtractImagesFromResource(resource unstructured.Unstructured, configs kyver
infos[extractor.Name] = infoMap infos[extractor.Name] = infoMap
} }
} }
return infos, nil return infos, nil
} }

View file

@ -10,6 +10,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine" "github.com/kyverno/kyverno/pkg/engine"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/context/resolvers" "github.com/kyverno/kyverno/pkg/engine/context/resolvers"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/metrics" "github.com/kyverno/kyverno/pkg/metrics"
"github.com/kyverno/kyverno/pkg/openapi" "github.com/kyverno/kyverno/pkg/openapi"
@ -39,6 +40,7 @@ func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhook
urLister := kyvernoInformers.Kyverno().V1beta1().UpdateRequests().Lister().UpdateRequests(config.KyvernoNamespace()) urLister := kyvernoInformers.Kyverno().V1beta1().UpdateRequests().Lister().UpdateRequests(config.KyvernoNamespace())
peLister := kyvernoInformers.Kyverno().V2alpha1().PolicyExceptions().Lister() peLister := kyvernoInformers.Kyverno().V2alpha1().PolicyExceptions().Lister()
rclient := registryclient.NewOrDie() rclient := registryclient.NewOrDie()
jp := jmespath.New(configuration)
return &resourceHandlers{ return &resourceHandlers{
client: dclient, client: dclient,
@ -51,10 +53,11 @@ func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhook
urGenerator: updaterequest.NewFake(), urGenerator: updaterequest.NewFake(),
eventGen: event.NewFake(), eventGen: event.NewFake(),
openApiManager: openapi.NewFake(), openApiManager: openapi.NewFake(),
pcBuilder: webhookutils.NewPolicyContextBuilder(configuration), pcBuilder: webhookutils.NewPolicyContextBuilder(configuration, jp),
engine: engine.NewEngine( engine: engine.NewEngine(
configuration, configuration,
config.NewDefaultMetricsConfiguration(), config.NewDefaultMetricsConfiguration(),
jp,
dclient, dclient,
rclient, rclient,
engineapi.DefaultContextLoaderFactory(configMapResolver), engineapi.DefaultContextLoaderFactory(configMapResolver),

View file

@ -14,6 +14,7 @@ import (
"github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/clients/dclient"
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/metrics" "github.com/kyverno/kyverno/pkg/metrics"
"github.com/kyverno/kyverno/pkg/openapi" "github.com/kyverno/kyverno/pkg/openapi"
@ -31,7 +32,6 @@ import (
webhookutils "github.com/kyverno/kyverno/pkg/webhooks/utils" webhookutils "github.com/kyverno/kyverno/pkg/webhooks/utils"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
corev1listers "k8s.io/client-go/listers/core/v1" corev1listers "k8s.io/client-go/listers/core/v1"
rbacv1listers "k8s.io/client-go/listers/rbac/v1"
) )
type resourceHandlers struct { type resourceHandlers struct {
@ -72,8 +72,6 @@ func NewHandlers(
metricsConfig metrics.MetricsConfigManager, metricsConfig metrics.MetricsConfigManager,
pCache policycache.Cache, pCache policycache.Cache,
nsLister corev1listers.NamespaceLister, nsLister corev1listers.NamespaceLister,
rbLister rbacv1listers.RoleBindingLister,
crbLister rbacv1listers.ClusterRoleBindingLister,
urLister kyvernov1beta1listers.UpdateRequestNamespaceLister, urLister kyvernov1beta1listers.UpdateRequestNamespaceLister,
cpolInformer kyvernov1informers.ClusterPolicyInformer, cpolInformer kyvernov1informers.ClusterPolicyInformer,
polInformer kyvernov1informers.PolicyInformer, polInformer kyvernov1informers.PolicyInformer,
@ -82,6 +80,7 @@ func NewHandlers(
openApiManager openapi.ValidateInterface, openApiManager openapi.ValidateInterface,
admissionReports bool, admissionReports bool,
backgroungServiceAccountName string, backgroungServiceAccountName string,
jp jmespath.Interface,
) webhooks.ResourceHandlers { ) webhooks.ResourceHandlers {
return &resourceHandlers{ return &resourceHandlers{
engine: engine, engine: engine,
@ -98,7 +97,7 @@ func NewHandlers(
urGenerator: urGenerator, urGenerator: urGenerator,
eventGen: eventGen, eventGen: eventGen,
openApiManager: openApiManager, openApiManager: openApiManager,
pcBuilder: webhookutils.NewPolicyContextBuilder(configuration), pcBuilder: webhookutils.NewPolicyContextBuilder(configuration, jp),
admissionReports: admissionReports, admissionReports: admissionReports,
backgroungServiceAccountName: backgroungServiceAccountName, backgroungServiceAccountName: backgroungServiceAccountName,
} }

View file

@ -10,6 +10,7 @@ import (
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine" "github.com/kyverno/kyverno/pkg/engine"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
log "github.com/kyverno/kyverno/pkg/logging" log "github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/registryclient"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
@ -1048,10 +1049,12 @@ func TestValidate_failure_action_overrides(t *testing.T) {
}, },
}, },
} }
cfg := config.NewDefaultConfiguration(false)
jp := jmespath.New(cfg)
eng := engine.NewEngine( eng := engine.NewEngine(
config.NewDefaultConfiguration(false), cfg,
config.NewDefaultMetricsConfiguration(), config.NewDefaultMetricsConfiguration(),
jp,
nil, nil,
registryclient.NewOrDie(), registryclient.NewOrDie(),
engineapi.DefaultContextLoaderFactory(nil), engineapi.DefaultContextLoaderFactory(nil),
@ -1065,7 +1068,7 @@ func TestValidate_failure_action_overrides(t *testing.T) {
resourceUnstructured, err := kubeutils.BytesToUnstructured(tc.rawResource) resourceUnstructured, err := kubeutils.BytesToUnstructured(tc.rawResource)
assert.NilError(t, err) assert.NilError(t, err)
ctx := engine.NewPolicyContext(kyvernov1.Create).WithPolicy(&policy).WithNewResource(*resourceUnstructured).WithNamespaceLabels(tc.rawResourceNamespaceLabels) ctx := engine.NewPolicyContext(jp, kyvernov1.Create).WithPolicy(&policy).WithNewResource(*resourceUnstructured).WithNamespaceLabels(tc.rawResourceNamespaceLabels)
er := eng.Validate( er := eng.Validate(
context.TODO(), context.TODO(),
ctx, ctx,
@ -1127,11 +1130,14 @@ func Test_RuleSelector(t *testing.T) {
assert.NilError(t, err) assert.NilError(t, err)
assert.Assert(t, resourceUnstructured != nil) assert.Assert(t, resourceUnstructured != nil)
ctx := engine.NewPolicyContext(kyvernov1.Create).WithPolicy(&policy).WithNewResource(*resourceUnstructured) cfg := config.NewDefaultConfiguration(false)
jp := jmespath.New(cfg)
ctx := engine.NewPolicyContext(jp, kyvernov1.Create).WithPolicy(&policy).WithNewResource(*resourceUnstructured)
eng := engine.NewEngine( eng := engine.NewEngine(
config.NewDefaultConfiguration(false), cfg,
config.NewDefaultMetricsConfiguration(), config.NewDefaultMetricsConfiguration(),
jp,
nil, nil,
registryclient.NewOrDie(), registryclient.NewOrDie(),
engineapi.DefaultContextLoaderFactory(nil), engineapi.DefaultContextLoaderFactory(nil),

View file

@ -4,6 +4,7 @@ import (
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1" kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine" "github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
admissionv1 "k8s.io/api/admission/v1" admissionv1 "k8s.io/api/admission/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
) )
@ -14,13 +15,16 @@ type PolicyContextBuilder interface {
type policyContextBuilder struct { type policyContextBuilder struct {
configuration config.Configuration configuration config.Configuration
jp jmespath.Interface
} }
func NewPolicyContextBuilder( func NewPolicyContextBuilder(
configuration config.Configuration, configuration config.Configuration,
jp jmespath.Interface,
) PolicyContextBuilder { ) PolicyContextBuilder {
return &policyContextBuilder{ return &policyContextBuilder{
configuration: configuration, configuration: configuration,
jp: jp,
} }
} }
@ -30,5 +34,5 @@ func (b *policyContextBuilder) Build(request admissionv1.AdmissionRequest, roles
Roles: roles, Roles: roles,
ClusterRoles: clusterRoles, ClusterRoles: clusterRoles,
} }
return engine.NewPolicyContextFromAdmissionRequest(request, userRequestInfo, gvk, b.configuration) return engine.NewPolicyContextFromAdmissionRequest(b.jp, request, userRequestInfo, gvk, b.configuration)
} }