Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing apimachinery::pkg::apis::meta::v1::CreateOptions #160

Closed
gauravgahlot opened this issue Jan 14, 2025 · 3 comments
Closed

Missing apimachinery::pkg::apis::meta::v1::CreateOptions #160

gauravgahlot opened this issue Jan 14, 2025 · 3 comments

Comments

@gauravgahlot
Copy link

I'm using v0.24.0 with v1_31 feature. I see that the type DeleteOptions is present, however, the CreateOptions is not.

Here is its Go equivalent - https://pkg.go.dev/k8s.io/[email protected]/pkg/apis/meta/v1#CreateOptions

I would really appreciate if this can be fixed. If not, what do you recommend?

@Arnavion
Copy link
Owner

I see that the type DeleteOptions is present, however, the CreateOptions is not.

DeleteOptions exists because it's defined in the OpenAPI spec:

"io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions": {
  "description": "DeleteOptions may be provided when deleting an API object.",
  "properties": {

... which in turn is because it's used as the body of some requests (notice "in": "body"):

"parameters": {
  "body-2Y1dVQaQ": {
    "in": "body",
    "name": "body",
    "schema": {
      "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions"
    }
  },

CreateOptions is not in the spec. The DryRun, FieldManager and FieldValidation fields that it contains are only ever set in the query string, not a request body, so the OpenAPI spec just references those fields directly instead of as a type containing those three fields (notice "in": "query"):

"parameters": [
  {
    "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed",
    "in": "query",
    "name": "dryRun",
    "type": "string",
    "uniqueItems": true
  },
"parameters": {
  "fieldManager-7c6nTn1T": {
    "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).",
    "in": "query",
    "name": "fieldManager",
    "type": "string",
    "uniqueItems": true
  },
{
  "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default in v1.23+ - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.",
  "in": "query",
  "name": "fieldValidation",
  "type": "string",
  "uniqueItems": true
}

The golang client just has a made-up type for convenience, ie so that create API just has to take one parameter instead of three. k8s-openapi used to have the same made-up type for the same reason back when it contained codegen for API operations. API operations codegen was removed in v0.20.0 so types like CreateOptional are no longer necessary in k8s-openapi itself.


If not, what do you recommend?

If you're using kube, you'd be using kube::Api::create and the PostParams parameter of that is your CreateOptions.

@gauravgahlot
Copy link
Author

Thank you! I'm actually working on a project called Argoflows - a Rust client for Argo Workflows.

I have been referring to the Argo Workflows OpenAPI spec, which happens to have the CreateOptions type definition.

As of now I'm not using kube, so maybe I should create a CreateOptions type within Argoflows.

That being said, I truly admire your work with k8s-openapi. Thank you 🙇.

I'm new to Rust, and I would truly appreciate if you have any suggestions for the project I'm working on.

@Arnavion
Copy link
Owner

Right, the Argo Workflows spec defines CreateOptions because it is used as fields of other resource types. The operator code uses the Kubernetes CreateOptions type so it ends up getting emitted in their OpenAPI spec.

In any case, for arbirary OpenAPI specs like yours you would not find the types within k8s-openapi. You have a few options:

  1. You can reuse the code generator library that k8s-openapi uses, k8s-openapi-codegen-common, to generate similar code for the resource types in the Argo Workflows spec. There is an old example at https://github.com/ctron/openshift-openapi for the OpenShift spec. The code generator is designed for this (it's why the MapNamespace trait exists), but AFAIK nobody has used it since the OpenShift one four years ago so I can't guarantee it's fully functional for external specs today. If you find something that makes it not work I will fix it.

  2. You can get the whole spec from your cluster while the Argo Workflows operator is installed (there's an /openapi/v2 endpoint to download it), ie both the built-in Kubernetes types as well as that CRD's related types in one spec, and use the k8s-openapi-codegen binary on that spec. This will generate a whole new k8s-openapi crate bespoke to your cluster. Since it'll be a strict superset in functionality, you will be able to [patch] it in into your crate graph and still be able to use other crates that depend on k8s-openapi like kube. See Running codegen against server-provided swagger spec #38 . As I wrote there, this is not the primary way I expect people to use k8s-openapi-codegen (that is option 1), but it is an option.

  3. You can use regular k8s-openapi and manually define your types in Rust, and manually keep them in sync with the actual operator. This option is the best when the operator is the Rust code (which is what $dayjob does for example), but in your case where it's a separate codebase by different people, keeping the two in sync manually can be a chore and source of bugs. I know of at least one project that switched from Rust + k8s-openapi to golang just to be able to reuse the golang code of the third party they were interfacing with, for this exact reason.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants