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

runtime.RawExtension processing #75

Open
henderiw opened this issue Jul 21, 2022 · 2 comments
Open

runtime.RawExtension processing #75

henderiw opened this issue Jul 21, 2022 · 2 comments
Labels
help wanted Extra attention is needed

Comments

@henderiw
Copy link

henderiw commented Jul 21, 2022

runtime.RawExtensions serves as a blob in the k8s CRD afaik and is reflected as an object in the openapi spec, like this.

The specific objects are origin and target, which are defined in go as following

// TransformInputSpec struct
type TransformInputSpec struct {
	Origin runtime.RawExtension `json:"origin,omitempty"`
	Target runtime.RawExtension `json:"target,omitempty"`
}
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  annotations:
    controller-gen.kubebuilder.io/version: v0.9.0
  creationTimestamp: null
  name: transforminputs.app.yndd.io
spec:
  group: app.example.io
  names:
    categories:
    - app
    kind: TransformInput
    listKind: TransformInputList
    plural: transforminputs
    singular: transforminput
  scope: Namespaced
  versions:
  - name: v1alpha1
    schema:
      openAPIV3Schema:
        description: TransformInput is the Schema for the TransformInput API
        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:
            type: object
          spec:
            description: TransformInputSpec struct
            properties:
              origin:
                type: object
              target:
                type: object
            type: object
        type: object
    served: true
    storage: true

when I use kopium to generate the rust code I get this.

use kube::CustomResource;
use schemars::JsonSchema;
use serde::{Serialize, Deserialize};

/// TransformInputSpec struct
#[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema)]
#[kube(
    group = "app.example.io",
    version = "v1alpha1",
    kind = "TransformInput",
    plural = "transforminputs"
)]
#[kube(namespaced)]
pub struct TransformInputSpec {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub origin: Option<TransformInputOrigin>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub target: Option<TransformInputTarget>,
}

#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub struct TransformInputOrigin {
}

#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub struct TransformInputTarget {
}

As you can see the struct TransformInputOrigin and TransformInputTarget are empty. The issue is that when you serializer/deserializerl it in json/yaml the data behind these object is no longer accessible.
When I change it to the following manually the marshal/unmarshal function works as the serde_json::Value is seen as a generic object in the serializer/deserializer afaik.

use kube::CustomResource;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value;

/// TransformInputSpec struct
#[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema)]
#[kube(
    group = "app.example.io",
    version = "v1alpha1",
    kind = "TransformInput",
    plural = "transforminputs"
)]
#[kube(namespaced)]
pub struct TransformInputSpec {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub origin: Option<Value>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub target: Option<Value>,
}

Can this be accommodated?

@clux
Copy link
Member

clux commented Jul 21, 2022

Hm, crd specification wise, I feel like the schema should really generate those objects (origin and target) with a x-preserve-unknown-fields specifier (see #31) so that we know that it's worth deserialising the properties into a serde_json::Value, because otherwise, I think what we are doing is technically correct.

However, it's possible we could have a flag for making empty-struct always use Value rather than empty structs. Need to consider this when implementing #31.

Thanks for the report, will try to dig into this when I have time.

@clux clux added the help wanted Extra attention is needed label Aug 2, 2022
@clux
Copy link
Member

clux commented Apr 25, 2024

We did a partial step in this direction in #230 but i believe there's probably one more step like that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants