diff --git a/cmd/kube-apiserver/app/aggregator.go b/cmd/kube-apiserver/app/aggregator.go index c56e19100ff..d2b0f115af4 100644 --- a/cmd/kube-apiserver/app/aggregator.go +++ b/cmd/kube-apiserver/app/aggregator.go @@ -70,7 +70,6 @@ func createAggregatorConfig( &genericConfig, externalInformers, genericConfig.LoopbackClientConfig, - aggregatorscheme.Scheme, pluginInitializers...) if err != nil { return nil, err diff --git a/cmd/kube-apiserver/app/apiextensions.go b/cmd/kube-apiserver/app/apiextensions.go index 181ca715858..2db21153cd0 100644 --- a/cmd/kube-apiserver/app/apiextensions.go +++ b/cmd/kube-apiserver/app/apiextensions.go @@ -52,7 +52,6 @@ func createAPIExtensionsConfig( &genericConfig, externalInformers, genericConfig.LoopbackClientConfig, - apiextensionsapiserver.Scheme, pluginInitializers...) if err != nil { return nil, err diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index afc0e721678..7daab88ceb9 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -491,7 +491,6 @@ func buildGenericConfig( genericConfig, versionedInformers, kubeClientConfig, - legacyscheme.Scheme, pluginInitializers...) if err != nil { lastErr = fmt.Errorf("failed to initialize admission: %v", err) 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/pkg/kubeapiserver/options/BUILD b/pkg/kubeapiserver/options/BUILD index 22b364ffb6e..7360f9c0eff 100644 --- a/pkg/kubeapiserver/options/BUILD +++ b/pkg/kubeapiserver/options/BUILD @@ -51,7 +51,6 @@ go_library( "//plugin/pkg/admission/storage/persistentvolume/resize:go_default_library", "//plugin/pkg/admission/storage/storageclass/setdefault:go_default_library", "//plugin/pkg/admission/storage/storageobjectinuseprotection:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/net: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/pkg/kubeapiserver/options/admission.go b/pkg/kubeapiserver/options/admission.go index 15f5d954921..dfad5aa0bcb 100644 --- a/pkg/kubeapiserver/options/admission.go +++ b/pkg/kubeapiserver/options/admission.go @@ -22,7 +22,6 @@ import ( "github.com/spf13/pflag" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/server" @@ -108,7 +107,6 @@ func (a *AdmissionOptions) ApplyTo( c *server.Config, informers informers.SharedInformerFactory, kubeAPIServerClientConfig *rest.Config, - scheme *runtime.Scheme, pluginInitializers ...admission.PluginInitializer, ) error { if a == nil { @@ -120,7 +118,7 @@ func (a *AdmissionOptions) ApplyTo( a.GenericAdmission.EnablePlugins, a.GenericAdmission.DisablePlugins = computePluginNames(a.PluginNames, a.GenericAdmission.RecommendedPluginOrder) } - return a.GenericAdmission.ApplyTo(c, informers, kubeAPIServerClientConfig, scheme, pluginInitializers...) + return a.GenericAdmission.ApplyTo(c, informers, kubeAPIServerClientConfig, pluginInitializers...) } // explicitly disable all plugins that are not in the enabled list diff --git a/plugin/pkg/admission/admit/admission.go b/plugin/pkg/admission/admit/admission.go index 867bbcdae4d..83d8c639030 100644 --- a/plugin/pkg/admission/admit/admission.go +++ b/plugin/pkg/admission/admit/admission.go @@ -40,12 +40,12 @@ var _ admission.MutationInterface = alwaysAdmit{} var _ admission.ValidationInterface = alwaysAdmit{} // Admit makes an admission decision based on the request attributes -func (alwaysAdmit) Admit(a admission.Attributes) (err error) { +func (alwaysAdmit) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) { return nil } // Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate. -func (alwaysAdmit) Validate(a admission.Attributes) (err error) { +func (alwaysAdmit) Validate(a admission.Attributes, o admission.ObjectInterfaces) (err error) { return nil } diff --git a/plugin/pkg/admission/admit/admission_test.go b/plugin/pkg/admission/admit/admission_test.go index cabd9cfc71d..6721aaf4eb5 100644 --- a/plugin/pkg/admission/admit/admission_test.go +++ b/plugin/pkg/admission/admit/admission_test.go @@ -25,7 +25,7 @@ import ( 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)) + 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) if err != nil { t.Errorf("Unexpected error returned from admission handler") } @@ -33,7 +33,7 @@ func TestAdmissionNonNilAttribute(t *testing.T) { func TestAdmissionNilAttribute(t *testing.T) { handler := NewAlwaysAdmit() - err := handler.(*alwaysAdmit).Admit(nil) + err := handler.(*alwaysAdmit).Admit(nil, nil) if err != nil { t.Errorf("Unexpected error returned from admission handler") } diff --git a/plugin/pkg/admission/alwayspullimages/admission.go b/plugin/pkg/admission/alwayspullimages/admission.go index 3024c98562b..9f751a48126 100644 --- a/plugin/pkg/admission/alwayspullimages/admission.go +++ b/plugin/pkg/admission/alwayspullimages/admission.go @@ -53,7 +53,7 @@ var _ admission.MutationInterface = &AlwaysPullImages{} var _ admission.ValidationInterface = &AlwaysPullImages{} // Admit makes an admission decision based on the request attributes -func (a *AlwaysPullImages) Admit(attributes admission.Attributes) (err error) { +func (a *AlwaysPullImages) Admit(attributes admission.Attributes, o admission.ObjectInterfaces) (err error) { // Ignore all calls to subresources or resources other than pods. if shouldIgnore(attributes) { return nil @@ -75,7 +75,7 @@ func (a *AlwaysPullImages) Admit(attributes admission.Attributes) (err error) { } // Validate makes sure that all containers are set to always pull images -func (*AlwaysPullImages) Validate(attributes admission.Attributes) (err error) { +func (*AlwaysPullImages) Validate(attributes admission.Attributes, o admission.ObjectInterfaces) (err error) { if shouldIgnore(attributes) { return nil } diff --git a/plugin/pkg/admission/alwayspullimages/admission_test.go b/plugin/pkg/admission/alwayspullimages/admission_test.go index 9d5ebbd6f4f..6f0756e30e8 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)) + 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) 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)) + 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) 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)) + 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) if tc.expectError { if err == nil { diff --git a/plugin/pkg/admission/antiaffinity/admission.go b/plugin/pkg/admission/antiaffinity/admission.go index 5e626c50d44..9e7e5592c0b 100644 --- a/plugin/pkg/admission/antiaffinity/admission.go +++ b/plugin/pkg/admission/antiaffinity/admission.go @@ -51,7 +51,7 @@ func NewInterPodAntiAffinity() *Plugin { // Validate will deny any pod that defines AntiAffinity topology key other than v1.LabelHostname i.e. "kubernetes.io/hostname" // in requiredDuringSchedulingRequiredDuringExecution and requiredDuringSchedulingIgnoredDuringExecution. -func (p *Plugin) Validate(attributes admission.Attributes) (err error) { +func (p *Plugin) Validate(attributes admission.Attributes, o admission.ObjectInterfaces) (err error) { // Ignore all calls to subresources or resources other than pods. if len(attributes.GetSubresource()) != 0 || attributes.GetResource().GroupResource() != api.Resource("pods") { return nil diff --git a/plugin/pkg/admission/antiaffinity/admission_test.go b/plugin/pkg/admission/antiaffinity/admission_test.go index abb5faea58f..9772716c255 100644 --- a/plugin/pkg/admission/antiaffinity/admission_test.go +++ b/plugin/pkg/admission/antiaffinity/admission_test.go @@ -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)) + err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", 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)) + 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) if tc.expectError { if err == nil { diff --git a/plugin/pkg/admission/defaulttolerationseconds/admission.go b/plugin/pkg/admission/defaulttolerationseconds/admission.go index c92b9d1b1f1..1bff0d701b2 100644 --- a/plugin/pkg/admission/defaulttolerationseconds/admission.go +++ b/plugin/pkg/admission/defaulttolerationseconds/admission.go @@ -81,7 +81,7 @@ func NewDefaultTolerationSeconds() *Plugin { } // Admit makes an admission decision based on the request attributes -func (p *Plugin) Admit(attributes admission.Attributes) (err error) { +func (p *Plugin) Admit(attributes admission.Attributes, o admission.ObjectInterfaces) (err error) { if attributes.GetResource().GroupResource() != api.Resource("pods") { return nil } diff --git a/plugin/pkg/admission/defaulttolerationseconds/admission_test.go b/plugin/pkg/admission/defaulttolerationseconds/admission_test.go index c6f9a00d38f..09f0fcd944a 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)) + err := handler.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", 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/admission.go b/plugin/pkg/admission/deny/admission.go index bf484590cbe..4c9a85e366c 100644 --- a/plugin/pkg/admission/deny/admission.go +++ b/plugin/pkg/admission/deny/admission.go @@ -42,12 +42,12 @@ var _ admission.MutationInterface = alwaysDeny{} var _ admission.ValidationInterface = alwaysDeny{} // Admit makes an admission decision based on the request attributes. -func (alwaysDeny) Admit(a admission.Attributes) (err error) { +func (alwaysDeny) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) { return admission.NewForbidden(a, errors.New("admission control is denying all modifications")) } // Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate. -func (alwaysDeny) Validate(a admission.Attributes) (err error) { +func (alwaysDeny) Validate(a admission.Attributes, o admission.ObjectInterfaces) (err error) { return admission.NewForbidden(a, errors.New("admission control is denying all modifications")) } diff --git a/plugin/pkg/admission/deny/admission_test.go b/plugin/pkg/admission/deny/admission_test.go index 1573a7f7937..1eb7e9928ae 100644 --- a/plugin/pkg/admission/deny/admission_test.go +++ b/plugin/pkg/admission/deny/admission_test.go @@ -25,7 +25,7 @@ import ( 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)) + 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) if err == nil { t.Error("Expected error returned from admission handler") } diff --git a/plugin/pkg/admission/eventratelimit/admission.go b/plugin/pkg/admission/eventratelimit/admission.go index 84e92db09d6..00506240556 100644 --- a/plugin/pkg/admission/eventratelimit/admission.go +++ b/plugin/pkg/admission/eventratelimit/admission.go @@ -81,7 +81,7 @@ func newEventRateLimit(config *eventratelimitapi.Configuration, clock flowcontro } // Validate makes admission decisions while enforcing event rate limits -func (a *Plugin) Validate(attr admission.Attributes) (err error) { +func (a *Plugin) Validate(attr admission.Attributes, o admission.ObjectInterfaces) (err error) { // ignore all operations that do not correspond to an Event kind if attr.GetKind().GroupKind() != api.Kind("Event") { return nil diff --git a/plugin/pkg/admission/eventratelimit/admission_test.go b/plugin/pkg/admission/eventratelimit/admission_test.go index f684852046e..468c3ad5c45 100644 --- a/plugin/pkg/admission/eventratelimit/admission_test.go +++ b/plugin/pkg/admission/eventratelimit/admission_test.go @@ -504,7 +504,7 @@ func TestEventRateLimiting(t *testing.T) { clock.Step(rq.delay) } attributes := attributesForRequest(rq) - err = eventratelimit.Validate(attributes) + err = eventratelimit.Validate(attributes, nil) if rq.accepted != (err == nil) { expectedAction := "admitted" if !rq.accepted { diff --git a/plugin/pkg/admission/exec/admission.go b/plugin/pkg/admission/exec/admission.go index c4ed9282fb4..a90581a07ad 100644 --- a/plugin/pkg/admission/exec/admission.go +++ b/plugin/pkg/admission/exec/admission.go @@ -111,7 +111,7 @@ func (d *DenyExec) ValidateInitialization() error { } // Validate makes an admission decision based on the request attributes -func (d *DenyExec) Validate(a admission.Attributes) (err error) { +func (d *DenyExec) Validate(a admission.Attributes, o admission.ObjectInterfaces) (err error) { path := a.GetResource().Resource if subresource := a.GetSubresource(); subresource != "" { path = path + "/" + subresource diff --git a/plugin/pkg/admission/exec/admission_test.go b/plugin/pkg/admission/exec/admission_test.go index c8d0b665c1b..14f29abf4af 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)) + 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) 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)) + 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) if shouldAccept && err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } diff --git a/plugin/pkg/admission/extendedresourcetoleration/admission.go b/plugin/pkg/admission/extendedresourcetoleration/admission.go index 207922a4787..b0bff24518e 100644 --- a/plugin/pkg/admission/extendedresourcetoleration/admission.go +++ b/plugin/pkg/admission/extendedresourcetoleration/admission.go @@ -56,7 +56,7 @@ type plugin struct { // a toleration with key "example.com/device", operator "Exists" and effect "NoSchedule". // The rationale for this is described in: // https://github.com/kubernetes/kubernetes/issues/55080 -func (p *plugin) Admit(attributes admission.Attributes) error { +func (p *plugin) Admit(attributes admission.Attributes, o admission.ObjectInterfaces) error { // Ignore all calls to subresources or resources other than pods. if len(attributes.GetSubresource()) != 0 || attributes.GetResource().GroupResource() != core.Resource("pods") { return nil diff --git a/plugin/pkg/admission/extendedresourcetoleration/admission_test.go b/plugin/pkg/admission/extendedresourcetoleration/admission_test.go index 7c8f6450345..b177950b225 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)) + err := plugin.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, core.Kind("Pod").WithVersion("version"), "foo", "name", core.Resource("pods").WithVersion("version"), "", "ignored", 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.go b/plugin/pkg/admission/gc/gc_admission.go index 89122da5a68..4036a2642c6 100644 --- a/plugin/pkg/admission/gc/gc_admission.go +++ b/plugin/pkg/admission/gc/gc_admission.go @@ -84,7 +84,7 @@ func (a *gcPermissionsEnforcement) isWhiteListed(groupResource schema.GroupResou return false } -func (a *gcPermissionsEnforcement) Validate(attributes admission.Attributes) (err error) { +func (a *gcPermissionsEnforcement) Validate(attributes admission.Attributes, o admission.ObjectInterfaces) (err error) { // // if the request is in the whitelist, we skip mutation checks for this resource. if a.isWhiteListed(attributes.GetResource().GroupResource(), attributes.GetSubresource()) { return nil diff --git a/plugin/pkg/admission/gc/gc_admission_test.go b/plugin/pkg/admission/gc/gc_admission_test.go index a7d51cd0ef1..8e0ef132ed7 100644 --- a/plugin/pkg/admission/gc/gc_admission_test.go +++ b/plugin/pkg/admission/gc/gc_admission_test.go @@ -100,7 +100,7 @@ func newGCPermissionsEnforcement() (*gcPermissionsEnforcement, error) { whiteList: whiteList, } - genericPluginInitializer := initializer.New(nil, nil, fakeAuthorizer{}, nil) + genericPluginInitializer := initializer.New(nil, nil, fakeAuthorizer{}) fakeDiscoveryClient := &fakediscovery.FakeDiscovery{Fake: &coretesting.Fake{}} fakeDiscoveryClient.Resources = []*metav1.APIResourceList{ { @@ -308,7 +308,7 @@ func TestGCAdmission(t *testing.T) { 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) - err = gcAdmit.Validate(attributes) + err = gcAdmit.Validate(attributes, nil) if !tc.checkError(err) { t.Errorf("unexpected err: %v", err) } @@ -611,7 +611,7 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) { 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) - err := gcAdmit.Validate(attributes) + err := gcAdmit.Validate(attributes, nil) if !tc.checkError(err) { t.Errorf("%v: unexpected err: %v", tc.name, err) } diff --git a/plugin/pkg/admission/imagepolicy/admission.go b/plugin/pkg/admission/imagepolicy/admission.go index cfcb70a0472..bf79294022a 100644 --- a/plugin/pkg/admission/imagepolicy/admission.go +++ b/plugin/pkg/admission/imagepolicy/admission.go @@ -131,7 +131,7 @@ func (a *Plugin) webhookError(pod *api.Pod, attributes admission.Attributes, err } // Validate makes an admission decision based on the request attributes -func (a *Plugin) Validate(attributes admission.Attributes) (err error) { +func (a *Plugin) Validate(attributes admission.Attributes, o admission.ObjectInterfaces) (err error) { // Ignore all calls to subresources or resources other than pods. if attributes.GetSubresource() != "" || attributes.GetResource().GroupResource() != api.Resource("pods") { return nil diff --git a/plugin/pkg/admission/imagepolicy/admission_test.go b/plugin/pkg/admission/imagepolicy/admission_test.go index 3bb47380b8d..3d748082a15 100644 --- a/plugin/pkg/admission/imagepolicy/admission_test.go +++ b/plugin/pkg/admission/imagepolicy/admission_test.go @@ -487,7 +487,7 @@ func TestTLSConfig(t *testing.T) { // Allow all and see if we get an error. service.Allow() - err = wh.Validate(attr) + err = wh.Validate(attr, nil) if tt.wantAllowed { if err != nil { t.Errorf("expected successful admission") @@ -509,7 +509,7 @@ func TestTLSConfig(t *testing.T) { } service.Deny() - if err := wh.Validate(attr); err == nil { + if err := wh.Validate(attr, nil); err == nil { t.Errorf("%s: incorrectly admitted with DenyAll policy", tt.test) } }) @@ -526,7 +526,7 @@ type webhookCacheTestCase struct { func testWebhookCacheCases(t *testing.T, serv *mockService, wh *Plugin, attr admission.Attributes, tests []webhookCacheTestCase) { for _, test := range tests { serv.statusCode = test.statusCode - err := wh.Validate(attr) + err := wh.Validate(attr, nil) authorized := err == nil if test.expectedErr && err == nil { @@ -759,7 +759,7 @@ func TestContainerCombinations(t *testing.T) { attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{}) - err = wh.Validate(attr) + err = wh.Validate(attr, nil) if tt.wantAllowed { if err != nil { t.Errorf("expected successful admission: %s", tt.test) @@ -855,7 +855,7 @@ func TestDefaultAllow(t *testing.T) { annotations := make(map[string]string) attr = &fakeAttributes{attr, annotations} - err = wh.Validate(attr) + err = wh.Validate(attr, nil) if tt.wantAllowed { if err != nil { t.Errorf("expected successful admission") @@ -963,7 +963,7 @@ func TestAnnotationFiltering(t *testing.T) { attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{}) - err = wh.Validate(attr) + err = wh.Validate(attr, nil) if err != nil { t.Errorf("expected successful admission") } @@ -1055,7 +1055,7 @@ func TestReturnedAnnotationAdd(t *testing.T) { annotations := make(map[string]string) attr = &fakeAttributes{attr, annotations} - err = wh.Validate(attr) + err = wh.Validate(attr, nil) if !reflect.DeepEqual(annotations, tt.expectedAnnotations) { t.Errorf("got audit annotations: %v; want: %v", annotations, tt.expectedAnnotations) } diff --git a/plugin/pkg/admission/limitranger/admission.go b/plugin/pkg/admission/limitranger/admission.go index 99356487d09..3e2d7613316 100644 --- a/plugin/pkg/admission/limitranger/admission.go +++ b/plugin/pkg/admission/limitranger/admission.go @@ -99,12 +99,12 @@ func (l *LimitRanger) ValidateInitialization() error { } // Admit admits resources into cluster that do not violate any defined LimitRange in the namespace -func (l *LimitRanger) Admit(a admission.Attributes) (err error) { +func (l *LimitRanger) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) { return l.runLimitFunc(a, l.actions.MutateLimit) } // Validate admits resources into cluster that do not violate any defined LimitRange in the namespace -func (l *LimitRanger) Validate(a admission.Attributes) (err error) { +func (l *LimitRanger) Validate(a admission.Attributes, o admission.ObjectInterfaces) (err error) { return l.runLimitFunc(a, l.actions.ValidateLimit) } diff --git a/plugin/pkg/admission/limitranger/admission_test.go b/plugin/pkg/admission/limitranger/admission_test.go index 21515e2fd91..ec184e4dfc7 100644 --- a/plugin/pkg/admission/limitranger/admission_test.go +++ b/plugin/pkg/admission/limitranger/admission_test.go @@ -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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) if err != nil { t.Errorf("LimitRange should ignore a pod marked for termination") } @@ -788,7 +788,7 @@ func newHandlerForTest(c clientset.Interface) (*LimitRanger, informers.SharedInf if err != nil { return nil, f, err } - pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil) + pluginInitializer := genericadmissioninitializer.New(c, f, nil) pluginInitializer.Initialize(handler) err = admission.ValidateInitialization(handler) return handler, f, err diff --git a/plugin/pkg/admission/namespace/autoprovision/admission.go b/plugin/pkg/admission/namespace/autoprovision/admission.go index 07bb104fcc7..2c95f49e895 100644 --- a/plugin/pkg/admission/namespace/autoprovision/admission.go +++ b/plugin/pkg/admission/namespace/autoprovision/admission.go @@ -55,7 +55,7 @@ var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&Provision{ var _ = genericadmissioninitializer.WantsExternalKubeClientSet(&Provision{}) // Admit makes an admission decision based on the request attributes -func (p *Provision) Admit(a admission.Attributes) error { +func (p *Provision) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { // Don't create a namespace if the request is for a dry-run. if a.IsDryRun() { return nil diff --git a/plugin/pkg/admission/namespace/autoprovision/admission_test.go b/plugin/pkg/admission/namespace/autoprovision/admission_test.go index 8e5e0dca5f4..cde6f315bf8 100644 --- a/plugin/pkg/admission/namespace/autoprovision/admission_test.go +++ b/plugin/pkg/admission/namespace/autoprovision/admission_test.go @@ -39,7 +39,7 @@ import ( func newHandlerForTest(c clientset.Interface) (admission.MutationInterface, informers.SharedInformerFactory, error) { f := informers.NewSharedInformerFactory(c, 5*time.Minute) handler := NewProvision() - pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil) + pluginInitializer := genericadmissioninitializer.New(c, f, nil) pluginInitializer.Initialize(handler) err := admission.ValidateInitialization(handler) return handler, f, err @@ -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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) if err != nil { t.Errorf("unexpected error returned from admission handler") } diff --git a/plugin/pkg/admission/namespace/exists/admission.go b/plugin/pkg/admission/namespace/exists/admission.go index 40f76a47337..703081747d1 100644 --- a/plugin/pkg/admission/namespace/exists/admission.go +++ b/plugin/pkg/admission/namespace/exists/admission.go @@ -54,7 +54,7 @@ var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&Exists{}) var _ = genericadmissioninitializer.WantsExternalKubeClientSet(&Exists{}) // Validate makes an admission decision based on the request attributes -func (e *Exists) Validate(a admission.Attributes) error { +func (e *Exists) Validate(a admission.Attributes, o admission.ObjectInterfaces) error { // if we're here, then we've already passed authentication, so we're allowed to do what we're trying to do // if we're here, then the API server has found a route, which means that if we have a non-empty namespace // its a namespaced resource. diff --git a/plugin/pkg/admission/namespace/exists/admission_test.go b/plugin/pkg/admission/namespace/exists/admission_test.go index 2aa72bc89c7..c1cbfa5b188 100644 --- a/plugin/pkg/admission/namespace/exists/admission_test.go +++ b/plugin/pkg/admission/namespace/exists/admission_test.go @@ -38,7 +38,7 @@ import ( func newHandlerForTest(c kubernetes.Interface) (admission.ValidationInterface, informers.SharedInformerFactory, error) { f := informers.NewSharedInformerFactory(c, 5*time.Minute) handler := NewExists() - pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil) + pluginInitializer := genericadmissioninitializer.New(c, f, nil) pluginInitializer.Initialize(handler) err := admission.ValidateInitialization(handler) return handler, f, err @@ -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)) + 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) 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)) + 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) if err == nil { actions := "" for _, action := range mockClient.Actions() { diff --git a/plugin/pkg/admission/noderestriction/admission.go b/plugin/pkg/admission/noderestriction/admission.go index e5ef4578e55..305fdddad66 100644 --- a/plugin/pkg/admission/noderestriction/admission.go +++ b/plugin/pkg/admission/noderestriction/admission.go @@ -102,7 +102,7 @@ var ( csiNodeInfoResource = csiv1alpha1.Resource("csinodeinfos") ) -func (c *nodePlugin) Admit(a admission.Attributes) error { +func (c *nodePlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { nodeName, isNode := c.nodeIdentifier.NodeIdentity(a.GetUserInfo()) // Our job is just to restrict nodes diff --git a/plugin/pkg/admission/noderestriction/admission_test.go b/plugin/pkg/admission/noderestriction/admission_test.go index 1ebadaf9f94..a81d9fa7dd9 100644 --- a/plugin/pkg/admission/noderestriction/admission_test.go +++ b/plugin/pkg/admission/noderestriction/admission_test.go @@ -1234,7 +1234,7 @@ func Test_nodePlugin_Admit(t *testing.T) { c.features = tt.features } c.podsGetter = tt.podsGetter - err := c.Admit(tt.attributes) + err := c.Admit(tt.attributes, nil) if (err == nil) != (len(tt.err) == 0) { t.Errorf("nodePlugin.Admit() error = %v, expected %v", err, tt.err) return diff --git a/plugin/pkg/admission/nodetaint/admission.go b/plugin/pkg/admission/nodetaint/admission.go index 71cce0d9e21..dbf0931ba2e 100644 --- a/plugin/pkg/admission/nodetaint/admission.go +++ b/plugin/pkg/admission/nodetaint/admission.go @@ -64,7 +64,7 @@ var ( ) // Admit is the main function that checks node identity and adds taints as needed. -func (p *Plugin) Admit(a admission.Attributes) error { +func (p *Plugin) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { // If TaintNodesByCondition is not enabled, we don't need to do anything. if !p.features.Enabled(features.TaintNodesByCondition) { return nil diff --git a/plugin/pkg/admission/nodetaint/admission_test.go b/plugin/pkg/admission/nodetaint/admission_test.go index 28c5a2da8c6..8cd075c21ef 100644 --- a/plugin/pkg/admission/nodetaint/admission_test.go +++ b/plugin/pkg/admission/nodetaint/admission_test.go @@ -100,7 +100,7 @@ func Test_nodeTaints(t *testing.T) { if tt.features != nil { c.features = tt.features } - err := c.Admit(attributes) + err := c.Admit(attributes, nil) if err != nil { t.Errorf("nodePlugin.Admit() error = %v", err) } diff --git a/plugin/pkg/admission/podnodeselector/admission.go b/plugin/pkg/admission/podnodeselector/admission.go index e3e81ea7164..94fe90ec7d0 100644 --- a/plugin/pkg/admission/podnodeselector/admission.go +++ b/plugin/pkg/admission/podnodeselector/admission.go @@ -94,7 +94,7 @@ func readConfig(config io.Reader) *pluginConfig { } // Admit enforces that pod and its namespace node label selectors matches at least a node in the cluster. -func (p *podNodeSelector) Admit(a admission.Attributes) error { +func (p *podNodeSelector) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { if shouldIgnore(a) { return nil } @@ -117,11 +117,11 @@ func (p *podNodeSelector) Admit(a admission.Attributes) error { // second selector wins podNodeSelectorLabels := labels.Merge(namespaceNodeSelector, pod.Spec.NodeSelector) pod.Spec.NodeSelector = map[string]string(podNodeSelectorLabels) - return p.Validate(a) + return p.Validate(a, o) } // Validate ensures that the pod node selector is allowed -func (p *podNodeSelector) Validate(a admission.Attributes) error { +func (p *podNodeSelector) Validate(a admission.Attributes, o admission.ObjectInterfaces) error { if shouldIgnore(a) { return nil } diff --git a/plugin/pkg/admission/podnodeselector/admission_test.go b/plugin/pkg/admission/podnodeselector/admission_test.go index 398ef18fb1f..73f1da09834 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)) + 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) 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)) + 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) if test.admit && err != nil { t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) } else if !test.admit && err == nil { @@ -197,7 +197,7 @@ func TestHandles(t *testing.T) { func newHandlerForTest(c kubernetes.Interface) (*podNodeSelector, informers.SharedInformerFactory, error) { f := informers.NewSharedInformerFactory(c, 5*time.Minute) handler := NewPodNodeSelector(nil) - pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil) + pluginInitializer := genericadmissioninitializer.New(c, f, nil) pluginInitializer.Initialize(handler) err := admission.ValidateInitialization(handler) return handler, f, err diff --git a/plugin/pkg/admission/podpreset/admission.go b/plugin/pkg/admission/podpreset/admission.go index e86f4511c4d..db53562b9c4 100644 --- a/plugin/pkg/admission/podpreset/admission.go +++ b/plugin/pkg/admission/podpreset/admission.go @@ -90,7 +90,7 @@ func (a *podPresetPlugin) SetExternalKubeInformerFactory(f informers.SharedInfor } // Admit injects a pod with the specific fields for each pod preset it matches. -func (c *podPresetPlugin) Admit(a admission.Attributes) error { +func (c *podPresetPlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { // Ignore all calls to subresources or resources other than pods. // Ignore all operations other than CREATE. if len(a.GetSubresource()) != 0 || a.GetResource().GroupResource() != api.Resource("pods") || a.GetOperation() != admission.Create { diff --git a/plugin/pkg/admission/podpreset/admission_test.go b/plugin/pkg/admission/podpreset/admission_test.go index 8e1a7fa4cc7..3dd8692fd99 100644 --- a/plugin/pkg/admission/podpreset/admission_test.go +++ b/plugin/pkg/admission/podpreset/admission_test.go @@ -823,7 +823,7 @@ func admitPod(pod *api.Pod, pip *settingsv1alpha1.PodPreset) error { &user.DefaultInfo{}, ) - err := plugin.Admit(attrs) + err := plugin.Admit(attrs, nil) if err != nil { return err } diff --git a/plugin/pkg/admission/podtolerationrestriction/admission.go b/plugin/pkg/admission/podtolerationrestriction/admission.go index 92ae3726cbc..12d7beb5a51 100644 --- a/plugin/pkg/admission/podtolerationrestriction/admission.go +++ b/plugin/pkg/admission/podtolerationrestriction/admission.go @@ -81,7 +81,7 @@ type podTolerationsPlugin struct { // instead if specified. Tolerations to a namespace are assigned via // scheduler.alpha.kubernetes.io/defaultTolerations and scheduler.alpha.kubernetes.io/tolerationsWhitelist // annotations keys. -func (p *podTolerationsPlugin) Admit(a admission.Attributes) error { +func (p *podTolerationsPlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { if shouldIgnore(a) { return nil } @@ -134,9 +134,9 @@ func (p *podTolerationsPlugin) Admit(a admission.Attributes) error { } pod.Spec.Tolerations = finalTolerations - return p.Validate(a) + return p.Validate(a, o) } -func (p *podTolerationsPlugin) Validate(a admission.Attributes) error { +func (p *podTolerationsPlugin) Validate(a admission.Attributes, o admission.ObjectInterfaces) error { if shouldIgnore(a) { return nil } diff --git a/plugin/pkg/admission/podtolerationrestriction/admission_test.go b/plugin/pkg/admission/podtolerationrestriction/admission_test.go index 8736d2de03a..7b7d9d88034 100644 --- a/plugin/pkg/admission/podtolerationrestriction/admission_test.go +++ b/plugin/pkg/admission/podtolerationrestriction/admission_test.go @@ -254,7 +254,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)) + 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) if test.admit && err != nil { t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) } else if !test.admit && err == nil { @@ -331,7 +331,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)) + 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) if err != nil { t.Errorf("expected no error, got: %v", err) } @@ -346,7 +346,7 @@ func newHandlerForTest(c kubernetes.Interface) (*podTolerationsPlugin, informers return nil, nil, err } handler := NewPodTolerationsPlugin(pluginConfig) - pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil) + pluginInitializer := genericadmissioninitializer.New(c, f, nil) pluginInitializer.Initialize(handler) err = admission.ValidateInitialization(handler) return handler, f, err diff --git a/plugin/pkg/admission/priority/admission.go b/plugin/pkg/admission/priority/admission.go index 11ade693533..16e7e85d198 100644 --- a/plugin/pkg/admission/priority/admission.go +++ b/plugin/pkg/admission/priority/admission.go @@ -97,7 +97,7 @@ var ( // Admit checks Pods and admits or rejects them. It also resolves the priority of pods based on their PriorityClass. // Note that pod validation mechanism prevents update of a pod priority. -func (p *priorityPlugin) Admit(a admission.Attributes) error { +func (p *priorityPlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { if !utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) { return nil } @@ -121,7 +121,7 @@ func (p *priorityPlugin) Admit(a admission.Attributes) error { } // Validate checks PriorityClasses and admits or rejects them. -func (p *priorityPlugin) Validate(a admission.Attributes) error { +func (p *priorityPlugin) Validate(a admission.Attributes, o admission.ObjectInterfaces) error { operation := a.GetOperation() // Ignore all calls to subresources if len(a.GetSubresource()) != 0 { diff --git a/plugin/pkg/admission/priority/admission_test.go b/plugin/pkg/admission/priority/admission_test.go index 8404467c82c..95b53a96dde 100644 --- a/plugin/pkg/admission/priority/admission_test.go +++ b/plugin/pkg/admission/priority/admission_test.go @@ -158,7 +158,7 @@ func TestPriorityClassAdmission(t *testing.T) { false, test.userInfo, ) - err := ctrl.Validate(attrs) + err := ctrl.Validate(attrs, nil) klog.Infof("Got %v", err) if err != nil && !test.expectError { t.Errorf("Test %q: unexpected error received: %v", test.name, err) @@ -254,7 +254,7 @@ func TestDefaultPriority(t *testing.T) { test.name, test.expectedDefaultNameBefore, test.expectedDefaultBefore, pcName, defaultPriority) } if test.attributes != nil { - err := ctrl.Validate(test.attributes) + err := ctrl.Validate(test.attributes, nil) if err != nil { t.Errorf("Test %q: unexpected error received: %v", test.name, err) } @@ -603,7 +603,7 @@ func TestPodAdmission(t *testing.T) { false, nil, ) - err := ctrl.Admit(attrs) + err := ctrl.Admit(attrs, nil) klog.Infof("Got %v", err) if !test.expectError { if err != nil { diff --git a/plugin/pkg/admission/resourcequota/admission.go b/plugin/pkg/admission/resourcequota/admission.go index 43097ef5569..0fad34051fb 100644 --- a/plugin/pkg/admission/resourcequota/admission.go +++ b/plugin/pkg/admission/resourcequota/admission.go @@ -127,7 +127,7 @@ func (a *QuotaAdmission) ValidateInitialization() error { } // Validate makes admission decisions while enforcing quota -func (a *QuotaAdmission) Validate(attr admission.Attributes) (err error) { +func (a *QuotaAdmission) Validate(attr admission.Attributes, o admission.ObjectInterfaces) (err error) { // ignore all operations that correspond to sub-resource actions if attr.GetSubresource() != "" { return nil diff --git a/plugin/pkg/admission/resourcequota/admission_test.go b/plugin/pkg/admission/resourcequota/admission_test.go index be7a8af6bb1..5de5a0eab4d 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)) + err := handler.Validate(admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), namespace, "name", corev1.Resource("pods").WithVersion("version"), "", admission.Delete, 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -1174,7 +1174,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)) + 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) if err != nil { t.Errorf("Got unexpected error: %v", err) } @@ -1217,14 +1217,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)) + 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) 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)) + 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) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -1265,7 +1265,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)) + 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) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -1299,7 +1299,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)) + 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) if err == nil { t.Errorf("Expected an error for consuming a limited resource without quota.") } @@ -1333,7 +1333,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)) + 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) if err != nil { t.Fatalf("Unexpected error: %v", err) } @@ -1381,7 +1381,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)) + 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) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1441,7 +1441,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)) + 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) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1489,7 +1489,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)) + 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) if err == nil { t.Fatalf("Expected an error since the quota did not cover cpu") } @@ -2150,7 +2150,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)) + 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) if testCase.expErr == "" { if err != nil { t.Fatalf("Testcase, %v, failed with unexpected error: %v. ExpErr: %v", testCase.description, err, testCase.expErr) diff --git a/plugin/pkg/admission/security/podsecuritypolicy/admission.go b/plugin/pkg/admission/security/podsecuritypolicy/admission.go index f980b932212..4f28229d57d 100644 --- a/plugin/pkg/admission/security/podsecuritypolicy/admission.go +++ b/plugin/pkg/admission/security/podsecuritypolicy/admission.go @@ -109,7 +109,7 @@ func (a *PodSecurityPolicyPlugin) SetExternalKubeInformerFactory(f informers.Sha // 3. Try to generate and validate a PSP with providers. If we find one then admit the pod // with the validated PSP. If we don't find any reject the pod and give all errors from the // failed attempts. -func (c *PodSecurityPolicyPlugin) Admit(a admission.Attributes) error { +func (c *PodSecurityPolicyPlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { if ignore, err := shouldIgnore(a); err != nil { return err } else if ignore { @@ -149,7 +149,7 @@ func (c *PodSecurityPolicyPlugin) Admit(a admission.Attributes) error { return admission.NewForbidden(a, fmt.Errorf("unable to validate against any pod security policy: %v", validationErrs)) } -func (c *PodSecurityPolicyPlugin) Validate(a admission.Attributes) error { +func (c *PodSecurityPolicyPlugin) Validate(a admission.Attributes, o admission.ObjectInterfaces) error { if ignore, err := shouldIgnore(a); err != nil { return err } else if ignore { diff --git a/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go b/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go index a0ce808020e..6712ab1ee1c 100644 --- a/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go +++ b/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go @@ -475,7 +475,7 @@ func TestFailClosedOnInvalidPod(t *testing.T) { 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{}) - err := plugin.Admit(attrs) + err := plugin.Admit(attrs, nil) if err == nil { t.Fatalf("expected versioned pod object to fail mutating admission") } @@ -483,7 +483,7 @@ func TestFailClosedOnInvalidPod(t *testing.T) { t.Errorf("expected type error on Admit but got: %v", err) } - err = plugin.Validate(attrs) + err = plugin.Validate(attrs, nil) if err == nil { t.Fatalf("expected versioned pod object to fail validating admission") } @@ -1779,7 +1779,7 @@ func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []* attrs := kadmission.NewAttributesRecord(pod, oldPod, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, "", kapi.Resource("pods").WithVersion("version"), "", op, false, userInfo) annotations := make(map[string]string) attrs = &fakeAttributes{attrs, annotations} - err := plugin.Admit(attrs) + err := plugin.Admit(attrs, nil) if shouldPassAdmit && err != nil { t.Errorf("%s: expected no errors on Admit but received %v", testCaseName, err) @@ -1807,7 +1807,7 @@ func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []* t.Errorf("%s: expected errors on Admit but received none", testCaseName) } - err = plugin.Validate(attrs) + err = plugin.Validate(attrs, nil) psp := "" if shouldPassAdmit && op == kadmission.Create { psp = expectedPSP diff --git a/plugin/pkg/admission/securitycontext/scdeny/admission.go b/plugin/pkg/admission/securitycontext/scdeny/admission.go index 5ff6c07a0fd..f17ce851573 100644 --- a/plugin/pkg/admission/securitycontext/scdeny/admission.go +++ b/plugin/pkg/admission/securitycontext/scdeny/admission.go @@ -50,7 +50,7 @@ func NewSecurityContextDeny() *Plugin { } // Validate will deny any pod that defines SupplementalGroups, SELinuxOptions, RunAsUser or FSGroup -func (p *Plugin) Validate(a admission.Attributes) (err error) { +func (p *Plugin) Validate(a admission.Attributes, o admission.ObjectInterfaces) (err error) { if a.GetSubresource() != "" || a.GetResource().GroupResource() != api.Resource("pods") { return nil } diff --git a/plugin/pkg/admission/securitycontext/scdeny/admission_test.go b/plugin/pkg/admission/securitycontext/scdeny/admission_test.go index aca4352bec5..65d7ad1d169 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)) + err := handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", 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)) + err = handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", 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)) + err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", 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.go b/plugin/pkg/admission/serviceaccount/admission.go index 007e20bf40b..eb9418805b1 100644 --- a/plugin/pkg/admission/serviceaccount/admission.go +++ b/plugin/pkg/admission/serviceaccount/admission.go @@ -148,7 +148,7 @@ func (a *serviceAccount) ValidateInitialization() error { return nil } -func (s *serviceAccount) Admit(a admission.Attributes) (err error) { +func (s *serviceAccount) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) { if shouldIgnore(a) { return nil } @@ -159,7 +159,7 @@ func (s *serviceAccount) Admit(a admission.Attributes) (err error) { // That makes the kubelet very angry and confused, and it immediately deletes the pod (because the spec doesn't match) // That said, don't allow mirror pods to reference ServiceAccounts or SecretVolumeSources either if _, isMirrorPod := pod.Annotations[api.MirrorPodAnnotationKey]; isMirrorPod { - return s.Validate(a) + return s.Validate(a, o) } // Set the default service account if needed @@ -186,10 +186,10 @@ func (s *serviceAccount) Admit(a admission.Attributes) (err error) { } } - return s.Validate(a) + return s.Validate(a, o) } -func (s *serviceAccount) Validate(a admission.Attributes) (err error) { +func (s *serviceAccount) Validate(a admission.Attributes, o admission.ObjectInterfaces) (err error) { if shouldIgnore(a) { return nil } diff --git a/plugin/pkg/admission/serviceaccount/admission_test.go b/plugin/pkg/admission/serviceaccount/admission_test.go index 79ae943d7ee..3caec44f6f8 100644 --- a/plugin/pkg/admission/serviceaccount/admission_test.go +++ b/plugin/pkg/admission/serviceaccount/admission_test.go @@ -65,7 +65,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) - err := NewServiceAccount().Admit(attrs) + err := NewServiceAccount().Admit(attrs, nil) if err != nil { t.Errorf("Expected non-pod resource allowed, got err: %v", err) } @@ -73,7 +73,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) - err := NewServiceAccount().Admit(attrs) + err := NewServiceAccount().Admit(attrs, nil) if err != nil { t.Errorf("Expected nil object allowed allowed, got err: %v", err) } @@ -82,7 +82,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) - err := NewServiceAccount().Admit(attrs) + err := NewServiceAccount().Admit(attrs, nil) if err != nil { t.Errorf("Expected non pod object allowed, got err: %v", err) } @@ -102,7 +102,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) - err := NewServiceAccount().Admit(attrs) + err := NewServiceAccount().Admit(attrs, nil) if err != nil { t.Errorf("Expected mirror pod without service account or secrets allowed, got err: %v", err) } @@ -120,7 +120,7 @@ func TestRejectsMirrorPodWithServiceAccount(t *testing.T) { }, } attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) - err := NewServiceAccount().Admit(attrs) + err := NewServiceAccount().Admit(attrs, nil) if err == nil { t.Errorf("Expected a mirror pod to be prevented from referencing a service account") } @@ -140,7 +140,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) - err := NewServiceAccount().Admit(attrs) + err := NewServiceAccount().Admit(attrs, nil) if err == nil { t.Errorf("Expected a mirror pod to be prevented from referencing a secret volume") } @@ -165,7 +165,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) - err := NewServiceAccount().Admit(attrs) + err := NewServiceAccount().Admit(attrs, nil) if err == nil { t.Errorf("Expected a mirror pod to be prevented from referencing a ServiceAccountToken volume projection") } @@ -190,7 +190,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) - err := admit.Admit(attrs) + err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -218,7 +218,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) - err := admit.Admit(attrs) + err := admit.Admit(attrs, nil) if err == nil || !errors.IsServerTimeout(err) { t.Errorf("Expected server timeout error for missing API token: %v", err) } @@ -243,7 +243,7 @@ func TestFetchesUncachedServiceAccount(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) - err := admit.Admit(attrs) + err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -265,7 +265,7 @@ func TestDeniesInvalidServiceAccount(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) - err := admit.Admit(attrs) + err := admit.Admit(attrs, nil) if err == nil { t.Errorf("Expected error for missing service account, got none") } @@ -331,7 +331,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) - err := admit.Admit(attrs) + err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -360,7 +360,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) - if err := admit.Admit(attrs); err != nil { + if err := admit.Admit(attrs, nil); err != nil { t.Errorf("Unexpected error: %v", err) } if pod.Spec.ServiceAccountName != DefaultServiceAccountName { @@ -442,7 +442,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) - err := admit.Admit(attrs) + err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -472,7 +472,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) - if err := admit.Admit(attrs); err != nil { + if err := admit.Admit(attrs, nil); err != nil { t.Errorf("Unexpected error: %v", err) } if pod.Spec.ServiceAccountName != DefaultServiceAccountName { @@ -518,7 +518,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) - if err := admit.Admit(attrs); err != nil { + if err := admit.Admit(attrs, nil); err != nil { t.Errorf("Unexpected error: %v", err) } @@ -542,7 +542,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) - if err := admit.Admit(attrs); err != nil { + if err := admit.Admit(attrs, nil); err != nil { t.Errorf("Unexpected error: %v", err) } @@ -566,7 +566,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) - if err := admit.Admit(attrs); err != nil { + if err := admit.Admit(attrs, nil); err != nil { t.Errorf("Unexpected error: %v", err) } } @@ -596,7 +596,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) - if err := admit.Admit(attrs); err == nil { + if err := admit.Admit(attrs, nil); err == nil { t.Errorf("Expected rejection for using a secret the service account does not reference") } @@ -620,7 +620,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) - if err := admit.Admit(attrs); err == nil || !strings.Contains(err.Error(), "with envVar") { + if err := admit.Admit(attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") { t.Errorf("Unexpected error: %v", err) } @@ -644,7 +644,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) - if err := admit.Admit(attrs); err == nil || !strings.Contains(err.Error(), "with envVar") { + if err := admit.Admit(attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") { t.Errorf("Unexpected error: %v", err) } } @@ -675,7 +675,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) - err := admit.Admit(attrs) + err := admit.Admit(attrs, nil) if err == nil { t.Errorf("Expected rejection for using a secret the service account does not reference") } @@ -707,7 +707,7 @@ func TestAllowsReferencedImagePullSecrets(t *testing.T) { }, } attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) - err := admit.Admit(attrs) + err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -736,7 +736,7 @@ func TestRejectsUnreferencedImagePullSecrets(t *testing.T) { }, } attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) - err := admit.Admit(attrs) + err := admit.Admit(attrs, nil) if err == nil { t.Errorf("Expected rejection for using a secret the service account does not reference") } @@ -769,7 +769,7 @@ func TestDoNotAddImagePullSecrets(t *testing.T) { }, } attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil) - err := admit.Admit(attrs) + err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -803,7 +803,7 @@ func TestAddImagePullSecrets(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) - err := admit.Admit(attrs) + err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -884,7 +884,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) - if err := admit.Admit(attrs); err != nil { + if err := admit.Admit(attrs, nil); err != nil { t.Fatal(err) } @@ -1038,7 +1038,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) - err := admit.Admit(attrs) + err := admit.Admit(attrs, nil) if err != nil { t.Errorf("Unexpected error: %v", err) } diff --git a/plugin/pkg/admission/storage/persistentvolume/label/admission.go b/plugin/pkg/admission/storage/persistentvolume/label/admission.go index 943eaea48c0..e0b11581012 100644 --- a/plugin/pkg/admission/storage/persistentvolume/label/admission.go +++ b/plugin/pkg/admission/storage/persistentvolume/label/admission.go @@ -97,7 +97,7 @@ func nodeSelectorRequirementKeysExistInNodeSelectorTerms(reqs []api.NodeSelector return false } -func (l *persistentVolumeLabel) Admit(a admission.Attributes) (err error) { +func (l *persistentVolumeLabel) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) { if a.GetResource().GroupResource() != api.Resource("persistentvolumes") { return nil } diff --git a/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go b/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go index d6e84e1dad8..c066d5d7bf5 100644 --- a/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go +++ b/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go @@ -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)) + 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) 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.go b/plugin/pkg/admission/storage/persistentvolume/resize/admission.go index 3a945ea9dcc..e616826faea 100644 --- a/plugin/pkg/admission/storage/persistentvolume/resize/admission.go +++ b/plugin/pkg/admission/storage/persistentvolume/resize/admission.go @@ -71,7 +71,7 @@ func (pvcr *persistentVolumeClaimResize) ValidateInitialization() error { return nil } -func (pvcr *persistentVolumeClaimResize) Validate(a admission.Attributes) error { +func (pvcr *persistentVolumeClaimResize) Validate(a admission.Attributes, o admission.ObjectInterfaces) error { if a.GetResource().GroupResource() != api.Resource("persistentvolumeclaims") { return nil } diff --git a/plugin/pkg/admission/storage/persistentvolume/resize/admission_test.go b/plugin/pkg/admission/storage/persistentvolume/resize/admission_test.go index 0eed48a5c58..e0cb263bddb 100644 --- a/plugin/pkg/admission/storage/persistentvolume/resize/admission_test.go +++ b/plugin/pkg/admission/storage/persistentvolume/resize/admission_test.go @@ -256,7 +256,7 @@ func TestPVCResizeAdmission(t *testing.T) { operation := admission.Update attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, false, nil) - err := ctrl.Validate(attributes) + err := ctrl.Validate(attributes, nil) if !tc.checkError(err) { t.Errorf("%v: unexpected err: %v", tc.name, err) } diff --git a/plugin/pkg/admission/storage/storageclass/setdefault/admission.go b/plugin/pkg/admission/storage/storageclass/setdefault/admission.go index 98610ae060e..9366312c935 100644 --- a/plugin/pkg/admission/storage/storageclass/setdefault/admission.go +++ b/plugin/pkg/admission/storage/storageclass/setdefault/admission.go @@ -85,7 +85,7 @@ func (a *claimDefaulterPlugin) ValidateInitialization() error { // 1. Find available StorageClasses. // 2. Figure which is the default // 3. Write to the PVClaim -func (a *claimDefaulterPlugin) Admit(attr admission.Attributes) error { +func (a *claimDefaulterPlugin) Admit(attr admission.Attributes, o admission.ObjectInterfaces) error { if attr.GetResource().GroupResource() != api.Resource("persistentvolumeclaims") { return nil } diff --git a/plugin/pkg/admission/storage/storageclass/setdefault/admission_test.go b/plugin/pkg/admission/storage/storageclass/setdefault/admission_test.go index e9d5fcbaf43..45152522f2b 100644 --- a/plugin/pkg/admission/storage/storageclass/setdefault/admission_test.go +++ b/plugin/pkg/admission/storage/storageclass/setdefault/admission_test.go @@ -211,7 +211,7 @@ func TestAdmission(t *testing.T) { false, // dryRun nil, // userInfo ) - err := ctrl.Admit(attrs) + err := ctrl.Admit(attrs, nil) klog.Infof("Got %v", err) if err != nil && !test.expectError { t.Errorf("Test %q: unexpected error received: %v", test.name, err) diff --git a/plugin/pkg/admission/storage/storageobjectinuseprotection/admission.go b/plugin/pkg/admission/storage/storageobjectinuseprotection/admission.go index f9d769c3266..8c70d927c8f 100644 --- a/plugin/pkg/admission/storage/storageobjectinuseprotection/admission.go +++ b/plugin/pkg/admission/storage/storageobjectinuseprotection/admission.go @@ -65,7 +65,7 @@ var ( // // This prevents users from deleting a PVC that's used by a running pod. // This also prevents admin from deleting a PV that's bound by a PVC -func (c *storageProtectionPlugin) Admit(a admission.Attributes) error { +func (c *storageProtectionPlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { if !feature.DefaultFeatureGate.Enabled(features.StorageObjectInUseProtection) { return nil } diff --git a/plugin/pkg/admission/storage/storageobjectinuseprotection/admission_test.go b/plugin/pkg/admission/storage/storageobjectinuseprotection/admission_test.go index 54ee9da6ae7..1870ea46dee 100644 --- a/plugin/pkg/admission/storage/storageobjectinuseprotection/admission_test.go +++ b/plugin/pkg/admission/storage/storageobjectinuseprotection/admission_test.go @@ -135,7 +135,7 @@ func TestAdmit(t *testing.T) { nil, // userInfo ) - err := ctrl.Admit(attrs) + err := ctrl.Admit(attrs, nil) if err != nil { t.Errorf("Test %q: got unexpected error: %v", test.name, err) } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/cmd/server/options/options.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/cmd/server/options/options.go index c787aa6419f..8803bb3997d 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/cmd/server/options/options.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/cmd/server/options/options.go @@ -91,7 +91,7 @@ func (o CustomResourceDefinitionsServerOptions) Config() (*apiserver.Config, err } serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs) - if err := o.RecommendedOptions.ApplyTo(serverConfig, apiserver.Scheme); err != nil { + if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil { return nil, err } if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), apiserver.Scheme); err != nil { diff --git a/staging/src/k8s.io/apiserver/pkg/admission/BUILD b/staging/src/k8s.io/apiserver/pkg/admission/BUILD index 658d1d3ff30..6a37d463e39 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/admission/BUILD @@ -42,6 +42,7 @@ go_library( "handler.go", "interfaces.go", "plugins.go", + "util.go", ], importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/admission", importpath = "k8s.io/apiserver/pkg/admission", 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/BUILD b/staging/src/k8s.io/apiserver/pkg/admission/initializer/BUILD index a5de9eee25c..130de6417b8 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/initializer/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/admission/initializer/BUILD @@ -15,7 +15,6 @@ go_library( importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/admission/initializer", importpath = "k8s.io/apiserver/pkg/admission/initializer", deps = [ - "//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/authorization/authorizer:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library", @@ -28,7 +27,6 @@ go_test( srcs = ["initializer_test.go"], embed = [":go_default_library"], deps = [ - "//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/authorization/authorizer:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library", diff --git a/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer.go b/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer.go index abe764bb94d..822885a5e87 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer.go @@ -17,7 +17,6 @@ limitations under the License. package initializer import ( - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/client-go/informers" @@ -28,7 +27,6 @@ type pluginInitializer struct { externalClient kubernetes.Interface externalInformers informers.SharedInformerFactory authorizer authorizer.Authorizer - scheme *runtime.Scheme } // New creates an instance of admission plugins initializer. @@ -37,13 +35,11 @@ func New( extClientset kubernetes.Interface, extInformers informers.SharedInformerFactory, authz authorizer.Authorizer, - scheme *runtime.Scheme, ) pluginInitializer { return pluginInitializer{ externalClient: extClientset, externalInformers: extInformers, authorizer: authz, - scheme: scheme, } } @@ -61,10 +57,6 @@ func (i pluginInitializer) Initialize(plugin admission.Interface) { if wants, ok := plugin.(WantsAuthorizer); ok { wants.SetAuthorizer(i.authorizer) } - - if wants, ok := plugin.(WantsScheme); ok { - wants.SetScheme(i.scheme) - } } var _ admission.PluginInitializer = pluginInitializer{} 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..fd2d500619f 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 @@ -20,7 +20,6 @@ import ( "testing" "time" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission/initializer" "k8s.io/apiserver/pkg/authorization/authorizer" @@ -29,22 +28,10 @@ import ( "k8s.io/client-go/kubernetes/fake" ) -// TestWantsScheme ensures that the scheme is injected when -// the WantsScheme interface is implemented by a plugin. -func TestWantsScheme(t *testing.T) { - scheme := runtime.NewScheme() - target := initializer.New(nil, nil, nil, scheme) - wantSchemeAdmission := &WantSchemeAdmission{} - target.Initialize(wantSchemeAdmission) - if wantSchemeAdmission.scheme != scheme { - t.Errorf("expected scheme to be initialized") - } -} - // TestWantsAuthorizer ensures that the authorizer is injected // when the WantsAuthorizer interface is implemented by a plugin. func TestWantsAuthorizer(t *testing.T) { - target := initializer.New(nil, nil, &TestAuthorizer{}, nil) + target := initializer.New(nil, nil, &TestAuthorizer{}) wantAuthorizerAdmission := &WantAuthorizerAdmission{} target.Initialize(wantAuthorizerAdmission) if wantAuthorizerAdmission.auth == nil { @@ -56,7 +43,7 @@ func TestWantsAuthorizer(t *testing.T) { // when the WantsExternalKubeClientSet interface is implemented by a plugin. func TestWantsExternalKubeClientSet(t *testing.T) { cs := &fake.Clientset{} - target := initializer.New(cs, nil, &TestAuthorizer{}, nil) + target := initializer.New(cs, nil, &TestAuthorizer{}) wantExternalKubeClientSet := &WantExternalKubeClientSet{} target.Initialize(wantExternalKubeClientSet) if wantExternalKubeClientSet.cs != cs { @@ -69,7 +56,7 @@ func TestWantsExternalKubeClientSet(t *testing.T) { func TestWantsExternalKubeInformerFactory(t *testing.T) { cs := &fake.Clientset{} sf := informers.NewSharedInformerFactory(cs, time.Duration(1)*time.Second) - target := initializer.New(cs, sf, &TestAuthorizer{}, nil) + target := initializer.New(cs, sf, &TestAuthorizer{}) wantExternalKubeInformerFactory := &WantExternalKubeInformerFactory{} target.Initialize(wantExternalKubeInformerFactory) if wantExternalKubeInformerFactory.sf != sf { @@ -85,7 +72,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 +87,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 +102,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,20 +123,9 @@ 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 } - -// WantSchemeAdmission is a test stub that fulfills the WantsScheme interface. -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) Handles(o admission.Operation) bool { return false } -func (self *WantSchemeAdmission) ValidateInitialization() error { return nil } - -var _ admission.Interface = &WantSchemeAdmission{} -var _ initializer.WantsScheme = &WantSchemeAdmission{} diff --git a/staging/src/k8s.io/apiserver/pkg/admission/initializer/interfaces.go b/staging/src/k8s.io/apiserver/pkg/admission/initializer/interfaces.go index 98a07585406..9bddb7155cd 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/initializer/interfaces.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/initializer/interfaces.go @@ -17,7 +17,6 @@ limitations under the License. package initializer import ( - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/client-go/informers" @@ -41,9 +40,3 @@ type WantsAuthorizer interface { SetAuthorizer(authorizer.Authorizer) admission.InitializationValidator } - -// WantsScheme defines a function that accepts runtime.Scheme for admission plugins that need it. -type WantsScheme interface { - SetScheme(*runtime.Scheme) - admission.InitializationValidator -} 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/namespace/lifecycle/admission.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle/admission.go index d7bb0215b98..c6517bee31e 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle/admission.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle/admission.go @@ -73,7 +73,7 @@ var _ = initializer.WantsExternalKubeInformerFactory(&Lifecycle{}) var _ = initializer.WantsExternalKubeClientSet(&Lifecycle{}) // Admit makes an admission decision based on the request attributes -func (l *Lifecycle) Admit(a admission.Attributes) error { +func (l *Lifecycle) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { // prevent deletion of immortal namespaces if a.GetOperation() == admission.Delete && a.GetKind().GroupKind() == v1.SchemeGroupVersion.WithKind("Namespace").GroupKind() && l.immortalNamespaces.Has(a.GetName()) { return errors.NewForbidden(a.GetResource().GroupResource(), a.GetName(), fmt.Errorf("this namespace may not be deleted")) 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 8a56cc3e86c..593c107dbf0 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 @@ -48,7 +48,7 @@ func newHandlerForTestWithClock(c clientset.Interface, cacheClock clock.Clock) ( if err != nil { return nil, f, err } - pluginInitializer := kubeadmission.New(c, f, nil, nil) + pluginInitializer := kubeadmission.New(c, f, nil) pluginInitializer.Initialize(handler) err = admission.ValidateInitialization(handler) return handler, f, err @@ -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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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)) + 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) 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/generic/BUILD b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/BUILD index 75883f61354..b8f9bb55274 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/BUILD @@ -50,6 +50,7 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured: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", "//staging/src/k8s.io/apiserver/pkg/apis/example:go_default_library", "//staging/src/k8s.io/apiserver/pkg/apis/example/v1:go_default_library", "//staging/src/k8s.io/apiserver/pkg/apis/example2/v1:go_default_library", 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/interfaces.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/interfaces.go index 3a7edb526d6..d998b6b71ec 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/interfaces.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/interfaces.go @@ -41,5 +41,5 @@ type VersionedAttributes struct { // Dispatcher dispatches webhook call to a list of webhooks with admission attributes as argument. type Dispatcher interface { // Dispatch a request to the webhooks using the given webhooks. A non-nil error means the request is rejected. - Dispatch(ctx context.Context, a *VersionedAttributes, hooks []*v1beta1.Webhook) error + Dispatch(ctx context.Context, a *VersionedAttributes, o admission.ObjectInterfaces, hooks []*v1beta1.Webhook) error } 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..c44f67346c2 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 @@ -24,7 +24,6 @@ import ( admissionv1beta1 "k8s.io/api/admission/v1beta1" "k8s.io/api/admissionregistration/v1beta1" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/admission" genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer" "k8s.io/apiserver/pkg/admission/plugin/webhook/config" @@ -43,7 +42,6 @@ type Webhook struct { hookSource Source clientManager *webhook.ClientManager - convertor *convertor namespaceMatcher *namespace.Matcher dispatcher Dispatcher } @@ -79,7 +77,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 @@ -98,13 +95,6 @@ func (a *Webhook) SetServiceResolver(sr webhook.ServiceResolver) { a.clientManager.SetServiceResolver(sr) } -// 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. // It sets external ClientSet for admission plugins that need it func (a *Webhook) SetExternalKubeClientSet(client clientset.Interface) { @@ -132,9 +122,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 +143,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,18 +175,18 @@ 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) } versionedAttr.VersionedObject = out } - return a.dispatcher.Dispatch(ctx, &versionedAttr, relevantHooks) + return a.dispatcher.Dispatch(ctx, &versionedAttr, o, relevantHooks) } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/BUILD b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/BUILD index da393cf2283..1a6530395f4 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/BUILD @@ -39,8 +39,6 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//staging/src/k8s.io/api/admission/v1beta1:go_default_library", - "//staging/src/k8s.io/api/core/v1: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/apis/meta/v1/unstructured:go_default_library", diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go index d646bacb535..44490d1b4f0 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go @@ -31,7 +31,9 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer/json" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apiserver/pkg/admission" admissionmetrics "k8s.io/apiserver/pkg/admission/metrics" webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors" "k8s.io/apiserver/pkg/admission/plugin/webhook/generic" @@ -53,10 +55,10 @@ func newMutatingDispatcher(p *Plugin) func(cm *webhook.ClientManager) generic.Di var _ generic.Dispatcher = &mutatingDispatcher{} -func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, relevantHooks []*v1beta1.Webhook) error { +func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, o admission.ObjectInterfaces, relevantHooks []*v1beta1.Webhook) error { for _, hook := range relevantHooks { t := time.Now() - err := a.callAttrMutatingHook(ctx, hook, attr) + err := a.callAttrMutatingHook(ctx, hook, attr, o) admissionmetrics.Metrics.ObserveWebhook(time.Since(t), err != nil, attr.Attributes, "admit", hook.Name) if err == nil { continue @@ -76,13 +78,13 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr *generic.Version // convert attr.VersionedObject to the internal version in the underlying admission.Attributes if attr.VersionedObject != nil { - return a.plugin.scheme.Convert(attr.VersionedObject, attr.Attributes.GetObject(), nil) + return o.GetObjectConvertor().Convert(attr.VersionedObject, attr.Attributes.GetObject(), nil) } return nil } // note that callAttrMutatingHook updates attr -func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta1.Webhook, attr *generic.VersionedAttributes) error { +func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta1.Webhook, attr *generic.VersionedAttributes, o admission.ObjectInterfaces) error { if attr.IsDryRun() { if h.SideEffects == nil { return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook SideEffects is nil")} @@ -135,7 +137,8 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta return apierrors.NewInternalError(fmt.Errorf("admission webhook %q attempted to modify the object, which is not supported for this operation", h.Name)) } - objJS, err := runtime.Encode(a.plugin.jsonSerializer, attr.VersionedObject) + jsonSerializer := json.NewSerializer(json.DefaultMetaFactory, o.GetObjectCreater(), o.GetObjectTyper(), false) + objJS, err := runtime.Encode(jsonSerializer, attr.VersionedObject) if err != nil { return apierrors.NewInternalError(err) } @@ -150,17 +153,17 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta // They are represented as Unstructured. newVersionedObject = &unstructured.Unstructured{} } else { - newVersionedObject, err = a.plugin.scheme.New(attr.GetKind()) + newVersionedObject, err = o.GetObjectCreater().New(attr.GetKind()) if err != nil { return apierrors.NewInternalError(err) } } // TODO: if we have multiple mutating webhooks, we can remember the json // instead of encoding and decoding for each one. - if _, _, err := a.plugin.jsonSerializer.Decode(patchedJS, nil, newVersionedObject); err != nil { + if _, _, err := jsonSerializer.Decode(patchedJS, nil, newVersionedObject); err != nil { return apierrors.NewInternalError(err) } attr.VersionedObject = newVersionedObject - a.plugin.scheme.Default(attr.VersionedObject) + o.GetObjectDefaulter().Default(attr.VersionedObject) return nil } 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 ccea2686243..53bcf0124dc 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 @@ -49,6 +49,7 @@ func TestDispatch(t *testing.T) { require.NoError(t, example.AddToScheme(scheme)) require.NoError(t, examplev1.AddToScheme(scheme)) require.NoError(t, example2v1.AddToScheme(scheme)) + objectInterfaces := &admission.SchemeBasedObjectInterfaces{scheme} tests := []struct { name string @@ -118,16 +119,14 @@ func TestDispatch(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { a := &mutatingDispatcher{ - plugin: &Plugin{ - scheme: scheme, - }, + plugin: &Plugin{}, } attr := generic.VersionedAttributes{ Attributes: admission.NewAttributesRecord(test.out, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", admission.Operation(""), false, nil), VersionedOldObject: nil, VersionedObject: test.in, } - if err := a.Dispatch(context.TODO(), &attr, nil); err != nil { + if err := a.Dispatch(context.TODO(), &attr, objectInterfaces, nil); err != nil { t.Fatalf("%s: unexpected error: %v", test.name, err) } if !reflect.DeepEqual(attr.Attributes.GetObject(), test.expectedObj) { 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..6202fbc63fe 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 @@ -17,11 +17,8 @@ limitations under the License. package mutating import ( - "fmt" "io" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/serializer/json" "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission/configuration" "k8s.io/apiserver/pkg/admission/plugin/webhook/generic" @@ -47,9 +44,6 @@ func Register(plugins *admission.Plugins) { // Plugin is an implementation of admission.Interface. type Plugin struct { *generic.Webhook - - scheme *runtime.Scheme - jsonSerializer *json.Serializer } var _ admission.MutationInterface = &Plugin{} @@ -67,30 +61,15 @@ func NewMutatingWebhook(configFile io.Reader) (*Plugin, error) { return p, nil } -// SetScheme sets a serializer(NegotiatedSerializer) which is derived from the scheme -func (a *Plugin) SetScheme(scheme *runtime.Scheme) { - a.Webhook.SetScheme(scheme) - if scheme != nil { - a.scheme = scheme - a.jsonSerializer = json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false) - } -} - // ValidateInitialization implements the InitializationValidator interface. func (a *Plugin) ValidateInitialization() error { if err := a.Webhook.ValidateInitialization(); err != nil { return err } - if a.scheme == nil { - return fmt.Errorf("scheme is not properly setup") - } - if a.jsonSerializer == nil { - return fmt.Errorf("jsonSerializer is not properly setup") - } return nil } // 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/BUILD b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/BUILD index ea9f489f8ec..f9f1c668eb7 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/BUILD @@ -32,13 +32,9 @@ go_test( srcs = ["plugin_test.go"], embed = [":go_default_library"], deps = [ - "//staging/src/k8s.io/api/admission/v1beta1:go_default_library", - "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/github.com/stretchr/testify/require:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/dispatcher.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/dispatcher.go index 166e21adcdf..d779be7b835 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/dispatcher.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/dispatcher.go @@ -28,6 +28,7 @@ import ( "k8s.io/api/admissionregistration/v1beta1" apierrors "k8s.io/apimachinery/pkg/api/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apiserver/pkg/admission" admissionmetrics "k8s.io/apiserver/pkg/admission/metrics" webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors" "k8s.io/apiserver/pkg/admission/plugin/webhook/generic" @@ -46,7 +47,7 @@ func newValidatingDispatcher(cm *webhook.ClientManager) generic.Dispatcher { var _ generic.Dispatcher = &validatingDispatcher{} -func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, relevantHooks []*v1beta1.Webhook) error { +func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, o admission.ObjectInterfaces, relevantHooks []*v1beta1.Webhook) error { wg := sync.WaitGroup{} errCh := make(chan error, len(relevantHooks)) wg.Add(len(relevantHooks)) 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/apiserver/pkg/server/options/admission.go b/staging/src/k8s.io/apiserver/pkg/server/options/admission.go index 898e0630933..d07180f9a57 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/admission.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/admission.go @@ -117,18 +117,12 @@ func (a *AdmissionOptions) ApplyTo( c *server.Config, informers informers.SharedInformerFactory, kubeAPIServerClientConfig *rest.Config, - scheme *runtime.Scheme, pluginInitializers ...admission.PluginInitializer, ) error { if a == nil { return nil } - // Admission need scheme to construct admission initializer. - if scheme == nil { - return fmt.Errorf("admission depends on a scheme, it cannot be nil") - } - // Admission depends on CoreAPI to set SharedInformerFactory and ClientConfig. if informers == nil { return fmt.Errorf("admission depends on a Kubernetes core API shared informer, it cannot be nil") @@ -145,7 +139,7 @@ func (a *AdmissionOptions) ApplyTo( if err != nil { return err } - genericInitializer := initializer.New(clientset, informers, c.Authorization.Authorizer, scheme) + genericInitializer := initializer.New(clientset, informers, c.Authorization.Authorizer) initializersChain := admission.PluginInitializers{} pluginInitializers = append(pluginInitializers, genericInitializer) initializersChain = append(initializersChain, pluginInitializers...) diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/api_enablement.go b/staging/src/k8s.io/apiserver/pkg/server/options/api_enablement.go index 686be5aba97..65f143bf0d7 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/api_enablement.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/api_enablement.go @@ -84,6 +84,7 @@ func (s *APIEnablementOptions) Validate(registries ...GroupRegisty) []error { // ApplyTo override MergedResourceConfig with defaults and registry func (s *APIEnablementOptions) ApplyTo(c *server.Config, defaultResourceConfig *serverstore.ResourceConfig, registry resourceconfig.GroupVersionRegistry) error { + if s == nil { return nil } diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go b/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go index 500d578d6bd..631b4f43e39 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go @@ -82,9 +82,8 @@ func (o *RecommendedOptions) AddFlags(fs *pflag.FlagSet) { } // ApplyTo adds RecommendedOptions to the server configuration. -// scheme is the scheme of the apiserver types that are sent to the admission chain. // pluginInitializers can be empty, it is only need for additional initializers. -func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig, scheme *runtime.Scheme) error { +func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig) error { if err := o.Etcd.ApplyTo(&config.Config); err != nil { return err } @@ -108,7 +107,7 @@ func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig, scheme *r } if initializers, err := o.ExtraAdmissionInitializers(config); err != nil { return err - } else if err := o.Admission.ApplyTo(&config.Config, config.SharedInformerFactory, config.ClientConfig, scheme, initializers...); err != nil { + } else if err := o.Admission.ApplyTo(&config.Config, config.SharedInformerFactory, config.ClientConfig, initializers...); err != nil { return err } diff --git a/staging/src/k8s.io/kube-aggregator/pkg/cmd/server/start.go b/staging/src/k8s.io/kube-aggregator/pkg/cmd/server/start.go index a86186f4fad..9dd8d7021f7 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/cmd/server/start.go +++ b/staging/src/k8s.io/kube-aggregator/pkg/cmd/server/start.go @@ -122,7 +122,7 @@ func (o AggregatorOptions) RunAggregator(stopCh <-chan struct{}) error { serverConfig := genericapiserver.NewRecommendedConfig(aggregatorscheme.Codecs) - if err := o.RecommendedOptions.ApplyTo(serverConfig, aggregatorscheme.Scheme); err != nil { + if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil { return err } if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), aggregatorscheme.Scheme); err != nil { 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 38809abc83c..474c1a58d10 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/plugin/banflunder/admission_test.go b/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission_test.go index df63438eb42..a6479aa1a98 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 @@ -138,6 +138,7 @@ func TestBanflunderAdmissionPlugin(t *testing.T) { admission.Create, false, nil), + nil, ) // validate 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 865a6790b76..8e994d71e14 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 } diff --git a/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go b/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go index 52b5bd9cdbd..48aa538ba08 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go @@ -120,7 +120,7 @@ func (o *WardleServerOptions) Config() (*apiserver.Config, error) { } serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs) - if err := o.RecommendedOptions.ApplyTo(serverConfig, apiserver.Scheme); err != nil { + if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil { return nil, err } diff --git a/test/e2e/apimachinery/webhook.go b/test/e2e/apimachinery/webhook.go index 7f6dba57c35..92de1b41096 100644 --- a/test/e2e/apimachinery/webhook.go +++ b/test/e2e/apimachinery/webhook.go @@ -183,6 +183,24 @@ var _ = SIGDescribe("AdmissionWebhook", func() { testCRDDenyWebhook(f) }) + It("Should mutate custom resource with different stored version", func() { + testcrd, err := framework.CreateMultiVersionTestCRDWithV1Storage(f) + if err != nil { + return + } + defer testcrd.CleanUp() + webhookCleanup := registerMutatingWebhookForCustomResource(f, context, testcrd) + defer webhookCleanup() + testMultiVersionCustomResourceWebhook(f, testcrd) + }) + + It("Should deny crd creation", func() { + crdWebhookCleanup := registerValidatingWebhookForCRD(f, context) + defer crdWebhookCleanup() + + testCRDDenyWebhook(f) + }) + // TODO: add more e2e tests for mutating webhooks // 1. mutating webhook that mutates pod // 2. mutating webhook that sends empty patch @@ -1154,7 +1172,7 @@ func registerWebhookForCustomResource(f *framework.Framework, context *certConte { Name: "deny-unwanted-custom-resource-data.k8s.io", Rules: []v1beta1.RuleWithOperations{{ - Operations: []v1beta1.OperationType{v1beta1.Create}, + Operations: []v1beta1.OperationType{v1beta1.Create, v1beta1.Update}, Rule: v1beta1.Rule{ APIGroups: []string{testcrd.ApiGroup}, APIVersions: testcrd.GetAPIVersions(), @@ -1195,7 +1213,7 @@ func registerMutatingWebhookForCustomResource(f *framework.Framework, context *c { Name: "mutate-custom-resource-data-stage-1.k8s.io", Rules: []v1beta1.RuleWithOperations{{ - Operations: []v1beta1.OperationType{v1beta1.Create}, + Operations: []v1beta1.OperationType{v1beta1.Create, v1beta1.Update}, Rule: v1beta1.Rule{ APIGroups: []string{testcrd.ApiGroup}, APIVersions: testcrd.GetAPIVersions(), @@ -1292,6 +1310,37 @@ func testMutatingCustomResourceWebhook(f *framework.Framework, crd *apiextension } } +func testMultiVersionCustomResourceWebhook(f *framework.Framework, testcrd *framework.TestCrd) { + customResourceClient := testcrd.GetV1DynamicClient() + By("Creating a custom resource while v1 is storage version") + crName := "cr-instance-1" + cr := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "kind": testcrd.Crd.Spec.Names.Kind, + "apiVersion": testcrd.Crd.Spec.Group + "/" + testcrd.Crd.Spec.Version, + "metadata": map[string]interface{}{ + "name": crName, + "namespace": f.Namespace.Name, + }, + "data": map[string]interface{}{ + "mutation-start": "yes", + }, + }, + } + _, err := customResourceClient.Create(cr, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred(), "failed to create custom resource %s in namespace: %s", crName, f.Namespace.Name) + + By("Patching Custom Resource Definition to set v2 as storage") + apiVersionWithV2StoragePatch := fmt.Sprint(`{"spec": {"versions": [{"name": "v1", "storage": false, "served": true},{"name": "v2", "storage": true, "served": true}]}}`) + _, err = testcrd.ApiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Patch(testcrd.Crd.Name, types.StrategicMergePatchType, []byte(apiVersionWithV2StoragePatch)) + Expect(err).NotTo(HaveOccurred(), "failed to patch custom resource definition %s in namespace: %s", testcrd.Crd.Name, f.Namespace.Name) + + By("Patching the custom resource while v2 is storage version") + crDummyPatch := fmt.Sprint(`[{ "op": "add", "path": "/dummy", "value": "test" }]`) + _, err = testcrd.DynamicClients["v2"].Patch(crName, types.JSONPatchType, []byte(crDummyPatch), metav1.PatchOptions{}) + Expect(err).NotTo(HaveOccurred(), "failed to patch custom resource %s in namespace: %s", crName, f.Namespace.Name) +} + func registerValidatingWebhookForCRD(f *framework.Framework, context *certContext) func() { client := f.ClientSet By("Registering the crd webhook via the AdmissionRegistration API") diff --git a/test/e2e/framework/crd_util.go b/test/e2e/framework/crd_util.go index dc48d188d76..0bd0365dfff 100644 --- a/test/e2e/framework/crd_util.go +++ b/test/e2e/framework/crd_util.go @@ -121,6 +121,24 @@ func CreateTestCRD(f *Framework) (*TestCrd, error) { return CreateMultiVersionTestCRD(f, group, apiVersions, nil) } +// CreateTestCRD creates a new CRD specifically for the calling test. +func CreateMultiVersionTestCRDWithV1Storage(f *Framework) (*TestCrd, error) { + group := fmt.Sprintf("%s-multiversion-crd-test.k8s.io", f.BaseName) + apiVersions := []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + { + Name: "v1", + Served: true, + Storage: true, + }, + { + Name: "v2", + Served: true, + Storage: false, + }, + } + return CreateMultiVersionTestCRD(f, group, apiVersions, nil) +} + // newCRDForTest generates a CRD definition for the test func newCRDForTest(testcrd *TestCrd) *apiextensionsv1beta1.CustomResourceDefinition { return &apiextensionsv1beta1.CustomResourceDefinition{