Rename ExternalAdmissionHookConfiguration to ValidatingWebhookConfiguration
Kubernetes-commit: 9ddea83a2ce0937cf0fc8f8c35614bb18e74cfad
This commit is contained in:
		
							parent
							
								
									b38d0e710e
								
							
						
					
					
						commit
						3846cb803e
					
				|  | @ -1,83 +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 configuration | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 
 | ||||
| 	"github.com/golang/glog" | ||||
| 
 | ||||
| 	"k8s.io/api/admissionregistration/v1alpha1" | ||||
| 	"k8s.io/apimachinery/pkg/api/errors" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| ) | ||||
| 
 | ||||
| type ExternalAdmissionHookConfigurationLister interface { | ||||
| 	List(opts metav1.ListOptions) (*v1alpha1.ExternalAdmissionHookConfigurationList, error) | ||||
| } | ||||
| 
 | ||||
| type ExternalAdmissionHookConfigurationManager struct { | ||||
| 	*poller | ||||
| } | ||||
| 
 | ||||
| func NewExternalAdmissionHookConfigurationManager(c ExternalAdmissionHookConfigurationLister) *ExternalAdmissionHookConfigurationManager { | ||||
| 	getFn := func() (runtime.Object, error) { | ||||
| 		list, err := c.List(metav1.ListOptions{}) | ||||
| 		if err != nil { | ||||
| 			if errors.IsNotFound(err) || errors.IsForbidden(err) { | ||||
| 				glog.V(5).Infof("ExternalAdmissionHookConfiguration are disabled due to an error: %v", err) | ||||
| 				return nil, ErrDisabled | ||||
| 			} | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return mergeExternalAdmissionHookConfigurations(list), nil | ||||
| 	} | ||||
| 
 | ||||
| 	return &ExternalAdmissionHookConfigurationManager{ | ||||
| 		newPoller(getFn), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // ExternalAdmissionHooks returns the merged ExternalAdmissionHookConfiguration.
 | ||||
| func (im *ExternalAdmissionHookConfigurationManager) ExternalAdmissionHooks() (*v1alpha1.ExternalAdmissionHookConfiguration, error) { | ||||
| 	configuration, err := im.poller.configuration() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	externalAdmissionHookConfiguration, ok := configuration.(*v1alpha1.ExternalAdmissionHookConfiguration) | ||||
| 	if !ok { | ||||
| 		return nil, fmt.Errorf("expected type %v, got type %v", reflect.TypeOf(externalAdmissionHookConfiguration), reflect.TypeOf(configuration)) | ||||
| 	} | ||||
| 	return externalAdmissionHookConfiguration, nil | ||||
| } | ||||
| 
 | ||||
| func (im *ExternalAdmissionHookConfigurationManager) Run(stopCh <-chan struct{}) { | ||||
| 	im.poller.Run(stopCh) | ||||
| } | ||||
| 
 | ||||
| func mergeExternalAdmissionHookConfigurations( | ||||
| 	list *v1alpha1.ExternalAdmissionHookConfigurationList, | ||||
| ) *v1alpha1.ExternalAdmissionHookConfiguration { | ||||
| 	configurations := list.Items | ||||
| 	var ret v1alpha1.ExternalAdmissionHookConfiguration | ||||
| 	for _, c := range configurations { | ||||
| 		ret.ExternalAdmissionHooks = append(ret.ExternalAdmissionHooks, c.ExternalAdmissionHooks...) | ||||
| 	} | ||||
| 	return &ret | ||||
| } | ||||
|  | @ -0,0 +1,84 @@ | |||
| /* | ||||
| 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 configuration | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 
 | ||||
| 	"github.com/golang/glog" | ||||
| 
 | ||||
| 	"k8s.io/api/admissionregistration/v1alpha1" | ||||
| 	"k8s.io/apimachinery/pkg/api/errors" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| ) | ||||
| 
 | ||||
| type ValidatingWebhookConfigurationLister interface { | ||||
| 	List(opts metav1.ListOptions) (*v1alpha1.ValidatingWebhookConfigurationList, error) | ||||
| } | ||||
| 
 | ||||
| // ValidatingWebhookConfigurationManager collects the validating webhook objects so that they can be called.
 | ||||
| type ValidatingWebhookConfigurationManager struct { | ||||
| 	*poller | ||||
| } | ||||
| 
 | ||||
| func NewValidatingWebhookConfigurationManager(c ValidatingWebhookConfigurationLister) *ValidatingWebhookConfigurationManager { | ||||
| 	getFn := func() (runtime.Object, error) { | ||||
| 		list, err := c.List(metav1.ListOptions{}) | ||||
| 		if err != nil { | ||||
| 			if errors.IsNotFound(err) || errors.IsForbidden(err) { | ||||
| 				glog.V(5).Infof("ValidatingWebhookConfiguration are disabled due to an error: %v", err) | ||||
| 				return nil, ErrDisabled | ||||
| 			} | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return mergeValidatingWebhookConfigurations(list), nil | ||||
| 	} | ||||
| 
 | ||||
| 	return &ValidatingWebhookConfigurationManager{ | ||||
| 		newPoller(getFn), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Webhooks returns the merged ValidatingWebhookConfiguration.
 | ||||
| func (im *ValidatingWebhookConfigurationManager) Webhooks() (*v1alpha1.ValidatingWebhookConfiguration, error) { | ||||
| 	configuration, err := im.poller.configuration() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	validatingWebhookConfiguration, ok := configuration.(*v1alpha1.ValidatingWebhookConfiguration) | ||||
| 	if !ok { | ||||
| 		return nil, fmt.Errorf("expected type %v, got type %v", reflect.TypeOf(validatingWebhookConfiguration), reflect.TypeOf(configuration)) | ||||
| 	} | ||||
| 	return validatingWebhookConfiguration, nil | ||||
| } | ||||
| 
 | ||||
| func (im *ValidatingWebhookConfigurationManager) Run(stopCh <-chan struct{}) { | ||||
| 	im.poller.Run(stopCh) | ||||
| } | ||||
| 
 | ||||
| func mergeValidatingWebhookConfigurations( | ||||
| 	list *v1alpha1.ValidatingWebhookConfigurationList, | ||||
| ) *v1alpha1.ValidatingWebhookConfiguration { | ||||
| 	configurations := list.Items | ||||
| 	var ret v1alpha1.ValidatingWebhookConfiguration | ||||
| 	for _, c := range configurations { | ||||
| 		ret.Webhooks = append(ret.Webhooks, c.Webhooks...) | ||||
| 	} | ||||
| 	return &ret | ||||
| } | ||||
|  | @ -25,15 +25,15 @@ import ( | |||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| ) | ||||
| 
 | ||||
| type disabledWebhookConfigLister struct{} | ||||
| type disabledValidatingWebhookConfigLister struct{} | ||||
| 
 | ||||
| func (l *disabledWebhookConfigLister) List(options metav1.ListOptions) (*v1alpha1.ExternalAdmissionHookConfigurationList, error) { | ||||
| 	return nil, errors.NewNotFound(schema.GroupResource{Group: "admissionregistration", Resource: "externalAdmissionHookConfigurations"}, "") | ||||
| func (l *disabledValidatingWebhookConfigLister) List(options metav1.ListOptions) (*v1alpha1.ValidatingWebhookConfigurationList, error) { | ||||
| 	return nil, errors.NewNotFound(schema.GroupResource{Group: "admissionregistration", Resource: "ValidatingWebhookConfigurations"}, "") | ||||
| } | ||||
| func TestWebhookConfigDisabled(t *testing.T) { | ||||
| 	manager := NewExternalAdmissionHookConfigurationManager(&disabledWebhookConfigLister{}) | ||||
| 	manager := NewValidatingWebhookConfigurationManager(&disabledValidatingWebhookConfigLister{}) | ||||
| 	manager.sync() | ||||
| 	_, err := manager.ExternalAdmissionHooks() | ||||
| 	_, err := manager.Webhooks() | ||||
| 	if err.Error() != ErrDisabled.Error() { | ||||
| 		t.Errorf("expected %v, got %v", ErrDisabled, err) | ||||
| 	} | ||||
|  | @ -75,7 +75,7 @@ func Register(plugins *admission.Plugins) { | |||
| // WebhookSource can list dynamic webhook plugins.
 | ||||
| type WebhookSource interface { | ||||
| 	Run(stopCh <-chan struct{}) | ||||
| 	ExternalAdmissionHooks() (*v1alpha1.ExternalAdmissionHookConfiguration, error) | ||||
| 	Webhooks() (*v1alpha1.ValidatingWebhookConfiguration, error) | ||||
| } | ||||
| 
 | ||||
| // NewGenericAdmissionWebhook returns a generic admission webhook plugin.
 | ||||
|  | @ -153,7 +153,7 @@ func (a *GenericAdmissionWebhook) SetScheme(scheme *runtime.Scheme) { | |||
| 
 | ||||
| // WantsExternalKubeClientSet defines a function which sets external ClientSet for admission plugins that need it
 | ||||
| func (a *GenericAdmissionWebhook) SetExternalKubeClientSet(client clientset.Interface) { | ||||
| 	a.hookSource = configuration.NewExternalAdmissionHookConfigurationManager(client.AdmissionregistrationV1alpha1().ExternalAdmissionHookConfigurations()) | ||||
| 	a.hookSource = configuration.NewValidatingWebhookConfigurationManager(client.AdmissionregistrationV1alpha1().ValidatingWebhookConfigurations()) | ||||
| } | ||||
| 
 | ||||
| // ValidateInitialization implements the InitializationValidator interface.
 | ||||
|  | @ -168,19 +168,19 @@ func (a *GenericAdmissionWebhook) ValidateInitialization() error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (a *GenericAdmissionWebhook) loadConfiguration(attr admission.Attributes) (*v1alpha1.ExternalAdmissionHookConfiguration, error) { | ||||
| 	hookConfig, err := a.hookSource.ExternalAdmissionHooks() | ||||
| 	// if ExternalAdmissionHook configuration is disabled, fail open
 | ||||
| func (a *GenericAdmissionWebhook) loadConfiguration(attr admission.Attributes) (*v1alpha1.ValidatingWebhookConfiguration, error) { | ||||
| 	hookConfig, err := a.hookSource.Webhooks() | ||||
| 	// if Webhook configuration is disabled, fail open
 | ||||
| 	if err == configuration.ErrDisabled { | ||||
| 		return &v1alpha1.ExternalAdmissionHookConfiguration{}, nil | ||||
| 		return &v1alpha1.ValidatingWebhookConfiguration{}, nil | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		e := apierrors.NewServerTimeout(attr.GetResource().GroupResource(), string(attr.GetOperation()), 1) | ||||
| 		e.ErrStatus.Message = fmt.Sprintf("Unable to refresh the ExternalAdmissionHook configuration: %v", err) | ||||
| 		e.ErrStatus.Message = fmt.Sprintf("Unable to refresh the Webhook configuration: %v", err) | ||||
| 		e.ErrStatus.Reason = "LoadingConfiguration" | ||||
| 		e.ErrStatus.Details.Causes = append(e.ErrStatus.Details.Causes, metav1.StatusCause{ | ||||
| 			Type:    "ExternalAdmissionHookConfigurationFailure", | ||||
| 			Message: "An error has occurred while refreshing the externalAdmissionHook configuration, no resources can be created/updated/deleted/connected until a refresh succeeds.", | ||||
| 			Type:    "ValidatingWebhookConfigurationFailure", | ||||
| 			Message: "An error has occurred while refreshing the ValidatingWebhook configuration, no resources can be created/updated/deleted/connected until a refresh succeeds.", | ||||
| 		}) | ||||
| 		return nil, e | ||||
| 	} | ||||
|  | @ -193,14 +193,14 @@ func (a *GenericAdmissionWebhook) Admit(attr admission.Attributes) error { | |||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	hooks := hookConfig.ExternalAdmissionHooks | ||||
| 	hooks := hookConfig.Webhooks | ||||
| 	ctx := context.TODO() | ||||
| 
 | ||||
| 	errCh := make(chan error, len(hooks)) | ||||
| 	wg := sync.WaitGroup{} | ||||
| 	wg.Add(len(hooks)) | ||||
| 	for i := range hooks { | ||||
| 		go func(hook *v1alpha1.ExternalAdmissionHook) { | ||||
| 		go func(hook *v1alpha1.Webhook) { | ||||
| 			defer wg.Done() | ||||
| 
 | ||||
| 			err := a.callHook(ctx, hook, attr) | ||||
|  | @ -245,7 +245,7 @@ func (a *GenericAdmissionWebhook) Admit(attr admission.Attributes) error { | |||
| 	return errs[0] | ||||
| } | ||||
| 
 | ||||
| func (a *GenericAdmissionWebhook) callHook(ctx context.Context, h *v1alpha1.ExternalAdmissionHook, attr admission.Attributes) error { | ||||
| func (a *GenericAdmissionWebhook) callHook(ctx context.Context, h *v1alpha1.Webhook, attr admission.Attributes) error { | ||||
| 	matches := false | ||||
| 	for _, r := range h.Rules { | ||||
| 		m := RuleMatcher{Rule: r, Attr: attr} | ||||
|  | @ -299,7 +299,7 @@ func toStatusErr(name string, result *metav1.Status) *apierrors.StatusError { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (a *GenericAdmissionWebhook) hookClient(h *v1alpha1.ExternalAdmissionHook) (*rest.RESTClient, error) { | ||||
| func (a *GenericAdmissionWebhook) hookClient(h *v1alpha1.Webhook) (*rest.RESTClient, error) { | ||||
| 	serverName := h.ClientConfig.Service.Name + "." + h.ClientConfig.Service.Namespace + ".svc" | ||||
| 	u, err := a.serviceResolver.ResolveEndpoint(h.ClientConfig.Service.Namespace, h.ClientConfig.Service.Name) | ||||
| 	if err != nil { | ||||
|  |  | |||
|  | @ -39,15 +39,15 @@ import ( | |||
| ) | ||||
| 
 | ||||
| type fakeHookSource struct { | ||||
| 	hooks []registrationv1alpha1.ExternalAdmissionHook | ||||
| 	hooks []registrationv1alpha1.Webhook | ||||
| 	err   error | ||||
| } | ||||
| 
 | ||||
| func (f *fakeHookSource) ExternalAdmissionHooks() (*registrationv1alpha1.ExternalAdmissionHookConfiguration, error) { | ||||
| func (f *fakeHookSource) Webhooks() (*registrationv1alpha1.ValidatingWebhookConfiguration, error) { | ||||
| 	if f.err != nil { | ||||
| 		return nil, f.err | ||||
| 	} | ||||
| 	return ®istrationv1alpha1.ExternalAdmissionHookConfiguration{ExternalAdmissionHooks: f.hooks}, nil | ||||
| 	return ®istrationv1alpha1.ValidatingWebhookConfiguration{Webhooks: f.hooks}, nil | ||||
| } | ||||
| 
 | ||||
| func (f *fakeHookSource) Run(stopCh <-chan struct{}) {} | ||||
|  | @ -137,8 +137,8 @@ func TestAdmit(t *testing.T) { | |||
| 		expectAllow   bool | ||||
| 		errorContains string | ||||
| 	} | ||||
| 	ccfg := func(urlPath string) registrationv1alpha1.AdmissionHookClientConfig { | ||||
| 		return registrationv1alpha1.AdmissionHookClientConfig{ | ||||
| 	ccfg := func(urlPath string) registrationv1alpha1.WebhookClientConfig { | ||||
| 		return registrationv1alpha1.WebhookClientConfig{ | ||||
| 			Service: registrationv1alpha1.ServiceReference{ | ||||
| 				Name:      "webhook-test", | ||||
| 				Namespace: "default", | ||||
|  | @ -163,7 +163,7 @@ func TestAdmit(t *testing.T) { | |||
| 	table := map[string]test{ | ||||
| 		"no match": { | ||||
| 			hookSource: fakeHookSource{ | ||||
| 				hooks: []registrationv1alpha1.ExternalAdmissionHook{{ | ||||
| 				hooks: []registrationv1alpha1.Webhook{{ | ||||
| 					Name:         "nomatch", | ||||
| 					ClientConfig: ccfg("disallow"), | ||||
| 					Rules: []registrationv1alpha1.RuleWithOperations{{ | ||||
|  | @ -175,7 +175,7 @@ func TestAdmit(t *testing.T) { | |||
| 		}, | ||||
| 		"match & allow": { | ||||
| 			hookSource: fakeHookSource{ | ||||
| 				hooks: []registrationv1alpha1.ExternalAdmissionHook{{ | ||||
| 				hooks: []registrationv1alpha1.Webhook{{ | ||||
| 					Name:         "allow", | ||||
| 					ClientConfig: ccfg("allow"), | ||||
| 					Rules:        matchEverythingRules, | ||||
|  | @ -185,7 +185,7 @@ func TestAdmit(t *testing.T) { | |||
| 		}, | ||||
| 		"match & disallow": { | ||||
| 			hookSource: fakeHookSource{ | ||||
| 				hooks: []registrationv1alpha1.ExternalAdmissionHook{{ | ||||
| 				hooks: []registrationv1alpha1.Webhook{{ | ||||
| 					Name:         "disallow", | ||||
| 					ClientConfig: ccfg("disallow"), | ||||
| 					Rules:        matchEverythingRules, | ||||
|  | @ -195,7 +195,7 @@ func TestAdmit(t *testing.T) { | |||
| 		}, | ||||
| 		"match & disallow ii": { | ||||
| 			hookSource: fakeHookSource{ | ||||
| 				hooks: []registrationv1alpha1.ExternalAdmissionHook{{ | ||||
| 				hooks: []registrationv1alpha1.Webhook{{ | ||||
| 					Name:         "disallowReason", | ||||
| 					ClientConfig: ccfg("disallowReason"), | ||||
| 					Rules:        matchEverythingRules, | ||||
|  | @ -205,7 +205,7 @@ func TestAdmit(t *testing.T) { | |||
| 		}, | ||||
| 		"match & fail (but allow because fail open)": { | ||||
| 			hookSource: fakeHookSource{ | ||||
| 				hooks: []registrationv1alpha1.ExternalAdmissionHook{{ | ||||
| 				hooks: []registrationv1alpha1.Webhook{{ | ||||
| 					Name:          "internalErr A", | ||||
| 					ClientConfig:  ccfg("internalErr"), | ||||
| 					Rules:         matchEverythingRules, | ||||
|  | @ -226,7 +226,7 @@ func TestAdmit(t *testing.T) { | |||
| 		}, | ||||
| 		"match & fail (but disallow because fail closed on nil)": { | ||||
| 			hookSource: fakeHookSource{ | ||||
| 				hooks: []registrationv1alpha1.ExternalAdmissionHook{{ | ||||
| 				hooks: []registrationv1alpha1.Webhook{{ | ||||
| 					Name:         "internalErr A", | ||||
| 					ClientConfig: ccfg("internalErr"), | ||||
| 					Rules:        matchEverythingRules, | ||||
|  | @ -244,7 +244,7 @@ func TestAdmit(t *testing.T) { | |||
| 		}, | ||||
| 		"match & fail (but fail because fail closed)": { | ||||
| 			hookSource: fakeHookSource{ | ||||
| 				hooks: []registrationv1alpha1.ExternalAdmissionHook{{ | ||||
| 				hooks: []registrationv1alpha1.Webhook{{ | ||||
| 					Name:          "internalErr A", | ||||
| 					ClientConfig:  ccfg("internalErr"), | ||||
| 					Rules:         matchEverythingRules, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue