Support dry run in admission webhooks

Kubernetes-commit: 2d0ec48f9beea6182a9a3bfdcc5eb98e50b44f77
This commit is contained in:
jennybuckley 2018-08-21 16:06:27 -07:00 committed by Kubernetes Publisher
parent 5673c9ff57
commit 817f61120c
4 changed files with 63 additions and 7 deletions

View File

@ -83,8 +83,12 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr *generic.Version
// note that callAttrMutatingHook updates attr
func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta1.Webhook, attr *generic.VersionedAttributes) error {
if attr.IsDryRun() {
// TODO: support this
return webhookerrors.NewDryRunUnsupportedErr(h.Name)
if h.SideEffects == nil {
return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook SideEffects is nil")}
}
if !(*h.SideEffects == v1beta1.SideEffectClassNone || *h.SideEffects == v1beta1.SideEffectClassNoneOnDryRun) {
return webhookerrors.NewDryRunUnsupportedErr(h.Name)
}
}
// Make the webhook request

View File

@ -36,6 +36,7 @@ func CreateAdmissionReview(attr *generic.VersionedAttributes) admissionv1beta1.A
UID: aUserInfo.GetUID(),
Username: aUserInfo.GetName(),
}
dryRun := attr.IsDryRun()
// Convert the extra information in the user object
for key, val := range aUserInfo.GetExtra() {
@ -66,6 +67,7 @@ func CreateAdmissionReview(attr *generic.VersionedAttributes) admissionv1beta1.A
OldObject: runtime.RawExtension{
Object: attr.VersionedOldObject,
},
DryRun: &dryRun,
},
}
}

View File

@ -43,6 +43,11 @@ var matchEverythingRules = []registrationv1beta1.RuleWithOperations{{
},
}}
var sideEffectsUnknown registrationv1beta1.SideEffectClass = registrationv1beta1.SideEffectClassUnknown
var sideEffectsNone registrationv1beta1.SideEffectClass = registrationv1beta1.SideEffectClassNone
var sideEffectsSome registrationv1beta1.SideEffectClass = registrationv1beta1.SideEffectClassSome
var sideEffectsNoneOnDryRun registrationv1beta1.SideEffectClass = registrationv1beta1.SideEffectClassNoneOnDryRun
// NewFakeDataSource returns a mock client and informer returning the given webhooks.
func NewFakeDataSource(name string, webhooks []registrationv1beta1.Webhook, mutating bool, stopCh <-chan struct{}) (clientset kubernetes.Interface, factory informers.SharedInformerFactory) {
var objs = []runtime.Object{
@ -388,26 +393,66 @@ func NewNonMutatingTestCases(url *url.URL) []Test {
Name: "no match dry run",
Webhooks: []registrationv1beta1.Webhook{{
Name: "nomatch",
ClientConfig: ccfgSVC("disallow"),
ClientConfig: ccfgSVC("allow"),
Rules: []registrationv1beta1.RuleWithOperations{{
Operations: []registrationv1beta1.OperationType{registrationv1beta1.Create},
}},
NamespaceSelector: &metav1.LabelSelector{},
SideEffects: &sideEffectsSome,
}},
IsDryRun: true,
ExpectAllow: true,
},
{
Name: "match dry run",
Name: "match dry run side effects Unknown",
Webhooks: []registrationv1beta1.Webhook{{
Name: "allow",
ClientConfig: ccfgSVC("allow"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
SideEffects: &sideEffectsUnknown,
}},
IsDryRun: true,
ErrorContains: "does not support dry run",
},
{
Name: "match dry run side effects None",
Webhooks: []registrationv1beta1.Webhook{{
Name: "allow",
ClientConfig: ccfgSVC("allow"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
SideEffects: &sideEffectsNone,
}},
IsDryRun: true,
ExpectAllow: true,
ExpectAnnotations: map[string]string{"allow/key1": "value1"},
},
{
Name: "match dry run side effects Some",
Webhooks: []registrationv1beta1.Webhook{{
Name: "allow",
ClientConfig: ccfgSVC("allow"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
SideEffects: &sideEffectsSome,
}},
IsDryRun: true,
ErrorContains: "does not support dry run",
},
{
Name: "match dry run side effects NoneOnDryRun",
Webhooks: []registrationv1beta1.Webhook{{
Name: "allow",
ClientConfig: ccfgSVC("allow"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
SideEffects: &sideEffectsNoneOnDryRun,
}},
IsDryRun: true,
ExpectAllow: true,
ExpectAnnotations: map[string]string{"allow/key1": "value1"},
},
{
Name: "illegal annotation format",
Webhooks: []registrationv1beta1.Webhook{{
@ -489,12 +534,13 @@ func NewMutatingTestCases(url *url.URL) []Test {
ErrorContains: "invalid character",
},
{
Name: "match & remove label dry run",
Name: "match & remove label dry run unsupported",
Webhooks: []registrationv1beta1.Webhook{{
Name: "removeLabel",
ClientConfig: ccfgSVC("removeLabel"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
SideEffects: &sideEffectsUnknown,
}},
IsDryRun: true,
ErrorContains: "does not support dry run",

View File

@ -98,8 +98,12 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.Versi
func (d *validatingDispatcher) callHook(ctx context.Context, h *v1beta1.Webhook, attr *generic.VersionedAttributes) error {
if attr.IsDryRun() {
// TODO: support this
return webhookerrors.NewDryRunUnsupportedErr(h.Name)
if h.SideEffects == nil {
return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook SideEffects is nil")}
}
if !(*h.SideEffects == v1beta1.SideEffectClassNone || *h.SideEffects == v1beta1.SideEffectClassNoneOnDryRun) {
return webhookerrors.NewDryRunUnsupportedErr(h.Name)
}
}
// Make the webhook request