2019-01-12 04:58:27 +00:00
|
|
|
/*
|
|
|
|
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/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.")
|
|
|
|
fs.Lookup("admission-control").Hidden = false
|
|
|
|
|
|
|
|
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,
|
|
|
|
pluginInitializers ...admission.PluginInitializer,
|
|
|
|
) error {
|
|
|
|
if a == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if a.PluginNames != nil {
|
|
|
|
// pass PluginNames to generic AdmissionOptions
|
|
|
|
a.GenericAdmission.EnablePlugins, a.GenericAdmission.DisablePlugins = computePluginNames(a.PluginNames, a.GenericAdmission.RecommendedPluginOrder)
|
|
|
|
}
|
|
|
|
|
2019-04-07 17:07:55 +00:00
|
|
|
return a.GenericAdmission.ApplyTo(c, informers, kubeAPIServerClientConfig, pluginInitializers...)
|
2019-01-12 04:58:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// explicitly disable all plugins that are not in the enabled list
|
|
|
|
func computePluginNames(explicitlyEnabled []string, all []string) (enabled []string, disabled []string) {
|
|
|
|
return explicitlyEnabled, sets.NewString(all...).Difference(sets.NewString(explicitlyEnabled...)).List()
|
|
|
|
}
|