wire up the webhook rejection metrics in webhook handlers

Kubernetes-commit: 620f5f2c587971be50cb27bb2a2d35209b3dc058
This commit is contained in:
Haowei Cai 2019-08-28 17:32:07 -07:00 committed by Kubernetes Publisher
parent 466e192e26
commit 8d86fef522
3 changed files with 44 additions and 9 deletions

View File

@ -136,10 +136,18 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr admission.Attrib
ignoreClientCallFailures := hook.FailurePolicy != nil && *hook.FailurePolicy == v1beta1.Ignore
rejected := false
if err != nil {
// ErrCallingWebhook is ignored if the webhook is configured to failopen.
// Otherwise the request is rejected.
if _, ok := err.(*webhookutil.ErrCallingWebhook); !ok || !ignoreClientCallFailures {
switch err := err.(type) {
case *webhookutil.ErrCallingWebhook:
if !ignoreClientCallFailures {
rejected = true
admissionmetrics.Metrics.ObserveWebhookRejection(hook.Name, "admit", string(versionedAttr.Attributes.GetOperation()), admissionmetrics.WebhookRejectionCallingWebhookError, 0)
}
case *webhookutil.ErrWebhookRejection:
rejected = true
admissionmetrics.Metrics.ObserveWebhookRejection(hook.Name, "admit", string(versionedAttr.Attributes.GetOperation()), admissionmetrics.WebhookRejectionNoError, int(err.Status.ErrStatus.Code))
default:
rejected = true
admissionmetrics.Metrics.ObserveWebhookRejection(hook.Name, "admit", string(versionedAttr.Attributes.GetOperation()), admissionmetrics.WebhookRejectionAPIServerInternalError, 0)
}
}
admissionmetrics.Metrics.ObserveWebhook(time.Since(t), rejected, versionedAttr.Attributes, "admit", hook.Name)
@ -172,6 +180,9 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr admission.Attrib
klog.Warningf("Failed calling webhook, failing closed %v: %v", hook.Name, err)
return apierrors.NewInternalError(err)
}
if rejectionErr, ok := err.(*webhookutil.ErrWebhookRejection); ok {
return rejectionErr.Status
}
return err
}
@ -257,7 +268,7 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta
}
if !result.Allowed {
return false, webhookerrors.ToStatusErr(h.Name, result.Result)
return false, &webhookutil.ErrWebhookRejection{Status: webhookerrors.ToStatusErr(h.Name, result.Result)}
}
if len(result.Patch) == 0 {

View File

@ -104,10 +104,18 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attr
ignoreClientCallFailures := hook.FailurePolicy != nil && *hook.FailurePolicy == v1beta1.Ignore
rejected := false
if err != nil {
// ErrCallingWebhook is ignored if the webhook is configured to failopen.
// Otherwise the request is rejected.
if _, ok := err.(*webhookutil.ErrCallingWebhook); !ok || !ignoreClientCallFailures {
switch err := err.(type) {
case *webhookutil.ErrCallingWebhook:
if !ignoreClientCallFailures {
rejected = true
admissionmetrics.Metrics.ObserveWebhookRejection(hook.Name, "validating", string(versionedAttr.Attributes.GetOperation()), admissionmetrics.WebhookRejectionCallingWebhookError, 0)
}
case *webhookutil.ErrWebhookRejection:
rejected = true
admissionmetrics.Metrics.ObserveWebhookRejection(hook.Name, "validating", string(versionedAttr.Attributes.GetOperation()), admissionmetrics.WebhookRejectionNoError, int(err.Status.ErrStatus.Code))
default:
rejected = true
admissionmetrics.Metrics.ObserveWebhookRejection(hook.Name, "validating", string(versionedAttr.Attributes.GetOperation()), admissionmetrics.WebhookRejectionAPIServerInternalError, 0)
}
}
admissionmetrics.Metrics.ObserveWebhook(time.Since(t), rejected, versionedAttr.Attributes, "validating", hook.Name)
@ -127,6 +135,9 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attr
return
}
if rejectionErr, ok := err.(*webhookutil.ErrWebhookRejection); ok {
err = rejectionErr.Status
}
klog.Warningf("rejected by webhook %q: %#v", hook.Name, err)
errCh <- err
}(relevantHooks[i])
@ -219,5 +230,5 @@ func (d *validatingDispatcher) callHook(ctx context.Context, h *v1beta1.Validati
if result.Allowed {
return nil
}
return webhookerrors.ToStatusErr(h.Name, result.Result)
return &webhookutil.ErrWebhookRejection{Status: webhookerrors.ToStatusErr(h.Name, result.Result)}
}

View File

@ -16,7 +16,11 @@ limitations under the License.
package webhook
import "fmt"
import (
"fmt"
apierrors "k8s.io/apimachinery/pkg/api/errors"
)
// ErrCallingWebhook is returned for transport-layer errors calling webhooks. It
// represents a failure to talk to the webhook, not the webhook rejecting a
@ -32,3 +36,12 @@ func (e *ErrCallingWebhook) Error() string {
}
return fmt.Sprintf("failed calling webhook %q; no further details available", e.WebhookName)
}
// ErrWebhookRejection represents a webhook properly rejecting a request.
type ErrWebhookRejection struct {
Status *apierrors.StatusError
}
func (e *ErrWebhookRejection) Error() string {
return e.Status.Error()
}