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

kube::Api lists crd resources of all versions #1659

Open
Razz4780 opened this issue Dec 6, 2024 · 1 comment
Open

kube::Api lists crd resources of all versions #1659

Razz4780 opened this issue Dec 6, 2024 · 1 comment
Labels
bug Something isn't working crd related to custom resource definitions question Direction unclear; possibly a bug, possibly could be improved.

Comments

@Razz4780
Copy link
Contributor

Razz4780 commented Dec 6, 2024

Current and expected behavior

kube::Api always lists resources of all versions, which causes deserialization errors. Code snippet to reproduce:

use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1::CustomResourceDefinition;
use kube::{
    api::{Patch, PatchParams},
    core::crd::merge_crds,
    runtime::{conditions, wait::await_condition},
    CustomResourceExt,
};
use v1::ExampleResource;

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

    #[derive(CustomResource, JsonSchema, Deserialize, Serialize, Clone, Debug)]
    #[kube(
        group = "my.example.group",
        version = "v1",
        kind = "ExampleResource",
        namespaced
    )]
    pub struct ExampleResourceSpec {
        pub field: String,
    }
}

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

    #[derive(CustomResource, JsonSchema, Deserialize, Serialize, Clone, Debug)]
    #[kube(
        group = "my.example.group",
        version = "v2",
        kind = "ExampleResource",
        namespaced
    )]
    pub struct ExampleResourceSpec {
        pub field: u32,
    }
}

#[tokio::test]
async fn test_listing() {
    let config = kube::Config::infer().await.unwrap();
    let client = kube::Client::try_from(config).unwrap();

    apply_crd(client.clone(), v1::ExampleResource::crd()).await;

    let api_v1 = kube::Api::<v1::ExampleResource>::default_namespaced(client.clone());
    api_v1
        .create(
            &Default::default(),
            &ExampleResource::new(
                "res-1",
                v1::ExampleResourceSpec {
                    field: "hello".into(),
                },
            ),
        )
        .await
        .unwrap();

    apply_crd(
        client.clone(),
        merge_crds(
            vec![v1::ExampleResource::crd(), v2::ExampleResource::crd()],
            "v2",
        )
        .unwrap(),
    )
    .await;

    let api_v2 = kube::Api::<v2::ExampleResource>::default_namespaced(client);
    api_v2
        .create(
            &Default::default(),
            &v2::ExampleResource::new("res-2", v2::ExampleResourceSpec { field: 12 }),
        )
        .await
        .unwrap();

    let error_1 = api_v1.list(&Default::default()).await.unwrap_err();
    let error_2 = api_v2.list(&Default::default()).await.unwrap_err();

    // This panics with:
    // SerdeError(Error("invalid type: integer `12`, expected a string", line: 1, column: 955))
    // SerdeError(Error("invalid type: string \"hello\", expected u32", line: 1, column: 501))
    panic!("{error_1:?} {error_2:?}");
}

async fn apply_crd(client: kube::Client, crd: CustomResourceDefinition) {
    let crds: kube::Api<CustomResourceDefinition> = kube::Api::all(client.clone());
    let ssapply = PatchParams::apply("my-example").force();
    crds.patch(
        "exampleresources.my.example.group",
        &ssapply,
        &Patch::Apply(&crd),
    )
    .await
    .unwrap();
    let establish = await_condition(
        crds.clone(),
        "exampleresources.my.example.group",
        conditions::is_crd_established(),
    );
    let _ = tokio::time::timeout(std::time::Duration::from_secs(10), establish)
        .await
        .unwrap();
}

Not sure if this is the intended behavior, but I expected only resources of the exact version to be listed.

Possible solution

No response

Additional context

No response

Environment

Client Version: v1.31.1
Kustomize Version: v5.4.2
Server Version: v1.31.0

Configuration and features

kube = { git = "https://github.com/kube-rs/kube.git", rev = "ecbdafc214538aadc78ec8447f2fa12d0057492b", default-features = false, features = [
    "runtime",
    "derive",
    "client",
    "ws",
    "rustls-tls",
    "oidc",
    "socks5",
    "http-proxy",
] }
k8s-openapi = { version = "0.23", features = ["earliest"] }

Affected crates

kube-client

Would you like to work on fixing this bug?

yes

@Razz4780 Razz4780 added the bug Something isn't working label Dec 6, 2024
@clux
Copy link
Member

clux commented Dec 12, 2024

I think, this is expected? The apiserver ultimately has restrictions on what can be in storage (only 1) and what can be served. You can ask for non-stored versions, but the conversion is done on retrieval and is lossy afaikr. It's explored a bit in the https://github.com/kube-rs/kube/blob/main/examples/crd_derive_multi.rs example.

If you have ideas or other information, happy to hear them though!

@clux clux added question Direction unclear; possibly a bug, possibly could be improved. crd related to custom resource definitions labels Dec 12, 2024
@clux clux changed the title kube::Api lists resources of all versions kube::Api lists crd resources of all versions Dec 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working crd related to custom resource definitions question Direction unclear; possibly a bug, possibly could be improved.
Projects
None yet
Development

No branches or pull requests

2 participants