Open Arnavion opened 5 years ago
Tried to tackle with that recently; set spec_url
to http://127.0.0.1:8001/openapi/v2
, codegen failed with:
[v1_16] INFO src\main.rs:110 Parsing spec file at http://127.0.0.1:8001/openapi/v2 ...
[v1_16] INFO src\main.rs:119 Applying fixups...
[v1_16] operation patchAcmeCertManagerIoV1alpha2NamespacedChallenge is a patch operation but doesn't have a force parameter
I've tried to modify fixups.rs
to skip that for now, replacing returning an Err
with continue
, then codegen failed with:
[v1_16] Nested anonymous types not supported
Any ideas how to implement support for anonymous types?
Depends. Share your AcmeCertManagerIo
CRD.
Also, if the only reason you're attempting this is to get CRUD API for your CRD, you may want to just use k8s-openapi-derive instead. (Read the docs from the source because docs.rs is still broken for proc-macro crates.)
Unfortunately, that's not mine CRD. Those came from cert-manager: https://github.com/jetstack/cert-manager/blob/v0.11.0/deploy/manifests/00-crds.yaml#L29
I guess that Nested anonymous types
codegen refers to is actually a listMeta with corresponding openapi schema: https://gist.github.com/ragne/ecebdbb09a29658c03624c5f03247683
Basically every CRD that allows listing resources having that one, but some refers to it as:
"metadata": {
"description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta_v2"
}
while others put all def into metadata
directly.
I think one can try to construct the appropriate ListMeta struct dynamically or find already defined ListMeta
or replace the literal definition with $ref
.
I guess that
Nested anonymous types
codegen refers to is actually a listMeta with corresponding openapi schema: https://gist.github.com/ragne/ecebdbb09a29658c03624c5f03247683
I'm surprised that Kubernetes is inlining the defintion like that instead of using a $ref
like it does for built-in *List
types. The list type is synthesized by Kubernetes after all, so it should treat it just like a PodList
etc.
It's worth testing if it does that for all CRDs, eg for the one in this repo's test.
I think one can try to construct the appropriate ListMeta struct dynamically or find already defined
ListMeta
or replace the literal definition with$ref
.
Replacing it with a $ref
to ListMeta
isn't the hard part. The hard part is making the decision to replace it, ie determining that ChallengeList
is a list and thus its metadata
ought to be a $ref
to ListMeta
.
Might be wrong, looks like when custom resource is described in code and uses kubebuilder to generate yamls it can also be annotated to generate openapi spec (haven’t yet looked how the generated openapi spec gets into k8s) via +k8s:openapi-gen=true
.
The generator looks for inline
jsonTag to perform inlining
I think one can try to construct the appropriate ListMeta struct dynamically or find already defined
ListMeta
or replace the literal definition with$ref
.Replacing it with a
$ref
toListMeta
isn't the hard part. The hard part is making the decision to replace it, ie determining thatChallengeList
is a list and thus itsmetadata
ought to be a$ref
toListMeta
.
So in https://github.com/Arnavion/k8s-openapi/commit/4c55b8118cc270a9294d7caab656dbb8bad3137e I've implemented emitting lists as aliases of a single k8s_openapi::List<T>
type instead of their raw spec, which means the code generator already has to guess what is a list and what isn't.
Currently it believes anything with an items
property and a metadata
property that's a ref to a ListMeta
is a List
. It should be fine to extend that to also consider anything with a metadata
property that's instead a SchemaKind::Properties
with the same structure as spec.definitions.get("...ListMeta")
.
I use k8s-openapi-codegen
for Traefik CRDs recently. I use some hack directly in k8s-openapi-codegen
codebase, and tweak the Swagger manually. Making a CLI tool to accept arbitrary CRD URL or Swagger file seems valuable.
@wdv4758h Can you share how you did that?
I think it would be super valuable to generate custom API bindings.
@wdv4758h Can you share how you did that?
@ibotty It was years ago, I don't have the source code of the hack version anymore. And I forgot the real steps.
IIRC, what I did was:
k8s-openapi-codegen
, just to make sure I can run itk8s-openapi-codegen/src/supported_version.rs
which will be requested in k8s-openapi-codegen/src/main.rs
(I launched a miniserve with pre-downloaded spec I need)k8s-openapi-codegen
, so need a more simple and plain version)k8s-openapi-codegen
(not sure)k8s-openapi-codegen
has been able to generate bindings from arbitrary file path or URL for quite some time: https://github.com/Arnavion/k8s-openapi/blob/5a079ad7abd5022f62839aa0501a0ab3b57599bd/k8s-openapi-codegen/src/main.rs#L125-L143 It's not meant for general purpose use outside the k8s-openapi crate, but you can try pointing it to your /openapi/v2
endpoint or to a pre-downloaded spec file using an arbitrary version string for the parameter name and see how usable the output is.
The API server exposes its spec at
/openapi/v2
Is it worth allowing a user to run
k8s-openapi-codegen
against this endpoint to generate a custom API bindings crate?Edit: Starting with v1.15, CRDs are also included in the spec: