Clean up webhook handler interface

Signed-off-by: James Munnelly <james@munnelly.eu>
This commit is contained in:
James Munnelly 2019-10-17 12:47:58 +01:00
parent ee9cbf25af
commit ca9e8f33b2
7 changed files with 18 additions and 69 deletions

View File

@ -59,8 +59,8 @@ var (
}
)
var validationHook handlers.ValidatingAdmissionHook = handlers.NewFuncBackedValidator(logs.Log, GroupName, webhook.Scheme, validationFuncs)
var mutationHook handlers.MutatingAdmissionHook = handlers.NewSchemeBackedDefaulter(logs.Log, GroupName, webhook.Scheme)
var validationHook handlers.ValidatingAdmissionHook = handlers.NewFuncBackedValidator(logs.Log, webhook.Scheme, validationFuncs)
var mutationHook handlers.MutatingAdmissionHook = handlers.NewSchemeBackedDefaulter(logs.Log, webhook.Scheme)
func main() {
klog.InitFlags(flag.CommandLine)

View File

@ -19,7 +19,6 @@ go_library(
"@io_k8s_apimachinery//pkg/runtime/serializer:go_default_library",
"@io_k8s_apimachinery//pkg/runtime/serializer/json:go_default_library",
"@io_k8s_apimachinery//pkg/util/validation/field:go_default_library",
"@io_k8s_client_go//rest:go_default_library",
],
)
@ -28,7 +27,6 @@ go_test(
srcs = ["mutation_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/webhook/handlers/testdata/apis/testgroup:go_default_library",
"//pkg/webhook/handlers/testdata/apis/testgroup/install:go_default_library",
"@com_github_mattbaird_jsonpatch//:go_default_library",
"@io_k8s_api//admission/v1beta1:go_default_library",

View File

@ -18,37 +18,16 @@ package handlers
import (
admissionv1beta1 "k8s.io/api/admission/v1beta1"
"k8s.io/apimachinery/pkg/runtime/schema"
restclient "k8s.io/client-go/rest"
)
type AdmissionHook interface {
// Initialize is called as a post-start hook
Initialize(kubeClientConfig *restclient.Config, stopCh <-chan struct{}) error
}
type ValidatingAdmissionHook interface {
AdmissionHook
// ValidatingResource is the resource to use for hosting your admission webhook. If the hook implements
// MutatingAdmissionHook as well, the two resources for validating and mutating admission must be different.
// Note: this is (usually) not the same as the payload resource!
ValidatingResource() (plural schema.GroupVersionResource, singular string)
// Validate is called to decide whether to accept the admission request. The returned AdmissionResponse
// must not use the Patch field.
Validate(admissionSpec *admissionv1beta1.AdmissionRequest) *admissionv1beta1.AdmissionResponse
}
type MutatingAdmissionHook interface {
AdmissionHook
// MutatingResource is the resource to use for hosting your admission webhook. If the hook implements
// ValidatingAdmissionHook as well, the two resources for validating and mutating admission must be different.
// Note: this is (usually) not the same as the payload resource!
MutatingResource() (plural schema.GroupVersionResource, singular string)
// Admit is called to decide whether to accept the admission request. The returned AdmissionResponse may
// use the Patch field to mutate the object from the passed AdmissionRequest.
Admit(admissionSpec *admissionv1beta1.AdmissionRequest) *admissionv1beta1.AdmissionResponse
Mutate(admissionSpec *admissionv1beta1.AdmissionRequest) *admissionv1beta1.AdmissionResponse
}

View File

@ -28,43 +28,29 @@ import (
admissionv1beta1 "k8s.io/api/admission/v1beta1"
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"
apijson "k8s.io/apimachinery/pkg/runtime/serializer/json"
restclient "k8s.io/client-go/rest"
)
type SchemeBackedDefaulter struct {
log logr.Logger
groupName string
scheme *runtime.Scheme
codec runtime.Codec
log logr.Logger
scheme *runtime.Scheme
codec runtime.Codec
}
func NewSchemeBackedDefaulter(log logr.Logger, groupName string, scheme *runtime.Scheme) *SchemeBackedDefaulter {
func NewSchemeBackedDefaulter(log logr.Logger, scheme *runtime.Scheme) *SchemeBackedDefaulter {
factory := serializer.NewCodecFactory(scheme)
serializer := apijson.NewSerializerWithOptions(apijson.DefaultMetaFactory, scheme, scheme, apijson.SerializerOptions{})
encoder := factory.WithoutConversion().EncoderForVersion(serializer, nil)
decoder := factory.UniversalDeserializer()
return &SchemeBackedDefaulter{
log: log,
groupName: groupName,
scheme: scheme,
codec: runtime.NewCodec(encoder, decoder),
log: log,
scheme: scheme,
codec: runtime.NewCodec(encoder, decoder),
}
}
func (c *SchemeBackedDefaulter) Initialize(kubeClientConfig *restclient.Config, stopCh <-chan struct{}) error {
return nil
}
func (c *SchemeBackedDefaulter) MutatingResource() (plural schema.GroupVersionResource, singular string) {
gv := admissionv1beta1.SchemeGroupVersion
gv.Group = c.groupName
return gv.WithResource("mutations"), "mutation"
}
func (c *SchemeBackedDefaulter) Admit(admissionSpec *admissionv1beta1.AdmissionRequest) *admissionv1beta1.AdmissionResponse {
func (c *SchemeBackedDefaulter) Mutate(admissionSpec *admissionv1beta1.AdmissionRequest) *admissionv1beta1.AdmissionResponse {
status := &admissionv1beta1.AdmissionResponse{}
// decode the raw object data

View File

@ -29,7 +29,6 @@ import (
"k8s.io/klog/klogr"
"k8s.io/utils/diff"
"github.com/jetstack/cert-manager/pkg/webhook/handlers/testdata/apis/testgroup"
"github.com/jetstack/cert-manager/pkg/webhook/handlers/testdata/apis/testgroup/install"
)
@ -52,7 +51,7 @@ func TestDefaultCertificate(t *testing.T) {
log := klogr.New()
klog.InitFlags(flag.CommandLine)
c := NewSchemeBackedDefaulter(log, testgroup.GroupName, scheme)
c := NewSchemeBackedDefaulter(log, scheme)
tests := map[string]testT{
"apply defaults to TestType": {
inputRequest: admissionv1beta1.AdmissionRequest{
@ -91,7 +90,7 @@ func TestDefaultCertificate(t *testing.T) {
for n, test := range tests {
t.Run(n, func(t *testing.T) {
runTest(t, c.Admit, test)
runTest(t, c.Mutate, test)
})
}
}
@ -101,9 +100,9 @@ type testT struct {
expectedResponse admissionv1beta1.AdmissionResponse
}
type mutateFn func(request *admissionv1beta1.AdmissionRequest) *admissionv1beta1.AdmissionResponse
type admitFn func(request *admissionv1beta1.AdmissionRequest) *admissionv1beta1.AdmissionResponse
func runTest(t *testing.T, fn mutateFn, test testT) {
func runTest(t *testing.T, fn admitFn, test testT) {
resp := fn(&test.inputRequest)
if !reflect.DeepEqual(&test.expectedResponse, resp) {
t.Errorf("Response was not as expected: %v", diff.ObjectGoPrintSideBySide(&test.expectedResponse, resp))

View File

@ -27,21 +27,18 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/client-go/rest"
)
type funcBackedValidator struct {
log logr.Logger
groupName string
decoder runtime.Decoder
validations map[schema.GroupVersionKind]ValidationFunc
}
func NewFuncBackedValidator(log logr.Logger, groupName string, scheme *runtime.Scheme, fns map[schema.GroupVersionKind]ValidationFunc) *funcBackedValidator {
func NewFuncBackedValidator(log logr.Logger, scheme *runtime.Scheme, fns map[schema.GroupVersionKind]ValidationFunc) *funcBackedValidator {
factory := serializer.NewCodecFactory(scheme)
return &funcBackedValidator{
log: log,
groupName: groupName,
log: log,
// TODO: switch to using UniversalDecoder and make validation functions
// run against the internal apiversion
decoder: factory.UniversalDeserializer(),
@ -51,16 +48,6 @@ func NewFuncBackedValidator(log logr.Logger, groupName string, scheme *runtime.S
type ValidationFunc func(runtime.Object) field.ErrorList
func (c *funcBackedValidator) Initialize(kubeClientConfig *rest.Config, stopCh <-chan struct{}) error {
return nil
}
func (c *funcBackedValidator) ValidatingResource() (plural schema.GroupVersionResource, singular string) {
gv := admissionv1beta1.SchemeGroupVersion
gv.Group = c.groupName
return gv.WithResource("validations"), "validation"
}
func (c *funcBackedValidator) Validate(admissionSpec *admissionv1beta1.AdmissionRequest) *admissionv1beta1.AdmissionResponse {
status := &admissionv1beta1.AdmissionResponse{}

View File

@ -240,7 +240,7 @@ func (s *Server) validate(obj runtime.Object) runtime.Object {
func (s *Server) mutate(obj runtime.Object) runtime.Object {
review := obj.(*admissionv1beta1.AdmissionReview)
resp := s.MutationWebhook.Admit(review.Request)
resp := s.MutationWebhook.Mutate(review.Request)
review.Response = resp
return review
}