k8s.io/apiserver@v0.31.1/pkg/cel/mutation/typeprovider.go (about)

     1  /*
     2  Copyright 2024 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package mutation
    18  
    19  import (
    20  	"k8s.io/apiserver/pkg/cel/mutation/common"
    21  
    22  	"github.com/google/cel-go/cel"
    23  	"github.com/google/cel-go/common/types"
    24  	"github.com/google/cel-go/common/types/ref"
    25  )
    26  
    27  // TypeProvider is a specialized CEL type provider that understands
    28  // the Object type alias that is used to construct an Apply configuration for
    29  // a mutation operation.
    30  type TypeProvider struct {
    31  	typeResolver           common.TypeResolver
    32  	underlyingTypeProvider types.Provider
    33  }
    34  
    35  var _ types.Provider = (*TypeProvider)(nil)
    36  
    37  // EnumValue returns the numeric value of the given enum value name.
    38  // This TypeProvider does not have special handling for EnumValue and thus directly delegate
    39  // to its underlying type provider.
    40  func (p *TypeProvider) EnumValue(enumName string) ref.Val {
    41  	return p.underlyingTypeProvider.EnumValue(enumName)
    42  }
    43  
    44  // FindIdent takes a qualified identifier name and returns a ref.ObjectVal if one exists.
    45  // This TypeProvider does not have special handling for FindIdent and thus directly delegate
    46  // to its underlying type provider.
    47  func (p *TypeProvider) FindIdent(identName string) (ref.Val, bool) {
    48  	return p.underlyingTypeProvider.FindIdent(identName)
    49  }
    50  
    51  // FindStructType returns the Type give a qualified type name, by looking it up with
    52  // the TypeResolver and translating it to CEL Type.
    53  // If the type is not known to the TypeResolver, the lookup falls back to the underlying
    54  // TypeProvider instead.
    55  func (p *TypeProvider) FindStructType(structType string) (*types.Type, bool) {
    56  	t, ok := p.typeResolver.Resolve(structType)
    57  	if ok {
    58  		return t.CELType(), true
    59  	}
    60  	return p.underlyingTypeProvider.FindStructType(structType)
    61  }
    62  
    63  // FindStructFieldNames returns the field names associated with the type, if the type
    64  // is found.
    65  func (p *TypeProvider) FindStructFieldNames(structType string) ([]string, bool) {
    66  	return nil, true
    67  }
    68  
    69  // FindStructFieldType returns the field type for a checked type value.
    70  // Returns false if the field could not be found.
    71  func (p *TypeProvider) FindStructFieldType(structType, fieldName string) (*types.FieldType, bool) {
    72  	t, ok := p.typeResolver.Resolve(structType)
    73  	if ok {
    74  		return t.Field(fieldName)
    75  	}
    76  	return p.underlyingTypeProvider.FindStructFieldType(structType, fieldName)
    77  }
    78  
    79  // NewValue creates a new type value from a qualified name and map of fields.
    80  func (p *TypeProvider) NewValue(structType string, fields map[string]ref.Val) ref.Val {
    81  	t, ok := p.typeResolver.Resolve(structType)
    82  	if ok {
    83  		return t.Val(fields)
    84  	}
    85  	return p.underlyingTypeProvider.NewValue(structType, fields)
    86  }
    87  
    88  // NewTypeProviderAndEnvOption creates the TypeProvider with a given TypeResolver,
    89  // and also returns the CEL EnvOption to apply it to the env.
    90  func NewTypeProviderAndEnvOption(resolver common.TypeResolver) (*TypeProvider, cel.EnvOption) {
    91  	tp := &TypeProvider{typeResolver: resolver}
    92  	var envOption cel.EnvOption = func(e *cel.Env) (*cel.Env, error) {
    93  		// wrap the existing type provider (acquired from the env)
    94  		// and set new type provider for the env.
    95  		tp.underlyingTypeProvider = e.CELTypeProvider()
    96  		typeProviderOption := cel.CustomTypeProvider(tp)
    97  		return typeProviderOption(e)
    98  	}
    99  	return tp, envOption
   100  }