diff --git a/go.mod b/go.mod index ccef1c542..90868c9a3 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible github.com/Masterminds/squirrel v1.1.1-0.20191017225151-12f2162c8d8d - github.com/PaesslerAG/gval v1.0.1 + github.com/PaesslerAG/gval v1.1.0 github.com/PaesslerAG/jsonpath v0.1.1 // indirect github.com/SentimensRG/ctx v0.0.0-20180729130232-0bfd988c655d github.com/crusttech/go-oidc v0.0.0-20180918092017-982855dad3e1 diff --git a/go.sum b/go.sum index 903520dbd..5f83116e6 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,8 @@ github.com/Masterminds/squirrel v1.1.1-0.20191017225151-12f2162c8d8d/go.mod h1:y github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PaesslerAG/gval v0.1.1/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I= github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I= -github.com/PaesslerAG/gval v1.0.1 h1:QnCvok0w0Y3uZNxmNmC6GZ0cuBl+jH0tu/rBMT8pso4= -github.com/PaesslerAG/gval v1.0.1/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I= +github.com/PaesslerAG/gval v1.1.0 h1:k3RuxeZDO3eejD4cMPSt+74tUSvTnbGvLx0df4mdwFc= +github.com/PaesslerAG/gval v1.1.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I= github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk= github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY= diff --git a/vendor/github.com/PaesslerAG/gval/.travis.yml b/vendor/github.com/PaesslerAG/gval/.travis.yml index 681fe4668..cd654a469 100644 --- a/vendor/github.com/PaesslerAG/gval/.travis.yml +++ b/vendor/github.com/PaesslerAG/gval/.travis.yml @@ -6,7 +6,7 @@ before_install: script: - go test -bench=. -benchmem -timeout 10m -coverprofile coverage.out -- $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN +- $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken=$COVERALLS_TOKEN - go test -bench=Random -benchtime 5m -timeout 30m -benchmem -coverprofile coverage.out go: "1.11" diff --git a/vendor/github.com/PaesslerAG/gval/evaluable.go b/vendor/github.com/PaesslerAG/gval/evaluable.go index 5238854c3..5da168ec5 100644 --- a/vendor/github.com/PaesslerAG/gval/evaluable.go +++ b/vendor/github.com/PaesslerAG/gval/evaluable.go @@ -202,7 +202,7 @@ func (*Parser) callFunc(fun function, args ...Evaluable) Evaluable { } a[i] = ai } - return fun(a...) + return fun(c, a...) } } diff --git a/vendor/github.com/PaesslerAG/gval/functions.go b/vendor/github.com/PaesslerAG/gval/functions.go index 396040f7c..4b4a3a082 100644 --- a/vendor/github.com/PaesslerAG/gval/functions.go +++ b/vendor/github.com/PaesslerAG/gval/functions.go @@ -1,55 +1,96 @@ package gval import ( + "context" "fmt" "reflect" ) -type function func(arguments ...interface{}) (interface{}, error) +type function func(ctx context.Context, arguments ...interface{}) (interface{}, error) func toFunc(f interface{}) function { if f, ok := f.(func(arguments ...interface{}) (interface{}, error)); ok { + return function(func(ctx context.Context, arguments ...interface{}) (interface{}, error) { + var v interface{} + errCh := make(chan error) + go func() { + result, err := f(arguments...) + v = result + errCh <- err + }() + + select { + case <-ctx.Done(): + return nil, ctx.Err() + case err := <-errCh: + return v, err + } + }) + } + if f, ok := f.(func(ctx context.Context, arguments ...interface{}) (interface{}, error)); ok { return function(f) } - return func(args ...interface{}) (interface{}, error) { - fun := reflect.ValueOf(f) - t := fun.Type() - in, err := createCallArguments(t, args) - if err != nil { - return nil, err - } - out := fun.Call(in) - - r := make([]interface{}, len(out)) - for i, e := range out { - r[i] = e.Interface() - } - - err = nil - errorInterface := reflect.TypeOf((*error)(nil)).Elem() - if len(r) > 0 && t.Out(len(r)-1).Implements(errorInterface) { - if r[len(r)-1] != nil { - err = r[len(r)-1].(error) + fun := reflect.ValueOf(f) + t := fun.Type() + return func(ctx context.Context, args ...interface{}) (interface{}, error) { + var v interface{} + errCh := make(chan error) + go func() { + in, err := createCallArguments(ctx, t, args) + if err != nil { + errCh <- err + return } - r = r[0 : len(r)-1] - } + out := fun.Call(in) - switch len(r) { - case 0: - return nil, err - case 1: - return r[0], err - default: - return r, err + r := make([]interface{}, len(out)) + for i, e := range out { + r[i] = e.Interface() + } + + err = nil + errorInterface := reflect.TypeOf((*error)(nil)).Elem() + if len(r) > 0 && t.Out(len(r)-1).Implements(errorInterface) { + if r[len(r)-1] != nil { + err = r[len(r)-1].(error) + } + r = r[0 : len(r)-1] + } + + switch len(r) { + case 0: + v = nil + case 1: + v = r[0] + default: + v = r + } + errCh <- err + }() + + select { + case <-ctx.Done(): + return nil, ctx.Err() + case err := <-errCh: + return v, err } } } -func createCallArguments(t reflect.Type, args []interface{}) ([]reflect.Value, error) { +func createCallArguments(ctx context.Context, t reflect.Type, args []interface{}) ([]reflect.Value, error) { variadic := t.IsVariadic() numIn := t.NumIn() + // if first argument is a context, use the given execution context + if numIn > 0 { + thisFun := reflect.ValueOf(createCallArguments) + thisT := thisFun.Type() + if t.In(0) == thisT.In(0) { + args = append([]interface{}{ctx}, args...) + } + } + if (!variadic && len(args) != numIn) || (variadic && len(args) < numIn-1) { return nil, fmt.Errorf("invalid number of parameters") } diff --git a/vendor/github.com/PaesslerAG/gval/gval.go b/vendor/github.com/PaesslerAG/gval/gval.go index ef6a5fcc2..57ed79b15 100644 --- a/vendor/github.com/PaesslerAG/gval/gval.go +++ b/vendor/github.com/PaesslerAG/gval/gval.go @@ -77,6 +77,16 @@ func JSON() Language { return ljson } +// Parentheses contains support for parentheses. +func Parentheses() Language { + return parentheses +} + +// Ident contains support for variables and functions. +func Ident() Language { + return ident +} + // Base contains equal (==) and not equal (!=), perentheses and general support for variables, constants and functions // It contains true, false, (floating point) number, string ("" or ``) and char ('') constants func Base() Language { @@ -205,6 +215,14 @@ var propositionalLogic = NewLanguage( base, ) +var parentheses = NewLanguage( + PrefixExtension('(', parseParentheses), +) + +var ident = NewLanguage( + PrefixMetaPrefix(scanner.Ident, parseIdent), +) + var base = NewLanguage( PrefixExtension(scanner.Int, parseNumber), PrefixExtension(scanner.Float, parseNumber), @@ -225,7 +243,7 @@ var base = NewLanguage( InfixOperator("==", func(a, b interface{}) (interface{}, error) { return reflect.DeepEqual(a, b), nil }), InfixOperator("!=", func(a, b interface{}) (interface{}, error) { return !reflect.DeepEqual(a, b), nil }), - PrefixExtension('(', parseParentheses), + parentheses, Precedence("??", 0), @@ -258,5 +276,5 @@ var base = NewLanguage( Precedence("**", 200), - PrefixMetaPrefix(scanner.Ident, parseIdent), + ident, ) diff --git a/vendor/modules.txt b/vendor/modules.txt index 20e6ac960..f9885d0d7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -18,7 +18,7 @@ github.com/Masterminds/sprig # github.com/Masterminds/squirrel v1.1.1-0.20191017225151-12f2162c8d8d ## explicit github.com/Masterminds/squirrel -# github.com/PaesslerAG/gval v1.0.1 +# github.com/PaesslerAG/gval v1.1.0 ## explicit github.com/PaesslerAG/gval # github.com/PaesslerAG/jsonpath v0.1.1