Closed michaeljmarshall closed 4 years ago
Are you trying to generate the spec for a CRD? Then better use kubebuilder's controller-tools, e.g. the schemapatch
command (https://github.com/kubernetes-sigs/controller-tools/blob/master/cmd/controller-gen/main.go#L140).
I would consider the openapi generator here deprecated and only to be used for the very specific use-case of aggregated API servers.
@sttts -- thanks for your insight here. I didn't realize the limited scope of this generator. I have a SparkApplication
CRD that is defined in the spark-on-k8s-operator repo. My end goal is to generate a Java client that knows about the CRDs defined in that project so that I can introduce type safety as well as make it easier to handle updates to the spark operator project. After searching through various projects, I had thought I would need to use this project to generate the go code (modules?) that I could then use to generate the openapi-spec json file. I thought I'd need an output similar to the one found in the kubernetes
project found here, and then I'd use the json file as the input to the kubernetes-client/gen project. Are you saying there is another way to make the openapi-spec json file for use by the client gen project? Or are you saying I can use the resulting yaml file from the controller-tools
command to build the Java client?
https://github.com/kubernetes-sigs/controller-tools/blob/master/cmd/controller-gen/main.go#L140 will give you a schema in your CRD manifest. Create that in a cluster and download the OpenAPI spec from the cluster: kubectl get --raw /openapi/v2
. That should do it for client generators.
@sttts - I am not sure I am following you. It seems inverted to me that I'd need to inspect my kubernetes cluster in order to get an OpenApi spec for a well defined CRD. There should be a way to generate an OpenApi spec that I could then use to generate a client library containing the data models for that CRD. I'd use the generate CRD code as a library to simplify serialization and deserialization of the objects when calling the CustomObjectsApi
.
I opened this issue because I was able to generate the OpenApi spec using this project along with my minor change (described above) to the k8s InternalEvent
type defined in the k8s apimachinery package. From the OpenApi spec, I was able to generate a client library containing the classes for the CRD. (I used this project https://github.com/kubernetes-client/gen to generate the client.)
From my perspective, this project seems capable of generating a valid OpenApi spec that could be used to generate data models that align with CRDs.
It might partly work now, but is no supported use-case of openapi-gen and it won't be extended towards CRDs. The spec is incomplete and also partly wrong (AFAIK, int-or-string is not generated correctly, maybe other types too).
It surprises me that there isn't an easy way to generate library definitions for CRDs. Thank you for the additional context and help here.
Reading comments on bug was key in helping me solve my own bug. Thank you.
Summary
I'm trying to use this library to generate the JSON openapi spec for the spark-on-k8s-operator, but I am running into an issue going from the generated models to the spec. Ultimately, I think root issue is a missing
+k8s:openapi-gen=false
annotation in the kubernetes apimachinery module. Since those annotations are used by this library, I wanted to verify my proposed change here before submitting a PR there tokubernetes/kubernetes
.Proprosal
Add the
+k8s:openapi-gen=false
annotation to theInternalEvent
type defined in k8s apimachinery. Link to the actual type definition: type InternalEvent. Reference copied here for convenience:Environment Setup
To simplify the duplication of my issue, I've created the following Dockerfile.
After running
docker build -t spark-on-k8s-operator:codegen
passing in the above Dockerfile, you can rundocker run -it spark-on-k8s-operator:codegen
to get access to theopenapi_generated.go
file in the initial directory after getting into the container.Issue
Now that we have a shared set up, you can open
openapi_generated.go
and inside, find one of the defined models:It is problematic that the model specifies
k8s.io/apimachinery/pkg/runtime.Object
as a dependency because runtime.Object is not annotated to be a part of the output of running openapi-gen. Because this dependency isn't defined within the generated output, I get the following error when I call thek8s.io/kube-openapi/pkg/builder.BuildOpenAPIDefinitionsForResources
method (defined in this project):Possible Solution
I was able to get past this issue by going into the vendored file
/go/src/github.com/GoogleCloudPlatform/spark-on-k8s-operator/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/watch.go
, adding the proposed annotation, and then re-running the openapi-gen code. That change successfully removes the reference toInternalEvent
in the generated output, which removes the dependency onruntime.Object
, and then the subsequent call toBuildOpenAPIDefinitionsForResources
can complete successfully.It seems to me that the most reasonable solution is to remove the
InternalEvent
from the openapi-gen output considering that this type is excluded from protobuf generation, that it's name implies it'd be unnecessary in a client, and that theruntime.Object
is not new and is not annotated to be included in the openapi-gen output. However, I have not used this library before, and I am new to kubernetes code generation. It's possible that I'm not using this project correctly. Does it make sense to submit a PR to thekubernetes
project to add the annotation? Any help or direction here is greatly appreciated. Thanks!