Limit v1 webhooks to None and NoneOnDryRun side effects classes

This commit is contained in:
Jordan Liggitt 2019-08-06 18:18:04 -04:00
parent 16d9a659da
commit 190c926d1f
4 changed files with 297 additions and 143 deletions

View File

@ -167,7 +167,7 @@ func isAcceptedAdmissionReviewVersion(v string) bool {
return false
}
func validateAdmissionReviewVersions(versions []string, requireRecognizedVersion bool, fldPath *field.Path) field.ErrorList {
func validateAdmissionReviewVersions(versions []string, requireRecognizedAdmissionReviewVersion bool, fldPath *field.Path) field.ErrorList {
allErrors := field.ErrorList{}
// Currently only v1beta1 accepted in AdmissionReviewVersions
@ -189,7 +189,7 @@ func validateAdmissionReviewVersions(versions []string, requireRecognizedVersion
hasAcceptedVersion = true
}
}
if requireRecognizedVersion && !hasAcceptedVersion {
if requireRecognizedAdmissionReviewVersion && !hasAcceptedVersion {
allErrors = append(allErrors, field.Invalid(
fldPath, versions,
fmt.Sprintf("must include at least one of %v",
@ -201,16 +201,20 @@ func validateAdmissionReviewVersions(versions []string, requireRecognizedVersion
// ValidateValidatingWebhookConfiguration validates a webhook before creation.
func ValidateValidatingWebhookConfiguration(e *admissionregistration.ValidatingWebhookConfiguration, requestGV schema.GroupVersion) field.ErrorList {
return validateValidatingWebhookConfiguration(e, true, requireUniqueWebhookNames(requestGV))
return validateValidatingWebhookConfiguration(e, validationOptions{
requireNoSideEffects: requireNoSideEffects(requestGV),
requireRecognizedAdmissionReviewVersion: true,
requireUniqueWebhookNames: requireUniqueWebhookNames(requestGV),
})
}
func validateValidatingWebhookConfiguration(e *admissionregistration.ValidatingWebhookConfiguration, requireRecognizedVersion, requireUniqueWebhookNames bool) field.ErrorList {
func validateValidatingWebhookConfiguration(e *admissionregistration.ValidatingWebhookConfiguration, opts validationOptions) field.ErrorList {
allErrors := genericvalidation.ValidateObjectMeta(&e.ObjectMeta, false, genericvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
hookNames := sets.NewString()
for i, hook := range e.Webhooks {
allErrors = append(allErrors, validateValidatingWebhook(&hook, field.NewPath("webhooks").Index(i))...)
allErrors = append(allErrors, validateAdmissionReviewVersions(hook.AdmissionReviewVersions, requireRecognizedVersion, field.NewPath("webhooks").Index(i).Child("admissionReviewVersions"))...)
if requireUniqueWebhookNames && len(hook.Name) > 0 {
allErrors = append(allErrors, validateValidatingWebhook(&hook, opts, field.NewPath("webhooks").Index(i))...)
allErrors = append(allErrors, validateAdmissionReviewVersions(hook.AdmissionReviewVersions, opts.requireRecognizedAdmissionReviewVersion, field.NewPath("webhooks").Index(i).Child("admissionReviewVersions"))...)
if opts.requireUniqueWebhookNames && len(hook.Name) > 0 {
if hookNames.Has(hook.Name) {
allErrors = append(allErrors, field.Duplicate(field.NewPath("webhooks").Index(i).Child("name"), hook.Name))
}
@ -222,16 +226,26 @@ func validateValidatingWebhookConfiguration(e *admissionregistration.ValidatingW
// ValidateMutatingWebhookConfiguration validates a webhook before creation.
func ValidateMutatingWebhookConfiguration(e *admissionregistration.MutatingWebhookConfiguration, requestGV schema.GroupVersion) field.ErrorList {
return validateMutatingWebhookConfiguration(e, true, requireUniqueWebhookNames(requestGV))
return validateMutatingWebhookConfiguration(e, validationOptions{
requireNoSideEffects: requireNoSideEffects(requestGV),
requireRecognizedAdmissionReviewVersion: true,
requireUniqueWebhookNames: requireUniqueWebhookNames(requestGV),
})
}
func validateMutatingWebhookConfiguration(e *admissionregistration.MutatingWebhookConfiguration, requireRecognizedVersion, requireUniqueWebhookNames bool) field.ErrorList {
type validationOptions struct {
requireNoSideEffects bool
requireRecognizedAdmissionReviewVersion bool
requireUniqueWebhookNames bool
}
func validateMutatingWebhookConfiguration(e *admissionregistration.MutatingWebhookConfiguration, opts validationOptions) field.ErrorList {
allErrors := genericvalidation.ValidateObjectMeta(&e.ObjectMeta, false, genericvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
hookNames := sets.NewString()
for i, hook := range e.Webhooks {
allErrors = append(allErrors, validateMutatingWebhook(&hook, field.NewPath("webhooks").Index(i))...)
allErrors = append(allErrors, validateAdmissionReviewVersions(hook.AdmissionReviewVersions, requireRecognizedVersion, field.NewPath("webhooks").Index(i).Child("admissionReviewVersions"))...)
if requireUniqueWebhookNames && len(hook.Name) > 0 {
allErrors = append(allErrors, validateMutatingWebhook(&hook, opts, field.NewPath("webhooks").Index(i))...)
allErrors = append(allErrors, validateAdmissionReviewVersions(hook.AdmissionReviewVersions, opts.requireRecognizedAdmissionReviewVersion, field.NewPath("webhooks").Index(i).Child("admissionReviewVersions"))...)
if opts.requireUniqueWebhookNames && len(hook.Name) > 0 {
if hookNames.Has(hook.Name) {
allErrors = append(allErrors, field.Duplicate(field.NewPath("webhooks").Index(i).Child("name"), hook.Name))
}
@ -241,7 +255,7 @@ func validateMutatingWebhookConfiguration(e *admissionregistration.MutatingWebho
return allErrors
}
func validateValidatingWebhook(hook *admissionregistration.ValidatingWebhook, fldPath *field.Path) field.ErrorList {
func validateValidatingWebhook(hook *admissionregistration.ValidatingWebhook, opts validationOptions, fldPath *field.Path) field.ErrorList {
var allErrors field.ErrorList
// hook.Name must be fully qualified
allErrors = append(allErrors, utilvalidation.IsFullyQualifiedName(fldPath.Child("name"), hook.Name)...)
@ -255,11 +269,15 @@ func validateValidatingWebhook(hook *admissionregistration.ValidatingWebhook, fl
if hook.MatchPolicy != nil && !supportedMatchPolicies.Has(string(*hook.MatchPolicy)) {
allErrors = append(allErrors, field.NotSupported(fldPath.Child("matchPolicy"), *hook.MatchPolicy, supportedMatchPolicies.List()))
}
if hook.SideEffects == nil {
allErrors = append(allErrors, field.Required(fldPath.Child("sideEffects"), fmt.Sprintf("must specify one of %v", strings.Join(supportedSideEffectClasses.List(), ", "))))
allowedSideEffects := supportedSideEffectClasses
if opts.requireNoSideEffects {
allowedSideEffects = noSideEffectClasses
}
if hook.SideEffects != nil && !supportedSideEffectClasses.Has(string(*hook.SideEffects)) {
allErrors = append(allErrors, field.NotSupported(fldPath.Child("sideEffects"), *hook.SideEffects, supportedSideEffectClasses.List()))
if hook.SideEffects == nil {
allErrors = append(allErrors, field.Required(fldPath.Child("sideEffects"), fmt.Sprintf("must specify one of %v", strings.Join(allowedSideEffects.List(), ", "))))
}
if hook.SideEffects != nil && !allowedSideEffects.Has(string(*hook.SideEffects)) {
allErrors = append(allErrors, field.NotSupported(fldPath.Child("sideEffects"), *hook.SideEffects, allowedSideEffects.List()))
}
if hook.TimeoutSeconds != nil && (*hook.TimeoutSeconds > 30 || *hook.TimeoutSeconds < 1) {
allErrors = append(allErrors, field.Invalid(fldPath.Child("timeoutSeconds"), *hook.TimeoutSeconds, "the timeout value must be between 1 and 30 seconds"))
@ -285,7 +303,7 @@ func validateValidatingWebhook(hook *admissionregistration.ValidatingWebhook, fl
return allErrors
}
func validateMutatingWebhook(hook *admissionregistration.MutatingWebhook, fldPath *field.Path) field.ErrorList {
func validateMutatingWebhook(hook *admissionregistration.MutatingWebhook, opts validationOptions, fldPath *field.Path) field.ErrorList {
var allErrors field.ErrorList
// hook.Name must be fully qualified
allErrors = append(allErrors, utilvalidation.IsFullyQualifiedName(fldPath.Child("name"), hook.Name)...)
@ -299,11 +317,15 @@ func validateMutatingWebhook(hook *admissionregistration.MutatingWebhook, fldPat
if hook.MatchPolicy != nil && !supportedMatchPolicies.Has(string(*hook.MatchPolicy)) {
allErrors = append(allErrors, field.NotSupported(fldPath.Child("matchPolicy"), *hook.MatchPolicy, supportedMatchPolicies.List()))
}
if hook.SideEffects == nil {
allErrors = append(allErrors, field.Required(fldPath.Child("sideEffects"), fmt.Sprintf("must specify one of %v", strings.Join(supportedSideEffectClasses.List(), ", "))))
allowedSideEffects := supportedSideEffectClasses
if opts.requireNoSideEffects {
allowedSideEffects = noSideEffectClasses
}
if hook.SideEffects != nil && !supportedSideEffectClasses.Has(string(*hook.SideEffects)) {
allErrors = append(allErrors, field.NotSupported(fldPath.Child("sideEffects"), *hook.SideEffects, supportedSideEffectClasses.List()))
if hook.SideEffects == nil {
allErrors = append(allErrors, field.Required(fldPath.Child("sideEffects"), fmt.Sprintf("must specify one of %v", strings.Join(allowedSideEffects.List(), ", "))))
}
if hook.SideEffects != nil && !allowedSideEffects.Has(string(*hook.SideEffects)) {
allErrors = append(allErrors, field.NotSupported(fldPath.Child("sideEffects"), *hook.SideEffects, allowedSideEffects.List()))
}
if hook.TimeoutSeconds != nil && (*hook.TimeoutSeconds > 30 || *hook.TimeoutSeconds < 1) {
allErrors = append(allErrors, field.Invalid(fldPath.Child("timeoutSeconds"), *hook.TimeoutSeconds, "the timeout value must be between 1 and 30 seconds"))
@ -348,6 +370,11 @@ var supportedSideEffectClasses = sets.NewString(
string(admissionregistration.SideEffectClassNoneOnDryRun),
)
var noSideEffectClasses = sets.NewString(
string(admissionregistration.SideEffectClassNone),
string(admissionregistration.SideEffectClassNoneOnDryRun),
)
var supportedOperations = sets.NewString(
string(admissionregistration.OperationAll),
string(admissionregistration.Create),
@ -448,23 +475,48 @@ func validatingHasUniqueWebhookNames(webhooks []admissionregistration.Validating
return true
}
// mutatingHasNoSideEffects returns true if all webhooks have no side effects
func mutatingHasNoSideEffects(webhooks []admissionregistration.MutatingWebhook) bool {
for _, hook := range webhooks {
if hook.SideEffects == nil || !noSideEffectClasses.Has(string(*hook.SideEffects)) {
return false
}
}
return true
}
// validatingHasNoSideEffects returns true if all webhooks have no side effects
func validatingHasNoSideEffects(webhooks []admissionregistration.ValidatingWebhook) bool {
for _, hook := range webhooks {
if hook.SideEffects == nil || !noSideEffectClasses.Has(string(*hook.SideEffects)) {
return false
}
}
return true
}
func ValidateValidatingWebhookConfigurationUpdate(newC, oldC *admissionregistration.ValidatingWebhookConfiguration, requestGV schema.GroupVersion) field.ErrorList {
return validateValidatingWebhookConfiguration(
newC,
validatingHasAcceptedAdmissionReviewVersions(oldC.Webhooks),
requireUniqueWebhookNames(requestGV) && validatingHasUniqueWebhookNames(oldC.Webhooks),
)
return validateValidatingWebhookConfiguration(newC, validationOptions{
requireNoSideEffects: requireNoSideEffects(requestGV) && validatingHasNoSideEffects(oldC.Webhooks),
requireRecognizedAdmissionReviewVersion: validatingHasAcceptedAdmissionReviewVersions(oldC.Webhooks),
requireUniqueWebhookNames: requireUniqueWebhookNames(requestGV) && validatingHasUniqueWebhookNames(oldC.Webhooks),
})
}
func ValidateMutatingWebhookConfigurationUpdate(newC, oldC *admissionregistration.MutatingWebhookConfiguration, requestGV schema.GroupVersion) field.ErrorList {
return validateMutatingWebhookConfiguration(
newC,
mutatingHasAcceptedAdmissionReviewVersions(oldC.Webhooks),
requireUniqueWebhookNames(requestGV) && mutatingHasUniqueWebhookNames(oldC.Webhooks),
)
return validateMutatingWebhookConfiguration(newC, validationOptions{
requireNoSideEffects: requireNoSideEffects(requestGV) && mutatingHasNoSideEffects(oldC.Webhooks),
requireRecognizedAdmissionReviewVersion: mutatingHasAcceptedAdmissionReviewVersions(oldC.Webhooks),
requireUniqueWebhookNames: requireUniqueWebhookNames(requestGV) && mutatingHasUniqueWebhookNames(oldC.Webhooks),
})
}
// requireUniqueWebhookNames returns true for all requests except v1beta1 (for backwards compatibility)
func requireUniqueWebhookNames(requestGV schema.GroupVersion) bool {
return requestGV != (schema.GroupVersion{Group: admissionregistration.GroupName, Version: "v1beta1"})
}
// requireNoSideEffects returns true for all requests except v1beta1 (for backwards compatibility)
func requireNoSideEffects(requestGV schema.GroupVersion) bool {
return requestGV != (schema.GroupVersion{Group: admissionregistration.GroupName, Version: "v1beta1"})
}

View File

@ -47,7 +47,6 @@ func newValidatingWebhookConfiguration(hooks []admissionregistration.ValidatingW
func TestValidateValidatingWebhookConfiguration(t *testing.T) {
unknownSideEffect := admissionregistration.SideEffectClassUnknown
validSideEffect := &unknownSideEffect
validClientConfig := admissionregistration.WebhookClientConfig{
URL: strPtr("https://example.com"),
}
@ -63,7 +62,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, false),
expectedError: `webhooks[0].admissionReviewVersions: Required value: must specify one of v1beta1`,
@ -84,10 +83,11 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"v1beta1"},
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
expectedError: ``,
},
{
@ -96,10 +96,11 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"v1beta1", "invalid-version"},
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
expectedError: ``,
},
{
@ -130,19 +131,20 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
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`,
},
{
@ -151,12 +153,12 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "foo", Version: "bar"},
@ -168,12 +170,12 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
@ -269,7 +271,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
Rules: []admissionregistration.RuleWithOperations{
{
Operations: []admissionregistration.OperationType{"CREATE"},
@ -282,6 +284,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
},
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
},
{
name: `resource "*" cannot mix with resources that don't have subresources`,
@ -289,7 +292,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
Rules: []admissionregistration.RuleWithOperations{
{
Operations: []admissionregistration.OperationType{"CREATE"},
@ -310,7 +313,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
Rules: []admissionregistration.RuleWithOperations{
{
Operations: []admissionregistration.OperationType{"CREATE"},
@ -331,7 +334,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
Rules: []admissionregistration.RuleWithOperations{
{
Operations: []admissionregistration.OperationType{"CREATE"},
@ -344,6 +347,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
},
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
},
{
name: "resource */a cannot mix with x/a",
@ -351,7 +355,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
Rules: []admissionregistration.RuleWithOperations{
{
Operations: []admissionregistration.OperationType{"CREATE"},
@ -372,7 +376,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
Rules: []admissionregistration.RuleWithOperations{
{
Operations: []admissionregistration.OperationType{"CREATE"},
@ -393,7 +397,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
FailurePolicy: func() *admissionregistration.FailurePolicyType {
r := admissionregistration.FailurePolicyType("other")
return &r
@ -408,7 +412,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, false),
expectedError: `webhooks[0].admissionReviewVersions: Required value: must specify one of v1beta1`,
@ -422,10 +426,10 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
SideEffects: nil,
},
}, true),
expectedError: `webhooks[0].sideEffects: Required value: must specify one of None, NoneOnDryRun, Some, Unknown`,
expectedError: `webhooks[0].sideEffects: Required value: must specify one of None, NoneOnDryRun`,
},
{
name: "SideEffects can only be \"Unknown\", \"None\", \"Some\", or \"NoneOnDryRun\"",
name: "SideEffects can only be \"Unknown\", \"None\", \"Some\", or \"NoneOnDryRun\" via v1beta1",
config: newValidatingWebhookConfiguration([]admissionregistration.ValidatingWebhook{
{
Name: "webhook.k8s.io",
@ -436,8 +440,24 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
}(),
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
expectedError: `webhooks[0].sideEffects: Unsupported value: "other": supported values: "None", "NoneOnDryRun", "Some", "Unknown"`,
},
{
name: "SideEffects can only be \"None\" or \"NoneOnDryRun\" via v1",
config: newValidatingWebhookConfiguration([]admissionregistration.ValidatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: func() *admissionregistration.SideEffectClass {
r := admissionregistration.SideEffectClass("other")
return &r
}(),
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1"},
expectedError: `webhooks[0].sideEffects: Unsupported value: "other": supported values: "None", "NoneOnDryRun"`,
},
{
name: "both service and URL missing",
config: newValidatingWebhookConfiguration([]admissionregistration.ValidatingWebhook{
@ -579,9 +599,10 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Port: 443,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
expectedError: ``,
},
{
@ -597,9 +618,10 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Port: 443,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
expectedError: ``,
},
{
@ -615,7 +637,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Port: 443,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: `clientConfig.service.path: Invalid value: "//": segment[0] may not be empty`,
@ -633,7 +655,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Port: 443,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: `clientConfig.service.path: Invalid value: "/foo//bar/": segment[1] may not be empty`,
@ -650,7 +672,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Port: 443,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: `clientConfig.service.path: Invalid value: "/foo/bar//": segment[2] may not be empty`,
@ -668,7 +690,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Port: 443,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: `clientConfig.service.path: Invalid value: "/apis/foo.bar/v1alpha1/--bad": segment[3]: a DNS-1123 subdomain`,
@ -687,7 +709,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Port: 0,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: `Invalid value: 0: port is not valid: must be between 1 and 65535, inclusive`,
@ -706,7 +728,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Port: 65536,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: `Invalid value: 65536: port is not valid: must be between 1 and 65535, inclusive`,
@ -717,7 +739,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
TimeoutSeconds: int32Ptr(31),
},
}, true),
@ -729,7 +751,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
TimeoutSeconds: int32Ptr(0),
},
}, true),
@ -741,7 +763,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
TimeoutSeconds: int32Ptr(-1),
},
}, true),
@ -753,22 +775,23 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
TimeoutSeconds: int32Ptr(1),
},
{
Name: "webhook2.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
TimeoutSeconds: int32Ptr(15),
},
{
Name: "webhook3.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
TimeoutSeconds: int32Ptr(30),
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
},
}
for _, test := range tests {
@ -791,7 +814,6 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
func TestValidateValidatingWebhookConfigurationUpdate(t *testing.T) {
unknownSideEffect := admissionregistration.SideEffectClassUnknown
validSideEffect := &unknownSideEffect
validClientConfig := admissionregistration.WebhookClientConfig{
URL: strPtr("https://example.com"),
}
@ -808,7 +830,7 @@ func TestValidateValidatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"v1beta1"},
},
}, true),
@ -816,7 +838,7 @@ func TestValidateValidatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: ``,
@ -827,7 +849,7 @@ func TestValidateValidatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"invalid-v1", "invalid-v2"},
},
}, true),
@ -835,7 +857,7 @@ func TestValidateValidatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"invalid-v0"},
},
}, true),
@ -847,7 +869,7 @@ func TestValidateValidatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"invalid-v1"},
},
}, true),
@ -855,7 +877,7 @@ func TestValidateValidatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"v1beta1", "invalid-v1"},
},
}, true),
@ -867,7 +889,7 @@ func TestValidateValidatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"invalid-v1"},
},
}, true),
@ -875,7 +897,7 @@ func TestValidateValidatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, false),
expectedError: `Invalid value: []string{"invalid-v1"}`,
@ -886,19 +908,19 @@ func TestValidateValidatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
oldconfig: newValidatingWebhookConfiguration([]admissionregistration.ValidatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, false),
gv: schema.GroupVersion{Group: "foo", Version: "bar"},
@ -910,24 +932,24 @@ func TestValidateValidatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
oldconfig: newValidatingWebhookConfiguration([]admissionregistration.ValidatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "foo", Version: "bar"},
@ -939,19 +961,19 @@ func TestValidateValidatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
oldconfig: newValidatingWebhookConfiguration([]admissionregistration.ValidatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, false),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
@ -994,7 +1016,6 @@ func newMutatingWebhookConfiguration(hooks []admissionregistration.MutatingWebho
func TestValidateMutatingWebhookConfiguration(t *testing.T) {
unknownSideEffect := admissionregistration.SideEffectClassUnknown
validSideEffect := &unknownSideEffect
validClientConfig := admissionregistration.WebhookClientConfig{
URL: strPtr("https://example.com"),
}
@ -1010,7 +1031,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, false),
expectedError: `webhooks[0].admissionReviewVersions: Required value: must specify one of v1beta1`,
@ -1031,10 +1052,11 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"v1beta1"},
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
expectedError: ``,
},
{
@ -1043,10 +1065,11 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"v1beta1", "invalid-version"},
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
expectedError: ``,
},
{
@ -1077,19 +1100,20 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
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`,
},
{
@ -1098,12 +1122,12 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "foo", Version: "bar"},
@ -1115,12 +1139,12 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
@ -1216,7 +1240,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
Rules: []admissionregistration.RuleWithOperations{
{
Operations: []admissionregistration.OperationType{"CREATE"},
@ -1229,6 +1253,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
},
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
},
{
name: `resource "*" cannot mix with resources that don't have subresources`,
@ -1236,7 +1261,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
Rules: []admissionregistration.RuleWithOperations{
{
Operations: []admissionregistration.OperationType{"CREATE"},
@ -1257,7 +1282,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
Rules: []admissionregistration.RuleWithOperations{
{
Operations: []admissionregistration.OperationType{"CREATE"},
@ -1278,7 +1303,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
Rules: []admissionregistration.RuleWithOperations{
{
Operations: []admissionregistration.OperationType{"CREATE"},
@ -1291,6 +1316,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
},
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
},
{
name: "resource */a cannot mix with x/a",
@ -1298,7 +1324,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
Rules: []admissionregistration.RuleWithOperations{
{
Operations: []admissionregistration.OperationType{"CREATE"},
@ -1319,7 +1345,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
Rules: []admissionregistration.RuleWithOperations{
{
Operations: []admissionregistration.OperationType{"CREATE"},
@ -1340,7 +1366,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
FailurePolicy: func() *admissionregistration.FailurePolicyType {
r := admissionregistration.FailurePolicyType("other")
return &r
@ -1355,7 +1381,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, false),
expectedError: `webhooks[0].admissionReviewVersions: Required value: must specify one of v1beta1`,
@ -1369,10 +1395,10 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
SideEffects: nil,
},
}, true),
expectedError: `webhooks[0].sideEffects: Required value: must specify one of None, NoneOnDryRun, Some, Unknown`,
expectedError: `webhooks[0].sideEffects: Required value: must specify one of None, NoneOnDryRun`,
},
{
name: "SideEffects can only be \"Unknown\", \"None\", \"Some\", or \"NoneOnDryRun\"",
name: "SideEffects can only be \"Unknown\", \"None\", \"Some\", or \"NoneOnDryRun\" via v1beta1",
config: newMutatingWebhookConfiguration([]admissionregistration.MutatingWebhook{
{
Name: "webhook.k8s.io",
@ -1383,8 +1409,24 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
}(),
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
expectedError: `webhooks[0].sideEffects: Unsupported value: "other": supported values: "None", "NoneOnDryRun", "Some", "Unknown"`,
},
{
name: "SideEffects can only be \"None\" or \"NoneOnDryRun\" via v1",
config: newMutatingWebhookConfiguration([]admissionregistration.MutatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: func() *admissionregistration.SideEffectClass {
r := admissionregistration.SideEffectClass("other")
return &r
}(),
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1"},
expectedError: `webhooks[0].sideEffects: Unsupported value: "other": supported values: "None", "NoneOnDryRun"`,
},
{
name: "both service and URL missing",
config: newMutatingWebhookConfiguration([]admissionregistration.MutatingWebhook{
@ -1526,9 +1568,10 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
Port: 443,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
expectedError: ``,
},
{
@ -1544,9 +1587,10 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
Port: 443,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
expectedError: ``,
},
{
@ -1562,7 +1606,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
Port: 443,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: `clientConfig.service.path: Invalid value: "//": segment[0] may not be empty`,
@ -1580,7 +1624,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
Port: 443,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: `clientConfig.service.path: Invalid value: "/foo//bar/": segment[1] may not be empty`,
@ -1597,7 +1641,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
Port: 443,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: `clientConfig.service.path: Invalid value: "/foo/bar//": segment[2] may not be empty`,
@ -1615,7 +1659,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
Port: 443,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: `clientConfig.service.path: Invalid value: "/apis/foo.bar/v1alpha1/--bad": segment[3]: a DNS-1123 subdomain`,
@ -1634,7 +1678,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
Port: 0,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: `Invalid value: 0: port is not valid: must be between 1 and 65535, inclusive`,
@ -1653,7 +1697,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
Port: 65536,
},
},
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: `Invalid value: 65536: port is not valid: must be between 1 and 65535, inclusive`,
@ -1664,7 +1708,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
TimeoutSeconds: int32Ptr(31),
},
}, true),
@ -1676,7 +1720,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
TimeoutSeconds: int32Ptr(0),
},
}, true),
@ -1688,7 +1732,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
TimeoutSeconds: int32Ptr(-1),
},
}, true),
@ -1700,22 +1744,23 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
TimeoutSeconds: int32Ptr(1),
},
{
Name: "webhook2.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
TimeoutSeconds: int32Ptr(15),
},
{
Name: "webhook3.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
TimeoutSeconds: int32Ptr(30),
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
},
}
for _, test := range tests {
@ -1738,7 +1783,7 @@ func TestValidateMutatingWebhookConfiguration(t *testing.T) {
func TestValidateMutatingWebhookConfigurationUpdate(t *testing.T) {
unknownSideEffect := admissionregistration.SideEffectClassUnknown
validSideEffect := &unknownSideEffect
noSideEffect := admissionregistration.SideEffectClassNone
validClientConfig := admissionregistration.WebhookClientConfig{
URL: strPtr("https://example.com"),
}
@ -1755,7 +1800,7 @@ func TestValidateMutatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"v1beta1"},
},
}, true),
@ -1763,7 +1808,7 @@ func TestValidateMutatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
expectedError: ``,
@ -1774,7 +1819,7 @@ func TestValidateMutatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"invalid-v1", "invalid-v2"},
},
}, true),
@ -1782,7 +1827,7 @@ func TestValidateMutatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"invalid-v0"},
},
}, true),
@ -1794,7 +1839,7 @@ func TestValidateMutatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"invalid-v1"},
},
}, true),
@ -1802,7 +1847,7 @@ func TestValidateMutatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"v1beta1", "invalid-v1"},
},
}, true),
@ -1814,7 +1859,7 @@ func TestValidateMutatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
AdmissionReviewVersions: []string{"invalid-v1"},
},
}, true),
@ -1822,7 +1867,7 @@ func TestValidateMutatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, false),
expectedError: `Invalid value: []string{"invalid-v1"}`,
@ -1833,24 +1878,24 @@ func TestValidateMutatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
oldconfig: newMutatingWebhookConfiguration([]admissionregistration.MutatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "foo", Version: "bar"},
@ -1862,19 +1907,76 @@ func TestValidateMutatingWebhookConfigurationUpdate(t *testing.T) {
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, true),
oldconfig: newMutatingWebhookConfiguration([]admissionregistration.MutatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: validSideEffect,
SideEffects: &unknownSideEffect,
},
}, false),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},
expectedError: ``,
},
{
name: "Webhooks can't have side effects when old config has no side effects via v1",
config: newMutatingWebhookConfiguration([]admissionregistration.MutatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: &unknownSideEffect,
},
}, true),
oldconfig: newMutatingWebhookConfiguration([]admissionregistration.MutatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: &noSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1"},
expectedError: `Unsupported value: "Unknown": supported values: "None", "NoneOnDryRun"`,
},
{
name: "Webhooks can have side effects when old config has side effects",
config: newMutatingWebhookConfiguration([]admissionregistration.MutatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: &unknownSideEffect,
},
}, true),
oldconfig: newMutatingWebhookConfiguration([]admissionregistration.MutatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: &unknownSideEffect,
},
}, true),
gv: schema.GroupVersion{Group: "foo", Version: "bar"},
expectedError: ``,
},
{
name: "Webhooks can have side effects when updated via v1beta1",
config: newMutatingWebhookConfiguration([]admissionregistration.MutatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: &unknownSideEffect,
},
}, true),
oldconfig: newMutatingWebhookConfiguration([]admissionregistration.MutatingWebhook{
{
Name: "webhook.k8s.io",
ClientConfig: validClientConfig,
SideEffects: &noSideEffect,
},
}, false),
gv: schema.GroupVersion{Group: "admissionregistration.k8s.io", Version: "v1beta1"},

View File

@ -273,8 +273,8 @@ type ValidatingWebhook struct {
// +optional
ObjectSelector *metav1.LabelSelector `json:"objectSelector,omitempty" protobuf:"bytes,10,opt,name=objectSelector"`
// SideEffects states whether this webhookk has side effects.
// Acceptable values are: Unknown, None, Some, NoneOnDryRun
// SideEffects states whether this webhook has side effects.
// Acceptable values are: None, NoneOnDryRun (webhooks created via v1beta1 may also specify Some or Unknown).
// Webhooks with side effects MUST implement a reconciliation system, since a request may be
// rejected by a future step in the admission change and the side effects therefore need to be undone.
// Requests with the dryRun attribute will be auto-rejected if they match a webhook with
@ -402,8 +402,8 @@ type MutatingWebhook struct {
// +optional
ObjectSelector *metav1.LabelSelector `json:"objectSelector,omitempty" protobuf:"bytes,11,opt,name=objectSelector"`
// SideEffects states whether this webhookk has side effects.
// Acceptable values are: Unknown, None, Some, NoneOnDryRun
// SideEffects states whether this webhook has side effects.
// Acceptable values are: None, NoneOnDryRun (webhooks created via v1beta1 may also specify Some or Unknown).
// Webhooks with side effects MUST implement a reconciliation system, since a request may be
// rejected by a future step in the admission change and the side effects therefore need to be undone.
// Requests with the dryRun attribute will be auto-rejected if they match a webhook with

View File

@ -415,12 +415,12 @@ func GetEtcdStorageDataForNamespace(namespace string) map[schema.GroupVersionRes
// k8s.io/kubernetes/pkg/apis/admissionregistration/v1
gvr("admissionregistration.k8s.io", "v1", "validatingwebhookconfigurations"): {
Stub: `{"metadata":{"name":"hook2","creationTimestamp":null},"webhooks":[{"name":"externaladmissionhook.k8s.io","clientConfig":{"service":{"namespace":"ns","name":"n"},"caBundle":null},"rules":[{"operations":["CREATE"],"apiGroups":["group"],"apiVersions":["version"],"resources":["resource"]}],"failurePolicy":"Ignore","sideEffects":"Unknown","admissionReviewVersions":["v1beta1"]}]}`,
Stub: `{"metadata":{"name":"hook2","creationTimestamp":null},"webhooks":[{"name":"externaladmissionhook.k8s.io","clientConfig":{"service":{"namespace":"ns","name":"n"},"caBundle":null},"rules":[{"operations":["CREATE"],"apiGroups":["group"],"apiVersions":["version"],"resources":["resource"]}],"failurePolicy":"Ignore","sideEffects":"None","admissionReviewVersions":["v1beta1"]}]}`,
ExpectedEtcdPath: "/registry/validatingwebhookconfigurations/hook2",
ExpectedGVK: gvkP("admissionregistration.k8s.io", "v1beta1", "ValidatingWebhookConfiguration"),
},
gvr("admissionregistration.k8s.io", "v1", "mutatingwebhookconfigurations"): {
Stub: `{"metadata":{"name":"hook2","creationTimestamp":null},"webhooks":[{"name":"externaladmissionhook.k8s.io","clientConfig":{"service":{"namespace":"ns","name":"n"},"caBundle":null},"rules":[{"operations":["CREATE"],"apiGroups":["group"],"apiVersions":["version"],"resources":["resource"]}],"failurePolicy":"Ignore","sideEffects":"Unknown","admissionReviewVersions":["v1beta1"]}]}`,
Stub: `{"metadata":{"name":"hook2","creationTimestamp":null},"webhooks":[{"name":"externaladmissionhook.k8s.io","clientConfig":{"service":{"namespace":"ns","name":"n"},"caBundle":null},"rules":[{"operations":["CREATE"],"apiGroups":["group"],"apiVersions":["version"],"resources":["resource"]}],"failurePolicy":"Ignore","sideEffects":"None","admissionReviewVersions":["v1beta1"]}]}`,
ExpectedEtcdPath: "/registry/mutatingwebhookconfigurations/hook2",
ExpectedGVK: gvkP("admissionregistration.k8s.io", "v1beta1", "MutatingWebhookConfiguration"),
},