Arnavion / k8s-openapi

Rust definitions of the resource types in the Kubernetes client API
Apache License 2.0
379 stars 41 forks source link

add optional schemars::JsonSchema derive #101

Closed cassandracomar closed 3 years ago

cassandracomar commented 3 years ago

this updates struct generation to include a derive for the schemars::JsonSchema.

fixes #86

Arnavion commented 3 years ago

Does this fix https://github.com/Arnavion/k8s-openapi/issues/86#issuecomment-760550161 ?

Eg look at the generated schema for api::core::v1::Pod with something like rustc --pretty=expanded. Does it have the "api_version" and "kind" fields?

cassandracomar commented 3 years ago

this generates the schema via schemars and does not pull in the schema from upstream (something schemars does not yet support - I don't think $refs are valid within CRD schema definitions, in any case, so we must embed these subschemas somehow).

so, per https://github.com/Arnavion/k8s-openapi/issues/86#issuecomment-777912231, $refs are expanded by injecting the subschema for the child struct, via schemars. thus, the following generation script:

    let gen = schemars::gen::SchemaSettings::openapi3()
        .with(|s| {
            s.inline_subschemas = true;
            s.meta_schema = None;
        })
        .into_generator();
    let schema = gen.into_root_schema_for::<Pod>();
    println!("{}", serde_json::to_string_pretty(&schema).unwrap());

yields: https://gist.github.com/cassandracomar/0bf6e3522ed203326c9dcf05e5f791c1

note: this does not include the api_version and kind fields -- the available, top-level fields are metadata, spec, and status, which I think matches upstream.

the generated schema should match the upstream schema with the $refs inlined unless the generated rust structs differ from the schemas. I found a couple of spots where this occurs (x-kubernetes-int-or-string and the handling around Vec<T> both popped up while attempting to use this) and have handling for such cases to restore the original schema as best we can. there may be other cases lurking that still need such fixing up.

we could instead manually construct each JsonSchema impl to inline the upstream schema after pre-processing to inline $refs ourselves but this is considerably more work.

Arnavion commented 3 years ago

note: this does not include the api_version and kind fields -- the available, top-level fields are metadata, spec, and status, which I think matches upstream.

No, upstream's OpenAPI spec for model types does include the api_version and kind fields. Eg:

    "io.k8s.api.core.v1.Pod": {
      "description": "Pod is a collection of containers that can run on a host. This resource is created by clients and scheduled onto hosts.",
      "properties": {
        "apiVersion": {
          "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
          "type": "string"
        },
        "kind": {
          "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
          "type": "string"
        },
        "metadata": {
          "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta",
          "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata"
        },
        "spec": {
          "$ref": "#/definitions/io.k8s.api.core.v1.PodSpec",
          "description": "Specification of the desired behavior of the pod. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status"
        },
        "status": {
          "$ref": "#/definitions/io.k8s.api.core.v1.PodStatus",
          "description": "Most recently observed status of the pod. This data may not be up to date. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status"
        }
      },
      "type": "object",
      "x-kubernetes-group-version-kind": [
        {
          "group": "",
          "kind": "Pod",
          "version": "v1"
        }
      ]
    },

That was why I was making the point I was re: needing to use the original spec's type (to be precise, the swagger20::Schema and swagger20::SchemaKind re-serialized, so as to catch the changes from any fixups) instead of #[derive]ing it from the generated types.


we could instead manually construct each JsonSchema impl to inline the upstream schema after pre-processing to inline $refs ourselves but this is considerably more work.

Does the suggestion in https://github.com/Arnavion/k8s-openapi/issues/86#issuecomment-777912231 work to make that easier?

cassandracomar commented 3 years ago

closing in favor of https://github.com/Arnavion/k8s-openapi/pull/104