Skip to content

Commit

Permalink
Merge branch 'main' into mkdocs
Browse files Browse the repository at this point in the history
  • Loading branch information
eddycharly authored Oct 5, 2023
2 parents b53b43c + fb2114f commit 23a2f7e
Show file tree
Hide file tree
Showing 23 changed files with 117 additions and 79 deletions.
12 changes: 7 additions & 5 deletions pkg/commands/docs/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ func Command(parent *cobra.Command) *cobra.Command {
Args: cobra.NoArgs,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, _ []string) error {
root := cmd
for {
if !root.HasParent() {
break
root := parent
if root != nil {
for {
if !root.HasParent() {
break
}
root = root.Parent()
}
root = root.Parent()
}
if err := options.validate(root); err != nil {
return err
Expand Down
3 changes: 2 additions & 1 deletion pkg/commands/jp/function/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package function

import (
"cmp"
"context"
"fmt"
"io"
"slices"
Expand Down Expand Up @@ -58,7 +59,7 @@ func functionString(f jpfunctions.FunctionEntry) string {
}

func printFunctions(out io.Writer, names ...string) {
funcs := template.GetFunctions()
funcs := template.GetFunctions(context.Background())
slices.SortFunc(funcs, func(a, b jpfunctions.FunctionEntry) int {
return cmp.Compare(functionString(a), functionString(b))
})
Expand Down
3 changes: 2 additions & 1 deletion pkg/commands/jp/query/command.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package query

import (
"context"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -146,7 +147,7 @@ func loadInput(cmd *cobra.Command, file string) (interface{}, error) {
}

func evaluate(input interface{}, query string) (interface{}, error) {
result, err := template.Execute(query, input, nil)
result, err := template.Execute(context.Background(), query, input, nil)
if err != nil {
if syntaxError, ok := err.(parsing.SyntaxError); ok {
return nil, fmt.Errorf("%s\n%s", syntaxError, syntaxError.HighlightLocation())
Expand Down
5 changes: 3 additions & 2 deletions pkg/commands/scan/options.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package scan

import (
"context"
"errors"
"fmt"

Expand Down Expand Up @@ -36,7 +37,7 @@ func (c *options) run(cmd *cobra.Command, _ []string) error {
}
fmt.Fprintln(out, "Pre processing ...")
for _, preprocessor := range c.preprocessors {
result, err := template.Execute(preprocessor, payload, nil)
result, err := template.Execute(context.Background(), preprocessor, payload, nil)
if err != nil {
return err
}
Expand All @@ -53,7 +54,7 @@ func (c *options) run(cmd *cobra.Command, _ []string) error {
}
fmt.Fprintln(out, "Running", "(", "evaluating", len(resources), pluralize.Pluralize(len(resources), "resource", "resources"), "against", len(policies), pluralize.Pluralize(len(policies), "policy", "policies"), ")", "...")
e := jsonengine.New()
responses := e.Run(jsonengine.JsonEngineRequest{
responses := e.Run(context.Background(), jsonengine.JsonEngineRequest{
Resources: resources,
Policies: policies,
})
Expand Down
18 changes: 10 additions & 8 deletions pkg/engine/assert/assert.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
package assert

import (
"context"

"github.com/jmespath-community/go-jmespath/pkg/binding"
"k8s.io/apimachinery/pkg/util/validation/field"
)

func Validate(assertion interface{}, value interface{}, bindings binding.Bindings) (field.ErrorList, error) {
return validate(nil, assertion, value, bindings)
func Validate(ctx context.Context, assertion interface{}, value interface{}, bindings binding.Bindings) (field.ErrorList, error) {
return validate(ctx, nil, assertion, value, bindings)
}

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

func validate(path *field.Path, assertion interface{}, value interface{}, bindings binding.Bindings) (field.ErrorList, error) {
return assert(path, Parse(assertion), value, bindings)
func validate(ctx context.Context, path *field.Path, assertion interface{}, value interface{}, bindings binding.Bindings) (field.ErrorList, error) {
return assert(ctx, path, Parse(ctx, assertion), value, bindings)
}

func assert(path *field.Path, assertion Assertion, value interface{}, bindings binding.Bindings) (field.ErrorList, error) {
return assertion.assert(path, value, bindings)
func assert(ctx context.Context, path *field.Path, assertion Assertion, value interface{}, bindings binding.Bindings) (field.ErrorList, error) {
return assertion.assert(ctx, path, value, bindings)
}
4 changes: 3 additions & 1 deletion pkg/engine/assert/assertion.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package assert

import (
"context"

"github.com/jmespath-community/go-jmespath/pkg/binding"
"k8s.io/apimachinery/pkg/util/validation/field"
)

type Assertion interface {
assert(*field.Path, interface{}, binding.Bindings) (field.ErrorList, error)
assert(context.Context, *field.Path, interface{}, binding.Bindings) (field.ErrorList, error)
}
6 changes: 4 additions & 2 deletions pkg/engine/assert/binding.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package assert

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"
Expand All @@ -19,15 +21,15 @@ func NewContextBindings(bindings binding.Bindings, value interface{}, entries ..
func NewContextBinding(path *field.Path, bindings binding.Bindings, value interface{}, entry v1alpha1.ContextEntry) binding.Binding {
return template.NewLazyBinding(
func() (interface{}, error) {
expression := parseExpression(entry.Variable.Value)
expression := parseExpression(context.TODO(), entry.Variable.Value)
if expression != nil && expression.engine != "" {
if expression.foreach {
return nil, field.Invalid(path.Child("variable"), entry.Variable.Value, "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")
}
projected, err := template.Execute(expression.statement, value, bindings)
projected, err := template.Execute(context.Background(), expression.statement, value, bindings)
if err != nil {
return nil, field.InternalError(path.Child("variable"), err)
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/engine/assert/expression.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package assert

import (
"context"
"reflect"
"regexp"

Expand All @@ -22,7 +23,7 @@ type expression struct {
engine string
}

func parseExpressionRegex(in string) *expression {
func parseExpressionRegex(ctx context.Context, in string) *expression {
expression := &expression{}
// 1. match foreach
if match := foreachRegex.FindStringSubmatch(in); match != nil {
Expand Down Expand Up @@ -56,9 +57,9 @@ func parseExpressionRegex(in string) *expression {
return expression
}

func parseExpression(value interface{}) *expression {
func parseExpression(ctx context.Context, value interface{}) *expression {
if reflectutils.GetKind(value) != reflect.String {
return nil
}
return parseExpressionRegex(reflect.ValueOf(value).String())
return parseExpressionRegex(ctx, reflect.ValueOf(value).String())
}
3 changes: 2 additions & 1 deletion pkg/engine/assert/expression_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package assert

import (
"context"
"reflect"
"testing"
)
Expand Down Expand Up @@ -169,7 +170,7 @@ func Test_parseExpressionRegex(t *testing.T) {
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := parseExpressionRegex(tt.in); !reflect.DeepEqual(got, tt.want) {
if got := parseExpressionRegex(context.Background(), tt.in); !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseExpressionRegex() = %v, want %v", got, tt.want)
}
})
Expand Down
16 changes: 9 additions & 7 deletions pkg/engine/assert/match.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package assert

import (
"context"

"github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/kyverno/kyverno-json/pkg/apis/v1alpha1"
"k8s.io/apimachinery/pkg/util/validation/field"
Expand All @@ -10,20 +12,20 @@ import (
// We should remove this dependency.
// Either move the Match struct in this package or move this file in a more specific package.

func Match(path *field.Path, match *v1alpha1.Match, actual interface{}, bindings binding.Bindings) (field.ErrorList, error) {
func Match(ctx context.Context, path *field.Path, match *v1alpha1.Match, actual interface{}, bindings binding.Bindings) (field.ErrorList, error) {
var errs field.ErrorList
if match == nil || (len(match.Any) == 0 && len(match.All) == 0) {
errs = append(errs, field.Invalid(path, match, "an empty match is not valid"))
} else {
if len(match.Any) != 0 {
_errs, err := MatchAny(path.Child("any"), match.Any, actual, bindings)
_errs, err := MatchAny(ctx, path.Child("any"), match.Any, actual, bindings)
if err != nil {
return errs, err
}
errs = append(errs, _errs...)
}
if len(match.All) != 0 {
_errs, err := MatchAll(path.Child("all"), match.All, actual, bindings)
_errs, err := MatchAll(ctx, path.Child("all"), match.All, actual, bindings)
if err != nil {
return errs, err
}
Expand All @@ -33,10 +35,10 @@ func Match(path *field.Path, match *v1alpha1.Match, actual interface{}, bindings
return errs, nil
}

func MatchAny(path *field.Path, assertions v1alpha1.Assertions, actual interface{}, bindings binding.Bindings) (field.ErrorList, error) {
func MatchAny(ctx context.Context, path *field.Path, assertions v1alpha1.Assertions, actual interface{}, bindings binding.Bindings) (field.ErrorList, error) {
var errs field.ErrorList
for i, assertion := range assertions {
_errs, err := validate(path.Index(i), assertion.Value, actual, bindings)
_errs, err := validate(ctx, path.Index(i), assertion.Value, actual, bindings)
if err != nil {
return errs, err
}
Expand All @@ -45,10 +47,10 @@ func MatchAny(path *field.Path, assertions v1alpha1.Assertions, actual interface
return errs, nil
}

func MatchAll(path *field.Path, assertions v1alpha1.Assertions, actual interface{}, bindings binding.Bindings) (field.ErrorList, error) {
func MatchAll(ctx context.Context, path *field.Path, assertions v1alpha1.Assertions, actual interface{}, bindings binding.Bindings) (field.ErrorList, error) {
var errs field.ErrorList
for i, assertion := range assertions {
_errs, err := validate(path.Index(i), assertion.Value, actual, bindings)
_errs, err := validate(ctx, path.Index(i), assertion.Value, actual, bindings)
if err != nil {
return errs, err
}
Expand Down
29 changes: 15 additions & 14 deletions pkg/engine/assert/parse.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package assert

import (
"context"
"fmt"
"reflect"

Expand All @@ -12,20 +13,20 @@ import (
"k8s.io/apimachinery/pkg/util/validation/field"
)

func Parse(assertion interface{}) Assertion {
func Parse(ctx context.Context, assertion interface{}) Assertion {
switch reflectutils.GetKind(assertion) {
case reflect.Slice:
node := sliceNode{}
valueOf := reflect.ValueOf(assertion)
for i := 0; i < valueOf.Len(); i++ {
node = append(node, Parse(valueOf.Index(i).Interface()))
node = append(node, Parse(ctx, valueOf.Index(i).Interface()))
}
return node
case reflect.Map:
node := mapNode{}
iter := reflect.ValueOf(assertion).MapRange()
for iter.Next() {
node[iter.Key().Interface()] = Parse(iter.Value().Interface())
node[iter.Key().Interface()] = Parse(ctx, iter.Value().Interface())
}
return node
default:
Expand All @@ -37,10 +38,10 @@ func Parse(assertion interface{}) Assertion {
// it is responsible for projecting the analysed resource and passing the result to the descendant
type mapNode map[interface{}]Assertion

func (n mapNode) assert(path *field.Path, value interface{}, bindings jpbinding.Bindings) (field.ErrorList, error) {
func (n mapNode) assert(ctx context.Context, path *field.Path, value interface{}, bindings jpbinding.Bindings) (field.ErrorList, error) {
var errs field.ErrorList
for k, v := range n {
projection, err := project(k, value, bindings)
projection, err := project(ctx, k, value, bindings)
if err != nil {
return nil, field.InternalError(path.Child(fmt.Sprint(k)), err)
} else {
Expand All @@ -56,7 +57,7 @@ func (n mapNode) assert(path *field.Path, value interface{}, bindings jpbinding.
if projection.foreachName != "" {
bindings = bindings.Register("$"+projection.foreachName, jpbinding.NewBinding(i))
}
if _errs, err := v.assert(path.Child(fmt.Sprint(k)).Index(i), valueOf.Index(i).Interface(), bindings); err != nil {
if _errs, err := v.assert(ctx, path.Child(fmt.Sprint(k)).Index(i), valueOf.Index(i).Interface(), bindings); err != nil {
return nil, err
} else {
errs = append(errs, _errs...)
Expand All @@ -70,7 +71,7 @@ func (n mapNode) assert(path *field.Path, value interface{}, bindings jpbinding.
if projection.foreachName != "" {
bindings = bindings.Register("$"+projection.foreachName, jpbinding.NewBinding(key))
}
if _errs, err := v.assert(path.Child(fmt.Sprint(k)).Key(fmt.Sprint(key)), iter.Value().Interface(), bindings); err != nil {
if _errs, err := v.assert(ctx, path.Child(fmt.Sprint(k)).Key(fmt.Sprint(key)), iter.Value().Interface(), bindings); err != nil {
return nil, err
} else {
errs = append(errs, _errs...)
Expand All @@ -80,7 +81,7 @@ func (n mapNode) assert(path *field.Path, value interface{}, bindings jpbinding.
return nil, field.TypeInvalid(path.Child(fmt.Sprint(k)), projection.result, "expected a slice or a map")
}
} else {
if _errs, err := v.assert(path.Child(fmt.Sprint(k)), projection.result, bindings); err != nil {
if _errs, err := v.assert(ctx, path.Child(fmt.Sprint(k)), projection.result, bindings); err != nil {
return nil, err
} else {
errs = append(errs, _errs...)
Expand All @@ -96,7 +97,7 @@ func (n mapNode) assert(path *field.Path, value interface{}, bindings jpbinding.
// if lengths match all descendants are evaluated with their corresponding items.
type sliceNode []Assertion

func (n sliceNode) assert(path *field.Path, value interface{}, bindings binding.Bindings) (field.ErrorList, error) {
func (n sliceNode) assert(ctx context.Context, path *field.Path, value interface{}, bindings binding.Bindings) (field.ErrorList, error) {
var errs field.ErrorList
if reflectutils.GetKind(value) != reflect.Slice {
return nil, field.TypeInvalid(path, value, "expected a slice")
Expand All @@ -106,7 +107,7 @@ func (n sliceNode) assert(path *field.Path, value interface{}, bindings binding.
errs = append(errs, field.Invalid(path, value, "lengths of slices don't match"))
} else {
for i := range n {
if _errs, err := n[i].assert(path.Index(i), valueOf.Index(i).Interface(), bindings); err != nil {
if _errs, err := n[i].assert(ctx, path.Index(i), valueOf.Index(i).Interface(), bindings); err != nil {
return nil, err
} else {
errs = append(errs, _errs...)
Expand All @@ -124,9 +125,9 @@ type scalarNode struct {
rhs interface{}
}

func (n *scalarNode) assert(path *field.Path, value interface{}, bindings binding.Bindings) (field.ErrorList, error) {
func (n *scalarNode) assert(ctx context.Context, path *field.Path, value interface{}, bindings binding.Bindings) (field.ErrorList, error) {
rhs := n.rhs
expression := parseExpression(rhs)
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
if expression != nil && expression.engine != "" {
Expand All @@ -136,14 +137,14 @@ func (n *scalarNode) assert(path *field.Path, value interface{}, bindings bindin
if expression.binding != "" {
return nil, field.Invalid(path, rhs, "binding is not supported on the RHS")
}
projected, err := template.Execute(expression.statement, value, bindings)
projected, err := template.Execute(ctx, expression.statement, value, bindings)
if err != nil {
return nil, field.InternalError(path, err)
}
rhs = projected
}
var errs field.ErrorList
if match, err := match.Match(rhs, value); err != nil {
if match, err := match.Match(ctx, rhs, value); err != nil {
return nil, field.InternalError(path, err)
} else if !match {
errs = append(errs, field.Invalid(path, value, expectValueMessage(rhs)))
Expand Down
Loading

0 comments on commit 23a2f7e

Please sign in to comment.