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/validation:go_default_library",
"//pkg/features:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//pkg/kubeapiserver/options:go_default_library",
"//pkg/kubelet/client:go_default_library",
"//pkg/master/ports:go_default_library",

View File

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

View File

@ -64,7 +64,7 @@ import (
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
generatedopenapi "k8s.io/kubernetes/pkg/generated/openapi"
"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"
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
@ -359,7 +359,12 @@ func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config,
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 {
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
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, ",")
var cloudConfig []byte
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)
}
}
pluginInitializer := kubeadmission.NewPluginInitializer(client, sharedInformers, apiAuthorizer, cloudConfig)
pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, apiAuthorizer, cloudConfig)
admissionConfigProvider, err := admission.ReadAdmissionConfiguration(admissionControlPluginNames, s.GenericServerRunOptions.AdmissionControlConfigFile)
if err != nil {
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

View File

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

View File

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

View File

@ -199,7 +199,7 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
if err != nil {
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 {
return fmt.Errorf("failed to initialize plugins: %v", err)
}

View File

@ -21,7 +21,10 @@ go_test(
go_library(
name = "go_default_library",
srcs = ["initializer.go"],
srcs = [
"initializer.go",
"registry.go",
],
tags = ["automanaged"],
deps = [
"//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",
srcs = ["admission.go"],
tags = ["automanaged"],
deps = ["//vendor:k8s.io/apiserver/pkg/admission"],
deps = [
"//pkg/kubeapiserver/admission:go_default_library",
"//vendor:k8s.io/apiserver/pkg/admission",
],
)
go_test(

View File

@ -20,10 +20,11 @@ import (
"io"
"k8s.io/apiserver/pkg/admission"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
)
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
})
}

View File

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

View File

@ -30,10 +30,11 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apiserver/pkg/admission"
"k8s.io/kubernetes/pkg/api"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
)
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
})
}

View File

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

View File

@ -24,10 +24,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission"
"k8s.io/kubernetes/pkg/api"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
)
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
})
}

View File

@ -28,6 +28,7 @@ go_library(
deps = [
"//pkg/api: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/apis/meta/v1",
"//vendor:k8s.io/apiserver/pkg/admission",

View File

@ -26,6 +26,7 @@ import (
"k8s.io/apiserver/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/helper"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
)
var (
@ -39,7 +40,7 @@ var (
)
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
})
}

View File

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

View File

@ -21,10 +21,11 @@ import (
"io"
"k8s.io/apiserver/pkg/admission"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
)
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
})
}

View File

@ -30,13 +30,13 @@ import (
)
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
})
// This is for legacy support of the DenyExecOnPrivileged admission controller. Most
// 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
})
}

View File

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

View File

@ -25,10 +25,11 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/authorization/authorizer"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
)
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{
Handler: admission.NewHandler(admission.Create, admission.Update),
}, nil

View File

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

View File

@ -39,6 +39,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"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
_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
@ -49,7 +50,7 @@ var (
)
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)
if err != nil {
return nil, err

View File

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

View File

@ -29,6 +29,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apiserver/pkg/admission"
"k8s.io/kubernetes/pkg/api"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
)
var (
@ -46,7 +47,7 @@ const (
// WARNING: this feature is experimental and will definitely change.
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
s, err := newDataSource(*source)
if err != nil {

View File

@ -44,7 +44,7 @@ const (
)
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{})
})
}

View File

@ -31,7 +31,7 @@ import (
)
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
})
}

View File

@ -31,7 +31,7 @@ import (
)
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
})
}

View File

@ -51,7 +51,7 @@ const (
)
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))
})
}

View File

@ -33,7 +33,7 @@ import (
)
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()
return persistentVolumeLabelAdmission, nil
})

View File

@ -40,7 +40,7 @@ import (
var NamespaceNodeSelectors = []string{"scheduler.alpha.kubernetes.io/node-selector"}
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.
pluginConfig := readConfig(config)
plugin := NewPodNodeSelector(pluginConfig.PodNodeSelectorPluginConfig)

View File

@ -41,7 +41,7 @@ const (
)
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
})
}

View File

@ -37,7 +37,7 @@ import (
)
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)
if err != nil {
return nil, err

View File

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

View File

@ -45,7 +45,7 @@ const (
)
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)
return plugin, nil
})

View File

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

View File

@ -23,10 +23,11 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apiserver/pkg/admission"
"k8s.io/kubernetes/pkg/api"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
)
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
})
}

View File

@ -55,7 +55,7 @@ const DefaultAPITokenMountPath = "/var/run/secrets/kubernetes.io/serviceaccount"
const PluginName = "ServiceAccount"
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()
return serviceAccountAdmission, nil
})

View File

@ -39,7 +39,7 @@ const (
)
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()
return plugin, nil
})

View File

@ -34,11 +34,13 @@ import (
// the parameter is nil.
type Factory func(config io.Reader) (Interface, error)
type Plugins struct {
lock sync.Mutex
registry map[string]Factory
}
// All registered admission options.
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 = func(name string, config io.Reader) bool {
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
type PluginEnabledFunc func(name string, config io.Reader) bool
// GetPlugins enumerates the names of all registered plugins.
func GetPlugins() []string {
pluginsMutex.Lock()
defer pluginsMutex.Unlock()
// Registered enumerates the names of all registered plugins.
func (ps *Plugins) Registered() []string {
ps.lock.Lock()
defer ps.lock.Unlock()
keys := []string{}
for k := range plugins {
for k := range ps.registry {
keys = append(keys, k)
}
sort.Strings(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.
func RegisterPlugin(name string, plugin Factory) {
pluginsMutex.Lock()
defer pluginsMutex.Unlock()
_, found := plugins[name]
func (ps *Plugins) Register(name string, plugin Factory) {
ps.lock.Lock()
defer ps.lock.Unlock()
_, found := ps.registry[name]
if found {
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)
plugins[name] = plugin
ps.registry[name] = plugin
}
// 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
// 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.
func getPlugin(name string, config io.Reader) (Interface, bool, error) {
pluginsMutex.Lock()
defer pluginsMutex.Unlock()
f, found := plugins[name]
func (ps *Plugins) getPlugin(name string, config io.Reader) (Interface, bool, error) {
ps.lock.Lock()
defer ps.lock.Unlock()
f, found := ps.registry[name]
if !found {
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
// 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{}
for _, pluginName := range pluginNames {
pluginConfig, err := configProvider.ConfigFor(pluginName)
@ -121,7 +126,7 @@ func NewFromPlugins(pluginNames []string, configProvider ConfigProvider, pluginI
return nil, err
}
plugin, err := InitPlugin(pluginName, pluginConfig, pluginInitializer)
plugin, err := ps.InitPlugin(pluginName, pluginConfig, pluginInitializer)
if err != nil {
return nil, err
}
@ -133,13 +138,13 @@ func NewFromPlugins(pluginNames []string, configProvider ConfigProvider, pluginI
}
// 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 == "" {
glog.Info("No admission plugin specified.")
return nil, nil
}
plugin, found, err := getPlugin(name, config)
plugin, found, err := ps.getPlugin(name, config)
if err != nil {
return nil, fmt.Errorf("Couldn't init admission plugin %q: %v", name, err)
}

View File

@ -46,16 +46,18 @@ type ServerRunOptions struct {
MinRequestTimeout int
TargetRAMMB int
WatchCacheSizes []string
AdmissionPlugins *admission.Plugins
}
func NewServerRunOptions() *ServerRunOptions {
func NewServerRunOptions(admissionPlugins *admission.Plugins) *ServerRunOptions {
defaults := server.NewConfig(serializer.CodecFactory{})
return &ServerRunOptions{
AdmissionControl: "AlwaysAdmit",
MaxRequestsInFlight: defaults.MaxRequestsInFlight,
MaxMutatingRequestsInFlight: defaults.MaxMutatingRequestsInFlight,
MinRequestTimeout: defaults.MinRequestTimeout,
AdmissionPlugins: admissionPlugins,
}
}
@ -96,7 +98,7 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.AdmissionControl, "admission-control", s.AdmissionControl, ""+
"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,
"File with admission control configuration.")