Skip to content

Commit

Permalink
ast
Browse files Browse the repository at this point in the history
Signed-off-by: Charles-Edouard Brétéché <[email protected]>
  • Loading branch information
eddycharly committed Sep 17, 2024
1 parent 65a70d6 commit e803423
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 20 deletions.
7 changes: 7 additions & 0 deletions pkg/engine/assert/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"context"
"reflect"
"regexp"
"sync"

"github.com/jmespath-community/go-jmespath/pkg/parsing"
reflectutils "github.com/kyverno/kyverno-json/pkg/utils/reflect"
)

Expand All @@ -21,6 +23,7 @@ type expression struct {
statement string
binding string
engine string
ast func() (parsing.ASTNode, error)
}

func parseExpressionRegex(_ context.Context, in string) *expression {
Expand Down Expand Up @@ -54,6 +57,10 @@ func parseExpressionRegex(_ context.Context, in string) *expression {
if expression.statement == "" {
return nil
}
expression.ast = sync.OnceValues(func() (parsing.ASTNode, error) {
parser := parsing.NewParser()
return parser.Parse(expression.statement)
})
return expression
}

Expand Down
29 changes: 10 additions & 19 deletions pkg/engine/assert/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

"github.com/jmespath-community/go-jmespath/pkg/binding"
jpbinding "github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/jmespath-community/go-jmespath/pkg/parsing"
"github.com/kyverno/kyverno-json/pkg/engine/match"
"github.com/kyverno/kyverno-json/pkg/engine/template"
reflectutils "github.com/kyverno/kyverno-json/pkg/utils/reflect"
Expand Down Expand Up @@ -142,11 +141,9 @@ func (n sliceNode) assert(ctx context.Context, path *field.Path, value any, bind
// scalarNode is a terminal type of assertion.
// it receives a value and compares it with an expected value.
// the expected value can be the result of an expression.
type scalarNode struct {
project func(value any, bindings binding.Bindings, opts ...template.Option) (any, error)
}
type scalarNode func(value any, bindings binding.Bindings, opts ...template.Option) (any, error)

func newScalarNode(ctx context.Context, path *field.Path, rhs any) (Assertion, error) {
func newScalarNode(ctx context.Context, path *field.Path, rhs any) (scalarNode, error) {
expression := parseExpression(ctx, rhs)
// we only project if the expression uses the engine syntax
// this is to avoid the case where the value is a map and the RHS is a string
Expand All @@ -157,28 +154,22 @@ func newScalarNode(ctx context.Context, path *field.Path, rhs any) (Assertion, e
if expression.binding != "" {
return nil, field.Invalid(path, rhs, "binding is not supported on the RHS")
}
parser := parsing.NewParser()
compiled, err := parser.Parse(expression.statement)
ast, err := expression.ast()
if err != nil {
return nil, field.InternalError(path, err)
}
return &scalarNode{
project: func(value any, bindings binding.Bindings, opts ...template.Option) (any, error) {
return template.ExecuteAST(ctx, compiled, value, bindings, opts...)
},
}, nil
} else {
return &scalarNode{
project: func(value any, bindings binding.Bindings, opts ...template.Option) (any, error) {
return rhs, nil
},
return func(value any, bindings binding.Bindings, opts ...template.Option) (any, error) {
return template.ExecuteAST(ctx, ast, value, bindings, opts...)
}, nil
}
return func(value any, bindings binding.Bindings, opts ...template.Option) (any, error) {
return rhs, nil
}, nil
}

func (n *scalarNode) assert(ctx context.Context, path *field.Path, value any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
func (n scalarNode) assert(ctx context.Context, path *field.Path, value any, bindings binding.Bindings, opts ...template.Option) (field.ErrorList, error) {
var errs field.ErrorList
if rhs, err := n.project(value, bindings, opts...); err != nil {
if rhs, err := n(value, bindings, opts...); err != nil {
return nil, field.InternalError(path, err)
} else if match, err := match.Match(ctx, rhs, value); err != nil {
return nil, field.InternalError(path, err)
Expand Down
6 changes: 5 additions & 1 deletion pkg/engine/assert/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ func project(ctx context.Context, key any, value any, bindings binding.Bindings,
expression := parseExpression(ctx, key)
if expression != nil {
if expression.engine != "" {
projected, err := template.Execute(ctx, expression.statement, value, bindings, opts...)
ast, err := expression.ast()
if err != nil {
return nil, err
}
projected, err := template.ExecuteAST(ctx, ast, value, bindings, opts...)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit e803423

Please sign in to comment.