Skip to content

serde(default) and KubeSchema - no function or associated item named default #1805

@tmsdce

Description

@tmsdce

Current and expected behavior

Hi,

First, thank you for your work on this crate, building k8s-related stuff with it is really nice

I'd like to use CEL related configuration in my CRD but it seems like KubeSchema doesn't play well with #[serde(default)].

Given the following code:

fn main() {
    println!("{}", serde_yaml::to_string(&MyCrd::crd()).unwrap());
}

#[derive(CustomResource, Deserialize, Serialize, Clone, Debug, KubeSchema)]
#[kube(kind = "MyCrd", group = "mygroup.io", version = "v1", namespaced)]
#[serde(rename_all = "camelCase")]
#[serde(default)]
struct MyCrdSpec {
    field_one: String,
    field_two: String,
}

impl Default for MyCrdSpec {
    fn default() -> Self {
        Self {
            field_one: "default_value_1".to_string(),
            field_two: "default_value_2".to_string(),
        }
    }
}

This fails to compile:

error[E0599]: no function or associated item named `default` found for struct `MyCrdSpecValidated` in the current scope
  --> src/main.rs:9:64
   |
9  | #[derive(CustomResource, Deserialize, Serialize, Clone, Debug, KubeSchema)]
   |                                                                ^^^^^^^^^^ function or associated item not found in `MyCrdSpecValidated`
...
13 | pub struct MyCrdSpec {
   | -------------------- function or associated item `default` not found for this struct
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `default`, perhaps you need to implement it:
           candidate #1: `Default`
   = note: this error originates in the derive macro `::schemars::JsonSchema` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0599`.

Using JsonSchema instead of KubeSchema makes this code compile, but you can't use CEL related configuration.

The workaround I found for now is not using the Default trait implementation at all (and not using the #[serde(default)] attribute on the struct), but defining default functions for each field of my struct, like so:

#[derive(CustomResource, Deserialize, Serialize, Clone, Debug, KubeSchema)]
#[kube(kind = "MyCrd", group = "mygroup.io", version = "v1", namespaced)]
#[serde(rename_all = "camelCase")]
struct MyCrdSpec {
    #[serde(default = "MyCrdSpec::default_for_field_one")]
    field_one: String,
    #[serde(default = "MyCrdSpec::default_for_field_two")]
    field_two: String,
}

impl MyCrdSpec {
    fn default_for_field_one() -> String {
        "default_value_1".to_string()
    }
    fn default_for_field_two() -> String {
        "default_value_2".to_string()
    }
}

This compiles fine but can quickly become cumbersome as you add fields with more complex types.

Possible solution

No response

Additional context

This issue seems related to #1746

Environment

Kubectl version

Client Version: v1.30.3
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.33.1

Configuration and features

k8s-openapi = { version = "0.25.0", features = ["v1_33", "schemars"] }
kube = { version = "1.1.0", features = ["runtime", "derive"] }
schemars = { version = "0.8", features = ["chrono"] }
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
serde_yaml = "0.9.34"

Affected crates

No response

Would you like to work on fixing this bug?

None

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions