Merge pull request #56408 from sttts/sttts-mutating-admission-webhook-config-scheme

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

admission: do not leak admission plugin config types outside of the plugin

We had two plugins that did not register their types into the external config scheme, breaking embedded config for them without noticing. Actually though, we do not want to leak those types at all into external scheme, but keep the types internal to the plugins. The second commit in this PR does that.
This commit is contained in:
Kubernetes Submit Queue
2018-01-15 08:22:29 -08:00
committed by GitHub
17 changed files with 138 additions and 170 deletions

View File

@@ -23,7 +23,6 @@ import (
"k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/flowcontrol"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
eventratelimitapi "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit" eventratelimitapi "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit"
eventratelimitapiv1alpha1 "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1"
"k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/validation" "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/validation"
) )
@@ -44,10 +43,6 @@ func Register(plugins *admission.Plugins) {
} }
return newEventRateLimit(configuration, realClock{}) return newEventRateLimit(configuration, realClock{})
}) })
// add our config types
eventratelimitapi.AddToScheme(plugins.ConfigScheme)
eventratelimitapiv1alpha1.AddToScheme(plugins.ConfigScheme)
} }
// Plugin implements an admission controller that can enforce event rate limits // Plugin implements an admission controller that can enforce event rate limits

View File

@@ -38,7 +38,6 @@ import (
"k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm"
"k8s.io/kubernetes/pkg/util/tolerations" "k8s.io/kubernetes/pkg/util/tolerations"
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction" pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
pluginapiv1alpha1 "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1"
) )
// Register registers a plugin // Register registers a plugin
@@ -50,9 +49,6 @@ func Register(plugins *admission.Plugins) {
} }
return NewPodTolerationsPlugin(pluginConfig), nil return NewPodTolerationsPlugin(pluginConfig), nil
}) })
// add our config types
pluginapi.AddToScheme(plugins.ConfigScheme)
pluginapiv1alpha1.AddToScheme(plugins.ConfigScheme)
} }
// The annotation keys for default and whitelist of tolerations // The annotation keys for default and whitelist of tolerations

View File

@@ -28,7 +28,6 @@ import (
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota" resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
resourcequotaapiv1alpha1 "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1"
"k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/validation" "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/validation"
) )
@@ -49,10 +48,6 @@ func Register(plugins *admission.Plugins) {
} }
return NewResourceQuota(configuration, 5, make(chan struct{})) return NewResourceQuota(configuration, 5, make(chan struct{}))
}) })
// add our config types
resourcequotaapi.AddToScheme(plugins.ConfigScheme)
resourcequotaapiv1alpha1.AddToScheme(plugins.ConfigScheme)
} }
// QuotaAdmission implements an admission controller that can enforce quota constraints // QuotaAdmission implements an admission controller that can enforce quota constraints

View File

@@ -20,6 +20,7 @@ go_test(
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1:go_default_library",
], ],

View File

@@ -126,16 +126,10 @@ type configProvider struct {
} }
// GetAdmissionPluginConfigurationFor returns a reader that holds the admission plugin configuration. // GetAdmissionPluginConfigurationFor returns a reader that holds the admission plugin configuration.
func GetAdmissionPluginConfigurationFor(pluginCfg apiserver.AdmissionPluginConfiguration, scheme *runtime.Scheme) (io.Reader, error) { func GetAdmissionPluginConfigurationFor(pluginCfg apiserver.AdmissionPluginConfiguration) (io.Reader, error) {
// if there is nothing nested in the object, we return the named location // if there is a nest object, return it directly
obj := pluginCfg.Configuration if pluginCfg.Configuration != nil {
if obj != nil { return bytes.NewBuffer(pluginCfg.Configuration.Raw), nil
// serialize the configuration and build a reader for it
content, err := writeYAML(obj, scheme)
if err != nil {
return nil, err
}
return bytes.NewBuffer(content), nil
} }
// there is nothing nested, so we delegate to path // there is nothing nested, so we delegate to path
if pluginCfg.Path != "" { if pluginCfg.Path != "" {
@@ -162,7 +156,7 @@ func (p configProvider) ConfigFor(pluginName string) (io.Reader, error) {
if pluginName != pluginCfg.Name { if pluginName != pluginCfg.Name {
continue continue
} }
pluginConfig, err := GetAdmissionPluginConfigurationFor(pluginCfg, p.scheme) pluginConfig, err := GetAdmissionPluginConfigurationFor(pluginCfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -23,6 +23,7 @@ import (
"testing" "testing"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/json"
"k8s.io/apiserver/pkg/apis/apiserver" "k8s.io/apiserver/pkg/apis/apiserver"
apiserverapi "k8s.io/apiserver/pkg/apis/apiserver" apiserverapi "k8s.io/apiserver/pkg/apis/apiserver"
apiserverapiv1alpha1 "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1" apiserverapiv1alpha1 "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"
@@ -49,7 +50,7 @@ func TestReadAdmissionConfiguration(t *testing.T) {
ExpectedAdmissionConfig *apiserver.AdmissionConfiguration ExpectedAdmissionConfig *apiserver.AdmissionConfiguration
PluginNames []string PluginNames []string
}{ }{
"v1Alpha1 configuration - path fixup": { "v1alpha1 configuration - path fixup": {
ConfigBody: `{ ConfigBody: `{
"apiVersion": "apiserver.k8s.io/v1alpha1", "apiVersion": "apiserver.k8s.io/v1alpha1",
"kind": "AdmissionConfiguration", "kind": "AdmissionConfiguration",
@@ -70,7 +71,7 @@ func TestReadAdmissionConfiguration(t *testing.T) {
}, },
PluginNames: []string{}, PluginNames: []string{},
}, },
"v1Alpha1 configuration - abspath": { "v1alpha1 configuration - abspath": {
ConfigBody: `{ ConfigBody: `{
"apiVersion": "apiserver.k8s.io/v1alpha1", "apiVersion": "apiserver.k8s.io/v1alpha1",
"kind": "AdmissionConfiguration", "kind": "AdmissionConfiguration",
@@ -153,3 +154,98 @@ func TestReadAdmissionConfiguration(t *testing.T) {
} }
} }
} }
func TestEmbeddedConfiguration(t *testing.T) {
// create a place holder file to hold per test config
configFile, err := ioutil.TempFile("", "admission-plugin-config")
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if err = configFile.Close(); err != nil {
t.Fatalf("unexpected err: %v", err)
}
configFileName := configFile.Name()
testCases := map[string]struct {
ConfigBody string
ExpectedConfig string
}{
"versioned configuration": {
ConfigBody: `{
"apiVersion": "apiserver.k8s.io/v1alpha1",
"kind": "AdmissionConfiguration",
"plugins": [
{
"name": "Foo",
"configuration": {
"apiVersion": "foo.admission.k8s.io/v1alpha1",
"kind": "Configuration",
"foo": "bar"
}
}
]}`,
ExpectedConfig: `{
"apiVersion": "foo.admission.k8s.io/v1alpha1",
"kind": "Configuration",
"foo": "bar"
}`,
},
"legacy configuration": {
ConfigBody: `{
"apiVersion": "apiserver.k8s.io/v1alpha1",
"kind": "AdmissionConfiguration",
"plugins": [
{
"name": "Foo",
"configuration": {
"foo": "bar"
}
}
]}`,
ExpectedConfig: `{
"foo": "bar"
}`,
},
}
for desc, test := range testCases {
scheme := runtime.NewScheme()
apiserverapi.AddToScheme(scheme)
apiserverapiv1alpha1.AddToScheme(scheme)
if err = ioutil.WriteFile(configFileName, []byte(test.ConfigBody), 0644); err != nil {
t.Errorf("[%s] unexpected err writing temp file: %v", desc, err)
continue
}
config, err := ReadAdmissionConfiguration([]string{"Foo"}, configFileName, scheme)
if err != nil {
t.Errorf("[%s] unexpected err: %v", desc, err)
continue
}
r, err := config.ConfigFor("Foo")
if err != nil {
t.Errorf("[%s] Failed to get Foo config: %v", desc, err)
continue
}
bs, err := ioutil.ReadAll(r)
if err != nil {
t.Errorf("[%s] Failed to read Foo config data: %v", desc, err)
continue
}
if !equalJSON(test.ExpectedConfig, string(bs)) {
t.Errorf("Unexpected config: expected=%q got=%q", test.ExpectedConfig, string(bs))
}
}
}
func equalJSON(a, b string) bool {
var x, y interface{}
if err := json.Unmarshal([]byte(a), &x); err != nil {
return false
}
if err := json.Unmarshal([]byte(b), &y); err != nil {
return false
}
return reflect.DeepEqual(x, y)
}

View File

@@ -23,8 +23,6 @@ go_library(
"//vendor/k8s.io/apiserver/pkg/admission/initializer:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/metrics:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/metrics:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/errors:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/errors:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/request:go_default_library",

View File

@@ -40,8 +40,6 @@ import (
genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer" genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer"
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics" admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config" "k8s.io/apiserver/pkg/admission/plugin/webhook/config"
webhookadmissionapi "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission"
webhookadmissionapiv1alpha1 "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1"
webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors" webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors"
"k8s.io/apiserver/pkg/admission/plugin/webhook/namespace" "k8s.io/apiserver/pkg/admission/plugin/webhook/namespace"
"k8s.io/apiserver/pkg/admission/plugin/webhook/request" "k8s.io/apiserver/pkg/admission/plugin/webhook/request"
@@ -66,9 +64,6 @@ func Register(plugins *admission.Plugins) {
return plugin, nil return plugin, nil
}) })
// add our config types
webhookadmissionapi.AddToScheme(plugins.ConfigScheme)
webhookadmissionapiv1alpha1.AddToScheme(plugins.ConfigScheme)
} }
// WebhookSource can list dynamic webhook plugins. // WebhookSource can list dynamic webhook plugins.

View File

@@ -25,8 +25,6 @@ import (
"sort" "sort"
"sync" "sync"
"k8s.io/apimachinery/pkg/runtime"
"github.com/golang/glog" "github.com/golang/glog"
) )
@@ -39,16 +37,10 @@ type Factory func(config io.Reader) (Interface, error)
type Plugins struct { type Plugins struct {
lock sync.Mutex lock sync.Mutex
registry map[string]Factory registry map[string]Factory
// ConfigScheme is used to parse the admission plugin config file.
// It is exposed to act as a hook for extending server providing their own config.
ConfigScheme *runtime.Scheme
} }
func NewPlugins() *Plugins { func NewPlugins() *Plugins {
return &Plugins{ return &Plugins{}
ConfigScheme: runtime.NewScheme(),
}
} }
// All registered admission options. // All registered admission options.

View File

@@ -46,5 +46,5 @@ type AdmissionPluginConfiguration struct {
// Configuration is an embedded configuration object to be used as the plugin's // Configuration is an embedded configuration object to be used as the plugin's
// configuration. If present, it will be used instead of the path to the configuration file. // configuration. If present, it will be used instead of the path to the configuration file.
// +optional // +optional
Configuration runtime.Object Configuration *runtime.Unknown
} }

View File

@@ -8,7 +8,6 @@ load(
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"conversion.go",
"doc.go", "doc.go",
"register.go", "register.go",
"types.go", "types.go",

View File

@@ -1,88 +0,0 @@
/*
Copyright 2017 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 v1alpha1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
var _ runtime.NestedObjectDecoder = &AdmissionConfiguration{}
// DecodeNestedObjects handles encoding RawExtensions on the AdmissionConfiguration, ensuring the
// objects are decoded with the provided decoder.
func (c *AdmissionConfiguration) DecodeNestedObjects(d runtime.Decoder) error {
// decoding failures result in a runtime.Unknown object being created in Object and passed
// to conversion
for k, v := range c.Plugins {
decodeNestedRawExtensionOrUnknown(d, &v.Configuration)
c.Plugins[k] = v
}
return nil
}
var _ runtime.NestedObjectEncoder = &AdmissionConfiguration{}
// EncodeNestedObjects handles encoding RawExtensions on the AdmissionConfiguration, ensuring the
// objects are encoded with the provided encoder.
func (c *AdmissionConfiguration) EncodeNestedObjects(e runtime.Encoder) error {
for k, v := range c.Plugins {
if err := encodeNestedRawExtension(e, &v.Configuration); err != nil {
return err
}
c.Plugins[k] = v
}
return nil
}
// decodeNestedRawExtensionOrUnknown decodes the raw extension into an object once. If called
// On a RawExtension that has already been decoded (has an object), it will not run again.
func decodeNestedRawExtensionOrUnknown(d runtime.Decoder, ext *runtime.RawExtension) {
if ext.Raw == nil || ext.Object != nil {
return
}
obj, gvk, err := d.Decode(ext.Raw, nil, nil)
if err != nil {
unk := &runtime.Unknown{Raw: ext.Raw}
if runtime.IsNotRegisteredError(err) {
if _, gvk, err := d.Decode(ext.Raw, nil, unk); err == nil {
unk.APIVersion = gvk.GroupVersion().String()
unk.Kind = gvk.Kind
ext.Object = unk
return
}
}
// TODO: record mime-type with the object
if gvk != nil {
unk.APIVersion = gvk.GroupVersion().String()
unk.Kind = gvk.Kind
}
obj = unk
}
ext.Object = obj
}
func encodeNestedRawExtension(e runtime.Encoder, ext *runtime.RawExtension) error {
if ext.Raw != nil || ext.Object == nil {
return nil
}
data, err := runtime.Encode(e, ext.Object)
if err != nil {
return err
}
ext.Raw = data
return nil
}

View File

@@ -46,5 +46,5 @@ type AdmissionPluginConfiguration struct {
// Configuration is an embedded configuration object to be used as the plugin's // Configuration is an embedded configuration object to be used as the plugin's
// configuration. If present, it will be used instead of the path to the configuration file. // configuration. If present, it will be used instead of the path to the configuration file.
// +optional // +optional
Configuration runtime.RawExtension `json:"configuration"` Configuration *runtime.Unknown `json:"configuration"`
} }

View File

@@ -21,6 +21,8 @@ limitations under the License.
package v1alpha1 package v1alpha1
import ( import (
unsafe "unsafe"
conversion "k8s.io/apimachinery/pkg/conversion" conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
apiserver "k8s.io/apiserver/pkg/apis/apiserver" apiserver "k8s.io/apiserver/pkg/apis/apiserver"
@@ -42,17 +44,7 @@ func RegisterConversions(scheme *runtime.Scheme) error {
} }
func autoConvert_v1alpha1_AdmissionConfiguration_To_apiserver_AdmissionConfiguration(in *AdmissionConfiguration, out *apiserver.AdmissionConfiguration, s conversion.Scope) error { func autoConvert_v1alpha1_AdmissionConfiguration_To_apiserver_AdmissionConfiguration(in *AdmissionConfiguration, out *apiserver.AdmissionConfiguration, s conversion.Scope) error {
if in.Plugins != nil { out.Plugins = *(*[]apiserver.AdmissionPluginConfiguration)(unsafe.Pointer(&in.Plugins))
in, out := &in.Plugins, &out.Plugins
*out = make([]apiserver.AdmissionPluginConfiguration, len(*in))
for i := range *in {
if err := Convert_v1alpha1_AdmissionPluginConfiguration_To_apiserver_AdmissionPluginConfiguration(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Plugins = nil
}
return nil return nil
} }
@@ -62,17 +54,7 @@ func Convert_v1alpha1_AdmissionConfiguration_To_apiserver_AdmissionConfiguration
} }
func autoConvert_apiserver_AdmissionConfiguration_To_v1alpha1_AdmissionConfiguration(in *apiserver.AdmissionConfiguration, out *AdmissionConfiguration, s conversion.Scope) error { func autoConvert_apiserver_AdmissionConfiguration_To_v1alpha1_AdmissionConfiguration(in *apiserver.AdmissionConfiguration, out *AdmissionConfiguration, s conversion.Scope) error {
if in.Plugins != nil { out.Plugins = *(*[]AdmissionPluginConfiguration)(unsafe.Pointer(&in.Plugins))
in, out := &in.Plugins, &out.Plugins
*out = make([]AdmissionPluginConfiguration, len(*in))
for i := range *in {
if err := Convert_apiserver_AdmissionPluginConfiguration_To_v1alpha1_AdmissionPluginConfiguration(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Plugins = nil
}
return nil return nil
} }
@@ -84,9 +66,7 @@ func Convert_apiserver_AdmissionConfiguration_To_v1alpha1_AdmissionConfiguration
func autoConvert_v1alpha1_AdmissionPluginConfiguration_To_apiserver_AdmissionPluginConfiguration(in *AdmissionPluginConfiguration, out *apiserver.AdmissionPluginConfiguration, s conversion.Scope) error { func autoConvert_v1alpha1_AdmissionPluginConfiguration_To_apiserver_AdmissionPluginConfiguration(in *AdmissionPluginConfiguration, out *apiserver.AdmissionPluginConfiguration, s conversion.Scope) error {
out.Name = in.Name out.Name = in.Name
out.Path = in.Path out.Path = in.Path
if err := runtime.Convert_runtime_RawExtension_To_runtime_Object(&in.Configuration, &out.Configuration, s); err != nil { out.Configuration = (*runtime.Unknown)(unsafe.Pointer(in.Configuration))
return err
}
return nil return nil
} }
@@ -98,9 +78,7 @@ func Convert_v1alpha1_AdmissionPluginConfiguration_To_apiserver_AdmissionPluginC
func autoConvert_apiserver_AdmissionPluginConfiguration_To_v1alpha1_AdmissionPluginConfiguration(in *apiserver.AdmissionPluginConfiguration, out *AdmissionPluginConfiguration, s conversion.Scope) error { func autoConvert_apiserver_AdmissionPluginConfiguration_To_v1alpha1_AdmissionPluginConfiguration(in *apiserver.AdmissionPluginConfiguration, out *AdmissionPluginConfiguration, s conversion.Scope) error {
out.Name = in.Name out.Name = in.Name
out.Path = in.Path out.Path = in.Path
if err := runtime.Convert_runtime_Object_To_runtime_RawExtension(&in.Configuration, &out.Configuration, s); err != nil { out.Configuration = (*runtime.Unknown)(unsafe.Pointer(in.Configuration))
return err
}
return nil return nil
} }

View File

@@ -60,7 +60,15 @@ func (in *AdmissionConfiguration) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AdmissionPluginConfiguration) DeepCopyInto(out *AdmissionPluginConfiguration) { func (in *AdmissionPluginConfiguration) DeepCopyInto(out *AdmissionPluginConfiguration) {
*out = *in *out = *in
in.Configuration.DeepCopyInto(&out.Configuration) if in.Configuration != nil {
in, out := &in.Configuration, &out.Configuration
if *in == nil {
*out = nil
} else {
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
}
return return
} }

View File

@@ -60,10 +60,14 @@ func (in *AdmissionConfiguration) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AdmissionPluginConfiguration) DeepCopyInto(out *AdmissionPluginConfiguration) { func (in *AdmissionPluginConfiguration) DeepCopyInto(out *AdmissionPluginConfiguration) {
*out = *in *out = *in
if in.Configuration == nil { if in.Configuration != nil {
out.Configuration = nil in, out := &in.Configuration, &out.Configuration
} else { if *in == nil {
out.Configuration = in.Configuration.DeepCopyObject() *out = nil
} else {
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
} }
return return
} }

View File

@@ -38,6 +38,13 @@ import (
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
) )
var scheme = runtime.NewScheme()
func init() {
apiserverapi.AddToScheme(scheme)
apiserverapiv1alpha1.AddToScheme(scheme)
}
// AdmissionOptions holds the admission options // AdmissionOptions holds the admission options
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
@@ -69,8 +76,6 @@ func NewAdmissionOptions() *AdmissionOptions {
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: []string{initialization.PluginName, mutatingwebhook.PluginName, validatingwebhook.PluginName},
} }
apiserverapi.AddToScheme(options.Plugins.ConfigScheme)
apiserverapiv1alpha1.AddToScheme(options.Plugins.ConfigScheme)
server.RegisterAllAdmissionPlugins(options.Plugins) server.RegisterAllAdmissionPlugins(options.Plugins)
return options return options
} }
@@ -120,7 +125,7 @@ func (a *AdmissionOptions) ApplyTo(
pluginNames = a.enabledPluginNames() pluginNames = a.enabledPluginNames()
} }
pluginsConfigProvider, err := admission.ReadAdmissionConfiguration(pluginNames, a.ConfigFile, a.Plugins.ConfigScheme) pluginsConfigProvider, err := admission.ReadAdmissionConfiguration(pluginNames, a.ConfigFile, scheme)
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)
} }