From 131905cdb8b929f7c15f810e02ec9a45b306b769 Mon Sep 17 00:00:00 2001 From: "Dr. Stefan Schimanski" Date: Mon, 30 Oct 2017 14:20:40 +0100 Subject: [PATCH] admission: unify plugin constructors --- plugin/pkg/admission/admit/admission.go | 15 ++++--- .../admission/alwayspullimages/admission.go | 11 ++--- .../alwayspullimages/admission_test.go | 4 +- .../pkg/admission/antiaffinity/admission.go | 10 ++--- .../admission/antiaffinity/admission_test.go | 2 +- .../defaulttolerationseconds/admission.go | 11 ++--- plugin/pkg/admission/deny/admission.go | 15 ++++--- .../pkg/admission/eventratelimit/admission.go | 10 ++--- plugin/pkg/admission/exec/admission.go | 23 +++++----- plugin/pkg/admission/exec/admission_test.go | 16 +++---- plugin/pkg/admission/imagepolicy/admission.go | 21 +++++----- .../admission/imagepolicy/admission_test.go | 6 +-- .../admission/initialresources/admission.go | 17 ++++---- plugin/pkg/admission/limitranger/admission.go | 20 ++++----- .../admission/limitranger/admission_test.go | 2 +- .../namespace/autoprovision/admission.go | 24 ++++++----- .../admission/namespace/exists/admission.go | 24 ++++++----- plugin/pkg/admission/priority/admission.go | 33 ++++++++------- .../pkg/admission/priority/admission_test.go | 8 ++-- .../pkg/admission/resourcequota/admission.go | 22 +++++----- .../admission/resourcequota/admission_test.go | 42 +++++++++---------- .../securitycontext/scdeny/admission.go | 9 ++-- .../k8s.io/apiserver/pkg/admission/chain.go | 2 +- .../plugin/initialization/initialization.go | 5 +++ .../plugin/namespace/lifecycle/admission.go | 3 ++ .../pkg/admission/plugin/webhook/admission.go | 3 ++ test/integration/quota/BUILD | 1 - test/integration/quota/quota_test.go | 13 +++--- 28 files changed, 203 insertions(+), 169 deletions(-) diff --git a/plugin/pkg/admission/admit/admission.go b/plugin/pkg/admission/admit/admission.go index 6ba8e59dd70..8605b9d2bf8 100644 --- a/plugin/pkg/admission/admit/admission.go +++ b/plugin/pkg/admission/admit/admission.go @@ -29,19 +29,22 @@ func Register(plugins *admission.Plugins) { }) } -// alwaysAdmit is an implementation of admission.Interface which always says yes to an admit request. +// AlwaysAdmit is an implementation of admission.Interface which always says yes to an admit request. // It is useful in tests and when using kubernetes in an open manner. -type alwaysAdmit struct{} +type AlwaysAdmit struct{} -func (alwaysAdmit) Admit(a admission.Attributes) (err error) { +// Admit makes an admission decision based on the request attributes +func (AlwaysAdmit) Admit(a admission.Attributes) (err error) { return nil } -func (alwaysAdmit) Handles(operation admission.Operation) bool { +// Handles returns true if this admission controller can handle the given operation +// where operation can be one of CREATE, UPDATE, DELETE, or CONNECT +func (AlwaysAdmit) Handles(operation admission.Operation) bool { return true } // NewAlwaysAdmit creates a new always admit admission handler -func NewAlwaysAdmit() admission.Interface { - return new(alwaysAdmit) +func NewAlwaysAdmit() *AlwaysAdmit { + return new(AlwaysAdmit) } diff --git a/plugin/pkg/admission/alwayspullimages/admission.go b/plugin/pkg/admission/alwayspullimages/admission.go index 0d71f127abf..af46c84732a 100644 --- a/plugin/pkg/admission/alwayspullimages/admission.go +++ b/plugin/pkg/admission/alwayspullimages/admission.go @@ -39,13 +39,14 @@ func Register(plugins *admission.Plugins) { }) } -// alwaysPullImages is an implementation of admission.Interface. +// AlwaysPullImages is an implementation of admission.Interface. // It looks at all new pods and overrides each container's image pull policy to Always. -type alwaysPullImages struct { +type AlwaysPullImages struct { *admission.Handler } -func (a *alwaysPullImages) Admit(attributes admission.Attributes) (err error) { +// Admit makes an admission decision based on the request attributes +func (a *AlwaysPullImages) Admit(attributes admission.Attributes) (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 @@ -67,8 +68,8 @@ func (a *alwaysPullImages) Admit(attributes admission.Attributes) (err error) { } // NewAlwaysPullImages creates a new always pull images admission control handler -func NewAlwaysPullImages() admission.Interface { - return &alwaysPullImages{ +func NewAlwaysPullImages() *AlwaysPullImages { + return &AlwaysPullImages{ Handler: admission.NewHandler(admission.Create, admission.Update), } } diff --git a/plugin/pkg/admission/alwayspullimages/admission_test.go b/plugin/pkg/admission/alwayspullimages/admission_test.go index e291e6e669c..7376f449f86 100644 --- a/plugin/pkg/admission/alwayspullimages/admission_test.go +++ b/plugin/pkg/admission/alwayspullimages/admission_test.go @@ -29,7 +29,7 @@ import ( // set to Always func TestAdmission(t *testing.T) { namespace := "test" - handler := &alwaysPullImages{} + handler := &AlwaysPullImages{} pod := api.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: namespace}, Spec: api.PodSpec{ @@ -107,7 +107,7 @@ func TestOtherResources(t *testing.T) { } for _, tc := range tests { - handler := &alwaysPullImages{} + 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, nil)) diff --git a/plugin/pkg/admission/antiaffinity/admission.go b/plugin/pkg/admission/antiaffinity/admission.go index c42a1b211c1..fd3cf54fdec 100644 --- a/plugin/pkg/admission/antiaffinity/admission.go +++ b/plugin/pkg/admission/antiaffinity/admission.go @@ -33,21 +33,21 @@ func Register(plugins *admission.Plugins) { }) } -// plugin contains the client used by the admission controller -type plugin struct { +// Plugin contains the client used by the admission controller +type Plugin struct { *admission.Handler } // NewInterPodAntiAffinity creates a new instance of the LimitPodHardAntiAffinityTopology admission controller -func NewInterPodAntiAffinity() admission.Interface { - return &plugin{ +func NewInterPodAntiAffinity() *Plugin { + return &Plugin{ Handler: admission.NewHandler(admission.Create, admission.Update), } } // Admit will deny any pod that defines AntiAffinity topology key other than kubeletapis.LabelHostname i.e. "kubernetes.io/hostname" // in requiredDuringSchedulingRequiredDuringExecution and requiredDuringSchedulingIgnoredDuringExecution. -func (p *plugin) Admit(attributes admission.Attributes) (err error) { +func (p *Plugin) Admit(attributes admission.Attributes) (err error) { // Ignore all calls to subresources or resources other than pods. if len(attributes.GetSubresource()) != 0 || attributes.GetResource().GroupResource() != api.Resource("pods") { return nil diff --git a/plugin/pkg/admission/antiaffinity/admission_test.go b/plugin/pkg/admission/antiaffinity/admission_test.go index f38be9a1f68..114c39766b6 100644 --- a/plugin/pkg/admission/antiaffinity/admission_test.go +++ b/plugin/pkg/admission/antiaffinity/admission_test.go @@ -265,7 +265,7 @@ func TestOtherResources(t *testing.T) { } for _, tc := range tests { - handler := &plugin{} + handler := &Plugin{} 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, nil)) diff --git a/plugin/pkg/admission/defaulttolerationseconds/admission.go b/plugin/pkg/admission/defaulttolerationseconds/admission.go index 430ed22f5be..f3630a873dd 100644 --- a/plugin/pkg/admission/defaulttolerationseconds/admission.go +++ b/plugin/pkg/admission/defaulttolerationseconds/admission.go @@ -45,24 +45,25 @@ func Register(plugins *admission.Plugins) { }) } -// plugin contains the client used by the admission controller +// Plugin contains the client used by the admission controller // It will add default tolerations for every pod // that tolerate taints `notReady:NoExecute` and `unreachable:NoExecute`, // with tolerationSeconds of 300s. // If the pod already specifies a toleration for taint `notReady:NoExecute` // or `unreachable:NoExecute`, the plugin won't touch it. -type plugin struct { +type Plugin struct { *admission.Handler } // NewDefaultTolerationSeconds creates a new instance of the DefaultTolerationSeconds admission controller -func NewDefaultTolerationSeconds() admission.Interface { - return &plugin{ +func NewDefaultTolerationSeconds() *Plugin { + return &Plugin{ Handler: admission.NewHandler(admission.Create, admission.Update), } } -func (p *plugin) Admit(attributes admission.Attributes) (err error) { +// Admit makes an admission decision based on the request attributes +func (p *Plugin) Admit(attributes admission.Attributes) (err error) { if attributes.GetResource().GroupResource() != api.Resource("pods") { return nil } diff --git a/plugin/pkg/admission/deny/admission.go b/plugin/pkg/admission/deny/admission.go index bef3429c251..671f1909963 100644 --- a/plugin/pkg/admission/deny/admission.go +++ b/plugin/pkg/admission/deny/admission.go @@ -30,19 +30,22 @@ func Register(plugins *admission.Plugins) { }) } -// alwaysDeny is an implementation of admission.Interface which always says no to an admission request. +// AlwaysDeny is an implementation of admission.Interface which always says no to an admission request. // It is useful in unit tests to force an operation to be forbidden. -type alwaysDeny struct{} +type AlwaysDeny struct{} -func (alwaysDeny) Admit(a admission.Attributes) (err error) { +// Admit makes an admission decision based on the request attributes. +func (AlwaysDeny) Admit(a admission.Attributes) (err error) { return admission.NewForbidden(a, errors.New("Admission control is denying all modifications")) } -func (alwaysDeny) Handles(operation admission.Operation) bool { +// Handles returns true if this admission controller can handle the given operation +// where operation can be one of CREATE, UPDATE, DELETE, or CONNECT +func (AlwaysDeny) Handles(operation admission.Operation) bool { return true } // NewAlwaysDeny creates an always deny admission handler -func NewAlwaysDeny() admission.Interface { - return new(alwaysDeny) +func NewAlwaysDeny() *AlwaysDeny { + return new(AlwaysDeny) } diff --git a/plugin/pkg/admission/eventratelimit/admission.go b/plugin/pkg/admission/eventratelimit/admission.go index 4318d66c688..d3fa062e220 100644 --- a/plugin/pkg/admission/eventratelimit/admission.go +++ b/plugin/pkg/admission/eventratelimit/admission.go @@ -45,8 +45,8 @@ func Register(plugins *admission.Plugins) { }) } -// eventRateLimitAdmission implements an admission controller that can enforce event rate limits -type eventRateLimitAdmission struct { +// Plugin implements an admission controller that can enforce event rate limits +type Plugin struct { *admission.Handler // limitEnforcers is the collection of limit enforcers. There is one limit enforcer for each // active limit type. As there are 4 limit types, the length of the array will be at most 4. @@ -55,7 +55,7 @@ type eventRateLimitAdmission struct { } // newEventRateLimit configures an admission controller that can enforce event rate limits -func newEventRateLimit(config *eventratelimitapi.Configuration, clock flowcontrol.Clock) (admission.Interface, error) { +func newEventRateLimit(config *eventratelimitapi.Configuration, clock flowcontrol.Clock) (*Plugin, error) { limitEnforcers := make([]*limitEnforcer, 0, len(config.Limits)) for _, limitConfig := range config.Limits { enforcer, err := newLimitEnforcer(limitConfig, clock) @@ -65,7 +65,7 @@ func newEventRateLimit(config *eventratelimitapi.Configuration, clock flowcontro limitEnforcers = append(limitEnforcers, enforcer) } - eventRateLimitAdmission := &eventRateLimitAdmission{ + eventRateLimitAdmission := &Plugin{ Handler: admission.NewHandler(admission.Create, admission.Update), limitEnforcers: limitEnforcers, } @@ -74,7 +74,7 @@ func newEventRateLimit(config *eventratelimitapi.Configuration, clock flowcontro } // Admit makes admission decisions while enforcing event rate limits -func (a *eventRateLimitAdmission) Admit(attr admission.Attributes) (err error) { +func (a *Plugin) Admit(attr admission.Attributes) (err error) { // ignore all operations that do not correspond to an Event kind if attr.GetKind().GroupKind() != api.Kind("Event") { return nil diff --git a/plugin/pkg/admission/exec/admission.go b/plugin/pkg/admission/exec/admission.go index f8f94b78f81..bde9e9db999 100644 --- a/plugin/pkg/admission/exec/admission.go +++ b/plugin/pkg/admission/exec/admission.go @@ -42,9 +42,9 @@ func Register(plugins *admission.Plugins) { }) } -// denyExec is an implementation of admission.Interface which says no to a pod/exec on +// DenyExec is an implementation of admission.Interface which says no to a pod/exec on // a pod using host based configurations. -type denyExec struct { +type DenyExec struct { *admission.Handler client internalclientset.Interface @@ -54,12 +54,12 @@ type denyExec struct { privileged bool } -var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&denyExec{}) +var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&DenyExec{}) // NewDenyEscalatingExec creates a new admission controller that denies an exec operation on a pod // using host based configurations. -func NewDenyEscalatingExec() admission.Interface { - return &denyExec{ +func NewDenyEscalatingExec() *DenyExec { + return &DenyExec{ Handler: admission.NewHandler(admission.Connect), hostIPC: true, hostPID: true, @@ -70,8 +70,8 @@ func NewDenyEscalatingExec() admission.Interface { // NewDenyExecOnPrivileged creates a new admission controller that is only checking the privileged // option. This is for legacy support of the DenyExecOnPrivileged admission controller. Most // of the time NewDenyEscalatingExec should be preferred. -func NewDenyExecOnPrivileged() admission.Interface { - return &denyExec{ +func NewDenyExecOnPrivileged() *DenyExec { + return &DenyExec{ Handler: admission.NewHandler(admission.Connect), hostIPC: false, hostPID: false, @@ -79,7 +79,8 @@ func NewDenyExecOnPrivileged() admission.Interface { } } -func (d *denyExec) Admit(a admission.Attributes) (err error) { +// Admit makes an admission decision based on the request attributes +func (d *DenyExec) Admit(a admission.Attributes) (err error) { connectRequest, ok := a.GetObject().(*rest.ConnectRequest) if !ok { return errors.NewBadRequest("a connect request was received, but could not convert the request object.") @@ -129,11 +130,13 @@ func isPrivileged(pod *api.Pod) bool { return false } -func (d *denyExec) SetInternalKubeClientSet(client internalclientset.Interface) { +// SetInternalKubeClientSet implements the WantsInternalKubeClientSet interface. +func (d *DenyExec) SetInternalKubeClientSet(client internalclientset.Interface) { d.client = client } -func (d *denyExec) Validate() error { +// Validate implements the Validator interface. +func (d *DenyExec) Validate() error { if d.client == nil { return fmt.Errorf("missing client") } diff --git a/plugin/pkg/admission/exec/admission_test.go b/plugin/pkg/admission/exec/admission_test.go index 0508331e5e2..f48ebcc7ae1 100644 --- a/plugin/pkg/admission/exec/admission_test.go +++ b/plugin/pkg/admission/exec/admission_test.go @@ -30,8 +30,8 @@ import ( // newAllowEscalatingExec returns `admission.Interface` that allows execution on // "hostIPC", "hostPID" and "privileged". -func newAllowEscalatingExec() admission.Interface { - return &denyExec{ +func newAllowEscalatingExec() *DenyExec { + return &DenyExec{ Handler: admission.NewHandler(admission.Connect), hostIPC: false, hostPID: false, @@ -77,21 +77,21 @@ func TestAdmission(t *testing.T) { } // Get the direct object though to allow testAdmission to inject the client - handler := NewDenyEscalatingExec().(*denyExec) + handler := NewDenyEscalatingExec() for _, tc := range testCases { testAdmission(t, tc.pod, handler, tc.shouldAccept) } // run with a permissive config and all cases should pass - handler = newAllowEscalatingExec().(*denyExec) + handler = newAllowEscalatingExec() for _, tc := range testCases { testAdmission(t, tc.pod, handler, true) } // run against an init container - handler = NewDenyEscalatingExec().(*denyExec) + handler = NewDenyEscalatingExec() for _, tc := range testCases { tc.pod.Spec.InitContainers = tc.pod.Spec.Containers @@ -100,14 +100,14 @@ func TestAdmission(t *testing.T) { } // run with a permissive config and all cases should pass - handler = newAllowEscalatingExec().(*denyExec) + handler = newAllowEscalatingExec() for _, tc := range testCases { testAdmission(t, tc.pod, handler, true) } } -func testAdmission(t *testing.T, pod *api.Pod, handler *denyExec, shouldAccept bool) { +func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept bool) { mockClient := &fake.Clientset{} mockClient.AddReactor("get", "pods", func(action core.Action) (bool, runtime.Object, error) { if action.(core.GetAction).GetName() == pod.Name { @@ -184,7 +184,7 @@ func TestDenyExecOnPrivileged(t *testing.T) { } // Get the direct object though to allow testAdmission to inject the client - handler := NewDenyExecOnPrivileged().(*denyExec) + handler := NewDenyExecOnPrivileged() for _, tc := range testCases { testAdmission(t, tc.pod, handler, tc.shouldAccept) diff --git a/plugin/pkg/admission/imagepolicy/admission.go b/plugin/pkg/admission/imagepolicy/admission.go index 97215ba02c4..9da95a2c365 100644 --- a/plugin/pkg/admission/imagepolicy/admission.go +++ b/plugin/pkg/admission/imagepolicy/admission.go @@ -58,8 +58,8 @@ func Register(plugins *admission.Plugins) { }) } -// imagePolicyWebhook is an implementation of admission.Interface. -type imagePolicyWebhook struct { +// Plugin is an implementation of admission.Interface. +type Plugin struct { *admission.Handler webhook *webhook.GenericWebhook responseCache *cache.LRUExpireCache @@ -69,7 +69,7 @@ type imagePolicyWebhook struct { defaultAllow bool } -func (a *imagePolicyWebhook) statusTTL(status v1alpha1.ImageReviewStatus) time.Duration { +func (a *Plugin) statusTTL(status v1alpha1.ImageReviewStatus) time.Duration { if status.Allowed { return a.allowTTL } @@ -77,7 +77,7 @@ func (a *imagePolicyWebhook) statusTTL(status v1alpha1.ImageReviewStatus) time.D } // Filter out annotations that don't match *.image-policy.k8s.io/* -func (a *imagePolicyWebhook) filterAnnotations(allAnnotations map[string]string) map[string]string { +func (a *Plugin) filterAnnotations(allAnnotations map[string]string) map[string]string { annotations := make(map[string]string) for k, v := range allAnnotations { if strings.Contains(k, ".image-policy.k8s.io/") { @@ -88,7 +88,7 @@ func (a *imagePolicyWebhook) filterAnnotations(allAnnotations map[string]string) } // Function to call on webhook failure; behavior determined by defaultAllow flag -func (a *imagePolicyWebhook) webhookError(pod *api.Pod, attributes admission.Attributes, err error) error { +func (a *Plugin) webhookError(pod *api.Pod, attributes admission.Attributes, err error) error { if err != nil { glog.V(2).Infof("error contacting webhook backend: %s", err) if a.defaultAllow { @@ -107,7 +107,8 @@ func (a *imagePolicyWebhook) webhookError(pod *api.Pod, attributes admission.Att return nil } -func (a *imagePolicyWebhook) Admit(attributes admission.Attributes) (err error) { +// Admit makes an admission decision based on the request attributes +func (a *Plugin) Admit(attributes admission.Attributes) (err error) { // Ignore all calls to subresources or resources other than pods. if attributes.GetSubresource() != "" || attributes.GetResource().GroupResource() != api.Resource("pods") { return nil @@ -141,7 +142,7 @@ func (a *imagePolicyWebhook) Admit(attributes admission.Attributes) (err error) return nil } -func (a *imagePolicyWebhook) admitPod(pod *api.Pod, attributes admission.Attributes, review *v1alpha1.ImageReview) error { +func (a *Plugin) admitPod(pod *api.Pod, attributes admission.Attributes, review *v1alpha1.ImageReview) error { cacheKey, err := json.Marshal(review.Spec) if err != nil { return err @@ -178,7 +179,7 @@ func (a *imagePolicyWebhook) admitPod(pod *api.Pod, attributes admission.Attribu return nil } -// NewImagePolicyWebhook a new imagePolicyWebhook from the provided config file. +// NewImagePolicyWebhook a new ImagePolicyWebhook plugin from the provided config file. // The config file is specified by --admission-control-config-file and has the // following format for a webhook: // @@ -215,7 +216,7 @@ func (a *imagePolicyWebhook) admitPod(pod *api.Pod, attributes admission.Attribu // // For additional HTTP configuration, refer to the kubeconfig documentation // http://kubernetes.io/v1.1/docs/user-guide/kubeconfig-file.html. -func NewImagePolicyWebhook(configFile io.Reader) (admission.Interface, error) { +func NewImagePolicyWebhook(configFile io.Reader) (*Plugin, error) { // TODO: move this to a versioned configuration file format var config AdmissionConfig d := yaml.NewYAMLOrJSONDecoder(configFile, 4096) @@ -233,7 +234,7 @@ func NewImagePolicyWebhook(configFile io.Reader) (admission.Interface, error) { if err != nil { return nil, err } - return &imagePolicyWebhook{ + return &Plugin{ Handler: admission.NewHandler(admission.Create, admission.Update), webhook: gw, responseCache: cache.NewLRUExpireCache(1024), diff --git a/plugin/pkg/admission/imagepolicy/admission_test.go b/plugin/pkg/admission/imagepolicy/admission_test.go index e700cdaa616..bd5a183cee5 100644 --- a/plugin/pkg/admission/imagepolicy/admission_test.go +++ b/plugin/pkg/admission/imagepolicy/admission_test.go @@ -346,7 +346,7 @@ func (m *mockService) HTTPStatusCode() int { return m.statusCode } // newImagePolicyWebhook creates a temporary kubeconfig file from the provided arguments and attempts to load // a new newImagePolicyWebhook from it. -func newImagePolicyWebhook(callbackURL string, clientCert, clientKey, ca []byte, cacheTime time.Duration, defaultAllow bool) (*imagePolicyWebhook, error) { +func newImagePolicyWebhook(callbackURL string, clientCert, clientKey, ca []byte, cacheTime time.Duration, defaultAllow bool) (*Plugin, error) { tempfile, err := ioutil.TempFile("", "") if err != nil { return nil, err @@ -407,7 +407,7 @@ func newImagePolicyWebhook(callbackURL string, clientCert, clientKey, ca []byte, if err != nil { return nil, err } - return wh.(*imagePolicyWebhook), err + return wh, err } func TestTLSConfig(t *testing.T) { @@ -513,7 +513,7 @@ type webhookCacheTestCase struct { expectedCached bool } -func testWebhookCacheCases(t *testing.T, serv *mockService, wh *imagePolicyWebhook, attr admission.Attributes, tests []webhookCacheTestCase) { +func testWebhookCacheCases(t *testing.T, serv *mockService, wh *Plugin, attr admission.Attributes, tests []webhookCacheTestCase) { for _, test := range tests { serv.statusCode = test.statusCode err := wh.Admit(attr) diff --git a/plugin/pkg/admission/initialresources/admission.go b/plugin/pkg/admission/initialresources/admission.go index 99af24fad13..f1e69d0677c 100644 --- a/plugin/pkg/admission/initialresources/admission.go +++ b/plugin/pkg/admission/initialresources/admission.go @@ -57,15 +57,15 @@ func Register(plugins *admission.Plugins) { }) } -type initialResources struct { +type InitialResources struct { *admission.Handler source dataSource percentile int64 nsOnly bool } -func newInitialResources(source dataSource, percentile int64, nsOnly bool) admission.Interface { - return &initialResources{ +func newInitialResources(source dataSource, percentile int64, nsOnly bool) *InitialResources { + return &InitialResources{ Handler: admission.NewHandler(admission.Create), source: source, percentile: percentile, @@ -73,7 +73,8 @@ func newInitialResources(source dataSource, percentile int64, nsOnly bool) admis } } -func (ir initialResources) Admit(a admission.Attributes) (err error) { +// Admit makes an admission decision based on the request attributes +func (ir InitialResources) Admit(a admission.Attributes) (err error) { // Ignore all calls to subresources or resources other than pods. if a.GetSubresource() != "" || a.GetResource().GroupResource() != api.Resource("pods") { return nil @@ -89,7 +90,7 @@ func (ir initialResources) Admit(a admission.Attributes) (err error) { // The method veryfies whether resources should be set for the given pod and // if there is estimation available the method fills Request field. -func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) { +func (ir InitialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) { var annotations []string for i := range pod.Spec.InitContainers { annotations = append(annotations, ir.estimateContainer(pod, &pod.Spec.InitContainers[i], "init container")...) @@ -106,7 +107,7 @@ func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) { } } -func (ir initialResources) estimateContainer(pod *api.Pod, c *api.Container, message string) []string { +func (ir InitialResources) estimateContainer(pod *api.Pod, c *api.Container, message string) []string { var annotations []string req := c.Resources.Requests cpu := ir.getEstimationIfNeeded(api.ResourceCPU, c, pod.ObjectMeta.Namespace) @@ -137,7 +138,7 @@ func (ir initialResources) estimateContainer(pod *api.Pod, c *api.Container, mes // getEstimationIfNeeded estimates compute resource for container if its corresponding // Request(min amount) and Limit(max amount) both are not specified. -func (ir initialResources) getEstimationIfNeeded(kind api.ResourceName, c *api.Container, ns string) *resource.Quantity { +func (ir InitialResources) getEstimationIfNeeded(kind api.ResourceName, c *api.Container, ns string) *resource.Quantity { requests := c.Resources.Requests limits := c.Resources.Limits var quantity *resource.Quantity @@ -152,7 +153,7 @@ func (ir initialResources) getEstimationIfNeeded(kind api.ResourceName, c *api.C } return quantity } -func (ir initialResources) getEstimation(kind api.ResourceName, c *api.Container, ns string) (*resource.Quantity, error) { +func (ir InitialResources) getEstimation(kind api.ResourceName, c *api.Container, ns string) (*resource.Quantity, error) { end := time.Now() start := end.Add(-week) var usage, samples int64 diff --git a/plugin/pkg/admission/limitranger/admission.go b/plugin/pkg/admission/limitranger/admission.go index 46486c37db7..356a53de289 100644 --- a/plugin/pkg/admission/limitranger/admission.go +++ b/plugin/pkg/admission/limitranger/admission.go @@ -50,8 +50,8 @@ func Register(plugins *admission.Plugins) { }) } -// limitRanger enforces usage limits on a per resource basis in the namespace -type limitRanger struct { +// LimitRanger enforces usage limits on a per resource basis in the namespace +type LimitRanger struct { *admission.Handler client internalclientset.Interface actions LimitRangerActions @@ -69,13 +69,13 @@ type liveLookupEntry struct { items []*api.LimitRange } -func (l *limitRanger) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { +func (l *LimitRanger) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { limitRangeInformer := f.Core().InternalVersion().LimitRanges() l.SetReadyFunc(limitRangeInformer.Informer().HasSynced) l.lister = limitRangeInformer.Lister() } -func (l *limitRanger) Validate() error { +func (l *LimitRanger) Validate() error { if l.lister == nil { return fmt.Errorf("missing limitRange lister") } @@ -86,7 +86,7 @@ func (l *limitRanger) Validate() 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) (err error) { if !l.actions.SupportsAttributes(a) { return nil } @@ -150,7 +150,7 @@ func (l *limitRanger) Admit(a admission.Attributes) (err error) { } // NewLimitRanger returns an object that enforces limits based on the supplied limit function -func NewLimitRanger(actions LimitRangerActions) (admission.Interface, error) { +func NewLimitRanger(actions LimitRangerActions) (*LimitRanger, error) { liveLookupCache, err := lru.New(10000) if err != nil { return nil, err @@ -160,7 +160,7 @@ func NewLimitRanger(actions LimitRangerActions) (admission.Interface, error) { actions = &DefaultLimitRangerActions{} } - return &limitRanger{ + return &LimitRanger{ Handler: admission.NewHandler(admission.Create, admission.Update), actions: actions, liveLookupCache: liveLookupCache, @@ -168,10 +168,10 @@ func NewLimitRanger(actions LimitRangerActions) (admission.Interface, error) { }, nil } -var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&limitRanger{}) -var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&limitRanger{}) +var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&LimitRanger{}) +var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&LimitRanger{}) -func (a *limitRanger) SetInternalKubeClientSet(client internalclientset.Interface) { +func (a *LimitRanger) SetInternalKubeClientSet(client internalclientset.Interface) { a.client = client } diff --git a/plugin/pkg/admission/limitranger/admission_test.go b/plugin/pkg/admission/limitranger/admission_test.go index f04051ecc3d..dcd4c0db548 100644 --- a/plugin/pkg/admission/limitranger/admission_test.go +++ b/plugin/pkg/admission/limitranger/admission_test.go @@ -738,7 +738,7 @@ func newMockClientForTest(limitRanges []api.LimitRange) *fake.Clientset { } // newHandlerForTest returns a handler configured for testing. -func newHandlerForTest(c clientset.Interface) (admission.Interface, informers.SharedInformerFactory, error) { +func newHandlerForTest(c clientset.Interface) (*LimitRanger, informers.SharedInformerFactory, error) { f := informers.NewSharedInformerFactory(c, 5*time.Minute) handler, err := NewLimitRanger(&DefaultLimitRangerActions{}) if err != nil { diff --git a/plugin/pkg/admission/namespace/autoprovision/admission.go b/plugin/pkg/admission/namespace/autoprovision/admission.go index f7f2b343aa4..7ee90198344 100644 --- a/plugin/pkg/admission/namespace/autoprovision/admission.go +++ b/plugin/pkg/admission/namespace/autoprovision/admission.go @@ -37,19 +37,20 @@ func Register(plugins *admission.Plugins) { }) } -// provision is an implementation of admission.Interface. +// Provision is an implementation of admission.Interface. // It looks at all incoming requests in a namespace context, and if the namespace does not exist, it creates one. // It is useful in deployments that do not want to restrict creation of a namespace prior to its usage. -type provision struct { +type Provision struct { *admission.Handler client internalclientset.Interface namespaceLister corelisters.NamespaceLister } -var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&provision{}) -var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&provision{}) +var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&Provision{}) +var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&Provision{}) -func (p *provision) Admit(a admission.Attributes) error { +// Admit makes an admission decision based on the request attributes +func (p *Provision) Admit(a admission.Attributes) 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. @@ -87,23 +88,26 @@ func (p *provision) Admit(a admission.Attributes) error { } // NewProvision creates a new namespace provision admission control handler -func NewProvision() admission.Interface { - return &provision{ +func NewProvision() *Provision { + return &Provision{ Handler: admission.NewHandler(admission.Create), } } -func (p *provision) SetInternalKubeClientSet(client internalclientset.Interface) { +// SetInternalKubeClientSet implements the WantsInternalKubeClientSet interface. +func (p *Provision) SetInternalKubeClientSet(client internalclientset.Interface) { p.client = client } -func (p *provision) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { +// SetInternalKubeInformerFactory implements the WantsInternalKubeInformerFactory interface. +func (p *Provision) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { namespaceInformer := f.Core().InternalVersion().Namespaces() p.namespaceLister = namespaceInformer.Lister() p.SetReadyFunc(namespaceInformer.Informer().HasSynced) } -func (p *provision) Validate() error { +// Validate implements the Validator interface. +func (p *Provision) Validate() error { if p.namespaceLister == nil { return fmt.Errorf("missing namespaceLister") } diff --git a/plugin/pkg/admission/namespace/exists/admission.go b/plugin/pkg/admission/namespace/exists/admission.go index 8bf1e6eccc5..bed404a83e4 100644 --- a/plugin/pkg/admission/namespace/exists/admission.go +++ b/plugin/pkg/admission/namespace/exists/admission.go @@ -37,19 +37,20 @@ func Register(plugins *admission.Plugins) { }) } -// exists is an implementation of admission.Interface. +// Exists is an implementation of admission.Interface. // It rejects all incoming requests in a namespace context if the namespace does not exist. // It is useful in deployments that want to enforce pre-declaration of a Namespace resource. -type exists struct { +type Exists struct { *admission.Handler client internalclientset.Interface namespaceLister corelisters.NamespaceLister } -var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&exists{}) -var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&exists{}) +var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&Exists{}) +var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&Exists{}) -func (e *exists) Admit(a admission.Attributes) error { +// Admit makes an admission decision based on the request attributes +func (e *Exists) Admit(a admission.Attributes) 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. @@ -82,23 +83,26 @@ func (e *exists) Admit(a admission.Attributes) error { } // NewExists creates a new namespace exists admission control handler -func NewExists() admission.Interface { - return &exists{ +func NewExists() *Exists { + return &Exists{ Handler: admission.NewHandler(admission.Create, admission.Update, admission.Delete), } } -func (e *exists) SetInternalKubeClientSet(client internalclientset.Interface) { +// SetInternalKubeClientSet implements the WantsInternalKubeClientSet interface. +func (e *Exists) SetInternalKubeClientSet(client internalclientset.Interface) { e.client = client } -func (e *exists) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { +// SetInternalKubeInformerFactory implements the WantsInternalKubeInformerFactory interface. +func (e *Exists) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { namespaceInformer := f.Core().InternalVersion().Namespaces() e.namespaceLister = namespaceInformer.Lister() e.SetReadyFunc(namespaceInformer.Informer().HasSynced) } -func (e *exists) Validate() error { +// Validate implements the Validator interface. +func (e *Exists) Validate() error { if e.namespaceLister == nil { return fmt.Errorf("missing namespaceLister") } diff --git a/plugin/pkg/admission/priority/admission.go b/plugin/pkg/admission/priority/admission.go index 517058e2404..c4487232ec7 100644 --- a/plugin/pkg/admission/priority/admission.go +++ b/plugin/pkg/admission/priority/admission.go @@ -55,8 +55,8 @@ func Register(plugins *admission.Plugins) { }) } -// priorityPlugin is an implementation of admission.Interface. -type priorityPlugin struct { +// PriorityPlugin is an implementation of admission.Interface. +type PriorityPlugin struct { *admission.Handler client internalclientset.Interface lister schedulinglisters.PriorityClassLister @@ -64,17 +64,18 @@ type priorityPlugin struct { globalDefaultPriority *int32 } -var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&priorityPlugin{}) -var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&priorityPlugin{}) +var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&PriorityPlugin{}) +var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&PriorityPlugin{}) // NewPlugin creates a new priority admission plugin. -func NewPlugin() admission.Interface { - return &priorityPlugin{ +func NewPlugin() *PriorityPlugin { + return &PriorityPlugin{ Handler: admission.NewHandler(admission.Create, admission.Update, admission.Delete), } } -func (p *priorityPlugin) Validate() error { +// Validate implements the Validator interface. +func (p *PriorityPlugin) Validate() error { if p.client == nil { return fmt.Errorf("%s requires a client", pluginName) } @@ -84,11 +85,13 @@ func (p *priorityPlugin) Validate() error { return nil } -func (p *priorityPlugin) SetInternalKubeClientSet(client internalclientset.Interface) { +// SetInternalKubeClientSet implements the WantsInternalKubeClientSet interface. +func (p *PriorityPlugin) SetInternalKubeClientSet(client internalclientset.Interface) { p.client = client } -func (p *priorityPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { +// SetInternalKubeInformerFactory implements the WantsInternalKubeInformerFactory interface. +func (p *PriorityPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { priorityInformer := f.Scheduling().InternalVersion().PriorityClasses() p.lister = priorityInformer.Lister() p.SetReadyFunc(priorityInformer.Informer().HasSynced) @@ -100,7 +103,7 @@ var ( ) // Admit checks Pods and PriorityClasses and admits or rejects them. It also resolves the priority of pods based on their PriorityClass. -func (p *priorityPlugin) Admit(a admission.Attributes) error { +func (p *PriorityPlugin) Admit(a admission.Attributes) error { operation := a.GetOperation() // Ignore all calls to subresources or resources other than pods. // Ignore all operations other than Create and Update. @@ -132,7 +135,7 @@ func (p *priorityPlugin) Admit(a admission.Attributes) error { // admitPod makes sure a new pod does not set spec.Priority field. It also makes sure that the PriorityClassName exists if it is provided and resolves the pod priority from the PriorityClassName. // Note that pod validation mechanism prevents update of a pod priority. -func (p *priorityPlugin) admitPod(a admission.Attributes) error { +func (p *PriorityPlugin) admitPod(a admission.Attributes) error { operation := a.GetOperation() pod, ok := a.GetObject().(*api.Pod) if !ok { @@ -174,7 +177,7 @@ func (p *priorityPlugin) admitPod(a admission.Attributes) error { } // admitPriorityClass ensures that the value field is not larger than the highest user definable priority. If the GlobalDefault is set, it ensures that there is no other PriorityClass whose GlobalDefault is set. -func (p *priorityPlugin) admitPriorityClass(a admission.Attributes) error { +func (p *PriorityPlugin) admitPriorityClass(a admission.Attributes) error { operation := a.GetOperation() pc, ok := a.GetObject().(*scheduling.PriorityClass) if !ok { @@ -204,7 +207,7 @@ func (p *priorityPlugin) admitPriorityClass(a admission.Attributes) error { return nil } -func (p *priorityPlugin) getDefaultPriorityClass() (*scheduling.PriorityClass, error) { +func (p *PriorityPlugin) getDefaultPriorityClass() (*scheduling.PriorityClass, error) { list, err := p.lister.List(labels.Everything()) if err != nil { return nil, err @@ -217,7 +220,7 @@ func (p *priorityPlugin) getDefaultPriorityClass() (*scheduling.PriorityClass, e return nil, nil } -func (p *priorityPlugin) getDefaultPriority() (int32, error) { +func (p *PriorityPlugin) getDefaultPriority() (int32, error) { // If global default priority is cached, return it. if p.globalDefaultPriority != nil { return *p.globalDefaultPriority, nil @@ -236,6 +239,6 @@ func (p *priorityPlugin) getDefaultPriority() (int32, error) { } // invalidateCachedDefaultPriority sets global default priority to nil to indicate that it should be looked up again. -func (p *priorityPlugin) invalidateCachedDefaultPriority() { +func (p *PriorityPlugin) invalidateCachedDefaultPriority() { p.globalDefaultPriority = nil } diff --git a/plugin/pkg/admission/priority/admission_test.go b/plugin/pkg/admission/priority/admission_test.go index b1f48ca54e6..77b2a04da37 100644 --- a/plugin/pkg/admission/priority/admission_test.go +++ b/plugin/pkg/admission/priority/admission_test.go @@ -32,7 +32,7 @@ import ( "k8s.io/kubernetes/pkg/features" ) -func addPriorityClasses(ctrl *priorityPlugin, priorityClasses []*scheduling.PriorityClass) { +func addPriorityClasses(ctrl *PriorityPlugin, priorityClasses []*scheduling.PriorityClass) { informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc()) ctrl.SetInternalKubeInformerFactory(informerFactory) // First add the existing classes to the cache. @@ -132,7 +132,7 @@ func TestPriorityClassAdmission(t *testing.T) { for _, test := range tests { glog.V(4).Infof("starting test %q", test.name) - ctrl := NewPlugin().(*priorityPlugin) + ctrl := NewPlugin() // Add existing priority classes. addPriorityClasses(ctrl, test.existingClasses) // Now add the new class. @@ -209,7 +209,7 @@ func TestDefaultPriority(t *testing.T) { for _, test := range tests { glog.V(4).Infof("starting test %q", test.name) - ctrl := NewPlugin().(*priorityPlugin) + ctrl := NewPlugin() addPriorityClasses(ctrl, test.classesBefore) defaultPriority, err := ctrl.getDefaultPriority() if err != nil { @@ -383,7 +383,7 @@ func TestPodAdmission(t *testing.T) { for _, test := range tests { glog.V(4).Infof("starting test %q", test.name) - ctrl := NewPlugin().(*priorityPlugin) + ctrl := NewPlugin() // Add existing priority classes. addPriorityClasses(ctrl, test.existingClasses) diff --git a/plugin/pkg/admission/resourcequota/admission.go b/plugin/pkg/admission/resourcequota/admission.go index a6885a22949..26ddb02d1a5 100644 --- a/plugin/pkg/admission/resourcequota/admission.go +++ b/plugin/pkg/admission/resourcequota/admission.go @@ -50,8 +50,8 @@ func Register(plugins *admission.Plugins) { }) } -// quotaAdmission implements an admission controller that can enforce quota constraints -type quotaAdmission struct { +// QuotaAdmission implements an admission controller that can enforce quota constraints +type QuotaAdmission struct { *admission.Handler config *resourcequotaapi.Configuration stopCh <-chan struct{} @@ -61,8 +61,8 @@ type quotaAdmission struct { evaluator Evaluator } -var _ = kubeapiserveradmission.WantsInternalKubeClientSet("aAdmission{}) -var _ = kubeapiserveradmission.WantsQuotaConfiguration("aAdmission{}) +var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&QuotaAdmission{}) +var _ = kubeapiserveradmission.WantsQuotaConfiguration(&QuotaAdmission{}) type liveLookupEntry struct { expiry time.Time @@ -72,13 +72,13 @@ type liveLookupEntry struct { // NewResourceQuota configures an admission controller that can enforce quota constraints // using the provided registry. The registry must have the capability to handle group/kinds that // are persisted by the server this admission controller is intercepting -func NewResourceQuota(config *resourcequotaapi.Configuration, numEvaluators int, stopCh <-chan struct{}) (admission.Interface, error) { +func NewResourceQuota(config *resourcequotaapi.Configuration, numEvaluators int, stopCh <-chan struct{}) (*QuotaAdmission, error) { quotaAccessor, err := newQuotaAccessor() if err != nil { return nil, err } - return "aAdmission{ + return &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), stopCh: stopCh, numEvaluators: numEvaluators, @@ -87,21 +87,21 @@ func NewResourceQuota(config *resourcequotaapi.Configuration, numEvaluators int, }, nil } -func (a *quotaAdmission) SetInternalKubeClientSet(client internalclientset.Interface) { +func (a *QuotaAdmission) SetInternalKubeClientSet(client internalclientset.Interface) { a.quotaAccessor.client = client } -func (a *quotaAdmission) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { +func (a *QuotaAdmission) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { a.quotaAccessor.lister = f.Core().InternalVersion().ResourceQuotas().Lister() } -func (a *quotaAdmission) SetQuotaConfiguration(c quota.Configuration) { +func (a *QuotaAdmission) SetQuotaConfiguration(c quota.Configuration) { a.quotaConfiguration = c a.evaluator = NewQuotaEvaluator(a.quotaAccessor, a.quotaConfiguration, nil, a.config, a.numEvaluators, a.stopCh) } // Validate ensures an authorizer is set. -func (a *quotaAdmission) Validate() error { +func (a *QuotaAdmission) Validate() error { if a.quotaAccessor == nil { return fmt.Errorf("missing quotaAccessor") } @@ -121,7 +121,7 @@ func (a *quotaAdmission) Validate() error { } // Admit makes admission decisions while enforcing quota -func (a *quotaAdmission) Admit(attr admission.Attributes) (err error) { +func (a *QuotaAdmission) Admit(attr admission.Attributes) (err error) { // ignore all operations that correspond to sub-resource actions if attr.GetSubresource() != "" { return nil diff --git a/plugin/pkg/admission/resourcequota/admission_test.go b/plugin/pkg/admission/resourcequota/admission_test.go index 671cda4cf45..bcf7573ea4d 100644 --- a/plugin/pkg/admission/resourcequota/admission_test.go +++ b/plugin/pkg/admission/resourcequota/admission_test.go @@ -135,7 +135,7 @@ func TestAdmissionIgnoresDelete(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -171,7 +171,7 @@ func TestAdmissionIgnoresSubresources(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -216,7 +216,7 @@ func TestAdmitBelowQuotaLimit(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -300,7 +300,7 @@ func TestAdmitHandlesOldObjects(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -407,7 +407,7 @@ func TestAdmitHandlesNegativePVCUpdates(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -474,7 +474,7 @@ func TestAdmitHandlesPVCUpdates(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -573,7 +573,7 @@ func TestAdmitHandlesCreatingUpdates(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -668,7 +668,7 @@ func TestAdmitExceedQuotaLimit(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -713,7 +713,7 @@ func TestAdmitEnforceQuotaConstraints(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -768,7 +768,7 @@ func TestAdmitPodInNamespaceWithoutQuota(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -835,7 +835,7 @@ func TestAdmitBelowTerminatingQuotaLimit(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -941,7 +941,7 @@ func TestAdmitBelowBestEffortQuotaLimit(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -1034,7 +1034,7 @@ func TestAdmitBestEffortQuotaLimitIgnoresBurstable(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -1120,7 +1120,7 @@ func TestAdmissionSetsMissingNamespace(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -1166,7 +1166,7 @@ func TestAdmitRejectsNegativeUsage(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -1213,7 +1213,7 @@ func TestAdmitWhenUnrelatedResourceExceedsQuota(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -1250,7 +1250,7 @@ func TestAdmitLimitedResourceNoQuota(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -1284,7 +1284,7 @@ func TestAdmitLimitedResourceNoQuotaIgnoresNonMatchingResources(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -1331,7 +1331,7 @@ func TestAdmitLimitedResourceWithQuota(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -1390,7 +1390,7 @@ func TestAdmitLimitedResourceWithMultipleQuota(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } @@ -1439,7 +1439,7 @@ func TestAdmitLimitedResourceWithQuotaThatDoesNotCover(t *testing.T) { quotaConfiguration := install.NewQuotaConfigurationForAdmission() evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh) - handler := "aAdmission{ + handler := &QuotaAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), evaluator: evaluator, } diff --git a/plugin/pkg/admission/securitycontext/scdeny/admission.go b/plugin/pkg/admission/securitycontext/scdeny/admission.go index 24e2ede3a6a..92e265e9fd4 100644 --- a/plugin/pkg/admission/securitycontext/scdeny/admission.go +++ b/plugin/pkg/admission/securitycontext/scdeny/admission.go @@ -32,19 +32,20 @@ func Register(plugins *admission.Plugins) { }) } -type plugin struct { +// Plugin implements admission.Interface. +type Plugin struct { *admission.Handler } // NewSecurityContextDeny creates a new instance of the SecurityContextDeny admission controller -func NewSecurityContextDeny() admission.Interface { - return &plugin{ +func NewSecurityContextDeny() *Plugin { + return &Plugin{ Handler: admission.NewHandler(admission.Create, admission.Update), } } // Admit will deny any pod that defines SELinuxOptions or RunAsUser. -func (p *plugin) Admit(a admission.Attributes) (err error) { +func (p *Plugin) Admit(a admission.Attributes) (err error) { if a.GetSubresource() != "" || a.GetResource().GroupResource() != api.Resource("pods") { return nil } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/chain.go b/staging/src/k8s.io/apiserver/pkg/admission/chain.go index 45c7f72f9cf..ba1813de15d 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/chain.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/chain.go @@ -20,7 +20,7 @@ package admission type chainAdmissionHandler []Interface // NewChainHandler creates a new chain handler from an array of handlers. Used for testing. -func NewChainHandler(handlers ...Interface) Interface { +func NewChainHandler(handlers ...Interface) chainAdmissionHandler { return chainAdmissionHandler(handlers) } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization/initialization.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization/initialization.go index e536e290dfb..5eebea997d7 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization/initialization.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization/initialization.go @@ -74,6 +74,7 @@ func NewInitializer() admission.Interface { return &initializer{} } +// Validate implements the Validator interface. func (i *initializer) Validate() error { if i.config == nil { return fmt.Errorf("the Initializer admission plugin requires a Kubernetes client to be provided") @@ -94,10 +95,12 @@ func (i *initializer) Validate() error { return nil } +// SetExternalKubeClientSet implements the WantsExternalKubeClientSet interface. func (i *initializer) SetExternalKubeClientSet(client clientset.Interface) { i.config = configuration.NewInitializerConfigurationManager(client.Admissionregistration().InitializerConfigurations()) } +// SetAuthorizer implements the WantsAuthorizer interface. func (i *initializer) SetAuthorizer(a authorizer.Authorizer) { i.authorizer = a } @@ -276,6 +279,8 @@ func (i *initializer) canInitialize(a admission.Attributes, message string) erro return nil } +// Handles returns true if this admission controller can handle the given operation +// where operation can be one of CREATE, UPDATE, DELETE, or CONNECT func (i *initializer) Handles(op admission.Operation) bool { return op == admission.Create || op == admission.Update } diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle/admission.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle/admission.go index f220237369b..e053a4907c7 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle/admission.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle/admission.go @@ -202,16 +202,19 @@ func newLifecycleWithClock(immortalNamespaces sets.String, clock utilcache.Clock }, nil } +// SetExternalKubeInformerFactory implements the WantsExternalKubeInformerFactory interface. func (l *lifecycle) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) { namespaceInformer := f.Core().V1().Namespaces() l.namespaceLister = namespaceInformer.Lister() l.SetReadyFunc(namespaceInformer.Informer().HasSynced) } +// SetExternalKubeClientSet implements the WantsExternalKubeClientSet interface. func (l *lifecycle) SetExternalKubeClientSet(client kubernetes.Interface) { l.client = client } +// Validate implement the Validator interface. func (l *lifecycle) Validate() error { if l.namespaceLister == nil { return fmt.Errorf("missing namespaceLister") diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/admission.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/admission.go index 8408e89b946..9a251f2d146 100644 --- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/admission.go +++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/admission.go @@ -151,10 +151,13 @@ func (a *GenericAdmissionWebhook) SetScheme(scheme *runtime.Scheme) { } } +// WantsExternalKubeClientSet defines a function which sets external ClientSet for admission plugins that need it func (a *GenericAdmissionWebhook) SetExternalKubeClientSet(client clientset.Interface) { a.hookSource = configuration.NewExternalAdmissionHookConfigurationManager(client.Admissionregistration().ExternalAdmissionHookConfigurations()) } +// Validator holds Validate functions, which are responsible for validation of initialized shared resources +// and should be implemented on admission plugins func (a *GenericAdmissionWebhook) Validate() error { if a.hookSource == nil { return fmt.Errorf("the GenericAdmissionWebhook admission plugin requires a Kubernetes client to be provided") diff --git a/test/integration/quota/BUILD b/test/integration/quota/BUILD index e9abba915d8..ec304e75103 100644 --- a/test/integration/quota/BUILD +++ b/test/integration/quota/BUILD @@ -21,7 +21,6 @@ go_test( "//pkg/controller:go_default_library", "//pkg/controller/replication:go_default_library", "//pkg/controller/resourcequota:go_default_library", - "//pkg/kubeapiserver/admission:go_default_library", "//pkg/quota/generic:go_default_library", "//pkg/quota/install:go_default_library", "//plugin/pkg/admission/resourcequota:go_default_library", diff --git a/test/integration/quota/quota_test.go b/test/integration/quota/quota_test.go index fa1816382ae..cd250617174 100644 --- a/test/integration/quota/quota_test.go +++ b/test/integration/quota/quota_test.go @@ -40,7 +40,6 @@ import ( "k8s.io/kubernetes/pkg/controller" replicationcontroller "k8s.io/kubernetes/pkg/controller/replication" resourcequotacontroller "k8s.io/kubernetes/pkg/controller/resourcequota" - kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" "k8s.io/kubernetes/pkg/quota/generic" quotainstall "k8s.io/kubernetes/pkg/quota/install" "k8s.io/kubernetes/plugin/pkg/admission/resourcequota" @@ -70,11 +69,11 @@ func TestQuota(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - admission.(kubeadmission.WantsInternalKubeClientSet).SetInternalKubeClientSet(internalClientset) + admission.SetInternalKubeClientSet(internalClientset) internalInformers := internalinformers.NewSharedInformerFactory(internalClientset, controller.NoResyncPeriodFunc()) - admission.(kubeadmission.WantsInternalKubeInformerFactory).SetInternalKubeInformerFactory(internalInformers) + admission.SetInternalKubeInformerFactory(internalInformers) qca := quotainstall.NewQuotaConfigurationForAdmission() - admission.(kubeadmission.WantsQuotaConfiguration).SetQuotaConfiguration(qca) + admission.SetQuotaConfiguration(qca) defer close(admissionCh) masterConfig := framework.NewIntegrationTestMasterConfig() @@ -268,10 +267,10 @@ func TestQuotaLimitedResourceDenial(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - admission.(kubeadmission.WantsInternalKubeClientSet).SetInternalKubeClientSet(internalClientset) + admission.SetInternalKubeClientSet(internalClientset) internalInformers := internalinformers.NewSharedInformerFactory(internalClientset, controller.NoResyncPeriodFunc()) - admission.(kubeadmission.WantsInternalKubeInformerFactory).SetInternalKubeInformerFactory(internalInformers) - admission.(kubeadmission.WantsQuotaConfiguration).SetQuotaConfiguration(qca) + admission.SetInternalKubeInformerFactory(internalInformers) + admission.SetQuotaConfiguration(qca) defer close(admissionCh) masterConfig := framework.NewIntegrationTestMasterConfig()