mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 12:18:16 +00:00 
			
		
		
		
	Add MutatingWebhookConfiguration type
This commit is contained in:
		
							
								
								
									
										2059
									
								
								api/openapi-spec/swagger.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2059
									
								
								api/openapi-spec/swagger.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
cluster/images/etcd-version-monitor
 | 
					cluster/images/etcd-version-monitor
 | 
				
			||||||
cmd/gke-certificates-controller/app
 | 
					cmd/gke-certificates-controller/app
 | 
				
			||||||
cmd/hyperkube
 | 
					cmd/hyperkube
 | 
				
			||||||
@@ -236,9 +237,10 @@ pkg/proxy/util
 | 
				
			|||||||
pkg/proxy/winkernel
 | 
					pkg/proxy/winkernel
 | 
				
			||||||
pkg/proxy/winuserspace
 | 
					pkg/proxy/winuserspace
 | 
				
			||||||
pkg/quota/evaluator/core
 | 
					pkg/quota/evaluator/core
 | 
				
			||||||
pkg/registry/admissionregistration/externaladmissionhookconfiguration/storage
 | 
					 | 
				
			||||||
pkg/registry/admissionregistration/initializerconfiguration/storage
 | 
					pkg/registry/admissionregistration/initializerconfiguration/storage
 | 
				
			||||||
 | 
					pkg/registry/admissionregistration/mutatingwebhookconfiguration/storage
 | 
				
			||||||
pkg/registry/admissionregistration/rest
 | 
					pkg/registry/admissionregistration/rest
 | 
				
			||||||
 | 
					pkg/registry/admissionregistration/validatingwebhookconfiguration/storage
 | 
				
			||||||
pkg/registry/apps/rest
 | 
					pkg/registry/apps/rest
 | 
				
			||||||
pkg/registry/apps/statefulset
 | 
					pkg/registry/apps/statefulset
 | 
				
			||||||
pkg/registry/apps/statefulset/storage
 | 
					pkg/registry/apps/statefulset/storage
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -137,6 +137,8 @@ func TestDefaulting(t *testing.T) {
 | 
				
			|||||||
		{Group: "settings.k8s.io", Version: "v1alpha1", Kind: "PodPresetList"}:                                   {},
 | 
							{Group: "settings.k8s.io", Version: "v1alpha1", Kind: "PodPresetList"}:                                   {},
 | 
				
			||||||
		{Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "ValidatingWebhookConfiguration"}:     {},
 | 
							{Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "ValidatingWebhookConfiguration"}:     {},
 | 
				
			||||||
		{Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "ValidatingWebhookConfigurationList"}: {},
 | 
							{Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "ValidatingWebhookConfigurationList"}: {},
 | 
				
			||||||
 | 
							{Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "MutatingWebhookConfiguration"}:       {},
 | 
				
			||||||
 | 
							{Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "MutatingWebhookConfigurationList"}:   {},
 | 
				
			||||||
		{Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicy"}:                                       {},
 | 
							{Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicy"}:                                       {},
 | 
				
			||||||
		{Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicyList"}:                                   {},
 | 
							{Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicyList"}:                                   {},
 | 
				
			||||||
		{Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClass"}:                                      {},
 | 
							{Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClass"}:                                      {},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,7 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Package admissionregistration is the internal version of the API.
 | 
					// Package admissionregistration is the internal version of the API.
 | 
				
			||||||
// AdmissionConfiguration and AdmissionPluginConfiguration are legacy static admission plugin configuration
 | 
					// AdmissionConfiguration and AdmissionPluginConfiguration are legacy static admission plugin configuration
 | 
				
			||||||
// InitializerConfiguration and ValidatingWebhookConfiguration is for the
 | 
					// InitializerConfiguration, ValidatingWebhookConfiguration, and MutatingWebhookConfiguration are for the
 | 
				
			||||||
// new dynamic admission controller configuration.
 | 
					// new dynamic admission controller configuration.
 | 
				
			||||||
// +groupName=admissionregistration.k8s.io
 | 
					// +groupName=admissionregistration.k8s.io
 | 
				
			||||||
package admissionregistration // import "k8s.io/kubernetes/pkg/apis/admissionregistration"
 | 
					package admissionregistration // import "k8s.io/kubernetes/pkg/apis/admissionregistration"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *r
 | 
				
			|||||||
	if err := announced.NewGroupMetaFactory(
 | 
						if err := announced.NewGroupMetaFactory(
 | 
				
			||||||
		&announced.GroupMetaFactoryArgs{
 | 
							&announced.GroupMetaFactoryArgs{
 | 
				
			||||||
			GroupName:                  admissionregistration.GroupName,
 | 
								GroupName:                  admissionregistration.GroupName,
 | 
				
			||||||
			RootScopedKinds:            sets.NewString("InitializerConfiguration", "ValidatingWebhookConfiguration"),
 | 
								RootScopedKinds:            sets.NewString("InitializerConfiguration", "ValidatingWebhookConfiguration", "MutatingWebhookConfiguration"),
 | 
				
			||||||
			VersionPreferenceOrder:     []string{v1alpha1.SchemeGroupVersion.Version},
 | 
								VersionPreferenceOrder:     []string{v1alpha1.SchemeGroupVersion.Version},
 | 
				
			||||||
			AddInternalObjectsToScheme: admissionregistration.AddToScheme,
 | 
								AddInternalObjectsToScheme: admissionregistration.AddToScheme,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,7 +48,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
 | 
				
			|||||||
		&InitializerConfigurationList{},
 | 
							&InitializerConfigurationList{},
 | 
				
			||||||
		&ValidatingWebhookConfiguration{},
 | 
							&ValidatingWebhookConfiguration{},
 | 
				
			||||||
		&ValidatingWebhookConfigurationList{},
 | 
							&ValidatingWebhookConfigurationList{},
 | 
				
			||||||
		// TODO add mutating configs here too
 | 
							&MutatingWebhookConfiguration{},
 | 
				
			||||||
 | 
							&MutatingWebhookConfigurationList{},
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -118,7 +118,7 @@ const (
 | 
				
			|||||||
// +genclient:nonNamespaced
 | 
					// +genclient:nonNamespaced
 | 
				
			||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
					// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ValidatingWebhookConfiguration describes the configuration of an admission webhook that accept or reject and object without changing it.
 | 
					// ValidatingWebhookConfiguration describes the configuration of an admission webhook that accepts or rejects and object without changing it.
 | 
				
			||||||
type ValidatingWebhookConfiguration struct {
 | 
					type ValidatingWebhookConfiguration struct {
 | 
				
			||||||
	metav1.TypeMeta
 | 
						metav1.TypeMeta
 | 
				
			||||||
	// Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata.
 | 
						// Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata.
 | 
				
			||||||
@@ -138,10 +138,38 @@ type ValidatingWebhookConfigurationList struct {
 | 
				
			|||||||
	// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
 | 
						// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	metav1.ListMeta
 | 
						metav1.ListMeta
 | 
				
			||||||
	// List of ValidatingWebhookConfiguration.
 | 
						// List of ValidatingWebhookConfigurations.
 | 
				
			||||||
	Items []ValidatingWebhookConfiguration
 | 
						Items []ValidatingWebhookConfiguration
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// +genclient
 | 
				
			||||||
 | 
					// +genclient:nonNamespaced
 | 
				
			||||||
 | 
					// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MutatingWebhookConfiguration describes the configuration of and admission webhook that accept or reject and may change the object.
 | 
				
			||||||
 | 
					type MutatingWebhookConfiguration struct {
 | 
				
			||||||
 | 
						metav1.TypeMeta
 | 
				
			||||||
 | 
						// Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata.
 | 
				
			||||||
 | 
						// +optional
 | 
				
			||||||
 | 
						metav1.ObjectMeta
 | 
				
			||||||
 | 
						// Webhooks is a list of webhooks and the affected resources and operations.
 | 
				
			||||||
 | 
						// +optional
 | 
				
			||||||
 | 
						Webhooks []Webhook
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MutatingWebhookConfigurationList is a list of MutatingWebhookConfiguration.
 | 
				
			||||||
 | 
					type MutatingWebhookConfigurationList struct {
 | 
				
			||||||
 | 
						metav1.TypeMeta
 | 
				
			||||||
 | 
						// Standard list metadata.
 | 
				
			||||||
 | 
						// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
 | 
				
			||||||
 | 
						// +optional
 | 
				
			||||||
 | 
						metav1.ListMeta
 | 
				
			||||||
 | 
						// List of MutatingWebhookConfiguration.
 | 
				
			||||||
 | 
						Items []MutatingWebhookConfiguration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Webhook describes an admission webhook and the resources and operations it applies to.
 | 
					// Webhook describes an admission webhook and the resources and operations it applies to.
 | 
				
			||||||
type Webhook struct {
 | 
					type Webhook struct {
 | 
				
			||||||
	// The name of the admission webhook.
 | 
						// The name of the admission webhook.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Package v1alpha1 is the v1alpha1 version of the API.
 | 
					// Package v1alpha1 is the v1alpha1 version of the API.
 | 
				
			||||||
// AdmissionConfiguration and AdmissionPluginConfiguration are legacy static admission plugin configuration
 | 
					// AdmissionConfiguration and AdmissionPluginConfiguration are legacy static admission plugin configuration
 | 
				
			||||||
// admissionregistrationv1alpha1.InitializerConfiguration and admissionregistrationv1alpha1.ValidatingWebhookConfiguration is for the
 | 
					// InitializerConfiguration, ValidatingWebhookConfiguration, and MutatingWebhookConfiguration are for the
 | 
				
			||||||
// new dynamic admission controller configuration.
 | 
					// new dynamic admission controller configuration.
 | 
				
			||||||
// +groupName=admissionregistration.k8s.io
 | 
					// +groupName=admissionregistration.k8s.io
 | 
				
			||||||
package v1alpha1 // import "k8s.io/kubernetes/pkg/apis/admissionregistration/v1alpha1"
 | 
					package v1alpha1 // import "k8s.io/kubernetes/pkg/apis/admissionregistration/v1alpha1"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -166,7 +166,15 @@ func ValidateInitializerConfigurationUpdate(newIC, oldIC *admissionregistration.
 | 
				
			|||||||
func ValidateValidatingWebhookConfiguration(e *admissionregistration.ValidatingWebhookConfiguration) field.ErrorList {
 | 
					func ValidateValidatingWebhookConfiguration(e *admissionregistration.ValidatingWebhookConfiguration) field.ErrorList {
 | 
				
			||||||
	allErrors := genericvalidation.ValidateObjectMeta(&e.ObjectMeta, false, genericvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
 | 
						allErrors := genericvalidation.ValidateObjectMeta(&e.ObjectMeta, false, genericvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
 | 
				
			||||||
	for i, hook := range e.Webhooks {
 | 
						for i, hook := range e.Webhooks {
 | 
				
			||||||
		allErrors = append(allErrors, validateWebhook(&hook, field.NewPath("validatingWebhooks").Index(i))...)
 | 
							allErrors = append(allErrors, validateWebhook(&hook, field.NewPath("webhooks").Index(i))...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrors
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateMutatingWebhookConfiguration(e *admissionregistration.MutatingWebhookConfiguration) field.ErrorList {
 | 
				
			||||||
 | 
						allErrors := genericvalidation.ValidateObjectMeta(&e.ObjectMeta, false, genericvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
 | 
				
			||||||
 | 
						for i, hook := range e.Webhooks {
 | 
				
			||||||
 | 
							allErrors = append(allErrors, validateWebhook(&hook, field.NewPath("webhooks").Index(i))...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return allErrors
 | 
						return allErrors
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -263,6 +271,10 @@ func validateRuleWithOperations(ruleWithOperations *admissionregistration.RuleWi
 | 
				
			|||||||
	return allErrors
 | 
						return allErrors
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ValidateValidatingwebhookConfigurationUpdate(newC, oldC *admissionregistration.ValidatingWebhookConfiguration) field.ErrorList {
 | 
					func ValidateValidatingWebhookConfigurationUpdate(newC, oldC *admissionregistration.ValidatingWebhookConfiguration) field.ErrorList {
 | 
				
			||||||
	return ValidateValidatingWebhookConfiguration(newC)
 | 
						return ValidateValidatingWebhookConfiguration(newC)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateMutatingWebhookConfigurationUpdate(newC, oldC *admissionregistration.MutatingWebhookConfiguration) field.ErrorList {
 | 
				
			||||||
 | 
						return ValidateMutatingWebhookConfiguration(newC)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -231,7 +231,7 @@ func TestValidateInitializerConfiguration(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getValidatingWebhookConfiguration(hooks []admissionregistration.Webhook) *admissionregistration.ValidatingWebhookConfiguration {
 | 
					func newValidatingWebhookConfiguration(hooks []admissionregistration.Webhook) *admissionregistration.ValidatingWebhookConfiguration {
 | 
				
			||||||
	return &admissionregistration.ValidatingWebhookConfiguration{
 | 
						return &admissionregistration.ValidatingWebhookConfiguration{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
			Name: "config",
 | 
								Name: "config",
 | 
				
			||||||
@@ -240,6 +240,8 @@ func getValidatingWebhookConfiguration(hooks []admissionregistration.Webhook) *a
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: Add TestValidateMutatingWebhookConfiguration to test validation for mutating webhooks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
					func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
		name          string
 | 
							name          string
 | 
				
			||||||
@@ -248,7 +250,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "all Webhooks must have a fully qualified name",
 | 
								name: "all Webhooks must have a fully qualified name",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -260,11 +262,11 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
						Name: "",
 | 
											Name: "",
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				}),
 | 
									}),
 | 
				
			||||||
			expectedError: `validatingWebhooks[1].name: Invalid value: "k8s.io": should be a domain with at least three segments separated by dots, validatingWebhooks[2].name: Required value`,
 | 
								expectedError: `webhooks[1].name: Invalid value: "k8s.io": should be a domain with at least three segments separated by dots, webhooks[2].name: Required value`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "Operations must not be empty or nil",
 | 
								name: "Operations must not be empty or nil",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -288,11 +290,11 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				}),
 | 
									}),
 | 
				
			||||||
			expectedError: `validatingWebhooks[0].rules[0].operations: Required value, validatingWebhooks[0].rules[1].operations: Required value`,
 | 
								expectedError: `webhooks[0].rules[0].operations: Required value, webhooks[0].rules[1].operations: Required value`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "\"\" is NOT a valid operation",
 | 
								name: "\"\" is NOT a valid operation",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -312,7 +314,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "operation must be either create/update/delete/connect",
 | 
								name: "operation must be either create/update/delete/connect",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -332,7 +334,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "wildcard operation cannot be mixed with other strings",
 | 
								name: "wildcard operation cannot be mixed with other strings",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -352,7 +354,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: `resource "*" can co-exist with resources that have subresources`,
 | 
								name: `resource "*" can co-exist with resources that have subresources`,
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -371,7 +373,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: `resource "*" cannot mix with resources that don't have subresources`,
 | 
								name: `resource "*" cannot mix with resources that don't have subresources`,
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -391,7 +393,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "resource a/* cannot mix with a/x",
 | 
								name: "resource a/* cannot mix with a/x",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -407,11 +409,11 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				}),
 | 
									}),
 | 
				
			||||||
			expectedError: `validatingWebhooks[0].rules[0].resources[1]: Invalid value: "a/x": if 'a/*' is present, must not specify a/x`,
 | 
								expectedError: `webhooks[0].rules[0].resources[1]: Invalid value: "a/x": if 'a/*' is present, must not specify a/x`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "resource a/* can mix with a",
 | 
								name: "resource a/* can mix with a",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -430,7 +432,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "resource */a cannot mix with x/a",
 | 
								name: "resource */a cannot mix with x/a",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -446,11 +448,11 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				}),
 | 
									}),
 | 
				
			||||||
			expectedError: `validatingWebhooks[0].rules[0].resources[1]: Invalid value: "x/a": if '*/a' is present, must not specify x/a`,
 | 
								expectedError: `webhooks[0].rules[0].resources[1]: Invalid value: "x/a": if '*/a' is present, must not specify x/a`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "resource */* cannot mix with other resources",
 | 
								name: "resource */* cannot mix with other resources",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -466,11 +468,11 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				}),
 | 
									}),
 | 
				
			||||||
			expectedError: `validatingWebhooks[0].rules[0].resources: Invalid value: []string{"*/*", "a"}: if '*/*' is present, must not specify other resources`,
 | 
								expectedError: `webhooks[0].rules[0].resources: Invalid value: []string{"*/*", "a"}: if '*/*' is present, must not specify other resources`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "FailurePolicy can only be \"Ignore\" or \"Fail\"",
 | 
								name: "FailurePolicy can only be \"Ignore\" or \"Fail\"",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -480,11 +482,11 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
						}(),
 | 
											}(),
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				}),
 | 
									}),
 | 
				
			||||||
			expectedError: `validatingWebhooks[0].failurePolicy: Unsupported value: "other": supported values: "Fail", "Ignore"`,
 | 
								expectedError: `webhooks[0].failurePolicy: Unsupported value: "other": supported values: "Fail", "Ignore"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "URLPath must start with slash",
 | 
								name: "URLPath must start with slash",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -497,7 +499,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "URLPath accepts slash",
 | 
								name: "URLPath accepts slash",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -510,7 +512,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "URLPath accepts no trailing slash",
 | 
								name: "URLPath accepts no trailing slash",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -523,7 +525,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "URLPath fails //",
 | 
								name: "URLPath fails //",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -536,7 +538,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "URLPath no empty step",
 | 
								name: "URLPath no empty step",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -548,7 +550,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
			expectedError: `clientConfig.urlPath: Invalid value: "/foo//bar/": segment[1] may not be empty`,
 | 
								expectedError: `clientConfig.urlPath: Invalid value: "/foo//bar/": segment[1] may not be empty`,
 | 
				
			||||||
		}, {
 | 
							}, {
 | 
				
			||||||
			name: "URLPath no empty step 2",
 | 
								name: "URLPath no empty step 2",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
@@ -561,7 +563,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "URLPath no non-subdomain",
 | 
								name: "URLPath no non-subdomain",
 | 
				
			||||||
			config: getValidatingWebhookConfiguration(
 | 
								config: newValidatingWebhookConfiguration(
 | 
				
			||||||
				[]admissionregistration.Webhook{
 | 
									[]admissionregistration.Webhook{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						Name: "webhook.k8s.io",
 | 
											Name: "webhook.k8s.io",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -106,7 +106,7 @@ func init() {
 | 
				
			|||||||
	if err := announced.NewGroupMetaFactory(
 | 
						if err := announced.NewGroupMetaFactory(
 | 
				
			||||||
		&announced.GroupMetaFactoryArgs{
 | 
							&announced.GroupMetaFactoryArgs{
 | 
				
			||||||
			GroupName:              admissionregistrationv1alpha1.GroupName,
 | 
								GroupName:              admissionregistrationv1alpha1.GroupName,
 | 
				
			||||||
			RootScopedKinds:        sets.NewString("InitializerConfiguration", "ValidatingWebhookConfiguration"),
 | 
								RootScopedKinds:        sets.NewString("InitializerConfiguration", "ValidatingWebhookConfiguration", "MutatingWebhookConfiguration"),
 | 
				
			||||||
			VersionPreferenceOrder: []string{admissionregistrationv1alpha1.SchemeGroupVersion.Version},
 | 
								VersionPreferenceOrder: []string{admissionregistrationv1alpha1.SchemeGroupVersion.Version},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		announced.VersionToSchemeFunc{
 | 
							announced.VersionToSchemeFunc{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2015 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 mutatingwebhookconfiguration // import "k8s.io/kubernetes/pkg/registry/admissionregistration/mutatingwebhookconfiguration"
 | 
				
			||||||
@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2015 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 storage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/runtime"
 | 
				
			||||||
 | 
						"k8s.io/apiserver/pkg/registry/generic"
 | 
				
			||||||
 | 
						genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/apis/admissionregistration"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/registry/admissionregistration/mutatingwebhookconfiguration"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// rest implements a RESTStorage for pod disruption budgets against etcd
 | 
				
			||||||
 | 
					type REST struct {
 | 
				
			||||||
 | 
						*genericregistry.Store
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewREST returns a RESTStorage object that will work against pod disruption budgets.
 | 
				
			||||||
 | 
					func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
 | 
				
			||||||
 | 
						store := &genericregistry.Store{
 | 
				
			||||||
 | 
							NewFunc:     func() runtime.Object { return &admissionregistration.MutatingWebhookConfiguration{} },
 | 
				
			||||||
 | 
							NewListFunc: func() runtime.Object { return &admissionregistration.MutatingWebhookConfigurationList{} },
 | 
				
			||||||
 | 
							ObjectNameFunc: func(obj runtime.Object) (string, error) {
 | 
				
			||||||
 | 
								return obj.(*admissionregistration.MutatingWebhookConfiguration).Name, nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							DefaultQualifiedResource: admissionregistration.Resource("mutatingwebhookconfigurations"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CreateStrategy: mutatingwebhookconfiguration.Strategy,
 | 
				
			||||||
 | 
							UpdateStrategy: mutatingwebhookconfiguration.Strategy,
 | 
				
			||||||
 | 
							DeleteStrategy: mutatingwebhookconfiguration.Strategy,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						options := &generic.StoreOptions{RESTOptions: optsGetter}
 | 
				
			||||||
 | 
						if err := store.CompleteWithOptions(options); err != nil {
 | 
				
			||||||
 | 
							panic(err) // TODO: Propagate error up
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &REST{store}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2014 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 mutatingwebhookconfiguration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/runtime"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/util/validation/field"
 | 
				
			||||||
 | 
						genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
 | 
				
			||||||
 | 
						"k8s.io/apiserver/pkg/storage/names"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/api/legacyscheme"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/apis/admissionregistration"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/apis/admissionregistration/validation"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// mutatingWebhookConfigurationStrategy implements verification logic for mutatingWebhookConfiguration.
 | 
				
			||||||
 | 
					type mutatingWebhookConfigurationStrategy struct {
 | 
				
			||||||
 | 
						runtime.ObjectTyper
 | 
				
			||||||
 | 
						names.NameGenerator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Strategy is the default logic that applies when creating and updating mutatingWebhookConfiguration objects.
 | 
				
			||||||
 | 
					var Strategy = mutatingWebhookConfigurationStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NamespaceScoped returns true because all mutatingWebhookConfiguration' need to be within a namespace.
 | 
				
			||||||
 | 
					func (mutatingWebhookConfigurationStrategy) NamespaceScoped() bool {
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PrepareForCreate clears the status of an mutatingWebhookConfiguration before creation.
 | 
				
			||||||
 | 
					func (mutatingWebhookConfigurationStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
 | 
				
			||||||
 | 
						ic := obj.(*admissionregistration.MutatingWebhookConfiguration)
 | 
				
			||||||
 | 
						ic.Generation = 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
 | 
				
			||||||
 | 
					func (mutatingWebhookConfigurationStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
 | 
				
			||||||
 | 
						newIC := obj.(*admissionregistration.MutatingWebhookConfiguration)
 | 
				
			||||||
 | 
						oldIC := old.(*admissionregistration.MutatingWebhookConfiguration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Any changes to the spec increment the generation number, any changes to the
 | 
				
			||||||
 | 
						// status should reflect the generation number of the corresponding object.
 | 
				
			||||||
 | 
						// See metav1.ObjectMeta description for more information on Generation.
 | 
				
			||||||
 | 
						if !reflect.DeepEqual(oldIC.Webhooks, newIC.Webhooks) {
 | 
				
			||||||
 | 
							newIC.Generation = oldIC.Generation + 1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Validate validates a new mutatingWebhookConfiguration.
 | 
				
			||||||
 | 
					func (mutatingWebhookConfigurationStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
 | 
				
			||||||
 | 
						ic := obj.(*admissionregistration.MutatingWebhookConfiguration)
 | 
				
			||||||
 | 
						return validation.ValidateMutatingWebhookConfiguration(ic)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Canonicalize normalizes the object after validation.
 | 
				
			||||||
 | 
					func (mutatingWebhookConfigurationStrategy) Canonicalize(obj runtime.Object) {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AllowCreateOnUpdate is true for mutatingWebhookConfiguration; this means you may create one with a PUT request.
 | 
				
			||||||
 | 
					func (mutatingWebhookConfigurationStrategy) AllowCreateOnUpdate() bool {
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateUpdate is the default update validation for an end user.
 | 
				
			||||||
 | 
					func (mutatingWebhookConfigurationStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
 | 
				
			||||||
 | 
						validationErrorList := validation.ValidateMutatingWebhookConfiguration(obj.(*admissionregistration.MutatingWebhookConfiguration))
 | 
				
			||||||
 | 
						updateErrorList := validation.ValidateMutatingWebhookConfigurationUpdate(obj.(*admissionregistration.MutatingWebhookConfiguration), old.(*admissionregistration.MutatingWebhookConfiguration))
 | 
				
			||||||
 | 
						return append(validationErrorList, updateErrorList...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AllowUnconditionalUpdate is the default update policy for mutatingWebhookConfiguration objects. Status update should
 | 
				
			||||||
 | 
					// only be allowed if version match.
 | 
				
			||||||
 | 
					func (mutatingWebhookConfigurationStrategy) AllowUnconditionalUpdate() bool {
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -25,6 +25,7 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/api/legacyscheme"
 | 
						"k8s.io/kubernetes/pkg/api/legacyscheme"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/apis/admissionregistration"
 | 
						"k8s.io/kubernetes/pkg/apis/admissionregistration"
 | 
				
			||||||
	initializerconfigurationstorage "k8s.io/kubernetes/pkg/registry/admissionregistration/initializerconfiguration/storage"
 | 
						initializerconfigurationstorage "k8s.io/kubernetes/pkg/registry/admissionregistration/initializerconfiguration/storage"
 | 
				
			||||||
 | 
						mutatingwebhookconfigurationstorage "k8s.io/kubernetes/pkg/registry/admissionregistration/mutatingwebhookconfiguration/storage"
 | 
				
			||||||
	validatingwebhookconfigurationstorage "k8s.io/kubernetes/pkg/registry/admissionregistration/validatingwebhookconfiguration/storage"
 | 
						validatingwebhookconfigurationstorage "k8s.io/kubernetes/pkg/registry/admissionregistration/validatingwebhookconfiguration/storage"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -53,6 +54,10 @@ func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstora
 | 
				
			|||||||
		s := validatingwebhookconfigurationstorage.NewREST(restOptionsGetter)
 | 
							s := validatingwebhookconfigurationstorage.NewREST(restOptionsGetter)
 | 
				
			||||||
		storage["validatingwebhookconfigurations"] = s
 | 
							storage["validatingwebhookconfigurations"] = s
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if apiResourceConfigSource.ResourceEnabled(version.WithResource("mutatingwebhookconfigurations")) {
 | 
				
			||||||
 | 
							s := mutatingwebhookconfigurationstorage.NewREST(restOptionsGetter)
 | 
				
			||||||
 | 
							storage["mutatingwebhookconfigurations"] = s
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return storage
 | 
						return storage
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,7 +79,7 @@ func (validatingWebhookConfigurationStrategy) AllowCreateOnUpdate() bool {
 | 
				
			|||||||
// ValidateUpdate is the default update validation for an end user.
 | 
					// ValidateUpdate is the default update validation for an end user.
 | 
				
			||||||
func (validatingWebhookConfigurationStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
 | 
					func (validatingWebhookConfigurationStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
 | 
				
			||||||
	validationErrorList := validation.ValidateValidatingWebhookConfiguration(obj.(*admissionregistration.ValidatingWebhookConfiguration))
 | 
						validationErrorList := validation.ValidateValidatingWebhookConfiguration(obj.(*admissionregistration.ValidatingWebhookConfiguration))
 | 
				
			||||||
	updateErrorList := validation.ValidateValidatingwebhookConfigurationUpdate(obj.(*admissionregistration.ValidatingWebhookConfiguration), old.(*admissionregistration.ValidatingWebhookConfiguration))
 | 
						updateErrorList := validation.ValidateValidatingWebhookConfigurationUpdate(obj.(*admissionregistration.ValidatingWebhookConfiguration), old.(*admissionregistration.ValidatingWebhookConfiguration))
 | 
				
			||||||
	return append(validationErrorList, updateErrorList...)
 | 
						return append(validationErrorList, updateErrorList...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,6 +47,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
 | 
				
			|||||||
		&InitializerConfigurationList{},
 | 
							&InitializerConfigurationList{},
 | 
				
			||||||
		&ValidatingWebhookConfiguration{},
 | 
							&ValidatingWebhookConfiguration{},
 | 
				
			||||||
		&ValidatingWebhookConfigurationList{},
 | 
							&ValidatingWebhookConfigurationList{},
 | 
				
			||||||
 | 
							&MutatingWebhookConfiguration{},
 | 
				
			||||||
 | 
							&MutatingWebhookConfigurationList{},
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
 | 
						metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -130,7 +130,7 @@ type ValidatingWebhookConfiguration struct {
 | 
				
			|||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	// +patchMergeKey=name
 | 
						// +patchMergeKey=name
 | 
				
			||||||
	// +patchStrategy=merge
 | 
						// +patchStrategy=merge
 | 
				
			||||||
	Webhooks []Webhook `json:"Webhooks,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,2,rep,name=Webhooks"`
 | 
						Webhooks []Webhook `json:"webhooks,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,2,rep,name=Webhooks"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
					// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
				
			||||||
@@ -146,6 +146,36 @@ type ValidatingWebhookConfigurationList struct {
 | 
				
			|||||||
	Items []ValidatingWebhookConfiguration `json:"items" protobuf:"bytes,2,rep,name=items"`
 | 
						Items []ValidatingWebhookConfiguration `json:"items" protobuf:"bytes,2,rep,name=items"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// +genclient
 | 
				
			||||||
 | 
					// +genclient:nonNamespaced
 | 
				
			||||||
 | 
					// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MutatingWebhookConfiguration describes the configuration of and admission webhook that accept or reject and may change the object.
 | 
				
			||||||
 | 
					type MutatingWebhookConfiguration struct {
 | 
				
			||||||
 | 
						metav1.TypeMeta `json:",inline"`
 | 
				
			||||||
 | 
						// Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata.
 | 
				
			||||||
 | 
						// +optional
 | 
				
			||||||
 | 
						metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
 | 
				
			||||||
 | 
						// Webhooks is a list of webhooks and the affected resources and operations.
 | 
				
			||||||
 | 
						// +optional
 | 
				
			||||||
 | 
						// +patchMergeKey=name
 | 
				
			||||||
 | 
						// +patchStrategy=merge
 | 
				
			||||||
 | 
						Webhooks []Webhook `json:"webhooks,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,2,rep,name=Webhooks"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MutatingWebhookConfigurationList is a list of MutatingWebhookConfiguration.
 | 
				
			||||||
 | 
					type MutatingWebhookConfigurationList struct {
 | 
				
			||||||
 | 
						metav1.TypeMeta `json:",inline"`
 | 
				
			||||||
 | 
						// Standard list metadata.
 | 
				
			||||||
 | 
						// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
 | 
				
			||||||
 | 
						// +optional
 | 
				
			||||||
 | 
						metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
 | 
				
			||||||
 | 
						// List of MutatingWebhookConfiguration.
 | 
				
			||||||
 | 
						Items []MutatingWebhookConfiguration `json:"items" protobuf:"bytes,2,rep,name=items"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Webhook describes an admission webhook and the resources and operations it applies to.
 | 
					// Webhook describes an admission webhook and the resources and operations it applies to.
 | 
				
			||||||
type Webhook struct {
 | 
					type Webhook struct {
 | 
				
			||||||
	// The name of the admission webhook.
 | 
						// The name of the admission webhook.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,101 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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"
 | 
				
			||||||
 | 
						"sort"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"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 MutatingWebhookConfigurationLister interface {
 | 
				
			||||||
 | 
						List(opts metav1.ListOptions) (*v1alpha1.MutatingWebhookConfigurationList, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MutatingWebhookConfigurationManager collects the mutating webhook objects so that they can be called.
 | 
				
			||||||
 | 
					type MutatingWebhookConfigurationManager struct {
 | 
				
			||||||
 | 
						*poller
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewMutatingWebhookConfigurationManager(c MutatingWebhookConfigurationLister) *MutatingWebhookConfigurationManager {
 | 
				
			||||||
 | 
						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("MutatingWebhookConfiguration are disabled due to an error: %v", err)
 | 
				
			||||||
 | 
									return nil, ErrDisabled
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return mergeMutatingWebhookConfigurations(list), nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &MutatingWebhookConfigurationManager{
 | 
				
			||||||
 | 
							newPoller(getFn),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Webhooks returns the merged MutatingWebhookConfiguration.
 | 
				
			||||||
 | 
					func (im *MutatingWebhookConfigurationManager) Webhooks() (*v1alpha1.MutatingWebhookConfiguration, error) {
 | 
				
			||||||
 | 
						configuration, err := im.poller.configuration()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						mutatingWebhookConfiguration, ok := configuration.(*v1alpha1.MutatingWebhookConfiguration)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("expected type %v, got type %v", reflect.TypeOf(mutatingWebhookConfiguration), reflect.TypeOf(configuration))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return mutatingWebhookConfiguration, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (im *MutatingWebhookConfigurationManager) Run(stopCh <-chan struct{}) {
 | 
				
			||||||
 | 
						im.poller.Run(stopCh)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func mergeMutatingWebhookConfigurations(
 | 
				
			||||||
 | 
						list *v1alpha1.MutatingWebhookConfigurationList,
 | 
				
			||||||
 | 
					) *v1alpha1.MutatingWebhookConfiguration {
 | 
				
			||||||
 | 
						configurations := append([]v1alpha1.MutatingWebhookConfiguration{}, list.Items...)
 | 
				
			||||||
 | 
						var ret v1alpha1.MutatingWebhookConfiguration
 | 
				
			||||||
 | 
						// The internal order of webhooks for each configuration is provided by the user
 | 
				
			||||||
 | 
						// but configurations themselves can be in any order. As we are going to run these
 | 
				
			||||||
 | 
						// webhooks in serial, they are sorted here to have a deterministic order.
 | 
				
			||||||
 | 
						sort.Sort(byName(configurations))
 | 
				
			||||||
 | 
						for _, c := range configurations {
 | 
				
			||||||
 | 
							ret.Webhooks = append(ret.Webhooks, c.Webhooks...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// byName sorts MutatingWebhookConfiguration by name. These objects are all in
 | 
				
			||||||
 | 
					// cluster namespace (aka no namespace) thus they all have unique names.
 | 
				
			||||||
 | 
					type byName []v1alpha1.MutatingWebhookConfiguration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x byName) Len() int { return len(x) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x byName) Less(i, j int) bool {
 | 
				
			||||||
 | 
						return x[i].ObjectMeta.Name < x[j].ObjectMeta.Name
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/api/admissionregistration/v1alpha1"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/api/errors"
 | 
				
			||||||
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/runtime/schema"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type disabledMutatingWebhookConfigLister struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *disabledMutatingWebhookConfigLister) List(options metav1.ListOptions) (*v1alpha1.MutatingWebhookConfigurationList, error) {
 | 
				
			||||||
 | 
						return nil, errors.NewNotFound(schema.GroupResource{Group: "admissionregistration", Resource: "MutatingWebhookConfigurations"}, "")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func TestMutatingWebhookConfigDisabled(t *testing.T) {
 | 
				
			||||||
 | 
						manager := NewMutatingWebhookConfigurationManager(&disabledMutatingWebhookConfigLister{})
 | 
				
			||||||
 | 
						manager.sync()
 | 
				
			||||||
 | 
						_, err := manager.Webhooks()
 | 
				
			||||||
 | 
						if err.Error() != ErrDisabled.Error() {
 | 
				
			||||||
 | 
							t.Errorf("expected %v, got %v", ErrDisabled, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -385,6 +385,10 @@ var etcdStorageData = map[schema.GroupVersionResource]struct {
 | 
				
			|||||||
		stub:             `{"metadata":{"name":"hook1","creationTimestamp":null},"webhooks":[{"name":"externaladmissionhook.k8s.io","clientConfig":{"service":{"namespace":"","name":""},"caBundle":null},"rules":[{"operations":["CREATE"],"apiGroups":["group"],"apiVersions":["version"],"resources":["resource"]}],"failurePolicy":"Ignore"}]}`,
 | 
							stub:             `{"metadata":{"name":"hook1","creationTimestamp":null},"webhooks":[{"name":"externaladmissionhook.k8s.io","clientConfig":{"service":{"namespace":"","name":""},"caBundle":null},"rules":[{"operations":["CREATE"],"apiGroups":["group"],"apiVersions":["version"],"resources":["resource"]}],"failurePolicy":"Ignore"}]}`,
 | 
				
			||||||
		expectedEtcdPath: "/registry/validatingwebhookconfigurations/hook1",
 | 
							expectedEtcdPath: "/registry/validatingwebhookconfigurations/hook1",
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
						gvr("admissionregistration.k8s.io", "v1alpha1", "mutatingwebhookconfigurations"): {
 | 
				
			||||||
 | 
							stub:             `{"metadata":{"name":"hook1","creationTimestamp":null},"webhooks":[{"name":"externaladmissionhook.k8s.io","clientConfig":{"service":{"namespace":"","name":""},"caBundle":null},"rules":[{"operations":["CREATE"],"apiGroups":["group"],"apiVersions":["version"],"resources":["resource"]}],"failurePolicy":"Ignore"}]}`,
 | 
				
			||||||
 | 
							expectedEtcdPath: "/registry/mutatingwebhookconfigurations/hook1",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
	// --
 | 
						// --
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1
 | 
						// k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user