Merge pull request #74154 from mbohlool/gimli

Use Request Object interfaces instead of static scheme that is more appropriate for CRDs
This commit is contained in:
Kubernetes Prow Robot 2019-02-19 07:21:53 -08:00 committed by GitHub
commit 0ffd59e403
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
110 changed files with 445 additions and 425 deletions

View File

@ -70,7 +70,6 @@ func createAggregatorConfig(
&genericConfig,
externalInformers,
genericConfig.LoopbackClientConfig,
aggregatorscheme.Scheme,
pluginInitializers...)
if err != nil {
return nil, err

View File

@ -52,7 +52,6 @@ func createAPIExtensionsConfig(
&genericConfig,
externalInformers,
genericConfig.LoopbackClientConfig,
apiextensionsapiserver.Scheme,
pluginInitializers...)
if err != nil {
return nil, err

View File

@ -491,7 +491,6 @@ func buildGenericConfig(
genericConfig,
versionedInformers,
kubeClientConfig,
legacyscheme.Scheme,
pluginInitializers...)
if err != nil {
lastErr = fmt.Errorf("failed to initialize admission: %v", err)

View File

@ -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 }

View File

@ -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",

View File

@ -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

View File

@ -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
}

View File

@ -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")
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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

View File

@ -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 {

View File

@ -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
}

View File

@ -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)
}

View File

@ -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"))
}

View File

@ -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")
}

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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)
}

View File

@ -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

View File

@ -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)
}

View File

@ -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

View File

@ -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)
}

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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

View File

@ -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

View File

@ -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")
}

View File

@ -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.

View File

@ -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() {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)
}

View File

@ -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
}

View File

@ -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

View File

@ -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 {

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -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

View File

@ -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)

View File

@ -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 {

View File

@ -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

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)
}

View File

@ -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 {

View File

@ -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",

View File

@ -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

View File

@ -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 {

View File

@ -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
}

View File

@ -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)

View File

@ -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",

View File

@ -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{}

View File

@ -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{}

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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"))

View File

@ -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)
}

View File

@ -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",

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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",

View File

@ -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
}

View File

@ -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) {

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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}
}

View File

@ -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",
],
)

View File

@ -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))

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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 }

View File

@ -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"))
}

View File

@ -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,
)
})

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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())
}

View File

@ -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,
)

View File

@ -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)
}
}

View File

@ -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)
}
}

Some files were not shown because too many files have changed in this diff Show More