From ae6243b431b7d68b27c02e06bd85c10dc664892a Mon Sep 17 00:00:00 2001 From: cici37 Date: Mon, 4 Jul 2022 16:04:25 -0700 Subject: [PATCH] Pick up dispatcher refactor changes from cel-go --- .../pkg/apiserver/schema/cel/compilation.go | 14 +- .../cel/library/library_compatibility_test.go | 9 +- .../pkg/apiserver/schema/cel/library/lists.go | 152 ++++++------------ .../pkg/apiserver/schema/cel/library/regex.go | 69 +++----- .../pkg/apiserver/schema/cel/library/urls.go | 146 ++++------------- .../forked/celopenapi/model/schemas.go | 11 +- .../forked/celopenapi/model/types.go | 43 +++-- .../forked/celopenapi/model/url.go | 2 + 8 files changed, 142 insertions(+), 304 deletions(-) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/compilation.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/compilation.go index ec4c44abbbc..7868827c345 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/compilation.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/compilation.go @@ -24,10 +24,6 @@ import ( "github.com/google/cel-go/cel" "github.com/google/cel-go/checker" - "github.com/google/cel-go/checker/decls" - expr "google.golang.org/genproto/googleapis/api/expr/v1alpha1" - "google.golang.org/protobuf/proto" - apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/pkg/apiserver/schema" "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library" @@ -104,7 +100,7 @@ func Compile(s *schema.Structural, isResourceRoot bool, perCallLimit uint64) ([] } celRules := s.Extensions.XValidations - var propDecls []*expr.Decl + var propDecls []cel.EnvOption var root *celmodel.DeclType var ok bool baseEnv, err := getBaseEnv() @@ -132,9 +128,9 @@ func Compile(s *schema.Structural, isResourceRoot bool, perCallLimit uint64) ([] } root = rootDecl.MaybeAssignTypeName(scopedTypeName) } - propDecls = append(propDecls, decls.NewVar(ScopedVarName, root.ExprType())) - propDecls = append(propDecls, decls.NewVar(OldScopedVarName, root.ExprType())) - opts = append(opts, cel.Declarations(propDecls...)) + propDecls = append(propDecls, cel.Variable(ScopedVarName, root.CelType())) + propDecls = append(propDecls, cel.Variable(OldScopedVarName, root.CelType())) + opts = append(opts, propDecls...) env, err := baseEnv.Extend(opts...) if err != nil { return nil, err @@ -161,7 +157,7 @@ func compileRule(rule apiextensions.ValidationRule, env *cel.Env, perCallLimit u compilationResult.Error = &Error{ErrorTypeInvalid, "compilation failed: " + issues.String()} return } - if !proto.Equal(ast.ResultType(), decls.Bool) { + if ast.OutputType() != cel.BoolType { compilationResult.Error = &Error{ErrorTypeInvalid, "cel expression must evaluate to a bool"} return } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/library_compatibility_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/library_compatibility_test.go index ddf9ef4e7fb..65473ff09a7 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/library_compatibility_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/library_compatibility_test.go @@ -20,13 +20,12 @@ import ( "testing" "github.com/google/cel-go/cel" - exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" ) func TestLibraryCompatibility(t *testing.T) { functionNames := map[string]struct{}{} - decls := map[cel.Library][]*exprpb.Decl{ + decls := map[cel.Library]map[string][]cel.FunctionOpt{ urlsLib: urlLibraryDecls, listsLib: listsLibraryDecls, regexLib: regexLibraryDecls, @@ -34,9 +33,9 @@ func TestLibraryCompatibility(t *testing.T) { if len(k8sExtensionLibs) != len(decls) { t.Errorf("Expected the same number of libraries in the ExtensionLibs as are tested for compatibility") } - for _, l := range decls { - for _, d := range l { - functionNames[d.GetName()] = struct{}{} + for _, decl := range decls { + for name := range decl { + functionNames[name] = struct{}{} } } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/lists.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/lists.go index 1c0f60b5b00..db29bedafb5 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/lists.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/lists.go @@ -20,12 +20,10 @@ import ( "fmt" "github.com/google/cel-go/cel" - "github.com/google/cel-go/checker/decls" "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/common/types/traits" "github.com/google/cel-go/interpreter/functions" - exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" ) // Lists provides a CEL function library extension of list utility functions. @@ -101,120 +99,64 @@ var listsLib = &lists{} type lists struct{} -var paramA = decls.NewTypeParamType("A") +var paramA = cel.TypeParamType("A") // CEL typeParams can be used to constraint to a specific trait (e.g. traits.ComparableType) if the 1st operand is the type to constrain. // But the functions we need to constrain are >, not just . -var summableTypes = map[string]*exprpb.Type{"int": decls.Int, "uint": decls.Uint, "double": decls.Double, "duration": decls.Duration} -var comparableTypes = map[string]*exprpb.Type{"bool": decls.Bool, "int": decls.Int, "uint": decls.Uint, "double": decls.Double, - "duration": decls.Duration, "timestamp": decls.Timestamp, "string": decls.String, "bytes": decls.Bytes} +var summableTypes = map[string]*cel.Type{"int": cel.IntType, "uint": cel.UintType, "double": cel.DoubleType, "duration": cel.DurationType} +var zeroValuesOfSummableTypes = map[string]ref.Val{ + "int": types.Int(0), + "uint": types.Uint(0), + "double": types.Double(0.0), + "duration": types.Duration{Duration: 0}, +} +var comparableTypes = map[string]*cel.Type{"bool": cel.BoolType, "int": cel.IntType, "uint": cel.UintType, "double": cel.DoubleType, + "duration": cel.DurationType, "timestamp": cel.TimestampType, "string": cel.StringType, "bytes": cel.BytesType} // WARNING: All library additions or modifications must follow // https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/2876-crd-validation-expression-language#function-library-updates -var listsLibraryDecls = []*exprpb.Decl{ - decls.NewFunction("isSorted", - templatedOverloads(comparableTypes, func(name string, paramType *exprpb.Type) *exprpb.Decl_FunctionDecl_Overload { - return decls.NewInstanceOverload(fmt.Sprintf("list_%s_is_sorted_bool", name), - []*exprpb.Type{decls.NewListType(paramType)}, - decls.Bool) - })..., - ), - decls.NewFunction("sum", - templatedOverloads(summableTypes, func(name string, paramType *exprpb.Type) *exprpb.Decl_FunctionDecl_Overload { - return decls.NewInstanceOverload(fmt.Sprintf("list_%s_sum_%s", name, name), - []*exprpb.Type{decls.NewListType(paramType)}, - paramType) - })..., - ), - decls.NewFunction("max", - templatedOverloads(comparableTypes, func(name string, paramType *exprpb.Type) *exprpb.Decl_FunctionDecl_Overload { - return decls.NewInstanceOverload(fmt.Sprintf("list_%s_max_%s", name, name), - []*exprpb.Type{decls.NewListType(paramType)}, - paramType) - })..., - ), - decls.NewFunction("min", - templatedOverloads(comparableTypes, func(name string, paramType *exprpb.Type) *exprpb.Decl_FunctionDecl_Overload { - return decls.NewInstanceOverload(fmt.Sprintf("list_%s_min_%s", name, name), - []*exprpb.Type{decls.NewListType(paramType)}, - paramType) - })..., - ), - decls.NewFunction("indexOf", - decls.NewInstanceOverload("list_a_index_of_int", - []*exprpb.Type{decls.NewListType(paramA), paramA}, - decls.Int), - ), - decls.NewFunction("lastIndexOf", - decls.NewInstanceOverload("list_a_last_index_of_int", - []*exprpb.Type{decls.NewListType(paramA), paramA}, - decls.Int), - ), +var listsLibraryDecls = map[string][]cel.FunctionOpt{ + "isSorted": templatedOverloads(comparableTypes, func(name string, paramType *cel.Type) cel.FunctionOpt { + return cel.MemberOverload(fmt.Sprintf("list_%s_is_sorted_bool", name), + []*cel.Type{cel.ListType(paramType)}, cel.BoolType, cel.UnaryBinding(isSorted)) + }), + "sum": templatedOverloads(summableTypes, func(name string, paramType *cel.Type) cel.FunctionOpt { + return cel.MemberOverload(fmt.Sprintf("list_%s_sum_%s", name, name), + []*cel.Type{cel.ListType(paramType)}, paramType, cel.UnaryBinding(func(list ref.Val) ref.Val { + return sum( + func() ref.Val { + return zeroValuesOfSummableTypes[name] + })(list) + })) + }), + "max": templatedOverloads(comparableTypes, func(name string, paramType *cel.Type) cel.FunctionOpt { + return cel.MemberOverload(fmt.Sprintf("list_%s_max_%s", name, name), + []*cel.Type{cel.ListType(paramType)}, paramType, cel.UnaryBinding(max())) + }), + "min": templatedOverloads(comparableTypes, func(name string, paramType *cel.Type) cel.FunctionOpt { + return cel.MemberOverload(fmt.Sprintf("list_%s_min_%s", name, name), + []*cel.Type{cel.ListType(paramType)}, paramType, cel.UnaryBinding(min())) + }), + "indexOf": { + cel.MemberOverload("list_a_index_of_int", []*cel.Type{cel.ListType(paramA), paramA}, cel.IntType, + cel.BinaryBinding(indexOf)), + }, + "lastIndexOf": { + cel.MemberOverload("list_a_last_index_of_int", []*cel.Type{cel.ListType(paramA), paramA}, cel.IntType, + cel.BinaryBinding(lastIndexOf)), + }, } func (*lists) CompileOptions() []cel.EnvOption { - return []cel.EnvOption{ - cel.Declarations(listsLibraryDecls...), + options := []cel.EnvOption{} + for name, overloads := range listsLibraryDecls { + options = append(options, cel.Function(name, overloads...)) } + return options } func (*lists) ProgramOptions() []cel.ProgramOption { - return []cel.ProgramOption{ - cel.Functions( - &functions.Overload{ - Operator: "isSorted", - Unary: isSorted, - }, - // if 'sum' is called directly, it is via dynamic dispatch, and we infer the type from the 1st element of the - // list if it has one, otherwise we return int64(0) - &functions.Overload{ - Operator: "sum", - Unary: dynSum(), - }, - // use overload names for sum so an initial accumulator value can be assigned to each - &functions.Overload{ - Operator: "list_int_sum_int", - Unary: sum(func() ref.Val { - return types.Int(0) - }), - }, - &functions.Overload{ - Operator: "list_uint_sum_uint", - Unary: sum(func() ref.Val { - return types.Uint(0) - }), - }, - &functions.Overload{ - Operator: "list_double_sum_double", - Unary: sum(func() ref.Val { - return types.Double(0.0) - }), - }, - &functions.Overload{ - Operator: "list_duration_sum_duration", - Unary: sum(func() ref.Val { - return types.Duration{Duration: 0} - }), - }, - &functions.Overload{ - Operator: "max", - Unary: max(), - }, - &functions.Overload{ - Operator: "min", - Unary: min(), - }, - // use overload names for indexOf and lastIndexOf to de-conflict with function of same name in strings extension library - &functions.Overload{ - Operator: "list_a_index_of_int", - Binary: indexOf, - }, - &functions.Overload{ - Operator: "list_a_last_index_of_int", - Binary: lastIndexOf, - }, - ), - } + return []cel.ProgramOption{} } func isSorted(val ref.Val) ref.Val { @@ -375,8 +317,8 @@ func lastIndexOf(list ref.Val, item ref.Val) ref.Val { // templatedOverloads returns overloads for each of the provided types. The template function is called with each type // name (map key) and type to construct the overloads. -func templatedOverloads(types map[string]*exprpb.Type, template func(name string, t *exprpb.Type) *exprpb.Decl_FunctionDecl_Overload) []*exprpb.Decl_FunctionDecl_Overload { - overloads := make([]*exprpb.Decl_FunctionDecl_Overload, len(types)) +func templatedOverloads(types map[string]*cel.Type, template func(name string, t *cel.Type) cel.FunctionOpt) []cel.FunctionOpt { + overloads := make([]cel.FunctionOpt, len(types)) i := 0 for name, t := range types { overloads[i] = template(name, t) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/regex.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/regex.go index e44f82090ab..cbb4faac82a 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/regex.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/regex.go @@ -20,12 +20,9 @@ import ( "regexp" "github.com/google/cel-go/cel" - "github.com/google/cel-go/checker/decls" "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/interpreter" - "github.com/google/cel-go/interpreter/functions" - exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" ) // Regex provides a CEL function library extension of regex utility functions. @@ -55,59 +52,33 @@ var regexLib = ®ex{} type regex struct{} -var regexLibraryDecls = []*exprpb.Decl{ - - decls.NewFunction("find", - decls.NewInstanceOverload("string_find_string", - []*exprpb.Type{decls.String, decls.String}, - decls.String), - ), - decls.NewFunction("findAll", - decls.NewInstanceOverload("string_find_all_string", - []*exprpb.Type{decls.String, decls.String}, - decls.NewListType(decls.String)), - decls.NewInstanceOverload("string_find_all_string_int", - []*exprpb.Type{decls.String, decls.String, decls.Int}, - decls.NewListType(decls.String)), - ), +var regexLibraryDecls = map[string][]cel.FunctionOpt{ + "find": { + cel.MemberOverload("string_find_string", []*cel.Type{cel.StringType, cel.StringType}, cel.StringType, + cel.BinaryBinding(find))}, + "findAll": { + cel.MemberOverload("string_find_all_string", []*cel.Type{cel.StringType, cel.StringType}, + cel.ListType(cel.StringType), + cel.BinaryBinding(func(str, regex ref.Val) ref.Val { + return findAll(str, regex, types.Int(-1)) + })), + cel.MemberOverload("string_find_all_string_int", + []*cel.Type{cel.StringType, cel.StringType, cel.IntType}, + cel.ListType(cel.StringType), + cel.FunctionBinding(findAll)), + }, } func (*regex) CompileOptions() []cel.EnvOption { - return []cel.EnvOption{ - cel.Declarations(regexLibraryDecls...), + options := []cel.EnvOption{} + for name, overloads := range regexLibraryDecls { + options = append(options, cel.Function(name, overloads...)) } + return options } func (*regex) ProgramOptions() []cel.ProgramOption { - return []cel.ProgramOption{ - cel.Functions( - &functions.Overload{ - Operator: "find", - Binary: find, - }, - &functions.Overload{ - Operator: "string_find_string", - Binary: find, - }, - &functions.Overload{ - Operator: "findAll", - Binary: func(str, regex ref.Val) ref.Val { - return findAll(str, regex, types.Int(-1)) - }, - Function: findAll, - }, - &functions.Overload{ - Operator: "string_find_all_string", - Binary: func(str, regex ref.Val) ref.Val { - return findAll(str, regex, types.Int(-1)) - }, - }, - &functions.Overload{ - Operator: "string_find_all_string_int", - Function: findAll, - }, - ), - } + return []cel.ProgramOption{} } func find(strVal ref.Val, regexVal ref.Val) ref.Val { diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/urls.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/urls.go index 8e47bb45ae7..7744931422c 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/urls.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/library/urls.go @@ -20,12 +20,8 @@ import ( "net/url" "github.com/google/cel-go/cel" - "github.com/google/cel-go/checker/decls" "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" - "github.com/google/cel-go/interpreter/functions" - exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" - "k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model" ) @@ -111,124 +107,44 @@ var urlsLib = &urls{} type urls struct{} -var urlLibraryDecls = []*exprpb.Decl{ - decls.NewFunction("url", - decls.NewOverload("string_to_url", - []*exprpb.Type{decls.String}, - model.URLObject), - ), - decls.NewFunction("getScheme", - decls.NewInstanceOverload("url_get_scheme", - []*exprpb.Type{model.URLObject}, - decls.String), - ), - decls.NewFunction("getHost", - decls.NewInstanceOverload("url_get_host", - []*exprpb.Type{model.URLObject}, - decls.String), - ), - decls.NewFunction("getHostname", - decls.NewInstanceOverload("url_get_hostname", - []*exprpb.Type{model.URLObject}, - decls.String), - ), - decls.NewFunction("getPort", - decls.NewInstanceOverload("url_get_port", - []*exprpb.Type{model.URLObject}, - decls.String), - ), - decls.NewFunction("getEscapedPath", - decls.NewInstanceOverload("url_get_escaped_path", - []*exprpb.Type{model.URLObject}, - decls.String), - ), - decls.NewFunction("getQuery", - decls.NewInstanceOverload("url_get_query", - []*exprpb.Type{model.URLObject}, - decls.NewMapType(decls.String, decls.NewListType(decls.String))), - ), - decls.NewFunction("isURL", - decls.NewOverload("is_url_string", - []*exprpb.Type{decls.String}, - decls.Bool), - ), +var urlLibraryDecls = map[string][]cel.FunctionOpt{ + "url": { + cel.Overload("string_to_url", []*cel.Type{cel.StringType}, model.URLType, + cel.UnaryBinding(stringToUrl))}, + "getScheme": { + cel.MemberOverload("url_get_scheme", []*cel.Type{model.URLType}, cel.StringType, + cel.UnaryBinding(getScheme))}, + "getHost": { + cel.MemberOverload("url_get_host", []*cel.Type{model.URLType}, cel.StringType, + cel.UnaryBinding(getHost))}, + "getHostname": { + cel.MemberOverload("url_get_hostname", []*cel.Type{model.URLType}, cel.StringType, + cel.UnaryBinding(getHostname))}, + "getPort": { + cel.MemberOverload("url_get_port", []*cel.Type{model.URLType}, cel.StringType, + cel.UnaryBinding(getPort))}, + "getEscapedPath": { + cel.MemberOverload("url_get_escaped_path", []*cel.Type{model.URLType}, cel.StringType, + cel.UnaryBinding(getEscapedPath))}, + "getQuery": { + cel.MemberOverload("url_get_query", []*cel.Type{model.URLType}, + cel.MapType(cel.StringType, cel.ListType(cel.StringType)), + cel.UnaryBinding(getQuery))}, + "isURL": { + cel.Overload("is_url_string", []*cel.Type{cel.StringType}, cel.BoolType, + cel.UnaryBinding(isURL))}, } func (*urls) CompileOptions() []cel.EnvOption { - return []cel.EnvOption{ - cel.Declarations(urlLibraryDecls...), + options := []cel.EnvOption{} + for name, overloads := range urlLibraryDecls { + options = append(options, cel.Function(name, overloads...)) } + return options } func (*urls) ProgramOptions() []cel.ProgramOption { - return []cel.ProgramOption{ - cel.Functions( - &functions.Overload{ - Operator: "url", - Unary: stringToUrl, - }, - &functions.Overload{ - Operator: "string_to_url", - Unary: stringToUrl, - }, - &functions.Overload{ - Operator: "getScheme", - Unary: getScheme, - }, - &functions.Overload{ - Operator: "url_get_scheme", - Unary: getScheme, - }, - &functions.Overload{ - Operator: "getHost", - Unary: getHost, - }, - &functions.Overload{ - Operator: "url_get_host", - Unary: getHost, - }, - &functions.Overload{ - Operator: "getHostname", - Unary: getHostname, - }, - &functions.Overload{ - Operator: "url_get_hostname", - Unary: getHostname, - }, - &functions.Overload{ - Operator: "getPort", - Unary: getPort, - }, - &functions.Overload{ - Operator: "url_get_port", - Unary: getPort, - }, - &functions.Overload{ - Operator: "getEscapedPath", - Unary: getEscapedPath, - }, - &functions.Overload{ - Operator: "url_get_escaped_path", - Unary: getEscapedPath, - }, - &functions.Overload{ - Operator: "getQuery", - Unary: getQuery, - }, - &functions.Overload{ - Operator: "url_get_query", - Unary: getQuery, - }, - &functions.Overload{ - Operator: "isURL", - Unary: isURL, - }, - &functions.Overload{ - Operator: "is_url_string", - Unary: isURL, - }, - ), - } + return []cel.ProgramOption{} } func stringToUrl(arg ref.Val) ref.Val { diff --git a/staging/src/k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model/schemas.go b/staging/src/k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model/schemas.go index b6a92a938e8..5eda1293c34 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model/schemas.go +++ b/staging/src/k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model/schemas.go @@ -15,6 +15,7 @@ package model import ( + "github.com/google/cel-go/cel" "time" "github.com/google/cel-go/checker/decls" @@ -72,7 +73,7 @@ func SchemaDeclType(s *schema.Structural, isResourceRoot bool) *DeclType { // To validate requirements on both the int and string representation: // `type(intOrStringField) == int ? intOrStringField < 5 : double(intOrStringField.replace('%', '')) < 0.5 // - dyn := newSimpleType("dyn", decls.Dyn, nil) + dyn := newSimpleType("dyn", decls.Dyn, cel.DynType, nil) // handle x-kubernetes-int-or-string by returning the max length of the largest possible string dyn.MaxElements = maxRequestSizeBytes - 2 return dyn @@ -149,7 +150,7 @@ func SchemaDeclType(s *schema.Structural, isResourceRoot bool) *DeclType { if s.ValueValidation != nil { switch s.ValueValidation.Format { case "byte": - byteWithMaxLength := newSimpleType("bytes", decls.Bytes, types.Bytes([]byte{})) + byteWithMaxLength := newSimpleType("bytes", decls.Bytes, cel.BytesType, types.Bytes([]byte{})) if s.ValueValidation.MaxLength != nil { byteWithMaxLength.MaxElements = zeroIfNegative(*s.ValueValidation.MaxLength) } else { @@ -157,16 +158,16 @@ func SchemaDeclType(s *schema.Structural, isResourceRoot bool) *DeclType { } return byteWithMaxLength case "duration": - durationWithMaxLength := newSimpleType("duration", decls.Duration, types.Duration{Duration: time.Duration(0)}) + durationWithMaxLength := newSimpleType("duration", decls.Duration, cel.DurationType, types.Duration{Duration: time.Duration(0)}) durationWithMaxLength.MaxElements = estimateMaxStringLengthPerRequest(s) return durationWithMaxLength case "date", "date-time": - timestampWithMaxLength := newSimpleType("timestamp", decls.Timestamp, types.Timestamp{Time: time.Time{}}) + timestampWithMaxLength := newSimpleType("timestamp", decls.Timestamp, cel.TimestampType, types.Timestamp{Time: time.Time{}}) timestampWithMaxLength.MaxElements = estimateMaxStringLengthPerRequest(s) return timestampWithMaxLength } } - strWithMaxLength := newSimpleType("string", decls.String, types.String("")) + strWithMaxLength := newSimpleType("string", decls.String, cel.StringType, types.String("")) if s.ValueValidation != nil && s.ValueValidation.MaxLength != nil { // multiply the user-provided max length by 4 in the case of an otherwise-untyped string // we do this because the OpenAPIv3 spec indicates that maxLength is specified in runes/code points, diff --git a/staging/src/k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model/types.go b/staging/src/k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model/types.go index 2f0a5b59dcd..6ef0488c11f 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model/types.go +++ b/staging/src/k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model/types.go @@ -42,6 +42,7 @@ func NewListType(elem *DeclType, maxItems int64) *DeclType { ElemType: elem, MaxElements: maxItems, exprType: decls.NewListType(elem.ExprType()), + celType: cel.ListType(elem.CelType()), defaultValue: NewListValue(), } } @@ -54,6 +55,7 @@ func NewMapType(key, elem *DeclType, maxProperties int64) *DeclType { ElemType: elem, MaxElements: maxProperties, exprType: decls.NewMapType(key.ExprType(), elem.ExprType()), + celType: cel.MapType(key.CelType(), elem.CelType()), defaultValue: NewMapValue(), } } @@ -64,6 +66,7 @@ func NewObjectType(name string, fields map[string]*DeclField) *DeclType { name: name, Fields: fields, exprType: decls.NewObjectType(name), + celType: cel.ObjectType(name), traitMask: traits.FieldTesterType | traits.IndexerType, } t.defaultValue = NewObjectValue(t) @@ -75,6 +78,7 @@ func NewObjectTypeRef(name string) *DeclType { t := &DeclType{ name: name, exprType: decls.NewObjectType(name), + celType: cel.ObjectType(name), traitMask: traits.FieldTesterType | traits.IndexerType, } return t @@ -89,13 +93,15 @@ func NewTypeParam(name string) *DeclType { name: name, TypeParam: true, exprType: decls.NewTypeParamType(name), + celType: cel.TypeParamType(name), } } -func newSimpleType(name string, exprType *exprpb.Type, zeroVal ref.Val) *DeclType { +func newSimpleType(name string, exprType *exprpb.Type, celType *cel.Type, zeroVal ref.Val) *DeclType { return &DeclType{ name: name, exprType: exprType, + celType: celType, defaultValue: zeroVal, } } @@ -113,6 +119,7 @@ type DeclType struct { MaxElements int64 exprType *exprpb.Type + celType *cel.Type traitMask int defaultValue ref.Val } @@ -158,6 +165,7 @@ func (t *DeclType) MaybeAssignTypeName(name string) *DeclType { TypeParam: t.TypeParam, Metadata: t.Metadata, exprType: decls.NewObjectType(name), + celType: cel.ObjectType(name), traitMask: t.traitMask, defaultValue: t.defaultValue, } @@ -186,6 +194,11 @@ func (t *DeclType) ExprType() *exprpb.Type { return t.exprType } +// CelType returns the CEL type of this declaration. +func (t *DeclType) CelType() *cel.Type { + return t.celType +} + // FindField returns the DeclField with the given name if present. func (t *DeclType) FindField(name string) (*DeclField, bool) { f, found := t.Fields[name] @@ -377,9 +390,7 @@ func (rt *RuleTypes) EnvOptions(tp ref.TypeProvider) ([]cel.EnvOption, error) { return []cel.EnvOption{ cel.CustomTypeProvider(rtWithTypes), cel.CustomTypeAdapter(rtWithTypes), - cel.Declarations( - decls.NewVar("rule", rt.ruleSchemaDeclTypes.root.ExprType()), - ), + cel.Variable("rule", rt.ruleSchemaDeclTypes.root.CelType()), }, nil } @@ -517,42 +528,42 @@ type schemaTypeProvider struct { var ( // AnyType is equivalent to the CEL 'protobuf.Any' type in that the value may have any of the // types supported. - AnyType = newSimpleType("any", decls.Any, nil) + AnyType = newSimpleType("any", decls.Any, cel.AnyType, nil) // BoolType is equivalent to the CEL 'bool' type. - BoolType = newSimpleType("bool", decls.Bool, types.False) + BoolType = newSimpleType("bool", decls.Bool, cel.BoolType, types.False) // BytesType is equivalent to the CEL 'bytes' type. - BytesType = newSimpleType("bytes", decls.Bytes, types.Bytes([]byte{})) + BytesType = newSimpleType("bytes", decls.Bytes, cel.BytesType, types.Bytes([]byte{})) // DoubleType is equivalent to the CEL 'double' type which is a 64-bit floating point value. - DoubleType = newSimpleType("double", decls.Double, types.Double(0)) + DoubleType = newSimpleType("double", decls.Double, cel.DoubleType, types.Double(0)) // DurationType is equivalent to the CEL 'duration' type. - DurationType = newSimpleType("duration", decls.Duration, types.Duration{Duration: time.Duration(0)}) + DurationType = newSimpleType("duration", decls.Duration, cel.DurationType, types.Duration{Duration: time.Duration(0)}) // DateType is equivalent to the CEL 'date' type. - DateType = newSimpleType("date", decls.Timestamp, types.Timestamp{Time: time.Time{}}) + DateType = newSimpleType("date", decls.Timestamp, cel.TimestampType, types.Timestamp{Time: time.Time{}}) // DynType is the equivalent of the CEL 'dyn' concept which indicates that the type will be // determined at runtime rather than compile time. - DynType = newSimpleType("dyn", decls.Dyn, nil) + DynType = newSimpleType("dyn", decls.Dyn, cel.DynType, nil) // IntType is equivalent to the CEL 'int' type which is a 64-bit signed int. - IntType = newSimpleType("int", decls.Int, types.IntZero) + IntType = newSimpleType("int", decls.Int, cel.IntType, types.IntZero) // NullType is equivalent to the CEL 'null_type'. - NullType = newSimpleType("null_type", decls.Null, types.NullValue) + NullType = newSimpleType("null_type", decls.Null, cel.NullType, types.NullValue) // StringType is equivalent to the CEL 'string' type which is expected to be a UTF-8 string. // StringType values may either be string literals or expression strings. - StringType = newSimpleType("string", decls.String, types.String("")) + StringType = newSimpleType("string", decls.String, cel.StringType, types.String("")) // TimestampType corresponds to the well-known protobuf.Timestamp type supported within CEL. - TimestampType = newSimpleType("timestamp", decls.Timestamp, types.Timestamp{Time: time.Time{}}) + TimestampType = newSimpleType("timestamp", decls.Timestamp, cel.TimestampType, types.Timestamp{Time: time.Time{}}) // UintType is equivalent to the CEL 'uint' type. - UintType = newSimpleType("uint", decls.Uint, types.Uint(0)) + UintType = newSimpleType("uint", decls.Uint, cel.UintType, types.Uint(0)) // ListType is equivalent to the CEL 'list' type. ListType = NewListType(AnyType, noMaxLength) diff --git a/staging/src/k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model/url.go b/staging/src/k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model/url.go index 34d2d0eab7c..7c46a93a8b9 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model/url.go +++ b/staging/src/k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model/url.go @@ -16,6 +16,7 @@ package model import ( "fmt" + "github.com/google/cel-go/cel" "net/url" "reflect" @@ -32,6 +33,7 @@ type URL struct { var ( URLObject = decls.NewObjectType("kubernetes.URL") typeValue = types.NewTypeValue("kubernetes.URL") + URLType = cel.ObjectType("kubernetes.URL") ) // ConvertToNative implements ref.Val.ConvertToNative.