Skip to content

Commit

Permalink
Updated validation webhook for blueprints
Browse files Browse the repository at this point in the history
Signed-off-by: Abhijit Mukherjee <[email protected]>
  • Loading branch information
mabhi committed Feb 21, 2024
1 parent fbfa08f commit e3e160e
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 25 deletions.
21 changes: 14 additions & 7 deletions pkg/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,18 @@ import (
"net/http"

"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
"sigs.k8s.io/controller-runtime/pkg/webhook"

crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1"
"github.com/kanisterio/kanister/pkg/validatingwebhook"
"github.com/kanisterio/kanister/pkg/version"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus/promhttp"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

const (
Expand Down Expand Up @@ -62,18 +66,21 @@ func (*healthCheckHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

// RunWebhookServer starts the validating webhook resources for blueprint kanister resources
func RunWebhookServer(c *rest.Config) error {
hookServerOptions := webhook.Options{CertDir: validatingwebhook.WHCertsDir}
log.SetLogger(zap.New())
mgr, err := manager.New(c, manager.Options{})
if err != nil {
return errors.Wrapf(err, "Failed to create new webhook manager")
}

hookServerOptions := webhook.Options{CertDir: validatingwebhook.WHCertsDir}
hookServer := webhook.NewServer(hookServerOptions)
hookServer.Register(whHandlePath, &webhook.Admission{Handler: &validatingwebhook.BlueprintValidator{}})
hook := admission.WithCustomValidator(mgr.GetScheme(), &crv1alpha1.Blueprint{}, &validatingwebhook.BlueprintValidator{})
hookServer.Register(whHandlePath, hook)
hookServer.Register(healthCheckPath, &healthCheckHandler{})
hookServer.Register(metricsPath, promhttp.Handler())

mgr, err := manager.New(c, manager.Options{
WebhookServer: hookServer,
})
if err != nil {
return errors.Wrapf(err, "Failed to create new webhook manager")
if err := mgr.Add(hookServer); err != nil {
return errors.Wrapf(err, "Failed to add new webhook server")
}

if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
Expand Down
45 changes: 27 additions & 18 deletions pkg/validatingwebhook/blueprint_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,44 @@ package validatingwebhook
import (
"context"
"fmt"
"net/http"

"sigs.k8s.io/controller-runtime/pkg/webhook/admission"

kanister "github.com/kanisterio/kanister/pkg"
crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1"
"github.com/kanisterio/kanister/pkg/blueprint/validate"
"k8s.io/apimachinery/pkg/runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

type BlueprintValidator struct {
decoder *admission.Decoder
}
//+kubebuilder:webhook:path=validate/v1alpha1/blueprint,mutating=false,failurePolicy=fail,sideEffects=None,groups=cr.kanister.io,resources=blueprints,verbs=create,versions=v1alpha1,name=blueprint.cr.kanister.io

func (b *BlueprintValidator) Handle(ctx context.Context, r admission.Request) admission.Response {
bp := &crv1alpha1.Blueprint{}
err := b.decoder.Decode(r, bp)
if err != nil {
return admission.Errored(http.StatusBadRequest, err)
}
type BlueprintValidator struct{}

var _ webhook.CustomValidator = &BlueprintValidator{}

func (b *BlueprintValidator) validate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
log := logf.FromContext(ctx)
bp, ok := obj.(*crv1alpha1.Blueprint)
if !ok {
return nil, fmt.Errorf("expected a Blueprint but got a %T", obj)
}
log.Info("Validating blueprint")
if err := validate.Do(bp, kanister.DefaultVersion); err != nil {
return admission.Denied(fmt.Sprintf("Invalid blueprint, %s\n", err.Error()))
return nil, fmt.Errorf("invalid blueprint, %s", err.Error())
}

return admission.Allowed("")
return nil, nil
}

func (b *BlueprintValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) {
return b.validate(ctx, obj)
}

func (b *BlueprintValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (warnings admission.Warnings, err error) {
return b.validate(ctx, newObj)
}

// InjectDecoder injects the decoder.
func (b *BlueprintValidator) InjectDecoder(d *admission.Decoder) error {
b.decoder = d
return nil
func (b BlueprintValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) {
return b.validate(ctx, obj)
}

0 comments on commit e3e160e

Please sign in to comment.