mirror of https://github.com/k3s-io/k3s
Remove the propagated scheme from the Admission chain
parent
d08bc3774d
commit
cebb4ee2ac
|
@ -70,7 +70,6 @@ func createAggregatorConfig(
|
||||||
&genericConfig,
|
&genericConfig,
|
||||||
externalInformers,
|
externalInformers,
|
||||||
genericConfig.LoopbackClientConfig,
|
genericConfig.LoopbackClientConfig,
|
||||||
aggregatorscheme.Scheme,
|
|
||||||
pluginInitializers...)
|
pluginInitializers...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -52,7 +52,6 @@ func createAPIExtensionsConfig(
|
||||||
&genericConfig,
|
&genericConfig,
|
||||||
externalInformers,
|
externalInformers,
|
||||||
genericConfig.LoopbackClientConfig,
|
genericConfig.LoopbackClientConfig,
|
||||||
apiextensionsapiserver.Scheme,
|
|
||||||
pluginInitializers...)
|
pluginInitializers...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -490,7 +490,6 @@ func buildGenericConfig(
|
||||||
genericConfig,
|
genericConfig,
|
||||||
versionedInformers,
|
versionedInformers,
|
||||||
kubeClientConfig,
|
kubeClientConfig,
|
||||||
legacyscheme.Scheme,
|
|
||||||
pluginInitializers...)
|
pluginInitializers...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lastErr = fmt.Errorf("failed to initialize admission: %v", err)
|
lastErr = fmt.Errorf("failed to initialize admission: %v", err)
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"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"
|
||||||
"k8s.io/apiserver/pkg/server"
|
"k8s.io/apiserver/pkg/server"
|
||||||
|
@ -108,7 +107,6 @@ func (a *AdmissionOptions) ApplyTo(
|
||||||
c *server.Config,
|
c *server.Config,
|
||||||
informers informers.SharedInformerFactory,
|
informers informers.SharedInformerFactory,
|
||||||
kubeAPIServerClientConfig *rest.Config,
|
kubeAPIServerClientConfig *rest.Config,
|
||||||
scheme *runtime.Scheme,
|
|
||||||
pluginInitializers ...admission.PluginInitializer,
|
pluginInitializers ...admission.PluginInitializer,
|
||||||
) error {
|
) error {
|
||||||
if a == nil {
|
if a == nil {
|
||||||
|
@ -120,7 +118,7 @@ func (a *AdmissionOptions) ApplyTo(
|
||||||
a.GenericAdmission.EnablePlugins, a.GenericAdmission.DisablePlugins = computePluginNames(a.PluginNames, a.GenericAdmission.RecommendedPluginOrder)
|
a.GenericAdmission.EnablePlugins, a.GenericAdmission.DisablePlugins = computePluginNames(a.PluginNames, a.GenericAdmission.RecommendedPluginOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.GenericAdmission.ApplyTo(c, informers, kubeAPIServerClientConfig, scheme, pluginInitializers...)
|
return a.GenericAdmission.ApplyTo(c, informers, kubeAPIServerClientConfig, pluginInitializers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// explicitly disable all plugins that are not in the enabled list
|
// explicitly disable all plugins that are not in the enabled list
|
||||||
|
|
|
@ -100,7 +100,7 @@ func newGCPermissionsEnforcement() (*gcPermissionsEnforcement, error) {
|
||||||
whiteList: whiteList,
|
whiteList: whiteList,
|
||||||
}
|
}
|
||||||
|
|
||||||
genericPluginInitializer := initializer.New(nil, nil, fakeAuthorizer{}, nil)
|
genericPluginInitializer := initializer.New(nil, nil, fakeAuthorizer{})
|
||||||
fakeDiscoveryClient := &fakediscovery.FakeDiscovery{Fake: &coretesting.Fake{}}
|
fakeDiscoveryClient := &fakediscovery.FakeDiscovery{Fake: &coretesting.Fake{}}
|
||||||
fakeDiscoveryClient.Resources = []*metav1.APIResourceList{
|
fakeDiscoveryClient.Resources = []*metav1.APIResourceList{
|
||||||
{
|
{
|
||||||
|
|
|
@ -788,7 +788,7 @@ func newHandlerForTest(c clientset.Interface) (*LimitRanger, informers.SharedInf
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, f, err
|
return nil, f, err
|
||||||
}
|
}
|
||||||
pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil)
|
pluginInitializer := genericadmissioninitializer.New(c, f, nil)
|
||||||
pluginInitializer.Initialize(handler)
|
pluginInitializer.Initialize(handler)
|
||||||
err = admission.ValidateInitialization(handler)
|
err = admission.ValidateInitialization(handler)
|
||||||
return handler, f, err
|
return handler, f, err
|
||||||
|
|
|
@ -39,7 +39,7 @@ import (
|
||||||
func newHandlerForTest(c clientset.Interface) (admission.MutationInterface, informers.SharedInformerFactory, error) {
|
func newHandlerForTest(c clientset.Interface) (admission.MutationInterface, informers.SharedInformerFactory, error) {
|
||||||
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
||||||
handler := NewProvision()
|
handler := NewProvision()
|
||||||
pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil)
|
pluginInitializer := genericadmissioninitializer.New(c, f, nil)
|
||||||
pluginInitializer.Initialize(handler)
|
pluginInitializer.Initialize(handler)
|
||||||
err := admission.ValidateInitialization(handler)
|
err := admission.ValidateInitialization(handler)
|
||||||
return handler, f, err
|
return handler, f, err
|
||||||
|
|
|
@ -38,7 +38,7 @@ import (
|
||||||
func newHandlerForTest(c kubernetes.Interface) (admission.ValidationInterface, informers.SharedInformerFactory, error) {
|
func newHandlerForTest(c kubernetes.Interface) (admission.ValidationInterface, informers.SharedInformerFactory, error) {
|
||||||
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
||||||
handler := NewExists()
|
handler := NewExists()
|
||||||
pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil)
|
pluginInitializer := genericadmissioninitializer.New(c, f, nil)
|
||||||
pluginInitializer.Initialize(handler)
|
pluginInitializer.Initialize(handler)
|
||||||
err := admission.ValidateInitialization(handler)
|
err := admission.ValidateInitialization(handler)
|
||||||
return handler, f, err
|
return handler, f, err
|
||||||
|
|
|
@ -197,7 +197,7 @@ func TestHandles(t *testing.T) {
|
||||||
func newHandlerForTest(c kubernetes.Interface) (*podNodeSelector, informers.SharedInformerFactory, error) {
|
func newHandlerForTest(c kubernetes.Interface) (*podNodeSelector, informers.SharedInformerFactory, error) {
|
||||||
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
||||||
handler := NewPodNodeSelector(nil)
|
handler := NewPodNodeSelector(nil)
|
||||||
pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil)
|
pluginInitializer := genericadmissioninitializer.New(c, f, nil)
|
||||||
pluginInitializer.Initialize(handler)
|
pluginInitializer.Initialize(handler)
|
||||||
err := admission.ValidateInitialization(handler)
|
err := admission.ValidateInitialization(handler)
|
||||||
return handler, f, err
|
return handler, f, err
|
||||||
|
|
|
@ -346,7 +346,7 @@ func newHandlerForTest(c kubernetes.Interface) (*podTolerationsPlugin, informers
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
handler := NewPodTolerationsPlugin(pluginConfig)
|
handler := NewPodTolerationsPlugin(pluginConfig)
|
||||||
pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil)
|
pluginInitializer := genericadmissioninitializer.New(c, f, nil)
|
||||||
pluginInitializer.Initialize(handler)
|
pluginInitializer.Initialize(handler)
|
||||||
err = admission.ValidateInitialization(handler)
|
err = admission.ValidateInitialization(handler)
|
||||||
return handler, f, err
|
return handler, f, err
|
||||||
|
|
|
@ -91,7 +91,7 @@ func (o CustomResourceDefinitionsServerOptions) Config() (*apiserver.Config, err
|
||||||
}
|
}
|
||||||
|
|
||||||
serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs)
|
serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs)
|
||||||
if err := o.RecommendedOptions.ApplyTo(serverConfig, apiserver.Scheme); err != nil {
|
if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), apiserver.Scheme); err != nil {
|
if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), apiserver.Scheme); err != nil {
|
||||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||||
package initializer
|
package initializer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
|
@ -28,7 +27,6 @@ type pluginInitializer struct {
|
||||||
externalClient kubernetes.Interface
|
externalClient kubernetes.Interface
|
||||||
externalInformers informers.SharedInformerFactory
|
externalInformers informers.SharedInformerFactory
|
||||||
authorizer authorizer.Authorizer
|
authorizer authorizer.Authorizer
|
||||||
scheme *runtime.Scheme
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates an instance of admission plugins initializer.
|
// New creates an instance of admission plugins initializer.
|
||||||
|
@ -37,13 +35,11 @@ func New(
|
||||||
extClientset kubernetes.Interface,
|
extClientset kubernetes.Interface,
|
||||||
extInformers informers.SharedInformerFactory,
|
extInformers informers.SharedInformerFactory,
|
||||||
authz authorizer.Authorizer,
|
authz authorizer.Authorizer,
|
||||||
scheme *runtime.Scheme,
|
|
||||||
) pluginInitializer {
|
) pluginInitializer {
|
||||||
return pluginInitializer{
|
return pluginInitializer{
|
||||||
externalClient: extClientset,
|
externalClient: extClientset,
|
||||||
externalInformers: extInformers,
|
externalInformers: extInformers,
|
||||||
authorizer: authz,
|
authorizer: authz,
|
||||||
scheme: scheme,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,10 +57,6 @@ func (i pluginInitializer) Initialize(plugin admission.Interface) {
|
||||||
if wants, ok := plugin.(WantsAuthorizer); ok {
|
if wants, ok := plugin.(WantsAuthorizer); ok {
|
||||||
wants.SetAuthorizer(i.authorizer)
|
wants.SetAuthorizer(i.authorizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if wants, ok := plugin.(WantsScheme); ok {
|
|
||||||
wants.SetScheme(i.scheme)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ admission.PluginInitializer = pluginInitializer{}
|
var _ admission.PluginInitializer = pluginInitializer{}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
"k8s.io/apiserver/pkg/admission/initializer"
|
"k8s.io/apiserver/pkg/admission/initializer"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
|
@ -29,22 +28,10 @@ import (
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestWantsScheme ensures that the scheme is injected when
|
|
||||||
// the WantsScheme interface is implemented by a plugin.
|
|
||||||
func TestWantsScheme(t *testing.T) {
|
|
||||||
scheme := runtime.NewScheme()
|
|
||||||
target := initializer.New(nil, nil, nil, scheme)
|
|
||||||
wantSchemeAdmission := &WantSchemeAdmission{}
|
|
||||||
target.Initialize(wantSchemeAdmission)
|
|
||||||
if wantSchemeAdmission.scheme != scheme {
|
|
||||||
t.Errorf("expected scheme to be initialized")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestWantsAuthorizer ensures that the authorizer is injected
|
// TestWantsAuthorizer ensures that the authorizer is injected
|
||||||
// when the WantsAuthorizer interface is implemented by a plugin.
|
// when the WantsAuthorizer interface is implemented by a plugin.
|
||||||
func TestWantsAuthorizer(t *testing.T) {
|
func TestWantsAuthorizer(t *testing.T) {
|
||||||
target := initializer.New(nil, nil, &TestAuthorizer{}, nil)
|
target := initializer.New(nil, nil, &TestAuthorizer{})
|
||||||
wantAuthorizerAdmission := &WantAuthorizerAdmission{}
|
wantAuthorizerAdmission := &WantAuthorizerAdmission{}
|
||||||
target.Initialize(wantAuthorizerAdmission)
|
target.Initialize(wantAuthorizerAdmission)
|
||||||
if wantAuthorizerAdmission.auth == nil {
|
if wantAuthorizerAdmission.auth == nil {
|
||||||
|
@ -56,7 +43,7 @@ func TestWantsAuthorizer(t *testing.T) {
|
||||||
// when the WantsExternalKubeClientSet interface is implemented by a plugin.
|
// when the WantsExternalKubeClientSet interface is implemented by a plugin.
|
||||||
func TestWantsExternalKubeClientSet(t *testing.T) {
|
func TestWantsExternalKubeClientSet(t *testing.T) {
|
||||||
cs := &fake.Clientset{}
|
cs := &fake.Clientset{}
|
||||||
target := initializer.New(cs, nil, &TestAuthorizer{}, nil)
|
target := initializer.New(cs, nil, &TestAuthorizer{})
|
||||||
wantExternalKubeClientSet := &WantExternalKubeClientSet{}
|
wantExternalKubeClientSet := &WantExternalKubeClientSet{}
|
||||||
target.Initialize(wantExternalKubeClientSet)
|
target.Initialize(wantExternalKubeClientSet)
|
||||||
if wantExternalKubeClientSet.cs != cs {
|
if wantExternalKubeClientSet.cs != cs {
|
||||||
|
@ -69,7 +56,7 @@ func TestWantsExternalKubeClientSet(t *testing.T) {
|
||||||
func TestWantsExternalKubeInformerFactory(t *testing.T) {
|
func TestWantsExternalKubeInformerFactory(t *testing.T) {
|
||||||
cs := &fake.Clientset{}
|
cs := &fake.Clientset{}
|
||||||
sf := informers.NewSharedInformerFactory(cs, time.Duration(1)*time.Second)
|
sf := informers.NewSharedInformerFactory(cs, time.Duration(1)*time.Second)
|
||||||
target := initializer.New(cs, sf, &TestAuthorizer{}, nil)
|
target := initializer.New(cs, sf, &TestAuthorizer{})
|
||||||
wantExternalKubeInformerFactory := &WantExternalKubeInformerFactory{}
|
wantExternalKubeInformerFactory := &WantExternalKubeInformerFactory{}
|
||||||
target.Initialize(wantExternalKubeInformerFactory)
|
target.Initialize(wantExternalKubeInformerFactory)
|
||||||
if wantExternalKubeInformerFactory.sf != sf {
|
if wantExternalKubeInformerFactory.sf != sf {
|
||||||
|
@ -142,18 +129,3 @@ func (s *clientCertWanter) Admit(a admission.Attributes, o admission.ObjectInter
|
||||||
}
|
}
|
||||||
func (s *clientCertWanter) Handles(o admission.Operation) bool { return false }
|
func (s *clientCertWanter) Handles(o admission.Operation) bool { return false }
|
||||||
func (s *clientCertWanter) ValidateInitialization() error { return nil }
|
func (s *clientCertWanter) ValidateInitialization() error { return nil }
|
||||||
|
|
||||||
// WantSchemeAdmission is a test stub that fulfills the WantsScheme interface.
|
|
||||||
type WantSchemeAdmission struct {
|
|
||||||
scheme *runtime.Scheme
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *WantSchemeAdmission) SetScheme(s *runtime.Scheme) { self.scheme = s }
|
|
||||||
func (self *WantSchemeAdmission) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (self *WantSchemeAdmission) Handles(o admission.Operation) bool { return false }
|
|
||||||
func (self *WantSchemeAdmission) ValidateInitialization() error { return nil }
|
|
||||||
|
|
||||||
var _ admission.Interface = &WantSchemeAdmission{}
|
|
||||||
var _ initializer.WantsScheme = &WantSchemeAdmission{}
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||||
package initializer
|
package initializer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
|
@ -41,9 +40,3 @@ type WantsAuthorizer interface {
|
||||||
SetAuthorizer(authorizer.Authorizer)
|
SetAuthorizer(authorizer.Authorizer)
|
||||||
admission.InitializationValidator
|
admission.InitializationValidator
|
||||||
}
|
}
|
||||||
|
|
||||||
// WantsScheme defines a function that accepts runtime.Scheme for admission plugins that need it.
|
|
||||||
type WantsScheme interface {
|
|
||||||
SetScheme(*runtime.Scheme)
|
|
||||||
admission.InitializationValidator
|
|
||||||
}
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ func newHandlerForTestWithClock(c clientset.Interface, cacheClock clock.Clock) (
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, f, err
|
return nil, f, err
|
||||||
}
|
}
|
||||||
pluginInitializer := kubeadmission.New(c, f, nil, nil)
|
pluginInitializer := kubeadmission.New(c, f, nil)
|
||||||
pluginInitializer.Initialize(handler)
|
pluginInitializer.Initialize(handler)
|
||||||
err = admission.ValidateInitialization(handler)
|
err = admission.ValidateInitialization(handler)
|
||||||
return handler, f, err
|
return handler, f, err
|
||||||
|
|
|
@ -41,5 +41,5 @@ type VersionedAttributes struct {
|
||||||
// Dispatcher dispatches webhook call to a list of webhooks with admission attributes as argument.
|
// Dispatcher dispatches webhook call to a list of webhooks with admission attributes as argument.
|
||||||
type Dispatcher interface {
|
type Dispatcher interface {
|
||||||
// Dispatch a request to the webhooks using the given webhooks. A non-nil error means the request is rejected.
|
// Dispatch a request to the webhooks using the given webhooks. A non-nil error means the request is rejected.
|
||||||
Dispatch(ctx context.Context, a *VersionedAttributes, hooks []*v1beta1.Webhook) error
|
Dispatch(ctx context.Context, a *VersionedAttributes, o admission.ObjectInterfaces, hooks []*v1beta1.Webhook) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import (
|
||||||
admissionv1beta1 "k8s.io/api/admission/v1beta1"
|
admissionv1beta1 "k8s.io/api/admission/v1beta1"
|
||||||
"k8s.io/api/admissionregistration/v1beta1"
|
"k8s.io/api/admissionregistration/v1beta1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer"
|
genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer"
|
||||||
"k8s.io/apiserver/pkg/admission/plugin/webhook/config"
|
"k8s.io/apiserver/pkg/admission/plugin/webhook/config"
|
||||||
|
@ -96,10 +95,6 @@ func (a *Webhook) SetServiceResolver(sr webhook.ServiceResolver) {
|
||||||
a.clientManager.SetServiceResolver(sr)
|
a.clientManager.SetServiceResolver(sr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetScheme sets a serializer(NegotiatedSerializer) which is derived from the scheme
|
|
||||||
func (a *Webhook) SetScheme(scheme *runtime.Scheme) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetExternalKubeClientSet implements the WantsExternalKubeInformerFactory interface.
|
// SetExternalKubeClientSet implements the WantsExternalKubeInformerFactory interface.
|
||||||
// It sets external ClientSet for admission plugins that need it
|
// It sets external ClientSet for admission plugins that need it
|
||||||
func (a *Webhook) SetExternalKubeClientSet(client clientset.Interface) {
|
func (a *Webhook) SetExternalKubeClientSet(client clientset.Interface) {
|
||||||
|
@ -193,5 +188,5 @@ func (a *Webhook) Dispatch(attr admission.Attributes, o admission.ObjectInterfac
|
||||||
}
|
}
|
||||||
versionedAttr.VersionedObject = out
|
versionedAttr.VersionedObject = out
|
||||||
}
|
}
|
||||||
return a.dispatcher.Dispatch(ctx, &versionedAttr, relevantHooks)
|
return a.dispatcher.Dispatch(ctx, &versionedAttr, o, relevantHooks)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,9 @@ import (
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
"k8s.io/apiserver/pkg/admission"
|
||||||
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
|
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
|
||||||
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/generic"
|
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
|
||||||
|
@ -53,10 +55,10 @@ func newMutatingDispatcher(p *Plugin) func(cm *webhook.ClientManager) generic.Di
|
||||||
|
|
||||||
var _ generic.Dispatcher = &mutatingDispatcher{}
|
var _ generic.Dispatcher = &mutatingDispatcher{}
|
||||||
|
|
||||||
func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, relevantHooks []*v1beta1.Webhook) error {
|
func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, o admission.ObjectInterfaces, relevantHooks []*v1beta1.Webhook) error {
|
||||||
for _, hook := range relevantHooks {
|
for _, hook := range relevantHooks {
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
err := a.callAttrMutatingHook(ctx, hook, attr)
|
err := a.callAttrMutatingHook(ctx, hook, attr, o)
|
||||||
admissionmetrics.Metrics.ObserveWebhook(time.Since(t), err != nil, attr.Attributes, "admit", hook.Name)
|
admissionmetrics.Metrics.ObserveWebhook(time.Since(t), err != nil, attr.Attributes, "admit", hook.Name)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
continue
|
continue
|
||||||
|
@ -76,13 +78,13 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr *generic.Version
|
||||||
|
|
||||||
// convert attr.VersionedObject to the internal version in the underlying admission.Attributes
|
// convert attr.VersionedObject to the internal version in the underlying admission.Attributes
|
||||||
if attr.VersionedObject != nil {
|
if attr.VersionedObject != nil {
|
||||||
return a.plugin.scheme.Convert(attr.VersionedObject, attr.Attributes.GetObject(), nil)
|
return o.GetObjectConvertor().Convert(attr.VersionedObject, attr.Attributes.GetObject(), nil)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// note that callAttrMutatingHook updates attr
|
// note that callAttrMutatingHook updates attr
|
||||||
func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta1.Webhook, attr *generic.VersionedAttributes) error {
|
func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta1.Webhook, attr *generic.VersionedAttributes, o admission.ObjectInterfaces) error {
|
||||||
if attr.IsDryRun() {
|
if attr.IsDryRun() {
|
||||||
if h.SideEffects == nil {
|
if h.SideEffects == nil {
|
||||||
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook SideEffects is nil")}
|
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook SideEffects is nil")}
|
||||||
|
@ -135,7 +137,8 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta
|
||||||
return apierrors.NewInternalError(fmt.Errorf("admission webhook %q attempted to modify the object, which is not supported for this operation", h.Name))
|
return apierrors.NewInternalError(fmt.Errorf("admission webhook %q attempted to modify the object, which is not supported for this operation", h.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
objJS, err := runtime.Encode(a.plugin.jsonSerializer, attr.VersionedObject)
|
jsonSerializer := json.NewSerializer(json.DefaultMetaFactory, o.GetObjectCreater(), o.GetObjectTyper(), false)
|
||||||
|
objJS, err := runtime.Encode(jsonSerializer, attr.VersionedObject)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apierrors.NewInternalError(err)
|
return apierrors.NewInternalError(err)
|
||||||
}
|
}
|
||||||
|
@ -150,17 +153,17 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta
|
||||||
// They are represented as Unstructured.
|
// They are represented as Unstructured.
|
||||||
newVersionedObject = &unstructured.Unstructured{}
|
newVersionedObject = &unstructured.Unstructured{}
|
||||||
} else {
|
} else {
|
||||||
newVersionedObject, err = a.plugin.scheme.New(attr.GetKind())
|
newVersionedObject, err = o.GetObjectCreater().New(attr.GetKind())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apierrors.NewInternalError(err)
|
return apierrors.NewInternalError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: if we have multiple mutating webhooks, we can remember the json
|
// TODO: if we have multiple mutating webhooks, we can remember the json
|
||||||
// instead of encoding and decoding for each one.
|
// instead of encoding and decoding for each one.
|
||||||
if _, _, err := a.plugin.jsonSerializer.Decode(patchedJS, nil, newVersionedObject); err != nil {
|
if _, _, err := jsonSerializer.Decode(patchedJS, nil, newVersionedObject); err != nil {
|
||||||
return apierrors.NewInternalError(err)
|
return apierrors.NewInternalError(err)
|
||||||
}
|
}
|
||||||
attr.VersionedObject = newVersionedObject
|
attr.VersionedObject = newVersionedObject
|
||||||
a.plugin.scheme.Default(attr.VersionedObject)
|
o.GetObjectDefaulter().Default(attr.VersionedObject)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ func TestDispatch(t *testing.T) {
|
||||||
require.NoError(t, example.AddToScheme(scheme))
|
require.NoError(t, example.AddToScheme(scheme))
|
||||||
require.NoError(t, examplev1.AddToScheme(scheme))
|
require.NoError(t, examplev1.AddToScheme(scheme))
|
||||||
require.NoError(t, example2v1.AddToScheme(scheme))
|
require.NoError(t, example2v1.AddToScheme(scheme))
|
||||||
|
objectInterfaces := &admission.SchemeBasedObjectInterfaces{scheme}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -118,16 +119,14 @@ func TestDispatch(t *testing.T) {
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
a := &mutatingDispatcher{
|
a := &mutatingDispatcher{
|
||||||
plugin: &Plugin{
|
plugin: &Plugin{},
|
||||||
scheme: scheme,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
attr := generic.VersionedAttributes{
|
attr := generic.VersionedAttributes{
|
||||||
Attributes: admission.NewAttributesRecord(test.out, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", admission.Operation(""), false, nil),
|
Attributes: admission.NewAttributesRecord(test.out, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", admission.Operation(""), false, nil),
|
||||||
VersionedOldObject: nil,
|
VersionedOldObject: nil,
|
||||||
VersionedObject: test.in,
|
VersionedObject: test.in,
|
||||||
}
|
}
|
||||||
if err := a.Dispatch(context.TODO(), &attr, nil); err != nil {
|
if err := a.Dispatch(context.TODO(), &attr, objectInterfaces, nil); err != nil {
|
||||||
t.Fatalf("%s: unexpected error: %v", test.name, err)
|
t.Fatalf("%s: unexpected error: %v", test.name, err)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(attr.Attributes.GetObject(), test.expectedObj) {
|
if !reflect.DeepEqual(attr.Attributes.GetObject(), test.expectedObj) {
|
||||||
|
|
|
@ -17,11 +17,8 @@ limitations under the License.
|
||||||
package mutating
|
package mutating
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
"k8s.io/apiserver/pkg/admission/configuration"
|
"k8s.io/apiserver/pkg/admission/configuration"
|
||||||
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
|
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
|
||||||
|
@ -47,9 +44,6 @@ func Register(plugins *admission.Plugins) {
|
||||||
// Plugin is an implementation of admission.Interface.
|
// Plugin is an implementation of admission.Interface.
|
||||||
type Plugin struct {
|
type Plugin struct {
|
||||||
*generic.Webhook
|
*generic.Webhook
|
||||||
|
|
||||||
scheme *runtime.Scheme
|
|
||||||
jsonSerializer *json.Serializer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ admission.MutationInterface = &Plugin{}
|
var _ admission.MutationInterface = &Plugin{}
|
||||||
|
@ -67,26 +61,11 @@ func NewMutatingWebhook(configFile io.Reader) (*Plugin, error) {
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetScheme sets a serializer(NegotiatedSerializer) which is derived from the scheme
|
|
||||||
func (a *Plugin) SetScheme(scheme *runtime.Scheme) {
|
|
||||||
a.Webhook.SetScheme(scheme)
|
|
||||||
if scheme != nil {
|
|
||||||
a.scheme = scheme
|
|
||||||
a.jsonSerializer = json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateInitialization implements the InitializationValidator interface.
|
// ValidateInitialization implements the InitializationValidator interface.
|
||||||
func (a *Plugin) ValidateInitialization() error {
|
func (a *Plugin) ValidateInitialization() error {
|
||||||
if err := a.Webhook.ValidateInitialization(); err != nil {
|
if err := a.Webhook.ValidateInitialization(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if a.scheme == nil {
|
|
||||||
return fmt.Errorf("scheme is not properly setup")
|
|
||||||
}
|
|
||||||
if a.jsonSerializer == nil {
|
|
||||||
return fmt.Errorf("jsonSerializer is not properly setup")
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"k8s.io/api/admissionregistration/v1beta1"
|
"k8s.io/api/admissionregistration/v1beta1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
"k8s.io/apiserver/pkg/admission"
|
||||||
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
|
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
|
||||||
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/generic"
|
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
|
||||||
|
@ -46,7 +47,7 @@ func newValidatingDispatcher(cm *webhook.ClientManager) generic.Dispatcher {
|
||||||
|
|
||||||
var _ generic.Dispatcher = &validatingDispatcher{}
|
var _ generic.Dispatcher = &validatingDispatcher{}
|
||||||
|
|
||||||
func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, relevantHooks []*v1beta1.Webhook) error {
|
func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, o admission.ObjectInterfaces, relevantHooks []*v1beta1.Webhook) error {
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
errCh := make(chan error, len(relevantHooks))
|
errCh := make(chan error, len(relevantHooks))
|
||||||
wg.Add(len(relevantHooks))
|
wg.Add(len(relevantHooks))
|
||||||
|
|
|
@ -114,18 +114,12 @@ func (a *AdmissionOptions) ApplyTo(
|
||||||
c *server.Config,
|
c *server.Config,
|
||||||
informers informers.SharedInformerFactory,
|
informers informers.SharedInformerFactory,
|
||||||
kubeAPIServerClientConfig *rest.Config,
|
kubeAPIServerClientConfig *rest.Config,
|
||||||
scheme *runtime.Scheme,
|
|
||||||
pluginInitializers ...admission.PluginInitializer,
|
pluginInitializers ...admission.PluginInitializer,
|
||||||
) error {
|
) error {
|
||||||
if a == nil {
|
if a == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Admission need scheme to construct admission initializer.
|
|
||||||
if scheme == nil {
|
|
||||||
return fmt.Errorf("admission depends on a scheme, it cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Admission depends on CoreAPI to set SharedInformerFactory and ClientConfig.
|
// Admission depends on CoreAPI to set SharedInformerFactory and ClientConfig.
|
||||||
if informers == nil {
|
if informers == nil {
|
||||||
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")
|
||||||
|
@ -142,7 +136,7 @@ func (a *AdmissionOptions) ApplyTo(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
genericInitializer := initializer.New(clientset, informers, c.Authorization.Authorizer, scheme)
|
genericInitializer := initializer.New(clientset, informers, c.Authorization.Authorizer)
|
||||||
initializersChain := admission.PluginInitializers{}
|
initializersChain := admission.PluginInitializers{}
|
||||||
pluginInitializers = append(pluginInitializers, genericInitializer)
|
pluginInitializers = append(pluginInitializers, genericInitializer)
|
||||||
initializersChain = append(initializersChain, pluginInitializers...)
|
initializersChain = append(initializersChain, pluginInitializers...)
|
||||||
|
|
|
@ -84,6 +84,7 @@ func (s *APIEnablementOptions) Validate(registries ...GroupRegisty) []error {
|
||||||
|
|
||||||
// ApplyTo override MergedResourceConfig with defaults and registry
|
// ApplyTo override MergedResourceConfig with defaults and registry
|
||||||
func (s *APIEnablementOptions) ApplyTo(c *server.Config, defaultResourceConfig *serverstore.ResourceConfig, registry resourceconfig.GroupVersionRegistry) error {
|
func (s *APIEnablementOptions) ApplyTo(c *server.Config, defaultResourceConfig *serverstore.ResourceConfig, registry resourceconfig.GroupVersionRegistry) error {
|
||||||
|
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,9 +82,8 @@ func (o *RecommendedOptions) AddFlags(fs *pflag.FlagSet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyTo adds RecommendedOptions to the server configuration.
|
// ApplyTo adds RecommendedOptions to the server configuration.
|
||||||
// scheme is the scheme of the apiserver types that are sent to the admission chain.
|
|
||||||
// pluginInitializers can be empty, it is only need for additional initializers.
|
// pluginInitializers can be empty, it is only need for additional initializers.
|
||||||
func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig, scheme *runtime.Scheme) error {
|
func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig) error {
|
||||||
if err := o.Etcd.ApplyTo(&config.Config); err != nil {
|
if err := o.Etcd.ApplyTo(&config.Config); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -108,7 +107,7 @@ func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig, scheme *r
|
||||||
}
|
}
|
||||||
if initializers, err := o.ExtraAdmissionInitializers(config); err != nil {
|
if initializers, err := o.ExtraAdmissionInitializers(config); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err := o.Admission.ApplyTo(&config.Config, config.SharedInformerFactory, config.ClientConfig, scheme, initializers...); err != nil {
|
} else if err := o.Admission.ApplyTo(&config.Config, config.SharedInformerFactory, config.ClientConfig, initializers...); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ func (o AggregatorOptions) RunAggregator(stopCh <-chan struct{}) error {
|
||||||
|
|
||||||
serverConfig := genericapiserver.NewRecommendedConfig(aggregatorscheme.Codecs)
|
serverConfig := genericapiserver.NewRecommendedConfig(aggregatorscheme.Codecs)
|
||||||
|
|
||||||
if err := o.RecommendedOptions.ApplyTo(serverConfig, aggregatorscheme.Scheme); err != nil {
|
if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), aggregatorscheme.Scheme); err != nil {
|
if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), aggregatorscheme.Scheme); err != nil {
|
||||||
|
|
|
@ -138,6 +138,7 @@ func TestBanflunderAdmissionPlugin(t *testing.T) {
|
||||||
admission.Create,
|
admission.Create,
|
||||||
false,
|
false,
|
||||||
nil),
|
nil),
|
||||||
|
nil,
|
||||||
)
|
)
|
||||||
|
|
||||||
// validate
|
// validate
|
||||||
|
|
|
@ -120,7 +120,7 @@ func (o *WardleServerOptions) Config() (*apiserver.Config, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs)
|
serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs)
|
||||||
if err := o.RecommendedOptions.ApplyTo(serverConfig, apiserver.Scheme); err != nil {
|
if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue