Skip to content

Commit

Permalink
⚠️fix webhook injector, drop name and client
Browse files Browse the repository at this point in the history
  • Loading branch information
Mengqi Yu committed Feb 14, 2019
1 parent 81b48be commit 29adcfc
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 85 deletions.
4 changes: 2 additions & 2 deletions example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func main() {
Build()

entryLog.Info("setting up webhook server")
as, err := webhook.NewServer("foo-admission-server", mgr, webhook.ServerOptions{
as, err := webhook.NewServer(mgr, webhook.ServerOptions{
Port: 9876,
CertDir: "/tmp/cert",
})
Expand All @@ -104,7 +104,7 @@ func main() {
entryLog.Info("registering webhooks to the webhook server")
err = as.Register(mutatingWebhook, validatingWebhook)
if err != nil {
entryLog.Error(err, "unable to register webhooks in the admission server")
entryLog.Error(err, "unable to setup the admission server")
os.Exit(1)
}

Expand Down
21 changes: 4 additions & 17 deletions pkg/webhook/admission/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (

admissionv1beta1 "k8s.io/api/admission/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/runtime/inject"
atypes "sigs.k8s.io/controller-runtime/pkg/webhook/admission/types"
"sigs.k8s.io/controller-runtime/pkg/webhook/types"
Expand Down Expand Up @@ -210,24 +209,12 @@ func (w *Webhook) Validate() error {
return nil
}

var _ inject.Client = &Webhook{}
var _ inject.Injector = &Webhook{}

// InjectClient injects the client into the handlers
func (w *Webhook) InjectClient(c client.Client) error {
// InjectFunc injects dependencies into the handlers.
func (w *Webhook) InjectFunc(f inject.Func) error {
for _, handler := range w.Handlers {
if _, err := inject.ClientInto(c, handler); err != nil {
return err
}
}
return nil
}

var _ inject.Decoder = &Webhook{}

// InjectDecoder injects the decoder into the handlers
func (w *Webhook) InjectDecoder(d atypes.Decoder) error {
for _, handler := range w.Handlers {
if _, err := inject.DecoderInto(d, handler); err != nil {
if err := f(handler); err != nil {
return err
}
}
Expand Down
87 changes: 21 additions & 66 deletions pkg/webhook/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,14 @@ package webhook
import (
"context"
"crypto/tls"
"fmt"
"net"
"net/http"
"path"
"strconv"
"sync"

"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/runtime/inject"
atypes "sigs.k8s.io/controller-runtime/pkg/webhook/admission/types"
)

const (
Expand All @@ -50,28 +46,20 @@ type ServerOptions struct {
// If using SecretCertWriter in Provisioner, the server will provision the certificate in a secret,
// the user is responsible to mount the secret to the this location for the server to consume.
CertDir string

// Client is a client defined in controller-runtime instead of a client-go client.
// It knows how to talk to a kubernetes cluster.
// Client will be injected by the manager if not set.
Client client.Client

// err will be non-nil if there is an error occur during initialization.
err error // nolint: structcheck
}

// Server is an admission webhook server that can serve traffic and
// generates related k8s resources for deploying.
type Server struct {
// Name is the name of server
Name string

// ServerOptions contains options for configuring the admission server.
ServerOptions

sMux *http.ServeMux
// registry maps a path to a http.Handler.
registry map[string]Webhook
registry map[string]http.Handler

// setFields is used to inject dependencies into webhooks
setFields func(i interface{}) error

// manager is the manager that this webhook server will be registered.
manager manager.Manager
Expand All @@ -81,6 +69,8 @@ type Server struct {

// Webhook defines the basics that a webhook should support.
type Webhook interface {
http.Handler

// GetPath returns the path that the webhook registered.
GetPath() string
// Handler returns a http.Handler for the webhook.
Expand All @@ -91,11 +81,10 @@ type Webhook interface {
}

// NewServer creates a new admission webhook server.
func NewServer(name string, mgr manager.Manager, options ServerOptions) (*Server, error) {
func NewServer(mgr manager.Manager, options ServerOptions) (*Server, error) {
as := &Server{
Name: name,
sMux: http.NewServeMux(),
registry: map[string]Webhook{},
registry: map[string]http.Handler{},
ServerOptions: options,
manager: mgr,
}
Expand All @@ -105,34 +94,18 @@ func NewServer(name string, mgr manager.Manager, options ServerOptions) (*Server

// setDefault does defaulting for the Server.
func (s *Server) setDefault() {
if len(s.Name) == 0 {
s.Name = "default-k8s-webhook-server"
}
if s.registry == nil {
s.registry = map[string]Webhook{}
s.registry = map[string]http.Handler{}
}
if s.sMux == nil {
s.sMux = http.DefaultServeMux
s.sMux = http.NewServeMux()
}
if s.Port <= 0 {
s.Port = 443
}
if len(s.CertDir) == 0 {
s.CertDir = path.Join("k8s-webhook-server", "cert")
}

if s.Client == nil {
cfg, err := config.GetConfig()
if err != nil {
s.err = err
return
}
s.Client, err = client.New(cfg, client.Options{})
if err != nil {
s.err = err
return
}
}
}

// Register validates and registers webhook(s) in the server
Expand All @@ -143,12 +116,14 @@ func (s *Server) Register(webhooks ...Webhook) error {
if err != nil {
return err
}
_, found := s.registry[webhook.GetPath()]
if found {
return fmt.Errorf("can't register duplicate path: %v", webhook.GetPath())
}
s.registry[webhook.GetPath()] = webhooks[i]
// Handle actually ensures that no duplicate paths are registered.
s.sMux.Handle(webhook.GetPath(), webhook.Handler())
s.registry[webhook.GetPath()] = webhooks[i]

// Inject dependencies to each webhook.
if err := s.setFields(webhooks[i]); err != nil {
return err
}
}

// Lazily add Server to manager.
Expand All @@ -167,9 +142,6 @@ var _ manager.Runnable = &Server{}
// It will install the webhook related resources depend on the server configuration.
func (s *Server) Start(stop <-chan struct{}) error {
s.once.Do(s.setDefault)
if s.err != nil {
return s.err
}

// TODO: watch the cert dir. Reload the cert if it changes
cert, err := tls.LoadX509KeyPair(path.Join(s.CertDir, certName), path.Join(s.CertDir, keyName))
Expand Down Expand Up @@ -211,27 +183,10 @@ func (s *Server) Start(stop <-chan struct{}) error {
return nil
}

var _ inject.Client = &Server{}

// InjectClient injects the client into the server
func (s *Server) InjectClient(c client.Client) error {
s.Client = c
for _, wh := range s.registry {
if _, err := inject.ClientInto(c, wh.Handler()); err != nil {
return err
}
}
return nil
}

var _ inject.Decoder = &Server{}
var _ inject.Injector = &Server{}

// InjectDecoder injects the decoder into the server
func (s *Server) InjectDecoder(d atypes.Decoder) error {
for _, wh := range s.registry {
if _, err := inject.DecoderInto(d, wh.Handler()); err != nil {
return err
}
}
// InjectFunc injects dependencies into the handlers.
func (s *Server) InjectFunc(f inject.Func) error {
s.setFields = f
return nil
}

0 comments on commit 29adcfc

Please sign in to comment.