mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-10 21:50:05 +00:00
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:
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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",
|
||||||
],
|
],
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
}
|
||||||
|
@@ -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",
|
||||||
|
@@ -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.
|
||||||
|
@@ -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.
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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",
|
||||||
|
@@ -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
|
|
||||||
}
|
|
@@ -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"`
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user