Merge pull request #54485 from sttts/sttts-unify-admission-constructors

Automatic merge from submit-queue (batch tested with PRs 54761, 54748, 53991, 54485, 46951). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

admission: unify plugin constructors

It's common in Go to return the actual object in constructors, not **one interface**
it implements. This allows us to implement multiple interfaces, but only have
one constructor. As having private types in constructors, we export all plugin structs, of course with private fields.

Note: super interfaces do not work if there are overlapping methods.
This commit is contained in:
Kubernetes Submit Queue 2017-10-30 15:38:33 -07:00 committed by GitHub
commit 7a944a69d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 203 additions and 169 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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(&quotaAdmission{})
var _ = kubeapiserveradmission.WantsQuotaConfiguration(&quotaAdmission{})
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 &quotaAdmission{
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

View File

@ -135,7 +135,7 @@ func TestAdmissionIgnoresDelete(t *testing.T) {
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
handler := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
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 := &quotaAdmission{
handler := &QuotaAdmission{
Handler: admission.NewHandler(admission.Create, admission.Update),
evaluator: evaluator,
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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