From 140c8c73a64deb102b528109138ca9fb7dbb2392 Mon Sep 17 00:00:00 2001 From: Joe Betz Date: Tue, 7 May 2019 13:34:18 -0700 Subject: [PATCH 1/3] Pass {Operation}Option to Webhooks --- pkg/apis/admission/types.go | 10 ++- .../src/k8s.io/api/admission/v1beta1/types.go | 10 ++- .../pkg/apis/apiextensions/v1beta1/types.go | 2 +- .../apiserver/pkg/admission/attributes.go | 8 +- .../apiserver/pkg/admission/interfaces.go | 2 + .../plugin/webhook/request/admissionreview.go | 3 + .../apiserver/pkg/endpoints/handlers/BUILD | 1 + .../pkg/endpoints/handlers/create.go | 3 +- .../pkg/endpoints/handlers/delete.go | 8 +- .../apiserver/pkg/endpoints/handlers/patch.go | 51 +++++++---- .../apiserver/pkg/endpoints/handlers/rest.go | 4 +- .../pkg/endpoints/handlers/rest_test.go | 90 ++++++++++++++++++- .../pkg/endpoints/handlers/update.go | 22 ++++- .../apiserver/pkg/registry/rest/create.go | 1 + .../apiserver/pkg/registry/rest/update.go | 1 + 15 files changed, 186 insertions(+), 30 deletions(-) diff --git a/pkg/apis/admission/types.go b/pkg/apis/admission/types.go index fb704abdf90..f874013e398 100644 --- a/pkg/apis/admission/types.go +++ b/pkg/apis/admission/types.go @@ -63,7 +63,8 @@ type AdmissionRequest struct { // Namespace is the namespace associated with the request (if any). // +optional Namespace string - // Operation is the operation being performed + // Operation is the operation being performed. This may be different than the operation + // requested. e.g. a patch can result in either a CREATE or UPDATE Operation. Operation Operation // UserInfo is information about the requesting user UserInfo authentication.UserInfo @@ -78,6 +79,13 @@ type AdmissionRequest struct { // Defaults to false. // +optional DryRun *bool + // Options is the operation option structure of the operation being performed. + // e.g. `meta.k8s.io/v1.DeleteOptions` or `meta.k8s.io/v1.CreateOptions`. This may be + // different than the options the caller provided. e.g. for a patch request the performed + // Operation might be a CREATE, in which case the Options will a + // `meta.k8s.io/v1.CreateOptions` even though the caller provided `meta.k8s.io/v1.PatchOptions`. + // +optional + Options runtime.Object } // AdmissionResponse describes an admission response. diff --git a/staging/src/k8s.io/api/admission/v1beta1/types.go b/staging/src/k8s.io/api/admission/v1beta1/types.go index 653e847107f..9d2884e66fe 100644 --- a/staging/src/k8s.io/api/admission/v1beta1/types.go +++ b/staging/src/k8s.io/api/admission/v1beta1/types.go @@ -61,7 +61,8 @@ type AdmissionRequest struct { // Namespace is the namespace associated with the request (if any). // +optional Namespace string `json:"namespace,omitempty" protobuf:"bytes,6,opt,name=namespace"` - // Operation is the operation being performed + // Operation is the operation being performed. This may be different than the operation + // requested. e.g. a patch can result in either a CREATE or UPDATE Operation. Operation Operation `json:"operation" protobuf:"bytes,7,opt,name=operation"` // UserInfo is information about the requesting user UserInfo authenticationv1.UserInfo `json:"userInfo" protobuf:"bytes,8,opt,name=userInfo"` @@ -75,6 +76,13 @@ type AdmissionRequest struct { // Defaults to false. // +optional DryRun *bool `json:"dryRun,omitempty" protobuf:"varint,11,opt,name=dryRun"` + // Options is the operation option structure of the operation being performed. + // e.g. `meta.k8s.io/v1.DeleteOptions` or `meta.k8s.io/v1.CreateOptions`. This may be + // different than the options the caller provided. e.g. for a patch request the performed + // Operation might be a CREATE, in which case the Options will a + // `meta.k8s.io/v1.CreateOptions` even though the caller provided `meta.k8s.io/v1.PatchOptions`. + // +optional + Options runtime.RawExtension `json:"options,omitempty" protobuf:"bytes,12,opt,name=options"` } // AdmissionResponse describes an admission response. diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go index 220a494bce2..0ca6673bf4a 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go @@ -443,7 +443,7 @@ type ConversionRequest struct { // ConversionResponse describes a conversion response. type ConversionResponse struct { // `uid` is an identifier for the individual request/response. - // This should be copied over from the corresponding AdmissionRequest. + // This should be copied over from the corresponding ConversionRequest. UID types.UID `json:"uid" protobuf:"bytes,1,name=uid"` // `convertedObjects` is the list of converted version of `request.objects` if the `result` is successful otherwise empty. // The webhook is expected to set apiVersion of these objects to the ConversionRequest.desiredAPIVersion. The list diff --git a/staging/src/k8s.io/apiserver/pkg/admission/attributes.go b/staging/src/k8s.io/apiserver/pkg/admission/attributes.go index c8973cc629b..ad6ca6ba6fc 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/attributes.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/attributes.go @@ -34,6 +34,7 @@ type attributesRecord struct { resource schema.GroupVersionResource subresource string operation Operation + options runtime.Object dryRun bool object runtime.Object oldObject runtime.Object @@ -45,7 +46,7 @@ type attributesRecord struct { annotationsLock sync.RWMutex } -func NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind schema.GroupVersionKind, namespace, name string, resource schema.GroupVersionResource, subresource string, operation Operation, dryRun bool, userInfo user.Info) Attributes { +func NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind schema.GroupVersionKind, namespace, name string, resource schema.GroupVersionResource, subresource string, operation Operation, operationOptions runtime.Object, dryRun bool, userInfo user.Info) Attributes { return &attributesRecord{ kind: kind, namespace: namespace, @@ -53,6 +54,7 @@ func NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind s resource: resource, subresource: subresource, operation: operation, + options: operationOptions, dryRun: dryRun, object: object, oldObject: oldObject, @@ -84,6 +86,10 @@ func (record *attributesRecord) GetOperation() Operation { return record.operation } +func (record *attributesRecord) GetOperationOptions() runtime.Object { + return record.options +} + func (record *attributesRecord) IsDryRun() bool { return record.dryRun } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go b/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go index 866777cc708..a8853fdd73e 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go @@ -41,6 +41,8 @@ type Attributes interface { GetSubresource() string // GetOperation is the operation being performed GetOperation() Operation + // GetOperationOptions is the options for the operation being performed + GetOperationOptions() runtime.Object // IsDryRun indicates that modifications will definitely not be persisted for this request. This is to prevent // admission controllers with side effects and a method of reconciliation from being overwhelmed. // However, a value of false for this does not mean that the modification will be persisted, because it diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request/admissionreview.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request/admissionreview.go index cec41315c2b..51a45a36a70 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request/admissionreview.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request/admissionreview.go @@ -68,6 +68,9 @@ func CreateAdmissionReview(attr *generic.VersionedAttributes) admissionv1beta1.A Object: attr.VersionedOldObject, }, DryRun: &dryRun, + Options: runtime.RawExtension{ + Object: attr.GetOperationOptions(), + }, }, } } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/BUILD b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/BUILD index 85695ff8635..87846313d46 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/BUILD @@ -27,6 +27,7 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/json:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go index 40c53efae33..d4a31b7e7e2 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go @@ -106,6 +106,7 @@ func createHandler(r rest.NamedCreater, scope *RequestScope, admit admission.Int scope.err(err, w, req) return } + options.TypeMeta.SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("CreateOptions")) defaultGVK := scope.Kind original := r.New() @@ -128,7 +129,7 @@ func createHandler(r rest.NamedCreater, scope *RequestScope, admit admission.Int audit.LogRequestObject(ae, obj, scope.Resource, scope.Subresource, scope.Serializer) userInfo, _ := request.UserFrom(ctx) - admissionAttributes := admission.NewAttributesRecord(obj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, dryrun.IsDryRun(options.DryRun), userInfo) + admissionAttributes := admission.NewAttributesRecord(obj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, options, dryrun.IsDryRun(options.DryRun), userInfo) if mutatingAdmission, ok := admit.(admission.MutationInterface); ok && mutatingAdmission.Handles(admission.Create) { err = mutatingAdmission.Admit(admissionAttributes, scope) if err != nil { diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go index 8f1d1d21793..7375c575eba 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go @@ -113,11 +113,12 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope *RequestSc scope.err(err, w, req) return } + options.TypeMeta.SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("DeleteOptions")) trace.Step("About to check admission control") if admit != nil && admit.Handles(admission.Delete) { userInfo, _ := request.UserFrom(ctx) - attrs := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Delete, dryrun.IsDryRun(options.DryRun), userInfo) + attrs := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Delete, options, dryrun.IsDryRun(options.DryRun), userInfo) if mutatingAdmission, ok := admit.(admission.MutationInterface); ok { if err := mutatingAdmission.Admit(attrs, scope); err != nil { scope.err(err, w, req) @@ -236,6 +237,8 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope *RequestSc scope.err(err, w, req) return } + // For backwards compatibility, we need to allow existing clients to submit per group DeleteOptions + // It is also allowed to pass a body with meta.k8s.io/v1.DeleteOptions defaultGVK := scope.Kind.GroupVersion().WithKind("DeleteOptions") obj, _, err := scope.Serializer.DecoderToVersion(s.Serializer, defaultGVK.GroupVersion()).Decode(body, &defaultGVK, options) if err != nil { @@ -262,11 +265,12 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope *RequestSc scope.err(err, w, req) return } + options.TypeMeta.SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("DeleteOptions")) admit = admission.WithAudit(admit, ae) if admit != nil && admit.Handles(admission.Delete) { userInfo, _ := request.UserFrom(ctx) - attrs := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, "", scope.Resource, scope.Subresource, admission.Delete, dryrun.IsDryRun(options.DryRun), userInfo) + attrs := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, "", scope.Resource, scope.Subresource, admission.Delete, options, dryrun.IsDryRun(options.DryRun), userInfo) if mutatingAdmission, ok := admit.(admission.MutationInterface); ok { err = mutatingAdmission.Admit(attrs, scope) if err != nil { diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go index 23644bd3409..c33f181661a 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go @@ -23,7 +23,7 @@ import ( "strings" "time" - "github.com/evanphx/json-patch" + jsonpatch "github.com/evanphx/json-patch" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" @@ -118,6 +118,7 @@ func PatchResource(r rest.Patcher, scope *RequestScope, admit admission.Interfac scope.err(err, w, req) return } + options.TypeMeta.SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("PatchOptions")) ae := request.AuditEventFrom(ctx) admit = admission.WithAudit(admit, ae) @@ -151,6 +152,7 @@ func PatchResource(r rest.Patcher, scope *RequestScope, admit admission.Interfac scope.Resource, scope.Subresource, admission.Create, + patchToCreateOptions(options), dryrun.IsDryRun(options.DryRun), userInfo) staticUpdateAttributes := admission.NewAttributesRecord( @@ -162,6 +164,7 @@ func PatchResource(r rest.Patcher, scope *RequestScope, admit admission.Interfac scope.Resource, scope.Subresource, admission.Update, + patchToUpdateOptions(options), dryrun.IsDryRun(options.DryRun), userInfo, ) @@ -489,9 +492,9 @@ func (p *patcher) applyPatch(_ context.Context, _, currentObject runtime.Object) return objToUpdate, nil } -func (p *patcher) admissionAttributes(ctx context.Context, updatedObject runtime.Object, currentObject runtime.Object, operation admission.Operation) admission.Attributes { +func (p *patcher) admissionAttributes(ctx context.Context, updatedObject runtime.Object, currentObject runtime.Object, operation admission.Operation, operationOptions runtime.Object) admission.Attributes { userInfo, _ := request.UserFrom(ctx) - return admission.NewAttributesRecord(updatedObject, currentObject, p.kind, p.namespace, p.name, p.resource, p.subresource, operation, p.dryRun, userInfo) + return admission.NewAttributesRecord(updatedObject, currentObject, p.kind, p.namespace, p.name, p.resource, p.subresource, operation, operationOptions, p.dryRun, userInfo) } // applyAdmission is called every time GuaranteedUpdate asks for the updated object, @@ -500,16 +503,19 @@ func (p *patcher) admissionAttributes(ctx context.Context, updatedObject runtime func (p *patcher) applyAdmission(ctx context.Context, patchedObject runtime.Object, currentObject runtime.Object) (runtime.Object, error) { p.trace.Step("About to check admission control") var operation admission.Operation + var options runtime.Object if hasUID, err := hasUID(currentObject); err != nil { return nil, err } else if !hasUID { operation = admission.Create currentObject = nil + options = patchToCreateOptions(p.options) } else { operation = admission.Update + options = patchToUpdateOptions(p.options) } if p.admissionCheck != nil && p.admissionCheck.Handles(operation) { - attributes := p.admissionAttributes(ctx, patchedObject, currentObject, operation) + attributes := p.admissionAttributes(ctx, patchedObject, currentObject, operation, options) return patchedObject, p.admissionCheck.Admit(attributes, p.objectInterfaces) } return patchedObject, nil @@ -551,11 +557,8 @@ func (p *patcher) patchResource(ctx context.Context, scope *RequestScope) (runti wasCreated := false p.updatedObjectInfo = rest.DefaultUpdatedObjectInfo(nil, p.applyPatch, p.applyAdmission) result, err := finishRequest(p.timeout, func() (runtime.Object, error) { - // TODO: Pass in UpdateOptions to override UpdateStrategy.AllowUpdateOnCreate - options, err := patchToUpdateOptions(p.options) - if err != nil { - return nil, err - } + // Pass in UpdateOptions to override UpdateStrategy.AllowUpdateOnCreate + options := patchToUpdateOptions(p.options) updateObject, created, updateErr := p.restPatcher.Update(ctx, p.name, p.updatedObjectInfo, p.createValidation, p.updateValidation, p.forceAllowCreate, options) wasCreated = created return updateObject, updateErr @@ -600,12 +603,28 @@ func interpretStrategicMergePatchError(err error) error { } } -func patchToUpdateOptions(po *metav1.PatchOptions) (*metav1.UpdateOptions, error) { - b, err := json.Marshal(po) - if err != nil { - return nil, err +// patchToUpdateOptions creates an UpdateOptions with the same field values as the provided PatchOptions. +func patchToUpdateOptions(po *metav1.PatchOptions) *metav1.UpdateOptions { + if po == nil { + return nil } - uo := metav1.UpdateOptions{} - err = json.Unmarshal(b, &uo) - return &uo, err + uo := &metav1.UpdateOptions{ + DryRun: po.DryRun, + FieldManager: po.FieldManager, + } + uo.TypeMeta.SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("UpdateOptions")) + return uo +} + +// patchToCreateOptions creates an CreateOptions with the same field values as the provided PatchOptions. +func patchToCreateOptions(po *metav1.PatchOptions) *metav1.CreateOptions { + if po == nil { + return nil + } + co := &metav1.CreateOptions{ + DryRun: po.DryRun, + FieldManager: po.FieldManager, + } + co.TypeMeta.SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("CreateOptions")) + return co } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go index 4db0c067627..cc82a8df8d0 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go @@ -137,14 +137,14 @@ func ConnectResource(connecter rest.Connecter, scope *RequestScope, admit admiss userInfo, _ := request.UserFrom(ctx) // TODO: remove the mutating admission here as soon as we have ported all plugin that handle CONNECT if mutatingAdmission, ok := admit.(admission.MutationInterface); ok { - err = mutatingAdmission.Admit(admission.NewAttributesRecord(opts, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, false, userInfo), scope) + err = mutatingAdmission.Admit(admission.NewAttributesRecord(opts, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, nil, false, userInfo), scope) if err != nil { scope.err(err, w, req) return } } if validatingAdmission, ok := admit.(admission.ValidationInterface); ok { - err = validatingAdmission.Validate(admission.NewAttributesRecord(opts, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, false, userInfo), scope) + err = validatingAdmission.Validate(admission.NewAttributesRecord(opts, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, nil, false, userInfo), scope) if err != nil { scope.err(err, w, req) return diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go index 2c9dab5b94e..4c33f05e79d 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go @@ -26,7 +26,8 @@ import ( "testing" "time" - "github.com/evanphx/json-patch" + jsonpatch "github.com/evanphx/json-patch" + fuzz "github.com/google/gofuzz" apiequality "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -37,6 +38,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/diff" + "k8s.io/apimachinery/pkg/util/json" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apiserver/pkg/admission" @@ -1000,3 +1002,89 @@ func (alwaysErrorTyper) ObjectKinds(runtime.Object) ([]schema.GroupVersionKind, func (alwaysErrorTyper) Recognizes(gvk schema.GroupVersionKind) bool { return false } + +func TestUpdateToCreateOptions(t *testing.T) { + f := fuzz.New() + for i := 0; i < 100; i++ { + t.Run(fmt.Sprintf("Run %d/100", i), func(t *testing.T) { + update := &metav1.UpdateOptions{} + f.Fuzz(update) + create := updateToCreateOptions(update) + + b, err := json.Marshal(create) + if err != nil { + t.Fatalf("failed to marshal CreateOptions (%v): %v", err, create) + } + got := &metav1.UpdateOptions{} + err = json.Unmarshal(b, &got) + if err != nil { + t.Fatalf("failed to unmarshal UpdateOptions: %v", err) + } + got.TypeMeta = metav1.TypeMeta{} + update.TypeMeta = metav1.TypeMeta{} + if !reflect.DeepEqual(*update, *got) { + t.Fatalf(`updateToCreateOptions round-trip failed: +got: %#+v +want: %#+v`, got, update) + } + + }) + } +} + +func TestPatchToUpdateOptions(t *testing.T) { + tests := []struct { + name string + converterFn func(po *metav1.PatchOptions) interface{} + }{ + { + name: "patchToUpdateOptions", + converterFn: func(patch *metav1.PatchOptions) interface{} { + return patchToUpdateOptions(patch) + }, + }, + { + name: "patchToCreateOptions", + converterFn: func(patch *metav1.PatchOptions) interface{} { + return patchToCreateOptions(patch) + }, + }, + } + + f := fuzz.New() + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + for i := 0; i < 100; i++ { + t.Run(fmt.Sprintf("Run %d/100", i), func(t *testing.T) { + patch := &metav1.PatchOptions{} + f.Fuzz(patch) + converted := test.converterFn(patch) + + b, err := json.Marshal(converted) + if err != nil { + t.Fatalf("failed to marshal converted object (%v): %v", err, converted) + } + got := &metav1.PatchOptions{} + err = json.Unmarshal(b, &got) + if err != nil { + t.Fatalf("failed to unmarshal converted object: %v", err) + } + + // Clear TypeMeta because we expect it to be different between the original and converted type + got.TypeMeta = metav1.TypeMeta{} + patch.TypeMeta = metav1.TypeMeta{} + + // clear fields that we know belong in PatchOptions only + patch.Force = nil + + if !reflect.DeepEqual(*patch, *got) { + t.Fatalf(`round-trip failed: +got: %#+v +want: %#+v`, got, converted) + } + + }) + } + }) + } +} diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go index 4117c0e1683..f3aec87b396 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go @@ -87,6 +87,7 @@ func UpdateResource(r rest.Updater, scope *RequestScope, admit admission.Interfa scope.err(err, w, req) return } + options.TypeMeta.SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("UpdateOptions")) s, err := negotiation.NegotiateInputSerializer(req, false, scope.Serializer) if err != nil { @@ -138,11 +139,11 @@ func UpdateResource(r rest.Updater, scope *RequestScope, admit admission.Interfa return nil, fmt.Errorf("unexpected error when extracting UID from oldObj: %v", err.Error()) } else if !isNotZeroObject { if mutatingAdmission.Handles(admission.Create) { - return newObj, mutatingAdmission.Admit(admission.NewAttributesRecord(newObj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, dryrun.IsDryRun(options.DryRun), userInfo), scope) + return newObj, mutatingAdmission.Admit(admission.NewAttributesRecord(newObj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, updateToCreateOptions(options), dryrun.IsDryRun(options.DryRun), userInfo), scope) } } else { if mutatingAdmission.Handles(admission.Update) { - return newObj, mutatingAdmission.Admit(admission.NewAttributesRecord(newObj, oldObj, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, dryrun.IsDryRun(options.DryRun), userInfo), scope) + return newObj, mutatingAdmission.Admit(admission.NewAttributesRecord(newObj, oldObj, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, options, dryrun.IsDryRun(options.DryRun), userInfo), scope) } } return newObj, nil @@ -172,11 +173,11 @@ func UpdateResource(r rest.Updater, scope *RequestScope, admit admission.Interfa rest.DefaultUpdatedObjectInfo(obj, transformers...), withAuthorization(rest.AdmissionToValidateObjectFunc( admit, - admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, dryrun.IsDryRun(options.DryRun), userInfo), scope), + admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, updateToCreateOptions(options), dryrun.IsDryRun(options.DryRun), userInfo), scope), scope.Authorizer, createAuthorizerAttributes), rest.AdmissionToValidateObjectUpdateFunc( admit, - admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, dryrun.IsDryRun(options.DryRun), userInfo), scope), + admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, options, dryrun.IsDryRun(options.DryRun), userInfo), scope), false, options, ) @@ -229,3 +230,16 @@ func withAuthorization(validate rest.ValidateObjectFunc, a authorizer.Authorizer return errors.NewForbidden(gr, name, err) } } + +// updateToCreateOptions creates a CreateOptions with the same field values as the provided UpdateOptions. +func updateToCreateOptions(uo *metav1.UpdateOptions) *metav1.CreateOptions { + if uo == nil { + return nil + } + co := &metav1.CreateOptions{ + DryRun: uo.DryRun, + FieldManager: uo.FieldManager, + } + co.TypeMeta.SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("CreateOptions")) + return co +} diff --git a/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go b/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go index cc3c9ce4bc5..7750cb7bfd6 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go @@ -175,6 +175,7 @@ func AdmissionToValidateObjectFunc(admit admission.Interface, staticAttributes a staticAttributes.GetResource(), staticAttributes.GetSubresource(), staticAttributes.GetOperation(), + staticAttributes.GetOperationOptions(), staticAttributes.IsDryRun(), staticAttributes.GetUserInfo(), ) diff --git a/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go b/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go index d214e7e6a8f..21719b015eb 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go @@ -271,6 +271,7 @@ func AdmissionToValidateObjectUpdateFunc(admit admission.Interface, staticAttrib staticAttributes.GetResource(), staticAttributes.GetSubresource(), staticAttributes.GetOperation(), + staticAttributes.GetOperationOptions(), staticAttributes.IsDryRun(), staticAttributes.GetUserInfo(), ) From 332d88db1aaddd0b68bfcc62a6a9dc3ce53eed34 Mon Sep 17 00:00:00 2001 From: Joe Betz Date: Tue, 7 May 2019 13:36:44 -0700 Subject: [PATCH 2/3] Generate proto bindings for: Pass {Operation}Option to Webhooks --- .../v1beta1/zz_generated.conversion.go | 6 + pkg/apis/admission/zz_generated.deepcopy.go | 3 + .../api/admission/v1beta1/generated.pb.go | 160 +++++++++++------- .../api/admission/v1beta1/generated.proto | 11 +- .../v1beta1/types_swagger_doc_generated.go | 3 +- .../v1beta1/zz_generated.deepcopy.go | 1 + .../apiextensions/v1beta1/generated.proto | 2 +- 7 files changed, 124 insertions(+), 62 deletions(-) diff --git a/pkg/apis/admission/v1beta1/zz_generated.conversion.go b/pkg/apis/admission/v1beta1/zz_generated.conversion.go index 15dbf75d937..d018d6f5d43 100644 --- a/pkg/apis/admission/v1beta1/zz_generated.conversion.go +++ b/pkg/apis/admission/v1beta1/zz_generated.conversion.go @@ -90,6 +90,9 @@ func autoConvert_v1beta1_AdmissionRequest_To_admission_AdmissionRequest(in *v1be return err } out.DryRun = (*bool)(unsafe.Pointer(in.DryRun)) + if err := runtime.Convert_runtime_RawExtension_To_runtime_Object(&in.Options, &out.Options, s); err != nil { + return err + } return nil } @@ -117,6 +120,9 @@ func autoConvert_admission_AdmissionRequest_To_v1beta1_AdmissionRequest(in *admi return err } out.DryRun = (*bool)(unsafe.Pointer(in.DryRun)) + if err := runtime.Convert_runtime_Object_To_runtime_RawExtension(&in.Options, &out.Options, s); err != nil { + return err + } return nil } diff --git a/pkg/apis/admission/zz_generated.deepcopy.go b/pkg/apis/admission/zz_generated.deepcopy.go index 4c767f0dc7d..b68f0c67c22 100644 --- a/pkg/apis/admission/zz_generated.deepcopy.go +++ b/pkg/apis/admission/zz_generated.deepcopy.go @@ -42,6 +42,9 @@ func (in *AdmissionRequest) DeepCopyInto(out *AdmissionRequest) { *out = new(bool) **out = **in } + if in.Options != nil { + out.Options = in.Options.DeepCopyObject() + } return } diff --git a/staging/src/k8s.io/api/admission/v1beta1/generated.pb.go b/staging/src/k8s.io/api/admission/v1beta1/generated.pb.go index 4082082ff94..2eb7b86a197 100644 --- a/staging/src/k8s.io/api/admission/v1beta1/generated.pb.go +++ b/staging/src/k8s.io/api/admission/v1beta1/generated.pb.go @@ -158,6 +158,14 @@ func (m *AdmissionRequest) MarshalTo(dAtA []byte) (int, error) { } i++ } + dAtA[i] = 0x62 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Options.Size())) + n6, err := m.Options.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n6 return i, nil } @@ -192,11 +200,11 @@ func (m *AdmissionResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Result.Size())) - n6, err := m.Result.MarshalTo(dAtA[i:]) + n7, err := m.Result.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n6 + i += n7 } if m.Patch != nil { dAtA[i] = 0x22 @@ -254,21 +262,21 @@ func (m *AdmissionReview) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Request.Size())) - n7, err := m.Request.MarshalTo(dAtA[i:]) + n8, err := m.Request.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n7 + i += n8 } if m.Response != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Response.Size())) - n8, err := m.Response.MarshalTo(dAtA[i:]) + n9, err := m.Response.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n8 + i += n9 } return i, nil } @@ -308,6 +316,8 @@ func (m *AdmissionRequest) Size() (n int) { if m.DryRun != nil { n += 2 } + l = m.Options.Size() + n += 1 + l + sovGenerated(uint64(l)) return n } @@ -383,6 +393,7 @@ func (this *AdmissionRequest) String() string { `Object:` + strings.Replace(strings.Replace(this.Object.String(), "RawExtension", "k8s_io_apimachinery_pkg_runtime.RawExtension", 1), `&`, ``, 1) + `,`, `OldObject:` + strings.Replace(strings.Replace(this.OldObject.String(), "RawExtension", "k8s_io_apimachinery_pkg_runtime.RawExtension", 1), `&`, ``, 1) + `,`, `DryRun:` + valueToStringGenerated(this.DryRun) + `,`, + `Options:` + strings.Replace(strings.Replace(this.Options.String(), "RawExtension", "k8s_io_apimachinery_pkg_runtime.RawExtension", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -776,6 +787,36 @@ func (m *AdmissionRequest) Unmarshal(dAtA []byte) error { } b := bool(v != 0) m.DryRun = &b + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Options.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -1334,57 +1375,58 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 821 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcf, 0x6f, 0xe3, 0x44, - 0x14, 0x8e, 0x37, 0x69, 0x12, 0x4f, 0x2a, 0x36, 0x3b, 0x80, 0x64, 0x45, 0xc8, 0x09, 0x3d, 0xa0, - 0x20, 0x6d, 0xc7, 0xb4, 0x82, 0x55, 0xb5, 0xe2, 0x12, 0xd3, 0x08, 0x55, 0x48, 0xdb, 0x6a, 0x76, - 0x83, 0x80, 0x03, 0xd2, 0xc4, 0x9e, 0x4d, 0x4c, 0xe2, 0x19, 0xe3, 0x99, 0x49, 0xc9, 0x0d, 0x71, - 0xe5, 0x82, 0xc4, 0x9f, 0xc4, 0xa5, 0xc7, 0x3d, 0xee, 0x29, 0xa2, 0xe1, 0xbf, 0xe8, 0x09, 0x79, - 0x3c, 0x8e, 0x43, 0xba, 0x85, 0x5d, 0xb4, 0x27, 0xfb, 0xfd, 0xf8, 0xbe, 0x37, 0xf3, 0xbd, 0x37, - 0x0f, 0x0c, 0x67, 0x27, 0x02, 0x45, 0xdc, 0x9b, 0xa9, 0x31, 0x4d, 0x19, 0x95, 0x54, 0x78, 0x0b, - 0xca, 0x42, 0x9e, 0x7a, 0x26, 0x40, 0x92, 0xc8, 0x23, 0x61, 0x1c, 0x09, 0x11, 0x71, 0xe6, 0x2d, - 0x8e, 0xc6, 0x54, 0x92, 0x23, 0x6f, 0x42, 0x19, 0x4d, 0x89, 0xa4, 0x21, 0x4a, 0x52, 0x2e, 0x39, - 0xfc, 0x20, 0xcf, 0x46, 0x24, 0x89, 0xd0, 0x26, 0x1b, 0x99, 0xec, 0xce, 0xe1, 0x24, 0x92, 0x53, - 0x35, 0x46, 0x01, 0x8f, 0xbd, 0x09, 0x9f, 0x70, 0x4f, 0x83, 0xc6, 0xea, 0xb9, 0xb6, 0xb4, 0xa1, - 0xff, 0x72, 0xb2, 0xce, 0xc3, 0xed, 0xd2, 0x4a, 0x4e, 0x29, 0x93, 0x51, 0x40, 0x64, 0x5e, 0x7f, - 0xb7, 0x74, 0xe7, 0xd3, 0x32, 0x3b, 0x26, 0xc1, 0x34, 0x62, 0x34, 0x5d, 0x7a, 0xc9, 0x6c, 0x92, - 0x39, 0x84, 0x17, 0x53, 0x49, 0x5e, 0x85, 0xf2, 0xee, 0x42, 0xa5, 0x8a, 0xc9, 0x28, 0xa6, 0xb7, - 0x00, 0x8f, 0xfe, 0x0b, 0x20, 0x82, 0x29, 0x8d, 0xc9, 0x2e, 0xee, 0xe0, 0xf7, 0x3a, 0x68, 0x0f, - 0x0a, 0x45, 0x30, 0xfd, 0x51, 0x51, 0x21, 0xa1, 0x0f, 0xaa, 0x2a, 0x0a, 0x1d, 0xab, 0x67, 0xf5, - 0x6d, 0xff, 0x93, 0xab, 0x55, 0xb7, 0xb2, 0x5e, 0x75, 0xab, 0xa3, 0xb3, 0xd3, 0x9b, 0x55, 0xf7, - 0xc3, 0xbb, 0x0a, 0xc9, 0x65, 0x42, 0x05, 0x1a, 0x9d, 0x9d, 0xe2, 0x0c, 0x0c, 0xbf, 0x01, 0xb5, - 0x59, 0xc4, 0x42, 0xe7, 0x5e, 0xcf, 0xea, 0xb7, 0x8e, 0x1f, 0xa1, 0xb2, 0x03, 0x1b, 0x18, 0x4a, - 0x66, 0x93, 0xcc, 0x21, 0x50, 0x26, 0x03, 0x5a, 0x1c, 0xa1, 0x2f, 0x53, 0xae, 0x92, 0xaf, 0x69, - 0x9a, 0x1d, 0xe6, 0xab, 0x88, 0x85, 0xfe, 0xbe, 0x29, 0x5e, 0xcb, 0x2c, 0xac, 0x19, 0xe1, 0x14, - 0x34, 0x53, 0x2a, 0xb8, 0x4a, 0x03, 0xea, 0x54, 0x35, 0xfb, 0xe3, 0x37, 0x67, 0xc7, 0x86, 0xc1, - 0x6f, 0x9b, 0x0a, 0xcd, 0xc2, 0x83, 0x37, 0xec, 0xf0, 0x33, 0xd0, 0x12, 0x6a, 0x5c, 0x04, 0x9c, - 0x9a, 0xd6, 0xe3, 0x5d, 0x03, 0x68, 0x3d, 0x2d, 0x43, 0x78, 0x3b, 0x0f, 0xf6, 0x40, 0x8d, 0x91, - 0x98, 0x3a, 0x7b, 0x3a, 0x7f, 0x73, 0x85, 0x27, 0x24, 0xa6, 0x58, 0x47, 0xa0, 0x07, 0xec, 0xec, - 0x2b, 0x12, 0x12, 0x50, 0xa7, 0xae, 0xd3, 0x1e, 0x98, 0x34, 0xfb, 0x49, 0x11, 0xc0, 0x65, 0x0e, - 0xfc, 0x1c, 0xd8, 0x3c, 0xc9, 0x1a, 0x17, 0x71, 0xe6, 0x34, 0x34, 0xc0, 0x2d, 0x00, 0xe7, 0x45, - 0xe0, 0x66, 0xdb, 0xc0, 0x25, 0x00, 0x3e, 0x03, 0x4d, 0x25, 0x68, 0x7a, 0xc6, 0x9e, 0x73, 0xa7, - 0xa9, 0x15, 0xfb, 0x08, 0x6d, 0xbf, 0x88, 0x7f, 0x0c, 0x71, 0xa6, 0xd4, 0xc8, 0x64, 0x97, 0xea, - 0x14, 0x1e, 0xbc, 0x61, 0x82, 0x23, 0x50, 0xe7, 0xe3, 0x1f, 0x68, 0x20, 0x1d, 0x5b, 0x73, 0x1e, - 0xde, 0xd9, 0x05, 0x33, 0x83, 0x08, 0x93, 0xcb, 0xe1, 0x4f, 0x92, 0xb2, 0xac, 0x01, 0xfe, 0x3b, - 0x86, 0xba, 0x7e, 0xae, 0x49, 0xb0, 0x21, 0x83, 0xdf, 0x03, 0x9b, 0xcf, 0xc3, 0xdc, 0xe9, 0x80, - 0xff, 0xc3, 0xbc, 0x91, 0xf2, 0xbc, 0xe0, 0xc1, 0x25, 0x25, 0x3c, 0x00, 0xf5, 0x30, 0x5d, 0x62, - 0xc5, 0x9c, 0x56, 0xcf, 0xea, 0x37, 0x7d, 0x90, 0x9d, 0xe1, 0x54, 0x7b, 0xb0, 0x89, 0x1c, 0xfc, - 0x52, 0x03, 0x0f, 0xb6, 0x5e, 0x85, 0x48, 0x38, 0x13, 0xf4, 0xad, 0x3c, 0x8b, 0x8f, 0x41, 0x83, - 0xcc, 0xe7, 0xfc, 0x92, 0xe6, 0x2f, 0xa3, 0xe9, 0xdf, 0x37, 0x3c, 0x8d, 0x41, 0xee, 0xc6, 0x45, - 0x1c, 0x5e, 0x80, 0xba, 0x90, 0x44, 0x2a, 0x61, 0xa6, 0xfc, 0xe1, 0xeb, 0x4d, 0xf9, 0x53, 0x8d, - 0xc9, 0xaf, 0x85, 0xa9, 0x50, 0x73, 0x89, 0x0d, 0x0f, 0xec, 0x82, 0xbd, 0x84, 0xc8, 0x60, 0xaa, - 0x27, 0x79, 0xdf, 0xb7, 0xd7, 0xab, 0xee, 0xde, 0x45, 0xe6, 0xc0, 0xb9, 0x1f, 0x9e, 0x00, 0x5b, - 0xff, 0x3c, 0x5b, 0x26, 0xc5, 0xf8, 0x76, 0x32, 0x21, 0x2f, 0x0a, 0xe7, 0xcd, 0xb6, 0x81, 0xcb, - 0x64, 0xf8, 0xab, 0x05, 0xda, 0x44, 0x85, 0x91, 0x1c, 0x30, 0xc6, 0xa5, 0x1e, 0x24, 0xe1, 0xd4, - 0x7b, 0xd5, 0x7e, 0xeb, 0x78, 0x88, 0xfe, 0x6d, 0xfb, 0xa2, 0x5b, 0x3a, 0xa3, 0xc1, 0x0e, 0xcf, - 0x90, 0xc9, 0x74, 0xe9, 0x3b, 0x46, 0xa8, 0xf6, 0x6e, 0x18, 0xdf, 0x2a, 0xdc, 0xf9, 0x02, 0xbc, - 0xff, 0x4a, 0x12, 0xd8, 0x06, 0xd5, 0x19, 0x5d, 0xe6, 0x2d, 0xc4, 0xd9, 0x2f, 0x7c, 0x0f, 0xec, - 0x2d, 0xc8, 0x5c, 0x51, 0xdd, 0x0e, 0x1b, 0xe7, 0xc6, 0xe3, 0x7b, 0x27, 0xd6, 0xc1, 0x1f, 0x16, - 0xb8, 0xbf, 0x75, 0xb8, 0x45, 0x44, 0x2f, 0xe1, 0x08, 0x34, 0xd2, 0x7c, 0x49, 0x6a, 0x8e, 0xd6, - 0x31, 0x7a, 0xed, 0xcb, 0x69, 0x94, 0xdf, 0xca, 0x5a, 0x6d, 0x0c, 0x5c, 0x70, 0xc1, 0x6f, 0xf5, - 0x4a, 0xd3, 0xb7, 0x37, 0x0b, 0xd3, 0x7b, 0x43, 0xd1, 0xfc, 0x7d, 0xb3, 0xc3, 0xb4, 0x85, 0x37, - 0x74, 0xfe, 0xe1, 0xd5, 0xb5, 0x5b, 0x79, 0x71, 0xed, 0x56, 0x5e, 0x5e, 0xbb, 0x95, 0x9f, 0xd7, - 0xae, 0x75, 0xb5, 0x76, 0xad, 0x17, 0x6b, 0xd7, 0x7a, 0xb9, 0x76, 0xad, 0x3f, 0xd7, 0xae, 0xf5, - 0xdb, 0x5f, 0x6e, 0xe5, 0xbb, 0x86, 0x21, 0xfe, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xf4, 0xc2, 0x6f, - 0x1b, 0x71, 0x07, 0x00, 0x00, + // 840 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcf, 0x6f, 0x1b, 0x45, + 0x14, 0xf6, 0xd6, 0x8e, 0xed, 0x1d, 0x47, 0xd4, 0x1d, 0x40, 0x5a, 0x59, 0x68, 0x6d, 0x72, 0x40, + 0x41, 0x6a, 0x66, 0x49, 0x04, 0x55, 0x54, 0x71, 0xc9, 0x92, 0x08, 0x45, 0x48, 0x4d, 0x34, 0xad, + 0x51, 0xe1, 0x80, 0x34, 0xde, 0x9d, 0xda, 0x8b, 0xbd, 0x33, 0xcb, 0xce, 0x8c, 0x83, 0x6f, 0x88, + 0x2b, 0x17, 0xfe, 0x27, 0x2e, 0x39, 0xf6, 0xd8, 0x53, 0x44, 0xcc, 0x99, 0x7f, 0x20, 0x27, 0x34, + 0xb3, 0xb3, 0x5e, 0x93, 0x34, 0xd0, 0x46, 0x3d, 0xed, 0xbc, 0x1f, 0xdf, 0xf7, 0xde, 0x7c, 0x6f, + 0xdf, 0x80, 0xa3, 0xe9, 0xbe, 0x40, 0x09, 0x0f, 0xa6, 0x6a, 0x44, 0x73, 0x46, 0x25, 0x15, 0xc1, + 0x9c, 0xb2, 0x98, 0xe7, 0x81, 0x0d, 0x90, 0x2c, 0x09, 0x48, 0x9c, 0x26, 0x42, 0x24, 0x9c, 0x05, + 0xf3, 0xdd, 0x11, 0x95, 0x64, 0x37, 0x18, 0x53, 0x46, 0x73, 0x22, 0x69, 0x8c, 0xb2, 0x9c, 0x4b, + 0x0e, 0x3f, 0x2a, 0xb2, 0x11, 0xc9, 0x12, 0xb4, 0xca, 0x46, 0x36, 0xbb, 0xb7, 0x33, 0x4e, 0xe4, + 0x44, 0x8d, 0x50, 0xc4, 0xd3, 0x60, 0xcc, 0xc7, 0x3c, 0x30, 0xa0, 0x91, 0x7a, 0x61, 0x2c, 0x63, + 0x98, 0x53, 0x41, 0xd6, 0x7b, 0xb8, 0x5e, 0x5a, 0xc9, 0x09, 0x65, 0x32, 0x89, 0x88, 0x2c, 0xea, + 0x5f, 0x2f, 0xdd, 0xfb, 0xbc, 0xca, 0x4e, 0x49, 0x34, 0x49, 0x18, 0xcd, 0x17, 0x41, 0x36, 0x1d, + 0x6b, 0x87, 0x08, 0x52, 0x2a, 0xc9, 0xeb, 0x50, 0xc1, 0x6d, 0xa8, 0x5c, 0x31, 0x99, 0xa4, 0xf4, + 0x06, 0xe0, 0xd1, 0xff, 0x01, 0x44, 0x34, 0xa1, 0x29, 0xb9, 0x8e, 0xdb, 0xfa, 0xbb, 0x09, 0xba, + 0x07, 0xa5, 0x22, 0x98, 0xfe, 0xa4, 0xa8, 0x90, 0x30, 0x04, 0x75, 0x95, 0xc4, 0x9e, 0x33, 0x70, + 0xb6, 0xdd, 0xf0, 0xb3, 0xf3, 0x8b, 0x7e, 0x6d, 0x79, 0xd1, 0xaf, 0x0f, 0x8f, 0x0f, 0xaf, 0x2e, + 0xfa, 0x1f, 0xdf, 0x56, 0x48, 0x2e, 0x32, 0x2a, 0xd0, 0xf0, 0xf8, 0x10, 0x6b, 0x30, 0x7c, 0x0e, + 0x1a, 0xd3, 0x84, 0xc5, 0xde, 0xbd, 0x81, 0xb3, 0xdd, 0xd9, 0x7b, 0x84, 0xaa, 0x09, 0xac, 0x60, + 0x28, 0x9b, 0x8e, 0xb5, 0x43, 0x20, 0x2d, 0x03, 0x9a, 0xef, 0xa2, 0xaf, 0x73, 0xae, 0xb2, 0x6f, + 0x69, 0xae, 0x9b, 0xf9, 0x26, 0x61, 0x71, 0xb8, 0x69, 0x8b, 0x37, 0xb4, 0x85, 0x0d, 0x23, 0x9c, + 0x80, 0x76, 0x4e, 0x05, 0x57, 0x79, 0x44, 0xbd, 0xba, 0x61, 0x7f, 0xfc, 0xf6, 0xec, 0xd8, 0x32, + 0x84, 0x5d, 0x5b, 0xa1, 0x5d, 0x7a, 0xf0, 0x8a, 0x1d, 0x7e, 0x01, 0x3a, 0x42, 0x8d, 0xca, 0x80, + 0xd7, 0x30, 0x7a, 0xbc, 0x6f, 0x01, 0x9d, 0xa7, 0x55, 0x08, 0xaf, 0xe7, 0xc1, 0x01, 0x68, 0x30, + 0x92, 0x52, 0x6f, 0xc3, 0xe4, 0xaf, 0xae, 0xf0, 0x84, 0xa4, 0x14, 0x9b, 0x08, 0x0c, 0x80, 0xab, + 0xbf, 0x22, 0x23, 0x11, 0xf5, 0x9a, 0x26, 0xed, 0x81, 0x4d, 0x73, 0x9f, 0x94, 0x01, 0x5c, 0xe5, + 0xc0, 0x2f, 0x81, 0xcb, 0x33, 0x3d, 0xb8, 0x84, 0x33, 0xaf, 0x65, 0x00, 0x7e, 0x09, 0x38, 0x29, + 0x03, 0x57, 0xeb, 0x06, 0xae, 0x00, 0xf0, 0x19, 0x68, 0x2b, 0x41, 0xf3, 0x63, 0xf6, 0x82, 0x7b, + 0x6d, 0xa3, 0xd8, 0x27, 0x68, 0x7d, 0x23, 0xfe, 0xf5, 0x13, 0x6b, 0xa5, 0x86, 0x36, 0xbb, 0x52, + 0xa7, 0xf4, 0xe0, 0x15, 0x13, 0x1c, 0x82, 0x26, 0x1f, 0xfd, 0x48, 0x23, 0xe9, 0xb9, 0x86, 0x73, + 0xe7, 0xd6, 0x29, 0xd8, 0x7f, 0x10, 0x61, 0x72, 0x76, 0xf4, 0xb3, 0xa4, 0x4c, 0x0f, 0x20, 0x7c, + 0xcf, 0x52, 0x37, 0x4f, 0x0c, 0x09, 0xb6, 0x64, 0xf0, 0x07, 0xe0, 0xf2, 0x59, 0x5c, 0x38, 0x3d, + 0x70, 0x17, 0xe6, 0x95, 0x94, 0x27, 0x25, 0x0f, 0xae, 0x28, 0xe1, 0x16, 0x68, 0xc6, 0xf9, 0x02, + 0x2b, 0xe6, 0x75, 0x06, 0xce, 0x76, 0x3b, 0x04, 0xba, 0x87, 0x43, 0xe3, 0xc1, 0x36, 0x02, 0x9f, + 0x83, 0x16, 0xcf, 0xb4, 0x18, 0xc2, 0xdb, 0xbc, 0x4b, 0x07, 0xf7, 0x6d, 0x07, 0xad, 0x93, 0x82, + 0x05, 0x97, 0x74, 0x5b, 0xbf, 0x36, 0xc0, 0x83, 0xb5, 0x7d, 0x13, 0x19, 0x67, 0x82, 0xbe, 0x93, + 0x85, 0xfb, 0x14, 0xb4, 0xc8, 0x6c, 0xc6, 0xcf, 0x68, 0xb1, 0x73, 0xed, 0xaa, 0x89, 0x83, 0xc2, + 0x8d, 0xcb, 0x38, 0x3c, 0x05, 0x4d, 0x21, 0x89, 0x54, 0xc2, 0xee, 0xcf, 0xc3, 0x37, 0xdb, 0x9f, + 0xa7, 0x06, 0x53, 0x08, 0x86, 0xa9, 0x50, 0x33, 0x89, 0x2d, 0x0f, 0xec, 0x83, 0x8d, 0x8c, 0xc8, + 0x68, 0x62, 0x76, 0x64, 0x33, 0x74, 0x97, 0x17, 0xfd, 0x8d, 0x53, 0xed, 0xc0, 0x85, 0x1f, 0xee, + 0x03, 0xd7, 0x1c, 0x9e, 0x2d, 0xb2, 0x72, 0x31, 0x7a, 0x7a, 0x44, 0xa7, 0xa5, 0xf3, 0x6a, 0xdd, + 0xc0, 0x55, 0x32, 0xfc, 0xcd, 0x01, 0x5d, 0xa2, 0xe2, 0x44, 0x1e, 0x30, 0xc6, 0x25, 0x29, 0xa6, + 0xd2, 0x1c, 0xd4, 0xb7, 0x3b, 0x7b, 0x47, 0xe8, 0xbf, 0xde, 0x75, 0x74, 0x43, 0x67, 0x74, 0x70, + 0x8d, 0xe7, 0x88, 0xc9, 0x7c, 0x11, 0x7a, 0x56, 0xa8, 0xee, 0xf5, 0x30, 0xbe, 0x51, 0xb8, 0xf7, + 0x15, 0xf8, 0xf0, 0xb5, 0x24, 0xb0, 0x0b, 0xea, 0x53, 0xba, 0x28, 0x46, 0x88, 0xf5, 0x11, 0x7e, + 0x00, 0x36, 0xe6, 0x64, 0xa6, 0xa8, 0x19, 0x87, 0x8b, 0x0b, 0xe3, 0xf1, 0xbd, 0x7d, 0x67, 0xeb, + 0x0f, 0x07, 0xdc, 0x5f, 0x6b, 0x6e, 0x9e, 0xd0, 0x33, 0x38, 0x04, 0xad, 0xbc, 0x78, 0x7e, 0x0d, + 0x47, 0x67, 0x0f, 0xbd, 0xf1, 0xe5, 0x0c, 0x2a, 0xec, 0xe8, 0x51, 0x5b, 0x03, 0x97, 0x5c, 0xf0, + 0x3b, 0xf3, 0x58, 0x9a, 0xdb, 0xdb, 0xa7, 0x38, 0x78, 0x4b, 0xd1, 0xc2, 0x4d, 0xfb, 0x3a, 0x1a, + 0x0b, 0xaf, 0xe8, 0xc2, 0x9d, 0xf3, 0x4b, 0xbf, 0xf6, 0xf2, 0xd2, 0xaf, 0xbd, 0xba, 0xf4, 0x6b, + 0xbf, 0x2c, 0x7d, 0xe7, 0x7c, 0xe9, 0x3b, 0x2f, 0x97, 0xbe, 0xf3, 0x6a, 0xe9, 0x3b, 0x7f, 0x2e, + 0x7d, 0xe7, 0xf7, 0xbf, 0xfc, 0xda, 0xf7, 0x2d, 0x4b, 0xfc, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x9a, 0x46, 0xfc, 0x70, 0xcb, 0x07, 0x00, 0x00, } diff --git a/staging/src/k8s.io/api/admission/v1beta1/generated.proto b/staging/src/k8s.io/api/admission/v1beta1/generated.proto index 451d4c9ad77..9bf414c1f47 100644 --- a/staging/src/k8s.io/api/admission/v1beta1/generated.proto +++ b/staging/src/k8s.io/api/admission/v1beta1/generated.proto @@ -60,7 +60,8 @@ message AdmissionRequest { // +optional optional string namespace = 6; - // Operation is the operation being performed + // Operation is the operation being performed. This may be different than the operation + // requested. e.g. a patch can result in either a CREATE or UPDATE Operation. optional string operation = 7; // UserInfo is information about the requesting user @@ -78,6 +79,14 @@ message AdmissionRequest { // Defaults to false. // +optional optional bool dryRun = 11; + + // Options is the operation option structure of the operation being performed. + // e.g. `meta.k8s.io/v1.DeleteOptions` or `meta.k8s.io/v1.CreateOptions`. This may be + // different than the options the caller provided. e.g. for a patch request the performed + // Operation might be a CREATE, in which case the Options will a + // `meta.k8s.io/v1.CreateOptions` even though the caller provided `meta.k8s.io/v1.PatchOptions`. + // +optional + optional k8s.io.apimachinery.pkg.runtime.RawExtension options = 12; } // AdmissionResponse describes an admission response. diff --git a/staging/src/k8s.io/api/admission/v1beta1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/admission/v1beta1/types_swagger_doc_generated.go index 8a938db3b4a..700b5f9e4a1 100644 --- a/staging/src/k8s.io/api/admission/v1beta1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/admission/v1beta1/types_swagger_doc_generated.go @@ -35,11 +35,12 @@ var map_AdmissionRequest = map[string]string{ "subResource": "SubResource is the name of the subresource being requested. This is a different resource, scoped to the parent resource, but it may have a different kind. For instance, /pods has the resource \"pods\" and the kind \"Pod\", while /pods/foo/status has the resource \"pods\", the sub resource \"status\", and the kind \"Pod\" (because status operates on pods). The binding resource for a pod though may be /pods/foo/binding, which has resource \"pods\", subresource \"binding\", and kind \"Binding\".", "name": "Name is the name of the object as presented in the request. On a CREATE operation, the client may omit name and rely on the server to generate the name. If that is the case, this method will return the empty string.", "namespace": "Namespace is the namespace associated with the request (if any).", - "operation": "Operation is the operation being performed", + "operation": "Operation is the operation being performed. This may be different than the operation requested. e.g. a patch can result in either a CREATE or UPDATE Operation.", "userInfo": "UserInfo is information about the requesting user", "object": "Object is the object from the incoming request prior to default values being applied", "oldObject": "OldObject is the existing object. Only populated for UPDATE requests.", "dryRun": "DryRun indicates that modifications will definitely not be persisted for this request. Defaults to false.", + "options": "Options is the operation option structure of the operation being performed. e.g. `meta.k8s.io/v1.DeleteOptions` or `meta.k8s.io/v1.CreateOptions`. This may be different than the options the caller provided. e.g. for a patch request the performed Operation might be a CREATE, in which case the Options will a `meta.k8s.io/v1.CreateOptions` even though the caller provided `meta.k8s.io/v1.PatchOptions`.", } func (AdmissionRequest) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/admission/v1beta1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/admission/v1beta1/zz_generated.deepcopy.go index 2b4352a9482..5bafcbdc5f9 100644 --- a/staging/src/k8s.io/api/admission/v1beta1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/admission/v1beta1/zz_generated.deepcopy.go @@ -38,6 +38,7 @@ func (in *AdmissionRequest) DeepCopyInto(out *AdmissionRequest) { *out = new(bool) **out = **in } + in.Options.DeepCopyInto(&out.Options) return } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto index a0c23a44f56..011cee45521 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto @@ -46,7 +46,7 @@ message ConversionRequest { // ConversionResponse describes a conversion response. message ConversionResponse { // `uid` is an identifier for the individual request/response. - // This should be copied over from the corresponding AdmissionRequest. + // This should be copied over from the corresponding ConversionRequest. optional string uid = 1; // `convertedObjects` is the list of converted version of `request.objects` if the `result` is successful otherwise empty. From 900d652a9ac11e53293950b3d191295c21430215 Mon Sep 17 00:00:00 2001 From: Joe Betz Date: Tue, 7 May 2019 13:37:07 -0700 Subject: [PATCH 3/3] Update tests for: Pass {Operation}Option to Webhooks --- plugin/pkg/admission/admit/BUILD | 1 + plugin/pkg/admission/admit/admission_test.go | 3 +- .../alwayspullimages/admission_test.go | 6 +- .../admission/antiaffinity/admission_test.go | 6 +- .../admission_test.go | 2 +- plugin/pkg/admission/deny/BUILD | 1 + plugin/pkg/admission/deny/admission_test.go | 3 +- plugin/pkg/admission/eventratelimit/BUILD | 1 + .../eventratelimit/admission_test.go | 2 + plugin/pkg/admission/exec/admission_test.go | 4 +- .../admission_test.go | 2 +- plugin/pkg/admission/gc/gc_admission_test.go | 8 +- plugin/pkg/admission/imagepolicy/BUILD | 1 + .../admission/imagepolicy/admission_test.go | 17 +- .../admission/limitranger/admission_test.go | 20 +- .../namespace/autoprovision/admission_test.go | 10 +- .../namespace/exists/admission_test.go | 4 +- .../noderestriction/admission_test.go | 268 +++++++++--------- plugin/pkg/admission/nodetaint/BUILD | 1 + .../pkg/admission/nodetaint/admission_test.go | 8 +- .../podnodeselector/admission_test.go | 4 +- .../pkg/admission/podpreset/admission_test.go | 1 + .../admission_test.go | 4 +- .../pkg/admission/priority/admission_test.go | 12 +- .../admission/resourcequota/admission_test.go | 58 ++-- .../podsecuritypolicy/admission_test.go | 10 +- .../securitycontext/scdeny/admission_test.go | 6 +- .../serviceaccount/admission_test.go | 56 ++-- .../persistentvolume/label/admission_test.go | 4 +- .../persistentvolume/resize/admission_test.go | 3 +- .../storageclass/setdefault/admission_test.go | 1 + .../admission_test.go | 1 + .../apiserver/pkg/admission/audit_test.go | 2 +- .../apiserver/pkg/admission/chain_test.go | 10 +- .../apiserver/pkg/admission/errors_test.go | 1 + .../apiserver/pkg/admission/metrics/BUILD | 2 + .../pkg/admission/metrics/metrics_test.go | 16 +- .../namespace/lifecycle/admission_test.go | 34 +-- .../webhook/mutating/dispatcher_test.go | 2 +- .../plugin/webhook/namespace/matcher_test.go | 12 +- .../pkg/admission/plugin/webhook/rules/BUILD | 2 + .../plugin/webhook/rules/rules_test.go | 163 +++++------ .../plugin/webhook/testing/testcase.go | 3 +- .../plugin/banflunder/admission_test.go | 1 + .../admissionwebhook/admission_test.go | 75 +++-- 45 files changed, 473 insertions(+), 378 deletions(-) diff --git a/plugin/pkg/admission/admit/BUILD b/plugin/pkg/admission/admit/BUILD index bd93027e33c..388dfd03d7e 100644 --- a/plugin/pkg/admission/admit/BUILD +++ b/plugin/pkg/admission/admit/BUILD @@ -22,6 +22,7 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", ], ) diff --git a/plugin/pkg/admission/admit/admission_test.go b/plugin/pkg/admission/admit/admission_test.go index 6721aaf4eb5..ff4bb8a66d8 100644 --- a/plugin/pkg/admission/admit/admission_test.go +++ b/plugin/pkg/admission/admit/admission_test.go @@ -19,13 +19,14 @@ package admit import ( "testing" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apiserver/pkg/admission" api "k8s.io/kubernetes/pkg/apis/core" ) func TestAdmissionNonNilAttribute(t *testing.T) { handler := NewAlwaysAdmit() - err := handler.(*alwaysAdmit).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, false, nil), nil) + err := handler.(*alwaysAdmit).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error returned from admission handler") } diff --git a/plugin/pkg/admission/alwayspullimages/admission_test.go b/plugin/pkg/admission/alwayspullimages/admission_test.go index 6f0756e30e8..7dab5611061 100644 --- a/plugin/pkg/admission/alwayspullimages/admission_test.go +++ b/plugin/pkg/admission/alwayspullimages/admission_test.go @@ -47,7 +47,7 @@ func TestAdmission(t *testing.T) { }, }, } - err := handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error returned from admission handler") } @@ -84,7 +84,7 @@ func TestValidate(t *testing.T) { }, } expectedError := `pods "123" is forbidden: spec.initContainers[0].imagePullPolicy: Unsupported value: "": supported values: "Always"` - err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Fatal("missing expected error") } @@ -139,7 +139,7 @@ func TestOtherResources(t *testing.T) { for _, tc := range tests { handler := &AlwaysPullImages{} - err := handler.Admit(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, false, nil), nil) + err := handler.Admit(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, &metav1.CreateOptions{}, false, nil), nil) if tc.expectError { if err == nil { diff --git a/plugin/pkg/admission/antiaffinity/admission_test.go b/plugin/pkg/admission/antiaffinity/admission_test.go index 9772716c255..b531b6a6aeb 100644 --- a/plugin/pkg/admission/antiaffinity/admission_test.go +++ b/plugin/pkg/admission/antiaffinity/admission_test.go @@ -19,7 +19,7 @@ package antiaffinity import ( "testing" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/admission" @@ -199,7 +199,7 @@ func TestInterPodAffinityAdmission(t *testing.T) { } for _, test := range tests { pod.Spec.Affinity = test.affinity - err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil, false, nil), nil) if test.errorExpected && err == nil { t.Errorf("Expected error for Anti Affinity %+v but did not get an error", test.affinity) @@ -267,7 +267,7 @@ func TestOtherResources(t *testing.T) { for _, tc := range tests { handler := &Plugin{} - err := handler.Validate(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, &metav1.CreateOptions{}, false, nil), nil) if tc.expectError { if err == nil { diff --git a/plugin/pkg/admission/defaulttolerationseconds/admission_test.go b/plugin/pkg/admission/defaulttolerationseconds/admission_test.go index 09f0fcd944a..4bf22839d83 100644 --- a/plugin/pkg/admission/defaulttolerationseconds/admission_test.go +++ b/plugin/pkg/admission/defaulttolerationseconds/admission_test.go @@ -263,7 +263,7 @@ func TestForgivenessAdmission(t *testing.T) { } for _, test := range tests { - err := handler.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil), nil) + err := handler.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil, false, nil), nil) if err != nil { t.Errorf("[%s]: unexpected error %v for pod %+v", test.description, err, test.requestedPod) } diff --git a/plugin/pkg/admission/deny/BUILD b/plugin/pkg/admission/deny/BUILD index cdbe0e929ad..524c8b90693 100644 --- a/plugin/pkg/admission/deny/BUILD +++ b/plugin/pkg/admission/deny/BUILD @@ -22,6 +22,7 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", ], ) diff --git a/plugin/pkg/admission/deny/admission_test.go b/plugin/pkg/admission/deny/admission_test.go index 1eb7e9928ae..0d431f4d76a 100644 --- a/plugin/pkg/admission/deny/admission_test.go +++ b/plugin/pkg/admission/deny/admission_test.go @@ -19,13 +19,14 @@ package deny import ( "testing" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apiserver/pkg/admission" api "k8s.io/kubernetes/pkg/apis/core" ) func TestAdmission(t *testing.T) { handler := NewAlwaysDeny() - err := handler.(*alwaysDeny).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, false, nil), nil) + err := handler.(*alwaysDeny).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Error("Expected error returned from admission handler") } diff --git a/plugin/pkg/admission/eventratelimit/BUILD b/plugin/pkg/admission/eventratelimit/BUILD index 97b33f9bbe3..1f154fc3b66 100644 --- a/plugin/pkg/admission/eventratelimit/BUILD +++ b/plugin/pkg/admission/eventratelimit/BUILD @@ -17,6 +17,7 @@ go_test( "//pkg/apis/core:go_default_library", "//plugin/pkg/admission/eventratelimit/apis/eventratelimit:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", diff --git a/plugin/pkg/admission/eventratelimit/admission_test.go b/plugin/pkg/admission/eventratelimit/admission_test.go index 468c3ad5c45..82566eea799 100644 --- a/plugin/pkg/admission/eventratelimit/admission_test.go +++ b/plugin/pkg/admission/eventratelimit/admission_test.go @@ -21,6 +21,7 @@ import ( "time" "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/clock" "k8s.io/apiserver/pkg/admission" @@ -46,6 +47,7 @@ func attributesForRequest(rq request) admission.Attributes { api.Resource("resource").WithVersion("version"), "", admission.Create, + &metav1.CreateOptions{}, rq.dryRun, &user.DefaultInfo{Name: rq.username}) } diff --git a/plugin/pkg/admission/exec/admission_test.go b/plugin/pkg/admission/exec/admission_test.go index 14f29abf4af..4d48e8c11dc 100644 --- a/plugin/pkg/admission/exec/admission_test.go +++ b/plugin/pkg/admission/exec/admission_test.go @@ -120,7 +120,7 @@ func testAdmission(t *testing.T, pod *corev1.Pod, handler *DenyExec, shouldAccep // pods/exec { - err := handler.Validate(admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), "test", pod.Name, api.Resource("pods").WithVersion("version"), "exec", admission.Connect, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), "test", pod.Name, api.Resource("pods").WithVersion("version"), "exec", admission.Connect, nil, false, nil), nil) if shouldAccept && err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } @@ -131,7 +131,7 @@ func testAdmission(t *testing.T, pod *corev1.Pod, handler *DenyExec, shouldAccep // pods/attach { - err := handler.Validate(admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), "test", pod.Name, api.Resource("pods").WithVersion("version"), "attach", admission.Connect, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), "test", pod.Name, api.Resource("pods").WithVersion("version"), "attach", admission.Connect, nil, false, nil), nil) if shouldAccept && err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } diff --git a/plugin/pkg/admission/extendedresourcetoleration/admission_test.go b/plugin/pkg/admission/extendedresourcetoleration/admission_test.go index b177950b225..fdb3aa5b46c 100644 --- a/plugin/pkg/admission/extendedresourcetoleration/admission_test.go +++ b/plugin/pkg/admission/extendedresourcetoleration/admission_test.go @@ -354,7 +354,7 @@ func TestAdmit(t *testing.T) { }, } for i, test := range tests { - err := plugin.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, core.Kind("Pod").WithVersion("version"), "foo", "name", core.Resource("pods").WithVersion("version"), "", "ignored", false, nil), nil) + err := plugin.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, core.Kind("Pod").WithVersion("version"), "foo", "name", core.Resource("pods").WithVersion("version"), "", "ignored", nil, false, nil), nil) if err != nil { t.Errorf("[%d: %s] unexpected error %v for pod %+v", i, test.description, err, test.requestedPod) } diff --git a/plugin/pkg/admission/gc/gc_admission_test.go b/plugin/pkg/admission/gc/gc_admission_test.go index 8e0ef132ed7..501e13a4154 100644 --- a/plugin/pkg/admission/gc/gc_admission_test.go +++ b/plugin/pkg/admission/gc/gc_admission_test.go @@ -302,11 +302,13 @@ func TestGCAdmission(t *testing.T) { } operation := admission.Create + var options runtime.Object = &metav1.CreateOptions{} if tc.oldObj != nil { operation = admission.Update + options = &metav1.UpdateOptions{} } user := &user.DefaultInfo{Name: tc.username} - attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, false, user) + attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, options, false, user) err = gcAdmit.Validate(attributes, nil) if !tc.checkError(err) { @@ -605,11 +607,13 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) { for _, tc := range tests { operation := admission.Create + var options runtime.Object = &metav1.CreateOptions{} if tc.oldObj != nil { operation = admission.Update + options = &metav1.UpdateOptions{} } user := &user.DefaultInfo{Name: tc.username} - attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, false, user) + attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, options, false, user) err := gcAdmit.Validate(attributes, nil) if !tc.checkError(err) { diff --git a/plugin/pkg/admission/imagepolicy/BUILD b/plugin/pkg/admission/imagepolicy/BUILD index fb8c1c55e54..20630ea3644 100644 --- a/plugin/pkg/admission/imagepolicy/BUILD +++ b/plugin/pkg/admission/imagepolicy/BUILD @@ -42,6 +42,7 @@ go_test( "//pkg/apis/core:go_default_library", "//pkg/apis/imagepolicy/install:go_default_library", "//staging/src/k8s.io/api/imagepolicy/v1alpha1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//staging/src/k8s.io/client-go/tools/clientcmd/api/v1:go_default_library", diff --git a/plugin/pkg/admission/imagepolicy/admission_test.go b/plugin/pkg/admission/imagepolicy/admission_test.go index 3d748082a15..cfa9d0c1174 100644 --- a/plugin/pkg/admission/imagepolicy/admission_test.go +++ b/plugin/pkg/admission/imagepolicy/admission_test.go @@ -29,9 +29,10 @@ import ( "time" "k8s.io/api/imagepolicy/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/authentication/user" - "k8s.io/client-go/tools/clientcmd/api/v1" + v1 "k8s.io/client-go/tools/clientcmd/api/v1" api "k8s.io/kubernetes/pkg/apis/core" "fmt" @@ -482,7 +483,7 @@ func TestTLSConfig(t *testing.T) { return } pod := goodPod(strconv.Itoa(rand.Intn(1000))) - attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{}) + attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, &user.DefaultInfo{}) // Allow all and see if we get an error. service.Allow() @@ -571,7 +572,7 @@ func TestWebhookCache(t *testing.T) { {statusCode: 500, expectedErr: false, expectedAuthorized: true, expectedCached: true}, } - attr := admission.NewAttributesRecord(goodPod("test"), nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{}) + attr := admission.NewAttributesRecord(goodPod("test"), nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, &user.DefaultInfo{}) serv.allow = true @@ -583,7 +584,7 @@ func TestWebhookCache(t *testing.T) { {statusCode: 200, expectedErr: false, expectedAuthorized: true, expectedCached: false}, {statusCode: 500, expectedErr: false, expectedAuthorized: true, expectedCached: true}, } - attr = admission.NewAttributesRecord(goodPod("test2"), nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{}) + attr = admission.NewAttributesRecord(goodPod("test2"), nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, &user.DefaultInfo{}) testWebhookCacheCases(t, serv, wh, attr, tests) } @@ -757,7 +758,7 @@ func TestContainerCombinations(t *testing.T) { return } - attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{}) + attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, &user.DefaultInfo{}) err = wh.Validate(attr, nil) if tt.wantAllowed { @@ -851,7 +852,7 @@ func TestDefaultAllow(t *testing.T) { return } - attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{}) + attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, &user.DefaultInfo{}) annotations := make(map[string]string) attr = &fakeAttributes{attr, annotations} @@ -961,7 +962,7 @@ func TestAnnotationFiltering(t *testing.T) { pod := goodPod("test") pod.Annotations = tt.annotations - attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{}) + attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, &user.DefaultInfo{}) err = wh.Validate(attr, nil) if err != nil { @@ -1051,7 +1052,7 @@ func TestReturnedAnnotationAdd(t *testing.T) { pod := tt.pod - attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{}) + attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, &user.DefaultInfo{}) annotations := make(map[string]string) attr = &fakeAttributes{attr, annotations} diff --git a/plugin/pkg/admission/limitranger/admission_test.go b/plugin/pkg/admission/limitranger/admission_test.go index ec184e4dfc7..acec3436b6f 100644 --- a/plugin/pkg/admission/limitranger/admission_test.go +++ b/plugin/pkg/admission/limitranger/admission_test.go @@ -35,7 +35,7 @@ import ( "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/v1" + v1 "k8s.io/kubernetes/pkg/apis/core/v1" ) func getComputeResourceList(cpu, memory string) api.ResourceList { @@ -705,20 +705,20 @@ func TestLimitRangerIgnoresSubresource(t *testing.T) { informerFactory.Start(wait.NeverStop) testPod := validPod("testPod", 1, api.ResourceRequirements{}) - err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Fatal(err) } - err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected an error since the pod did not specify resource limits in its create call") } - err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err != nil { t.Errorf("Expected not to call limitranger actions on pod updates") } - err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "status", admission.Update, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "status", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err != nil { t.Errorf("Should have ignored calls to any subresource of pod %v", err) } @@ -735,20 +735,20 @@ func TestLimitRangerAdmitPod(t *testing.T) { informerFactory.Start(wait.NeverStop) testPod := validPod("testPod", 1, api.ResourceRequirements{}) - err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Fatal(err) } - err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected an error since the pod did not specify resource limits in its create call") } - err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err != nil { t.Errorf("Expected not to call limitranger actions on pod updates") } - err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "status", admission.Update, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "status", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err != nil { t.Errorf("Should have ignored calls to any subresource of pod %v", err) } @@ -757,7 +757,7 @@ func TestLimitRangerAdmitPod(t *testing.T) { terminatingPod := validPod("terminatingPod", 1, api.ResourceRequirements{}) now := metav1.Now() terminatingPod.DeletionTimestamp = &now - err = handler.Validate(admission.NewAttributesRecord(&terminatingPod, &terminatingPod, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "terminatingPod", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(&terminatingPod, &terminatingPod, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "terminatingPod", api.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err != nil { t.Errorf("LimitRange should ignore a pod marked for termination") } diff --git a/plugin/pkg/admission/namespace/autoprovision/admission_test.go b/plugin/pkg/admission/namespace/autoprovision/admission_test.go index cde6f315bf8..63b508f77cf 100644 --- a/plugin/pkg/admission/namespace/autoprovision/admission_test.go +++ b/plugin/pkg/admission/namespace/autoprovision/admission_test.go @@ -99,7 +99,7 @@ func TestAdmission(t *testing.T) { informerFactory.Start(wait.NeverStop) pod := newPod(namespace) - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("unexpected error returned from admission handler") } @@ -119,7 +119,7 @@ func TestAdmissionNamespaceExists(t *testing.T) { informerFactory.Start(wait.NeverStop) pod := newPod(namespace) - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("unexpected error returned from admission handler") } @@ -139,7 +139,7 @@ func TestAdmissionDryRun(t *testing.T) { informerFactory.Start(wait.NeverStop) pod := newPod(namespace) - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, true, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, true, nil), nil) if err != nil { t.Errorf("unexpected error returned from admission handler") } @@ -160,7 +160,7 @@ func TestIgnoreAdmission(t *testing.T) { chainHandler := admission.NewChainHandler(handler) pod := newPod(namespace) - err = chainHandler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil), nil) + err = chainHandler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err != nil { t.Errorf("unexpected error returned from admission handler") } @@ -182,7 +182,7 @@ func TestAdmissionWithLatentCache(t *testing.T) { informerFactory.Start(wait.NeverStop) pod := newPod(namespace) - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("unexpected error returned from admission handler") } diff --git a/plugin/pkg/admission/namespace/exists/admission_test.go b/plugin/pkg/admission/namespace/exists/admission_test.go index c1cbfa5b188..7ba55539e88 100644 --- a/plugin/pkg/admission/namespace/exists/admission_test.go +++ b/plugin/pkg/admission/namespace/exists/admission_test.go @@ -88,7 +88,7 @@ func TestAdmissionNamespaceExists(t *testing.T) { informerFactory.Start(wait.NeverStop) pod := newPod(namespace) - err = handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("unexpected error returned from admission handler") } @@ -108,7 +108,7 @@ func TestAdmissionNamespaceDoesNotExist(t *testing.T) { informerFactory.Start(wait.NeverStop) pod := newPod(namespace) - err = handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { actions := "" for _, action := range mockClient.Actions() { diff --git a/plugin/pkg/admission/noderestriction/admission_test.go b/plugin/pkg/admission/noderestriction/admission_test.go index bca668fd37b..a053d9e83d1 100644 --- a/plugin/pkg/admission/noderestriction/admission_test.go +++ b/plugin/pkg/admission/noderestriction/admission_test.go @@ -374,61 +374,61 @@ func Test_nodePlugin_Admit(t *testing.T) { { name: "allow creating a mirror pod bound to self", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coremymirrorpod, nil, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(coremymirrorpod, nil, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "", }, { name: "forbid update of mirror pod bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coremymirrorpod, coremymirrorpod, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(coremymirrorpod, coremymirrorpod, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "allow delete of mirror pod bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "", }, { name: "forbid create of mirror pod status bound to self", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coremymirrorpod, nil, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "status", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(coremymirrorpod, nil, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "allow update of mirror pod status bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coremymirrorpod, coremymirrorpod, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "status", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(coremymirrorpod, coremymirrorpod, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "forbid delete of mirror pod status bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "status", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "allow create of eviction for mirror pod bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mymirrorpodEviction, nil, evictionKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(mymirrorpodEviction, nil, evictionKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "", }, { name: "forbid update of eviction for mirror pod bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mymirrorpodEviction, nil, evictionKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "eviction", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mymirrorpodEviction, nil, evictionKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid delete of eviction for mirror pod bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mymirrorpodEviction, nil, evictionKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "eviction", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(mymirrorpodEviction, nil, evictionKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "allow create of unnamed eviction for mirror pod bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coremymirrorpod.Namespace, coremymirrorpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "", }, @@ -436,61 +436,61 @@ func Test_nodePlugin_Admit(t *testing.T) { { name: "forbid creating a mirror pod bound to another", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coreothermirrorpod, nil, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(coreothermirrorpod, nil, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid update of mirror pod bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coreothermirrorpod, coreothermirrorpod, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(coreothermirrorpod, coreothermirrorpod, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid delete of mirror pod bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid create of mirror pod status bound to another", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coreothermirrorpod, nil, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "status", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(coreothermirrorpod, nil, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid update of mirror pod status bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coreothermirrorpod, coreothermirrorpod, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "status", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(coreothermirrorpod, coreothermirrorpod, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid delete of mirror pod status bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "status", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid create of eviction for mirror pod bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(othermirrorpodEviction, nil, evictionKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(othermirrorpodEviction, nil, evictionKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid update of eviction for mirror pod bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(othermirrorpodEviction, nil, evictionKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "eviction", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(othermirrorpodEviction, nil, evictionKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid delete of eviction for mirror pod bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(othermirrorpodEviction, nil, evictionKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "eviction", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(othermirrorpodEviction, nil, evictionKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid create of unnamed eviction for mirror pod to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreothermirrorpod.Namespace, coreothermirrorpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, @@ -498,61 +498,61 @@ func Test_nodePlugin_Admit(t *testing.T) { { name: "forbid creating a mirror pod unbound", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coreunboundmirrorpod, nil, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(coreunboundmirrorpod, nil, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid update of mirror pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coreunboundmirrorpod, coreunboundmirrorpod, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(coreunboundmirrorpod, coreunboundmirrorpod, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid delete of mirror pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid create of mirror pod status unbound", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coreunboundmirrorpod, nil, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "status", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(coreunboundmirrorpod, nil, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid update of mirror pod status unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coreunboundmirrorpod, coreunboundmirrorpod, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "status", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(coreunboundmirrorpod, coreunboundmirrorpod, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid delete of mirror pod status unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "status", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid create of eviction for mirror pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unboundmirrorpodEviction, nil, evictionKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(unboundmirrorpodEviction, nil, evictionKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid update of eviction for mirror pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unboundmirrorpodEviction, nil, evictionKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "eviction", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(unboundmirrorpodEviction, nil, evictionKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid delete of eviction for mirror pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unboundmirrorpodEviction, nil, evictionKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "eviction", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(unboundmirrorpodEviction, nil, evictionKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid create of unnamed eviction for mirror pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreunboundmirrorpod.Namespace, coreunboundmirrorpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, @@ -560,55 +560,55 @@ func Test_nodePlugin_Admit(t *testing.T) { { name: "forbid creating a normal pod bound to self", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coremypod, nil, podKind, coremypod.Namespace, coremypod.Name, podResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(coremypod, nil, podKind, coremypod.Namespace, coremypod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "can only create mirror pods", }, { name: "forbid update of normal pod bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coremypod, coremypod, podKind, coremypod.Namespace, coremypod.Name, podResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(coremypod, coremypod, podKind, coremypod.Namespace, coremypod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "allow delete of normal pod bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coremypod.Namespace, coremypod.Name, podResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coremypod.Namespace, coremypod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "", }, { name: "forbid create of normal pod status bound to self", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coremypod, nil, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(coremypod, nil, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "allow update of normal pod status bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coremypod, coremypod, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(coremypod, coremypod, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "forbid delete of normal pod status bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coremypod.Namespace, coremypod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid update of eviction for normal pod bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid delete of eviction for normal pod bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "allow create of unnamed eviction for normal pod bound to self", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "", }, @@ -616,61 +616,61 @@ func Test_nodePlugin_Admit(t *testing.T) { { name: "forbid creating a normal pod bound to another", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coreotherpod, nil, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(coreotherpod, nil, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "can only create mirror pods", }, { name: "forbid update of normal pod bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coreotherpod, coreotherpod, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(coreotherpod, coreotherpod, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid delete of normal pod bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "", admission.Delete, &metav1.UpdateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid create of normal pod status bound to another", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coreotherpod, nil, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "status", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(coreotherpod, nil, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid update of normal pod status bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coreotherpod, coreotherpod, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "status", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(coreotherpod, coreotherpod, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid delete of normal pod status bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "status", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid create of eviction for normal pod bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(otherpodEviction, nil, evictionKind, otherpodEviction.Namespace, otherpodEviction.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(otherpodEviction, nil, evictionKind, otherpodEviction.Namespace, otherpodEviction.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid update of eviction for normal pod bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(otherpodEviction, nil, evictionKind, otherpodEviction.Namespace, otherpodEviction.Name, podResource, "eviction", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(otherpodEviction, nil, evictionKind, otherpodEviction.Namespace, otherpodEviction.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid delete of eviction for normal pod bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(otherpodEviction, nil, evictionKind, otherpodEviction.Namespace, otherpodEviction.Name, podResource, "eviction", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(otherpodEviction, nil, evictionKind, otherpodEviction.Namespace, otherpodEviction.Name, podResource, "eviction", admission.Delete, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid create of unnamed eviction for normal pod bound to another", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreotherpod.Namespace, coreotherpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, @@ -678,61 +678,61 @@ func Test_nodePlugin_Admit(t *testing.T) { { name: "forbid creating a normal pod unbound", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coreunboundpod, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(coreunboundpod, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "can only create mirror pods", }, { name: "forbid update of normal pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coreunboundpod, coreunboundpod, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(coreunboundpod, coreunboundpod, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid delete of normal pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid create of normal pod status unbound", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coreunboundpod, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(coreunboundpod, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid update of normal pod status unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coreunboundpod, coreunboundpod, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(coreunboundpod, coreunboundpod, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid delete of normal pod status unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid create of eviction for normal pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unboundpodEviction, nil, evictionKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(unboundpodEviction, nil, evictionKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, { name: "forbid update of eviction for normal pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unboundpodEviction, nil, evictionKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "eviction", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(unboundpodEviction, nil, evictionKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid delete of eviction for normal pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unboundpodEviction, nil, evictionKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "eviction", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(unboundpodEviction, nil, evictionKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid create of unnamed eviction for normal unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "spec.nodeName set to itself", }, @@ -740,31 +740,31 @@ func Test_nodePlugin_Admit(t *testing.T) { { name: "forbid delete of unknown pod", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "not found", }, { name: "forbid create of eviction for unknown pod", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "not found", }, { name: "forbid update of eviction for unknown pod", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid delete of eviction for unknown pod", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid create of unnamed eviction for unknown pod", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coremypod.Namespace, coremypod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "not found", }, @@ -772,26 +772,26 @@ func Test_nodePlugin_Admit(t *testing.T) { { name: "allow create of eviction for unnamed pod", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coreunnamedpod.Namespace, coreunnamedpod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coreunnamedpod.Namespace, coreunnamedpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), // use the submitted eviction resource name as the pod name err: "", }, { name: "forbid update of eviction for unnamed pod", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coreunnamedpod.Namespace, coreunnamedpod.Name, podResource, "eviction", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coreunnamedpod.Namespace, coreunnamedpod.Name, podResource, "eviction", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid delete of eviction for unnamed pod", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coreunnamedpod.Namespace, coreunnamedpod.Name, podResource, "eviction", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(mypodEviction, nil, evictionKind, coreunnamedpod.Namespace, coreunnamedpod.Name, podResource, "eviction", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "forbidden: unexpected operation", }, { name: "forbid create of unnamed eviction for unnamed pod", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreunnamedpod.Namespace, coreunnamedpod.Name, podResource, "eviction", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, coreunnamedpod.Namespace, coreunnamedpod.Name, podResource, "eviction", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "could not determine pod from request data", }, @@ -799,25 +799,25 @@ func Test_nodePlugin_Admit(t *testing.T) { { name: "forbid create of pod referencing service account", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(sapod, nil, podKind, sapod.Namespace, sapod.Name, podResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(sapod, nil, podKind, sapod.Namespace, sapod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "reference a service account", }, { name: "forbid create of pod referencing secret", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(secretpod, nil, podKind, secretpod.Namespace, secretpod.Name, podResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(secretpod, nil, podKind, secretpod.Namespace, secretpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "reference secrets", }, { name: "forbid create of pod referencing configmap", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(configmappod, nil, podKind, configmappod.Namespace, configmappod.Name, podResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(configmappod, nil, podKind, configmappod.Namespace, configmappod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "reference configmaps", }, { name: "forbid create of pod referencing persistentvolumeclaim", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(pvcpod, nil, podKind, pvcpod.Namespace, pvcpod.Name, podResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(pvcpod, nil, podKind, pvcpod.Namespace, pvcpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "reference persistentvolumeclaims", }, @@ -825,157 +825,157 @@ func Test_nodePlugin_Admit(t *testing.T) { { name: "allow create of my node", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(mynodeObj, nil, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObj, nil, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "", }, { name: "allow create of my node pulling name from object", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(mynodeObj, nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObj, nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "", }, { name: "allow create of my node with taints", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(mynodeObjTaintA, nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObjTaintA, nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "", }, { name: "allow create of my node with labels", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(setAllowedCreateLabels(mynodeObj, ""), nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(setAllowedCreateLabels(mynodeObj, ""), nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "", }, { name: "forbid create of my node with forbidden labels", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(setForbiddenCreateLabels(mynodeObj, ""), nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(setForbiddenCreateLabels(mynodeObj, ""), nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: `is not allowed to set the following labels: foo.node-restriction.kubernetes.io/foo, node-restriction.kubernetes.io/foo`, }, { name: "allow update of my node", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mynodeObj, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObj, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "allow delete of my node", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "", }, { name: "allow update of my node status", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mynodeObj, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "status", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObj, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "forbid create of my node with non-nil configSource", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(mynodeObjConfigA, nil, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObjConfigA, nil, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "is not allowed to create pods with a non-nil configSource", }, { name: "forbid update of my node: nil configSource to new non-nil configSource", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mynodeObjConfigA, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObjConfigA, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "update configSource to a new non-nil configSource", }, { name: "forbid update of my node: non-nil configSource to new non-nil configSource", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mynodeObjConfigB, mynodeObjConfigA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObjConfigB, mynodeObjConfigA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "update configSource to a new non-nil configSource", }, { name: "allow update of my node: non-nil configSource unchanged", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mynodeObjConfigA, mynodeObjConfigA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObjConfigA, mynodeObjConfigA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "allow update of my node: non-nil configSource to nil configSource", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mynodeObj, mynodeObjConfigA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObj, mynodeObjConfigA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "allow update of my node: no change to taints", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mynodeObjTaintA, mynodeObjTaintA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObjTaintA, mynodeObjTaintA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "allow update of my node: add allowed labels", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(setAllowedUpdateLabels(mynodeObj, ""), mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(setAllowedUpdateLabels(mynodeObj, ""), mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "allow update of my node: remove allowed labels", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mynodeObj, setAllowedUpdateLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObj, setAllowedUpdateLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "allow update of my node: modify allowed labels", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(setAllowedUpdateLabels(mynodeObj, "b"), setAllowedUpdateLabels(mynodeObj, "a"), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(setAllowedUpdateLabels(mynodeObj, "b"), setAllowedUpdateLabels(mynodeObj, "a"), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "allow update of my node: no change to labels", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(setAllLabels(mynodeObj, ""), setAllLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(setAllLabels(mynodeObj, ""), setAllLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "allow update of my node: add allowed labels while forbidden labels exist unmodified", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(setAllLabels(mynodeObj, ""), setForbiddenUpdateLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(setAllLabels(mynodeObj, ""), setForbiddenUpdateLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "allow update of my node: remove allowed labels while forbidden labels exist unmodified", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(setForbiddenUpdateLabels(mynodeObj, ""), setAllLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(setForbiddenUpdateLabels(mynodeObj, ""), setAllLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "forbid update of my node: add taints", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mynodeObjTaintA, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObjTaintA, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "is not allowed to modify taints", }, { name: "forbid update of my node: remove taints", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mynodeObj, mynodeObjTaintA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObj, mynodeObjTaintA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "is not allowed to modify taints", }, { name: "forbid update of my node: change taints", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mynodeObjTaintA, mynodeObjTaintB, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObjTaintA, mynodeObjTaintB, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "is not allowed to modify taints", }, { name: "forbid update of my node: add labels", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(setForbiddenUpdateLabels(mynodeObj, ""), mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(setForbiddenUpdateLabels(mynodeObj, ""), mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: `is not allowed to modify labels: foo.node-restriction.kubernetes.io/foo, node-restriction.kubernetes.io/foo, other.k8s.io/foo, other.kubernetes.io/foo`, }, { name: "forbid update of my node: remove labels", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(mynodeObj, setForbiddenUpdateLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(mynodeObj, setForbiddenUpdateLabels(mynodeObj, ""), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: `is not allowed to modify labels: foo.node-restriction.kubernetes.io/foo, node-restriction.kubernetes.io/foo, other.k8s.io/foo, other.kubernetes.io/foo`, }, { name: "forbid update of my node: change labels", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(setForbiddenUpdateLabels(mynodeObj, "new"), setForbiddenUpdateLabels(mynodeObj, "old"), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(setForbiddenUpdateLabels(mynodeObj, "new"), setForbiddenUpdateLabels(mynodeObj, "old"), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: `is not allowed to modify labels: foo.node-restriction.kubernetes.io/foo, node-restriction.kubernetes.io/foo, other.k8s.io/foo, other.kubernetes.io/foo`, }, @@ -983,31 +983,31 @@ func Test_nodePlugin_Admit(t *testing.T) { { name: "forbid create of other node", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(othernodeObj, nil, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(othernodeObj, nil, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "is not allowed to modify node", }, { name: "forbid create of other node pulling name from object", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(othernodeObj, nil, nodeKind, othernodeObj.Namespace, "", nodeResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(othernodeObj, nil, nodeKind, othernodeObj.Namespace, "", nodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "is not allowed to modify node", }, { name: "forbid update of other node", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(othernodeObj, othernodeObj, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(othernodeObj, othernodeObj, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "is not allowed to modify node", }, { name: "forbid delete of other node", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "is not allowed to modify node", }, { name: "forbid update of other node status", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(othernodeObj, othernodeObj, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "status", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(othernodeObj, othernodeObj, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "status", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "is not allowed to modify node", }, @@ -1016,54 +1016,54 @@ func Test_nodePlugin_Admit(t *testing.T) { name: "forbid create of unbound token", podsGetter: noExistingPods, features: trEnabledFeature, - attributes: admission.NewAttributesRecord(makeTokenRequest("", ""), nil, tokenrequestKind, "ns", "mysa", svcacctResource, "token", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(makeTokenRequest("", ""), nil, tokenrequestKind, "ns", "mysa", svcacctResource, "token", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "not bound to a pod", }, { name: "forbid create of token bound to nonexistant pod", podsGetter: noExistingPods, features: trEnabledFeature, - attributes: admission.NewAttributesRecord(makeTokenRequest("nopod", "someuid"), nil, tokenrequestKind, "ns", "mysa", svcacctResource, "token", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(makeTokenRequest("nopod", "someuid"), nil, tokenrequestKind, "ns", "mysa", svcacctResource, "token", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "not found", }, { name: "forbid create of token bound to pod without uid", podsGetter: existingPods, features: trEnabledFeature, - attributes: admission.NewAttributesRecord(makeTokenRequest(coremypod.Name, ""), nil, tokenrequestKind, "ns", "mysa", svcacctResource, "token", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(makeTokenRequest(coremypod.Name, ""), nil, tokenrequestKind, "ns", "mysa", svcacctResource, "token", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "pod binding without a uid", }, { name: "forbid create of token bound to pod scheduled on another node", podsGetter: existingPods, features: trEnabledFeature, - attributes: admission.NewAttributesRecord(makeTokenRequest(coreotherpod.Name, coreotherpod.UID), nil, tokenrequestKind, coreotherpod.Namespace, "mysa", svcacctResource, "token", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(makeTokenRequest(coreotherpod.Name, coreotherpod.UID), nil, tokenrequestKind, coreotherpod.Namespace, "mysa", svcacctResource, "token", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "pod scheduled on a different node", }, { name: "allow create of token bound to pod scheduled this node", podsGetter: existingPods, features: trEnabledFeature, - attributes: admission.NewAttributesRecord(makeTokenRequest(coremypod.Name, coremypod.UID), nil, tokenrequestKind, coremypod.Namespace, "mysa", svcacctResource, "token", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(makeTokenRequest(coremypod.Name, coremypod.UID), nil, tokenrequestKind, coremypod.Namespace, "mysa", svcacctResource, "token", admission.Create, &metav1.CreateOptions{}, false, mynode), }, // Unrelated objects { name: "allow create of unrelated object", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(&api.ConfigMap{}, nil, configmapKind, "myns", "mycm", configmapResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(&api.ConfigMap{}, nil, configmapKind, "myns", "mycm", configmapResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), err: "", }, { name: "allow update of unrelated object", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(&api.ConfigMap{}, &api.ConfigMap{}, configmapKind, "myns", "mycm", configmapResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(&api.ConfigMap{}, &api.ConfigMap{}, configmapKind, "myns", "mycm", configmapResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), err: "", }, { name: "allow delete of unrelated object", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, configmapKind, "myns", "mycm", configmapResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, configmapKind, "myns", "mycm", configmapResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), err: "", }, @@ -1071,140 +1071,140 @@ func Test_nodePlugin_Admit(t *testing.T) { { name: "allow unrelated user creating a normal pod unbound", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coreunboundpod, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Create, false, bob), + attributes: admission.NewAttributesRecord(coreunboundpod, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Create, &metav1.CreateOptions{}, false, bob), err: "", }, { name: "allow unrelated user update of normal pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coreunboundpod, coreunboundpod, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Update, false, bob), + attributes: admission.NewAttributesRecord(coreunboundpod, coreunboundpod, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Update, &metav1.UpdateOptions{}, false, bob), err: "", }, { name: "allow unrelated user delete of normal pod unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Delete, false, bob), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "", admission.Delete, &metav1.DeleteOptions{}, false, bob), err: "", }, { name: "allow unrelated user create of normal pod status unbound", podsGetter: noExistingPods, - attributes: admission.NewAttributesRecord(coreunboundpod, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Create, false, bob), + attributes: admission.NewAttributesRecord(coreunboundpod, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Create, &metav1.CreateOptions{}, false, bob), err: "", }, { name: "allow unrelated user update of normal pod status unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(coreunboundpod, coreunboundpod, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Update, false, bob), + attributes: admission.NewAttributesRecord(coreunboundpod, coreunboundpod, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Update, &metav1.UpdateOptions{}, false, bob), err: "", }, { name: "allow unrelated user delete of normal pod status unbound", podsGetter: existingPods, - attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Delete, false, bob), + attributes: admission.NewAttributesRecord(nil, nil, podKind, coreunboundpod.Namespace, coreunboundpod.Name, podResource, "status", admission.Delete, &metav1.DeleteOptions{}, false, bob), err: "", }, // Node leases { name: "disallowed create lease - feature disabled", - attributes: admission.NewAttributesRecord(lease, nil, leaseKind, lease.Namespace, lease.Name, leaseResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(lease, nil, leaseKind, lease.Namespace, lease.Name, leaseResource, "", admission.Create, &metav1.DeleteOptions{}, false, mynode), features: leaseDisabledFeature, err: "forbidden: disabled by feature gate NodeLease", }, { name: "disallowed create lease in namespace other than kube-node-lease - feature enabled", - attributes: admission.NewAttributesRecord(leaseWrongNS, nil, leaseKind, leaseWrongNS.Namespace, leaseWrongNS.Name, leaseResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(leaseWrongNS, nil, leaseKind, leaseWrongNS.Namespace, leaseWrongNS.Name, leaseResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), features: leaseEnabledFeature, err: "forbidden: ", }, { name: "disallowed update lease in namespace other than kube-node-lease - feature enabled", - attributes: admission.NewAttributesRecord(leaseWrongNS, leaseWrongNS, leaseKind, leaseWrongNS.Namespace, leaseWrongNS.Name, leaseResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(leaseWrongNS, leaseWrongNS, leaseKind, leaseWrongNS.Namespace, leaseWrongNS.Name, leaseResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), features: leaseEnabledFeature, err: "forbidden: ", }, { name: "disallowed delete lease in namespace other than kube-node-lease - feature enabled", - attributes: admission.NewAttributesRecord(nil, nil, leaseKind, leaseWrongNS.Namespace, leaseWrongNS.Name, leaseResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, leaseKind, leaseWrongNS.Namespace, leaseWrongNS.Name, leaseResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), features: leaseEnabledFeature, err: "forbidden: ", }, { name: "disallowed create another node's lease - feature enabled", - attributes: admission.NewAttributesRecord(leaseWrongName, nil, leaseKind, leaseWrongName.Namespace, leaseWrongName.Name, leaseResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(leaseWrongName, nil, leaseKind, leaseWrongName.Namespace, leaseWrongName.Name, leaseResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), features: leaseEnabledFeature, err: "forbidden: ", }, { name: "disallowed update another node's lease - feature enabled", - attributes: admission.NewAttributesRecord(leaseWrongName, leaseWrongName, leaseKind, leaseWrongName.Namespace, leaseWrongName.Name, leaseResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(leaseWrongName, leaseWrongName, leaseKind, leaseWrongName.Namespace, leaseWrongName.Name, leaseResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), features: leaseEnabledFeature, err: "forbidden: ", }, { name: "disallowed delete another node's lease - feature enabled", - attributes: admission.NewAttributesRecord(nil, nil, leaseKind, leaseWrongName.Namespace, leaseWrongName.Name, leaseResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, leaseKind, leaseWrongName.Namespace, leaseWrongName.Name, leaseResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), features: leaseEnabledFeature, err: "forbidden: ", }, { name: "allowed create node lease - feature enabled", - attributes: admission.NewAttributesRecord(lease, nil, leaseKind, lease.Namespace, lease.Name, leaseResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(lease, nil, leaseKind, lease.Namespace, lease.Name, leaseResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), features: leaseEnabledFeature, err: "", }, { name: "allowed update node lease - feature enabled", - attributes: admission.NewAttributesRecord(lease, lease, leaseKind, lease.Namespace, lease.Name, leaseResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(lease, lease, leaseKind, lease.Namespace, lease.Name, leaseResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), features: leaseEnabledFeature, err: "", }, { name: "allowed delete node lease - feature enabled", - attributes: admission.NewAttributesRecord(nil, nil, leaseKind, lease.Namespace, lease.Name, leaseResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, leaseKind, lease.Namespace, lease.Name, leaseResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), features: leaseEnabledFeature, err: "", }, // CSINode { name: "disallowed create CSINode - feature disabled", - attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), features: csiNodeInfoDisabledFeature, err: fmt.Sprintf("forbidden: disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo), }, { name: "disallowed create another node's CSINode - feature enabled", - attributes: admission.NewAttributesRecord(nodeInfoWrongName, nil, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(nodeInfoWrongName, nil, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), features: csiNodeInfoEnabledFeature, err: "forbidden: ", }, { name: "disallowed update another node's CSINode - feature enabled", - attributes: admission.NewAttributesRecord(nodeInfoWrongName, nodeInfoWrongName, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(nodeInfoWrongName, nodeInfoWrongName, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), features: csiNodeInfoEnabledFeature, err: "forbidden: ", }, { name: "disallowed delete another node's CSINode - feature enabled", - attributes: admission.NewAttributesRecord(nil, nil, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Delete, &metav1.DeleteOptions{}, false, mynode), features: csiNodeInfoEnabledFeature, err: "forbidden: ", }, { name: "allowed create node CSINode - feature enabled", - attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Create, false, mynode), + attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Create, &metav1.CreateOptions{}, false, mynode), features: csiNodeInfoEnabledFeature, err: "", }, { name: "allowed update node CSINode - feature enabled", - attributes: admission.NewAttributesRecord(nodeInfo, nodeInfo, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Update, false, mynode), + attributes: admission.NewAttributesRecord(nodeInfo, nodeInfo, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode), features: csiNodeInfoEnabledFeature, err: "", }, { name: "allowed delete node CSINode - feature enabled", - attributes: admission.NewAttributesRecord(nil, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Delete, false, mynode), + attributes: admission.NewAttributesRecord(nil, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Delete, &metav1.UpdateOptions{}, false, mynode), features: csiNodeInfoEnabledFeature, err: "", }, diff --git a/plugin/pkg/admission/nodetaint/BUILD b/plugin/pkg/admission/nodetaint/BUILD index 03a745fb27e..c01864b455d 100644 --- a/plugin/pkg/admission/nodetaint/BUILD +++ b/plugin/pkg/admission/nodetaint/BUILD @@ -22,6 +22,7 @@ go_test( "//pkg/apis/core:go_default_library", "//pkg/features:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//staging/src/k8s.io/component-base/featuregate:go_default_library", diff --git a/plugin/pkg/admission/nodetaint/admission_test.go b/plugin/pkg/admission/nodetaint/admission_test.go index 6dad6f0dff9..6dd56c506d6 100644 --- a/plugin/pkg/admission/nodetaint/admission_test.go +++ b/plugin/pkg/admission/nodetaint/admission_test.go @@ -21,6 +21,7 @@ import ( "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/component-base/featuregate" @@ -62,6 +63,7 @@ func Test_nodeTaints(t *testing.T) { oldNode api.Node features featuregate.FeatureGate operation admission.Operation + options runtime.Object expectedTaints []api.Taint }{ { @@ -69,6 +71,7 @@ func Test_nodeTaints(t *testing.T) { node: myNodeObj, features: enableTaintNodesByCondition, operation: admission.Create, + options: &metav1.CreateOptions{}, expectedTaints: []api.Taint{notReadyTaint}, }, { @@ -76,6 +79,7 @@ func Test_nodeTaints(t *testing.T) { node: myNodeObj, features: disableTaintNodesByCondition, operation: admission.Create, + options: &metav1.CreateOptions{}, expectedTaints: nil, }, { @@ -83,6 +87,7 @@ func Test_nodeTaints(t *testing.T) { node: myTaintedNodeObj, features: enableTaintNodesByCondition, operation: admission.Create, + options: &metav1.CreateOptions{}, expectedTaints: []api.Taint{notReadyTaint}, }, { @@ -90,12 +95,13 @@ func Test_nodeTaints(t *testing.T) { node: myUnreadyNodeObj, features: enableTaintNodesByCondition, operation: admission.Create, + options: &metav1.CreateOptions{}, expectedTaints: []api.Taint{notReadyTaint}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - attributes := admission.NewAttributesRecord(&tt.node, &tt.oldNode, nodeKind, myNodeObj.Namespace, myNodeObj.Name, resource, "", tt.operation, false, mynode) + attributes := admission.NewAttributesRecord(&tt.node, &tt.oldNode, nodeKind, myNodeObj.Namespace, myNodeObj.Name, resource, "", tt.operation, tt.options, false, mynode) c := NewPlugin() if tt.features != nil { c.features = tt.features diff --git a/plugin/pkg/admission/podnodeselector/admission_test.go b/plugin/pkg/admission/podnodeselector/admission_test.go index 73f1da09834..b7596ed7645 100644 --- a/plugin/pkg/admission/podnodeselector/admission_test.go +++ b/plugin/pkg/admission/podnodeselector/admission_test.go @@ -161,7 +161,7 @@ func TestPodAdmission(t *testing.T) { handler.clusterNodeSelectors[namespace.Name] = test.whitelist pod.Spec = api.PodSpec{NodeSelector: test.podNodeSelector} - err := handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if test.admit && err != nil { t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) } else if !test.admit && err == nil { @@ -170,7 +170,7 @@ func TestPodAdmission(t *testing.T) { if test.admit && !labels.Equals(test.mergedNodeSelector, labels.Set(pod.Spec.NodeSelector)) { t.Errorf("Test: %s, expected: %s but got: %s", test.testName, test.mergedNodeSelector, pod.Spec.NodeSelector) } - err = handler.Validate(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if test.admit && err != nil { t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) } else if !test.admit && err == nil { diff --git a/plugin/pkg/admission/podpreset/admission_test.go b/plugin/pkg/admission/podpreset/admission_test.go index 3dd8692fd99..babf068ce70 100644 --- a/plugin/pkg/admission/podpreset/admission_test.go +++ b/plugin/pkg/admission/podpreset/admission_test.go @@ -819,6 +819,7 @@ func admitPod(pod *api.Pod, pip *settingsv1alpha1.PodPreset) error { api.Resource("pods").WithVersion("version"), "", kadmission.Create, + &metav1.CreateOptions{}, false, &user.DefaultInfo{}, ) diff --git a/plugin/pkg/admission/podtolerationrestriction/admission_test.go b/plugin/pkg/admission/podtolerationrestriction/admission_test.go index 6cc63c98a32..9bfde7184a9 100644 --- a/plugin/pkg/admission/podtolerationrestriction/admission_test.go +++ b/plugin/pkg/admission/podtolerationrestriction/admission_test.go @@ -266,7 +266,7 @@ func TestPodAdmission(t *testing.T) { pod := test.pod pod.Spec.Tolerations = test.podTolerations - err = handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if test.admit && err != nil { t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) } else if !test.admit && err == nil { @@ -343,7 +343,7 @@ func TestIgnoreUpdatingInitializedPod(t *testing.T) { } // if the update of initialized pod is not ignored, an error will be returned because the pod's Tolerations conflicts with namespace's Tolerations. - err = handler.Admit(admission.NewAttributesRecord(pod, pod, api.Kind("Pod").WithVersion("version"), "testNamespace", pod.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(pod, pod, api.Kind("Pod").WithVersion("version"), "testNamespace", pod.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("expected no error, got: %v", err) } diff --git a/plugin/pkg/admission/priority/admission_test.go b/plugin/pkg/admission/priority/admission_test.go index e81ec4ea029..81bf5774524 100644 --- a/plugin/pkg/admission/priority/admission_test.go +++ b/plugin/pkg/admission/priority/admission_test.go @@ -30,7 +30,7 @@ import ( featuregatetesting "k8s.io/component-base/featuregate/testing" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/scheduling" - "k8s.io/kubernetes/pkg/apis/scheduling/v1" + v1 "k8s.io/kubernetes/pkg/apis/scheduling/v1" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/features" ) @@ -155,6 +155,7 @@ func TestPriorityClassAdmission(t *testing.T) { scheduling.Resource("priorityclasses").WithVersion("version"), "", admission.Create, + &metav1.CreateOptions{}, false, test.userInfo, ) @@ -200,7 +201,7 @@ func TestDefaultPriority(t *testing.T) { name: "add a default class", classesBefore: []*scheduling.PriorityClass{nondefaultClass1}, classesAfter: []*scheduling.PriorityClass{nondefaultClass1, defaultClass1}, - attributes: admission.NewAttributesRecord(defaultClass1, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Create, false, nil), + attributes: admission.NewAttributesRecord(defaultClass1, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Create, &metav1.CreateOptions{}, false, nil), expectedDefaultBefore: scheduling.DefaultPriorityWhenNoDefaultClassExists, expectedDefaultNameBefore: "", expectedDefaultAfter: defaultClass1.Value, @@ -210,7 +211,7 @@ func TestDefaultPriority(t *testing.T) { name: "multiple default classes resolves to the minimum value among them", classesBefore: []*scheduling.PriorityClass{defaultClass1, defaultClass2}, classesAfter: []*scheduling.PriorityClass{defaultClass2}, - attributes: admission.NewAttributesRecord(nil, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Delete, false, nil), + attributes: admission.NewAttributesRecord(nil, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Delete, &metav1.DeleteOptions{}, false, nil), expectedDefaultBefore: defaultClass1.Value, expectedDefaultNameBefore: defaultClass1.Name, expectedDefaultAfter: defaultClass2.Value, @@ -220,7 +221,7 @@ func TestDefaultPriority(t *testing.T) { name: "delete default priority class", classesBefore: []*scheduling.PriorityClass{defaultClass1}, classesAfter: []*scheduling.PriorityClass{}, - attributes: admission.NewAttributesRecord(nil, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Delete, false, nil), + attributes: admission.NewAttributesRecord(nil, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Delete, &metav1.DeleteOptions{}, false, nil), expectedDefaultBefore: defaultClass1.Value, expectedDefaultNameBefore: defaultClass1.Name, expectedDefaultAfter: scheduling.DefaultPriorityWhenNoDefaultClassExists, @@ -230,7 +231,7 @@ func TestDefaultPriority(t *testing.T) { name: "update default class and remove its global default", classesBefore: []*scheduling.PriorityClass{defaultClass1}, classesAfter: []*scheduling.PriorityClass{&updatedDefaultClass1}, - attributes: admission.NewAttributesRecord(&updatedDefaultClass1, defaultClass1, pcKind, "", defaultClass1.Name, pcResource, "", admission.Update, false, nil), + attributes: admission.NewAttributesRecord(&updatedDefaultClass1, defaultClass1, pcKind, "", defaultClass1.Name, pcResource, "", admission.Update, &metav1.UpdateOptions{}, false, nil), expectedDefaultBefore: defaultClass1.Value, expectedDefaultNameBefore: defaultClass1.Name, expectedDefaultAfter: scheduling.DefaultPriorityWhenNoDefaultClassExists, @@ -600,6 +601,7 @@ func TestPodAdmission(t *testing.T) { api.Resource("pods").WithVersion("version"), "", admission.Create, + &metav1.CreateOptions{}, false, nil, ) diff --git a/plugin/pkg/admission/resourcequota/admission_test.go b/plugin/pkg/admission/resourcequota/admission_test.go index 8b6e45203ab..57e6aa948fe 100644 --- a/plugin/pkg/admission/resourcequota/admission_test.go +++ b/plugin/pkg/admission/resourcequota/admission_test.go @@ -153,7 +153,7 @@ func TestAdmissionIgnoresDelete(t *testing.T) { evaluator: evaluator, } namespace := "default" - err := handler.Validate(admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), namespace, "name", corev1.Resource("pods").WithVersion("version"), "", admission.Delete, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), namespace, "name", corev1.Resource("pods").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil) if err != nil { t.Errorf("ResourceQuota should admit all deletes: %v", err) } @@ -190,11 +190,11 @@ func TestAdmissionIgnoresSubresources(t *testing.T) { } informerFactory.Core().V1().ResourceQuotas().Informer().GetIndexer().Add(resourceQuota) newPod := validPod("123", 1, getResourceRequirements(getResourceList("100m", "2Gi"), getResourceList("", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected an error because the pod exceeded allowed quota") } - err = handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "subresource", admission.Create, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "subresource", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("Did not expect an error because the action went to a subresource: %v", err) } @@ -235,7 +235,7 @@ func TestAdmitBelowQuotaLimit(t *testing.T) { } informerFactory.Core().V1().ResourceQuotas().Informer().GetIndexer().Add(resourceQuota) newPod := validPod("allowed-pod", 1, getResourceRequirements(getResourceList("100m", "2Gi"), getResourceList("", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -318,13 +318,13 @@ func TestAdmitDryRun(t *testing.T) { informerFactory.Core().V1().ResourceQuotas().Informer().GetIndexer().Add(resourceQuota) newPod := validPod("allowed-pod", 1, getResourceRequirements(getResourceList("100m", "2Gi"), getResourceList("", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, true, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, true, nil), nil) if err != nil { t.Errorf("Unexpected error: %v", err) } newPod = validPod("too-large-pod", 1, getResourceRequirements(getResourceList("100m", "60Gi"), getResourceList("", ""))) - err = handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, true, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, true, nil), nil) if err == nil { t.Errorf("Expected error but got none") } @@ -384,7 +384,7 @@ func TestAdmitHandlesOldObjects(t *testing.T) { Ports: []api.ServicePort{{Port: 1234}}, }, } - err := handler.Validate(admission.NewAttributesRecord(newService, existingService, api.Kind("Service").WithVersion("version"), newService.Namespace, newService.Name, corev1.Resource("services").WithVersion("version"), "", admission.Update, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newService, existingService, api.Kind("Service").WithVersion("version"), newService.Namespace, newService.Name, corev1.Resource("services").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -485,7 +485,7 @@ func TestAdmitHandlesNegativePVCUpdates(t *testing.T) { }, } - err := handler.Validate(admission.NewAttributesRecord(newPVC, oldPVC, api.Kind("PersistentVolumeClaim").WithVersion("version"), newPVC.Namespace, newPVC.Name, corev1.Resource("persistentvolumeclaims").WithVersion("version"), "", admission.Update, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPVC, oldPVC, api.Kind("PersistentVolumeClaim").WithVersion("version"), newPVC.Namespace, newPVC.Name, corev1.Resource("persistentvolumeclaims").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -544,7 +544,7 @@ func TestAdmitHandlesPVCUpdates(t *testing.T) { }, } - err := handler.Validate(admission.NewAttributesRecord(newPVC, oldPVC, api.Kind("PersistentVolumeClaim").WithVersion("version"), newPVC.Namespace, newPVC.Name, corev1.Resource("persistentvolumeclaims").WithVersion("version"), "", admission.Update, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPVC, oldPVC, api.Kind("PersistentVolumeClaim").WithVersion("version"), newPVC.Namespace, newPVC.Name, corev1.Resource("persistentvolumeclaims").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -641,7 +641,7 @@ func TestAdmitHandlesCreatingUpdates(t *testing.T) { Ports: []api.ServicePort{{Port: 1234}}, }, } - err := handler.Validate(admission.NewAttributesRecord(newService, oldService, api.Kind("Service").WithVersion("version"), newService.Namespace, newService.Name, corev1.Resource("services").WithVersion("version"), "", admission.Update, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newService, oldService, api.Kind("Service").WithVersion("version"), newService.Namespace, newService.Name, corev1.Resource("services").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -724,7 +724,7 @@ func TestAdmitExceedQuotaLimit(t *testing.T) { } informerFactory.Core().V1().ResourceQuotas().Informer().GetIndexer().Add(resourceQuota) newPod := validPod("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected an error exceeding quota") } @@ -770,7 +770,7 @@ func TestAdmitEnforceQuotaConstraints(t *testing.T) { informerFactory.Core().V1().ResourceQuotas().Informer().GetIndexer().Add(resourceQuota) // verify all values are specified as required on the quota newPod := validPod("not-allowed-pod", 1, getResourceRequirements(getResourceList("100m", "2Gi"), getResourceList("200m", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected an error because the pod does not specify a memory limit") } @@ -821,7 +821,7 @@ func TestAdmitPodInNamespaceWithoutQuota(t *testing.T) { newPod := validPod("not-allowed-pod", 1, getResourceRequirements(getResourceList("100m", "2Gi"), getResourceList("200m", ""))) // Add to the lru cache so we do not do a live client lookup liveLookupCache.Add(newPod.Namespace, liveLookupEntry{expiry: time.Now().Add(time.Duration(30 * time.Second)), items: []*corev1.ResourceQuota{}}) - err = handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("Did not expect an error because the pod is in a different namespace than the quota") } @@ -890,7 +890,7 @@ func TestAdmitBelowTerminatingQuotaLimit(t *testing.T) { newPod := validPod("allowed-pod", 1, getResourceRequirements(getResourceList("100m", "2Gi"), getResourceList("", ""))) activeDeadlineSeconds := int64(30) newPod.Spec.ActiveDeadlineSeconds = &activeDeadlineSeconds - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -994,7 +994,7 @@ func TestAdmitBelowBestEffortQuotaLimit(t *testing.T) { // create a pod that is best effort because it does not make a request for anything newPod := validPod("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -1084,7 +1084,7 @@ func TestAdmitBestEffortQuotaLimitIgnoresBurstable(t *testing.T) { } informerFactory.Core().V1().ResourceQuotas().Informer().GetIndexer().Add(resourceQuota) newPod := validPod("allowed-pod", 1, getResourceRequirements(getResourceList("100m", "1Gi"), getResourceList("", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -1193,7 +1193,7 @@ func TestAdmissionSetsMissingNamespace(t *testing.T) { // unset the namespace newPod.ObjectMeta.Namespace = "" - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("Got unexpected error: %v", err) } @@ -1236,14 +1236,14 @@ func TestAdmitRejectsNegativeUsage(t *testing.T) { informerFactory.Core().V1().ResourceQuotas().Informer().GetIndexer().Add(resourceQuota) // verify quota rejects negative pvc storage requests newPvc := validPersistentVolumeClaim("not-allowed-pvc", getResourceRequirements(api.ResourceList{api.ResourceStorage: resource.MustParse("-1Gi")}, api.ResourceList{})) - err := handler.Validate(admission.NewAttributesRecord(newPvc, nil, api.Kind("PersistentVolumeClaim").WithVersion("version"), newPvc.Namespace, newPvc.Name, corev1.Resource("persistentvolumeclaims").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPvc, nil, api.Kind("PersistentVolumeClaim").WithVersion("version"), newPvc.Namespace, newPvc.Name, corev1.Resource("persistentvolumeclaims").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected an error because the pvc has negative storage usage") } // verify quota accepts non-negative pvc storage requests newPvc = validPersistentVolumeClaim("not-allowed-pvc", getResourceRequirements(api.ResourceList{api.ResourceStorage: resource.MustParse("1Gi")}, api.ResourceList{})) - err = handler.Validate(admission.NewAttributesRecord(newPvc, nil, api.Kind("PersistentVolumeClaim").WithVersion("version"), newPvc.Namespace, newPvc.Name, corev1.Resource("persistentvolumeclaims").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(newPvc, nil, api.Kind("PersistentVolumeClaim").WithVersion("version"), newPvc.Namespace, newPvc.Name, corev1.Resource("persistentvolumeclaims").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -1284,7 +1284,7 @@ func TestAdmitWhenUnrelatedResourceExceedsQuota(t *testing.T) { // create a pod that should pass existing quota newPod := validPod("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -1318,7 +1318,7 @@ func TestAdmitLimitedResourceNoQuota(t *testing.T) { evaluator: evaluator, } newPod := validPod("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected an error for consuming a limited resource without quota.") } @@ -1352,7 +1352,7 @@ func TestAdmitLimitedResourceNoQuotaIgnoresNonMatchingResources(t *testing.T) { evaluator: evaluator, } newPod := validPod("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Fatalf("Unexpected error: %v", err) } @@ -1400,7 +1400,7 @@ func TestAdmitLimitedResourceWithQuota(t *testing.T) { } indexer.Add(resourceQuota) newPod := validPod("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1460,7 +1460,7 @@ func TestAdmitLimitedResourceWithMultipleQuota(t *testing.T) { indexer.Add(resourceQuota1) indexer.Add(resourceQuota2) newPod := validPod("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1508,7 +1508,7 @@ func TestAdmitLimitedResourceWithQuotaThatDoesNotCover(t *testing.T) { } indexer.Add(resourceQuota) newPod := validPod("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", ""))) - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Fatalf("Expected an error since the quota did not cover cpu") } @@ -2169,7 +2169,7 @@ func TestAdmitLimitedScopeWithCoverQuota(t *testing.T) { if testCase.anotherQuota != nil { indexer.Add(testCase.anotherQuota) } - err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, corev1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if testCase.expErr == "" { if err != nil { t.Fatalf("Testcase, %v, failed with unexpected error: %v. ExpErr: %v", testCase.description, err, testCase.expErr) @@ -2221,7 +2221,7 @@ func TestAdmitZeroDeltaUsageWithoutCoveringQuota(t *testing.T) { Spec: api.ServiceSpec{Type: api.ServiceTypeLoadBalancer}, } - err := handler.Validate(admission.NewAttributesRecord(newService, existingService, api.Kind("Service").WithVersion("version"), newService.Namespace, newService.Name, corev1.Resource("services").WithVersion("version"), "", admission.Update, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newService, existingService, api.Kind("Service").WithVersion("version"), newService.Namespace, newService.Name, corev1.Resource("services").WithVersion("version"), "", admission.Update, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -2267,7 +2267,7 @@ func TestAdmitRejectIncreaseUsageWithoutCoveringQuota(t *testing.T) { Spec: api.ServiceSpec{Type: api.ServiceTypeLoadBalancer}, } - err := handler.Validate(admission.NewAttributesRecord(newService, existingService, api.Kind("Service").WithVersion("version"), newService.Namespace, newService.Name, corev1.Resource("services").WithVersion("version"), "", admission.Update, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newService, existingService, api.Kind("Service").WithVersion("version"), newService.Namespace, newService.Name, corev1.Resource("services").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected an error for consuming a limited resource without quota.") } @@ -2313,7 +2313,7 @@ func TestAdmitAllowDecreaseUsageWithoutCoveringQuota(t *testing.T) { }, } - err := handler.Validate(admission.NewAttributesRecord(newService, existingService, api.Kind("Service").WithVersion("version"), newService.Namespace, newService.Name, corev1.Resource("services").WithVersion("version"), "", admission.Update, false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(newService, existingService, api.Kind("Service").WithVersion("version"), newService.Namespace, newService.Name, corev1.Resource("services").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err != nil { t.Errorf("Expected no error for decreasing a limited resource without quota, got %v", err) } diff --git a/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go b/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go index 6712ab1ee1c..9936bda0612 100644 --- a/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go +++ b/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go @@ -24,7 +24,7 @@ import ( "github.com/stretchr/testify/assert" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" policy "k8s.io/api/policy/v1beta1" apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -473,7 +473,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { func TestFailClosedOnInvalidPod(t *testing.T) { plugin := NewTestAdmission(nil, nil) pod := &v1.Pod{} - attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, false, &user.DefaultInfo{}) + attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, &metav1.CreateOptions{}, false, &user.DefaultInfo{}) err := plugin.Admit(attrs, nil) if err == nil { @@ -1776,7 +1776,7 @@ func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []* originalPod := pod.DeepCopy() plugin := NewTestAdmission(psps, authz) - attrs := kadmission.NewAttributesRecord(pod, oldPod, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, "", kapi.Resource("pods").WithVersion("version"), "", op, false, userInfo) + attrs := kadmission.NewAttributesRecord(pod, oldPod, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, "", kapi.Resource("pods").WithVersion("version"), "", op, nil, false, userInfo) annotations := make(map[string]string) attrs = &fakeAttributes{attrs, annotations} err := plugin.Admit(attrs, nil) @@ -2240,7 +2240,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) { pod.Spec.SecurityContext.HostPID = true plugin := NewTestAdmission(tc.inPolicies, authz) - attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), ns, "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, false, &user.DefaultInfo{Name: userName}) + attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), ns, "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, &metav1.CreateOptions{}, false, &user.DefaultInfo{Name: userName}) allowedPod, _, validationErrs, err := plugin.computeSecurityContext(attrs, pod, true, "") assert.Nil(t, allowedPod) @@ -2333,7 +2333,7 @@ func TestPreferValidatedPSP(t *testing.T) { pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = &allowPrivilegeEscalation plugin := NewTestAdmission(tc.inPolicies, authz) - attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), "ns", "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Update, false, &user.DefaultInfo{Name: "test"}) + attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), "ns", "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Update, &metav1.UpdateOptions{}, false, &user.DefaultInfo{Name: "test"}) _, pspName, validationErrs, err := plugin.computeSecurityContext(attrs, pod, false, tc.validatedPSPHint) assert.NoError(t, err) diff --git a/plugin/pkg/admission/securitycontext/scdeny/admission_test.go b/plugin/pkg/admission/securitycontext/scdeny/admission_test.go index 65d7ad1d169..0111341d00b 100644 --- a/plugin/pkg/admission/securitycontext/scdeny/admission_test.go +++ b/plugin/pkg/admission/securitycontext/scdeny/admission_test.go @@ -82,7 +82,7 @@ func TestAdmission(t *testing.T) { p.Spec.SecurityContext = tc.podSc p.Spec.Containers[0].SecurityContext = tc.sc - err := handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil, false, nil), nil) if err != nil && !tc.expectError { t.Errorf("%v: unexpected error: %v", tc.name, err) } else if err == nil && tc.expectError { @@ -96,7 +96,7 @@ func TestAdmission(t *testing.T) { p.Spec.InitContainers = p.Spec.Containers p.Spec.Containers = nil - err = handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil), nil) + err = handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil, false, nil), nil) if err != nil && !tc.expectError { t.Errorf("%v: unexpected error: %v", tc.name, err) } else if err == nil && tc.expectError { @@ -140,7 +140,7 @@ func TestPodSecurityContextAdmission(t *testing.T) { } for _, test := range tests { pod.Spec.SecurityContext = &test.securityContext - err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil), nil) + err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil, false, nil), nil) if test.errorExpected && err == nil { t.Errorf("Expected error for security context %+v but did not get an error", test.securityContext) diff --git a/plugin/pkg/admission/serviceaccount/admission_test.go b/plugin/pkg/admission/serviceaccount/admission_test.go index 32c0c020728..712ceb60b6b 100644 --- a/plugin/pkg/admission/serviceaccount/admission_test.go +++ b/plugin/pkg/admission/serviceaccount/admission_test.go @@ -64,7 +64,7 @@ func TestIgnoresNonCreate(t *testing.T) { func TestIgnoresNonPodResource(t *testing.T) { pod := &api.Pod{} - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("CustomResource").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("CustomResource").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := NewServiceAccount().Admit(attrs, nil) if err != nil { t.Errorf("Expected non-pod resource allowed, got err: %v", err) @@ -72,7 +72,7 @@ func TestIgnoresNonPodResource(t *testing.T) { } func TestIgnoresNilObject(t *testing.T) { - attrs := admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := NewServiceAccount().Admit(attrs, nil) if err != nil { t.Errorf("Expected nil object allowed allowed, got err: %v", err) @@ -81,7 +81,7 @@ func TestIgnoresNilObject(t *testing.T) { func TestIgnoresNonPodObject(t *testing.T) { obj := &api.Namespace{} - attrs := admission.NewAttributesRecord(obj, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(obj, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := NewServiceAccount().Admit(attrs, nil) if err != nil { t.Errorf("Expected non pod object allowed, got err: %v", err) @@ -101,7 +101,7 @@ func TestIgnoresMirrorPod(t *testing.T) { }, }, } - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := NewServiceAccount().Admit(attrs, nil) if err != nil { t.Errorf("Expected mirror pod without service account or secrets allowed, got err: %v", err) @@ -119,7 +119,7 @@ func TestRejectsMirrorPodWithServiceAccount(t *testing.T) { ServiceAccountName: "default", }, } - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := NewServiceAccount().Admit(attrs, nil) if err == nil { t.Errorf("Expected a mirror pod to be prevented from referencing a service account") @@ -139,7 +139,7 @@ func TestRejectsMirrorPodWithSecretVolumes(t *testing.T) { }, }, } - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := NewServiceAccount().Admit(attrs, nil) if err == nil { t.Errorf("Expected a mirror pod to be prevented from referencing a secret volume") @@ -164,7 +164,7 @@ func TestRejectsMirrorPodWithServiceAccountTokenVolumeProjections(t *testing.T) }, }, } - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := NewServiceAccount().Admit(attrs, nil) if err == nil { t.Errorf("Expected a mirror pod to be prevented from referencing a ServiceAccountToken volume projection") @@ -189,7 +189,7 @@ func TestAssignsDefaultServiceAccountAndToleratesMissingAPIToken(t *testing.T) { }) pod := &api.Pod{} - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) @@ -217,7 +217,7 @@ func TestAssignsDefaultServiceAccountAndRejectsMissingAPIToken(t *testing.T) { }) pod := &api.Pod{} - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admit.Admit(attrs, nil) if err == nil || !errors.IsServerTimeout(err) { t.Errorf("Expected server timeout error for missing API token: %v", err) @@ -242,7 +242,7 @@ func TestFetchesUncachedServiceAccount(t *testing.T) { admit.RequireAPIToken = false pod := &api.Pod{} - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) @@ -264,7 +264,7 @@ func TestDeniesInvalidServiceAccount(t *testing.T) { admit.SetExternalKubeInformerFactory(informerFactory) pod := &api.Pod{} - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admit.Admit(attrs, nil) if err == nil { t.Errorf("Expected error for missing service account, got none") @@ -330,7 +330,7 @@ func TestAutomountsAPIToken(t *testing.T) { }, }, } - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) @@ -359,7 +359,7 @@ func TestAutomountsAPIToken(t *testing.T) { }, }, } - attrs = admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs = admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) if err := admit.Admit(attrs, nil); err != nil { t.Errorf("Unexpected error: %v", err) } @@ -441,7 +441,7 @@ func TestRespectsExistingMount(t *testing.T) { }, }, } - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) @@ -471,7 +471,7 @@ func TestRespectsExistingMount(t *testing.T) { }, }, } - attrs = admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs = admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) if err := admit.Admit(attrs, nil); err != nil { t.Errorf("Unexpected error: %v", err) } @@ -517,7 +517,7 @@ func TestAllowsReferencedSecret(t *testing.T) { }, }, } - attrs := admission.NewAttributesRecord(pod1, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod1, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) if err := admit.Admit(attrs, nil); err != nil { t.Errorf("Unexpected error: %v", err) } @@ -541,7 +541,7 @@ func TestAllowsReferencedSecret(t *testing.T) { }, }, } - attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) if err := admit.Admit(attrs, nil); err != nil { t.Errorf("Unexpected error: %v", err) } @@ -565,7 +565,7 @@ func TestAllowsReferencedSecret(t *testing.T) { }, }, } - attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) if err := admit.Admit(attrs, nil); err != nil { t.Errorf("Unexpected error: %v", err) } @@ -595,7 +595,7 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) { }, }, } - attrs := admission.NewAttributesRecord(pod1, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod1, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) if err := admit.Admit(attrs, nil); err == nil { t.Errorf("Expected rejection for using a secret the service account does not reference") } @@ -619,7 +619,7 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) { }, }, } - attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) if err := admit.Admit(attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") { t.Errorf("Unexpected error: %v", err) } @@ -643,7 +643,7 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) { }, }, } - attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) if err := admit.Admit(attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") { t.Errorf("Unexpected error: %v", err) } @@ -674,7 +674,7 @@ func TestAllowUnreferencedSecretVolumesForPermissiveSAs(t *testing.T) { }, }, } - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admit.Admit(attrs, nil) if err == nil { t.Errorf("Expected rejection for using a secret the service account does not reference") @@ -706,7 +706,7 @@ func TestAllowsReferencedImagePullSecrets(t *testing.T) { ImagePullSecrets: []api.LocalObjectReference{{Name: "foo"}}, }, } - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) @@ -735,7 +735,7 @@ func TestRejectsUnreferencedImagePullSecrets(t *testing.T) { ImagePullSecrets: []api.LocalObjectReference{{Name: "foo"}}, }, } - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admit.Admit(attrs, nil) if err == nil { t.Errorf("Expected rejection for using a secret the service account does not reference") @@ -768,7 +768,7 @@ func TestDoNotAddImagePullSecrets(t *testing.T) { ImagePullSecrets: []api.LocalObjectReference{{Name: "foo"}}, }, } - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) @@ -802,7 +802,7 @@ func TestAddImagePullSecrets(t *testing.T) { informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(sa) pod := &api.Pod{} - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) @@ -883,7 +883,7 @@ func TestMultipleReferencedSecrets(t *testing.T) { }, } - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) if err := admit.Admit(attrs, nil); err != nil { t.Fatal(err) } @@ -1037,7 +1037,7 @@ func TestAutomountIsBackwardsCompatible(t *testing.T) { }, }, } - attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) diff --git a/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go b/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go index c066d5d7bf5..c551dfef186 100644 --- a/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go +++ b/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go @@ -23,7 +23,7 @@ import ( "sort" "testing" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -756,7 +756,7 @@ func Test_PVLAdmission(t *testing.T) { setPVLabeler(testcase.handler, testcase.pvlabeler) handler := admission.NewChainHandler(testcase.handler) - err := handler.Admit(admission.NewAttributesRecord(testcase.preAdmissionPV, nil, api.Kind("PersistentVolume").WithVersion("version"), testcase.preAdmissionPV.Namespace, testcase.preAdmissionPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, false, nil), nil) + err := handler.Admit(admission.NewAttributesRecord(testcase.preAdmissionPV, nil, api.Kind("PersistentVolume").WithVersion("version"), testcase.preAdmissionPV.Namespace, testcase.preAdmissionPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if !reflect.DeepEqual(err, testcase.err) { t.Logf("expected error: %q", testcase.err) t.Logf("actual error: %q", err) diff --git a/plugin/pkg/admission/storage/persistentvolume/resize/admission_test.go b/plugin/pkg/admission/storage/persistentvolume/resize/admission_test.go index e0cb263bddb..699a24abff3 100644 --- a/plugin/pkg/admission/storage/persistentvolume/resize/admission_test.go +++ b/plugin/pkg/admission/storage/persistentvolume/resize/admission_test.go @@ -254,7 +254,8 @@ func TestPVCResizeAdmission(t *testing.T) { for _, tc := range tests { operation := admission.Update - attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, false, nil) + operationOptions := &metav1.CreateOptions{} + attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, operationOptions, false, nil) err := ctrl.Validate(attributes, nil) if !tc.checkError(err) { diff --git a/plugin/pkg/admission/storage/storageclass/setdefault/admission_test.go b/plugin/pkg/admission/storage/storageclass/setdefault/admission_test.go index 45152522f2b..3d7eaf18ed5 100644 --- a/plugin/pkg/admission/storage/storageclass/setdefault/admission_test.go +++ b/plugin/pkg/admission/storage/storageclass/setdefault/admission_test.go @@ -208,6 +208,7 @@ func TestAdmission(t *testing.T) { api.Resource("persistentvolumeclaims").WithVersion("version"), "", // subresource admission.Create, + &metav1.CreateOptions{}, false, // dryRun nil, // userInfo ) diff --git a/plugin/pkg/admission/storage/storageobjectinuseprotection/admission_test.go b/plugin/pkg/admission/storage/storageobjectinuseprotection/admission_test.go index e5e9f8108b1..15f77f8af70 100644 --- a/plugin/pkg/admission/storage/storageobjectinuseprotection/admission_test.go +++ b/plugin/pkg/admission/storage/storageobjectinuseprotection/admission_test.go @@ -131,6 +131,7 @@ func TestAdmit(t *testing.T) { test.resource, "", // subresource admission.Create, + &metav1.CreateOptions{}, false, // dryRun nil, // userInfo ) diff --git a/staging/src/k8s.io/apiserver/pkg/admission/audit_test.go b/staging/src/k8s.io/apiserver/pkg/admission/audit_test.go index 0b04cf2646a..4ead632f6ed 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/audit_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/audit_test.go @@ -64,7 +64,7 @@ func (h fakeHandler) Handles(o Operation) bool { } func attributes() Attributes { - return NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", "", false, nil) + return NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", "", nil, false, nil) } func TestWithAudit(t *testing.T) { diff --git a/staging/src/k8s.io/apiserver/pkg/admission/chain_test.go b/staging/src/k8s.io/apiserver/pkg/admission/chain_test.go index 20ab2faad2a..490a0af171e 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/chain_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/chain_test.go @@ -21,6 +21,7 @@ import ( "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) @@ -63,6 +64,7 @@ func TestAdmitAndValidate(t *testing.T) { name string ns string operation Operation + options runtime.Object chain chainAdmissionHandler accept bool calls map[string]bool @@ -71,6 +73,7 @@ func TestAdmitAndValidate(t *testing.T) { name: "all accept", ns: sysns, operation: Create, + options: &metav1.CreateOptions{}, chain: []Interface{ makeHandler("a", true, Update, Delete, Create), makeHandler("b", true, Delete, Create), @@ -83,6 +86,7 @@ func TestAdmitAndValidate(t *testing.T) { name: "ignore handler", ns: otherns, operation: Create, + options: &metav1.CreateOptions{}, chain: []Interface{ makeHandler("a", true, Update, Delete, Create), makeHandler("b", false, Delete), @@ -95,6 +99,7 @@ func TestAdmitAndValidate(t *testing.T) { name: "ignore all", ns: sysns, operation: Connect, + options: nil, chain: []Interface{ makeHandler("a", true, Update, Delete, Create), makeHandler("b", false, Delete), @@ -107,6 +112,7 @@ func TestAdmitAndValidate(t *testing.T) { name: "reject one", ns: otherns, operation: Delete, + options: &metav1.DeleteOptions{}, chain: []Interface{ makeHandler("a", true, Update, Delete, Create), makeHandler("b", false, Delete), @@ -119,7 +125,7 @@ func TestAdmitAndValidate(t *testing.T) { for _, test := range tests { t.Logf("testcase = %s", test.name) // call admit and check that validate was not called at all - err := test.chain.Admit(NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, false, nil), nil) + err := test.chain.Admit(NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, test.options, false, nil), nil) accepted := (err == nil) if accepted != test.accept { t.Errorf("unexpected result of admit call: %v", accepted) @@ -140,7 +146,7 @@ func TestAdmitAndValidate(t *testing.T) { } // call validate and check that admit was not called at all - err = test.chain.Validate(NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, false, nil), nil) + err = test.chain.Validate(NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, test.options, false, nil), nil) accepted = (err == nil) if accepted != test.accept { t.Errorf("unexpected result of validate call: %v\n", accepted) diff --git a/staging/src/k8s.io/apiserver/pkg/admission/errors_test.go b/staging/src/k8s.io/apiserver/pkg/admission/errors_test.go index 871d7a57156..5c60c91f605 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/errors_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/errors_test.go @@ -36,6 +36,7 @@ func TestNewForbidden(t *testing.T) { schema.GroupVersionResource{Group: "foo", Version: "bar", Resource: "baz"}, "", Create, + nil, false, nil) err := errors.New("some error") diff --git a/staging/src/k8s.io/apiserver/pkg/admission/metrics/BUILD b/staging/src/k8s.io/apiserver/pkg/admission/metrics/BUILD index 7df816a7a21..e0f92b550d1 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/metrics/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/admission/metrics/BUILD @@ -20,6 +20,8 @@ go_test( ], embed = [":go_default_library"], deps = [ + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", diff --git a/staging/src/k8s.io/apiserver/pkg/admission/metrics/metrics_test.go b/staging/src/k8s.io/apiserver/pkg/admission/metrics/metrics_test.go index c0ce0bc1ef3..2934b624b9b 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/metrics/metrics_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/metrics/metrics_test.go @@ -21,6 +21,8 @@ import ( "testing" "time" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/admission" ) @@ -28,7 +30,7 @@ import ( var ( kind = schema.GroupVersionKind{Group: "kgroup", Version: "kversion", Kind: "kind"} resource = schema.GroupVersionResource{Group: "rgroup", Version: "rversion", Resource: "resource"} - attr = admission.NewAttributesRecord(nil, nil, kind, "ns", "name", resource, "subresource", admission.Create, false, nil) + attr = admission.NewAttributesRecord(nil, nil, kind, "ns", "name", resource, "subresource", admission.Create, &metav1.CreateOptions{}, false, nil) ) func TestObserveAdmissionStep(t *testing.T) { @@ -85,6 +87,7 @@ func TestWithMetrics(t *testing.T) { name string ns string operation admission.Operation + options runtime.Object handler admission.Interface admit, validate bool } @@ -93,6 +96,7 @@ func TestWithMetrics(t *testing.T) { "both-interfaces-admit-and-validate", "some-ns", admission.Create, + &metav1.CreateOptions{}, &mutatingAndValidatingFakeHandler{admission.NewHandler(admission.Create, admission.Update), true, true}, true, true, }, @@ -100,6 +104,7 @@ func TestWithMetrics(t *testing.T) { "both-interfaces-dont-admit", "some-ns", admission.Create, + &metav1.CreateOptions{}, &mutatingAndValidatingFakeHandler{admission.NewHandler(admission.Create, admission.Update), false, true}, false, true, }, @@ -107,6 +112,7 @@ func TestWithMetrics(t *testing.T) { "both-interfaces-admit-dont-validate", "some-ns", admission.Create, + &metav1.CreateOptions{}, &mutatingAndValidatingFakeHandler{admission.NewHandler(admission.Create, admission.Update), true, false}, true, false, }, @@ -114,6 +120,7 @@ func TestWithMetrics(t *testing.T) { "validate-interfaces-validate", "some-ns", admission.Create, + &metav1.CreateOptions{}, &validatingFakeHandler{admission.NewHandler(admission.Create, admission.Update), true}, true, true, }, @@ -121,6 +128,7 @@ func TestWithMetrics(t *testing.T) { "validate-interfaces-dont-validate", "some-ns", admission.Create, + &metav1.CreateOptions{}, &validatingFakeHandler{admission.NewHandler(admission.Create, admission.Update), false}, true, false, }, @@ -128,6 +136,7 @@ func TestWithMetrics(t *testing.T) { "mutating-interfaces-admit", "some-ns", admission.Create, + &metav1.CreateOptions{}, &mutatingFakeHandler{admission.NewHandler(admission.Create, admission.Update), true}, true, true, }, @@ -135,6 +144,7 @@ func TestWithMetrics(t *testing.T) { "mutating-interfaces-dont-admit", "some-ns", admission.Create, + &metav1.CreateOptions{}, &mutatingFakeHandler{admission.NewHandler(admission.Create, admission.Update), false}, false, true, }, @@ -144,7 +154,7 @@ func TestWithMetrics(t *testing.T) { h := WithMetrics(test.handler, Metrics.ObserveAdmissionController, test.name) // test mutation - err := h.(admission.MutationInterface).Admit(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, false, nil), nil) + err := h.(admission.MutationInterface).Admit(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, test.options, false, nil), nil) if test.admit && err != nil { t.Errorf("expected admit to succeed, but failed: %v", err) continue @@ -169,7 +179,7 @@ func TestWithMetrics(t *testing.T) { } // test validation - err = h.(admission.ValidationInterface).Validate(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, false, nil), nil) + err = h.(admission.ValidationInterface).Validate(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, test.options, false, nil), nil) if test.validate && err != nil { t.Errorf("expected admit to succeed, but failed: %v", err) continue diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle/admission_test.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle/admission_test.go index 593c107dbf0..ccc17392ee0 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle/admission_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle/admission_test.go @@ -21,7 +21,7 @@ import ( "testing" "time" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -104,7 +104,7 @@ func TestAccessReviewCheckOnMissingNamespace(t *testing.T) { } informerFactory.Start(wait.NeverStop) - err = handler.Admit(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{Group: "authorization.k8s.io", Version: "v1", Kind: "LocalSubjectAccesReview"}, namespace, "", schema.GroupVersionResource{Group: "authorization.k8s.io", Version: "v1", Resource: "localsubjectaccessreviews"}, "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{Group: "authorization.k8s.io", Version: "v1", Kind: "LocalSubjectAccesReview"}, namespace, "", schema.GroupVersionResource{Group: "authorization.k8s.io", Version: "v1", Resource: "localsubjectaccessreviews"}, "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Error(err) } @@ -124,7 +124,7 @@ func TestAdmissionNamespaceDoesNotExist(t *testing.T) { informerFactory.Start(wait.NeverStop) pod := newPod(namespace) - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { actions := "" for _, action := range mockClient.Actions() { @@ -134,19 +134,19 @@ func TestAdmissionNamespaceDoesNotExist(t *testing.T) { } // verify create operations in the namespace cause an error - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected error rejecting creates in a namespace when it is missing") } // verify update operations in the namespace cause an error - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Update, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected error rejecting updates in a namespace when it is missing") } // verify delete operations in the namespace can proceed - err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Delete, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } @@ -166,7 +166,7 @@ func TestAdmissionNamespaceActive(t *testing.T) { informerFactory.Start(wait.NeverStop) pod := newPod(namespace) - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("unexpected error returned from admission handler") } @@ -187,31 +187,31 @@ func TestAdmissionNamespaceTerminating(t *testing.T) { pod := newPod(namespace) // verify create operations in the namespace cause an error - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected error rejecting creates in a namespace when it is terminating") } // verify update operations in the namespace can proceed - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Update, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } // verify delete operations in the namespace can proceed - err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Delete, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } // verify delete of namespace default can never proceed - err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Namespace").GroupKind().WithVersion("version"), "", metav1.NamespaceDefault, v1.Resource("namespaces").WithVersion("version"), "", admission.Delete, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Namespace").GroupKind().WithVersion("version"), "", metav1.NamespaceDefault, v1.Resource("namespaces").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected an error that this namespace can never be deleted") } // verify delete of namespace other than default can proceed - err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Namespace").GroupKind().WithVersion("version"), "", "other", v1.Resource("namespaces").WithVersion("version"), "", admission.Delete, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Namespace").GroupKind().WithVersion("version"), "", "other", v1.Resource("namespaces").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil) if err != nil { t.Errorf("Did not expect an error %v", err) } @@ -238,7 +238,7 @@ func TestAdmissionNamespaceForceLiveLookup(t *testing.T) { pod := newPod(namespace) // verify create operations in the namespace is allowed - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err != nil { t.Errorf("Unexpected error rejecting creates in an active namespace") } @@ -248,7 +248,7 @@ func TestAdmissionNamespaceForceLiveLookup(t *testing.T) { getCalls = 0 // verify delete of namespace can proceed - err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Namespace").GroupKind().WithVersion("version"), namespace, namespace, v1.Resource("namespaces").WithVersion("version"), "", admission.Delete, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Namespace").GroupKind().WithVersion("version"), namespace, namespace, v1.Resource("namespaces").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil) if err != nil { t.Errorf("Expected namespace deletion to be allowed") } @@ -261,7 +261,7 @@ func TestAdmissionNamespaceForceLiveLookup(t *testing.T) { phases[namespace] = v1.NamespaceTerminating // verify create operations in the namespace cause an error - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected error rejecting creates in a namespace right after deleting it") } @@ -274,7 +274,7 @@ func TestAdmissionNamespaceForceLiveLookup(t *testing.T) { fakeClock.Step(forceLiveLookupTTL) // verify create operations in the namespace cause an error - err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if err == nil { t.Errorf("Expected error rejecting creates in a namespace right after deleting it") } @@ -287,7 +287,7 @@ func TestAdmissionNamespaceForceLiveLookup(t *testing.T) { fakeClock.Step(time.Millisecond) // verify create operations in the namespace don't force a live lookup after the timeout - handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, false, nil), nil) + handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil) if getCalls != 0 { t.Errorf("Expected no live lookup of the namespace at t=forceLiveLookupTTL+1ms, got %d", getCalls) } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher_test.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher_test.go index 53bcf0124dc..a38f6387d67 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher_test.go @@ -122,7 +122,7 @@ func TestDispatch(t *testing.T) { plugin: &Plugin{}, } attr := generic.VersionedAttributes{ - Attributes: admission.NewAttributesRecord(test.out, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", admission.Operation(""), false, nil), + Attributes: admission.NewAttributesRecord(test.out, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", admission.Operation(""), nil, false, nil), VersionedOldObject: nil, VersionedObject: test.in, } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace/matcher_test.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace/matcher_test.go index bf7dee828c9..616ff7bbe31 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace/matcher_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace/matcher_test.go @@ -75,27 +75,27 @@ func TestGetNamespaceLabels(t *testing.T) { }{ { name: "request is for creating namespace, the labels should be from the object itself", - attr: admission.NewAttributesRecord(&namespace2, nil, schema.GroupVersionKind{}, "", namespace2.Name, schema.GroupVersionResource{Resource: "namespaces"}, "", admission.Create, false, nil), + attr: admission.NewAttributesRecord(&namespace2, nil, schema.GroupVersionKind{}, "", namespace2.Name, schema.GroupVersionResource{Resource: "namespaces"}, "", admission.Create, &metav1.CreateOptions{}, false, nil), expectedLabels: namespace2Labels, }, { name: "request is for updating namespace, the labels should be from the new object", - attr: admission.NewAttributesRecord(&namespace2, nil, schema.GroupVersionKind{}, namespace2.Name, namespace2.Name, schema.GroupVersionResource{Resource: "namespaces"}, "", admission.Update, false, nil), + attr: admission.NewAttributesRecord(&namespace2, nil, schema.GroupVersionKind{}, namespace2.Name, namespace2.Name, schema.GroupVersionResource{Resource: "namespaces"}, "", admission.Update, &metav1.UpdateOptions{}, false, nil), expectedLabels: namespace2Labels, }, { name: "request is for deleting namespace, the labels should be from the cache", - attr: admission.NewAttributesRecord(&namespace2, nil, schema.GroupVersionKind{}, namespace1.Name, namespace1.Name, schema.GroupVersionResource{Resource: "namespaces"}, "", admission.Delete, false, nil), + attr: admission.NewAttributesRecord(&namespace2, nil, schema.GroupVersionKind{}, namespace1.Name, namespace1.Name, schema.GroupVersionResource{Resource: "namespaces"}, "", admission.Delete, &metav1.DeleteOptions{}, false, nil), expectedLabels: namespace1Labels, }, { name: "request is for namespace/finalizer", - attr: admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, namespace1.Name, "mock-name", schema.GroupVersionResource{Resource: "namespaces"}, "finalizers", admission.Create, false, nil), + attr: admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, namespace1.Name, "mock-name", schema.GroupVersionResource{Resource: "namespaces"}, "finalizers", admission.Create, &metav1.CreateOptions{}, false, nil), expectedLabels: namespace1Labels, }, { name: "request is for pod", - attr: admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, namespace1.Name, "mock-name", schema.GroupVersionResource{Resource: "pods"}, "", admission.Create, false, nil), + attr: admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, namespace1.Name, "mock-name", schema.GroupVersionResource{Resource: "pods"}, "", admission.Create, &metav1.CreateOptions{}, false, nil), expectedLabels: namespace1Labels, }, } @@ -117,7 +117,7 @@ func TestNotExemptClusterScopedResource(t *testing.T) { hook := ®istrationv1beta1.Webhook{ NamespaceSelector: &metav1.LabelSelector{}, } - attr := admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "", "mock-name", schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, "", admission.Create, false, nil) + attr := admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "", "mock-name", schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, "", admission.Create, &metav1.CreateOptions{}, false, nil) matcher := Matcher{} matches, err := matcher.MatchNamespaceSelector(hook, attr) if err != nil { diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules/BUILD b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules/BUILD index e48ba5583f1..9b22e407f13 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules/BUILD @@ -20,6 +20,8 @@ go_test( embed = [":go_default_library"], deps = [ "//staging/src/k8s.io/api/admissionregistration/v1beta1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules/rules_test.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules/rules_test.go index 85fba433eb7..ac09ee9f6f8 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules/rules_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules/rules_test.go @@ -21,6 +21,8 @@ import ( "testing" adreg "k8s.io/api/admissionregistration/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apiserver/pkg/admission" @@ -33,37 +35,40 @@ type ruleTest struct { } type tests map[string]ruleTest -func a(group, version, resource, subresource, name string, operation admission.Operation) admission.Attributes { +func a(group, version, resource, subresource, name string, operation admission.Operation, operationOptions runtime.Object) admission.Attributes { return admission.NewAttributesRecord( nil, nil, schema.GroupVersionKind{Group: group, Version: version, Kind: "k" + resource}, "ns", name, schema.GroupVersionResource{Group: group, Version: version, Resource: resource}, subresource, operation, + operationOptions, false, nil, ) } -func namespacedAttributes(group, version, resource, subresource, name string, operation admission.Operation) admission.Attributes { +func namespacedAttributes(group, version, resource, subresource, name string, operation admission.Operation, operationOptions runtime.Object) admission.Attributes { return admission.NewAttributesRecord( nil, nil, schema.GroupVersionKind{Group: group, Version: version, Kind: "k" + resource}, "ns", name, schema.GroupVersionResource{Group: group, Version: version, Resource: resource}, subresource, operation, + operationOptions, false, nil, ) } -func clusterScopedAttributes(group, version, resource, subresource, name string, operation admission.Operation) admission.Attributes { +func clusterScopedAttributes(group, version, resource, subresource, name string, operation admission.Operation, operationOptions runtime.Object) admission.Attributes { return admission.NewAttributesRecord( nil, nil, schema.GroupVersionKind{Group: group, Version: version, Kind: "k" + resource}, "", name, schema.GroupVersionResource{Group: group, Version: version, Resource: resource}, subresource, operation, + operationOptions, false, nil, ) @@ -82,7 +87,7 @@ func TestGroup(t *testing.T) { }, }, match: attrList( - a("g", "v", "r", "", "name", admission.Create), + a("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), ), }, "exact": { @@ -92,12 +97,12 @@ func TestGroup(t *testing.T) { }, }, match: attrList( - a("g1", "v", "r", "", "name", admission.Create), - a("g2", "v2", "r3", "", "name", admission.Create), + a("g1", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("g2", "v2", "r3", "", "name", admission.Create, &metav1.CreateOptions{}), ), noMatch: attrList( - a("g3", "v", "r", "", "name", admission.Create), - a("g4", "v", "r", "", "name", admission.Create), + a("g3", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("g4", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), ), }, } @@ -127,7 +132,7 @@ func TestVersion(t *testing.T) { }, }, match: attrList( - a("g", "v", "r", "", "name", admission.Create), + a("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), ), }, "exact": { @@ -137,12 +142,12 @@ func TestVersion(t *testing.T) { }, }, match: attrList( - a("g1", "v1", "r", "", "name", admission.Create), - a("g2", "v2", "r", "", "name", admission.Create), + a("g1", "v1", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("g2", "v2", "r", "", "name", admission.Create, &metav1.CreateOptions{}), ), noMatch: attrList( - a("g1", "v3", "r", "", "name", admission.Create), - a("g2", "v4", "r", "", "name", admission.Create), + a("g1", "v3", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("g2", "v4", "r", "", "name", admission.Create, &metav1.CreateOptions{}), ), }, } @@ -167,65 +172,65 @@ func TestOperation(t *testing.T) { "wildcard": { rule: adreg.RuleWithOperations{Operations: []adreg.OperationType{adreg.OperationAll}}, match: attrList( - a("g", "v", "r", "", "name", admission.Create), - a("g", "v", "r", "", "name", admission.Update), - a("g", "v", "r", "", "name", admission.Delete), - a("g", "v", "r", "", "name", admission.Connect), + a("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("g", "v", "r", "", "name", admission.Update, &metav1.UpdateOptions{}), + a("g", "v", "r", "", "name", admission.Delete, &metav1.DeleteOptions{}), + a("g", "v", "r", "", "name", admission.Connect, nil), ), }, "create": { rule: adreg.RuleWithOperations{Operations: []adreg.OperationType{adreg.Create}}, match: attrList( - a("g", "v", "r", "", "name", admission.Create), + a("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), ), noMatch: attrList( - a("g", "v", "r", "", "name", admission.Update), - a("g", "v", "r", "", "name", admission.Delete), - a("g", "v", "r", "", "name", admission.Connect), + a("g", "v", "r", "", "name", admission.Update, &metav1.UpdateOptions{}), + a("g", "v", "r", "", "name", admission.Delete, &metav1.DeleteOptions{}), + a("g", "v", "r", "", "name", admission.Connect, nil), ), }, "update": { rule: adreg.RuleWithOperations{Operations: []adreg.OperationType{adreg.Update}}, match: attrList( - a("g", "v", "r", "", "name", admission.Update), + a("g", "v", "r", "", "name", admission.Update, &metav1.UpdateOptions{}), ), noMatch: attrList( - a("g", "v", "r", "", "name", admission.Create), - a("g", "v", "r", "", "name", admission.Delete), - a("g", "v", "r", "", "name", admission.Connect), + a("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("g", "v", "r", "", "name", admission.Delete, &metav1.DeleteOptions{}), + a("g", "v", "r", "", "name", admission.Connect, nil), ), }, "delete": { rule: adreg.RuleWithOperations{Operations: []adreg.OperationType{adreg.Delete}}, match: attrList( - a("g", "v", "r", "", "name", admission.Delete), + a("g", "v", "r", "", "name", admission.Delete, &metav1.DeleteOptions{}), ), noMatch: attrList( - a("g", "v", "r", "", "name", admission.Create), - a("g", "v", "r", "", "name", admission.Update), - a("g", "v", "r", "", "name", admission.Connect), + a("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("g", "v", "r", "", "name", admission.Update, &metav1.UpdateOptions{}), + a("g", "v", "r", "", "name", admission.Connect, nil), ), }, "connect": { rule: adreg.RuleWithOperations{Operations: []adreg.OperationType{adreg.Connect}}, match: attrList( - a("g", "v", "r", "", "name", admission.Connect), + a("g", "v", "r", "", "name", admission.Connect, nil), ), noMatch: attrList( - a("g", "v", "r", "", "name", admission.Create), - a("g", "v", "r", "", "name", admission.Update), - a("g", "v", "r", "", "name", admission.Delete), + a("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("g", "v", "r", "", "name", admission.Update, &metav1.UpdateOptions{}), + a("g", "v", "r", "", "name", admission.Delete, &metav1.DeleteOptions{}), ), }, "multiple": { rule: adreg.RuleWithOperations{Operations: []adreg.OperationType{adreg.Update, adreg.Delete}}, match: attrList( - a("g", "v", "r", "", "name", admission.Update), - a("g", "v", "r", "", "name", admission.Delete), + a("g", "v", "r", "", "name", admission.Update, &metav1.UpdateOptions{}), + a("g", "v", "r", "", "name", admission.Delete, &metav1.DeleteOptions{}), ), noMatch: attrList( - a("g", "v", "r", "", "name", admission.Create), - a("g", "v", "r", "", "name", admission.Connect), + a("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("g", "v", "r", "", "name", admission.Connect, nil), ), }, } @@ -254,12 +259,12 @@ func TestResource(t *testing.T) { }, }, match: attrList( - a("g", "v", "r", "", "name", admission.Create), - a("2", "v", "r2", "", "name", admission.Create), + a("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("2", "v", "r2", "", "name", admission.Create, &metav1.CreateOptions{}), ), noMatch: attrList( - a("g", "v", "r", "exec", "name", admission.Create), - a("2", "v", "r2", "proxy", "name", admission.Create), + a("g", "v", "r", "exec", "name", admission.Create, &metav1.CreateOptions{}), + a("2", "v", "r2", "proxy", "name", admission.Create, &metav1.CreateOptions{}), ), }, "r & subresources": { @@ -269,12 +274,12 @@ func TestResource(t *testing.T) { }, }, match: attrList( - a("g", "v", "r", "", "name", admission.Create), - a("g", "v", "r", "exec", "name", admission.Create), + a("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("g", "v", "r", "exec", "name", admission.Create, &metav1.CreateOptions{}), ), noMatch: attrList( - a("2", "v", "r2", "", "name", admission.Create), - a("2", "v", "r2", "proxy", "name", admission.Create), + a("2", "v", "r2", "", "name", admission.Create, &metav1.CreateOptions{}), + a("2", "v", "r2", "proxy", "name", admission.Create, &metav1.CreateOptions{}), ), }, "r & subresources or r2": { @@ -284,12 +289,12 @@ func TestResource(t *testing.T) { }, }, match: attrList( - a("g", "v", "r", "", "name", admission.Create), - a("g", "v", "r", "exec", "name", admission.Create), - a("2", "v", "r2", "", "name", admission.Create), + a("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("g", "v", "r", "exec", "name", admission.Create, &metav1.CreateOptions{}), + a("2", "v", "r2", "", "name", admission.Create, &metav1.CreateOptions{}), ), noMatch: attrList( - a("2", "v", "r2", "proxy", "name", admission.Create), + a("2", "v", "r2", "proxy", "name", admission.Create, &metav1.CreateOptions{}), ), }, "proxy or exec": { @@ -299,14 +304,14 @@ func TestResource(t *testing.T) { }, }, match: attrList( - a("g", "v", "r", "exec", "name", admission.Create), - a("2", "v", "r2", "proxy", "name", admission.Create), - a("2", "v", "r3", "proxy", "name", admission.Create), + a("g", "v", "r", "exec", "name", admission.Create, &metav1.CreateOptions{}), + a("2", "v", "r2", "proxy", "name", admission.Create, &metav1.CreateOptions{}), + a("2", "v", "r3", "proxy", "name", admission.Create, &metav1.CreateOptions{}), ), noMatch: attrList( - a("g", "v", "r", "", "name", admission.Create), - a("2", "v", "r2", "", "name", admission.Create), - a("2", "v", "r4", "scale", "name", admission.Create), + a("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + a("2", "v", "r2", "", "name", admission.Create, &metav1.CreateOptions{}), + a("2", "v", "r4", "scale", "name", admission.Create, &metav1.CreateOptions{}), ), }, } @@ -339,16 +344,16 @@ func TestScope(t *testing.T) { }, }, match: attrList( - clusterScopedAttributes("g", "v", "r", "", "name", admission.Create), - clusterScopedAttributes("g", "v", "r", "exec", "name", admission.Create), - clusterScopedAttributes("", "v1", "namespaces", "", "ns", admission.Create), - clusterScopedAttributes("", "v1", "namespaces", "finalize", "ns", admission.Create), - namespacedAttributes("", "v1", "namespaces", "", "ns", admission.Create), - namespacedAttributes("", "v1", "namespaces", "finalize", "ns", admission.Create), + clusterScopedAttributes("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + clusterScopedAttributes("g", "v", "r", "exec", "name", admission.Create, &metav1.CreateOptions{}), + clusterScopedAttributes("", "v1", "namespaces", "", "ns", admission.Create, &metav1.CreateOptions{}), + clusterScopedAttributes("", "v1", "namespaces", "finalize", "ns", admission.Create, &metav1.CreateOptions{}), + namespacedAttributes("", "v1", "namespaces", "", "ns", admission.Create, &metav1.CreateOptions{}), + namespacedAttributes("", "v1", "namespaces", "finalize", "ns", admission.Create, &metav1.CreateOptions{}), ), noMatch: attrList( - namespacedAttributes("g", "v", "r", "", "name", admission.Create), - namespacedAttributes("g", "v", "r", "exec", "name", admission.Create), + namespacedAttributes("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + namespacedAttributes("g", "v", "r", "exec", "name", admission.Create, &metav1.CreateOptions{}), ), }, "namespace scope": { @@ -359,16 +364,16 @@ func TestScope(t *testing.T) { }, }, match: attrList( - namespacedAttributes("g", "v", "r", "", "name", admission.Create), - namespacedAttributes("g", "v", "r", "exec", "name", admission.Create), + namespacedAttributes("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + namespacedAttributes("g", "v", "r", "exec", "name", admission.Create, &metav1.CreateOptions{}), ), noMatch: attrList( - clusterScopedAttributes("", "v1", "namespaces", "", "ns", admission.Create), - clusterScopedAttributes("", "v1", "namespaces", "finalize", "ns", admission.Create), - namespacedAttributes("", "v1", "namespaces", "", "ns", admission.Create), - namespacedAttributes("", "v1", "namespaces", "finalize", "ns", admission.Create), - clusterScopedAttributes("g", "v", "r", "", "name", admission.Create), - clusterScopedAttributes("g", "v", "r", "exec", "name", admission.Create), + clusterScopedAttributes("", "v1", "namespaces", "", "ns", admission.Create, &metav1.CreateOptions{}), + clusterScopedAttributes("", "v1", "namespaces", "finalize", "ns", admission.Create, &metav1.CreateOptions{}), + namespacedAttributes("", "v1", "namespaces", "", "ns", admission.Create, &metav1.CreateOptions{}), + namespacedAttributes("", "v1", "namespaces", "finalize", "ns", admission.Create, &metav1.CreateOptions{}), + clusterScopedAttributes("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + clusterScopedAttributes("g", "v", "r", "exec", "name", admission.Create, &metav1.CreateOptions{}), ), }, "all scopes": { @@ -379,14 +384,14 @@ func TestScope(t *testing.T) { }, }, match: attrList( - namespacedAttributes("g", "v", "r", "", "name", admission.Create), - namespacedAttributes("g", "v", "r", "exec", "name", admission.Create), - clusterScopedAttributes("g", "v", "r", "", "name", admission.Create), - clusterScopedAttributes("g", "v", "r", "exec", "name", admission.Create), - clusterScopedAttributes("", "v1", "namespaces", "", "ns", admission.Create), - clusterScopedAttributes("", "v1", "namespaces", "finalize", "ns", admission.Create), - namespacedAttributes("", "v1", "namespaces", "", "ns", admission.Create), - namespacedAttributes("", "v1", "namespaces", "finalize", "ns", admission.Create), + namespacedAttributes("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + namespacedAttributes("g", "v", "r", "exec", "name", admission.Create, &metav1.CreateOptions{}), + clusterScopedAttributes("g", "v", "r", "", "name", admission.Create, &metav1.CreateOptions{}), + clusterScopedAttributes("g", "v", "r", "exec", "name", admission.Create, &metav1.CreateOptions{}), + clusterScopedAttributes("", "v1", "namespaces", "", "ns", admission.Create, &metav1.CreateOptions{}), + clusterScopedAttributes("", "v1", "namespaces", "finalize", "ns", admission.Create, &metav1.CreateOptions{}), + namespacedAttributes("", "v1", "namespaces", "", "ns", admission.Create, &metav1.CreateOptions{}), + namespacedAttributes("", "v1", "namespaces", "finalize", "ns", admission.Create, &metav1.CreateOptions{}), ), noMatch: attrList(), }, diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/testcase.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/testcase.go index b99d8ab45b1..250ce00ab04 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/testcase.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/testcase.go @@ -101,9 +101,10 @@ func newAttributesRecord(object metav1.Object, oldObject metav1.Object, kind sch Name: "webhook-test", UID: "webhook-test", } + options := &metav1.UpdateOptions{} return &FakeAttributes{ - Attributes: admission.NewAttributesRecord(object.(runtime.Object), oldObject.(runtime.Object), kind, namespace, name, gvr, subResource, admission.Update, dryRun, &userInfo), + Attributes: admission.NewAttributesRecord(object.(runtime.Object), oldObject.(runtime.Object), kind, namespace, name, gvr, subResource, admission.Update, options, dryRun, &userInfo), } } diff --git a/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission_test.go b/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission_test.go index a6479aa1a98..c4c2d8628e1 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission_test.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission_test.go @@ -136,6 +136,7 @@ func TestBanflunderAdmissionPlugin(t *testing.T) { scenario.admissionInputResource, "", admission.Create, + &metav1.CreateOptions{}, false, nil), nil, diff --git a/test/integration/apiserver/admissionwebhook/admission_test.go b/test/integration/apiserver/admissionwebhook/admission_test.go index bd506e4dcf1..eeae7e0c82a 100644 --- a/test/integration/apiserver/admissionwebhook/admission_test.go +++ b/test/integration/apiserver/admissionwebhook/admission_test.go @@ -151,9 +151,11 @@ type holder struct { recordNamespace string recordName string - expectGVK schema.GroupVersionKind - expectObject bool - expectOldObject bool + expectGVK schema.GroupVersionKind + expectObject bool + expectOldObject bool + expectOptionsGVK schema.GroupVersionKind + expectOptions bool recorded map[string]*v1beta1.AdmissionRequest } @@ -169,12 +171,14 @@ func (h *holder) reset(t *testing.T) { h.recordNamespace = "" h.expectObject = false h.expectOldObject = false + h.expectOptionsGVK = schema.GroupVersionKind{} + h.expectOptions = false h.recorded = map[string]*v1beta1.AdmissionRequest{ mutation: nil, validation: nil, } } -func (h *holder) expect(gvr schema.GroupVersionResource, gvk schema.GroupVersionKind, operation v1beta1.Operation, name, namespace string, object, oldObject bool) { +func (h *holder) expect(gvr schema.GroupVersionResource, gvk, optionsGVK schema.GroupVersionKind, operation v1beta1.Operation, name, namespace string, object, oldObject, options bool) { // Special-case namespaces, since the object name shows up in request attributes for update/delete requests if len(namespace) == 0 && gvk.Group == "" && gvk.Version == "v1" && gvk.Kind == "Namespace" && operation != v1beta1.Create { namespace = name @@ -189,6 +193,8 @@ func (h *holder) expect(gvr schema.GroupVersionResource, gvk schema.GroupVersion h.recordNamespace = namespace h.expectObject = object h.expectOldObject = oldObject + h.expectOptionsGVK = optionsGVK + h.expectOptions = options h.recorded = map[string]*v1beta1.AdmissionRequest{ mutation: nil, validation: nil, @@ -283,6 +289,14 @@ func (h *holder) verifyRequest(request *v1beta1.AdmissionRequest) error { return fmt.Errorf("unexpected old object: %#v", request.OldObject.Object) } + if h.expectOptions { + if err := h.verifyOptions(request.Options.Object); err != nil { + return fmt.Errorf("options error: %v", err) + } + } else if request.Options.Object != nil { + return fmt.Errorf("unexpected options: %#v", request.Options.Object) + } + return nil } @@ -296,6 +310,16 @@ func (h *holder) verifyObject(obj runtime.Object) error { return nil } +func (h *holder) verifyOptions(options runtime.Object) error { + if options == nil { + return fmt.Errorf("no options sent") + } + if options.GetObjectKind().GroupVersionKind() != h.expectOptionsGVK { + return fmt.Errorf("expected %#v, got %#v", h.expectOptionsGVK, options.GetObjectKind().GroupVersionKind()) + } + return nil +} + // TestWebhookV1beta1 tests communication between API server and webhook process. func TestWebhookV1beta1(t *testing.T) { // holder communicates expectations to webhooks, and results from webhooks @@ -456,7 +480,7 @@ func testResourceCreate(c *testContext) { if c.resource.Namespaced { ns = testNamespace } - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Create, stubObj.GetName(), ns, true, false) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), gvkCreateOptions, v1beta1.Create, stubObj.GetName(), ns, true, false, true) _, err = c.client.Resource(c.gvr).Namespace(ns).Create(stubObj, metav1.CreateOptions{}) if err != nil { c.t.Error(err) @@ -471,7 +495,7 @@ func testResourceUpdate(c *testContext) { return err } obj.SetAnnotations(map[string]string{"update": "true"}) - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Update, obj.GetName(), obj.GetNamespace(), true, true) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), gvkUpdateOptions, v1beta1.Update, obj.GetName(), obj.GetNamespace(), true, true, true) _, err = c.client.Resource(c.gvr).Namespace(obj.GetNamespace()).Update(obj, metav1.UpdateOptions{}) return err }); err != nil { @@ -486,7 +510,7 @@ func testResourcePatch(c *testContext) { c.t.Error(err) return } - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Update, obj.GetName(), obj.GetNamespace(), true, true) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), gvkUpdateOptions, v1beta1.Update, obj.GetName(), obj.GetNamespace(), true, true, true) _, err = c.client.Resource(c.gvr).Namespace(obj.GetNamespace()).Patch( obj.GetName(), types.MergePatchType, @@ -506,7 +530,7 @@ func testResourceDelete(c *testContext) { } background := metav1.DeletePropagationBackground zero := int64(0) - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Delete, obj.GetName(), obj.GetNamespace(), false, false) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), gvkDeleteOptions, v1beta1.Delete, obj.GetName(), obj.GetNamespace(), false, false, true) err = c.client.Resource(c.gvr).Namespace(obj.GetNamespace()).Delete(obj.GetName(), &metav1.DeleteOptions{GracePeriodSeconds: &zero, PropagationPolicy: &background}) if err != nil { c.t.Error(err) @@ -552,7 +576,7 @@ func testResourceDeletecollection(c *testContext) { } // set expectations - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Delete, "", obj.GetNamespace(), false, false) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), gvkDeleteOptions, v1beta1.Delete, "", obj.GetNamespace(), false, false, true) // delete err = c.client.Resource(c.gvr).Namespace(obj.GetNamespace()).DeleteCollection(&metav1.DeleteOptions{GracePeriodSeconds: &zero, PropagationPolicy: &background}, metav1.ListOptions{LabelSelector: "webhooktest=true"}) @@ -617,7 +641,7 @@ func testSubresourceUpdate(c *testContext) { submitObj.SetAnnotations(map[string]string{"subresourceupdate": "true"}) // set expectations - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Update, obj.GetName(), obj.GetNamespace(), true, true) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), gvkUpdateOptions, v1beta1.Update, obj.GetName(), obj.GetNamespace(), true, true, true) _, err = c.client.Resource(gvrWithoutSubresources).Namespace(obj.GetNamespace()).Update( submitObj, @@ -644,7 +668,7 @@ func testSubresourcePatch(c *testContext) { subresources := strings.Split(c.gvr.Resource, "/")[1:] // set expectations - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Update, obj.GetName(), obj.GetNamespace(), true, true) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), gvkUpdateOptions, v1beta1.Update, obj.GetName(), obj.GetNamespace(), true, true, true) _, err = c.client.Resource(gvrWithoutSubresources).Namespace(obj.GetNamespace()).Patch( obj.GetName(), @@ -680,7 +704,7 @@ func testNamespaceDelete(c *testContext) { background := metav1.DeletePropagationBackground zero := int64(0) - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Delete, obj.GetName(), obj.GetNamespace(), false, false) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), gvkDeleteOptions, v1beta1.Delete, obj.GetName(), obj.GetNamespace(), false, false, true) err = c.client.Resource(c.gvr).Namespace(obj.GetNamespace()).Delete(obj.GetName(), &metav1.DeleteOptions{GracePeriodSeconds: &zero, PropagationPolicy: &background}) if err != nil { c.t.Error(err) @@ -706,7 +730,7 @@ func testNamespaceDelete(c *testContext) { } // then run the final delete and make sure admission is called again - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Delete, obj.GetName(), obj.GetNamespace(), false, false) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), gvkDeleteOptions, v1beta1.Delete, obj.GetName(), obj.GetNamespace(), false, false, true) err = c.client.Resource(c.gvr).Namespace(obj.GetNamespace()).Delete(obj.GetName(), &metav1.DeleteOptions{GracePeriodSeconds: &zero, PropagationPolicy: &background}) if err != nil { c.t.Error(err) @@ -736,7 +760,7 @@ func testDeploymentRollback(c *testContext) { gvrWithoutSubresources.Resource = strings.Split(gvrWithoutSubresources.Resource, "/")[0] subresources := strings.Split(c.gvr.Resource, "/")[1:] - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Create, obj.GetName(), obj.GetNamespace(), true, false) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), gvkCreateOptions, v1beta1.Create, obj.GetName(), obj.GetNamespace(), true, false, true) var rollbackObj runtime.Object switch c.gvr { @@ -785,7 +809,7 @@ func testPodConnectSubresource(c *testContext) { for _, httpMethod := range []string{"GET", "POST"} { c.t.Logf("verifying %v", httpMethod) - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Connect, pod.GetName(), pod.GetNamespace(), true, false) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), schema.GroupVersionKind{}, v1beta1.Connect, pod.GetName(), pod.GetNamespace(), true, false, false) var err error switch c.gvr { case gvr("", "v1", "pods/exec"): @@ -827,7 +851,7 @@ func testPodBindingEviction(c *testContext) { } }() - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Create, pod.GetName(), pod.GetNamespace(), true, false) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), gvkCreateOptions, v1beta1.Create, pod.GetName(), pod.GetNamespace(), true, false, true) switch c.gvr { case gvr("", "v1", "bindings"): @@ -895,7 +919,7 @@ func testSubresourceProxy(c *testContext) { } // set expectations - c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), v1beta1.Connect, obj.GetName(), obj.GetNamespace(), true, false) + c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), schema.GroupVersionKind{}, v1beta1.Connect, obj.GetName(), obj.GetNamespace(), true, false, false) // run the request. we don't actually care if the request is successful, just that admission gets called as expected err = request.Resource(gvrWithoutSubresources.Resource).Name(obj.GetName()).SubResource(subresources...).Do().Error() if err != nil { @@ -918,6 +942,7 @@ func newWebhookHandler(t *testing.T, holder *holder, phase string) http.Handler t.Error(err) return } + if contentType := r.Header.Get("Content-Type"); contentType != "application/json" { t.Errorf("contentType=%s, expect application/json", contentType) return @@ -955,6 +980,16 @@ func newWebhookHandler(t *testing.T, holder *holder, phase string) http.Handler review.Request.OldObject.Object = u } + if len(review.Request.Options.Raw) > 0 { + u := &unstructured.Unstructured{Object: map[string]interface{}{}} + if err := json.Unmarshal(review.Request.Options.Raw, u); err != nil { + t.Errorf("Fail to deserialize options object: %s for admission request %#+v with error: %v", string(review.Request.Options.Raw), review.Request, err) + http.Error(w, err.Error(), 400) + return + } + review.Request.Options.Object = u + } + if review.Request.UserInfo.Username == testClientUsername { // only record requests originating from this integration test's client holder.record(phase, review.Request) @@ -1043,6 +1078,12 @@ func gvk(group, version, kind string) schema.GroupVersionKind { return schema.GroupVersionKind{Group: group, Version: version, Kind: kind} } +var ( + gvkCreateOptions = metav1.SchemeGroupVersion.WithKind("CreateOptions") + gvkUpdateOptions = metav1.SchemeGroupVersion.WithKind("UpdateOptions") + gvkDeleteOptions = metav1.SchemeGroupVersion.WithKind("DeleteOptions") +) + func shouldTestResource(gvr schema.GroupVersionResource, resource metav1.APIResource) bool { if !sets.NewString(resource.Verbs...).HasAny("create", "update", "patch", "connect", "delete", "deletecollection") { return false