Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove deps from engine to api #272

Merged
merged 2 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions pkg/binding/binding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package binding

import (
"github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/kyverno/kyverno-json/pkg/apis/v1alpha1"
"github.com/kyverno/kyverno-json/pkg/engine/assert"
"k8s.io/apimachinery/pkg/util/validation/field"
)

func NewContextBindings(bindings binding.Bindings, value any, entries ...v1alpha1.ContextEntry) binding.Bindings {
var path *field.Path
path = path.Child("context")
for i, entry := range entries {
bindings = bindings.Register("$"+entry.Name, assert.NewContextBinding(path.Index(i), bindings, value, entry.Variable.Value))
}
return bindings
}
6 changes: 1 addition & 5 deletions pkg/engine/assert/assert.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ import (
"k8s.io/apimachinery/pkg/util/validation/field"
)

func Assert(ctx context.Context, assertion Assertion, value any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
return assert(ctx, nil, assertion, value, bindings, opts...)
}

func assert(ctx context.Context, path *field.Path, assertion Assertion, value any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
func Assert(ctx context.Context, path *field.Path, assertion Assertion, value any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
return assertion.assert(ctx, path, value, bindings, opts...)
}
20 changes: 5 additions & 15 deletions pkg/engine/assert/binding.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,28 @@ import (
"context"

"github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/kyverno/kyverno-json/pkg/apis/v1alpha1"
"github.com/kyverno/kyverno-json/pkg/engine/template"
"k8s.io/apimachinery/pkg/util/validation/field"
)

func NewContextBindings(bindings binding.Bindings, value any, entries ...v1alpha1.ContextEntry) binding.Bindings {
var path *field.Path
path = path.Child("context")
for i, entry := range entries {
bindings = bindings.Register("$"+entry.Name, NewContextBinding(path.Index(i), bindings, value, entry))
}
return bindings
}

func NewContextBinding(path *field.Path, bindings binding.Bindings, value any, entry v1alpha1.ContextEntry) binding.Binding {
func NewContextBinding(path *field.Path, bindings binding.Bindings, value any, entry any) binding.Binding {
return template.NewLazyBinding(
func() (any, error) {
expression := parseExpression(context.TODO(), entry.Variable.Value)
expression := parseExpression(context.TODO(), entry)
if expression != nil && expression.engine != "" {
if expression.foreach {
return nil, field.Invalid(path.Child("variable"), entry.Variable.Value, "foreach is not supported in context")
return nil, field.Invalid(path.Child("variable"), entry, "foreach is not supported in context")
}
if expression.binding != "" {
return nil, field.Invalid(path.Child("variable"), entry.Variable.Value, "binding is not supported in context")
return nil, field.Invalid(path.Child("variable"), entry, "binding is not supported in context")
}
projected, err := template.Execute(context.Background(), expression.statement, value, bindings)
if err != nil {
return nil, field.InternalError(path.Child("variable"), err)
}
return projected, nil
}
return entry.Variable.Value, nil
return entry, nil
},
)
}
11 changes: 6 additions & 5 deletions pkg/json-engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import (

jpbinding "github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/kyverno/kyverno-json/pkg/apis/v1alpha1"
"github.com/kyverno/kyverno-json/pkg/binding"
"github.com/kyverno/kyverno-json/pkg/engine"
"github.com/kyverno/kyverno-json/pkg/engine/assert"
"github.com/kyverno/kyverno-json/pkg/engine/blocks/loop"
"github.com/kyverno/kyverno-json/pkg/engine/builder"
"github.com/kyverno/kyverno-json/pkg/engine/template"
"github.com/kyverno/kyverno-json/pkg/matching"
"go.uber.org/multierr"
)

Expand Down Expand Up @@ -59,7 +60,7 @@ func New() engine.Engine[Request, RuleResponse] {
bindings = bindings.Register("$policy", jpbinding.NewBinding(policy))
for _, rule := range policy.Spec.Rules {
bindings = bindings.Register("$rule", jpbinding.NewBinding(rule))
bindings = assert.NewContextBindings(bindings, resource, rule.Context...)
bindings = binding.NewContextBindings(bindings, resource, rule.Context...)
requests = append(requests, request{
policy: policy,
rule: rule,
Expand All @@ -73,23 +74,23 @@ func New() engine.Engine[Request, RuleResponse] {
}
inner := builder.
Function(func(ctx context.Context, r request) RuleResponse {
errs, err := assert.MatchAssert(ctx, nil, r.rule.Assert, r.value, r.bindings)
errs, err := matching.MatchAssert(ctx, nil, r.rule.Assert, r.value, r.bindings)
response := buildResponse(r, errs, err)
return response
}).
Predicate(func(ctx context.Context, r request) bool {
if r.rule.Exclude == nil {
return true
}
errs, err := assert.Match(ctx, nil, r.rule.Exclude, r.value, r.bindings)
errs, err := matching.Match(ctx, nil, r.rule.Exclude, r.value, r.bindings)
// TODO: handle error and skip
return err == nil && len(errs) != 0
}).
Predicate(func(ctx context.Context, r request) bool {
if r.rule.Match == nil {
return true
}
errs, err := assert.Match(ctx, nil, r.rule.Match, r.value, r.bindings)
errs, err := matching.Match(ctx, nil, r.rule.Match, r.value, r.bindings)
// TODO: handle error and skip
return err == nil && len(errs) == 0
})
Expand Down
15 changes: 6 additions & 9 deletions pkg/engine/assert/match.go → pkg/matching/match.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
package assert
package matching

import (
"context"
"errors"

"github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/kyverno/kyverno-json/pkg/apis/v1alpha1"
"github.com/kyverno/kyverno-json/pkg/engine/assert"
"github.com/kyverno/kyverno-json/pkg/engine/template"
"k8s.io/apimachinery/pkg/util/validation/field"
)

// TODO: this is the only file we reference the apis package.
// We should remove this dependency.
// Either move the Match struct in this package or move this file in a more specific package.

func MatchAssert(ctx context.Context, path *field.Path, match *v1alpha1.Assert, actual any, bindings binding.Bindings, opts ...template.Option) ([]error, error) {
if match == nil || (len(match.Any) == 0 && len(match.All) == 0) {
return nil, field.Invalid(path, match, "an empty assert is not valid")
Expand All @@ -22,7 +19,7 @@ func MatchAssert(ctx context.Context, path *field.Path, match *v1alpha1.Assert,
var fails []error
path := path.Child("any")
for i, assertion := range match.Any {
checkFails, err := assert(ctx, path.Index(i).Child("check"), Parse(ctx, assertion.Check.Value), actual, bindings, opts...)
checkFails, err := assert.Assert(ctx, path.Index(i).Child("check"), assert.Parse(ctx, assertion.Check.Value), actual, bindings, opts...)
if err != nil {
return fails, err
}
Expand All @@ -46,7 +43,7 @@ func MatchAssert(ctx context.Context, path *field.Path, match *v1alpha1.Assert,
var fails []error
path := path.Child("all")
for i, assertion := range match.All {
checkFails, err := assert(ctx, path.Index(i).Child("check"), Parse(ctx, assertion.Check.Value), actual, bindings, opts...)
checkFails, err := assert.Assert(ctx, path.Index(i).Child("check"), assert.Parse(ctx, assertion.Check.Value), actual, bindings, opts...)
if err != nil {
return fails, err
}
Expand Down Expand Up @@ -92,7 +89,7 @@ func Match(ctx context.Context, path *field.Path, match *v1alpha1.Match, actual
func MatchAny(ctx context.Context, path *field.Path, assertions []v1alpha1.Any, actual any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
var errs field.ErrorList
for i, assertion := range assertions {
_errs, err := assert(ctx, path.Index(i), Parse(ctx, assertion.Value), actual, bindings, opts...)
_errs, err := assert.Assert(ctx, path.Index(i), assert.Parse(ctx, assertion.Value), actual, bindings, opts...)
if err != nil {
return errs, err
}
Expand All @@ -107,7 +104,7 @@ func MatchAny(ctx context.Context, path *field.Path, assertions []v1alpha1.Any,
func MatchAll(ctx context.Context, path *field.Path, assertions []v1alpha1.Any, actual any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
var errs field.ErrorList
for i, assertion := range assertions {
_errs, err := assert(ctx, path.Index(i), Parse(ctx, assertion.Value), actual, bindings, opts...)
_errs, err := assert.Assert(ctx, path.Index(i), assert.Parse(ctx, assertion.Value), actual, bindings, opts...)
if err != nil {
return errs, err
}
Expand Down