mirror of https://github.com/k3s-io/k3s
refactor admission flag: add two admission flags and make plugins auto in recommended order
parent
621f3f3c0a
commit
7c5f9e0bba
|
@ -46,7 +46,7 @@ type ServerRunOptions struct {
|
||||||
InsecureServing *kubeoptions.InsecureServingOptions
|
InsecureServing *kubeoptions.InsecureServingOptions
|
||||||
Audit *genericoptions.AuditOptions
|
Audit *genericoptions.AuditOptions
|
||||||
Features *genericoptions.FeatureOptions
|
Features *genericoptions.FeatureOptions
|
||||||
Admission *genericoptions.AdmissionOptions
|
Admission *kubeoptions.AdmissionOptions
|
||||||
Authentication *kubeoptions.BuiltInAuthenticationOptions
|
Authentication *kubeoptions.BuiltInAuthenticationOptions
|
||||||
Authorization *kubeoptions.BuiltInAuthorizationOptions
|
Authorization *kubeoptions.BuiltInAuthorizationOptions
|
||||||
CloudProvider *kubeoptions.CloudProviderOptions
|
CloudProvider *kubeoptions.CloudProviderOptions
|
||||||
|
@ -82,7 +82,7 @@ func NewServerRunOptions() *ServerRunOptions {
|
||||||
InsecureServing: kubeoptions.NewInsecureServingOptions(),
|
InsecureServing: kubeoptions.NewInsecureServingOptions(),
|
||||||
Audit: genericoptions.NewAuditOptions(),
|
Audit: genericoptions.NewAuditOptions(),
|
||||||
Features: genericoptions.NewFeatureOptions(),
|
Features: genericoptions.NewFeatureOptions(),
|
||||||
Admission: genericoptions.NewAdmissionOptions(),
|
Admission: kubeoptions.NewAdmissionOptions(),
|
||||||
Authentication: kubeoptions.NewBuiltInAuthenticationOptions().WithAll(),
|
Authentication: kubeoptions.NewBuiltInAuthenticationOptions().WithAll(),
|
||||||
Authorization: kubeoptions.NewBuiltInAuthorizationOptions(),
|
Authorization: kubeoptions.NewBuiltInAuthorizationOptions(),
|
||||||
CloudProvider: kubeoptions.NewCloudProviderOptions(),
|
CloudProvider: kubeoptions.NewCloudProviderOptions(),
|
||||||
|
@ -116,10 +116,6 @@ func NewServerRunOptions() *ServerRunOptions {
|
||||||
// Overwrite the default for storage data format.
|
// Overwrite the default for storage data format.
|
||||||
s.Etcd.DefaultStorageMediaType = "application/vnd.kubernetes.protobuf"
|
s.Etcd.DefaultStorageMediaType = "application/vnd.kubernetes.protobuf"
|
||||||
|
|
||||||
// register all admission plugins
|
|
||||||
RegisterAllAdmissionPlugins(s.Admission.Plugins)
|
|
||||||
// Set the default for admission plugins names
|
|
||||||
s.Admission.PluginNames = []string{"AlwaysAdmit"}
|
|
||||||
return &s
|
return &s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 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 options
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/apiserver/pkg/admission"
|
||||||
|
"k8s.io/apiserver/pkg/server"
|
||||||
|
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||||
|
"k8s.io/client-go/informers"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdmissionOptions holds the admission options.
|
||||||
|
// It is a wrap of generic AdmissionOptions.
|
||||||
|
type AdmissionOptions struct {
|
||||||
|
// GenericAdmission holds the generic admission options.
|
||||||
|
GenericAdmission *genericoptions.AdmissionOptions
|
||||||
|
// DEPRECATED flag, should use EnabledAdmissionPlugins and DisabledAdmissionPlugins.
|
||||||
|
// They are mutually exclusive, specify both will lead to an error.
|
||||||
|
PluginNames []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAdmissionOptions creates a new instance of AdmissionOptions
|
||||||
|
// Note:
|
||||||
|
// In addition it calls RegisterAllAdmissionPlugins to register
|
||||||
|
// all kube-apiserver admission plugins.
|
||||||
|
//
|
||||||
|
// Provides the list of RecommendedPluginOrder that holds sane values
|
||||||
|
// that can be used by servers that don't care about admission chain.
|
||||||
|
// Servers that do care can overwrite/append that field after creation.
|
||||||
|
func NewAdmissionOptions() *AdmissionOptions {
|
||||||
|
options := genericoptions.NewAdmissionOptions()
|
||||||
|
// register all admission plugins
|
||||||
|
RegisterAllAdmissionPlugins(options.Plugins)
|
||||||
|
// set RecommendedPluginOrder
|
||||||
|
options.RecommendedPluginOrder = AllOrderedPlugins
|
||||||
|
// set DefaultOffPlugins
|
||||||
|
options.DefaultOffPlugins = DefaultOffAdmissionPlugins()
|
||||||
|
|
||||||
|
return &AdmissionOptions{
|
||||||
|
GenericAdmission: options,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFlags adds flags related to admission for kube-apiserver to the specified FlagSet
|
||||||
|
func (a *AdmissionOptions) AddFlags(fs *pflag.FlagSet) {
|
||||||
|
fs.StringSliceVar(&a.PluginNames, "admission-control", a.PluginNames, ""+
|
||||||
|
"Admission is divided into two phases. "+
|
||||||
|
"In the first phase, only mutating admission plugins run. "+
|
||||||
|
"In the second phase, only validating admission plugins run. "+
|
||||||
|
"The names in the below list may represent a validating plugin, a mutating plugin, or both. "+
|
||||||
|
"The order of plugins in which they are passed to this flag does not matter. "+
|
||||||
|
"Comma-delimited list of: "+strings.Join(a.GenericAdmission.Plugins.Registered(), ", ")+".")
|
||||||
|
fs.MarkDeprecated("admission-control", "Use --enable-admission-plugins or --disable-admission-plugins instead. Will be removed in a future version.")
|
||||||
|
|
||||||
|
a.GenericAdmission.AddFlags(fs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate verifies flags passed to kube-apiserver AdmissionOptions.
|
||||||
|
// Kube-apiserver verifies PluginNames and then call generic AdmissionOptions.Validate.
|
||||||
|
func (a *AdmissionOptions) Validate() []error {
|
||||||
|
if a == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
errs := []error{}
|
||||||
|
if a.PluginNames != nil &&
|
||||||
|
(a.GenericAdmission.EnablePlugins != nil || a.GenericAdmission.DisablePlugins != nil) {
|
||||||
|
errs = append(errs, fmt.Errorf("admission-control and enable-admission-plugins/disable-admission-plugins flags are mutually exclusive"))
|
||||||
|
}
|
||||||
|
|
||||||
|
registeredPlugins := sets.NewString(a.GenericAdmission.Plugins.Registered()...)
|
||||||
|
for _, name := range a.PluginNames {
|
||||||
|
if !registeredPlugins.Has(name) {
|
||||||
|
errs = append(errs, fmt.Errorf("admission-control plugin %q is unknown", name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errs = append(errs, a.GenericAdmission.Validate()...)
|
||||||
|
|
||||||
|
return errs
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyTo adds the admission chain to the server configuration.
|
||||||
|
// Kube-apiserver just call generic AdmissionOptions.ApplyTo.
|
||||||
|
func (a *AdmissionOptions) ApplyTo(
|
||||||
|
c *server.Config,
|
||||||
|
informers informers.SharedInformerFactory,
|
||||||
|
kubeAPIServerClientConfig *rest.Config,
|
||||||
|
scheme *runtime.Scheme,
|
||||||
|
pluginInitializers ...admission.PluginInitializer,
|
||||||
|
) error {
|
||||||
|
if a == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.PluginNames != nil {
|
||||||
|
// pass PluginNames to generic AdmissionOptions
|
||||||
|
a.GenericAdmission.EnablePlugins = a.PluginNames
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.GenericAdmission.ApplyTo(c, informers, kubeAPIServerClientConfig, scheme, pluginInitializers...)
|
||||||
|
}
|
|
@ -24,7 +24,6 @@ import (
|
||||||
_ "k8s.io/kubernetes/pkg/cloudprovider/providers"
|
_ "k8s.io/kubernetes/pkg/cloudprovider/providers"
|
||||||
|
|
||||||
// Admission policies
|
// Admission policies
|
||||||
"k8s.io/apiserver/pkg/admission"
|
|
||||||
"k8s.io/kubernetes/plugin/pkg/admission/admit"
|
"k8s.io/kubernetes/plugin/pkg/admission/admit"
|
||||||
"k8s.io/kubernetes/plugin/pkg/admission/alwayspullimages"
|
"k8s.io/kubernetes/plugin/pkg/admission/alwayspullimages"
|
||||||
"k8s.io/kubernetes/plugin/pkg/admission/antiaffinity"
|
"k8s.io/kubernetes/plugin/pkg/admission/antiaffinity"
|
||||||
|
@ -52,15 +51,59 @@ import (
|
||||||
"k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny"
|
"k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny"
|
||||||
"k8s.io/kubernetes/plugin/pkg/admission/serviceaccount"
|
"k8s.io/kubernetes/plugin/pkg/admission/serviceaccount"
|
||||||
"k8s.io/kubernetes/plugin/pkg/admission/storageclass/setdefault"
|
"k8s.io/kubernetes/plugin/pkg/admission/storageclass/setdefault"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/apiserver/pkg/admission"
|
||||||
|
"k8s.io/apiserver/pkg/admission/plugin/initialization"
|
||||||
|
"k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle"
|
||||||
|
mutatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating"
|
||||||
|
validatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/validating"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegisterAllAdmissionPlugins registers all admission plugins
|
// AllOrderedPlugins is the list of all the plugins in order.
|
||||||
|
var AllOrderedPlugins = []string{
|
||||||
|
admit.PluginName, // AlwaysAdmit
|
||||||
|
autoprovision.PluginName, // NamespaceAutoProvision
|
||||||
|
lifecycle.PluginName, // NamespaceLifecycle
|
||||||
|
exists.PluginName, // NamespaceExists
|
||||||
|
scdeny.PluginName, // SecurityContextDeny
|
||||||
|
antiaffinity.PluginName, // LimitPodHardAntiAffinity
|
||||||
|
initialresources.PluginName, // InitialResources
|
||||||
|
podpreset.PluginName, // PodPreset
|
||||||
|
limitranger.PluginName, // LimitRanger
|
||||||
|
serviceaccount.PluginName, // ServiceAccount
|
||||||
|
noderestriction.PluginName, // NodeRestriction
|
||||||
|
alwayspullimages.PluginName, // AlwaysPullImages
|
||||||
|
imagepolicy.PluginName, // ImagePolicyWebhook
|
||||||
|
podsecuritypolicy.PluginName, // PodSecurityPolicy
|
||||||
|
podnodeselector.PluginName, // PodNodeSelector
|
||||||
|
podpriority.PluginName, // Priority
|
||||||
|
defaulttolerationseconds.PluginName, // DefaultTolerationSeconds
|
||||||
|
podtolerationrestriction.PluginName, // PodTolerationRestriction
|
||||||
|
exec.DenyEscalatingExec, // DenyEscalatingExec
|
||||||
|
exec.DenyExecOnPrivileged, // DenyExecOnPrivileged
|
||||||
|
eventratelimit.PluginName, // EventRateLimit
|
||||||
|
extendedresourcetoleration.PluginName, // ExtendedResourceToleration
|
||||||
|
label.PluginName, // PersistentVolumeLabel
|
||||||
|
setdefault.PluginName, // DefaultStorageClass
|
||||||
|
pvcprotection.PluginName, // PVCProtection
|
||||||
|
gc.PluginName, // OwnerReferencesPermissionEnforcement
|
||||||
|
resize.PluginName, // PersistentVolumeClaimResize
|
||||||
|
mutatingwebhook.PluginName, // MutatingAdmissionWebhook
|
||||||
|
initialization.PluginName, // Initializers
|
||||||
|
validatingwebhook.PluginName, // ValidatingAdmissionWebhook
|
||||||
|
resourcequota.PluginName, // ResourceQuota
|
||||||
|
deny.PluginName, // AlwaysDeny
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterAllAdmissionPlugins registers all admission plugins and
|
||||||
|
// sets the recommended plugins order.
|
||||||
func RegisterAllAdmissionPlugins(plugins *admission.Plugins) {
|
func RegisterAllAdmissionPlugins(plugins *admission.Plugins) {
|
||||||
admit.Register(plugins)
|
admit.Register(plugins) // DEPRECATED as no real meaning
|
||||||
alwayspullimages.Register(plugins)
|
alwayspullimages.Register(plugins)
|
||||||
antiaffinity.Register(plugins)
|
antiaffinity.Register(plugins)
|
||||||
defaulttolerationseconds.Register(plugins)
|
defaulttolerationseconds.Register(plugins)
|
||||||
deny.Register(plugins)
|
deny.Register(plugins) // DEPRECATED as no real meaning
|
||||||
eventratelimit.Register(plugins)
|
eventratelimit.Register(plugins)
|
||||||
exec.Register(plugins)
|
exec.Register(plugins)
|
||||||
extendedresourcetoleration.Register(plugins)
|
extendedresourcetoleration.Register(plugins)
|
||||||
|
@ -84,3 +127,11 @@ func RegisterAllAdmissionPlugins(plugins *admission.Plugins) {
|
||||||
resize.Register(plugins)
|
resize.Register(plugins)
|
||||||
pvcprotection.Register(plugins)
|
pvcprotection.Register(plugins)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultOffAdmissionPlugins get admission plugins off by default for kube-apiserver.
|
||||||
|
func DefaultOffAdmissionPlugins() sets.String {
|
||||||
|
defaultOffPlugins := sets.NewString(AllOrderedPlugins...)
|
||||||
|
defaultOffPlugins.Delete(lifecycle.PluginName)
|
||||||
|
|
||||||
|
return defaultOffPlugins
|
||||||
|
}
|
|
@ -19,40 +19,46 @@ package admit
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
const PluginName = "AlwaysAdmit"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("AlwaysAdmit", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
return NewAlwaysAdmit(), nil
|
return NewAlwaysAdmit(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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{}
|
|
||||||
|
|
||||||
var _ admission.MutationInterface = AlwaysAdmit{}
|
var _ admission.MutationInterface = alwaysAdmit{}
|
||||||
var _ admission.ValidationInterface = AlwaysAdmit{}
|
var _ admission.ValidationInterface = alwaysAdmit{}
|
||||||
|
|
||||||
// Admit makes an admission decision based on the request attributes
|
// Admit makes an admission decision based on the request attributes
|
||||||
func (AlwaysAdmit) Admit(a admission.Attributes) (err error) {
|
func (alwaysAdmit) Admit(a admission.Attributes) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate.
|
// Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate.
|
||||||
func (AlwaysAdmit) Validate(a admission.Attributes) (err error) {
|
func (alwaysAdmit) Validate(a admission.Attributes) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles returns true if this admission controller can handle the given operation
|
// Handles returns true if this admission controller can handle the given operation
|
||||||
// where operation can be one of CREATE, UPDATE, DELETE, or CONNECT
|
// where operation can be one of CREATE, UPDATE, DELETE, or CONNECT
|
||||||
func (AlwaysAdmit) Handles(operation admission.Operation) bool {
|
func (alwaysAdmit) Handles(operation admission.Operation) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAlwaysAdmit creates a new always admit admission handler
|
// NewAlwaysAdmit creates a new always admit admission handler
|
||||||
func NewAlwaysAdmit() *AlwaysAdmit {
|
func NewAlwaysAdmit() admission.Interface {
|
||||||
return new(AlwaysAdmit)
|
// DEPRECATED: AlwaysAdmit admit all admission request, it is no use.
|
||||||
|
glog.Warningf("%s admission controller is deprecated. "+
|
||||||
|
"Please remove this controller from your configuration files and scripts.", PluginName)
|
||||||
|
return new(alwaysAdmit)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
|
|
||||||
func TestAdmissionNonNilAttribute(t *testing.T) {
|
func TestAdmissionNonNilAttribute(t *testing.T) {
|
||||||
handler := NewAlwaysAdmit()
|
handler := NewAlwaysAdmit()
|
||||||
err := handler.Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, nil))
|
err := handler.(*alwaysAdmit).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error returned from admission handler")
|
t.Errorf("Unexpected error returned from admission handler")
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ func TestAdmissionNonNilAttribute(t *testing.T) {
|
||||||
|
|
||||||
func TestAdmissionNilAttribute(t *testing.T) {
|
func TestAdmissionNilAttribute(t *testing.T) {
|
||||||
handler := NewAlwaysAdmit()
|
handler := NewAlwaysAdmit()
|
||||||
err := handler.Admit(nil)
|
err := handler.(*alwaysAdmit).Admit(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error returned from admission handler")
|
t.Errorf("Unexpected error returned from admission handler")
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,12 @@ import (
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
const PluginName = "AlwaysPullImages"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("AlwaysPullImages", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
return NewAlwaysPullImages(), nil
|
return NewAlwaysPullImages(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,11 @@ import (
|
||||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const PluginName = "LimitPodHardAntiAffinity"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("LimitPodHardAntiAffinityTopology", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
return NewInterPodAntiAffinity(), nil
|
return NewInterPodAntiAffinity(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,9 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/scheduler/algorithm"
|
"k8s.io/kubernetes/pkg/scheduler/algorithm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
const PluginName = "DefaultTolerationSeconds"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaultNotReadyTolerationSeconds = flag.Int64("default-not-ready-toleration-seconds", 300,
|
defaultNotReadyTolerationSeconds = flag.Int64("default-not-ready-toleration-seconds", 300,
|
||||||
"Indicates the tolerationSeconds of the toleration for notReady:NoExecute"+
|
"Indicates the tolerationSeconds of the toleration for notReady:NoExecute"+
|
||||||
|
@ -40,7 +43,7 @@ var (
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("DefaultTolerationSeconds", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
return NewDefaultTolerationSeconds(), nil
|
return NewDefaultTolerationSeconds(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,40 +20,47 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
const PluginName = "AlwaysDeny"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("AlwaysDeny", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
return NewAlwaysDeny(), nil
|
return NewAlwaysDeny(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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{}
|
|
||||||
|
|
||||||
var _ admission.MutationInterface = AlwaysDeny{}
|
var _ admission.MutationInterface = alwaysDeny{}
|
||||||
var _ admission.ValidationInterface = AlwaysDeny{}
|
var _ admission.ValidationInterface = alwaysDeny{}
|
||||||
|
|
||||||
// Admit makes an admission decision based on the request attributes.
|
// Admit makes an admission decision based on the request attributes.
|
||||||
func (AlwaysDeny) Admit(a admission.Attributes) (err error) {
|
func (alwaysDeny) Admit(a admission.Attributes) (err error) {
|
||||||
return admission.NewForbidden(a, errors.New("Admission control is denying all modifications"))
|
return admission.NewForbidden(a, errors.New("admission control is denying all modifications"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate.
|
// Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate.
|
||||||
func (AlwaysDeny) Validate(a admission.Attributes) (err error) {
|
func (alwaysDeny) Validate(a admission.Attributes) (err error) {
|
||||||
return admission.NewForbidden(a, errors.New("Admission control is denying all modifications"))
|
return admission.NewForbidden(a, errors.New("admission control is denying all modifications"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles returns true if this admission controller can handle the given operation
|
// Handles returns true if this admission controller can handle the given operation
|
||||||
// where operation can be one of CREATE, UPDATE, DELETE, or CONNECT
|
// where operation can be one of CREATE, UPDATE, DELETE, or CONNECT
|
||||||
func (AlwaysDeny) Handles(operation admission.Operation) bool {
|
func (alwaysDeny) Handles(operation admission.Operation) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAlwaysDeny creates an always deny admission handler
|
// NewAlwaysDeny creates an always deny admission handler
|
||||||
func NewAlwaysDeny() *AlwaysDeny {
|
func NewAlwaysDeny() admission.Interface {
|
||||||
return new(AlwaysDeny)
|
// DEPRECATED: AlwaysDeny denys all admission request, it is no use.
|
||||||
|
glog.Warningf("%s admission controller is deprecated. "+
|
||||||
|
"Please remove this controller from your configuration files and scripts.", PluginName)
|
||||||
|
return new(alwaysDeny)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
|
|
||||||
func TestAdmission(t *testing.T) {
|
func TestAdmission(t *testing.T) {
|
||||||
handler := NewAlwaysDeny()
|
handler := NewAlwaysDeny()
|
||||||
err := handler.Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, nil))
|
err := handler.(*alwaysDeny).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, nil))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Expected error returned from admission handler")
|
t.Error("Expected error returned from admission handler")
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,12 @@ import (
|
||||||
"k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/validation"
|
"k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
const PluginName = "EventRateLimit"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("EventRateLimit",
|
plugins.Register(PluginName,
|
||||||
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)
|
||||||
|
|
|
@ -29,15 +29,23 @@ import (
|
||||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DenyEscalatingExec indicates name of admission plugin.
|
||||||
|
DenyEscalatingExec = "DenyEscalatingExec"
|
||||||
|
// DenyExecOnPrivileged indicates name of admission plugin.
|
||||||
|
// Deprecated, should use DenyEscalatingExec instead.
|
||||||
|
DenyExecOnPrivileged = "DenyExecOnPrivileged"
|
||||||
|
)
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("DenyEscalatingExec", func(config io.Reader) (admission.Interface, error) {
|
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.
|
||||||
plugins.Register("DenyExecOnPrivileged", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(DenyExecOnPrivileged, func(config io.Reader) (admission.Interface, error) {
|
||||||
return NewDenyExecOnPrivileged(), nil
|
return NewDenyExecOnPrivileged(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,12 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/apis/core/helper"
|
"k8s.io/kubernetes/pkg/apis/core/helper"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
const PluginName = "ExtendedResourceToleration"
|
||||||
|
|
||||||
// Register is called by the apiserver to register the plugin factory.
|
// Register is called by the apiserver to register the plugin factory.
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("ExtendedResourceToleration", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
return newExtendedResourceToleration(), nil
|
return newExtendedResourceToleration(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,12 @@ import (
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
const PluginName = "OwnerReferencesPermissionEnforcement"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("OwnerReferencesPermissionEnforcement", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
// the pods/status endpoint is ignored by this plugin since old kubelets
|
// the pods/status endpoint is ignored by this plugin since old kubelets
|
||||||
// corrupt them. the pod status strategy ensures status updates cannot mutate
|
// corrupt them. the pod status strategy ensures status updates cannot mutate
|
||||||
// ownerRef.
|
// ownerRef.
|
||||||
|
|
|
@ -43,13 +43,16 @@ import (
|
||||||
_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
|
_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
const PluginName = "ImagePolicyWebhook"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
groupVersions = []schema.GroupVersion{v1alpha1.SchemeGroupVersion}
|
groupVersions = []schema.GroupVersion{v1alpha1.SchemeGroupVersion}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("ImagePolicyWebhook", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, 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
|
||||||
|
|
|
@ -42,12 +42,14 @@ const (
|
||||||
samplesThreshold = 30
|
samplesThreshold = 30
|
||||||
week = 7 * 24 * time.Hour
|
week = 7 * 24 * time.Hour
|
||||||
month = 30 * 24 * time.Hour
|
month = 30 * 24 * time.Hour
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
PluginName = "InitialResources"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
// WARNING: this feature is experimental and will definitely change.
|
// WARNING: this feature is experimental and will definitely change.
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("InitialResources", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, 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 {
|
||||||
|
|
|
@ -41,11 +41,13 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
limitRangerAnnotation = "kubernetes.io/limit-ranger"
|
limitRangerAnnotation = "kubernetes.io/limit-ranger"
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
PluginName = "LimitRanger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("LimitRanger", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
return NewLimitRanger(&DefaultLimitRangerActions{})
|
return NewLimitRanger(&DefaultLimitRangerActions{})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,12 @@ import (
|
||||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
const PluginName = "NamespaceAutoProvision"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("NamespaceAutoProvision", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
return NewProvision(), nil
|
return NewProvision(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,12 @@ import (
|
||||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
const PluginName = "NamespaceExists"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("NamespaceExists", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
return NewExists(), nil
|
return NewExists(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,11 @@ import (
|
||||||
vol "k8s.io/kubernetes/pkg/volume"
|
vol "k8s.io/kubernetes/pkg/volume"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const PluginName = "PersistentVolumeLabel"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("PersistentVolumeLabel", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
persistentVolumeLabelAdmission := NewPersistentVolumeLabel()
|
persistentVolumeLabelAdmission := NewPersistentVolumeLabel()
|
||||||
return persistentVolumeLabelAdmission, nil
|
return persistentVolumeLabelAdmission, nil
|
||||||
})
|
})
|
||||||
|
|
|
@ -40,9 +40,11 @@ import (
|
||||||
// node selectors labels to namespaces
|
// node selectors labels to namespaces
|
||||||
var NamespaceNodeSelectors = []string{"scheduler.alpha.kubernetes.io/node-selector"}
|
var NamespaceNodeSelectors = []string{"scheduler.alpha.kubernetes.io/node-selector"}
|
||||||
|
|
||||||
|
const PluginName = "PodNodeSelector"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("PodNodeSelector", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, 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)
|
||||||
|
|
|
@ -41,12 +41,12 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
annotationPrefix = "podpreset.admission.kubernetes.io"
|
annotationPrefix = "podpreset.admission.kubernetes.io"
|
||||||
pluginName = "PodPreset"
|
PluginName = "PodPreset"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register(pluginName, func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
return NewPlugin(), nil
|
return NewPlugin(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -72,10 +72,10 @@ func NewPlugin() *podPresetPlugin {
|
||||||
|
|
||||||
func (plugin *podPresetPlugin) ValidateInitialization() error {
|
func (plugin *podPresetPlugin) ValidateInitialization() error {
|
||||||
if plugin.client == nil {
|
if plugin.client == nil {
|
||||||
return fmt.Errorf("%s requires a client", pluginName)
|
return fmt.Errorf("%s requires a client", PluginName)
|
||||||
}
|
}
|
||||||
if plugin.lister == nil {
|
if plugin.lister == nil {
|
||||||
return fmt.Errorf("%s requires a lister", pluginName)
|
return fmt.Errorf("%s requires a lister", PluginName)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,9 +40,11 @@ import (
|
||||||
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
|
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const PluginName = "PodTolerationRestriction"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("PodTolerationRestriction", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, 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
|
||||||
|
|
|
@ -34,7 +34,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
pluginName = "Priority"
|
// PluginName indicates name of admission plugin.
|
||||||
|
PluginName = "Priority"
|
||||||
|
|
||||||
// HighestUserDefinablePriority is the highest priority for user defined priority classes. Priority values larger than 1 billion are reserved for Kubernetes system use.
|
// HighestUserDefinablePriority is the highest priority for user defined priority classes. Priority values larger than 1 billion are reserved for Kubernetes system use.
|
||||||
HighestUserDefinablePriority = 1000000000
|
HighestUserDefinablePriority = 1000000000
|
||||||
|
@ -50,7 +51,7 @@ var SystemPriorityClasses = map[string]int32{
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register(pluginName, func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
return NewPlugin(), nil
|
return NewPlugin(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -79,10 +80,10 @@ func NewPlugin() *PriorityPlugin {
|
||||||
// ValidateInitialization implements the InitializationValidator interface.
|
// ValidateInitialization implements the InitializationValidator interface.
|
||||||
func (p *PriorityPlugin) ValidateInitialization() error {
|
func (p *PriorityPlugin) ValidateInitialization() error {
|
||||||
if p.client == nil {
|
if p.client == nil {
|
||||||
return fmt.Errorf("%s requires a client", pluginName)
|
return fmt.Errorf("%s requires a client", PluginName)
|
||||||
}
|
}
|
||||||
if p.lister == nil {
|
if p.lister == nil {
|
||||||
return fmt.Errorf("%s requires a lister", pluginName)
|
return fmt.Errorf("%s requires a lister", PluginName)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,9 +31,11 @@ import (
|
||||||
"k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/validation"
|
"k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const PluginName = "ResourceQuota"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("ResourceQuota",
|
plugins.Register(PluginName,
|
||||||
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)
|
||||||
|
|
|
@ -25,9 +25,12 @@ import (
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PluginName indicates name of admission plugin.
|
||||||
|
const PluginName = "SecurityContextDeny"
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
func Register(plugins *admission.Plugins) {
|
func Register(plugins *admission.Plugins) {
|
||||||
plugins.Register("SecurityContextDeny", func(config io.Reader) (admission.Interface, error) {
|
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||||
return NewSecurityContextDeny(), nil
|
return NewSecurityContextDeny(), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admissi
|
||||||
scope.err(err, w, req)
|
scope.err(err, w, req)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if admit.Handles(admission.Connect) {
|
if admit != nil && admit.Handles(admission.Connect) {
|
||||||
connectRequest := &rest.ConnectRequest{
|
connectRequest := &rest.ConnectRequest{
|
||||||
Name: name,
|
Name: name,
|
||||||
Options: opts,
|
Options: opts,
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
|
@ -49,11 +50,16 @@ func init() {
|
||||||
type AdmissionOptions struct {
|
type AdmissionOptions struct {
|
||||||
// RecommendedPluginOrder holds an ordered list of plugin names we recommend to use by default
|
// RecommendedPluginOrder holds an ordered list of plugin names we recommend to use by default
|
||||||
RecommendedPluginOrder []string
|
RecommendedPluginOrder []string
|
||||||
// DefaultOffPlugins a list of plugin names that should be disabled by default
|
// DefaultOffPlugins is a set of plugin names that is disabled by default
|
||||||
DefaultOffPlugins []string
|
DefaultOffPlugins sets.String
|
||||||
PluginNames []string
|
|
||||||
ConfigFile string
|
|
||||||
|
|
||||||
|
// EnablePlugins indicates plugins to be enabled passed through `--enable-admission-plugins`.
|
||||||
|
EnablePlugins []string
|
||||||
|
// DisablePlugins indicates plugins to be disabled passed through `--disable-admission-plugins`.
|
||||||
|
DisablePlugins []string
|
||||||
|
// ConfigFile is the file path with admission control configuration.
|
||||||
|
ConfigFile string
|
||||||
|
// Plugins contains all registered plugins.
|
||||||
Plugins *admission.Plugins
|
Plugins *admission.Plugins
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,14 +73,13 @@ type AdmissionOptions struct {
|
||||||
// Servers that do care can overwrite/append that field after creation.
|
// Servers that do care can overwrite/append that field after creation.
|
||||||
func NewAdmissionOptions() *AdmissionOptions {
|
func NewAdmissionOptions() *AdmissionOptions {
|
||||||
options := &AdmissionOptions{
|
options := &AdmissionOptions{
|
||||||
Plugins: admission.NewPlugins(),
|
Plugins: admission.NewPlugins(),
|
||||||
PluginNames: []string{},
|
|
||||||
// This list is mix of mutating admission plugins and validating
|
// This list is mix of mutating admission plugins and validating
|
||||||
// admission plugins. The apiserver always runs the validating ones
|
// admission plugins. The apiserver always runs the validating ones
|
||||||
// after all the mutating ones, so their relative order in this list
|
// after all the mutating ones, so their relative order in this list
|
||||||
// doesn't matter.
|
// doesn't matter.
|
||||||
RecommendedPluginOrder: []string{lifecycle.PluginName, initialization.PluginName, mutatingwebhook.PluginName, validatingwebhook.PluginName},
|
RecommendedPluginOrder: []string{lifecycle.PluginName, initialization.PluginName, mutatingwebhook.PluginName, validatingwebhook.PluginName},
|
||||||
DefaultOffPlugins: []string{initialization.PluginName, mutatingwebhook.PluginName, validatingwebhook.PluginName},
|
DefaultOffPlugins: sets.NewString(initialization.PluginName, mutatingwebhook.PluginName, validatingwebhook.PluginName),
|
||||||
}
|
}
|
||||||
server.RegisterAllAdmissionPlugins(options.Plugins)
|
server.RegisterAllAdmissionPlugins(options.Plugins)
|
||||||
return options
|
return options
|
||||||
|
@ -82,14 +87,14 @@ func NewAdmissionOptions() *AdmissionOptions {
|
||||||
|
|
||||||
// AddFlags adds flags related to admission for a specific APIServer to the specified FlagSet
|
// AddFlags adds flags related to admission for a specific APIServer to the specified FlagSet
|
||||||
func (a *AdmissionOptions) AddFlags(fs *pflag.FlagSet) {
|
func (a *AdmissionOptions) AddFlags(fs *pflag.FlagSet) {
|
||||||
fs.StringSliceVar(&a.PluginNames, "admission-control", a.PluginNames, ""+
|
fs.StringSliceVar(&a.EnablePlugins, "enable-admission-plugins", a.EnablePlugins, ""+
|
||||||
"Admission is divided into two phases. "+
|
"admission plugins that should be enabled in addition to default enabled ones. "+
|
||||||
"In the first phase, only mutating admission plugins run. "+
|
"Comma-delimited list of admission plugins: "+strings.Join(a.Plugins.Registered(), ", ")+". "+
|
||||||
"In the second phase, only validating admission plugins run. "+
|
"The order of plugins in this flag does not matter.")
|
||||||
"The names in the below list may represent a validating plugin, a mutating plugin, or both. "+
|
fs.StringSliceVar(&a.DisablePlugins, "disable-admission-plugins", a.DisablePlugins, ""+
|
||||||
"Within each phase, the plugins will run in the order in which they are passed to this flag. "+
|
"admission plugins that should be disabled although they are in the default enabled plugins list. "+
|
||||||
"Comma-delimited list of: "+strings.Join(a.Plugins.Registered(), ", ")+".")
|
"Comma-delimited list of admission plugins: "+strings.Join(a.Plugins.Registered(), ", ")+". "+
|
||||||
|
"The order of plugins in this flag does not matter.")
|
||||||
fs.StringVar(&a.ConfigFile, "admission-control-config-file", a.ConfigFile,
|
fs.StringVar(&a.ConfigFile, "admission-control-config-file", a.ConfigFile,
|
||||||
"File with admission control configuration.")
|
"File with admission control configuration.")
|
||||||
}
|
}
|
||||||
|
@ -120,10 +125,7 @@ func (a *AdmissionOptions) ApplyTo(
|
||||||
return fmt.Errorf("admission depends on a Kubernetes core API shared informer, it cannot be nil")
|
return fmt.Errorf("admission depends on a Kubernetes core API shared informer, it cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginNames := a.PluginNames
|
pluginNames := a.enabledPluginNames()
|
||||||
if len(a.PluginNames) == 0 {
|
|
||||||
pluginNames = a.enabledPluginNames()
|
|
||||||
}
|
|
||||||
|
|
||||||
pluginsConfigProvider, err := admission.ReadAdmissionConfiguration(pluginNames, a.ConfigFile, configScheme)
|
pluginsConfigProvider, err := admission.ReadAdmissionConfiguration(pluginNames, a.ConfigFile, configScheme)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -148,6 +150,7 @@ func (a *AdmissionOptions) ApplyTo(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate verifies flags passed to AdmissionOptions.
|
||||||
func (a *AdmissionOptions) Validate() []error {
|
func (a *AdmissionOptions) Validate() []error {
|
||||||
if a == nil {
|
if a == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -156,41 +159,57 @@ func (a *AdmissionOptions) Validate() []error {
|
||||||
errs := []error{}
|
errs := []error{}
|
||||||
|
|
||||||
registeredPlugins := sets.NewString(a.Plugins.Registered()...)
|
registeredPlugins := sets.NewString(a.Plugins.Registered()...)
|
||||||
for _, name := range a.PluginNames {
|
for _, name := range a.EnablePlugins {
|
||||||
if !registeredPlugins.Has(name) {
|
if !registeredPlugins.Has(name) {
|
||||||
errs = append(errs, fmt.Errorf("admission-control plugin %q is invalid", name))
|
errs = append(errs, fmt.Errorf("enable-admission-plugins plugin %q is unknown", name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, name := range a.DisablePlugins {
|
||||||
|
if !registeredPlugins.Has(name) {
|
||||||
|
errs = append(errs, fmt.Errorf("disable-admission-plugins plugin %q is unknown", name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enablePlugins := sets.NewString(a.EnablePlugins...)
|
||||||
|
disablePlugins := sets.NewString(a.DisablePlugins...)
|
||||||
|
if len(enablePlugins.Intersection(disablePlugins).List()) > 0 {
|
||||||
|
errs = append(errs, fmt.Errorf("%v in enable-admission-plugins and disable-admission-plugins "+
|
||||||
|
"overlapped", enablePlugins.Intersection(disablePlugins).List()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify RecommendedPluginOrder.
|
||||||
|
recommendPlugins := sets.NewString(a.RecommendedPluginOrder...)
|
||||||
|
intersections := registeredPlugins.Intersection(recommendPlugins)
|
||||||
|
if !intersections.Equal(recommendPlugins) {
|
||||||
|
// Developer error, this should never run in.
|
||||||
|
errs = append(errs, fmt.Errorf("plugins %v in RecommendedPluginOrder are not registered",
|
||||||
|
recommendPlugins.Difference(intersections).List()))
|
||||||
|
}
|
||||||
|
if !intersections.Equal(registeredPlugins) {
|
||||||
|
// Developer error, this should never run in.
|
||||||
|
errs = append(errs, fmt.Errorf("plugins %v registered are not in RecommendedPluginOrder",
|
||||||
|
registeredPlugins.Difference(intersections).List()))
|
||||||
|
}
|
||||||
|
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
// enabledPluginNames makes use of RecommendedPluginOrder and DefaultOffPlugins fields
|
// enabledPluginNames makes use of RecommendedPluginOrder, DefaultOffPlugins,
|
||||||
// to prepare a list of plugin names that are enabled.
|
// EnablePlugins, DisablePlugins fields
|
||||||
//
|
// to prepare a list of ordered plugin names that are enabled.
|
||||||
// TODO(p0lyn0mial): In the end we will introduce two new flags:
|
|
||||||
// --disable-admission-plugin this would be a list of admission plugins that a cluster-admin wants to explicitly disable.
|
|
||||||
// --enable-admission-plugin this would be a list of admission plugins that a cluster-admin wants to explicitly enable.
|
|
||||||
// both flags are going to be handled by this method
|
|
||||||
func (a *AdmissionOptions) enabledPluginNames() []string {
|
func (a *AdmissionOptions) enabledPluginNames() []string {
|
||||||
//TODO(p0lyn0mial): first subtract plugins that a user wants to explicitly enable from allOffPlugins (DefaultOffPlugins)
|
allOffPlugins := append(a.DefaultOffPlugins.List(), a.DisablePlugins...)
|
||||||
//TODO(p0lyn0miial): then add/append plugins that a user wants to explicitly disable to allOffPlugins
|
disabledPlugins := sets.NewString(allOffPlugins...)
|
||||||
//TODO(p0lyn0mial): so that --off=three --on=one,three default-off=one,two results in "one" being enabled.
|
enabledPlugins := sets.NewString(a.EnablePlugins...)
|
||||||
allOffPlugins := a.DefaultOffPlugins
|
disabledPlugins = disabledPlugins.Difference(enabledPlugins)
|
||||||
onlyEnabledPluginNames := []string{}
|
|
||||||
for _, pluginName := range a.RecommendedPluginOrder {
|
orderedPlugins := []string{}
|
||||||
disablePlugin := false
|
for _, plugin := range a.RecommendedPluginOrder {
|
||||||
for _, disabledPluginName := range allOffPlugins {
|
if !disabledPlugins.Has(plugin) {
|
||||||
if pluginName == disabledPluginName {
|
orderedPlugins = append(orderedPlugins, plugin)
|
||||||
disablePlugin = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if disablePlugin {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
onlyEnabledPluginNames = append(onlyEnabledPluginNames, pluginName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return onlyEnabledPluginNames
|
return orderedPlugins
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue