Skip to content

Commit e318642

Browse files
authored
Merge pull request kubernetes#74998 from mbohlool/pippin
Webhook configurations can choose which version of Review request they accept
2 parents eaa78b8 + cbe0002 commit e318642

File tree

33 files changed

+1784
-790
lines changed

33 files changed

+1784
-790
lines changed

api/openapi-spec/swagger.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apis/admissionregistration/fuzzer/fuzzer.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
4343
i := int32(30)
4444
obj.TimeoutSeconds = &i
4545
}
46+
obj.AdmissionReviewVersions = []string{"v1beta1"}
4647
},
4748
}
4849
}

pkg/apis/admissionregistration/types.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,15 @@ type Webhook struct {
239239
// The timeout value must be between 1 and 30 seconds.
240240
// +optional
241241
TimeoutSeconds *int32
242+
243+
// AdmissionReviewVersions is an ordered list of preferred `AdmissionReview`
244+
// versions the Webhook expects. API server will try to use first version in
245+
// the list which it supports. If none of the versions specified in this list
246+
// supported by API server, validation will fail for this object.
247+
// If the webhook configuration has already been persisted with a version apiserver
248+
// does not understand, calls to the webhook will fail and be subject to the failure policy.
249+
// +optional
250+
AdmissionReviewVersions []string
242251
}
243252

244253
// RuleWithOperations is a tuple of Operations and Resources. It is recommended to make

pkg/apis/admissionregistration/v1beta1/defaults.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ func SetDefaults_Webhook(obj *admissionregistrationv1beta1.Webhook) {
4444
obj.TimeoutSeconds = new(int32)
4545
*obj.TimeoutSeconds = 30
4646
}
47+
48+
if len(obj.AdmissionReviewVersions) == 0 {
49+
obj.AdmissionReviewVersions = []string{admissionregistrationv1beta1.SchemeGroupVersion.Version}
50+
}
4751
}
4852

4953
func SetDefaults_Rule(obj *admissionregistrationv1beta1.Rule) {

pkg/apis/admissionregistration/v1beta1/zz_generated.conversion.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apis/admissionregistration/validation/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ go_library(
2222
importpath = "k8s.io/kubernetes/pkg/apis/admissionregistration/validation",
2323
deps = [
2424
"//pkg/apis/admissionregistration:go_default_library",
25+
"//pkg/apis/admissionregistration/v1beta1:go_default_library",
2526
"//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library",
2627
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
2728
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",

pkg/apis/admissionregistration/validation/validation.go

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ import (
2424
metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
2525
"k8s.io/apimachinery/pkg/util/sets"
2626
"k8s.io/apimachinery/pkg/util/validation"
27+
utilvalidation "k8s.io/apimachinery/pkg/util/validation"
2728
"k8s.io/apimachinery/pkg/util/validation/field"
2829
"k8s.io/apiserver/pkg/util/webhook"
2930
"k8s.io/kubernetes/pkg/apis/admissionregistration"
31+
"k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1"
3032
)
3133

3234
func hasWildcard(slice []string) bool {
@@ -150,18 +152,71 @@ func validateRule(rule *admissionregistration.Rule, fldPath *field.Path, allowSu
150152
return allErrors
151153
}
152154

155+
var AcceptedAdmissionReviewVersions = []string{v1beta1.SchemeGroupVersion.Version}
156+
157+
func isAcceptedAdmissionReviewVersion(v string) bool {
158+
for _, version := range AcceptedAdmissionReviewVersions {
159+
if v == version {
160+
return true
161+
}
162+
}
163+
return false
164+
}
165+
166+
func validateAdmissionReviewVersions(versions []string, requireRecognizedVersion bool, fldPath *field.Path) field.ErrorList {
167+
allErrors := field.ErrorList{}
168+
169+
// Currently only v1beta1 accepted in AdmissionReviewVersions
170+
if len(versions) < 1 {
171+
allErrors = append(allErrors, field.Required(fldPath, ""))
172+
} else {
173+
seen := map[string]bool{}
174+
hasAcceptedVersion := false
175+
for i, v := range versions {
176+
if seen[v] {
177+
allErrors = append(allErrors, field.Invalid(fldPath.Index(i), v, "duplicate version"))
178+
continue
179+
}
180+
seen[v] = true
181+
for _, errString := range utilvalidation.IsDNS1035Label(v) {
182+
allErrors = append(allErrors, field.Invalid(fldPath.Index(i), v, errString))
183+
}
184+
if isAcceptedAdmissionReviewVersion(v) {
185+
hasAcceptedVersion = true
186+
}
187+
}
188+
if requireRecognizedVersion && !hasAcceptedVersion {
189+
allErrors = append(allErrors, field.Invalid(
190+
fldPath, versions,
191+
fmt.Sprintf("none of the versions accepted by this server. accepted version(s) are %v",
192+
strings.Join(AcceptedAdmissionReviewVersions, ", "))))
193+
}
194+
}
195+
return allErrors
196+
}
197+
153198
func ValidateValidatingWebhookConfiguration(e *admissionregistration.ValidatingWebhookConfiguration) field.ErrorList {
199+
return validateValidatingWebhookConfiguration(e, true)
200+
}
201+
202+
func validateValidatingWebhookConfiguration(e *admissionregistration.ValidatingWebhookConfiguration, requireRecognizedVersion bool) field.ErrorList {
154203
allErrors := genericvalidation.ValidateObjectMeta(&e.ObjectMeta, false, genericvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
155204
for i, hook := range e.Webhooks {
156205
allErrors = append(allErrors, validateWebhook(&hook, field.NewPath("webhooks").Index(i))...)
206+
allErrors = append(allErrors, validateAdmissionReviewVersions(hook.AdmissionReviewVersions, requireRecognizedVersion, field.NewPath("webhooks").Index(i).Child("admissionReviewVersions"))...)
157207
}
158208
return allErrors
159209
}
160210

161211
func ValidateMutatingWebhookConfiguration(e *admissionregistration.MutatingWebhookConfiguration) field.ErrorList {
212+
return validateMutatingWebhookConfiguration(e, true)
213+
}
214+
215+
func validateMutatingWebhookConfiguration(e *admissionregistration.MutatingWebhookConfiguration, requireRecognizedVersion bool) field.ErrorList {
162216
allErrors := genericvalidation.ValidateObjectMeta(&e.ObjectMeta, false, genericvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
163217
for i, hook := range e.Webhooks {
164218
allErrors = append(allErrors, validateWebhook(&hook, field.NewPath("webhooks").Index(i))...)
219+
allErrors = append(allErrors, validateAdmissionReviewVersions(hook.AdmissionReviewVersions, requireRecognizedVersion, field.NewPath("webhooks").Index(i).Child("admissionReviewVersions"))...)
165220
}
166221
return allErrors
167222
}
@@ -247,10 +302,28 @@ func validateRuleWithOperations(ruleWithOperations *admissionregistration.RuleWi
247302
return allErrors
248303
}
249304

305+
// hasAcceptedAdmissionReviewVersions returns true if all webhooks have at least one
306+
// admission review version this apiserver accepts.
307+
func hasAcceptedAdmissionReviewVersions(webhooks []admissionregistration.Webhook) bool {
308+
for _, hook := range webhooks {
309+
hasRecognizedVersion := false
310+
for _, version := range hook.AdmissionReviewVersions {
311+
if isAcceptedAdmissionReviewVersion(version) {
312+
hasRecognizedVersion = true
313+
break
314+
}
315+
}
316+
if !hasRecognizedVersion && len(hook.AdmissionReviewVersions) > 0 {
317+
return false
318+
}
319+
}
320+
return true
321+
}
322+
250323
func ValidateValidatingWebhookConfigurationUpdate(newC, oldC *admissionregistration.ValidatingWebhookConfiguration) field.ErrorList {
251-
return ValidateValidatingWebhookConfiguration(newC)
324+
return validateValidatingWebhookConfiguration(newC, hasAcceptedAdmissionReviewVersions(oldC.Webhooks))
252325
}
253326

254327
func ValidateMutatingWebhookConfigurationUpdate(newC, oldC *admissionregistration.MutatingWebhookConfiguration) field.ErrorList {
255-
return ValidateMutatingWebhookConfiguration(newC)
328+
return validateMutatingWebhookConfiguration(newC, hasAcceptedAdmissionReviewVersions(oldC.Webhooks))
256329
}

0 commit comments

Comments
 (0)