I'm trying to follow this example and building my webhook https://github.com/kubernetes-sigs/controller-runtime/blob/master/examples/builtins/validatingwebhook.go
However, having this webhook it does not work
type MyTypeValidator struct {
client.Client
*admission.Decoder
}
var _ inject.Client = &MyTypeValidator{}
func (v *MyTypeValidator) Handle(ctx context.Context, req admission.Request) admission.Response {
quota := &MyType{}
return admission.Allowed("")
}
// MyTypeValidator implements inject.Client.
// A client will be automatically injected.
// InjectClient injects the client.
func (v *MyTypeValidator) InjectClient(c client.Client) error {
v.Client = c
return nil
}
// MyTypeValidator implements admission.DecoderInjector.
// A decoder will be automatically injected.
// InjectDecoder injects the decoder.
func (v *MyTypeValidator) InjectDecoder(d *admission.Decoder) error {
v.Decoder = d
return nil
}
I get this error:
invalid field type interface{sigs.k8s.io/controller-runtime/pkg/client.Reader; sigs.k8s.io/controller-runtime/pkg/client.StatusClient; sigs.k8s.io/controller-runtime/pkg/client.Writer}
The only difference with the example is that the struct there podValidator is private while I have it public.
Solved this by following the exact implementation of the defaulter and validator.
func ValidatingWebhookFor() *admission.Webhook {
return &admission.Webhook{
Handler: &validatingHandler{},
}
}
type validatingHandler struct {
client client.Client
decoder *admission.Decoder
}
var _ inject.Client = &validatingHandler{}
var _ admission.Handler = &validatingHandler{}
func (v *validatingHandler) Handle(ctx context.Context, req admission.Request) admission.Response {
quota := &MyType{}
return admission.Allowed("")
}
// validatingHandler implements inject.Client.
// A client will be automatically injected.
// InjectClient injects the client.
func (v *validatingHandler) InjectClient(c client.Client) error {
v.client = c
return nil
}
// validatingHandler implements admission.DecoderInjector.
// A decoder will be automatically injected.
// InjectDecoder injects the decoder.
func (v *validatingHandler) InjectDecoder(d *admission.Decoder) error {
v.decoder = d
return nil
}
public vs private should not matter here.
I'm not able to reproduce the issue using the code in https://github.com/kubernetes-sigs/controller-runtime/issues/780#issue-554773367.
If you are using CRD, why not using the Defaulter and the Validator interfaces?
I needed to use the client and I could not see any way to use it via the defaulter or the validator
/priority awaiting-more-evidence
yeah. it does not work. refkubebuilder#1228
See the response to that issue https://github.com/kubernetes-sigs/kubebuilder/issues/1228#issuecomment-562347631
I just tested the the example checked into controller-runtime master, it works fine. Is there a more specific question you have? Or a repro for a scenario you expect to work?
i tried and it does not work,too. It is interesting that I tried first time and it worked, but after I do make docker-build and make deploy , I add more validatingwebhook (for namespace and others), then it failed.
$ make run
go: creating new go.mod: module tmp
go: found sigs.k8s.io/controller-tools/cmd/controller-gen in sigs.k8s.io/controller-tools v0.2.5
/root/mygo/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
g.hz.netease.com/k8s/scud/api/v1:-: invalid field type interface{sigs.k8s.io/controller-runtime/pkg/client.Reader; sigs.k8s.io/controller-runtime/pkg/client.StatusClient; sigs.k8s.io/controller-runtime/pkg/client.Writer}
Error: not all generators ran successfully
run `controller-gen object:headerFile=hack/boilerplate.go.txt paths=./... -w` to see all available markers, or `controller-gen object:headerFile=hack/boilerplate.go.txt paths=./... -h` for usage
Makefile:55: recipe for target 'generate' failed
make: *** [generate] Error 1
Is it possible that some generate code or files cause this failure?
There is no makefile in the example I linked. I assume this is a controller you鈥檙e writing. Can you please provide a complete, minimal repro to understand the issue?
/assign
Using the validator from https://github.com/kubernetes-sigs/controller-runtime/issues/780#issue-554773367, this also builds/starts up fine for me. Haven't validated runtime.
I tried again and now I'm sure that it is error when make generate because I can successfully run make manifests ; go run ./main.go
I tried again and now I'm sure that it is error when make generate because I can successfully run make manifests ; go run ./main.go
Looking at your error:
g.hz.netease.com/k8s/scud/api/v1:-: invalid field type interface{sigs.k8s.io/controller-runtime/pkg/client.Reader; sigs.k8s.io/controller-runtime/pkg/client.StatusClient; sigs.k8s.io/controller-runtime/pkg/client.Writer}
seems like you may be attempting to embed a client into a CRD? That won't work for the reason you're seeing, it's an interface.
As far as this issue is concerned, I'd say the example is still valid. If someone can produce a repro, feel free to reopen.
/close
@alexeldeib: Closing this issue.
In response to this:
As far as this issue is concerned, I'd say the example is still valid. If someone can produce a repro, feel free to reopen.
/close
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.
see the same error when trying to add a webhook for native k8s resource in a KubeBuilder project:
invalid field type interface{sigs.k8s.io/controller-runtime/pkg/client.Reader; sigs.k8s.io/controller-runtime/pkg/client.StatusClient; sigs.k8s.io/controller-runtime/pkg/client.Writer}
and figured out why.
tldr: move the webhook file out of your kubebuilder CRD dir: ./api/_your-crd-version_
The error is generated by controller-gen when running make run, simply run
controller-gen object paths="./..." output:stdout
to reproducer the error.
It tries to generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. The struct in code example contains a field which is an interface:
type validatingHandler struct {
client client.Client // client.Client is an interface <<<<<<<<<<<<<<<---
decoder *admission.Decoder
}
It is not supported by controller-gen, thus the error.
Since we don't need the code generation for this struct, simply moves it out of that dir, the the error will gone.
Most helpful comment
Solved this by following the exact implementation of the
defaulterandvalidator.