use istio client-go library instead of knative (#1661)
use istio client-go library instead of knative bump kubernetes dependency version change code coverage to codecov
This commit is contained in:
164
vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/dispatcher.go
generated
vendored
164
vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/dispatcher.go
generated
vendored
@@ -22,47 +22,108 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/klog"
|
||||
|
||||
admissionv1beta1 "k8s.io/api/admission/v1beta1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/webhook"
|
||||
webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/webhook/request"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/webhook/util"
|
||||
"k8s.io/apiserver/pkg/util/webhook"
|
||||
webhookrequest "k8s.io/apiserver/pkg/admission/plugin/webhook/request"
|
||||
webhookutil "k8s.io/apiserver/pkg/util/webhook"
|
||||
"k8s.io/klog"
|
||||
utiltrace "k8s.io/utils/trace"
|
||||
)
|
||||
|
||||
type validatingDispatcher struct {
|
||||
cm *webhook.ClientManager
|
||||
cm *webhookutil.ClientManager
|
||||
plugin *Plugin
|
||||
}
|
||||
|
||||
func newValidatingDispatcher(cm *webhook.ClientManager) generic.Dispatcher {
|
||||
return &validatingDispatcher{cm}
|
||||
func newValidatingDispatcher(p *Plugin) func(cm *webhookutil.ClientManager) generic.Dispatcher {
|
||||
return func(cm *webhookutil.ClientManager) generic.Dispatcher {
|
||||
return &validatingDispatcher{cm, p}
|
||||
}
|
||||
}
|
||||
|
||||
var _ generic.Dispatcher = &validatingDispatcher{}
|
||||
|
||||
func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, relevantHooks []*v1beta1.Webhook) error {
|
||||
func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attributes, o admission.ObjectInterfaces, hooks []webhook.WebhookAccessor) error {
|
||||
var relevantHooks []*generic.WebhookInvocation
|
||||
// Construct all the versions we need to call our webhooks
|
||||
versionedAttrs := map[schema.GroupVersionKind]*generic.VersionedAttributes{}
|
||||
for _, hook := range hooks {
|
||||
invocation, statusError := d.plugin.ShouldCallHook(hook, attr, o)
|
||||
if statusError != nil {
|
||||
return statusError
|
||||
}
|
||||
if invocation == nil {
|
||||
continue
|
||||
}
|
||||
relevantHooks = append(relevantHooks, invocation)
|
||||
// If we already have this version, continue
|
||||
if _, ok := versionedAttrs[invocation.Kind]; ok {
|
||||
continue
|
||||
}
|
||||
versionedAttr, err := generic.NewVersionedAttributes(attr, invocation.Kind, o)
|
||||
if err != nil {
|
||||
return apierrors.NewInternalError(err)
|
||||
}
|
||||
versionedAttrs[invocation.Kind] = versionedAttr
|
||||
}
|
||||
|
||||
if len(relevantHooks) == 0 {
|
||||
// no matching hooks
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if the request has already timed out before spawning remote calls
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// parent context is canceled or timed out, no point in continuing
|
||||
return apierrors.NewTimeoutError("request did not complete within requested timeout", 0)
|
||||
default:
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
errCh := make(chan error, len(relevantHooks))
|
||||
wg.Add(len(relevantHooks))
|
||||
for i := range relevantHooks {
|
||||
go func(hook *v1beta1.Webhook) {
|
||||
go func(invocation *generic.WebhookInvocation) {
|
||||
defer wg.Done()
|
||||
|
||||
hook, ok := invocation.Webhook.GetValidatingWebhook()
|
||||
if !ok {
|
||||
utilruntime.HandleError(fmt.Errorf("validating webhook dispatch requires v1beta1.ValidatingWebhook, but got %T", hook))
|
||||
return
|
||||
}
|
||||
versionedAttr := versionedAttrs[invocation.Kind]
|
||||
t := time.Now()
|
||||
err := d.callHook(ctx, hook, attr)
|
||||
admissionmetrics.Metrics.ObserveWebhook(time.Since(t), err != nil, attr.Attributes, "validating", hook.Name)
|
||||
err := d.callHook(ctx, hook, invocation, versionedAttr)
|
||||
ignoreClientCallFailures := hook.FailurePolicy != nil && *hook.FailurePolicy == v1beta1.Ignore
|
||||
rejected := false
|
||||
if err != nil {
|
||||
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)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ignoreClientCallFailures := hook.FailurePolicy != nil && *hook.FailurePolicy == v1beta1.Ignore
|
||||
if callErr, ok := err.(*webhook.ErrCallingWebhook); ok {
|
||||
if callErr, ok := err.(*webhookutil.ErrCallingWebhook); ok {
|
||||
if ignoreClientCallFailures {
|
||||
klog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr)
|
||||
utilruntime.HandleError(callErr)
|
||||
@@ -74,6 +135,9 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.Versi
|
||||
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])
|
||||
@@ -97,38 +161,74 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.Versi
|
||||
return errs[0]
|
||||
}
|
||||
|
||||
func (d *validatingDispatcher) callHook(ctx context.Context, h *v1beta1.Webhook, attr *generic.VersionedAttributes) error {
|
||||
if attr.IsDryRun() {
|
||||
func (d *validatingDispatcher) callHook(ctx context.Context, h *v1beta1.ValidatingWebhook, invocation *generic.WebhookInvocation, attr *generic.VersionedAttributes) error {
|
||||
if attr.Attributes.IsDryRun() {
|
||||
if h.SideEffects == nil {
|
||||
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook SideEffects is nil")}
|
||||
return &webhookutil.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
|
||||
request := request.CreateAdmissionReview(attr)
|
||||
client, err := d.cm.HookClient(util.HookClientConfigForWebhook(h))
|
||||
uid, request, response, err := webhookrequest.CreateAdmissionObjects(attr, invocation)
|
||||
if err != nil {
|
||||
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
|
||||
return &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
|
||||
}
|
||||
response := &admissionv1beta1.AdmissionReview{}
|
||||
if err := client.Post().Context(ctx).Body(&request).Do().Into(response); err != nil {
|
||||
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
|
||||
// Make the webhook request
|
||||
client, err := invocation.Webhook.GetRESTClient(d.cm)
|
||||
if err != nil {
|
||||
return &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
|
||||
}
|
||||
trace := utiltrace.New("Call validating webhook",
|
||||
utiltrace.Field{"configuration", invocation.Webhook.GetConfigurationName()},
|
||||
utiltrace.Field{"webhook", h.Name},
|
||||
utiltrace.Field{"resource", attr.GetResource()},
|
||||
utiltrace.Field{"subresource", attr.GetSubresource()},
|
||||
utiltrace.Field{"operation", attr.GetOperation()},
|
||||
utiltrace.Field{"UID", uid})
|
||||
defer trace.LogIfLong(500 * time.Millisecond)
|
||||
|
||||
// if the webhook has a specific timeout, wrap the context to apply it
|
||||
if h.TimeoutSeconds != nil {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, time.Duration(*h.TimeoutSeconds)*time.Second)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
if response.Response == nil {
|
||||
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook response was absent")}
|
||||
r := client.Post().Context(ctx).Body(request)
|
||||
|
||||
// if the context has a deadline, set it as a parameter to inform the backend
|
||||
if deadline, hasDeadline := ctx.Deadline(); hasDeadline {
|
||||
// compute the timeout
|
||||
if timeout := time.Until(deadline); timeout > 0 {
|
||||
// if it's not an even number of seconds, round up to the nearest second
|
||||
if truncated := timeout.Truncate(time.Second); truncated != timeout {
|
||||
timeout = truncated + time.Second
|
||||
}
|
||||
// set the timeout
|
||||
r.Timeout(timeout)
|
||||
}
|
||||
}
|
||||
for k, v := range response.Response.AuditAnnotations {
|
||||
|
||||
if err := r.Do().Into(response); err != nil {
|
||||
return &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
|
||||
}
|
||||
trace.Step("Request completed")
|
||||
|
||||
result, err := webhookrequest.VerifyAdmissionResponse(uid, false, response)
|
||||
if err != nil {
|
||||
return &webhookutil.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
|
||||
}
|
||||
|
||||
for k, v := range result.AuditAnnotations {
|
||||
key := h.Name + "/" + k
|
||||
if err := attr.AddAnnotation(key, v); err != nil {
|
||||
if err := attr.Attributes.AddAnnotation(key, v); err != nil {
|
||||
klog.Warningf("Failed to set admission audit annotation %s to %s for validating webhook %s: %v", key, v, h.Name, err)
|
||||
}
|
||||
}
|
||||
if response.Response.Allowed {
|
||||
if result.Allowed {
|
||||
return nil
|
||||
}
|
||||
return webhookerrors.ToStatusErr(h.Name, response.Response.Result)
|
||||
return &webhookutil.ErrWebhookRejection{Status: webhookerrors.ToStatusErr(h.Name, result.Result)}
|
||||
}
|
||||
|
||||
11
vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin.go
generated
vendored
11
vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin.go
generated
vendored
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package validating
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
@@ -51,14 +52,16 @@ var _ admission.ValidationInterface = &Plugin{}
|
||||
// NewValidatingAdmissionWebhook returns a generic admission webhook plugin.
|
||||
func NewValidatingAdmissionWebhook(configFile io.Reader) (*Plugin, error) {
|
||||
handler := admission.NewHandler(admission.Connect, admission.Create, admission.Delete, admission.Update)
|
||||
webhook, err := generic.NewWebhook(handler, configFile, configuration.NewValidatingWebhookConfigurationManager, newValidatingDispatcher)
|
||||
p := &Plugin{}
|
||||
var err error
|
||||
p.Webhook, err = generic.NewWebhook(handler, configFile, configuration.NewValidatingWebhookConfigurationManager, newValidatingDispatcher(p))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Plugin{webhook}, nil
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// Validate makes an admission decision based on the request attributes.
|
||||
func (a *Plugin) Validate(attr admission.Attributes) error {
|
||||
return a.Webhook.Dispatch(attr)
|
||||
func (a *Plugin) Validate(ctx context.Context, attr admission.Attributes, o admission.ObjectInterfaces) error {
|
||||
return a.Webhook.Dispatch(ctx, attr, o)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user