diff --git a/pkg/kubeapiserver/admission/initializer_test.go b/pkg/kubeapiserver/admission/initializer_test.go index f5a6b144c6a..a1c6d106249 100644 --- a/pkg/kubeapiserver/admission/initializer_test.go +++ b/pkg/kubeapiserver/admission/initializer_test.go @@ -24,7 +24,9 @@ import ( type doNothingAdmission struct{} -func (doNothingAdmission) Admit(a admission.Attributes) error { return nil } +func (doNothingAdmission) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { + return nil +} func (doNothingAdmission) Handles(o admission.Operation) bool { return false } func (doNothingAdmission) Validate() error { return nil } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/audit.go b/staging/src/k8s.io/apiserver/pkg/admission/audit.go index 13d86b33b96..d81622b9217 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/audit.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/audit.go @@ -44,7 +44,7 @@ func WithAudit(i Interface, ae *auditinternal.Event) Interface { return &auditHandler{i, ae} } -func (handler auditHandler) Admit(a Attributes) error { +func (handler auditHandler) Admit(a Attributes, o ObjectInterfaces) error { if !handler.Interface.Handles(a.GetOperation()) { return nil } @@ -53,13 +53,13 @@ func (handler auditHandler) Admit(a Attributes) error { } var err error if mutator, ok := handler.Interface.(MutationInterface); ok { - err = mutator.Admit(a) + err = mutator.Admit(a, o) handler.logAnnotations(a) } return err } -func (handler auditHandler) Validate(a Attributes) error { +func (handler auditHandler) Validate(a Attributes, o ObjectInterfaces) error { if !handler.Interface.Handles(a.GetOperation()) { return nil } @@ -68,7 +68,7 @@ func (handler auditHandler) Validate(a Attributes) error { } var err error if validator, ok := handler.Interface.(ValidationInterface); ok { - err = validator.Validate(a) + err = validator.Validate(a, o) handler.logAnnotations(a) } return err 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 2dd88e9c9f4..0b04cf2646a 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/audit_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/audit_test.go @@ -45,14 +45,14 @@ var _ Interface = &fakeHandler{} var _ MutationInterface = &fakeHandler{} var _ ValidationInterface = &fakeHandler{} -func (h fakeHandler) Admit(a Attributes) error { +func (h fakeHandler) Admit(a Attributes, o ObjectInterfaces) error { for k, v := range h.admitAnnotations { a.AddAnnotation(k, v) } return h.admit } -func (h fakeHandler) Validate(a Attributes) error { +func (h fakeHandler) Validate(a Attributes, o ObjectInterfaces) error { for k, v := range h.validateAnnotations { a.AddAnnotation(k, v) } @@ -149,13 +149,13 @@ func TestWithAudit(t *testing.T) { require.True(t, ok) auditMutator, ok := auditHandler.(MutationInterface) require.True(t, ok) - assert.Equal(t, mutator.Admit(a), auditMutator.Admit(a), tcName+": WithAudit decorator should not effect the return value") + assert.Equal(t, mutator.Admit(a, nil), auditMutator.Admit(a, nil), tcName+": WithAudit decorator should not effect the return value") validator, ok := handler.(ValidationInterface) require.True(t, ok) auditValidator, ok := auditHandler.(ValidationInterface) require.True(t, ok) - assert.Equal(t, validator.Validate(a), auditValidator.Validate(a), tcName+": WithAudit decorator should not effect the return value") + assert.Equal(t, validator.Validate(a, nil), auditValidator.Validate(a, nil), tcName+": WithAudit decorator should not effect the return value") annotations := make(map[string]string, len(tc.admitAnnotations)+len(tc.validateAnnotations)) for k, v := range tc.admitAnnotations { diff --git a/staging/src/k8s.io/apiserver/pkg/admission/chain.go b/staging/src/k8s.io/apiserver/pkg/admission/chain.go index 011641ff065..37405aeaf04 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/chain.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/chain.go @@ -26,13 +26,13 @@ func NewChainHandler(handlers ...Interface) chainAdmissionHandler { } // Admit performs an admission control check using a chain of handlers, and returns immediately on first error -func (admissionHandler chainAdmissionHandler) Admit(a Attributes) error { +func (admissionHandler chainAdmissionHandler) Admit(a Attributes, o ObjectInterfaces) error { for _, handler := range admissionHandler { if !handler.Handles(a.GetOperation()) { continue } if mutator, ok := handler.(MutationInterface); ok { - err := mutator.Admit(a) + err := mutator.Admit(a, o) if err != nil { return err } @@ -42,13 +42,13 @@ func (admissionHandler chainAdmissionHandler) Admit(a Attributes) error { } // Validate performs an admission control check using a chain of handlers, and returns immediately on first error -func (admissionHandler chainAdmissionHandler) Validate(a Attributes) error { +func (admissionHandler chainAdmissionHandler) Validate(a Attributes, o ObjectInterfaces) error { for _, handler := range admissionHandler { if !handler.Handles(a.GetOperation()) { continue } if validator, ok := handler.(ValidationInterface); ok { - err := validator.Validate(a) + err := validator.Validate(a, o) if err != nil { return err } 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 7c3d940e1ed..20ab2faad2a 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/chain_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/chain_test.go @@ -31,7 +31,7 @@ type FakeHandler struct { validate, validateCalled bool } -func (h *FakeHandler) Admit(a Attributes) (err error) { +func (h *FakeHandler) Admit(a Attributes, o ObjectInterfaces) (err error) { h.admitCalled = true if h.admit { return nil @@ -39,7 +39,7 @@ func (h *FakeHandler) Admit(a Attributes) (err error) { return fmt.Errorf("Don't admit") } -func (h *FakeHandler) Validate(a Attributes) (err error) { +func (h *FakeHandler) Validate(a Attributes, o ObjectInterfaces) (err error) { h.validateCalled = true if h.validate { return nil @@ -119,7 +119,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)) + err := test.chain.Admit(NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, false, nil), nil) accepted := (err == nil) if accepted != test.accept { t.Errorf("unexpected result of admit call: %v", accepted) @@ -140,7 +140,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)) + err = test.chain.Validate(NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, 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/initializer/initializer_test.go b/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer_test.go index 6a72d909059..2e3a7049336 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer_test.go @@ -85,7 +85,9 @@ type WantExternalKubeInformerFactory struct { func (self *WantExternalKubeInformerFactory) SetExternalKubeInformerFactory(sf informers.SharedInformerFactory) { self.sf = sf } -func (self *WantExternalKubeInformerFactory) Admit(a admission.Attributes) error { return nil } +func (self *WantExternalKubeInformerFactory) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { + return nil +} func (self *WantExternalKubeInformerFactory) Handles(o admission.Operation) bool { return false } func (self *WantExternalKubeInformerFactory) ValidateInitialization() error { return nil } @@ -98,9 +100,11 @@ type WantExternalKubeClientSet struct { } func (self *WantExternalKubeClientSet) SetExternalKubeClientSet(cs kubernetes.Interface) { self.cs = cs } -func (self *WantExternalKubeClientSet) Admit(a admission.Attributes) error { return nil } -func (self *WantExternalKubeClientSet) Handles(o admission.Operation) bool { return false } -func (self *WantExternalKubeClientSet) ValidateInitialization() error { return nil } +func (self *WantExternalKubeClientSet) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { + return nil +} +func (self *WantExternalKubeClientSet) Handles(o admission.Operation) bool { return false } +func (self *WantExternalKubeClientSet) ValidateInitialization() error { return nil } var _ admission.Interface = &WantExternalKubeClientSet{} var _ initializer.WantsExternalKubeClientSet = &WantExternalKubeClientSet{} @@ -111,9 +115,11 @@ type WantAuthorizerAdmission struct { } func (self *WantAuthorizerAdmission) SetAuthorizer(a authorizer.Authorizer) { self.auth = a } -func (self *WantAuthorizerAdmission) Admit(a admission.Attributes) error { return nil } -func (self *WantAuthorizerAdmission) Handles(o admission.Operation) bool { return false } -func (self *WantAuthorizerAdmission) ValidateInitialization() error { return nil } +func (self *WantAuthorizerAdmission) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { + return nil +} +func (self *WantAuthorizerAdmission) Handles(o admission.Operation) bool { return false } +func (self *WantAuthorizerAdmission) ValidateInitialization() error { return nil } var _ admission.Interface = &WantAuthorizerAdmission{} var _ initializer.WantsAuthorizer = &WantAuthorizerAdmission{} @@ -130,8 +136,10 @@ type clientCertWanter struct { gotCert, gotKey []byte } -func (s *clientCertWanter) SetClientCert(cert, key []byte) { s.gotCert, s.gotKey = cert, key } -func (s *clientCertWanter) Admit(a admission.Attributes) error { return nil } +func (s *clientCertWanter) SetClientCert(cert, key []byte) { s.gotCert, s.gotKey = cert, key } +func (s *clientCertWanter) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { + return nil +} func (s *clientCertWanter) Handles(o admission.Operation) bool { return false } func (s *clientCertWanter) ValidateInitialization() error { return nil } @@ -140,8 +148,10 @@ type WantSchemeAdmission struct { scheme *runtime.Scheme } -func (self *WantSchemeAdmission) SetScheme(s *runtime.Scheme) { self.scheme = s } -func (self *WantSchemeAdmission) Admit(a admission.Attributes) error { return nil } +func (self *WantSchemeAdmission) SetScheme(s *runtime.Scheme) { self.scheme = s } +func (self *WantSchemeAdmission) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { + return nil +} func (self *WantSchemeAdmission) Handles(o admission.Operation) bool { return false } func (self *WantSchemeAdmission) ValidateInitialization() error { return nil } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go b/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go index a17c28990ab..866777cc708 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go @@ -62,6 +62,20 @@ type Attributes interface { AddAnnotation(key, value string) error } +// ObjectInterfaces is an interface used by AdmissionController to get object interfaces +// such as Converter or Defaulter. These interfaces are normally coming from Request Scope +// to handle special cases like CRDs. +type ObjectInterfaces interface { + // GetObjectCreater is the ObjectCreator appropriate for the requested object. + GetObjectCreater() runtime.ObjectCreater + // GetObjectTyper is the ObjectTyper appropriate for the requested object. + GetObjectTyper() runtime.ObjectTyper + // GetObjectDefaulter is the ObjectDefaulter appropriate for the requested object. + GetObjectDefaulter() runtime.ObjectDefaulter + // GetObjectConvertor is the ObjectConvertor appropriate for the requested object. + GetObjectConvertor() runtime.ObjectConvertor +} + // privateAnnotationsGetter is a private interface which allows users to get annotations from Attributes. type privateAnnotationsGetter interface { getAnnotations() map[string]string @@ -84,7 +98,7 @@ type MutationInterface interface { Interface // Admit makes an admission decision based on the request attributes - Admit(a Attributes) (err error) + Admit(a Attributes, o ObjectInterfaces) (err error) } // ValidationInterface is an abstract, pluggable interface for Admission Control decisions. @@ -92,7 +106,7 @@ type ValidationInterface interface { Interface // Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate - Validate(a Attributes) (err error) + Validate(a Attributes, o ObjectInterfaces) (err error) } // Operation is the type of resource operation being checked for admission control diff --git a/staging/src/k8s.io/apiserver/pkg/admission/metrics/metrics.go b/staging/src/k8s.io/apiserver/pkg/admission/metrics/metrics.go index d5514ed86a4..e5f0a6e3ab9 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/metrics/metrics.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/metrics/metrics.go @@ -75,27 +75,27 @@ type pluginHandlerWithMetrics struct { } // Admit performs a mutating admission control check and emit metrics. -func (p pluginHandlerWithMetrics) Admit(a admission.Attributes) error { +func (p pluginHandlerWithMetrics) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { mutatingHandler, ok := p.Interface.(admission.MutationInterface) if !ok { return nil } start := time.Now() - err := mutatingHandler.Admit(a) + err := mutatingHandler.Admit(a, o) p.observer(time.Since(start), err != nil, a, stepAdmit, p.extraLabels...) return err } // Validate performs a non-mutating admission control check and emits metrics. -func (p pluginHandlerWithMetrics) Validate(a admission.Attributes) error { +func (p pluginHandlerWithMetrics) Validate(a admission.Attributes, o admission.ObjectInterfaces) error { validatingHandler, ok := p.Interface.(admission.ValidationInterface) if !ok { return nil } start := time.Now() - err := validatingHandler.Validate(a) + err := validatingHandler.Validate(a, o) p.observer(time.Since(start), err != nil, a, stepValidate, p.extraLabels...) return err } 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 92c8314da03..94527ef3c01 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 @@ -34,8 +34,8 @@ var ( func TestObserveAdmissionStep(t *testing.T) { Metrics.reset() handler := WithStepMetrics(&mutatingAndValidatingFakeHandler{admission.NewHandler(admission.Create), true, true}) - handler.(admission.MutationInterface).Admit(attr) - handler.(admission.ValidationInterface).Validate(attr) + handler.(admission.MutationInterface).Admit(attr, nil) + handler.(admission.ValidationInterface).Validate(attr, nil) wantLabels := map[string]string{ "operation": string(admission.Create), "type": "admit", @@ -52,8 +52,8 @@ func TestObserveAdmissionStep(t *testing.T) { func TestObserveAdmissionController(t *testing.T) { Metrics.reset() handler := WithControllerMetrics(&mutatingAndValidatingFakeHandler{admission.NewHandler(admission.Create), true, true}, "a") - handler.(admission.MutationInterface).Admit(attr) - handler.(admission.ValidationInterface).Validate(attr) + handler.(admission.MutationInterface).Admit(attr, nil) + handler.(admission.ValidationInterface).Validate(attr, nil) wantLabels := map[string]string{ "name": "a", "operation": string(admission.Create), @@ -144,7 +144,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)) + err := h.(admission.MutationInterface).Admit(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, false, nil), nil) if test.admit && err != nil { t.Errorf("expected admit to succeed, but failed: %v", err) continue @@ -169,7 +169,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)) + err = h.(admission.ValidationInterface).Validate(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, false, nil), nil) if test.validate && err != nil { t.Errorf("expected admit to succeed, but failed: %v", err) continue @@ -196,14 +196,14 @@ type mutatingAndValidatingFakeHandler struct { validate bool } -func (h *mutatingAndValidatingFakeHandler) Admit(a admission.Attributes) (err error) { +func (h *mutatingAndValidatingFakeHandler) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) { if h.admit { return nil } return fmt.Errorf("don't admit") } -func (h *mutatingAndValidatingFakeHandler) Validate(a admission.Attributes) (err error) { +func (h *mutatingAndValidatingFakeHandler) Validate(a admission.Attributes, o admission.ObjectInterfaces) (err error) { if h.validate { return nil } @@ -215,7 +215,7 @@ type validatingFakeHandler struct { validate bool } -func (h *validatingFakeHandler) Validate(a admission.Attributes) (err error) { +func (h *validatingFakeHandler) Validate(a admission.Attributes, o admission.ObjectInterfaces) (err error) { if h.validate { return nil } @@ -227,7 +227,7 @@ type mutatingFakeHandler struct { admit bool } -func (h *mutatingFakeHandler) Admit(a admission.Attributes) (err error) { +func (h *mutatingFakeHandler) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) { if h.admit { return nil } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion.go index a75c63fa9fe..f00e0bc0154 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion.go @@ -17,39 +17,25 @@ limitations under the License. package generic import ( - "fmt" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apiserver/pkg/admission" ) -// convertor converts objects to the desired version. -type convertor struct { - Scheme *runtime.Scheme -} - // ConvertToGVK converts object to the desired gvk. -func (c *convertor) ConvertToGVK(obj runtime.Object, gvk schema.GroupVersionKind) (runtime.Object, error) { +func ConvertToGVK(obj runtime.Object, gvk schema.GroupVersionKind, o admission.ObjectInterfaces) (runtime.Object, error) { // Unlike other resources, custom resources do not have internal version, so // if obj is a custom resource, it should not need conversion. if obj.GetObjectKind().GroupVersionKind() == gvk { return obj, nil } - out, err := c.Scheme.New(gvk) + out, err := o.GetObjectCreater().New(gvk) if err != nil { return nil, err } - err = c.Scheme.Convert(obj, out, nil) + err = o.GetObjectConvertor().Convert(obj, out, nil) if err != nil { return nil, err } return out, nil } - -// Validate checks if the conversion has a scheme. -func (c *convertor) Validate() error { - if c.Scheme == nil { - return fmt.Errorf("the convertor requires a scheme") - } - return nil -} diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion_test.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion_test.go index 499853566fe..5bb70d1b4b9 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion_test.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/apis/example" examplev1 "k8s.io/apiserver/pkg/apis/example/v1" example2v1 "k8s.io/apiserver/pkg/apis/example2/v1" @@ -41,7 +42,7 @@ func initiateScheme(t *testing.T) *runtime.Scheme { func TestConvertToGVK(t *testing.T) { scheme := initiateScheme(t) - c := convertor{Scheme: scheme} + o := &admission.SchemeBasedObjectInterfaces{scheme} table := map[string]struct { obj runtime.Object gvk schema.GroupVersionKind @@ -122,7 +123,7 @@ func TestConvertToGVK(t *testing.T) { for name, test := range table { t.Run(name, func(t *testing.T) { - actual, err := c.ConvertToGVK(test.obj, test.gvk) + actual, err := ConvertToGVK(test.obj, test.gvk, o) if err != nil { t.Error(err) } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/webhook.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/webhook.go index 13b898bca9b..6cd86a51d20 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/webhook.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/webhook.go @@ -43,7 +43,6 @@ type Webhook struct { hookSource Source clientManager *webhook.ClientManager - convertor *convertor namespaceMatcher *namespace.Matcher dispatcher Dispatcher } @@ -79,7 +78,6 @@ func NewWebhook(handler *admission.Handler, configFile io.Reader, sourceFactory Handler: handler, sourceFactory: sourceFactory, clientManager: &cm, - convertor: &convertor{}, namespaceMatcher: &namespace.Matcher{}, dispatcher: dispatcherFactory(&cm), }, nil @@ -100,9 +98,6 @@ func (a *Webhook) SetServiceResolver(sr webhook.ServiceResolver) { // SetScheme sets a serializer(NegotiatedSerializer) which is derived from the scheme func (a *Webhook) SetScheme(scheme *runtime.Scheme) { - if scheme != nil { - a.convertor.Scheme = scheme - } } // SetExternalKubeClientSet implements the WantsExternalKubeInformerFactory interface. @@ -132,9 +127,6 @@ func (a *Webhook) ValidateInitialization() error { if err := a.clientManager.Validate(); err != nil { return fmt.Errorf("clientManager is not properly setup: %v", err) } - if err := a.convertor.Validate(); err != nil { - return fmt.Errorf("convertor is not properly setup: %v", err) - } return nil } @@ -156,7 +148,7 @@ func (a *Webhook) ShouldCallHook(h *v1beta1.Webhook, attr admission.Attributes) } // Dispatch is called by the downstream Validate or Admit methods. -func (a *Webhook) Dispatch(attr admission.Attributes) error { +func (a *Webhook) Dispatch(attr admission.Attributes, o admission.ObjectInterfaces) error { if rules.IsWebhookConfigurationResource(attr) { return nil } @@ -188,14 +180,14 @@ func (a *Webhook) Dispatch(attr admission.Attributes) error { Attributes: attr, } if oldObj := attr.GetOldObject(); oldObj != nil { - out, err := a.convertor.ConvertToGVK(oldObj, attr.GetKind()) + out, err := ConvertToGVK(oldObj, attr.GetKind(), o) if err != nil { return apierrors.NewInternalError(err) } versionedAttr.VersionedOldObject = out } if obj := attr.GetObject(); obj != nil { - out, err := a.convertor.ConvertToGVK(obj, attr.GetKind()) + out, err := ConvertToGVK(obj, attr.GetKind(), o) if err != nil { return apierrors.NewInternalError(err) } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin.go index 33572b24b5b..df5a2522f18 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin.go @@ -91,6 +91,6 @@ func (a *Plugin) ValidateInitialization() error { } // Admit makes an admission decision based on the request attributes. -func (a *Plugin) Admit(attr admission.Attributes) error { - return a.Webhook.Dispatch(attr) +func (a *Plugin) Admit(attr admission.Attributes, o admission.ObjectInterfaces) error { + return a.Webhook.Dispatch(attr, o) } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin_test.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin_test.go index e41f84aee43..e4ff80295e8 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin_test.go @@ -23,23 +23,15 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "k8s.io/api/admission/v1beta1" - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/admission" webhooktesting "k8s.io/apiserver/pkg/admission/plugin/webhook/testing" ) // TestAdmit tests that MutatingWebhook#Admit works as expected func TestAdmit(t *testing.T) { - scheme := runtime.NewScheme() - require.NoError(t, v1beta1.AddToScheme(scheme)) - require.NoError(t, corev1.AddToScheme(scheme)) - testServer := webhooktesting.NewTestServer(t) testServer.StartTLS() defer testServer.Close() @@ -48,6 +40,8 @@ func TestAdmit(t *testing.T) { t.Fatalf("this should never happen? %v", err) } + objectInterfaces := webhooktesting.NewObjectInterfacesForTest() + stopCh := make(chan struct{}) defer close(stopCh) @@ -66,7 +60,6 @@ func TestAdmit(t *testing.T) { wh.SetAuthenticationInfoResolverWrapper(webhooktesting.Wrapper(webhooktesting.NewAuthenticationInfoResolver(new(int32)))) wh.SetServiceResolver(webhooktesting.NewServiceResolver(*serverURL)) - wh.SetScheme(scheme) wh.SetExternalKubeClientSet(client) wh.SetExternalKubeInformerFactory(informer) @@ -85,7 +78,7 @@ func TestAdmit(t *testing.T) { attr = webhooktesting.NewAttribute(ns, tt.AdditionalLabels, tt.IsDryRun) } - err = wh.Admit(attr) + err = wh.Admit(attr, objectInterfaces) if tt.ExpectAllow != (err == nil) { t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err) } @@ -118,10 +111,6 @@ func TestAdmit(t *testing.T) { // TestAdmitCachedClient tests that MutatingWebhook#Admit should cache restClient func TestAdmitCachedClient(t *testing.T) { - scheme := runtime.NewScheme() - require.NoError(t, v1beta1.AddToScheme(scheme)) - require.NoError(t, corev1.AddToScheme(scheme)) - testServer := webhooktesting.NewTestServer(t) testServer.StartTLS() defer testServer.Close() @@ -130,6 +119,8 @@ func TestAdmitCachedClient(t *testing.T) { t.Fatalf("this should never happen? %v", err) } + objectInterfaces := webhooktesting.NewObjectInterfacesForTest() + stopCh := make(chan struct{}) defer close(stopCh) @@ -138,7 +129,6 @@ func TestAdmitCachedClient(t *testing.T) { t.Fatalf("Failed to create mutating webhook: %v", err) } wh.SetServiceResolver(webhooktesting.NewServiceResolver(*serverURL)) - wh.SetScheme(scheme) for _, tt := range webhooktesting.NewCachedClientTestcases(serverURL) { ns := "webhook-test" @@ -158,7 +148,7 @@ func TestAdmitCachedClient(t *testing.T) { continue } - err = wh.Admit(webhooktesting.NewAttribute(ns, nil, false)) + err = wh.Admit(webhooktesting.NewAttribute(ns, nil, false), objectInterfaces) if tt.ExpectAllow != (err == nil) { t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err) } 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 ad3efee0e62..a09fc8da3f9 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 @@ -649,3 +649,10 @@ func newMatchEverythingRules() []registrationv1beta1.RuleWithOperations { }, }} } + +// NewObjectInterfacesForTest returns an ObjectInterfaces appropriate for test cases in this file. +func NewObjectInterfacesForTest() admission.ObjectInterfaces { + scheme := runtime.NewScheme() + corev1.AddToScheme(scheme) + return &admission.SchemeBasedObjectInterfaces{scheme} +} diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin.go index 7f79b9d7a08..388a237c984 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin.go @@ -59,6 +59,6 @@ func NewValidatingAdmissionWebhook(configFile io.Reader) (*Plugin, error) { } // Validate makes an admission decision based on the request attributes. -func (a *Plugin) Validate(attr admission.Attributes) error { - return a.Webhook.Dispatch(attr) +func (a *Plugin) Validate(attr admission.Attributes, o admission.ObjectInterfaces) error { + return a.Webhook.Dispatch(attr, o) } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin_test.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin_test.go index 3dff3864dbc..0ed2a9744c3 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin_test.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin_test.go @@ -22,25 +22,19 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "k8s.io/api/admission/v1beta1" - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" webhooktesting "k8s.io/apiserver/pkg/admission/plugin/webhook/testing" ) // TestValidate tests that ValidatingWebhook#Validate works as expected func TestValidate(t *testing.T) { - scheme := runtime.NewScheme() - require.NoError(t, v1beta1.AddToScheme(scheme)) - require.NoError(t, corev1.AddToScheme(scheme)) - testServer := webhooktesting.NewTestServer(t) testServer.StartTLS() defer testServer.Close() + objectInterfaces := webhooktesting.NewObjectInterfacesForTest() + serverURL, err := url.ParseRequestURI(testServer.URL) if err != nil { t.Fatalf("this should never happen? %v", err) @@ -61,7 +55,6 @@ func TestValidate(t *testing.T) { wh.SetAuthenticationInfoResolverWrapper(webhooktesting.Wrapper(webhooktesting.NewAuthenticationInfoResolver(new(int32)))) wh.SetServiceResolver(webhooktesting.NewServiceResolver(*serverURL)) - wh.SetScheme(scheme) wh.SetExternalKubeClientSet(client) wh.SetExternalKubeInformerFactory(informer) @@ -74,7 +67,7 @@ func TestValidate(t *testing.T) { } attr := webhooktesting.NewAttribute(ns, nil, tt.IsDryRun) - err = wh.Validate(attr) + err = wh.Validate(attr, objectInterfaces) if tt.ExpectAllow != (err == nil) { t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err) } @@ -102,10 +95,6 @@ func TestValidate(t *testing.T) { // TestValidateCachedClient tests that ValidatingWebhook#Validate should cache restClient func TestValidateCachedClient(t *testing.T) { - scheme := runtime.NewScheme() - require.NoError(t, v1beta1.AddToScheme(scheme)) - require.NoError(t, corev1.AddToScheme(scheme)) - testServer := webhooktesting.NewTestServer(t) testServer.StartTLS() defer testServer.Close() @@ -114,6 +103,8 @@ func TestValidateCachedClient(t *testing.T) { t.Fatalf("this should never happen? %v", err) } + objectInterfaces := webhooktesting.NewObjectInterfacesForTest() + stopCh := make(chan struct{}) defer close(stopCh) @@ -122,7 +113,6 @@ func TestValidateCachedClient(t *testing.T) { t.Fatalf("Failed to create validating webhook: %v", err) } wh.SetServiceResolver(webhooktesting.NewServiceResolver(*serverURL)) - wh.SetScheme(scheme) for _, tt := range webhooktesting.NewCachedClientTestcases(serverURL) { ns := "webhook-test" @@ -142,7 +132,7 @@ func TestValidateCachedClient(t *testing.T) { continue } - err = wh.Validate(webhooktesting.NewAttribute(ns, nil, false)) + err = wh.Validate(webhooktesting.NewAttribute(ns, nil, false), objectInterfaces) if tt.ExpectAllow != (err == nil) { t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err) } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/util.go b/staging/src/k8s.io/apiserver/pkg/admission/util.go new file mode 100644 index 00000000000..61222f5d55c --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/admission/util.go @@ -0,0 +1,28 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package admission + +import "k8s.io/apimachinery/pkg/runtime" + +type SchemeBasedObjectInterfaces struct { + Scheme *runtime.Scheme +} + +func (r *SchemeBasedObjectInterfaces) GetObjectCreater() runtime.ObjectCreater { return r.Scheme } +func (r *SchemeBasedObjectInterfaces) GetObjectTyper() runtime.ObjectTyper { return r.Scheme } +func (r *SchemeBasedObjectInterfaces) GetObjectDefaulter() runtime.ObjectDefaulter { return r.Scheme } +func (r *SchemeBasedObjectInterfaces) GetObjectConvertor() runtime.ObjectConvertor { return r.Scheme } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go index 36a925c3acf..ed5d76dd7dd 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go @@ -76,7 +76,7 @@ import ( type alwaysMutatingDeny struct{} -func (alwaysMutatingDeny) Admit(a admission.Attributes) (err error) { +func (alwaysMutatingDeny) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) { return admission.NewForbidden(a, errors.New("Mutating admission control is denying all modifications")) } @@ -86,7 +86,7 @@ func (alwaysMutatingDeny) Handles(operation admission.Operation) bool { type alwaysValidatingDeny struct{} -func (alwaysValidatingDeny) Validate(a admission.Attributes) (err error) { +func (alwaysValidatingDeny) Validate(a admission.Attributes, o admission.ObjectInterfaces) (err error) { return admission.NewForbidden(a, errors.New("Validating admission control is denying all modifications")) } 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 fdb85eca6af..067675a3bb8 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go @@ -127,7 +127,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, admit admission.Inte userInfo, _ := request.UserFrom(ctx) admissionAttributes := admission.NewAttributesRecord(obj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, dryrun.IsDryRun(options.DryRun), userInfo) if mutatingAdmission, ok := admit.(admission.MutationInterface); ok && mutatingAdmission.Handles(admission.Create) { - err = mutatingAdmission.Admit(admissionAttributes) + err = mutatingAdmission.Admit(admissionAttributes, &scope) if err != nil { scope.err(err, w, req) return @@ -154,7 +154,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, admit admission.Inte ctx, name, obj, - rest.AdmissionToValidateObjectFunc(admit, admissionAttributes), + rest.AdmissionToValidateObjectFunc(admit, admissionAttributes, &scope), options, ) }) 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 4246a7fd234..a37c7f8d525 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go @@ -119,13 +119,13 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope RequestSco userInfo, _ := request.UserFrom(ctx) attrs := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Delete, dryrun.IsDryRun(options.DryRun), userInfo) if mutatingAdmission, ok := admit.(admission.MutationInterface); ok { - if err := mutatingAdmission.Admit(attrs); err != nil { + if err := mutatingAdmission.Admit(attrs, &scope); err != nil { scope.err(err, w, req) return } } if validatingAdmission, ok := admit.(admission.ValidationInterface); ok { - if err := validatingAdmission.Validate(attrs); err != nil { + if err := validatingAdmission.Validate(attrs, &scope); err != nil { scope.err(err, w, req) return } @@ -269,7 +269,7 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco userInfo, _ := request.UserFrom(ctx) attrs := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, "", scope.Resource, scope.Subresource, admission.Delete, dryrun.IsDryRun(options.DryRun), userInfo) if mutatingAdmission, ok := admit.(admission.MutationInterface); ok { - err = mutatingAdmission.Admit(attrs) + err = mutatingAdmission.Admit(attrs, &scope) if err != nil { scope.err(err, w, req) return @@ -277,7 +277,7 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco } if validatingAdmission, ok := admit.(admission.ValidationInterface); ok { - err = validatingAdmission.Validate(attrs) + err = validatingAdmission.Validate(attrs, &scope) if err != nil { scope.err(err, w, req) return 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 b257eadd494..50592c5d7ab 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go @@ -191,10 +191,12 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface subresource: scope.Subresource, dryRun: dryrun.IsDryRun(options.DryRun), + objectInterfaces: &scope, + hubGroupVersion: scope.HubGroupVersion, - createValidation: withAuthorization(rest.AdmissionToValidateObjectFunc(admit, staticCreateAttributes), scope.Authorizer, createAuthorizerAttributes), - updateValidation: rest.AdmissionToValidateObjectUpdateFunc(admit, staticUpdateAttributes), + createValidation: withAuthorization(rest.AdmissionToValidateObjectFunc(admit, staticCreateAttributes, &scope), scope.Authorizer, createAuthorizerAttributes), + updateValidation: rest.AdmissionToValidateObjectUpdateFunc(admit, staticUpdateAttributes, &scope), admissionCheck: mutatingAdmission, codec: codec, @@ -257,6 +259,8 @@ type patcher struct { subresource string dryRun bool + objectInterfaces admission.ObjectInterfaces + hubGroupVersion schema.GroupVersion // Validation functions @@ -507,7 +511,7 @@ func (p *patcher) applyAdmission(ctx context.Context, patchedObject runtime.Obje } if p.admissionCheck != nil && p.admissionCheck.Handles(operation) { attributes := p.admissionAttributes(ctx, patchedObject, currentObject, operation) - return patchedObject, p.admissionCheck.Admit(attributes) + return patchedObject, p.admissionCheck.Admit(attributes, p.objectInterfaces) } return patchedObject, nil } 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 299be6e67dc..74bb39c6d42 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go @@ -103,6 +103,13 @@ func (scope *RequestScope) AllowsStreamSchema(s string) bool { return s == "watch" } +var _ admission.ObjectInterfaces = &RequestScope{} + +func (r *RequestScope) GetObjectCreater() runtime.ObjectCreater { return r.Creater } +func (r *RequestScope) GetObjectTyper() runtime.ObjectTyper { return r.Typer } +func (r *RequestScope) GetObjectDefaulter() runtime.ObjectDefaulter { return r.Defaulter } +func (r *RequestScope) GetObjectConvertor() runtime.ObjectConvertor { return r.Convertor } + // ConnectResource returns a function that handles a connect request on a rest.Storage object. func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admission.Interface, restPath string, isSubresource bool) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { @@ -131,14 +138,14 @@ func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admissi 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)) + err = mutatingAdmission.Admit(admission.NewAttributesRecord(opts, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, 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)) + err = validatingAdmission.Validate(admission.NewAttributesRecord(opts, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, 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 f6690f86950..9ebd06786e4 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 @@ -365,6 +365,7 @@ func (tc *patchTestCase) Run(t *testing.T) { creater := runtime.ObjectCreater(scheme) defaulter := runtime.ObjectDefaulter(scheme) convertor := runtime.UnsafeObjectConvertor(scheme) + objectInterfaces := &admission.SchemeBasedObjectInterfaces{scheme} kind := examplev1.SchemeGroupVersion.WithKind("Pod") resource := examplev1.SchemeGroupVersion.WithResource("pods") schemaReferenceObj := &examplev1.Pod{} @@ -441,6 +442,8 @@ func (tc *patchTestCase) Run(t *testing.T) { kind: kind, resource: resource, + objectInterfaces: objectInterfaces, + hubGroupVersion: hubVersion, createValidation: rest.ValidateAllObjectFunc, @@ -944,6 +947,6 @@ func (f mutateObjectUpdateFunc) Handles(operation admission.Operation) bool { return true } -func (f mutateObjectUpdateFunc) Admit(a admission.Attributes) (err error) { +func (f mutateObjectUpdateFunc) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) { return f(a.GetObject(), a.GetOldObject()) } 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 bf65532143d..e55d87092fb 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go @@ -138,11 +138,11 @@ func UpdateResource(r rest.Updater, scope RequestScope, admit admission.Interfac 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)) + return newObj, mutatingAdmission.Admit(admission.NewAttributesRecord(newObj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, 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)) + 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, nil @@ -172,11 +172,11 @@ func UpdateResource(r rest.Updater, scope RequestScope, admit admission.Interfac 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)), + admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, 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)), + admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, dryrun.IsDryRun(options.DryRun), userInfo), &scope), false, options, ) 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 7d0c4a1834a..cc3c9ce4bc5 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go @@ -160,7 +160,7 @@ type NamespaceScopedStrategy interface { } // AdmissionToValidateObjectFunc converts validating admission to a rest validate object func -func AdmissionToValidateObjectFunc(admit admission.Interface, staticAttributes admission.Attributes) ValidateObjectFunc { +func AdmissionToValidateObjectFunc(admit admission.Interface, staticAttributes admission.Attributes, o admission.ObjectInterfaces) ValidateObjectFunc { validatingAdmission, ok := admit.(admission.ValidationInterface) if !ok { return func(obj runtime.Object) error { return nil } @@ -181,6 +181,6 @@ func AdmissionToValidateObjectFunc(admit admission.Interface, staticAttributes a if !validatingAdmission.Handles(finalAttributes.GetOperation()) { return nil } - return validatingAdmission.Validate(finalAttributes) + return validatingAdmission.Validate(finalAttributes, o) } } 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 290b016f427..d214e7e6a8f 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go @@ -256,7 +256,7 @@ func (i *wrappedUpdatedObjectInfo) UpdatedObject(ctx context.Context, oldObj run } // AdmissionToValidateObjectUpdateFunc converts validating admission to a rest validate object update func -func AdmissionToValidateObjectUpdateFunc(admit admission.Interface, staticAttributes admission.Attributes) ValidateObjectUpdateFunc { +func AdmissionToValidateObjectUpdateFunc(admit admission.Interface, staticAttributes admission.Attributes, o admission.ObjectInterfaces) ValidateObjectUpdateFunc { validatingAdmission, ok := admit.(admission.ValidationInterface) if !ok { return func(obj, old runtime.Object) error { return nil } @@ -277,6 +277,6 @@ func AdmissionToValidateObjectUpdateFunc(admit admission.Interface, staticAttrib if !validatingAdmission.Handles(finalAttributes.GetOperation()) { return nil } - return validatingAdmission.Validate(finalAttributes) + return validatingAdmission.Validate(finalAttributes, o) } } diff --git a/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission.go b/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission.go index 70d618614a9..8cfc0c59326 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission.go @@ -47,7 +47,7 @@ var _ = wardleinitializer.WantsInternalWardleInformerFactory(&DisallowFlunder{}) // Admit ensures that the object in-flight is of kind Flunder. // In addition checks that the Name is not on the banned list. // The list is stored in Fischers API objects. -func (d *DisallowFlunder) Admit(a admission.Attributes) error { +func (d *DisallowFlunder) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { // we are only interested in flunders if a.GetKind().GroupKind() != wardle.Kind("Flunder") { return nil diff --git a/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/wardleinitializer_test.go b/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/wardleinitializer_test.go index ff6fee1a92f..46ae05e807a 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/wardleinitializer_test.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/wardleinitializer_test.go @@ -48,7 +48,9 @@ type wantInternalWardleInformerFactory struct { func (self *wantInternalWardleInformerFactory) SetInternalWardleInformerFactory(sf informers.SharedInformerFactory) { self.sf = sf } -func (self *wantInternalWardleInformerFactory) Admit(a admission.Attributes) error { return nil } +func (self *wantInternalWardleInformerFactory) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { + return nil +} func (self *wantInternalWardleInformerFactory) Handles(o admission.Operation) bool { return false } func (self *wantInternalWardleInformerFactory) ValidateInitialization() error { return nil }