code: func (a *Webhook) Dispatch(attr admission.Attributes, o admission.ObjectInterfaces) error {
  	if rules.IsWebhookConfigurationResource(attr) {
  		return nil
  	}
  	if !a.WaitForReady() {
  		return admission.NewForbidden(attr, fmt.Errorf("not yet ready to handle request"))
  	}
  	hooks := a.hookSource.Webhooks()
  	// TODO: Figure out if adding one second timeout make sense here.
  	ctx := context.TODO()
  
  	var relevantHooks []*v1beta1.Webhook
  	for i := range hooks {
  		call, err := a.ShouldCallHook(&hooks[i], attr)
  		if err != nil {
  			return err
  		}
  		if call {
  			relevantHooks = append(relevantHooks, &hooks[i])
  		}
  	}
  
  	if len(relevantHooks) == 0 {
  		// no matching hooks
  		return nil
  	}
  
  	// convert the object to the external version before sending it to the webhook
  	versionedAttr := VersionedAttributes{
  		Attributes: attr,
  	}
  	if oldObj := attr.GetOldObject(); oldObj != nil {
  		out, err := ConvertToGVK(oldObj, attr.GetKind(), o)
  		if err != nil {
  			return apierrors.NewInternalError(err)
  		}
  		versionedAttr.VersionedOldObject = out
  	}
  	if obj := attr.GetObject(); obj != nil {
  		out, err := ConvertToGVK(obj, attr.GetKind(), o)
  		if err != nil {
  			return apierrors.NewInternalError(err)
  		}
  		versionedAttr.VersionedObject = out
  	}
  	return a.dispatcher.Dispatch(ctx, &versionedAttr, o, relevantHooks)
  }
docs: // Dispatch is called by the downstream Validate or Admit methods.