Merge pull request #116264 from ivelichkovich/versionedattrrefactor

migrate versionedattr to avoid circular dependency
This commit is contained in:
Kubernetes Prow Robot 2023-03-07 12:38:32 -08:00 committed by GitHub
commit 323ad355b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 81 additions and 89 deletions

View File

@ -14,16 +14,40 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package generic package admission
import ( import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission"
) )
// VersionedAttributes is a wrapper around the original admission attributes, adding versioned
// variants of the object and old object.
type VersionedAttributes struct {
// Attributes holds the original admission attributes
Attributes
// VersionedOldObject holds Attributes.OldObject (if non-nil), converted to VersionedKind.
// It must never be mutated.
VersionedOldObject runtime.Object
// VersionedObject holds Attributes.Object (if non-nil), converted to VersionedKind.
// If mutated, Dirty must be set to true by the mutator.
VersionedObject runtime.Object
// VersionedKind holds the fully qualified kind
VersionedKind schema.GroupVersionKind
// Dirty indicates VersionedObject has been modified since being converted from Attributes.Object
Dirty bool
}
// GetObject overrides the Attributes.GetObject()
func (v *VersionedAttributes) GetObject() runtime.Object {
if v.VersionedObject != nil {
return v.VersionedObject
}
return v.Attributes.GetObject()
}
// ConvertToGVK converts object to the desired gvk. // ConvertToGVK converts object to the desired gvk.
func ConvertToGVK(obj runtime.Object, gvk schema.GroupVersionKind, o admission.ObjectInterfaces) (runtime.Object, error) { func ConvertToGVK(obj runtime.Object, gvk schema.GroupVersionKind, o ObjectInterfaces) (runtime.Object, error) {
// Unlike other resources, custom resources do not have internal version, so // Unlike other resources, custom resources do not have internal version, so
// if obj is a custom resource, it should not need conversion. // if obj is a custom resource, it should not need conversion.
if obj.GetObjectKind().GroupVersionKind() == gvk { if obj.GetObjectKind().GroupVersionKind() == gvk {
@ -43,7 +67,7 @@ func ConvertToGVK(obj runtime.Object, gvk schema.GroupVersionKind, o admission.O
} }
// NewVersionedAttributes returns versioned attributes with the old and new object (if non-nil) converted to the requested kind // NewVersionedAttributes returns versioned attributes with the old and new object (if non-nil) converted to the requested kind
func NewVersionedAttributes(attr admission.Attributes, gvk schema.GroupVersionKind, o admission.ObjectInterfaces) (*VersionedAttributes, error) { func NewVersionedAttributes(attr Attributes, gvk schema.GroupVersionKind, o ObjectInterfaces) (*VersionedAttributes, error) {
// convert the old and new objects to the requested version // convert the old and new objects to the requested version
versionedAttr := &VersionedAttributes{ versionedAttr := &VersionedAttributes{
Attributes: attr, Attributes: attr,
@ -72,7 +96,7 @@ func NewVersionedAttributes(attr admission.Attributes, gvk schema.GroupVersionKi
// * attr.VersionedObject is used as the source for the new object if Dirty=true (and is round-tripped through attr.Attributes.Object, clearing Dirty in the process) // * attr.VersionedObject is used as the source for the new object if Dirty=true (and is round-tripped through attr.Attributes.Object, clearing Dirty in the process)
// * attr.Attributes.Object is used as the source for the new object if Dirty=false // * attr.Attributes.Object is used as the source for the new object if Dirty=false
// * attr.Attributes.OldObject is used as the source for the old object // * attr.Attributes.OldObject is used as the source for the old object
func ConvertVersionedAttributes(attr *VersionedAttributes, gvk schema.GroupVersionKind, o admission.ObjectInterfaces) error { func ConvertVersionedAttributes(attr *VersionedAttributes, gvk schema.GroupVersionKind, o ObjectInterfaces) error {
// we already have the desired kind, we're done // we already have the desired kind, we're done
if attr.VersionedKind == gvk { if attr.VersionedKind == gvk {
return nil return nil

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package generic package admission
import ( import (
"encoding/json" "encoding/json"
@ -28,7 +28,6 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/apis/example" "k8s.io/apiserver/pkg/apis/example"
examplev1 "k8s.io/apiserver/pkg/apis/example/v1" examplev1 "k8s.io/apiserver/pkg/apis/example/v1"
example2v1 "k8s.io/apiserver/pkg/apis/example2/v1" example2v1 "k8s.io/apiserver/pkg/apis/example2/v1"
@ -44,7 +43,7 @@ func initiateScheme(t *testing.T) *runtime.Scheme {
func TestConvertToGVK(t *testing.T) { func TestConvertToGVK(t *testing.T) {
scheme := initiateScheme(t) scheme := initiateScheme(t)
o := admission.NewObjectInterfacesFromScheme(scheme) o := NewObjectInterfacesFromScheme(scheme)
table := map[string]struct { table := map[string]struct {
obj runtime.Object obj runtime.Object
gvk schema.GroupVersionKind gvk schema.GroupVersionKind
@ -165,13 +164,13 @@ func TestRuntimeSchemeConvert(t *testing.T) {
func TestConvertVersionedAttributes(t *testing.T) { func TestConvertVersionedAttributes(t *testing.T) {
scheme := initiateScheme(t) scheme := initiateScheme(t)
o := admission.NewObjectInterfacesFromScheme(scheme) o := NewObjectInterfacesFromScheme(scheme)
gvk := func(g, v, k string) schema.GroupVersionKind { gvk := func(g, v, k string) schema.GroupVersionKind {
return schema.GroupVersionKind{Group: g, Version: v, Kind: k} return schema.GroupVersionKind{Group: g, Version: v, Kind: k}
} }
attrs := func(obj, oldObj runtime.Object) admission.Attributes { attrs := func(obj, oldObj runtime.Object) Attributes {
return admission.NewAttributesRecord(obj, oldObj, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", "", nil, false, nil) return NewAttributesRecord(obj, oldObj, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", "", nil, false, nil)
} }
u := func(data string) *unstructured.Unstructured { u := func(data string) *unstructured.Unstructured {
t.Helper() t.Helper()

View File

@ -32,7 +32,6 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/apiserver/pkg/cel/library" "k8s.io/apiserver/pkg/cel/library"
) )
@ -120,7 +119,7 @@ func objectToResolveVal(r runtime.Object) (interface{}, error) {
// ForInput evaluates the compiled CEL expressions converting them into CELEvaluations // ForInput evaluates the compiled CEL expressions converting them into CELEvaluations
// errors per evaluation are returned on the Evaluation object // errors per evaluation are returned on the Evaluation object
// runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input. // runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input.
func (f *filter) ForInput(ctx context.Context, versionedAttr *generic.VersionedAttributes, request *admissionv1.AdmissionRequest, inputs OptionalVariableBindings, runtimeCELCostBudget int64) ([]EvaluationResult, error) { func (f *filter) ForInput(ctx context.Context, versionedAttr *admission.VersionedAttributes, request *admissionv1.AdmissionRequest, inputs OptionalVariableBindings, runtimeCELCostBudget int64) ([]EvaluationResult, error) {
// TODO: replace unstructured with ref.Val for CEL variables when native type support is available // TODO: replace unstructured with ref.Val for CEL variables when native type support is available
evaluations := make([]EvaluationResult, len(f.compilationResults)) evaluations := make([]EvaluationResult, len(f.compilationResults))
var err error var err error

View File

@ -34,7 +34,6 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
celconfig "k8s.io/apiserver/pkg/apis/cel" celconfig "k8s.io/apiserver/pkg/apis/cel"
"k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
@ -655,7 +654,7 @@ func TestFilter(t *testing.T) {
CompilationResults := f.(*filter).compilationResults CompilationResults := f.(*filter).compilationResults
require.Equal(t, len(validations), len(CompilationResults)) require.Equal(t, len(validations), len(CompilationResults))
versionedAttr, err := generic.NewVersionedAttributes(tc.attributes, tc.attributes.GetKind(), newObjectInterfacesForTest()) versionedAttr, err := admission.NewVersionedAttributes(tc.attributes, tc.attributes.GetKind(), newObjectInterfacesForTest())
if err != nil { if err != nil {
t.Fatalf("unexpected error on conversion: %v", err) t.Fatalf("unexpected error on conversion: %v", err)
} }
@ -758,7 +757,7 @@ func TestRuntimeCELCostBudget(t *testing.T) {
CompilationResults := f.(*filter).compilationResults CompilationResults := f.(*filter).compilationResults
require.Equal(t, len(validations), len(CompilationResults)) require.Equal(t, len(validations), len(CompilationResults))
versionedAttr, err := generic.NewVersionedAttributes(tc.attributes, tc.attributes.GetKind(), newObjectInterfacesForTest()) versionedAttr, err := admission.NewVersionedAttributes(tc.attributes, tc.attributes.GetKind(), newObjectInterfacesForTest())
if err != nil { if err != nil {
t.Fatalf("unexpected error on conversion: %v", err) t.Fatalf("unexpected error on conversion: %v", err)
} }

View File

@ -25,7 +25,7 @@ import (
v1 "k8s.io/api/admission/v1" v1 "k8s.io/api/admission/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic" "k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
) )
@ -94,7 +94,7 @@ type OptionalVariableBindings struct {
type Filter interface { type Filter interface {
// ForInput converts compiled CEL-typed values into evaluated CEL-typed values // ForInput converts compiled CEL-typed values into evaluated CEL-typed values
// runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input. // runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input.
ForInput(ctx context.Context, versionedAttr *generic.VersionedAttributes, request *v1.AdmissionRequest, optionalVars OptionalVariableBindings, runtimeCELCostBudget int64) ([]EvaluationResult, error) ForInput(ctx context.Context, versionedAttr *admission.VersionedAttributes, request *v1.AdmissionRequest, optionalVars OptionalVariableBindings, runtimeCELCostBudget int64) ([]EvaluationResult, error)
// CompilationErrors returns a list of errors from the compilation of the evaluator // CompilationErrors returns a list of errors from the compilation of the evaluator
CompilationErrors() []error CompilationErrors() []error

View File

@ -47,7 +47,6 @@ import (
"k8s.io/apiserver/pkg/admission/initializer" "k8s.io/apiserver/pkg/admission/initializer"
"k8s.io/apiserver/pkg/admission/plugin/cel" "k8s.io/apiserver/pkg/admission/plugin/cel"
"k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/internal/generic" "k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/internal/generic"
whgeneric "k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
auditinternal "k8s.io/apiserver/pkg/apis/audit" auditinternal "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/features"
@ -253,7 +252,7 @@ type fakeFilter struct {
keyId string keyId string
} }
func (f *fakeFilter) ForInput(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, request *admissionv1.AdmissionRequest, inputs cel.OptionalVariableBindings, runtimeCELCostBudget int64) ([]cel.EvaluationResult, error) { func (f *fakeFilter) ForInput(ctx context.Context, versionedAttr *admission.VersionedAttributes, request *admissionv1.AdmissionRequest, inputs cel.OptionalVariableBindings, runtimeCELCostBudget int64) ([]cel.EvaluationResult, error) {
return []cel.EvaluationResult{}, nil return []cel.EvaluationResult{}, nil
} }
@ -265,10 +264,10 @@ var _ Validator = &fakeValidator{}
type fakeValidator struct { type fakeValidator struct {
validationFilter, auditAnnotationFilter *fakeFilter validationFilter, auditAnnotationFilter *fakeFilter
ValidateFunc func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult ValidateFunc func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult
} }
func (f *fakeValidator) RegisterDefinition(definition *v1alpha1.ValidatingAdmissionPolicy, validateFunc func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult) { func (f *fakeValidator) RegisterDefinition(definition *v1alpha1.ValidatingAdmissionPolicy, validateFunc func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult) {
//Key must be something that we can decipher from the inputs to Validate so using message which will be on the validationCondition object of evalResult //Key must be something that we can decipher from the inputs to Validate so using message which will be on the validationCondition object of evalResult
var key string var key string
if len(definition.Spec.Validations) > 0 { if len(definition.Spec.Validations) > 0 {
@ -285,7 +284,7 @@ func (f *fakeValidator) RegisterDefinition(definition *v1alpha1.ValidatingAdmiss
validatorMap[key] = f validatorMap[key] = f
} }
func (f *fakeValidator) Validate(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { func (f *fakeValidator) Validate(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return f.ValidateFunc(ctx, versionedAttr, versionedParams, runtimeCELCostBudget) return f.ValidateFunc(ctx, versionedAttr, versionedParams, runtimeCELCostBudget)
} }
@ -769,7 +768,7 @@ func TestBasicPolicyDefinitionFailure(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -839,7 +838,7 @@ func TestDefinitionDoesntMatch(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -952,7 +951,7 @@ func TestReconfigureBinding(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1062,7 +1061,7 @@ func TestRemoveDefinition(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1131,7 +1130,7 @@ func TestRemoveBinding(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1241,7 +1240,7 @@ func TestInvalidParamSourceInstanceName(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1309,7 +1308,7 @@ func TestEmptyParamSource(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1411,7 +1410,7 @@ func TestMultiplePoliciesSharedParamType(t *testing.T) {
} }
}) })
validator1.RegisterDefinition(&policy1, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator1.RegisterDefinition(&policy1, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
evaluations1.Add(1) evaluations1.Add(1)
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
@ -1430,7 +1429,7 @@ func TestMultiplePoliciesSharedParamType(t *testing.T) {
} }
}) })
validator2.RegisterDefinition(&policy2, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator2.RegisterDefinition(&policy2, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
evaluations2.Add(1) evaluations2.Add(1)
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
@ -1540,7 +1539,7 @@ func TestNativeTypeParam(t *testing.T) {
} }
}) })
validator.RegisterDefinition(&nativeTypeParamPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(&nativeTypeParamPolicy, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
evaluations.Add(1) evaluations.Add(1)
if _, ok := versionedParams.(*v1.ConfigMap); ok { if _, ok := versionedParams.(*v1.ConfigMap); ok {
return ValidateResult{ return ValidateResult{
@ -1622,7 +1621,7 @@ func TestAuditValidationAction(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1693,7 +1692,7 @@ func TestWarnValidationAction(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1752,7 +1751,7 @@ func TestAllValidationActions(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1823,7 +1822,7 @@ func TestAuditAnnotations(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
o, err := meta.Accessor(versionedParams) o, err := meta.Accessor(versionedParams)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View File

@ -41,7 +41,6 @@ import (
"k8s.io/apiserver/pkg/admission/plugin/cel" "k8s.io/apiserver/pkg/admission/plugin/cel"
"k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/internal/generic" "k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/internal/generic"
"k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/matching" "k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/matching"
whgeneric "k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
celconfig "k8s.io/apiserver/pkg/apis/cel" celconfig "k8s.io/apiserver/pkg/apis/cel"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/warning" "k8s.io/apiserver/pkg/warning"
@ -267,7 +266,7 @@ func (c *celAdmissionController) Validate(
// is scoped outside of the param loop so we only convert once. We defer // is scoped outside of the param loop so we only convert once. We defer
// conversion so that it is only performed when we know a policy matches, // conversion so that it is only performed when we know a policy matches,
// saving the cost of converting non-matching requests. // saving the cost of converting non-matching requests.
var versionedAttr *whgeneric.VersionedAttributes var versionedAttr *admission.VersionedAttributes
// If definition has paramKind, paramRef is required in binding. // If definition has paramKind, paramRef is required in binding.
// If definition has no paramKind, paramRef set in binding will be ignored. // If definition has no paramKind, paramRef set in binding will be ignored.
@ -320,7 +319,7 @@ func (c *celAdmissionController) Validate(
} }
if versionedAttr == nil { if versionedAttr == nil {
va, err := whgeneric.NewVersionedAttributes(a, matchKind, o) va, err := admission.NewVersionedAttributes(a, matchKind, o)
if err != nil { if err != nil {
wrappedErr := fmt.Errorf("failed to convert object version: %w", err) wrappedErr := fmt.Errorf("failed to convert object version: %w", err)
addConfigError(wrappedErr, definition, binding) addConfigError(wrappedErr, definition, binding)

View File

@ -27,7 +27,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/cel" "k8s.io/apiserver/pkg/admission/plugin/cel"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
) )
var _ cel.ExpressionAccessor = &ValidationCondition{} var _ cel.ExpressionAccessor = &ValidationCondition{}
@ -86,5 +85,5 @@ type ValidateResult struct {
type Validator interface { type Validator interface {
// Validate is used to take cel evaluations and convert into decisions // Validate is used to take cel evaluations and convert into decisions
// runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input. // runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input.
Validate(ctx context.Context, versionedAttr *generic.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult Validate(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult
} }

View File

@ -28,8 +28,8 @@ import (
v1 "k8s.io/api/admissionregistration/v1" v1 "k8s.io/api/admissionregistration/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/cel" "k8s.io/apiserver/pkg/admission/plugin/cel"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
) )
@ -66,7 +66,7 @@ func auditAnnotationEvaluationForError(f v1.FailurePolicyType) PolicyAuditAnnota
// Validate takes a list of Evaluation and a failure policy and converts them into actionable PolicyDecisions // Validate takes a list of Evaluation and a failure policy and converts them into actionable PolicyDecisions
// runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input. // runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input.
func (v *validator) Validate(ctx context.Context, versionedAttr *generic.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { func (v *validator) Validate(ctx context.Context, versionedAttr *admission.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
var f v1.FailurePolicyType var f v1.FailurePolicyType
if v.failPolicy == nil { if v.failPolicy == nil {
f = v1.Fail f = v1.Fail

View File

@ -33,7 +33,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/cel" "k8s.io/apiserver/pkg/admission/plugin/cel"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
celconfig "k8s.io/apiserver/pkg/apis/cel" celconfig "k8s.io/apiserver/pkg/apis/cel"
) )
@ -44,7 +43,7 @@ type fakeCelFilter struct {
throwError bool throwError bool
} }
func (f *fakeCelFilter) ForInput(context.Context, *generic.VersionedAttributes, *admissionv1.AdmissionRequest, cel.OptionalVariableBindings, int64) ([]cel.EvaluationResult, error) { func (f *fakeCelFilter) ForInput(context.Context, *admission.VersionedAttributes, *admissionv1.AdmissionRequest, cel.OptionalVariableBindings, int64) ([]cel.EvaluationResult, error) {
if f.throwError { if f.throwError {
return nil, errors.New("test error") return nil, errors.New("test error")
} }
@ -63,7 +62,7 @@ func TestValidate(t *testing.T) {
unauthorizedReason := metav1.StatusReasonUnauthorized unauthorizedReason := metav1.StatusReasonUnauthorized
fakeAttr := admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "default", "foo", schema.GroupVersionResource{}, "", admission.Create, nil, false, nil) fakeAttr := admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "default", "foo", schema.GroupVersionResource{}, "", admission.Create, nil, false, nil)
fakeVersionedAttr, _ := generic.NewVersionedAttributes(fakeAttr, schema.GroupVersionKind{}, nil) fakeVersionedAttr, _ := admission.NewVersionedAttributes(fakeAttr, schema.GroupVersionKind{}, nil)
cases := []struct { cases := []struct {
name string name string
@ -625,7 +624,7 @@ func TestContextCanceled(t *testing.T) {
fail := v1.Fail fail := v1.Fail
fakeAttr := admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "default", "foo", schema.GroupVersionResource{}, "", admission.Create, nil, false, nil) fakeAttr := admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "default", "foo", schema.GroupVersionResource{}, "", admission.Create, nil, false, nil)
fakeVersionedAttr, _ := generic.NewVersionedAttributes(fakeAttr, schema.GroupVersionKind{}, nil) fakeVersionedAttr, _ := admission.NewVersionedAttributes(fakeAttr, schema.GroupVersionKind{}, nil)
fc := cel.NewFilterCompiler() fc := cel.NewFilterCompiler()
f := fc.Compile([]cel.ExpressionAccessor{&ValidationCondition{Expression: "[1,2,3,4,5,6,7,8,9,10].map(x, [1,2,3,4,5,6,7,8,9,10].map(y, x*y)) == []"}}, cel.OptionalVariableDeclarations{HasParams: false, HasAuthorizer: false}, celconfig.PerCallLimit) f := fc.Compile([]cel.ExpressionAccessor{&ValidationCondition{Expression: "[1,2,3,4,5,6,7,8,9,10].map(x, [1,2,3,4,5,6,7,8,9,10].map(y, x*y)) == []"}}, cel.OptionalVariableDeclarations{HasParams: false, HasAuthorizer: false}, celconfig.PerCallLimit)
v := validator{ v := validator{

View File

@ -19,7 +19,6 @@ package generic
import ( import (
"context" "context"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/webhook" "k8s.io/apiserver/pkg/admission/plugin/webhook"
@ -31,31 +30,6 @@ type Source interface {
HasSynced() bool HasSynced() bool
} }
// VersionedAttributes is a wrapper around the original admission attributes, adding versioned
// variants of the object and old object.
type VersionedAttributes struct {
// Attributes holds the original admission attributes
admission.Attributes
// VersionedOldObject holds Attributes.OldObject (if non-nil), converted to VersionedKind.
// It must never be mutated.
VersionedOldObject runtime.Object
// VersionedObject holds Attributes.Object (if non-nil), converted to VersionedKind.
// If mutated, Dirty must be set to true by the mutator.
VersionedObject runtime.Object
// VersionedKind holds the fully qualified kind
VersionedKind schema.GroupVersionKind
// Dirty indicates VersionedObject has been modified since being converted from Attributes.Object
Dirty bool
}
// GetObject overrides the Attributes.GetObject()
func (v *VersionedAttributes) GetObject() runtime.Object {
if v.VersionedObject != nil {
return v.VersionedObject
}
return v.Attributes.GetObject()
}
// WebhookInvocation describes how to call a webhook, including the resource and subresource the webhook registered for, // WebhookInvocation describes how to call a webhook, including the resource and subresource the webhook registered for,
// and the kind that should be sent to the webhook. // and the kind that should be sent to the webhook.
type WebhookInvocation struct { type WebhookInvocation struct {

View File

@ -95,7 +95,7 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr admission.Attrib
defer func() { defer func() {
webhookReinvokeCtx.SetLastWebhookInvocationOutput(attr.GetObject()) webhookReinvokeCtx.SetLastWebhookInvocationOutput(attr.GetObject())
}() }()
var versionedAttr *generic.VersionedAttributes var versionedAttr *admission.VersionedAttributes
for i, hook := range hooks { for i, hook := range hooks {
attrForCheck := attr attrForCheck := attr
if versionedAttr != nil { if versionedAttr != nil {
@ -124,12 +124,12 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr admission.Attrib
if versionedAttr == nil { if versionedAttr == nil {
// First webhook, create versioned attributes // First webhook, create versioned attributes
var err error var err error
if versionedAttr, err = generic.NewVersionedAttributes(attr, invocation.Kind, o); err != nil { if versionedAttr, err = admission.NewVersionedAttributes(attr, invocation.Kind, o); err != nil {
return apierrors.NewInternalError(err) return apierrors.NewInternalError(err)
} }
} else { } else {
// Subsequent webhook, convert existing versioned attributes to this webhook's version // Subsequent webhook, convert existing versioned attributes to this webhook's version
if err := generic.ConvertVersionedAttributes(versionedAttr, invocation.Kind, o); err != nil { if err := admission.ConvertVersionedAttributes(versionedAttr, invocation.Kind, o); err != nil {
return apierrors.NewInternalError(err) return apierrors.NewInternalError(err)
} }
} }
@ -212,7 +212,7 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr admission.Attrib
// note that callAttrMutatingHook updates attr // note that callAttrMutatingHook updates attr
func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *admissionregistrationv1.MutatingWebhook, invocation *generic.WebhookInvocation, attr *generic.VersionedAttributes, annotator *webhookAnnotator, o admission.ObjectInterfaces, round, idx int) (bool, error) { func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *admissionregistrationv1.MutatingWebhook, invocation *generic.WebhookInvocation, attr *admission.VersionedAttributes, annotator *webhookAnnotator, o admission.ObjectInterfaces, round, idx int) (bool, error) {
configurationName := invocation.Webhook.GetConfigurationName() configurationName := invocation.Webhook.GetConfigurationName()
changed := false changed := false
defer func() { annotator.addMutationAnnotation(changed) }() defer func() { annotator.addMutationAnnotation(changed) }()
@ -363,7 +363,7 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *admiss
} }
type webhookAnnotator struct { type webhookAnnotator struct {
attr *generic.VersionedAttributes attr *admission.VersionedAttributes
failedOpenAnnotationKey string failedOpenAnnotationKey string
patchAnnotationKey string patchAnnotationKey string
mutationAnnotationKey string mutationAnnotationKey string
@ -371,7 +371,7 @@ type webhookAnnotator struct {
configuration string configuration string
} }
func newWebhookAnnotator(attr *generic.VersionedAttributes, round, idx int, webhook, configuration string) *webhookAnnotator { func newWebhookAnnotator(attr *admission.VersionedAttributes, round, idx int, webhook, configuration string) *webhookAnnotator {
return &webhookAnnotator{ return &webhookAnnotator{
attr: attr, attr: attr,
failedOpenAnnotationKey: fmt.Sprintf("%sround_%d_index_%d", MutationAuditAnnotationFailedOpenKeyPrefix, round, idx), failedOpenAnnotationKey: fmt.Sprintf("%sround_%d_index_%d", MutationAuditAnnotationFailedOpenKeyPrefix, round, idx),

View File

@ -26,6 +26,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic" "k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
) )
@ -130,7 +131,7 @@ func VerifyAdmissionResponse(uid types.UID, mutating bool, review runtime.Object
// CreateAdmissionObjects returns the unique request uid, the AdmissionReview object to send the webhook and to decode the response into, // CreateAdmissionObjects returns the unique request uid, the AdmissionReview object to send the webhook and to decode the response into,
// or an error if the webhook does not support receiving any of the admission review versions we know to send // or an error if the webhook does not support receiving any of the admission review versions we know to send
func CreateAdmissionObjects(versionedAttributes *generic.VersionedAttributes, invocation *generic.WebhookInvocation) (uid types.UID, request, response runtime.Object, err error) { func CreateAdmissionObjects(versionedAttributes *admission.VersionedAttributes, invocation *generic.WebhookInvocation) (uid types.UID, request, response runtime.Object, err error) {
for _, version := range invocation.Webhook.GetAdmissionReviewVersions() { for _, version := range invocation.Webhook.GetAdmissionReviewVersions() {
switch version { switch version {
case admissionv1.SchemeGroupVersion.Version: case admissionv1.SchemeGroupVersion.Version:
@ -151,7 +152,7 @@ func CreateAdmissionObjects(versionedAttributes *generic.VersionedAttributes, in
} }
// CreateV1AdmissionReview creates an AdmissionReview for the provided admission.Attributes // CreateV1AdmissionReview creates an AdmissionReview for the provided admission.Attributes
func CreateV1AdmissionReview(uid types.UID, versionedAttributes *generic.VersionedAttributes, invocation *generic.WebhookInvocation) *admissionv1.AdmissionReview { func CreateV1AdmissionReview(uid types.UID, versionedAttributes *admission.VersionedAttributes, invocation *generic.WebhookInvocation) *admissionv1.AdmissionReview {
attr := versionedAttributes.Attributes attr := versionedAttributes.Attributes
gvk := invocation.Kind gvk := invocation.Kind
gvr := invocation.Resource gvr := invocation.Resource
@ -217,7 +218,7 @@ func CreateV1AdmissionReview(uid types.UID, versionedAttributes *generic.Version
} }
// CreateV1beta1AdmissionReview creates an AdmissionReview for the provided admission.Attributes // CreateV1beta1AdmissionReview creates an AdmissionReview for the provided admission.Attributes
func CreateV1beta1AdmissionReview(uid types.UID, versionedAttributes *generic.VersionedAttributes, invocation *generic.WebhookInvocation) *admissionv1beta1.AdmissionReview { func CreateV1beta1AdmissionReview(uid types.UID, versionedAttributes *admission.VersionedAttributes, invocation *generic.WebhookInvocation) *admissionv1beta1.AdmissionReview {
attr := versionedAttributes.Attributes attr := versionedAttributes.Attributes
gvk := invocation.Kind gvk := invocation.Kind
gvr := invocation.Resource gvr := invocation.Resource

View File

@ -476,7 +476,7 @@ func TestCreateAdmissionObjects(t *testing.T) {
testcases := []struct { testcases := []struct {
name string name string
attrs *generic.VersionedAttributes attrs *admission.VersionedAttributes
invocation *generic.WebhookInvocation invocation *generic.WebhookInvocation
expectRequest func(uid types.UID) runtime.Object expectRequest func(uid types.UID) runtime.Object
@ -501,7 +501,7 @@ func TestCreateAdmissionObjects(t *testing.T) {
}, },
{ {
name: "v1", name: "v1",
attrs: &generic.VersionedAttributes{ attrs: &admission.VersionedAttributes{
VersionedObject: versionedObj.DeepCopyObject(), VersionedObject: versionedObj.DeepCopyObject(),
VersionedOldObject: versionedObjOld.DeepCopyObject(), VersionedOldObject: versionedObjOld.DeepCopyObject(),
Attributes: attrs, Attributes: attrs,
@ -544,7 +544,7 @@ func TestCreateAdmissionObjects(t *testing.T) {
}, },
{ {
name: "v1beta1", name: "v1beta1",
attrs: &generic.VersionedAttributes{ attrs: &admission.VersionedAttributes{
VersionedObject: versionedObj.DeepCopyObject(), VersionedObject: versionedObj.DeepCopyObject(),
VersionedOldObject: versionedObjOld.DeepCopyObject(), VersionedOldObject: versionedObjOld.DeepCopyObject(),
Attributes: attrs, Attributes: attrs,

View File

@ -67,7 +67,7 @@ var _ generic.Dispatcher = &validatingDispatcher{}
func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attributes, o admission.ObjectInterfaces, hooks []webhook.WebhookAccessor) error { func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attributes, o admission.ObjectInterfaces, hooks []webhook.WebhookAccessor) error {
var relevantHooks []*generic.WebhookInvocation var relevantHooks []*generic.WebhookInvocation
// Construct all the versions we need to call our webhooks // Construct all the versions we need to call our webhooks
versionedAttrs := map[schema.GroupVersionKind]*generic.VersionedAttributes{} versionedAttrs := map[schema.GroupVersionKind]*admission.VersionedAttributes{}
for _, hook := range hooks { for _, hook := range hooks {
invocation, statusError := d.plugin.ShouldCallHook(hook, attr, o) invocation, statusError := d.plugin.ShouldCallHook(hook, attr, o)
if statusError != nil { if statusError != nil {
@ -81,7 +81,7 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attr
if _, ok := versionedAttrs[invocation.Kind]; ok { if _, ok := versionedAttrs[invocation.Kind]; ok {
continue continue
} }
versionedAttr, err := generic.NewVersionedAttributes(attr, invocation.Kind, o) versionedAttr, err := admission.NewVersionedAttributes(attr, invocation.Kind, o)
if err != nil { if err != nil {
return apierrors.NewInternalError(err) return apierrors.NewInternalError(err)
} }
@ -215,7 +215,7 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attr
return errs[0] return errs[0]
} }
func (d *validatingDispatcher) callHook(ctx context.Context, h *v1.ValidatingWebhook, invocation *generic.WebhookInvocation, attr *generic.VersionedAttributes) error { func (d *validatingDispatcher) callHook(ctx context.Context, h *v1.ValidatingWebhook, invocation *generic.WebhookInvocation, attr *admission.VersionedAttributes) error {
if attr.Attributes.IsDryRun() { if attr.Attributes.IsDryRun() {
if h.SideEffects == nil { if h.SideEffects == nil {
return &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook SideEffects is nil"), Status: apierrors.NewBadRequest("Webhook SideEffects is nil")} return &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook SideEffects is nil"), Status: apierrors.NewBadRequest("Webhook SideEffects is nil")}