Skip to content

Commit

Permalink
Address comments and pull kubernetes-sigs#316 in
Browse files Browse the repository at this point in the history
drop server name and client
fix injector
  • Loading branch information
Mengqi Yu committed Feb 13, 2019
1 parent d169520 commit 52baf75
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 80 deletions.
5 changes: 2 additions & 3 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 @@ -102,8 +102,7 @@ func main() {
}

entryLog.Info("registering webhooks to the webhook server")
as.Register(mutatingWebhook, validatingWebhook)
err = as.Complete()
err = as.Register(mutatingWebhook, validatingWebhook)
if err != nil {
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
81 changes: 21 additions & 60 deletions pkg/webhook/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ import (
"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"
)
Expand All @@ -48,32 +46,24 @@ 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
}

// 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]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

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

once sync.Once
}

Expand All @@ -91,9 +81,8 @@ 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]http.Handler{},
ServerOptions: options,
Expand All @@ -105,74 +94,54 @@ 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]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
func (s *Server) Register(webhooks ...Webhook) {
func (s *Server) Register(webhooks ...Webhook) error {
for i, webhook := range webhooks {
// validate the webhook before registering it.
err := webhook.Validate()
if err != nil {
s.err = err
return
return err
}
// 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.
// Because the all webhook handlers to be in place, so we can inject the things they need.
return s.manager.Add(s)
}

// Handle registers a http.Handler for the given pattern.
func (s *Server) Handle(pattern string, handler http.Handler) {
s.sMux.Handle(pattern, handler)
}

// Complete must be called to complete the server setup
func (s *Server) Complete() error {
if s.err != nil {
return s.err
}
// TODO(mengqiy): inject dependencies into each http.Handler
return s.manager.Add(s)
}

var _ manager.Runnable = &Server{}

// Start runs the 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 @@ -214,18 +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 path := range s.registry {
// TODO(mengqiy): remove this in PR #316
if wh, ok := s.registry[path].(Webhook); ok {
if _, err := inject.ClientInto(c, wh.Handler()); err != nil {
return err
}
}
}
var _ inject.Injector = &Server{}

// InjectFunc injects dependencies into the handlers.
func (s *Server) InjectFunc(f inject.Func) error {
s.setFields = f
return nil
}

0 comments on commit 52baf75

Please sign in to comment.