Skip to content

Commit

Permalink
Merge pull request #54861 from hzxuzhonghu/admission-webhook
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue (batch tested with PRs 53047, 54861, 55413, 55395, 55308). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

cache admission webhook restClient

**What this PR does / why we need it**:

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #54860

**Special notes for your reviewer**:

**Release note**:

```release-note
NONE
```

Kubernetes-commit: 331c52c0fd4890ce999bad29265600d16cbb7abd
  • Loading branch information
k8s-publish-robot committed Nov 27, 2017
2 parents 2c208d7 + af81777 commit afbd83a
Show file tree
Hide file tree
Showing 3 changed files with 249 additions and 77 deletions.
1 change: 1 addition & 0 deletions pkg/admission/plugin/webhook/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/hashicorp/golang-lru:go_default_library",
"//vendor/k8s.io/api/admission/v1alpha1:go_default_library",
"//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library",
"//vendor/k8s.io/api/authentication/v1:go_default_library",
Expand Down
51 changes: 43 additions & 8 deletions pkg/admission/plugin/webhook/admission.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ package webhook

import (
"context"
"encoding/json"
"fmt"
"io"
"net"
"net/url"
"path"
"sync"

"github.com/golang/glog"
lru "github.com/hashicorp/golang-lru"

admissionv1alpha1 "k8s.io/api/admission/v1alpha1"
"k8s.io/api/admissionregistration/v1alpha1"
Expand All @@ -45,7 +47,8 @@ import (

const (
// Name of admission plug-in
PluginName = "GenericAdmissionWebhook"
PluginName = "GenericAdmissionWebhook"
defaultCacheSize = 200
)

type ErrCallingWebhook struct {
Expand Down Expand Up @@ -96,6 +99,11 @@ func NewGenericAdmissionWebhook(configFile io.Reader) (*GenericAdmissionWebhook,
return nil, err
}

cache, err := lru.New(defaultCacheSize)
if err != nil {
return nil, err
}

return &GenericAdmissionWebhook{
Handler: admission.NewHandler(
admission.Connect,
Expand All @@ -105,6 +113,7 @@ func NewGenericAdmissionWebhook(configFile io.Reader) (*GenericAdmissionWebhook,
),
authInfoResolver: authInfoResolver,
serviceResolver: defaultServiceResolver{},
cache: cache,
}, nil
}

Expand All @@ -116,6 +125,7 @@ type GenericAdmissionWebhook struct {
negotiatedSerializer runtime.NegotiatedSerializer

authInfoResolver AuthenticationInfoResolver
cache *lru.Cache
}

// serviceResolver knows how to convert a service reference into an actual location.
Expand Down Expand Up @@ -300,23 +310,48 @@ func toStatusErr(name string, result *metav1.Status) *apierrors.StatusError {
}

func (a *GenericAdmissionWebhook) hookClient(h *v1alpha1.Webhook) (*rest.RESTClient, error) {
serverName := h.ClientConfig.Service.Name + "." + h.ClientConfig.Service.Namespace + ".svc"
u, err := a.serviceResolver.ResolveEndpoint(h.ClientConfig.Service.Namespace, h.ClientConfig.Service.Name)
cacheKey, err := json.Marshal(h.ClientConfig)
if err != nil {
return nil, err
}
if client, ok := a.cache.Get(string(cacheKey)); ok {
return client.(*rest.RESTClient), nil
}

// TODO: cache these instead of constructing one each time
serverName := h.ClientConfig.Service.Name + "." + h.ClientConfig.Service.Namespace + ".svc"
restConfig, err := a.authInfoResolver.ClientConfigFor(serverName)
if err != nil {
return nil, err
}

cfg := rest.CopyConfig(restConfig)
cfg.Host = u.Host
cfg.APIPath = path.Join(u.Path, h.ClientConfig.URLPath)
host := serverName + ":443"
cfg.Host = "https://" + host
cfg.APIPath = h.ClientConfig.URLPath
cfg.TLSClientConfig.ServerName = serverName
cfg.TLSClientConfig.CAData = h.ClientConfig.CABundle
cfg.ContentConfig.NegotiatedSerializer = a.negotiatedSerializer
cfg.ContentConfig.ContentType = runtime.ContentTypeJSON
return rest.UnversionedRESTClientFor(cfg)

delegateDialer := cfg.Dial
if delegateDialer == nil {
delegateDialer = net.Dial
}

cfg.Dial = func(network, addr string) (net.Conn, error) {
if addr == host {
u, err := a.serviceResolver.ResolveEndpoint(h.ClientConfig.Service.Namespace, h.ClientConfig.Service.Name)
if err != nil {
return nil, err
}
addr = u.Host
}
return delegateDialer(network, addr)
}

client, err := rest.UnversionedRESTClientFor(cfg)
if err == nil {
a.cache.Add(string(cacheKey), client)
}
return client, err
}
Loading

0 comments on commit afbd83a

Please sign in to comment.