Skip to content

Commit

Permalink
feat: add core/compilers packages (#506)
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 authored Sep 20, 2024
1 parent 183fe67 commit fc7ad29
Show file tree
Hide file tree
Showing 22 changed files with 146 additions and 116 deletions.
4 changes: 2 additions & 2 deletions pkg/commands/jp/query/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ func loadInput(cmd *cobra.Command, file string) (any, error) {
}

func evaluate(input any, query string) (any, error) {
compiler := templating.NewCompiler(templating.CompilerOptions{})
result, err := templating.ExecuteJP(query, input, nil, compiler)
compiler := templating.DefaultCompiler
result, err := templating.Execute(query, input, nil, compiler.Jp)
if err != nil {
if syntaxError, ok := err.(parsing.SyntaxError); ok {
return nil, fmt.Errorf("%s\n%s", syntaxError, syntaxError.HighlightLocation())
Expand Down
4 changes: 2 additions & 2 deletions pkg/commands/scan/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ func (c *options) run(cmd *cobra.Command, _ []string) error {
return errors.New("payload is `null`")
}
out.println("Pre processing ...")
compiler := templating.NewCompiler(templating.CompilerOptions{})
compiler := templating.DefaultCompiler
for _, preprocessor := range c.preprocessors {
result, err := templating.ExecuteJP(preprocessor, payload, nil, compiler)
result, err := templating.Execute(preprocessor, payload, nil, compiler.Jp)
if err != nil {
return err
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/core/assertion/assertion.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"sync"

"github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/kyverno/kyverno-json/pkg/core/compilers"
"github.com/kyverno/kyverno-json/pkg/core/expression"
"github.com/kyverno/kyverno-json/pkg/core/matching"
"github.com/kyverno/kyverno-json/pkg/core/projection"
Expand Down Expand Up @@ -174,8 +175,8 @@ func parseScalar(assertion any, compiler templating.Compiler) (node, error) {
}
switch expr.Engine {
case expression.EngineJP:
parse := sync.OnceValues(func() (templating.Program, error) {
return compiler.CompileJP(expr.Statement)
parse := sync.OnceValues(func() (compilers.Program, error) {
return compiler.Jp.Compile(expr.Statement)
})
project = func(value any, bindings binding.Bindings) (any, error) {
program, err := parse()
Expand All @@ -186,7 +187,7 @@ func parseScalar(assertion any, compiler templating.Compiler) (node, error) {
}
case expression.EngineCEL:
project = func(value any, bindings binding.Bindings) (any, error) {
program, err := compiler.CompileCEL(expr.Statement)
program, err := compiler.Cel.Compile(expr.Statement)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/core/assertion/assertion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func TestAssert(t *testing.T) {
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
compiler := templating.NewCompiler(templating.CompilerOptions{})
compiler := templating.DefaultCompiler
parsed, err := Parse(tt.assertion, compiler)
tassert.NoError(t, err)
got, err := parsed.Assert(nil, tt.value, tt.bindings)
Expand Down
47 changes: 47 additions & 0 deletions pkg/core/compilers/cel/cel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package cel

import (
"github.com/google/cel-go/cel"
"github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/kyverno/kyverno-json/pkg/core/compilers"
)

type Compiler interface {
Compile(string) (compilers.Program, error)
}

type compiler struct{}

func NewCompiler() *compiler {
return &compiler{}
}

func (c *compiler) Compile(statement string) (compilers.Program, error) {
env, err := DefaultEnv()
if err != nil {
return nil, err
}
ast, iss := env.Compile(statement)
if iss.Err() != nil {
return nil, iss.Err()
}
program, err := env.Program(ast)
if err != nil {
return nil, err
}
return func(value any, bindings binding.Bindings) (any, error) {
return Execute(program, value, bindings)
}, nil
}

func Execute(program cel.Program, value any, bindings binding.Bindings) (any, error) {
data := map[string]interface{}{
"object": value,
"bindings": NewVal(bindings, BindingsType),
}
out, _, err := program.Eval(data)
if err != nil {
return nil, err
}
return out.Value(), nil
}
File renamed without changes.
File renamed without changes.
5 changes: 5 additions & 0 deletions pkg/core/compilers/compiler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package compilers

type Compiler interface {
Compile(string) (Program, error)
}
53 changes: 53 additions & 0 deletions pkg/core/compilers/jp/jp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package jp

import (
"sync"

"github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/jmespath-community/go-jmespath/pkg/interpreter"
"github.com/jmespath-community/go-jmespath/pkg/parsing"
"github.com/kyverno/kyverno-json/pkg/core/compilers"
)

type Compiler interface {
Compile(string) (compilers.Program, error)
Options() []Option
}

type compiler struct {
options []Option
buildOptions func() options
}

func NewCompiler(opts ...Option) *compiler {
return &compiler{
options: opts,
buildOptions: sync.OnceValue(func() options {
return buildOptions(opts...)
}),
}
}

func (c *compiler) Options() []Option {
return c.options
}

func (c *compiler) Compile(statement string) (compilers.Program, error) {
parser := parsing.NewParser()
compiled, err := parser.Parse(statement)
if err != nil {
return nil, err
}
return func(value any, bindings binding.Bindings) (any, error) {
return execute(compiled, value, bindings, c.buildOptions())
}, nil
}

func Execute(ast parsing.ASTNode, value any, bindings binding.Bindings, opts ...Option) (any, error) {
return execute(ast, value, bindings, buildOptions(opts...))
}

func execute(ast parsing.ASTNode, value any, bindings binding.Bindings, options options) (any, error) {
vm := interpreter.NewInterpreter(nil, bindings)
return vm.Execute(ast, value, interpreter.WithFunctionCaller(options.functionCaller))
}
File renamed without changes.
7 changes: 7 additions & 0 deletions pkg/core/compilers/program.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package compilers

import (
"github.com/jmespath-community/go-jmespath/pkg/binding"
)

type Program func(any, binding.Bindings) (any, error)
2 changes: 1 addition & 1 deletion pkg/core/message/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

"github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/jmespath-community/go-jmespath/pkg/parsing"
"github.com/kyverno/kyverno-json/pkg/core/templating/jp"
"github.com/kyverno/kyverno-json/pkg/core/compilers/jp"
)

var variable = regexp.MustCompile(`{{(.*?)}}`)
Expand Down
7 changes: 4 additions & 3 deletions pkg/core/projection/projection.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"sync"

"github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/kyverno/kyverno-json/pkg/core/compilers"
"github.com/kyverno/kyverno-json/pkg/core/expression"
"github.com/kyverno/kyverno-json/pkg/core/templating"
reflectutils "github.com/kyverno/kyverno-json/pkg/utils/reflect"
Expand Down Expand Up @@ -36,8 +37,8 @@ func Parse(in any, compiler templating.Compiler) (projection Projection) {
// 3. compute the projection func
switch expr.Engine {
case expression.EngineJP:
parse := sync.OnceValues(func() (templating.Program, error) {
return compiler.CompileJP(expr.Statement)
parse := sync.OnceValues(func() (compilers.Program, error) {
return compiler.Jp.Compile(expr.Statement)
})
projection.Handler = func(value any, bindings binding.Bindings) (any, bool, error) {
program, err := parse()
Expand All @@ -52,7 +53,7 @@ func Parse(in any, compiler templating.Compiler) (projection Projection) {
}
case expression.EngineCEL:
projection.Handler = func(value any, bindings binding.Bindings) (any, bool, error) {
program, err := compiler.CompileCEL(expr.Statement)
program, err := compiler.Cel.Compile(expr.Statement)
if err != nil {
return nil, false, err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/core/projection/projection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func TestProjection(t *testing.T) {
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
compiler := templating.NewCompiler(templating.CompilerOptions{})
compiler := templating.DefaultCompiler
proj := Parse(tt.key, compiler)
got, found, err := proj.Handler(tt.value, tt.bindings)
if tt.wantErr {
Expand Down
18 changes: 0 additions & 18 deletions pkg/core/templating/cel/cel.go

This file was deleted.

64 changes: 9 additions & 55 deletions pkg/core/templating/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,66 +4,20 @@ import (
"sync"

"github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/jmespath-community/go-jmespath/pkg/interpreter"
"github.com/jmespath-community/go-jmespath/pkg/parsing"
"github.com/kyverno/kyverno-json/pkg/core/compilers/cel"
"github.com/kyverno/kyverno-json/pkg/core/compilers/jp"
"github.com/kyverno/kyverno-json/pkg/core/expression"
"github.com/kyverno/kyverno-json/pkg/core/templating/cel"
"github.com/kyverno/kyverno-json/pkg/core/templating/jp"
"k8s.io/apimachinery/pkg/util/validation/field"
)

type CelOptions struct {
FunctionCaller interpreter.FunctionCaller
}

type CompilerOptions struct {
Cel CelOptions
Jp []jp.Option
var DefaultCompiler = Compiler{
Jp: jp.NewCompiler(),
Cel: cel.NewCompiler(),
}

type Compiler struct {
options CompilerOptions
}

func NewCompiler(options CompilerOptions) Compiler {
return Compiler{
options: options,
}
}

type Program func(any, binding.Bindings) (any, error)

func (c Compiler) Options() CompilerOptions {
return c.options
}

func (c Compiler) CompileCEL(statement string) (Program, error) {
env, err := cel.DefaultEnv()
if err != nil {
return nil, err
}
ast, iss := env.Compile(statement)
if iss.Err() != nil {
return nil, iss.Err()
}
program, err := env.Program(ast)
if err != nil {
return nil, err
}
return func(value any, bindings binding.Bindings) (any, error) {
return cel.Execute(program, value, bindings)
}, nil
}

func (c Compiler) CompileJP(statement string) (Program, error) {
parser := parsing.NewParser()
compiled, err := parser.Parse(statement)
if err != nil {
return nil, err
}
return func(value any, bindings binding.Bindings) (any, error) {
return jp.Execute(compiled, value, bindings, c.options.Jp...)
}, nil
Jp jp.Compiler
Cel cel.Compiler
}

func (c Compiler) NewBinding(path *field.Path, value any, bindings binding.Bindings, template any) binding.Binding {
Expand All @@ -81,13 +35,13 @@ func (c Compiler) NewBinding(path *field.Path, value any, bindings binding.Bindi
}
switch expr.Engine {
case expression.EngineJP:
projected, err := ExecuteJP(expr.Statement, value, bindings, c)
projected, err := Execute(expr.Statement, value, bindings, c.Jp)
if err != nil {
return nil, field.InternalError(path.Child("variable"), err)
}
return projected, nil
case expression.EngineCEL:
projected, err := ExecuteCEL(expr.Statement, value, bindings, c)
projected, err := Execute(expr.Statement, value, bindings, c.Cel)
if err != nil {
return nil, field.InternalError(path.Child("variable"), err)
}
Expand Down
13 changes: 0 additions & 13 deletions pkg/core/templating/jp/jp.go

This file was deleted.

13 changes: 3 additions & 10 deletions pkg/core/templating/templating.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,11 @@ package templating

import (
"github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/kyverno/kyverno-json/pkg/core/compilers"
)

func ExecuteJP(statement string, value any, bindings binding.Bindings, compiler Compiler) (any, error) {
program, err := compiler.CompileJP(statement)
if err != nil {
return nil, err
}
return program(value, bindings)
}

func ExecuteCEL(statement string, value any, bindings binding.Bindings, compiler Compiler) (any, error) {
program, err := compiler.CompileCEL(statement)
func Execute(statement string, value any, bindings binding.Bindings, compiler compilers.Compiler) (any, error) {
program, err := compiler.Compile(statement)
if err != nil {
return nil, err
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/json-engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func New() engine.Engine[Request, Response] {
bindings jpbinding.Bindings
}
compiler := matching.Compiler{
Compiler: templating.NewCompiler(templating.CompilerOptions{}),
Compiler: templating.DefaultCompiler,
}
ruleEngine := builder.
Function(func(ctx context.Context, r ruleRequest) []RuleResponse {
Expand All @@ -80,7 +80,7 @@ func New() engine.Engine[Request, Response] {
}
identifier := ""
if r.rule.Identifier != "" {
result, err := templating.ExecuteJP(r.rule.Identifier, r.resource, bindings, compiler.Compiler)
result, err := templating.Execute(r.rule.Identifier, r.resource, bindings, compiler.Compiler.Jp)
if err != nil {
identifier = fmt.Sprintf("(error: %s)", err)
} else {
Expand Down Expand Up @@ -119,7 +119,7 @@ func New() engine.Engine[Request, Response] {
}
var feedback map[string]Feedback
for _, f := range r.rule.Feedback {
result, err := templating.ExecuteJP(f.Value, r.resource, bindings, compiler.Compiler)
result, err := templating.Execute(f.Value, r.resource, bindings, compiler.Compiler.Jp)
if feedback == nil {
feedback = map[string]Feedback{}
}
Expand Down
Loading

0 comments on commit fc7ad29

Please sign in to comment.