diff --git a/go.mod b/go.mod index 92487dbfe2..eb702a6753 100644 --- a/go.mod +++ b/go.mod @@ -339,6 +339,6 @@ replace ( github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.1 github.com/docker/cli => github.com/docker/cli v20.10.9+incompatible github.com/evanphx/json-patch/v5 => github.com/kyverno/json-patch/v5 v5.5.1-0.20210915204938-7578f4ee9c77 - github.com/jmespath/go-jmespath => github.com/kyverno/go-jmespath v0.4.1-0.20210511164400-a1d46efa2ed6 + github.com/jmespath/go-jmespath => github.com/kyverno/go-jmespath v0.4.1-0.20230204162932-3ee946b9433d github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.2 ) diff --git a/go.sum b/go.sum index 02c3584ec0..f7413849a0 100644 --- a/go.sum +++ b/go.sum @@ -924,8 +924,8 @@ github.com/kunwardeep/paralleltest v1.0.2/go.mod h1:ZPqNm1fVHPllh5LPVujzbVz1JN2G github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= -github.com/kyverno/go-jmespath v0.4.1-0.20210511164400-a1d46efa2ed6 h1:3toVuFm87/kV8FSub2JSnjSuLz3l521ON4sOpvuTNbk= -github.com/kyverno/go-jmespath v0.4.1-0.20210511164400-a1d46efa2ed6/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/kyverno/go-jmespath v0.4.1-0.20230204162932-3ee946b9433d h1:g63VNwOo6yYRY1n3mgF2ou4cjnwyonsIKqnbBM9pTRA= +github.com/kyverno/go-jmespath v0.4.1-0.20230204162932-3ee946b9433d/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/kyverno/json-patch/v5 v5.5.1-0.20210915204938-7578f4ee9c77 h1:aJGVoRShRsIq1wmRxsmrYseBK4T7LzpcOUOqhPTe2vI= github.com/kyverno/json-patch/v5 v5.5.1-0.20210915204938-7578f4ee9c77/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/ldez/gomoddirectives v0.2.1/go.mod h1:sGicqkRgBOg//JfpXwkB9Hj0X5RyJ7mlACM5B9f6Me4= diff --git a/pkg/engine/jmespath/functions.go b/pkg/engine/jmespath/functions.go index c9a2705576..c964a08b10 100644 --- a/pkg/engine/jmespath/functions.go +++ b/pkg/engine/jmespath/functions.go @@ -70,6 +70,7 @@ const ( errorPrefix = "JMESPath function '%s': " invalidArgumentTypeError = errorPrefix + "%d argument is expected of %s type" genericError = errorPrefix + "%s" + argOutOfBoundsError = errorPrefix + "%d argument is out of bounds (%d)" zeroDivisionError = errorPrefix + "Zero divisor passed" undefinedQuoError = errorPrefix + "Undefined quotient" nonIntModuloError = errorPrefix + "Non-integer argument(s) passed for modulo" diff --git a/pkg/engine/jmespath/new.go b/pkg/engine/jmespath/new.go index d60c08207d..7a19a7f41a 100644 --- a/pkg/engine/jmespath/new.go +++ b/pkg/engine/jmespath/new.go @@ -10,7 +10,7 @@ func New(query string) (*gojmespath.JMESPath, error) { return nil, err } for _, function := range GetFunctions() { - jp.Register(&function.FunctionEntry) + jp.Register(function.FunctionEntry) } return jp, nil } diff --git a/pkg/engine/jmespath/time_test.go b/pkg/engine/jmespath/time_test.go index 3e237344bf..314d7e4276 100644 --- a/pkg/engine/jmespath/time_test.go +++ b/pkg/engine/jmespath/time_test.go @@ -2,7 +2,9 @@ package jmespath import ( "fmt" + "reflect" "testing" + "time" "gotest.tools/assert" ) @@ -182,3 +184,347 @@ func Test_TimeDiff(t *testing.T) { }) } } + +func Test_getTimeArg(t *testing.T) { + mustParse := func(s string) time.Time { + t, err := time.Parse(time.RFC3339, s) + if err != nil { + panic(err) + } + return t + } + type args struct { + f string + arguments []interface{} + index int + } + tests := []struct { + name string + args args + want time.Time + wantErr bool + }{{ + args: args{ + f: "test", + arguments: []interface{}{ + "2021-01-02T15:04:05-07:00", + }, + index: 0, + }, + want: mustParse("2021-01-02T15:04:05-07:00"), + }, { + args: args{ + f: "test", + arguments: []interface{}{ + "2021-01-02T15:04:05-07:00", + }, + index: 1, + }, + wantErr: true, + }, { + args: args{ + f: "test", + arguments: []interface{}{ + 1, + }, + index: 0, + }, + wantErr: true, + }, { + args: args{ + f: "test", + arguments: []interface{}{ + "", + }, + index: 0, + }, + wantErr: true, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := getTimeArg(tt.args.f, tt.args.arguments, tt.args.index) + if (err != nil) != tt.wantErr { + t.Errorf("getTimeArg() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("getTimeArg() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_getDurationArg(t *testing.T) { + mustParse := func(s string) time.Duration { + t, err := time.ParseDuration(s) + if err != nil { + panic(err) + } + return t + } + type args struct { + f string + arguments []interface{} + index int + } + tests := []struct { + name string + args args + want time.Duration + wantErr bool + }{{ + args: args{ + f: "test", + arguments: []interface{}{ + "20s", + }, + index: 0, + }, + want: mustParse("20s"), + }, { + args: args{ + f: "test", + arguments: []interface{}{ + "20s", + }, + index: 1, + }, + wantErr: true, + }, { + args: args{ + f: "test", + arguments: []interface{}{ + 1, + }, + index: 0, + }, + wantErr: true, + }, { + args: args{ + f: "test", + arguments: []interface{}{ + "", + }, + index: 0, + }, + wantErr: true, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := getDurationArg(tt.args.f, tt.args.arguments, tt.args.index) + if (err != nil) != tt.wantErr { + t.Errorf("getDurationArg() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("getDurationArg() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_jpTimeBefore(t *testing.T) { + type args struct { + arguments []interface{} + } + tests := []struct { + name string + args args + want interface{} + wantErr bool + }{{ + args: args{ + arguments: []interface{}{ + "2021-01-02T15:04:05-07:00", + "2021-01-02T16:04:05-07:00", + }, + }, + want: true, + }, { + args: args{ + arguments: []interface{}{ + "2021-01-02T15:04:05-07:00", + "2021-01-02T15:04:05-07:00", + }, + }, + want: false, + }, { + args: args{ + arguments: []interface{}{ + "2021-01-02T16:04:05-07:00", + "2021-01-02T15:04:05-07:00", + }, + }, + want: false, + }, { + args: args{ + arguments: []interface{}{ + 1, + "2021-01-02T15:04:05-07:00", + }, + }, + wantErr: true, + }, { + args: args{ + arguments: []interface{}{ + "2021-01-02T15:04:05-07:00", + 1, + }, + }, + wantErr: true, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := jpTimeBefore(tt.args.arguments) + if (err != nil) != tt.wantErr { + t.Errorf("jpTimeBefore() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("jpTimeBefore() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_jpTimeAfter(t *testing.T) { + type args struct { + arguments []interface{} + } + tests := []struct { + name string + args args + want interface{} + wantErr bool + }{{ + args: args{ + arguments: []interface{}{ + "2021-01-02T15:04:05-07:00", + "2021-01-02T16:04:05-07:00", + }, + }, + want: false, + }, { + args: args{ + arguments: []interface{}{ + "2021-01-02T15:04:05-07:00", + "2021-01-02T15:04:05-07:00", + }, + }, + want: false, + }, { + args: args{ + arguments: []interface{}{ + "2021-01-02T16:04:05-07:00", + "2021-01-02T15:04:05-07:00", + }, + }, + want: true, + }, { + args: args{ + arguments: []interface{}{ + 1, + "2021-01-02T15:04:05-07:00", + }, + }, + wantErr: true, + }, { + args: args{ + arguments: []interface{}{ + "2021-01-02T15:04:05-07:00", + 1, + }, + }, + wantErr: true, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := jpTimeAfter(tt.args.arguments) + if (err != nil) != tt.wantErr { + t.Errorf("jpTimeAfter() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("jpTimeAfter() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_jpTimeBetween(t *testing.T) { + type args struct { + arguments []interface{} + } + tests := []struct { + name string + args args + want interface{} + wantErr bool + }{{ + args: args{ + arguments: []interface{}{ + "2021-01-02T17:04:05-07:00", + "2021-01-02T15:04:05-07:00", + "2021-01-02T18:04:05-07:00", + }, + }, + want: true, + }, { + args: args{ + arguments: []interface{}{ + "2021-01-02T15:04:05-07:00", + "2021-01-02T15:04:05-07:00", + "2021-01-02T18:04:05-07:00", + }, + }, + want: false, + }, { + args: args{ + arguments: []interface{}{ + "2021-01-02T18:04:05-07:00", + "2021-01-02T15:04:05-07:00", + "2021-01-02T18:04:05-07:00", + }, + }, + want: false, + }, { + args: args{ + arguments: []interface{}{ + 1, + "2021-01-02T15:04:05-07:00", + "2021-01-02T18:04:05-07:00", + }, + }, + wantErr: true, + }, { + args: args{ + arguments: []interface{}{ + "2021-01-02T15:04:05-07:00", + 1, + "2021-01-02T18:04:05-07:00", + }, + }, + wantErr: true, + }, { + args: args{ + arguments: []interface{}{ + "2021-01-02T15:04:05-07:00", + "2021-01-02T18:04:05-07:00", + 1, + }, + }, + wantErr: true, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := jpTimeBetween(tt.args.arguments) + if (err != nil) != tt.wantErr { + t.Errorf("jpTimeBetween() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("jpTimeBetween() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/engine/jmespath/utils.go b/pkg/engine/jmespath/utils.go index e28fad7c4a..0bc6797e73 100644 --- a/pkg/engine/jmespath/utils.go +++ b/pkg/engine/jmespath/utils.go @@ -6,6 +6,9 @@ import ( ) func validateArg(f string, arguments []interface{}, index int, expectedType reflect.Kind) (reflect.Value, error) { + if index >= len(arguments) { + return reflect.Value{}, fmt.Errorf(argOutOfBoundsError, f, index+1, len(arguments)) + } arg := reflect.ValueOf(arguments[index]) if arg.Type().Kind() != expectedType { return reflect.Value{}, fmt.Errorf(invalidArgumentTypeError, f, index+1, expectedType.String())