There are 2 bugs that I thought would get fixed in release 4.0.0 but still persist.
I was getting the following error:
Failed to list *spec.APIProxy: no kind "ApiProxyList" is registered for version "kanali.io/v1"
The fix was to change my type name from APIProxyList to ApiProxyList. Of course this will break golint. It seems as though it expects the type name to match the kind name. However, since we are giving it a runtime.Object telling it what the type should be, why should it matter what the type name is?
In addition, client-go does not seem to be respecting the json tags for a type. For example, client-go will not understand my type unless I have an Items field in my list type. I would think I could name it whatever I want as long as I have json:"items"
It is really unfortunate that in order for client-go to work, I would have to turn off linting...
Is there a fix or a workaround?
Would someone be able to comment on this issue?
@deads2k suggested that this might be fixed with CRDs and that this problem might just be localized to TPRs.
@deads2k suggested that this might be fixed with CRDs and that this problem might just be localized to TPRs.
In particular, the serialization of list kinds from the API server using TPRs used a guess at what the valid ListKind may be. CRDs have a field for the user to specify the actual value.
@deads2k
This issue persists with CRDs. I have created a complete reproducible program along with instructions. Find it here. Here is a recap of the README for that project:
$ minikube start
$ git clone [email protected]:frankgreco/client-go-crd-bug.git
$ cd client-go-crd-bug
$ glide install
$ go build
$ kubectl apply -f crd.yml
$ kubect apply -f example.yml
$ ./client-go-crd-bug --kubeconfig=~/.kube/config
adding crd named example
$ sed -i -e 's/ApiFoo/APIFoo/g' main.go
$ go build
$ ./client-go-crd-bug --kubeconfig=~/.kube/config
E0927 20:37:00.072532 26614 reflector.go:201] github.com/frankgreco/client-go-crd-bug/main.go:96: Failed to list *main.APIFoo: no kind "ApiFooList" is registered for version "bar.io/v1"
Thanks to @liggitt for discussing this with me in the Kubernetes Slack. Here is the summary of our conversation that will result in the closing of this issue:
ApiFoo, then your struct should be type ApiFoo structgolint will notice that in this particular edge case (ApiFoo), having a struct with this name would break one of the rules. However, as I learned the hard way, _golint is not, and will never be, trustworthy enough for its suggestions to be enforced automatically, for example as part of a build process_. However, there is a workaround if you still have a compelling reason not to change your kind or spec names: scheme.AddKnownTypeWithName(schemeGroupVersion.WithKind("ApiFoo"), &APIFoo{})It is highly recommended that the name of the CRD kind match exactly (case sensitive) the name of the golang struct used with it. For example, if your kind is ApiFoo, then your struct should be type ApiFoo struct.
I think this is not just recommended and this may be a must when defining the golang struct of the CRD.
If not so, the CRDList could not be registered and it couldn't use client-go to create instances of a CRD resource which is difficult to find what's wrong until knowing the implicit rule 😢
@flyer103
I agree but what about:
‘’’
scheme.AddKnownTypeWithName(schemeGroupVersion.WithKind("ApiFoo"), &APIFoo{})
‘’’
I have tested it on k8s-v1.7.3 using client-go-v4.0.
If the SchemeBuilder is built from the following, it could use client-go to create instances of a CRD resource but the controller which watches the events of the CRD resource couldn't list the CRDList:
func AddKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypeWithName(schema.GroupVersionKind{
Group: XXX, // CRD Group
Version: XXX, // CRD Version
Kind: XXX, // CRD Kind
},
&CRD_STRUCT{}, // a pointer to an instance of the CRD struct
)
return nil
}
Do I have missed something to register the CRDList?
If the SchemeBuilder is built from the following and the name of the golang struct of the CRD resource is the same as the CRDKind, then it's ok to use client-go to create instances of the CRD resource and watch events of the CRD resource for a controller:
func AddKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(
schema.GroupVersion{
Group: XXX, // CRD Group
Version: XXX, // CRD Version
},
&CRD_STRUCT{}, // a pointer to an instance of the CRD struct
&CRD_LIST_STRUCT{}, // a pointer to an instance of the CRD LIST struct
)
metav1.AddToGroupVersion(scheme, schema.GroupVersion{
Group: XXX, // CRD Group
Version: XXX, // CRD Version
})
return nil
}
@flyer103 How to solve this issue?
Most helpful comment
Thanks to @liggitt for discussing this with me in the Kubernetes Slack. Here is the summary of our conversation that will result in the closing of this issue:
ApiFoo, then your struct should betype ApiFoo structgolintwill notice that in this particular edge case (ApiFoo), having a struct with this name would break one of the rules. However, as I learned the hard way, _golint is not, and will never be, trustworthy enough for its suggestions to be enforced automatically, for example as part of a build process_. However, there is a workaround if you still have a compelling reason not to change your kind or spec names:scheme.AddKnownTypeWithName(schemeGroupVersion.WithKind("ApiFoo"), &APIFoo{})