func generatePath(gvk schema.GroupVersionKind) string {
	return strings.Replace(gvk.Group, ".", "-", -1) + "-" +
		gvk.Version + "-" + strings.ToLower(gvk.Kind)
}
generate a unique path for each gvk
package webhooks
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"reflect"
	"strings"
	"github.com/go-logr/logr"
	"gomodules.xyz/jsonpatch/v2"
	adminv1 "k8s.io/api/admission/v1"
	admregv1 "k8s.io/api/admissionregistration/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/runtime/serializer"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	ctrl "sigs.k8s.io/controller-runtime"
)
var (
	mutate_path_prefix   = "/mutate-"
	validate_path_prefix = "/validate-"
	Cert_mount_path      = "/etc/k8s-webhook-certs/"
	scheme = runtime.NewScheme()
	codecs = serializer.NewCodecFactory(scheme)
	pT     = adminv1.PatchTypeJSONPatch  
)
func init() {
	utilruntime.Must(adminv1.AddToScheme(scheme))
	utilruntime.Must(admregv1.AddToScheme(scheme))
}
type admitFunc func(adminv1.AdmissionReview) *adminv1.AdmissionResponse
type httpHandler func(http.ResponseWriter, *http.Request)
func RegisterWebhookWithManager(mgr ctrl.Manager, path string, hook http.Handler) error {
	if handlerExist(mgr, path) {
		return fmt.Errorf("webhook handler for %s already exist", path)
	}
	mgr.GetWebhookServer().Register(path, hook)
	return nil
}
func convertToHttpHandler(admit admitFunc, logger logr.Logger) httpHandler {
	return func(w http.ResponseWriter, r *http.Request) {
		var body []byte
		if r.Body != nil {
			if data, err := ioutil.ReadAll(r.Body); err == nil {
				body = data
			}
		}
		contentType := r.Header.Get("Content-Type")
		if contentType != "application/json" {
			logger.Error(fmt.Errorf("wrong content type"), "contentType=%s, expect application/json", contentType)
			return
		}
		logger.Info("handling request", "body length", r.ContentLength)
		requestedAdmissionReview := adminv1.AdmissionReview{}
		responseAdmissionReview := adminv1.AdmissionReview{
			TypeMeta: metav1.TypeMeta{
				APIVersion: adminv1.SchemeGroupVersion.String(),
				Kind:       reflect.TypeOf(adminv1.AdmissionReview{}).Name(),
			},
		}
		deserializer := codecs.UniversalDeserializer()
		if _, _, err := deserializer.Decode(body, nil, &requestedAdmissionReview); err != nil {
			logger.Error(err, "Failed to deserialize the body", "body", body)
			responseAdmissionReview.Response = toErrAdmissionResponse(err, http.StatusBadRequest)
		} else {
			responseAdmissionReview.Response = admit(requestedAdmissionReview)
		}
		responseAdmissionReview.Response.UID = requestedAdmissionReview.Request.UID
		logger.Info("sending response",
			"allowed", responseAdmissionReview.Response.Allowed,
			"http code", responseAdmissionReview.Response.Result.Code,
			"status", responseAdmissionReview.Response.Result.Status,
			"message", responseAdmissionReview.Response.Result.Message)
		encoder := json.NewEncoder(w)
		if err := encoder.Encode(responseAdmissionReview); err != nil {
			logger.Error(err, "Failed to write the response")
		}
	}
}