pkg/admission: make plugin registry non-global

This commit is contained in:
Dr. Stefan Schimanski 2017-03-27 13:26:03 +02:00
parent 750d5c3bc5
commit 63f547e1b1
41 changed files with 124 additions and 59 deletions

View File

@ -19,6 +19,7 @@ go_library(
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/validation:go_default_library", "//pkg/api/validation:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//pkg/kubeapiserver/options:go_default_library", "//pkg/kubeapiserver/options:go_default_library",
"//pkg/kubelet/client:go_default_library", "//pkg/kubelet/client:go_default_library",
"//pkg/master/ports:go_default_library", "//pkg/master/ports:go_default_library",

View File

@ -26,6 +26,7 @@ import (
"k8s.io/apiserver/pkg/storage/storagebackend" "k8s.io/apiserver/pkg/storage/storagebackend"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/api/validation"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options" kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
"k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/pkg/master/ports"
@ -71,7 +72,7 @@ type ServerRunOptions struct {
// NewServerRunOptions creates a new ServerRunOptions object with default parameters // NewServerRunOptions creates a new ServerRunOptions object with default parameters
func NewServerRunOptions() *ServerRunOptions { func NewServerRunOptions() *ServerRunOptions {
s := ServerRunOptions{ s := ServerRunOptions{
GenericServerRunOptions: genericoptions.NewServerRunOptions(), GenericServerRunOptions: genericoptions.NewServerRunOptions(&kubeapiserveradmission.Plugins),
Etcd: genericoptions.NewEtcdOptions(storagebackend.NewDefaultConfig(kubeoptions.DefaultEtcdPathPrefix, api.Scheme, nil)), Etcd: genericoptions.NewEtcdOptions(storagebackend.NewDefaultConfig(kubeoptions.DefaultEtcdPathPrefix, api.Scheme, nil)),
SecureServing: kubeoptions.NewSecureServingOptions(), SecureServing: kubeoptions.NewSecureServingOptions(),
InsecureServing: kubeoptions.NewInsecureServingOptions(), InsecureServing: kubeoptions.NewInsecureServingOptions(),

View File

@ -64,7 +64,7 @@ import (
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount" serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
generatedopenapi "k8s.io/kubernetes/pkg/generated/openapi" generatedopenapi "k8s.io/kubernetes/pkg/generated/openapi"
"k8s.io/kubernetes/pkg/kubeapiserver" "k8s.io/kubernetes/pkg/kubeapiserver"
kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
kubeauthenticator "k8s.io/kubernetes/pkg/kubeapiserver/authenticator" kubeauthenticator "k8s.io/kubernetes/pkg/kubeapiserver/authenticator"
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options" kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
@ -359,7 +359,12 @@ func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config,
genericConfig.DisabledPostStartHooks.Insert(rbacrest.PostStartHookName) genericConfig.DisabledPostStartHooks.Insert(rbacrest.PostStartHookName)
} }
genericConfig.AdmissionControl, err = BuildAdmission(s, client, sharedInformers, genericConfig.Authorizer) genericConfig.AdmissionControl, err = BuildAdmission(s,
s.GenericServerRunOptions.AdmissionPlugins,
client,
sharedInformers,
genericConfig.Authorizer,
)
if err != nil { if err != nil {
return nil, nil, nil, fmt.Errorf("failed to initialize admission: %v", err) return nil, nil, nil, fmt.Errorf("failed to initialize admission: %v", err)
} }
@ -368,7 +373,7 @@ func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config,
} }
// BuildAdmission constructs the admission chain // BuildAdmission constructs the admission chain
func BuildAdmission(s *options.ServerRunOptions, client internalclientset.Interface, sharedInformers informers.SharedInformerFactory, apiAuthorizer authorizer.Authorizer) (admission.Interface, error) { func BuildAdmission(s *options.ServerRunOptions, plugins *admission.Plugins, client internalclientset.Interface, sharedInformers informers.SharedInformerFactory, apiAuthorizer authorizer.Authorizer) (admission.Interface, error) {
admissionControlPluginNames := strings.Split(s.GenericServerRunOptions.AdmissionControl, ",") admissionControlPluginNames := strings.Split(s.GenericServerRunOptions.AdmissionControl, ",")
var cloudConfig []byte var cloudConfig []byte
var err error var err error
@ -379,12 +384,12 @@ func BuildAdmission(s *options.ServerRunOptions, client internalclientset.Interf
glog.Fatalf("Error reading from cloud configuration file %s: %#v", s.CloudProvider.CloudConfigFile, err) glog.Fatalf("Error reading from cloud configuration file %s: %#v", s.CloudProvider.CloudConfigFile, err)
} }
} }
pluginInitializer := kubeadmission.NewPluginInitializer(client, sharedInformers, apiAuthorizer, cloudConfig) pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, apiAuthorizer, cloudConfig)
admissionConfigProvider, err := admission.ReadAdmissionConfiguration(admissionControlPluginNames, s.GenericServerRunOptions.AdmissionControlConfigFile) admissionConfigProvider, err := admission.ReadAdmissionConfiguration(admissionControlPluginNames, s.GenericServerRunOptions.AdmissionControlConfigFile)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read plugin config: %v", err) return nil, fmt.Errorf("failed to read plugin config: %v", err)
} }
return admission.NewFromPlugins(admissionControlPluginNames, admissionConfigProvider, pluginInitializer) return plugins.NewFromPlugins(admissionControlPluginNames, admissionConfigProvider, pluginInitializer)
} }
// BuildAuthenticator constructs the authenticator // BuildAuthenticator constructs the authenticator

View File

@ -17,6 +17,7 @@ go_library(
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//pkg/kubeapiserver/options:go_default_library", "//pkg/kubeapiserver/options:go_default_library",
"//vendor:github.com/spf13/pflag", "//vendor:github.com/spf13/pflag",
"//vendor:k8s.io/apiserver/pkg/server/options", "//vendor:k8s.io/apiserver/pkg/server/options",

View File

@ -23,6 +23,7 @@ import (
genericoptions "k8s.io/apiserver/pkg/server/options" genericoptions "k8s.io/apiserver/pkg/server/options"
"k8s.io/apiserver/pkg/storage/storagebackend" "k8s.io/apiserver/pkg/storage/storagebackend"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options" kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
// add the kubernetes feature gates // add the kubernetes feature gates
@ -51,7 +52,7 @@ type ServerRunOptions struct {
// NewServerRunOptions creates a new ServerRunOptions object with default values. // NewServerRunOptions creates a new ServerRunOptions object with default values.
func NewServerRunOptions() *ServerRunOptions { func NewServerRunOptions() *ServerRunOptions {
s := ServerRunOptions{ s := ServerRunOptions{
GenericServerRunOptions: genericoptions.NewServerRunOptions(), GenericServerRunOptions: genericoptions.NewServerRunOptions(&kubeapiserveradmission.Plugins),
Etcd: genericoptions.NewEtcdOptions(storagebackend.NewDefaultConfig(kubeoptions.DefaultEtcdPathPrefix, api.Scheme, nil)), Etcd: genericoptions.NewEtcdOptions(storagebackend.NewDefaultConfig(kubeoptions.DefaultEtcdPathPrefix, api.Scheme, nil)),
SecureServing: kubeoptions.NewSecureServingOptions(), SecureServing: kubeoptions.NewSecureServingOptions(),
InsecureServing: kubeoptions.NewInsecureServingOptions(), InsecureServing: kubeoptions.NewInsecureServingOptions(),

View File

@ -199,7 +199,7 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
if err != nil { if err != nil {
return fmt.Errorf("failed to read plugin config: %v", err) return fmt.Errorf("failed to read plugin config: %v", err)
} }
admissionController, err := admission.NewFromPlugins(admissionControlPluginNames, admissionConfigProvider, pluginInitializer) admissionController, err := kubeapiserveradmission.Plugins.NewFromPlugins(admissionControlPluginNames, admissionConfigProvider, pluginInitializer)
if err != nil { if err != nil {
return fmt.Errorf("failed to initialize plugins: %v", err) return fmt.Errorf("failed to initialize plugins: %v", err)
} }

View File

@ -21,7 +21,10 @@ go_test(
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["initializer.go"], srcs = [
"initializer.go",
"registry.go",
],
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library",

View File

@ -0,0 +1,24 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package admission
import (
"k8s.io/apiserver/pkg/admission"
)
// Plugins is a global registry for admission plugins.
var Plugins = admission.Plugins{}

View File

@ -12,7 +12,10 @@ go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["admission.go"], srcs = ["admission.go"],
tags = ["automanaged"], tags = ["automanaged"],
deps = ["//vendor:k8s.io/apiserver/pkg/admission"], deps = [
"//pkg/kubeapiserver/admission:go_default_library",
"//vendor:k8s.io/apiserver/pkg/admission",
],
) )
go_test( go_test(

View File

@ -20,10 +20,11 @@ import (
"io" "io"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
) )
func init() { func init() {
admission.RegisterPlugin("AlwaysAdmit", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("AlwaysAdmit", func(config io.Reader) (admission.Interface, error) {
return NewAlwaysAdmit(), nil return NewAlwaysAdmit(), nil
}) })
} }

View File

@ -14,6 +14,7 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/api/errors", "//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apiserver/pkg/admission", "//vendor:k8s.io/apiserver/pkg/admission",
], ],

View File

@ -30,10 +30,11 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
) )
func init() { func init() {
admission.RegisterPlugin("AlwaysPullImages", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("AlwaysPullImages", func(config io.Reader) (admission.Interface, error) {
return NewAlwaysPullImages(), nil return NewAlwaysPullImages(), nil
}) })
} }

View File

@ -17,6 +17,7 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/api/errors", "//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apiserver/pkg/admission", "//vendor:k8s.io/apiserver/pkg/admission",

View File

@ -24,10 +24,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
) )
func init() { func init() {
admission.RegisterPlugin("LimitPodHardAntiAffinityTopology", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("LimitPodHardAntiAffinityTopology", func(config io.Reader) (admission.Interface, error) {
return NewInterPodAntiAffinity(), nil return NewInterPodAntiAffinity(), nil
}) })
} }

View File

@ -28,6 +28,7 @@ go_library(
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/helper:go_default_library", "//pkg/api/helper:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/api/errors", "//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apiserver/pkg/admission", "//vendor:k8s.io/apiserver/pkg/admission",

View File

@ -26,6 +26,7 @@ import (
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/helper" "k8s.io/kubernetes/pkg/api/helper"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
) )
var ( var (
@ -39,7 +40,7 @@ var (
) )
func init() { func init() {
admission.RegisterPlugin("DefaultTolerationSeconds", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("DefaultTolerationSeconds", func(config io.Reader) (admission.Interface, error) {
return NewDefaultTolerationSeconds(), nil return NewDefaultTolerationSeconds(), nil
}) })
} }

View File

@ -12,7 +12,10 @@ go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["admission.go"], srcs = ["admission.go"],
tags = ["automanaged"], tags = ["automanaged"],
deps = ["//vendor:k8s.io/apiserver/pkg/admission"], deps = [
"//pkg/kubeapiserver/admission:go_default_library",
"//vendor:k8s.io/apiserver/pkg/admission",
],
) )
go_test( go_test(

View File

@ -21,10 +21,11 @@ import (
"io" "io"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
) )
func init() { func init() {
admission.RegisterPlugin("AlwaysDeny", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("AlwaysDeny", func(config io.Reader) (admission.Interface, error) {
return NewAlwaysDeny(), nil return NewAlwaysDeny(), nil
}) })
} }

View File

@ -30,13 +30,13 @@ import (
) )
func init() { func init() {
admission.RegisterPlugin("DenyEscalatingExec", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("DenyEscalatingExec", func(config io.Reader) (admission.Interface, error) {
return NewDenyEscalatingExec(), nil return NewDenyEscalatingExec(), nil
}) })
// This is for legacy support of the DenyExecOnPrivileged admission controller. Most // This is for legacy support of the DenyExecOnPrivileged admission controller. Most
// of the time DenyEscalatingExec should be preferred. // of the time DenyEscalatingExec should be preferred.
admission.RegisterPlugin("DenyExecOnPrivileged", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("DenyExecOnPrivileged", func(config io.Reader) (admission.Interface, error) {
return NewDenyExecOnPrivileged(), nil return NewDenyExecOnPrivileged(), nil
}) })
} }

View File

@ -13,6 +13,7 @@ go_library(
srcs = ["gc_admission.go"], srcs = ["gc_admission.go"],
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/kubeapiserver/admission:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/api/equality", "//vendor:k8s.io/apimachinery/pkg/api/equality",
"//vendor:k8s.io/apimachinery/pkg/api/meta", "//vendor:k8s.io/apimachinery/pkg/api/meta",
"//vendor:k8s.io/apimachinery/pkg/runtime", "//vendor:k8s.io/apimachinery/pkg/runtime",

View File

@ -25,10 +25,11 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
) )
func init() { func init() {
admission.RegisterPlugin("OwnerReferencesPermissionEnforcement", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("OwnerReferencesPermissionEnforcement", func(config io.Reader) (admission.Interface, error) {
return &gcPermissionsEnforcement{ return &gcPermissionsEnforcement{
Handler: admission.NewHandler(admission.Create, admission.Update), Handler: admission.NewHandler(admission.Create, admission.Update),
}, nil }, nil

View File

@ -20,6 +20,7 @@ go_library(
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/apis/imagepolicy/install:go_default_library", "//pkg/apis/imagepolicy/install:go_default_library",
"//pkg/apis/imagepolicy/v1alpha1:go_default_library", "//pkg/apis/imagepolicy/v1alpha1:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//vendor:github.com/golang/glog", "//vendor:github.com/golang/glog",
"//vendor:k8s.io/apimachinery/pkg/api/errors", "//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema", "//vendor:k8s.io/apimachinery/pkg/runtime/schema",

View File

@ -39,6 +39,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1" "k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
// install the clientgo image policy API for use with api registry // install the clientgo image policy API for use with api registry
_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install" _ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
@ -49,7 +50,7 @@ var (
) )
func init() { func init() {
admission.RegisterPlugin("ImagePolicyWebhook", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("ImagePolicyWebhook", func(config io.Reader) (admission.Interface, error) {
newImagePolicyWebhook, err := NewImagePolicyWebhook(config) newImagePolicyWebhook, err := NewImagePolicyWebhook(config)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -20,6 +20,7 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//vendor:cloud.google.com/go/compute/metadata", "//vendor:cloud.google.com/go/compute/metadata",
"//vendor:github.com/golang/glog", "//vendor:github.com/golang/glog",
"//vendor:github.com/hawkular/hawkular-client-go/metrics", "//vendor:github.com/hawkular/hawkular-client-go/metrics",

View File

@ -29,6 +29,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
) )
var ( var (
@ -46,7 +47,7 @@ const (
// WARNING: this feature is experimental and will definitely change. // WARNING: this feature is experimental and will definitely change.
func init() { func init() {
admission.RegisterPlugin("InitialResources", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("InitialResources", func(config io.Reader) (admission.Interface, error) {
// TODO: remove the usage of flags in favor of reading versioned configuration // TODO: remove the usage of flags in favor of reading versioned configuration
s, err := newDataSource(*source) s, err := newDataSource(*source)
if err != nil { if err != nil {

View File

@ -44,7 +44,7 @@ const (
) )
func init() { func init() {
admission.RegisterPlugin("LimitRanger", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("LimitRanger", func(config io.Reader) (admission.Interface, error) {
return NewLimitRanger(&DefaultLimitRangerActions{}) return NewLimitRanger(&DefaultLimitRangerActions{})
}) })
} }

View File

@ -31,7 +31,7 @@ import (
) )
func init() { func init() {
admission.RegisterPlugin("NamespaceAutoProvision", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("NamespaceAutoProvision", func(config io.Reader) (admission.Interface, error) {
return NewProvision(), nil return NewProvision(), nil
}) })
} }

View File

@ -31,7 +31,7 @@ import (
) )
func init() { func init() {
admission.RegisterPlugin("NamespaceExists", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("NamespaceExists", func(config io.Reader) (admission.Interface, error) {
return NewExists(), nil return NewExists(), nil
}) })
} }

View File

@ -51,7 +51,7 @@ const (
) )
func init() { func init() {
admission.RegisterPlugin(PluginName, func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
return NewLifecycle(sets.NewString(metav1.NamespaceDefault, metav1.NamespaceSystem, metav1.NamespacePublic)) return NewLifecycle(sets.NewString(metav1.NamespaceDefault, metav1.NamespaceSystem, metav1.NamespacePublic))
}) })
} }

View File

@ -33,7 +33,7 @@ import (
) )
func init() { func init() {
admission.RegisterPlugin("PersistentVolumeLabel", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("PersistentVolumeLabel", func(config io.Reader) (admission.Interface, error) {
persistentVolumeLabelAdmission := NewPersistentVolumeLabel() persistentVolumeLabelAdmission := NewPersistentVolumeLabel()
return persistentVolumeLabelAdmission, nil return persistentVolumeLabelAdmission, nil
}) })

View File

@ -40,7 +40,7 @@ import (
var NamespaceNodeSelectors = []string{"scheduler.alpha.kubernetes.io/node-selector"} var NamespaceNodeSelectors = []string{"scheduler.alpha.kubernetes.io/node-selector"}
func init() { func init() {
admission.RegisterPlugin("PodNodeSelector", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("PodNodeSelector", func(config io.Reader) (admission.Interface, error) {
// TODO move this to a versioned configuration file format. // TODO move this to a versioned configuration file format.
pluginConfig := readConfig(config) pluginConfig := readConfig(config)
plugin := NewPodNodeSelector(pluginConfig.PodNodeSelectorPluginConfig) plugin := NewPodNodeSelector(pluginConfig.PodNodeSelectorPluginConfig)

View File

@ -41,7 +41,7 @@ const (
) )
func init() { func init() {
admission.RegisterPlugin(pluginName, func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register(pluginName, func(config io.Reader) (admission.Interface, error) {
return NewPlugin(), nil return NewPlugin(), nil
}) })
} }

View File

@ -37,7 +37,7 @@ import (
) )
func init() { func init() {
admission.RegisterPlugin("PodTolerationRestriction", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("PodTolerationRestriction", func(config io.Reader) (admission.Interface, error) {
pluginConfig, err := loadConfiguration(config) pluginConfig, err := loadConfiguration(config)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -33,7 +33,7 @@ import (
) )
func init() { func init() {
admission.RegisterPlugin("ResourceQuota", kubeapiserveradmission.Plugins.Register("ResourceQuota",
func(config io.Reader) (admission.Interface, error) { func(config io.Reader) (admission.Interface, error) {
// load the configuration provided (if any) // load the configuration provided (if any)
configuration, err := LoadConfiguration(config) configuration, err := LoadConfiguration(config)

View File

@ -45,7 +45,7 @@ const (
) )
func init() { func init() {
admission.RegisterPlugin(PluginName, func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
plugin := NewPlugin(psp.NewSimpleStrategyFactory(), getMatchingPolicies, true) plugin := NewPlugin(psp.NewSimpleStrategyFactory(), getMatchingPolicies, true)
return plugin, nil return plugin, nil
}) })

View File

@ -14,6 +14,7 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/api/errors", "//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apiserver/pkg/admission", "//vendor:k8s.io/apiserver/pkg/admission",
], ],

View File

@ -23,10 +23,11 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
) )
func init() { func init() {
admission.RegisterPlugin("SecurityContextDeny", func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register("SecurityContextDeny", func(config io.Reader) (admission.Interface, error) {
return NewSecurityContextDeny(), nil return NewSecurityContextDeny(), nil
}) })
} }

View File

@ -55,7 +55,7 @@ const DefaultAPITokenMountPath = "/var/run/secrets/kubernetes.io/serviceaccount"
const PluginName = "ServiceAccount" const PluginName = "ServiceAccount"
func init() { func init() {
admission.RegisterPlugin(PluginName, func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
serviceAccountAdmission := NewServiceAccount() serviceAccountAdmission := NewServiceAccount()
return serviceAccountAdmission, nil return serviceAccountAdmission, nil
}) })

View File

@ -39,7 +39,7 @@ const (
) )
func init() { func init() {
admission.RegisterPlugin(PluginName, func(config io.Reader) (admission.Interface, error) { kubeapiserveradmission.Plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
plugin := newPlugin() plugin := newPlugin()
return plugin, nil return plugin, nil
}) })

View File

@ -34,11 +34,13 @@ import (
// the parameter is nil. // the parameter is nil.
type Factory func(config io.Reader) (Interface, error) type Factory func(config io.Reader) (Interface, error)
type Plugins struct {
lock sync.Mutex
registry map[string]Factory
}
// All registered admission options. // All registered admission options.
var ( var (
pluginsMutex sync.Mutex
plugins = make(map[string]Factory)
// PluginEnabledFn checks whether a plugin is enabled. By default, if you ask about it, it's enabled. // PluginEnabledFn checks whether a plugin is enabled. By default, if you ask about it, it's enabled.
PluginEnabledFn = func(name string, config io.Reader) bool { PluginEnabledFn = func(name string, config io.Reader) bool {
return true return true
@ -48,39 +50,42 @@ var (
// PluginEnabledFunc is a function type that can provide an external check on whether an admission plugin may be enabled // PluginEnabledFunc is a function type that can provide an external check on whether an admission plugin may be enabled
type PluginEnabledFunc func(name string, config io.Reader) bool type PluginEnabledFunc func(name string, config io.Reader) bool
// GetPlugins enumerates the names of all registered plugins. // Registered enumerates the names of all registered plugins.
func GetPlugins() []string { func (ps *Plugins) Registered() []string {
pluginsMutex.Lock() ps.lock.Lock()
defer pluginsMutex.Unlock() defer ps.lock.Unlock()
keys := []string{} keys := []string{}
for k := range plugins { for k := range ps.registry {
keys = append(keys, k) keys = append(keys, k)
} }
sort.Strings(keys) sort.Strings(keys)
return keys return keys
} }
// RegisterPlugin registers a plugin Factory by name. This // Register registers a plugin Factory by name. This
// is expected to happen during app startup. // is expected to happen during app startup.
func RegisterPlugin(name string, plugin Factory) { func (ps *Plugins) Register(name string, plugin Factory) {
pluginsMutex.Lock() ps.lock.Lock()
defer pluginsMutex.Unlock() defer ps.lock.Unlock()
_, found := plugins[name] _, found := ps.registry[name]
if found { if found {
glog.Fatalf("Admission plugin %q was registered twice", name) glog.Fatalf("Admission plugin %q was registered twice", name)
} }
if ps.registry == nil {
ps.registry = map[string]Factory{}
}
glog.V(1).Infof("Registered admission plugin %q", name) glog.V(1).Infof("Registered admission plugin %q", name)
plugins[name] = plugin ps.registry[name] = plugin
} }
// getPlugin creates an instance of the named plugin. It returns `false` if the // getPlugin creates an instance of the named plugin. It returns `false` if the
// the name is not known. The error is returned only when the named provider was // the name is not known. The error is returned only when the named provider was
// known but failed to initialize. The config parameter specifies the io.Reader // known but failed to initialize. The config parameter specifies the io.Reader
// handler of the configuration file for the cloud provider, or nil for no configuration. // handler of the configuration file for the cloud provider, or nil for no configuration.
func getPlugin(name string, config io.Reader) (Interface, bool, error) { func (ps *Plugins) getPlugin(name string, config io.Reader) (Interface, bool, error) {
pluginsMutex.Lock() ps.lock.Lock()
defer pluginsMutex.Unlock() defer ps.lock.Unlock()
f, found := plugins[name] f, found := ps.registry[name]
if !found { if !found {
return nil, false, nil return nil, false, nil
} }
@ -113,7 +118,7 @@ func splitStream(config io.Reader) (io.Reader, io.Reader, error) {
// NewFromPlugins returns an admission.Interface that will enforce admission control decisions of all // NewFromPlugins returns an admission.Interface that will enforce admission control decisions of all
// the given plugins. // the given plugins.
func NewFromPlugins(pluginNames []string, configProvider ConfigProvider, pluginInitializer PluginInitializer) (Interface, error) { func (ps *Plugins) NewFromPlugins(pluginNames []string, configProvider ConfigProvider, pluginInitializer PluginInitializer) (Interface, error) {
plugins := []Interface{} plugins := []Interface{}
for _, pluginName := range pluginNames { for _, pluginName := range pluginNames {
pluginConfig, err := configProvider.ConfigFor(pluginName) pluginConfig, err := configProvider.ConfigFor(pluginName)
@ -121,7 +126,7 @@ func NewFromPlugins(pluginNames []string, configProvider ConfigProvider, pluginI
return nil, err return nil, err
} }
plugin, err := InitPlugin(pluginName, pluginConfig, pluginInitializer) plugin, err := ps.InitPlugin(pluginName, pluginConfig, pluginInitializer)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -133,13 +138,13 @@ func NewFromPlugins(pluginNames []string, configProvider ConfigProvider, pluginI
} }
// InitPlugin creates an instance of the named interface. // InitPlugin creates an instance of the named interface.
func InitPlugin(name string, config io.Reader, pluginInitializer PluginInitializer) (Interface, error) { func (ps *Plugins) InitPlugin(name string, config io.Reader, pluginInitializer PluginInitializer) (Interface, error) {
if name == "" { if name == "" {
glog.Info("No admission plugin specified.") glog.Info("No admission plugin specified.")
return nil, nil return nil, nil
} }
plugin, found, err := getPlugin(name, config) plugin, found, err := ps.getPlugin(name, config)
if err != nil { if err != nil {
return nil, fmt.Errorf("Couldn't init admission plugin %q: %v", name, err) return nil, fmt.Errorf("Couldn't init admission plugin %q: %v", name, err)
} }

View File

@ -46,16 +46,18 @@ type ServerRunOptions struct {
MinRequestTimeout int MinRequestTimeout int
TargetRAMMB int TargetRAMMB int
WatchCacheSizes []string WatchCacheSizes []string
AdmissionPlugins *admission.Plugins
} }
func NewServerRunOptions() *ServerRunOptions { func NewServerRunOptions(admissionPlugins *admission.Plugins) *ServerRunOptions {
defaults := server.NewConfig(serializer.CodecFactory{}) defaults := server.NewConfig(serializer.CodecFactory{})
return &ServerRunOptions{ return &ServerRunOptions{
AdmissionControl: "AlwaysAdmit", AdmissionControl: "AlwaysAdmit",
MaxRequestsInFlight: defaults.MaxRequestsInFlight, MaxRequestsInFlight: defaults.MaxRequestsInFlight,
MaxMutatingRequestsInFlight: defaults.MaxMutatingRequestsInFlight, MaxMutatingRequestsInFlight: defaults.MaxMutatingRequestsInFlight,
MinRequestTimeout: defaults.MinRequestTimeout, MinRequestTimeout: defaults.MinRequestTimeout,
AdmissionPlugins: admissionPlugins,
} }
} }
@ -96,7 +98,7 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.AdmissionControl, "admission-control", s.AdmissionControl, ""+ fs.StringVar(&s.AdmissionControl, "admission-control", s.AdmissionControl, ""+
"Ordered list of plug-ins to do admission control of resources into cluster. "+ "Ordered list of plug-ins to do admission control of resources into cluster. "+
"Comma-delimited list of: "+strings.Join(admission.GetPlugins(), ", ")+".") "Comma-delimited list of: "+strings.Join(s.AdmissionPlugins.Registered(), ", ")+".")
fs.StringVar(&s.AdmissionControlConfigFile, "admission-control-config-file", s.AdmissionControlConfigFile, fs.StringVar(&s.AdmissionControlConfigFile, "admission-control-config-file", s.AdmissionControlConfigFile,
"File with admission control configuration.") "File with admission control configuration.")