mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
rebase: update kubernetes to 1.28.0 in main
updating kubernetes to 1.28.0 in the main repo. Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
committed by
mergify[bot]
parent
b2fdc269c3
commit
ff3e84ad67
119
vendor/k8s.io/apiserver/pkg/cel/composited.go
generated
vendored
119
vendor/k8s.io/apiserver/pkg/cel/composited.go
generated
vendored
@ -1,119 +0,0 @@
|
||||
/*
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cel
|
||||
|
||||
import (
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
||||
)
|
||||
|
||||
var _ ref.TypeProvider = (*CompositedTypeProvider)(nil)
|
||||
var _ ref.TypeAdapter = (*CompositedTypeAdapter)(nil)
|
||||
|
||||
// CompositedTypeProvider is the provider that tries each of the underlying
|
||||
// providers in order, and returns result of the first successful attempt.
|
||||
type CompositedTypeProvider struct {
|
||||
// Providers contains the underlying type providers.
|
||||
// If Providers is empty, the CompositedTypeProvider becomes no-op provider.
|
||||
Providers []ref.TypeProvider
|
||||
}
|
||||
|
||||
// EnumValue finds out the numeric value of the given enum name.
|
||||
// The result comes from first provider that returns non-nil.
|
||||
func (c *CompositedTypeProvider) EnumValue(enumName string) ref.Val {
|
||||
for _, p := range c.Providers {
|
||||
val := p.EnumValue(enumName)
|
||||
if val != nil {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindIdent takes a qualified identifier name and returns a Value if one
|
||||
// exists. The result comes from first provider that returns non-nil.
|
||||
func (c *CompositedTypeProvider) FindIdent(identName string) (ref.Val, bool) {
|
||||
for _, p := range c.Providers {
|
||||
val, ok := p.FindIdent(identName)
|
||||
if ok {
|
||||
return val, ok
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// FindType finds the Type given a qualified type name, or return false
|
||||
// if none of the providers finds the type.
|
||||
// If any of the providers find the type, the first provider that returns true
|
||||
// will be the result.
|
||||
func (c *CompositedTypeProvider) FindType(typeName string) (*exprpb.Type, bool) {
|
||||
for _, p := range c.Providers {
|
||||
typ, ok := p.FindType(typeName)
|
||||
if ok {
|
||||
return typ, ok
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// FindFieldType returns the field type for a checked type value. Returns
|
||||
// false if none of the providers can find the type.
|
||||
// If multiple providers can find the field, the result is taken from
|
||||
// the first that does.
|
||||
func (c *CompositedTypeProvider) FindFieldType(messageType string, fieldName string) (*ref.FieldType, bool) {
|
||||
for _, p := range c.Providers {
|
||||
ft, ok := p.FindFieldType(messageType, fieldName)
|
||||
if ok {
|
||||
return ft, ok
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// NewValue creates a new type value from a qualified name and map of field
|
||||
// name to value.
|
||||
// If multiple providers can create the new type, the first that returns
|
||||
// non-nil will decide the result.
|
||||
func (c *CompositedTypeProvider) NewValue(typeName string, fields map[string]ref.Val) ref.Val {
|
||||
for _, p := range c.Providers {
|
||||
v := p.NewValue(typeName, fields)
|
||||
if v != nil {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CompositedTypeAdapter is the adapter that tries each of the underlying
|
||||
// type adapter in order until the first successfully conversion.
|
||||
type CompositedTypeAdapter struct {
|
||||
// Adapters contains underlying type adapters.
|
||||
// If Adapters is empty, the CompositedTypeAdapter becomes a no-op adapter.
|
||||
Adapters []ref.TypeAdapter
|
||||
}
|
||||
|
||||
// NativeToValue takes the value and convert it into a ref.Val
|
||||
// The result comes from the first TypeAdapter that returns non-nil.
|
||||
func (c *CompositedTypeAdapter) NativeToValue(value interface{}) ref.Val {
|
||||
for _, a := range c.Adapters {
|
||||
v := a.NativeToValue(value)
|
||||
if v != nil {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
119
vendor/k8s.io/apiserver/pkg/cel/environment/base.go
generated
vendored
Normal file
119
vendor/k8s.io/apiserver/pkg/cel/environment/base.go
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package environment
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/ext"
|
||||
"golang.org/x/sync/singleflight"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
celconfig "k8s.io/apiserver/pkg/apis/cel"
|
||||
"k8s.io/apiserver/pkg/cel/library"
|
||||
)
|
||||
|
||||
// DefaultCompatibilityVersion returns a default compatibility version for use with EnvSet
|
||||
// that guarantees compatibility with CEL features/libraries/parameters understood by
|
||||
// an n-1 version
|
||||
//
|
||||
// This default will be set to no more than n-1 the current Kubernetes major.minor version.
|
||||
//
|
||||
// Note that a default version number less than n-1 indicates a wider range of version
|
||||
// compatibility than strictly required for rollback. A wide range of compatibility is
|
||||
// desirable because it means that CEL expressions are portable across a wider range
|
||||
// of Kubernetes versions.
|
||||
func DefaultCompatibilityVersion() *version.Version {
|
||||
return version.MajorMinor(1, 27)
|
||||
}
|
||||
|
||||
var baseOpts = []VersionedOptions{
|
||||
{
|
||||
// CEL epoch was actually 1.23, but we artificially set it to 1.0 because these
|
||||
// options should always be present.
|
||||
IntroducedVersion: version.MajorMinor(1, 0),
|
||||
EnvOptions: []cel.EnvOption{
|
||||
cel.HomogeneousAggregateLiterals(),
|
||||
// Validate function declarations once during base env initialization,
|
||||
// so they don't need to be evaluated each time a CEL rule is compiled.
|
||||
// This is a relatively expensive operation.
|
||||
cel.EagerlyValidateDeclarations(true),
|
||||
cel.DefaultUTCTimeZone(true),
|
||||
|
||||
ext.Strings(ext.StringsVersion(0)),
|
||||
library.URLs(),
|
||||
library.Regex(),
|
||||
library.Lists(),
|
||||
},
|
||||
ProgramOptions: []cel.ProgramOption{
|
||||
cel.EvalOptions(cel.OptOptimize, cel.OptTrackCost),
|
||||
cel.CostLimit(celconfig.PerCallLimit),
|
||||
},
|
||||
},
|
||||
{
|
||||
IntroducedVersion: version.MajorMinor(1, 27),
|
||||
EnvOptions: []cel.EnvOption{
|
||||
library.Authz(),
|
||||
},
|
||||
},
|
||||
{
|
||||
IntroducedVersion: version.MajorMinor(1, 28),
|
||||
EnvOptions: []cel.EnvOption{
|
||||
cel.CrossTypeNumericComparisons(true),
|
||||
cel.OptionalTypes(),
|
||||
library.Quantity(),
|
||||
},
|
||||
},
|
||||
// TODO: switch to ext.Strings version 2 once format() is fixed to work with HomogeneousAggregateLiterals.
|
||||
}
|
||||
|
||||
// MustBaseEnvSet returns the common CEL base environments for Kubernetes for Version, or panics
|
||||
// if the version is nil, or does not have major and minor components.
|
||||
//
|
||||
// The returned environment contains function libraries, language settings, optimizations and
|
||||
// runtime cost limits appropriate CEL as it is used in Kubernetes.
|
||||
//
|
||||
// The returned environment contains no CEL variable definitions or custom type declarations and
|
||||
// should be extended to construct environments with the appropriate variable definitions,
|
||||
// type declarations and any other needed configuration.
|
||||
func MustBaseEnvSet(ver *version.Version) *EnvSet {
|
||||
if ver == nil {
|
||||
panic("version must be non-nil")
|
||||
}
|
||||
if len(ver.Components()) < 2 {
|
||||
panic(fmt.Sprintf("version must contain an major and minor component, but got: %s", ver.String()))
|
||||
}
|
||||
key := strconv.FormatUint(uint64(ver.Major()), 10) + "." + strconv.FormatUint(uint64(ver.Minor()), 10)
|
||||
if entry, ok := baseEnvs.Load(key); ok {
|
||||
return entry.(*EnvSet)
|
||||
}
|
||||
|
||||
entry, _, _ := baseEnvsSingleflight.Do(key, func() (interface{}, error) {
|
||||
entry := mustNewEnvSet(ver, baseOpts)
|
||||
baseEnvs.Store(key, entry)
|
||||
return entry, nil
|
||||
})
|
||||
return entry.(*EnvSet)
|
||||
}
|
||||
|
||||
var (
|
||||
baseEnvs = sync.Map{}
|
||||
baseEnvsSingleflight = &singleflight.Group{}
|
||||
)
|
274
vendor/k8s.io/apiserver/pkg/cel/environment/environment.go
generated
vendored
Normal file
274
vendor/k8s.io/apiserver/pkg/cel/environment/environment.go
generated
vendored
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package environment
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
apiservercel "k8s.io/apiserver/pkg/cel"
|
||||
)
|
||||
|
||||
// Type defines the different types of CEL environments used in Kubernetes.
|
||||
// CEL environments are used to compile and evaluate CEL expressions.
|
||||
// Environments include:
|
||||
// - Function libraries
|
||||
// - Variables
|
||||
// - Types (both core CEL types and Kubernetes types)
|
||||
// - Other CEL environment and program options
|
||||
type Type string
|
||||
|
||||
const (
|
||||
// NewExpressions is used to validate new or modified expressions in
|
||||
// requests that write expressions to API resources.
|
||||
//
|
||||
// This environment type is compatible with a specific Kubernetes
|
||||
// major/minor version. To ensure safe rollback, this environment type
|
||||
// may not include all the function libraries, variables, type declarations, and CEL
|
||||
// language settings available in the StoredExpressions environment type.
|
||||
//
|
||||
// NewExpressions must be used to validate (parse, compile, type check)
|
||||
// all new or modified CEL expressions before they are written to storage.
|
||||
NewExpressions Type = "NewExpressions"
|
||||
|
||||
// StoredExpressions is used to compile and run CEL expressions that have been
|
||||
// persisted to storage.
|
||||
//
|
||||
// This environment type is compatible with CEL expressions that have been
|
||||
// persisted to storage by all known versions of Kubernetes. This is the most
|
||||
// permissive environment available.
|
||||
//
|
||||
// StoredExpressions is appropriate for use with CEL expressions in
|
||||
// configuration files.
|
||||
StoredExpressions Type = "StoredExpressions"
|
||||
)
|
||||
|
||||
// EnvSet manages the creation and extension of CEL environments. Each EnvSet contains
|
||||
// both an NewExpressions and StoredExpressions environment. EnvSets are created
|
||||
// and extended using VersionedOptions so that the EnvSet can prepare environments according
|
||||
// to what options were introduced at which versions.
|
||||
//
|
||||
// Each EnvSet is given a compatibility version when it is created, and prepares the
|
||||
// NewExpressions environment to be compatible with that version. The EnvSet also
|
||||
// prepares StoredExpressions to be compatible with all known versions of Kubernetes.
|
||||
type EnvSet struct {
|
||||
// compatibilityVersion is the version that all configuration in
|
||||
// the NewExpressions environment is compatible with.
|
||||
compatibilityVersion *version.Version
|
||||
|
||||
// newExpressions is an environment containing only configuration
|
||||
// in this EnvSet that is enabled at this compatibilityVersion.
|
||||
newExpressions *cel.Env
|
||||
|
||||
// storedExpressions is an environment containing the latest configuration
|
||||
// in this EnvSet.
|
||||
storedExpressions *cel.Env
|
||||
}
|
||||
|
||||
func newEnvSet(compatibilityVersion *version.Version, opts []VersionedOptions) (*EnvSet, error) {
|
||||
base, err := cel.NewEnv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
baseSet := EnvSet{compatibilityVersion: compatibilityVersion, newExpressions: base, storedExpressions: base}
|
||||
return baseSet.Extend(opts...)
|
||||
}
|
||||
|
||||
func mustNewEnvSet(ver *version.Version, opts []VersionedOptions) *EnvSet {
|
||||
envSet, err := newEnvSet(ver, opts)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Default environment misconfigured: %v", err))
|
||||
}
|
||||
return envSet
|
||||
}
|
||||
|
||||
// NewExpressionsEnv returns the NewExpressions environment Type for this EnvSet.
|
||||
// See NewExpressions for details.
|
||||
func (e *EnvSet) NewExpressionsEnv() *cel.Env {
|
||||
return e.newExpressions
|
||||
}
|
||||
|
||||
// StoredExpressionsEnv returns the StoredExpressions environment Type for this EnvSet.
|
||||
// See StoredExpressions for details.
|
||||
func (e *EnvSet) StoredExpressionsEnv() *cel.Env {
|
||||
return e.storedExpressions
|
||||
}
|
||||
|
||||
// Env returns the CEL environment for the given Type.
|
||||
func (e *EnvSet) Env(envType Type) (*cel.Env, error) {
|
||||
switch envType {
|
||||
case NewExpressions:
|
||||
return e.newExpressions, nil
|
||||
case StoredExpressions:
|
||||
return e.storedExpressions, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported environment type: %v", envType)
|
||||
}
|
||||
}
|
||||
|
||||
// VersionedOptions provides a set of CEL configuration options as well as the version the
|
||||
// options were introduced and, optionally, the version the options were removed.
|
||||
type VersionedOptions struct {
|
||||
// IntroducedVersion is the version at which these options were introduced.
|
||||
// The NewExpressions environment will only include options introduced at or before the
|
||||
// compatibility version of the EnvSet.
|
||||
//
|
||||
// For example, to configure a CEL environment with an "object" variable bound to a
|
||||
// resource kind, first create a DeclType from the groupVersionKind of the resource and then
|
||||
// populate a VersionedOptions with the variable and the type:
|
||||
//
|
||||
// schema := schemaResolver.ResolveSchema(groupVersionKind)
|
||||
// objectType := apiservercel.SchemaDeclType(schema, true)
|
||||
// ...
|
||||
// VersionOptions{
|
||||
// IntroducedVersion: version.MajorMinor(1, 26),
|
||||
// DeclTypes: []*apiservercel.DeclType{ objectType },
|
||||
// EnvOptions: []cel.EnvOption{ cel.Variable("object", objectType.CelType()) },
|
||||
// },
|
||||
//
|
||||
// To create an DeclType from a CRD, use a structural schema. For example:
|
||||
//
|
||||
// schema := structuralschema.NewStructural(crdJSONProps)
|
||||
// objectType := apiservercel.SchemaDeclType(schema, true)
|
||||
//
|
||||
// Required.
|
||||
IntroducedVersion *version.Version
|
||||
// RemovedVersion is the version at which these options were removed.
|
||||
// The NewExpressions environment will not include options removed at or before the
|
||||
// compatibility version of the EnvSet.
|
||||
//
|
||||
// All option removals must be backward compatible; the removal must either be paired
|
||||
// with a compatible replacement introduced at the same version, or the removal must be non-breaking.
|
||||
// The StoredExpressions environment will not include removed options.
|
||||
//
|
||||
// A function library may be upgraded by setting the RemovedVersion of the old library
|
||||
// to the same value as the IntroducedVersion of the new library. The new library must
|
||||
// be backward compatible with the old library.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// VersionOptions{
|
||||
// IntroducedVersion: version.MajorMinor(1, 26), RemovedVersion: version.MajorMinor(1, 27),
|
||||
// EnvOptions: []cel.EnvOption{ libraries.Example(libraries.ExampleVersion(1)) },
|
||||
// },
|
||||
// VersionOptions{
|
||||
// IntroducedVersion: version.MajorMinor(1, 27),
|
||||
// EnvOptions: []EnvOptions{ libraries.Example(libraries.ExampleVersion(2)) },
|
||||
// },
|
||||
//
|
||||
// Optional.
|
||||
RemovedVersion *version.Version
|
||||
|
||||
// EnvOptions provides CEL EnvOptions. This may be used to add a cel.Variable, a
|
||||
// cel.Library, or to enable other CEL EnvOptions such as language settings.
|
||||
//
|
||||
// If an added cel.Variable has an OpenAPI type, the type must be included in DeclTypes.
|
||||
EnvOptions []cel.EnvOption
|
||||
// ProgramOptions provides CEL ProgramOptions. This may be used to set a cel.CostLimit,
|
||||
// enable optimizations, and set other program level options that should be enabled
|
||||
// for all programs using this environment.
|
||||
ProgramOptions []cel.ProgramOption
|
||||
// DeclTypes provides OpenAPI type declarations to register with the environment.
|
||||
//
|
||||
// If cel.Variables added to EnvOptions refer to a OpenAPI type, the type must be included in
|
||||
// DeclTypes.
|
||||
DeclTypes []*apiservercel.DeclType
|
||||
}
|
||||
|
||||
// Extend returns an EnvSet based on this EnvSet but extended with given VersionedOptions.
|
||||
// This EnvSet is not mutated.
|
||||
// The returned EnvSet has the same compatibility version as the EnvSet that was extended.
|
||||
//
|
||||
// Extend is an expensive operation and each call to Extend that adds DeclTypes increases
|
||||
// the depth of a chain of resolvers. For these reasons, calls to Extend should be kept
|
||||
// to a minimum.
|
||||
//
|
||||
// Some best practices:
|
||||
//
|
||||
// - Minimize calls Extend when handling API requests. Where possible, call Extend
|
||||
// when initializing components.
|
||||
// - If an EnvSets returned by Extend can be used to compile multiple CEL programs,
|
||||
// call Extend once and reuse the returned EnvSets.
|
||||
// - Prefer a single call to Extend with a full list of VersionedOptions over
|
||||
// making multiple calls to Extend.
|
||||
func (e *EnvSet) Extend(options ...VersionedOptions) (*EnvSet, error) {
|
||||
if len(options) > 0 {
|
||||
newExprOpts, err := e.filterAndBuildOpts(e.newExpressions, e.compatibilityVersion, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p, err := e.newExpressions.Extend(newExprOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storedExprOpt, err := e.filterAndBuildOpts(e.storedExpressions, version.MajorMinor(math.MaxUint, math.MaxUint), options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := e.storedExpressions.Extend(storedExprOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EnvSet{compatibilityVersion: e.compatibilityVersion, newExpressions: p, storedExpressions: s}, nil
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
|
||||
func (e *EnvSet) filterAndBuildOpts(base *cel.Env, compatVer *version.Version, opts []VersionedOptions) (cel.EnvOption, error) {
|
||||
var envOpts []cel.EnvOption
|
||||
var progOpts []cel.ProgramOption
|
||||
var declTypes []*apiservercel.DeclType
|
||||
|
||||
for _, opt := range opts {
|
||||
if compatVer.AtLeast(opt.IntroducedVersion) && (opt.RemovedVersion == nil || compatVer.LessThan(opt.RemovedVersion)) {
|
||||
envOpts = append(envOpts, opt.EnvOptions...)
|
||||
progOpts = append(progOpts, opt.ProgramOptions...)
|
||||
declTypes = append(declTypes, opt.DeclTypes...)
|
||||
}
|
||||
}
|
||||
|
||||
if len(declTypes) > 0 {
|
||||
provider := apiservercel.NewDeclTypeProvider(declTypes...)
|
||||
providerOpts, err := provider.EnvOptions(base.TypeProvider())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
envOpts = append(envOpts, providerOpts...)
|
||||
}
|
||||
|
||||
combined := cel.Lib(&envLoader{
|
||||
envOpts: envOpts,
|
||||
progOpts: progOpts,
|
||||
})
|
||||
return combined, nil
|
||||
}
|
||||
|
||||
type envLoader struct {
|
||||
envOpts []cel.EnvOption
|
||||
progOpts []cel.ProgramOption
|
||||
}
|
||||
|
||||
func (e *envLoader) CompileOptions() []cel.EnvOption {
|
||||
return e.envOpts
|
||||
}
|
||||
|
||||
func (e *envLoader) ProgramOptions() []cel.ProgramOption {
|
||||
return e.progOpts
|
||||
}
|
191
vendor/k8s.io/apiserver/pkg/cel/lazy/lazy.go
generated
vendored
Normal file
191
vendor/k8s.io/apiserver/pkg/cel/lazy/lazy.go
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package lazy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
"github.com/google/cel-go/common/types/traits"
|
||||
|
||||
"k8s.io/apiserver/pkg/cel"
|
||||
)
|
||||
|
||||
type GetFieldFunc func(*MapValue) ref.Val
|
||||
|
||||
var _ ref.Val = (*MapValue)(nil)
|
||||
var _ traits.Mapper = (*MapValue)(nil)
|
||||
|
||||
// MapValue is a map that lazily evaluate its value when a field is first accessed.
|
||||
// The map value is not designed to be thread-safe.
|
||||
type MapValue struct {
|
||||
typeValue *types.TypeValue
|
||||
|
||||
// values are previously evaluated values obtained from callbacks
|
||||
values map[string]ref.Val
|
||||
// callbacks are a map of field name to the function that returns the field Val
|
||||
callbacks map[string]GetFieldFunc
|
||||
// knownValues are registered names, used for iteration
|
||||
knownValues []string
|
||||
}
|
||||
|
||||
func NewMapValue(objectType ref.Type) *MapValue {
|
||||
return &MapValue{
|
||||
typeValue: types.NewTypeValue(objectType.TypeName(), traits.IndexerType|traits.FieldTesterType|traits.IterableType),
|
||||
values: map[string]ref.Val{},
|
||||
callbacks: map[string]GetFieldFunc{},
|
||||
}
|
||||
}
|
||||
|
||||
// Append adds the given field with its name and callback.
|
||||
func (m *MapValue) Append(name string, callback GetFieldFunc) {
|
||||
m.knownValues = append(m.knownValues, name)
|
||||
m.callbacks[name] = callback
|
||||
}
|
||||
|
||||
// Contains checks if the key is known to the map
|
||||
func (m *MapValue) Contains(key ref.Val) ref.Val {
|
||||
v, found := m.Find(key)
|
||||
if v != nil && types.IsUnknownOrError(v) {
|
||||
return v
|
||||
}
|
||||
return types.Bool(found)
|
||||
}
|
||||
|
||||
// Iterator returns an iterator to traverse the map.
|
||||
func (m *MapValue) Iterator() traits.Iterator {
|
||||
return &iterator{parent: m, index: 0}
|
||||
}
|
||||
|
||||
// Size returns the number of currently known fields
|
||||
func (m *MapValue) Size() ref.Val {
|
||||
return types.Int(len(m.callbacks))
|
||||
}
|
||||
|
||||
// ConvertToNative returns an error because it is disallowed
|
||||
func (m *MapValue) ConvertToNative(typeDesc reflect.Type) (any, error) {
|
||||
return nil, fmt.Errorf("disallowed conversion from %q to %q", m.typeValue.TypeName(), typeDesc.Name())
|
||||
}
|
||||
|
||||
// ConvertToType converts the map to the given type.
|
||||
// Only its own type and "Type" type are allowed.
|
||||
func (m *MapValue) ConvertToType(typeVal ref.Type) ref.Val {
|
||||
switch typeVal {
|
||||
case m.typeValue:
|
||||
return m
|
||||
case types.TypeType:
|
||||
return m.typeValue
|
||||
}
|
||||
return types.NewErr("disallowed conversion from %q to %q", m.typeValue.TypeName(), typeVal.TypeName())
|
||||
}
|
||||
|
||||
// Equal returns true if the other object is the same pointer-wise.
|
||||
func (m *MapValue) Equal(other ref.Val) ref.Val {
|
||||
otherMap, ok := other.(*MapValue)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(other)
|
||||
}
|
||||
return types.Bool(m == otherMap)
|
||||
}
|
||||
|
||||
// Type returns its registered type.
|
||||
func (m *MapValue) Type() ref.Type {
|
||||
return m.typeValue
|
||||
}
|
||||
|
||||
// Value is not allowed.
|
||||
func (m *MapValue) Value() any {
|
||||
return types.NoSuchOverloadErr()
|
||||
}
|
||||
|
||||
// resolveField resolves the field. Calls the callback if the value is not yet stored.
|
||||
func (m *MapValue) resolveField(name string) ref.Val {
|
||||
v, seen := m.values[name]
|
||||
if seen {
|
||||
return v
|
||||
}
|
||||
f := m.callbacks[name]
|
||||
v = f(m)
|
||||
m.values[name] = v
|
||||
return v
|
||||
}
|
||||
|
||||
func (m *MapValue) Find(key ref.Val) (ref.Val, bool) {
|
||||
n, ok := key.(types.String)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(n), true
|
||||
}
|
||||
name, ok := cel.Unescape(n.Value().(string))
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if _, exists := m.callbacks[name]; !exists {
|
||||
return nil, false
|
||||
}
|
||||
return m.resolveField(name), true
|
||||
}
|
||||
|
||||
func (m *MapValue) Get(key ref.Val) ref.Val {
|
||||
v, found := m.Find(key)
|
||||
if found {
|
||||
return v
|
||||
}
|
||||
return types.ValOrErr(key, "no such key: %v", key)
|
||||
}
|
||||
|
||||
type iterator struct {
|
||||
parent *MapValue
|
||||
index int
|
||||
}
|
||||
|
||||
func (i *iterator) ConvertToNative(typeDesc reflect.Type) (any, error) {
|
||||
return nil, fmt.Errorf("disallowed conversion to %q", typeDesc.Name())
|
||||
}
|
||||
|
||||
func (i *iterator) ConvertToType(typeValue ref.Type) ref.Val {
|
||||
return types.NewErr("disallowed conversion o %q", typeValue.TypeName())
|
||||
}
|
||||
|
||||
func (i *iterator) Equal(other ref.Val) ref.Val {
|
||||
otherIterator, ok := other.(*iterator)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(other)
|
||||
}
|
||||
return types.Bool(otherIterator == i)
|
||||
}
|
||||
|
||||
func (i *iterator) Type() ref.Type {
|
||||
return types.IteratorType
|
||||
}
|
||||
|
||||
func (i *iterator) Value() any {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *iterator) HasNext() ref.Val {
|
||||
return types.Bool(i.index < len(i.parent.knownValues))
|
||||
}
|
||||
|
||||
func (i *iterator) Next() ref.Val {
|
||||
ret := i.parent.Get(types.String(i.parent.knownValues[i.index]))
|
||||
i.index++
|
||||
return ret
|
||||
}
|
||||
|
||||
var _ traits.Iterator = (*iterator)(nil)
|
62
vendor/k8s.io/apiserver/pkg/cel/library/authz.go
generated
vendored
62
vendor/k8s.io/apiserver/pkg/cel/library/authz.go
generated
vendored
@ -174,6 +174,26 @@ import (
|
||||
// Examples:
|
||||
//
|
||||
// authorizer.path('/healthz').check('GET').reason()
|
||||
//
|
||||
// errored
|
||||
//
|
||||
// Returns true if the authorization check resulted in an error.
|
||||
//
|
||||
// <Decision>.errored() <bool>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// authorizer.group('').resource('pods').namespace('default').check('create').errored() // Returns true if the authorization check resulted in an error
|
||||
//
|
||||
// error
|
||||
//
|
||||
// If the authorization check resulted in an error, returns the error. Otherwise, returns the empty string.
|
||||
//
|
||||
// <Decision>.error() <string>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// authorizer.group('').resource('pods').namespace('default').check('create').error()
|
||||
func Authz() cel.EnvOption {
|
||||
return cel.Lib(authzLib)
|
||||
}
|
||||
@ -209,6 +229,12 @@ var authzLibraryDecls = map[string][]cel.FunctionOpt{
|
||||
cel.BinaryBinding(pathCheckCheck)),
|
||||
cel.MemberOverload("resourcecheck_check", []*cel.Type{ResourceCheckType, cel.StringType}, DecisionType,
|
||||
cel.BinaryBinding(resourceCheckCheck))},
|
||||
"errored": {
|
||||
cel.MemberOverload("decision_errored", []*cel.Type{DecisionType}, cel.BoolType,
|
||||
cel.UnaryBinding(decisionErrored))},
|
||||
"error": {
|
||||
cel.MemberOverload("decision_error", []*cel.Type{DecisionType}, cel.StringType,
|
||||
cel.UnaryBinding(decisionError))},
|
||||
"allowed": {
|
||||
cel.MemberOverload("decision_allowed", []*cel.Type{DecisionType}, cel.BoolType,
|
||||
cel.UnaryBinding(decisionAllowed))},
|
||||
@ -384,6 +410,27 @@ func resourceCheckCheck(arg1, arg2 ref.Val) ref.Val {
|
||||
return resourceCheck.Authorize(context.TODO(), apiVerb)
|
||||
}
|
||||
|
||||
func decisionErrored(arg ref.Val) ref.Val {
|
||||
decision, ok := arg.(decisionVal)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.Bool(decision.err != nil)
|
||||
}
|
||||
|
||||
func decisionError(arg ref.Val) ref.Val {
|
||||
decision, ok := arg.(decisionVal)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
if decision.err == nil {
|
||||
return types.String("")
|
||||
}
|
||||
return types.String(decision.err.Error())
|
||||
}
|
||||
|
||||
func decisionAllowed(arg ref.Val) ref.Val {
|
||||
decision, ok := arg.(decisionVal)
|
||||
if !ok {
|
||||
@ -478,10 +525,7 @@ func (a pathCheckVal) Authorize(ctx context.Context, verb string) ref.Val {
|
||||
}
|
||||
|
||||
decision, reason, err := a.authorizer.authAuthorizer.Authorize(ctx, attr)
|
||||
if err != nil {
|
||||
return types.NewErr("error in authorization check: %v", err)
|
||||
}
|
||||
return newDecision(decision, reason)
|
||||
return newDecision(decision, err, reason)
|
||||
}
|
||||
|
||||
type groupCheckVal struct {
|
||||
@ -516,18 +560,16 @@ func (a resourceCheckVal) Authorize(ctx context.Context, verb string) ref.Val {
|
||||
User: a.groupCheck.authorizer.userInfo,
|
||||
}
|
||||
decision, reason, err := a.groupCheck.authorizer.authAuthorizer.Authorize(ctx, attr)
|
||||
if err != nil {
|
||||
return types.NewErr("error in authorization check: %v", err)
|
||||
}
|
||||
return newDecision(decision, reason)
|
||||
return newDecision(decision, err, reason)
|
||||
}
|
||||
|
||||
func newDecision(authDecision authorizer.Decision, reason string) decisionVal {
|
||||
return decisionVal{receiverOnlyObjectVal: receiverOnlyVal(DecisionType), authDecision: authDecision, reason: reason}
|
||||
func newDecision(authDecision authorizer.Decision, err error, reason string) decisionVal {
|
||||
return decisionVal{receiverOnlyObjectVal: receiverOnlyVal(DecisionType), authDecision: authDecision, err: err, reason: reason}
|
||||
}
|
||||
|
||||
type decisionVal struct {
|
||||
receiverOnlyObjectVal
|
||||
err error
|
||||
authDecision authorizer.Decision
|
||||
reason string
|
||||
}
|
||||
|
4
vendor/k8s.io/apiserver/pkg/cel/library/cost.go
generated
vendored
4
vendor/k8s.io/apiserver/pkg/cel/library/cost.go
generated
vendored
@ -41,7 +41,7 @@ func (l *CostEstimator) CallCost(function, overloadId string, args []ref.Val, re
|
||||
// This cost is set to allow for only two authorization checks per expression
|
||||
cost := uint64(350000)
|
||||
return &cost
|
||||
case "serviceAccount", "path", "group", "resource", "subresource", "namespace", "name", "allowed", "denied", "reason":
|
||||
case "serviceAccount", "path", "group", "resource", "subresource", "namespace", "name", "allowed", "reason", "error", "errored":
|
||||
// All authorization builder and accessor functions have a nominal cost
|
||||
cost := uint64(1)
|
||||
return &cost
|
||||
@ -91,7 +91,7 @@ func (l *CostEstimator) EstimateCallCost(function, overloadId string, target *ch
|
||||
// An authorization check has a fixed cost
|
||||
// This cost is set to allow for only two authorization checks per expression
|
||||
return &checker.CallEstimate{CostEstimate: checker.CostEstimate{Min: 350000, Max: 350000}}
|
||||
case "serviceAccount", "path", "group", "resource", "subresource", "namespace", "name", "allowed", "denied", "reason":
|
||||
case "serviceAccount", "path", "group", "resource", "subresource", "namespace", "name", "allowed", "reason", "error", "errored":
|
||||
// All authorization builder and accessor functions have a nominal cost
|
||||
return &checker.CallEstimate{CostEstimate: checker.CostEstimate{Min: 1, Max: 1}}
|
||||
case "isSorted", "sum", "max", "min", "indexOf", "lastIndexOf":
|
||||
|
35
vendor/k8s.io/apiserver/pkg/cel/library/libraries.go
generated
vendored
35
vendor/k8s.io/apiserver/pkg/cel/library/libraries.go
generated
vendored
@ -1,35 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package library
|
||||
|
||||
import (
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/ext"
|
||||
"github.com/google/cel-go/interpreter"
|
||||
)
|
||||
|
||||
// ExtensionLibs declares the set of CEL extension libraries available everywhere CEL is used in Kubernetes.
|
||||
var ExtensionLibs = append(k8sExtensionLibs, ext.Strings())
|
||||
|
||||
var k8sExtensionLibs = []cel.EnvOption{
|
||||
URLs(),
|
||||
Regex(),
|
||||
Lists(),
|
||||
Authz(),
|
||||
}
|
||||
|
||||
var ExtensionLibRegexOptimizations = []*interpreter.RegexOptimization{FindRegexOptimization, FindAllRegexOptimization}
|
375
vendor/k8s.io/apiserver/pkg/cel/library/quantity.go
generated
vendored
Normal file
375
vendor/k8s.io/apiserver/pkg/cel/library/quantity.go
generated
vendored
Normal file
@ -0,0 +1,375 @@
|
||||
/*
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package library
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
apiservercel "k8s.io/apiserver/pkg/cel"
|
||||
)
|
||||
|
||||
// Quantity provides a CEL function library extension of Kubernetes
|
||||
// resource.Quantity parsing functions. See `resource.Quantity`
|
||||
// documentation for more detailed information about the format itself:
|
||||
// https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity
|
||||
//
|
||||
// quantity
|
||||
//
|
||||
// Converts a string to a Quantity or results in an error if the string is not a valid Quantity. Refer
|
||||
// to resource.Quantity documentation for information on accepted patterns.
|
||||
//
|
||||
// quantity(<string>) <Quantity>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// quantity('1.5G') // returns a Quantity
|
||||
// quantity('200k') // returns a Quantity
|
||||
// quantity('200K') // error
|
||||
// quantity('Three') // error
|
||||
// quantity('Mi') // error
|
||||
//
|
||||
// isQuantity
|
||||
//
|
||||
// Returns true if a string is a valid Quantity. isQuantity returns true if and
|
||||
// only if quantity does not result in error.
|
||||
//
|
||||
// isQuantity( <string>) <bool>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// isQuantity('1.3G') // returns true
|
||||
// isQuantity('1.3Gi') // returns true
|
||||
// isQuantity('1,3G') // returns false
|
||||
// isQuantity('10000k') // returns true
|
||||
// isQuantity('200K') // returns false
|
||||
// isQuantity('Three') // returns false
|
||||
// isQuantity('Mi') // returns false
|
||||
//
|
||||
// Conversion to Scalars:
|
||||
//
|
||||
// - isInteger: returns true if and only if asInteger is safe to call without an error
|
||||
//
|
||||
// - asInteger: returns a representation of the current value as an int64 if
|
||||
// possible or results in an error if conversion would result in overflow
|
||||
// or loss of precision.
|
||||
//
|
||||
// - asApproximateFloat: returns a float64 representation of the quantity which may
|
||||
// lose precision. If the value of the quantity is outside the range of a float64
|
||||
// +Inf/-Inf will be returned.
|
||||
//
|
||||
// <Quantity>.isInteger() <bool>
|
||||
// <Quantity>.asInteger() <int>
|
||||
// <Quantity>.asApproximateFloat() <float>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// quantity("50000000G").isInteger() // returns true
|
||||
// quantity("50k").isInteger() // returns true
|
||||
// quantity("9999999999999999999999999999999999999G").asInteger() // error: cannot convert value to integer
|
||||
// quantity("9999999999999999999999999999999999999G").isInteger() // returns false
|
||||
// quantity("50k").asInteger() == 50000 // returns true
|
||||
// quantity("50k").sub(20000).asApproximateFloat() == 30000 // returns true
|
||||
//
|
||||
// Arithmetic
|
||||
//
|
||||
// - sign: Returns `1` if the quantity is positive, `-1` if it is negative. `0` if it is zero
|
||||
//
|
||||
// - add: Returns sum of two quantities or a quantity and an integer
|
||||
//
|
||||
// - sub: Returns difference between two quantities or a quantity and an integer
|
||||
//
|
||||
// <Quantity>.sign() <int>
|
||||
// <Quantity>.add(<quantity>) <quantity>
|
||||
// <Quantity>.add(<integer>) <quantity>
|
||||
// <Quantity>.sub(<quantity>) <quantity>
|
||||
// <Quantity>.sub(<integer>) <quantity>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// quantity("50k").add("20k") == quantity("70k") // returns true
|
||||
// quantity("50k").add(20) == quantity("50020") // returns true
|
||||
// quantity("50k").sub("20k") == quantity("30k") // returns true
|
||||
// quantity("50k").sub(20000) == quantity("30k") // returns true
|
||||
// quantity("50k").add(20).sub(quantity("100k")).sub(-50000) == quantity("20") // returns true
|
||||
//
|
||||
// Comparisons
|
||||
//
|
||||
// - isGreaterThan: Returns true if and only if the receiver is greater than the operand
|
||||
//
|
||||
// - isLessThan: Returns true if and only if the receiver is less than the operand
|
||||
//
|
||||
// - compareTo: Compares receiver to operand and returns 0 if they are equal, 1 if the receiver is greater, or -1 if the receiver is less than the operand
|
||||
//
|
||||
//
|
||||
// <Quantity>.isLessThan(<quantity>) <bool>
|
||||
// <Quantity>.isGreaterThan(<quantity>) <bool>
|
||||
// <Quantity>.compareTo(<quantity>) <int>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// quantity("200M").compareTo(quantity("0.2G")) // returns 0
|
||||
// quantity("50M").compareTo(quantity("50Mi")) // returns -1
|
||||
// quantity("50Mi").compareTo(quantity("50M")) // returns 1
|
||||
// quantity("150Mi").isGreaterThan(quantity("100Mi")) // returns true
|
||||
// quantity("50Mi").isGreaterThan(quantity("100Mi")) // returns false
|
||||
// quantity("50M").isLessThan(quantity("100M")) // returns true
|
||||
// quantity("100M").isLessThan(quantity("50M")) // returns false
|
||||
|
||||
func Quantity() cel.EnvOption {
|
||||
return cel.Lib(quantityLib)
|
||||
}
|
||||
|
||||
var quantityLib = &quantity{}
|
||||
|
||||
type quantity struct{}
|
||||
|
||||
var quantityLibraryDecls = map[string][]cel.FunctionOpt{
|
||||
"quantity": {
|
||||
cel.Overload("string_to_quantity", []*cel.Type{cel.StringType}, apiservercel.QuantityType, cel.UnaryBinding((stringToQuantity))),
|
||||
},
|
||||
"isQuantity": {
|
||||
cel.Overload("is_quantity_string", []*cel.Type{cel.StringType}, cel.BoolType, cel.UnaryBinding(isQuantity)),
|
||||
},
|
||||
"sign": {
|
||||
cel.Overload("quantity_sign", []*cel.Type{apiservercel.QuantityType}, cel.IntType, cel.UnaryBinding(quantityGetSign)),
|
||||
},
|
||||
"isGreaterThan": {
|
||||
cel.MemberOverload("quantity_is_greater_than", []*cel.Type{apiservercel.QuantityType, apiservercel.QuantityType}, cel.BoolType, cel.BinaryBinding(quantityIsGreaterThan)),
|
||||
},
|
||||
"isLessThan": {
|
||||
cel.MemberOverload("quantity_is_less_than", []*cel.Type{apiservercel.QuantityType, apiservercel.QuantityType}, cel.BoolType, cel.BinaryBinding(quantityIsLessThan)),
|
||||
},
|
||||
"compareTo": {
|
||||
cel.MemberOverload("quantity_compare_to", []*cel.Type{apiservercel.QuantityType, apiservercel.QuantityType}, cel.IntType, cel.BinaryBinding(quantityCompareTo)),
|
||||
},
|
||||
"asApproximateFloat": {
|
||||
cel.MemberOverload("quantity_get_float", []*cel.Type{apiservercel.QuantityType}, cel.DoubleType, cel.UnaryBinding(quantityGetApproximateFloat)),
|
||||
},
|
||||
"asInteger": {
|
||||
cel.MemberOverload("quantity_get_int", []*cel.Type{apiservercel.QuantityType}, cel.IntType, cel.UnaryBinding(quantityGetValue)),
|
||||
},
|
||||
"isInteger": {
|
||||
cel.MemberOverload("quantity_is_integer", []*cel.Type{apiservercel.QuantityType}, cel.BoolType, cel.UnaryBinding(quantityCanValue)),
|
||||
},
|
||||
"add": {
|
||||
cel.MemberOverload("quantity_add", []*cel.Type{apiservercel.QuantityType, apiservercel.QuantityType}, apiservercel.QuantityType, cel.BinaryBinding(quantityAdd)),
|
||||
cel.MemberOverload("quantity_add_int", []*cel.Type{apiservercel.QuantityType, cel.IntType}, apiservercel.QuantityType, cel.BinaryBinding(quantityAddInt)),
|
||||
},
|
||||
"sub": {
|
||||
cel.MemberOverload("quantity_sub", []*cel.Type{apiservercel.QuantityType, apiservercel.QuantityType}, apiservercel.QuantityType, cel.BinaryBinding(quantitySub)),
|
||||
cel.MemberOverload("quantity_sub_int", []*cel.Type{apiservercel.QuantityType, cel.IntType}, apiservercel.QuantityType, cel.BinaryBinding(quantitySubInt)),
|
||||
},
|
||||
}
|
||||
|
||||
func (*quantity) CompileOptions() []cel.EnvOption {
|
||||
options := make([]cel.EnvOption, 0, len(quantityLibraryDecls))
|
||||
for name, overloads := range quantityLibraryDecls {
|
||||
options = append(options, cel.Function(name, overloads...))
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func (*quantity) ProgramOptions() []cel.ProgramOption {
|
||||
return []cel.ProgramOption{}
|
||||
}
|
||||
|
||||
func isQuantity(arg ref.Val) ref.Val {
|
||||
str, ok := arg.Value().(string)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
_, err := resource.ParseQuantity(str)
|
||||
if err != nil {
|
||||
return types.Bool(false)
|
||||
}
|
||||
|
||||
return types.Bool(true)
|
||||
}
|
||||
|
||||
func stringToQuantity(arg ref.Val) ref.Val {
|
||||
str, ok := arg.Value().(string)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
q, err := resource.ParseQuantity(str)
|
||||
if err != nil {
|
||||
return types.WrapErr(err)
|
||||
}
|
||||
|
||||
return apiservercel.Quantity{Quantity: &q}
|
||||
}
|
||||
|
||||
func quantityGetApproximateFloat(arg ref.Val) ref.Val {
|
||||
q, ok := arg.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
return types.Double(q.AsApproximateFloat64())
|
||||
}
|
||||
|
||||
func quantityCanValue(arg ref.Val) ref.Val {
|
||||
q, ok := arg.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
_, success := q.AsInt64()
|
||||
return types.Bool(success)
|
||||
}
|
||||
|
||||
func quantityGetValue(arg ref.Val) ref.Val {
|
||||
q, ok := arg.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
v, success := q.AsInt64()
|
||||
if !success {
|
||||
return types.WrapErr(errors.New("cannot convert value to integer"))
|
||||
}
|
||||
return types.Int(v)
|
||||
}
|
||||
|
||||
func quantityGetSign(arg ref.Val) ref.Val {
|
||||
q, ok := arg.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
return types.Int(q.Sign())
|
||||
}
|
||||
|
||||
func quantityIsGreaterThan(arg ref.Val, other ref.Val) ref.Val {
|
||||
q, ok := arg.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
q2, ok := other.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.Bool(q.Cmp(*q2) == 1)
|
||||
}
|
||||
|
||||
func quantityIsLessThan(arg ref.Val, other ref.Val) ref.Val {
|
||||
q, ok := arg.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
q2, ok := other.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.Bool(q.Cmp(*q2) == -1)
|
||||
}
|
||||
|
||||
func quantityCompareTo(arg ref.Val, other ref.Val) ref.Val {
|
||||
q, ok := arg.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
q2, ok := other.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.Int(q.Cmp(*q2))
|
||||
}
|
||||
|
||||
func quantityAdd(arg ref.Val, other ref.Val) ref.Val {
|
||||
q, ok := arg.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
q2, ok := other.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
copy := *q
|
||||
copy.Add(*q2)
|
||||
return &apiservercel.Quantity{
|
||||
Quantity: ©,
|
||||
}
|
||||
}
|
||||
|
||||
func quantityAddInt(arg ref.Val, other ref.Val) ref.Val {
|
||||
q, ok := arg.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
q2, ok := other.Value().(int64)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
q2Converted := *resource.NewQuantity(q2, resource.DecimalExponent)
|
||||
|
||||
copy := *q
|
||||
copy.Add(q2Converted)
|
||||
return &apiservercel.Quantity{
|
||||
Quantity: ©,
|
||||
}
|
||||
}
|
||||
|
||||
func quantitySub(arg ref.Val, other ref.Val) ref.Val {
|
||||
q, ok := arg.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
q2, ok := other.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
copy := *q
|
||||
copy.Sub(*q2)
|
||||
return &apiservercel.Quantity{
|
||||
Quantity: ©,
|
||||
}
|
||||
}
|
||||
|
||||
func quantitySubInt(arg ref.Val, other ref.Val) ref.Val {
|
||||
q, ok := arg.Value().(*resource.Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
q2, ok := other.Value().(int64)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
q2Converted := *resource.NewQuantity(q2, resource.DecimalExponent)
|
||||
|
||||
copy := *q
|
||||
copy.Sub(q2Converted)
|
||||
return &apiservercel.Quantity{
|
||||
Quantity: ©,
|
||||
}
|
||||
}
|
4
vendor/k8s.io/apiserver/pkg/cel/library/regex.go
generated
vendored
4
vendor/k8s.io/apiserver/pkg/cel/library/regex.go
generated
vendored
@ -77,7 +77,9 @@ func (*regex) CompileOptions() []cel.EnvOption {
|
||||
}
|
||||
|
||||
func (*regex) ProgramOptions() []cel.ProgramOption {
|
||||
return []cel.ProgramOption{}
|
||||
return []cel.ProgramOption{
|
||||
cel.OptimizeRegex(FindRegexOptimization, FindAllRegexOptimization),
|
||||
}
|
||||
}
|
||||
|
||||
func find(strVal ref.Val, regexVal ref.Val) ref.Val {
|
||||
|
79
vendor/k8s.io/apiserver/pkg/cel/library/test.go
generated
vendored
Normal file
79
vendor/k8s.io/apiserver/pkg/cel/library/test.go
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package library
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
)
|
||||
|
||||
// Test provides a test() function that returns true.
|
||||
func Test(options ...TestOption) cel.EnvOption {
|
||||
t := &testLib{version: math.MaxUint32}
|
||||
for _, o := range options {
|
||||
t = o(t)
|
||||
}
|
||||
return cel.Lib(t)
|
||||
}
|
||||
|
||||
type testLib struct {
|
||||
version uint32
|
||||
}
|
||||
|
||||
type TestOption func(*testLib) *testLib
|
||||
|
||||
func TestVersion(version uint32) func(lib *testLib) *testLib {
|
||||
return func(sl *testLib) *testLib {
|
||||
sl.version = version
|
||||
return sl
|
||||
}
|
||||
}
|
||||
|
||||
func (t *testLib) CompileOptions() []cel.EnvOption {
|
||||
var options []cel.EnvOption
|
||||
|
||||
if t.version == 0 {
|
||||
options = append(options, cel.Function("test",
|
||||
cel.Overload("test", []*cel.Type{}, cel.BoolType,
|
||||
cel.FunctionBinding(func(args ...ref.Val) ref.Val {
|
||||
return types.True
|
||||
}))))
|
||||
}
|
||||
|
||||
if t.version >= 1 {
|
||||
options = append(options, cel.Function("test",
|
||||
cel.Overload("test", []*cel.Type{}, cel.BoolType,
|
||||
cel.FunctionBinding(func(args ...ref.Val) ref.Val {
|
||||
// Return false here so tests can observe which version of the function is registered
|
||||
// Actual function libraries must not break backward compatibility
|
||||
return types.False
|
||||
}))))
|
||||
options = append(options, cel.Function("testV1",
|
||||
cel.Overload("testV1", []*cel.Type{}, cel.BoolType,
|
||||
cel.FunctionBinding(func(args ...ref.Val) ref.Val {
|
||||
return types.True
|
||||
}))))
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func (*testLib) ProgramOptions() []cel.ProgramOption {
|
||||
return []cel.ProgramOption{}
|
||||
}
|
76
vendor/k8s.io/apiserver/pkg/cel/quantity.go
generated
vendored
Normal file
76
vendor/k8s.io/apiserver/pkg/cel/quantity.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"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"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
)
|
||||
|
||||
var (
|
||||
QuantityObject = decls.NewObjectType("kubernetes.Quantity")
|
||||
quantityTypeValue = types.NewTypeValue("kubernetes.Quantity")
|
||||
QuantityType = cel.ObjectType("kubernetes.Quantity")
|
||||
)
|
||||
|
||||
// Quantity provdes a CEL representation of a resource.Quantity
|
||||
type Quantity struct {
|
||||
*resource.Quantity
|
||||
}
|
||||
|
||||
func (d Quantity) ConvertToNative(typeDesc reflect.Type) (interface{}, error) {
|
||||
if reflect.TypeOf(d.Quantity).AssignableTo(typeDesc) {
|
||||
return d.Quantity, nil
|
||||
}
|
||||
if reflect.TypeOf("").AssignableTo(typeDesc) {
|
||||
return d.Quantity.String(), nil
|
||||
}
|
||||
return nil, fmt.Errorf("type conversion error from 'Quantity' to '%v'", typeDesc)
|
||||
}
|
||||
|
||||
func (d Quantity) ConvertToType(typeVal ref.Type) ref.Val {
|
||||
switch typeVal {
|
||||
case typeValue:
|
||||
return d
|
||||
case types.TypeType:
|
||||
return quantityTypeValue
|
||||
default:
|
||||
return types.NewErr("type conversion error from '%s' to '%s'", quantityTypeValue, typeVal)
|
||||
}
|
||||
}
|
||||
|
||||
func (d Quantity) Equal(other ref.Val) ref.Val {
|
||||
otherDur, ok := other.(Quantity)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(other)
|
||||
}
|
||||
return types.Bool(d.Quantity.Equal(*otherDur.Quantity))
|
||||
}
|
||||
|
||||
func (d Quantity) Type() ref.Type {
|
||||
return quantityTypeValue
|
||||
}
|
||||
|
||||
func (d Quantity) Value() interface{} {
|
||||
return d.Quantity
|
||||
}
|
79
vendor/k8s.io/apiserver/pkg/cel/registry.go
generated
vendored
79
vendor/k8s.io/apiserver/pkg/cel/registry.go
generated
vendored
@ -1,79 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cel
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
)
|
||||
|
||||
// Resolver declares methods to find policy templates and related configuration objects.
|
||||
type Resolver interface {
|
||||
// FindType returns a DeclType instance corresponding to the given fully-qualified name, if
|
||||
// present.
|
||||
FindType(name string) (*DeclType, bool)
|
||||
}
|
||||
|
||||
// NewRegistry create a registry for keeping track of environments and types
|
||||
// from a base cel.Env expression environment.
|
||||
func NewRegistry(stdExprEnv *cel.Env) *Registry {
|
||||
return &Registry{
|
||||
exprEnvs: map[string]*cel.Env{"": stdExprEnv},
|
||||
types: map[string]*DeclType{
|
||||
BoolType.TypeName(): BoolType,
|
||||
BytesType.TypeName(): BytesType,
|
||||
DoubleType.TypeName(): DoubleType,
|
||||
DurationType.TypeName(): DurationType,
|
||||
IntType.TypeName(): IntType,
|
||||
NullType.TypeName(): NullType,
|
||||
StringType.TypeName(): StringType,
|
||||
TimestampType.TypeName(): TimestampType,
|
||||
UintType.TypeName(): UintType,
|
||||
ListType.TypeName(): ListType,
|
||||
MapType.TypeName(): MapType,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Registry defines a repository of environment, schema, template, and type definitions.
|
||||
//
|
||||
// Registry instances are concurrency-safe.
|
||||
type Registry struct {
|
||||
rwMux sync.RWMutex
|
||||
exprEnvs map[string]*cel.Env
|
||||
types map[string]*DeclType
|
||||
}
|
||||
|
||||
// FindType implements the Resolver interface method.
|
||||
func (r *Registry) FindType(name string) (*DeclType, bool) {
|
||||
r.rwMux.RLock()
|
||||
defer r.rwMux.RUnlock()
|
||||
typ, found := r.types[name]
|
||||
if found {
|
||||
return typ, true
|
||||
}
|
||||
return typ, found
|
||||
}
|
||||
|
||||
// SetType registers a DeclType descriptor by its fully qualified name.
|
||||
func (r *Registry) SetType(name string, declType *DeclType) error {
|
||||
r.rwMux.Lock()
|
||||
defer r.rwMux.Unlock()
|
||||
r.types[name] = declType
|
||||
return nil
|
||||
}
|
156
vendor/k8s.io/apiserver/pkg/cel/types.go
generated
vendored
156
vendor/k8s.io/apiserver/pkg/cel/types.go
generated
vendored
@ -319,44 +319,53 @@ func (f *DeclField) EnumValues() []ref.Val {
|
||||
return ev
|
||||
}
|
||||
|
||||
// NewRuleTypes returns an Open API Schema-based type-system which is CEL compatible.
|
||||
func NewRuleTypes(kind string,
|
||||
declType *DeclType,
|
||||
res Resolver) (*RuleTypes, error) {
|
||||
func allTypesForDecl(declTypes []*DeclType) map[string]*DeclType {
|
||||
if declTypes == nil {
|
||||
return nil
|
||||
}
|
||||
allTypes := map[string]*DeclType{}
|
||||
for _, declType := range declTypes {
|
||||
for k, t := range FieldTypeMap(declType.TypeName(), declType) {
|
||||
allTypes[k] = t
|
||||
}
|
||||
}
|
||||
|
||||
return allTypes
|
||||
}
|
||||
|
||||
// NewDeclTypeProvider returns an Open API Schema-based type-system which is CEL compatible.
|
||||
func NewDeclTypeProvider(rootTypes ...*DeclType) *DeclTypeProvider {
|
||||
// Note, if the schema indicates that it's actually based on another proto
|
||||
// then prefer the proto definition. For expressions in the proto, a new field
|
||||
// annotation will be needed to indicate the expected environment and type of
|
||||
// the expression.
|
||||
schemaTypes, err := newSchemaTypeProvider(kind, declType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
allTypes := allTypesForDecl(rootTypes)
|
||||
return &DeclTypeProvider{
|
||||
registeredTypes: allTypes,
|
||||
}
|
||||
if schemaTypes == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return &RuleTypes{
|
||||
ruleSchemaDeclTypes: schemaTypes,
|
||||
resolver: res,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RuleTypes extends the CEL ref.TypeProvider interface and provides an Open API Schema-based
|
||||
// DeclTypeProvider extends the CEL ref.TypeProvider interface and provides an Open API Schema-based
|
||||
// type-system.
|
||||
type RuleTypes struct {
|
||||
ref.TypeProvider
|
||||
ruleSchemaDeclTypes *schemaTypeProvider
|
||||
typeAdapter ref.TypeAdapter
|
||||
resolver Resolver
|
||||
type DeclTypeProvider struct {
|
||||
registeredTypes map[string]*DeclType
|
||||
typeProvider ref.TypeProvider
|
||||
typeAdapter ref.TypeAdapter
|
||||
}
|
||||
|
||||
func (rt *DeclTypeProvider) EnumValue(enumName string) ref.Val {
|
||||
return rt.typeProvider.EnumValue(enumName)
|
||||
}
|
||||
|
||||
func (rt *DeclTypeProvider) FindIdent(identName string) (ref.Val, bool) {
|
||||
return rt.typeProvider.FindIdent(identName)
|
||||
}
|
||||
|
||||
// EnvOptions returns a set of cel.EnvOption values which includes the declaration set
|
||||
// as well as a custom ref.TypeProvider.
|
||||
//
|
||||
// Note, the standard declaration set includes 'rule' which is defined as the top-level rule-schema
|
||||
// type if one is configured.
|
||||
//
|
||||
// If the RuleTypes value is nil, an empty []cel.EnvOption set is returned.
|
||||
func (rt *RuleTypes) EnvOptions(tp ref.TypeProvider) ([]cel.EnvOption, error) {
|
||||
// If the DeclTypeProvider value is nil, an empty []cel.EnvOption set is returned.
|
||||
func (rt *DeclTypeProvider) EnvOptions(tp ref.TypeProvider) ([]cel.EnvOption, error) {
|
||||
if rt == nil {
|
||||
return []cel.EnvOption{}, nil
|
||||
}
|
||||
@ -367,13 +376,12 @@ func (rt *RuleTypes) EnvOptions(tp ref.TypeProvider) ([]cel.EnvOption, error) {
|
||||
return []cel.EnvOption{
|
||||
cel.CustomTypeProvider(rtWithTypes),
|
||||
cel.CustomTypeAdapter(rtWithTypes),
|
||||
cel.Variable("rule", rt.ruleSchemaDeclTypes.root.CelType()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// WithTypeProvider returns a new RuleTypes that sets the given TypeProvider
|
||||
// If the original RuleTypes is nil, the returned RuleTypes is still nil.
|
||||
func (rt *RuleTypes) WithTypeProvider(tp ref.TypeProvider) (*RuleTypes, error) {
|
||||
// WithTypeProvider returns a new DeclTypeProvider that sets the given TypeProvider
|
||||
// If the original DeclTypeProvider is nil, the returned DeclTypeProvider is still nil.
|
||||
func (rt *DeclTypeProvider) WithTypeProvider(tp ref.TypeProvider) (*DeclTypeProvider, error) {
|
||||
if rt == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@ -382,13 +390,12 @@ func (rt *RuleTypes) WithTypeProvider(tp ref.TypeProvider) (*RuleTypes, error) {
|
||||
if ok {
|
||||
ta = tpa
|
||||
}
|
||||
rtWithTypes := &RuleTypes{
|
||||
TypeProvider: tp,
|
||||
typeAdapter: ta,
|
||||
ruleSchemaDeclTypes: rt.ruleSchemaDeclTypes,
|
||||
resolver: rt.resolver,
|
||||
rtWithTypes := &DeclTypeProvider{
|
||||
typeProvider: tp,
|
||||
typeAdapter: ta,
|
||||
registeredTypes: rt.registeredTypes,
|
||||
}
|
||||
for name, declType := range rt.ruleSchemaDeclTypes.types {
|
||||
for name, declType := range rt.registeredTypes {
|
||||
tpType, found := tp.FindType(name)
|
||||
expT, err := declType.ExprType()
|
||||
if err != nil {
|
||||
@ -396,7 +403,7 @@ func (rt *RuleTypes) WithTypeProvider(tp ref.TypeProvider) (*RuleTypes, error) {
|
||||
}
|
||||
if found && !proto.Equal(tpType, expT) {
|
||||
return nil, fmt.Errorf(
|
||||
"type %s definition differs between CEL environment and rule", name)
|
||||
"type %s definition differs between CEL environment and type provider", name)
|
||||
}
|
||||
}
|
||||
return rtWithTypes, nil
|
||||
@ -409,7 +416,7 @@ func (rt *RuleTypes) WithTypeProvider(tp ref.TypeProvider) (*RuleTypes, error) {
|
||||
//
|
||||
// Note, when the type name is based on the Open API Schema, the name will reflect the object path
|
||||
// where the type definition appears.
|
||||
func (rt *RuleTypes) FindType(typeName string) (*exprpb.Type, bool) {
|
||||
func (rt *DeclTypeProvider) FindType(typeName string) (*exprpb.Type, bool) {
|
||||
if rt == nil {
|
||||
return nil, false
|
||||
}
|
||||
@ -421,11 +428,11 @@ func (rt *RuleTypes) FindType(typeName string) (*exprpb.Type, bool) {
|
||||
}
|
||||
return expT, found
|
||||
}
|
||||
return rt.TypeProvider.FindType(typeName)
|
||||
return rt.typeProvider.FindType(typeName)
|
||||
}
|
||||
|
||||
// FindDeclType returns the CPT type description which can be mapped to a CEL type.
|
||||
func (rt *RuleTypes) FindDeclType(typeName string) (*DeclType, bool) {
|
||||
func (rt *DeclTypeProvider) FindDeclType(typeName string) (*DeclType, bool) {
|
||||
if rt == nil {
|
||||
return nil, false
|
||||
}
|
||||
@ -438,10 +445,10 @@ func (rt *RuleTypes) FindDeclType(typeName string) (*DeclType, bool) {
|
||||
// If, in the future an object instance rather than a type name were provided, the field
|
||||
// resolution might more accurately reflect the expected type model. However, in this case
|
||||
// concessions were made to align with the existing CEL interfaces.
|
||||
func (rt *RuleTypes) FindFieldType(typeName, fieldName string) (*ref.FieldType, bool) {
|
||||
func (rt *DeclTypeProvider) FindFieldType(typeName, fieldName string) (*ref.FieldType, bool) {
|
||||
st, found := rt.findDeclType(typeName)
|
||||
if !found {
|
||||
return rt.TypeProvider.FindFieldType(typeName, fieldName)
|
||||
return rt.typeProvider.FindFieldType(typeName, fieldName)
|
||||
}
|
||||
|
||||
f, found := st.Fields[fieldName]
|
||||
@ -471,48 +478,63 @@ func (rt *RuleTypes) FindFieldType(typeName, fieldName string) (*ref.FieldType,
|
||||
|
||||
// NativeToValue is an implementation of the ref.TypeAdapater interface which supports conversion
|
||||
// of rule values to CEL ref.Val instances.
|
||||
func (rt *RuleTypes) NativeToValue(val interface{}) ref.Val {
|
||||
func (rt *DeclTypeProvider) NativeToValue(val interface{}) ref.Val {
|
||||
return rt.typeAdapter.NativeToValue(val)
|
||||
}
|
||||
|
||||
// TypeNames returns the list of type names declared within the RuleTypes object.
|
||||
func (rt *RuleTypes) TypeNames() []string {
|
||||
typeNames := make([]string, len(rt.ruleSchemaDeclTypes.types))
|
||||
func (rt *DeclTypeProvider) NewValue(typeName string, fields map[string]ref.Val) ref.Val {
|
||||
// TODO: implement for OpenAPI types to enable CEL object instantiation, which is needed
|
||||
// for mutating admission.
|
||||
return rt.typeProvider.NewValue(typeName, fields)
|
||||
}
|
||||
|
||||
// TypeNames returns the list of type names declared within the DeclTypeProvider object.
|
||||
func (rt *DeclTypeProvider) TypeNames() []string {
|
||||
typeNames := make([]string, len(rt.registeredTypes))
|
||||
i := 0
|
||||
for name := range rt.ruleSchemaDeclTypes.types {
|
||||
for name := range rt.registeredTypes {
|
||||
typeNames[i] = name
|
||||
i++
|
||||
}
|
||||
return typeNames
|
||||
}
|
||||
|
||||
func (rt *RuleTypes) findDeclType(typeName string) (*DeclType, bool) {
|
||||
declType, found := rt.ruleSchemaDeclTypes.types[typeName]
|
||||
func (rt *DeclTypeProvider) findDeclType(typeName string) (*DeclType, bool) {
|
||||
declType, found := rt.registeredTypes[typeName]
|
||||
if found {
|
||||
return declType, true
|
||||
}
|
||||
declType, found = rt.resolver.FindType(typeName)
|
||||
if found {
|
||||
return declType, true
|
||||
}
|
||||
return nil, false
|
||||
declType = findScalar(typeName)
|
||||
return declType, declType != nil
|
||||
}
|
||||
|
||||
func newSchemaTypeProvider(kind string, declType *DeclType) (*schemaTypeProvider, error) {
|
||||
if declType == nil {
|
||||
return nil, nil
|
||||
func findScalar(typename string) *DeclType {
|
||||
switch typename {
|
||||
case BoolType.TypeName():
|
||||
return BoolType
|
||||
case BytesType.TypeName():
|
||||
return BytesType
|
||||
case DoubleType.TypeName():
|
||||
return DoubleType
|
||||
case DurationType.TypeName():
|
||||
return DurationType
|
||||
case IntType.TypeName():
|
||||
return IntType
|
||||
case NullType.TypeName():
|
||||
return NullType
|
||||
case StringType.TypeName():
|
||||
return StringType
|
||||
case TimestampType.TypeName():
|
||||
return TimestampType
|
||||
case UintType.TypeName():
|
||||
return UintType
|
||||
case ListType.TypeName():
|
||||
return ListType
|
||||
case MapType.TypeName():
|
||||
return MapType
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
root := declType.MaybeAssignTypeName(kind)
|
||||
types := FieldTypeMap(kind, root)
|
||||
return &schemaTypeProvider{
|
||||
root: root,
|
||||
types: types,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type schemaTypeProvider struct {
|
||||
root *DeclType
|
||||
types map[string]*DeclType
|
||||
}
|
||||
|
||||
var (
|
||||
|
Reference in New Issue
Block a user