From 4ea04d3ccf120fdf4b7ed4d7c2c532a2602d970a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 1 Nov 2021 12:06:17 +0100 Subject: [PATCH 01/13] Allow opting out of schema derivation per type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Teo Klestrup Röijezon --- examples/Cargo.toml | 5 ++--- examples/crd_derive_no_schema.rs | 26 ++++++++++---------------- kube-derive/Cargo.toml | 4 ---- kube-derive/src/custom_resource.rs | 8 +++++--- 4 files changed, 17 insertions(+), 26 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 7f762faac..44a8c71aa 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -14,9 +14,8 @@ license = "Apache-2.0" release = false [features] -default = ["native-tls", "schema", "kubederive", "ws", "latest", "runtime"] -kubederive = ["kube/derive"] # by default import kube-derive with its default features -schema = ["kube-derive/schema"] # crd_derive_no_schema shows how to opt out +default = ["native-tls", "kubederive", "ws", "latest", "runtime"] +kubederive = ["kube/derive"] native-tls = ["kube/client", "kube/native-tls"] rustls-tls = ["kube/client", "kube/rustls-tls"] runtime = ["kube/runtime"] diff --git a/examples/crd_derive_no_schema.rs b/examples/crd_derive_no_schema.rs index 89bd95c86..d72aa11b6 100644 --- a/examples/crd_derive_no_schema.rs +++ b/examples/crd_derive_no_schema.rs @@ -1,25 +1,26 @@ -#[cfg(not(feature = "schema"))] use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1::{ CustomResourceDefinition, CustomResourceValidation, JSONSchemaProps, }; -#[cfg(not(feature = "schema"))] use kube_derive::CustomResource; -#[cfg(not(feature = "schema"))] use serde::{Deserialize, Serialize}; +use kube_derive::CustomResource; +use serde::{Deserialize, Serialize}; /// CustomResource with manually implemented schema /// -/// NB: Everything here is gated on the example's `schema` feature not being set -/// /// Normally you would do this by deriving JsonSchema or manually implementing it / parts of it. /// But here, we simply drop in a valid schema from a string and avoid schemars from the dependency tree entirely. -#[cfg(not(feature = "schema"))] #[derive(CustomResource, Serialize, Deserialize, Debug, Clone)] -#[kube(group = "clux.dev", version = "v1", kind = "Bar", namespaced)] +#[kube( + group = "clux.dev", + version = "v1", + kind = "Bar", + namespaced, + derive_schema = false +)] pub struct MyBar { bars: u32, } -#[cfg(not(feature = "schema"))] -const MANUAL_SCHEMA: &'static str = r#" +const MANUAL_SCHEMA: &str = r#" type: object properties: spec: @@ -31,7 +32,6 @@ properties: - bars "#; -#[cfg(not(feature = "schema"))] impl Bar { fn crd_with_manual_schema() -> CustomResourceDefinition { use kube::CustomResourceExt; @@ -47,18 +47,12 @@ impl Bar { } } -#[cfg(not(feature = "schema"))] fn main() { let crd = Bar::crd_with_manual_schema(); println!("{}", serde_yaml::to_string(&crd).unwrap()); } -#[cfg(feature = "schema")] -fn main() { - eprintln!("This example it disabled when using the schema feature"); -} // Verify CustomResource derivable still -#[cfg(not(feature = "schema"))] #[test] fn verify_bar_is_a_custom_resource() { use kube::Resource; diff --git a/kube-derive/Cargo.toml b/kube-derive/Cargo.toml index eb44d65bf..d333d9e12 100644 --- a/kube-derive/Cargo.toml +++ b/kube-derive/Cargo.toml @@ -22,10 +22,6 @@ darling = "0.13.0" [lib] proc-macro = true -[features] -default = ["schema"] -schema = [] - [dev-dependencies] serde = { version = "1.0.130", features = ["derive"] } serde_yaml = "0.8.21" diff --git a/kube-derive/src/custom_resource.rs b/kube-derive/src/custom_resource.rs index 2caa5712e..d426c3303 100644 --- a/kube-derive/src/custom_resource.rs +++ b/kube-derive/src/custom_resource.rs @@ -24,6 +24,8 @@ struct KubeAttrs { #[darling(multiple, rename = "derive")] derives: Vec, #[darling(default)] + derive_schema: Option, + #[darling(default)] status: Option, #[darling(multiple, rename = "category")] categories: Vec, @@ -92,6 +94,7 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea version, namespaced, derives, + derive_schema, status, plural, singular, @@ -152,9 +155,8 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea } } - // Schema generation is always enabled for v1 because it's mandatory. - // TODO Enable schema generation for v1beta1 if the spec derives `JsonSchema`. - let schema_gen_enabled = apiextensions == "v1" && cfg!(feature = "schema"); + // Enable schema generation by default for v1 because it's mandatory. + let schema_gen_enabled = derive_schema.unwrap_or(apiextensions == "v1"); // We exclude fields `apiVersion`, `kind`, and `metadata` from our schema because // these are validated by the API server implicitly. Also, we can't generate the // schema for `metadata` (`ObjectMeta`) because it doesn't implement `JsonSchema`. From 3443a5dce4782b97baf0b2e420249b2a8a2ec20d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 1 Nov 2021 12:12:32 +0100 Subject: [PATCH 02/13] Changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Teo Klestrup Röijezon --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 718aba724..7d9648a1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ UNRELEASED - Replaced `kube::Error::RequestValidation(String)` variant with `kube::Error::BuildRequest(kube::core::request::Error)`. This variant includes possible errors when building an HTTP request as described above, and contains errors that was previously grouped under `kube::Error::SerdeError` and `kube::Error::HttpError`. - Removed `impl From for kube::Error` for the following types: `std::io::Error`, `hyper::Error`, `tower::BoxError`, `std::string::FromUtf8Error`, `http::Error`, `http::uri::InvalidUri`, `serde_json::Error`, `openssl::error::ErrorStack`, `kube::core::Error`, `kube::error::ConfigError`, `kube::error::DisoveryError`, `kube::error::OAuthError`. - Changed variants of error enums in `kube::runtime`. Replaced `snafu` with `thiserror`. + * BREAKING: Replaced feature `kube-runtime/schema` with attribute `#[kube(derive_schema)]` - #690 + - If you currently disable default `kube-runtime` default features to avoid this issue, add `#[kube(derive_schema = false)]` to your spec struct instead 0.63.2 / 2021-10-28 =================== From 38684a8967f56e88cfcfb77c4ad8185c10414835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 1 Nov 2021 12:23:06 +0100 Subject: [PATCH 03/13] Document `derive_schema = false` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Teo Klestrup Röijezon --- kube-derive/src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kube-derive/src/lib.rs b/kube-derive/src/lib.rs index 205374151..bc787b57b 100644 --- a/kube-derive/src/lib.rs +++ b/kube-derive/src/lib.rs @@ -111,6 +111,12 @@ mod custom_resource; /// Adding `#[kube(derive = "PartialEq")]` is required if you want your generated /// top level type to be able to `#[derive(PartialEq)]` /// +/// ### `#[kube(derive_schema = false)]` +/// Disables the automatic `#[derive(JsonSchema)]` on the top level generated type. +/// +/// This can be used to provide a completely custom schema, or to interact with third-party custom resources, +/// where you are not responsible for installing the `CustomResourceDefinition`. +/// /// ### `#[kube(scale = r#"json"#)]` /// Allow customizing the scale struct for the [scale subresource](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#subresources). /// @@ -190,7 +196,7 @@ mod custom_resource; /// /// See [kubernetes openapi validation](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation) for the format of the OpenAPI v3 schemas. /// -/// If you have to override a lot, [you can opt-out of schema-generation entirely](https://github.com/kube-rs/kube-rs/issues/355#issuecomment-751253657) +/// If you have to override a lot, [you can opt-out of schema-generation entirely](#kubederive_schema--false) /// /// ## Advanced Features /// - **embedding k8s-openapi types** can be done by enabling the `schemars` feature of `k8s-openapi` from [`0.13.0`](https://github.com/Arnavion/k8s-openapi/blob/master/CHANGELOG.md#v0130-2021-08-09) From d6686b45f76fa4446e385717c3338c38247c61d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 1 Nov 2021 12:46:22 +0100 Subject: [PATCH 04/13] Add an in-between mode where schema is still used but not derived MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Teo Klestrup Röijezon --- CHANGELOG.md | 4 +-- examples/crd_derive_no_schema.rs | 2 +- kube-derive/src/custom_resource.rs | 54 ++++++++++++++++++++++++++---- kube-derive/src/lib.rs | 16 +++++++-- 4 files changed, 63 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d9648a1d..e2a3ecf05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,8 @@ UNRELEASED - Replaced `kube::Error::RequestValidation(String)` variant with `kube::Error::BuildRequest(kube::core::request::Error)`. This variant includes possible errors when building an HTTP request as described above, and contains errors that was previously grouped under `kube::Error::SerdeError` and `kube::Error::HttpError`. - Removed `impl From for kube::Error` for the following types: `std::io::Error`, `hyper::Error`, `tower::BoxError`, `std::string::FromUtf8Error`, `http::Error`, `http::uri::InvalidUri`, `serde_json::Error`, `openssl::error::ErrorStack`, `kube::core::Error`, `kube::error::ConfigError`, `kube::error::DisoveryError`, `kube::error::OAuthError`. - Changed variants of error enums in `kube::runtime`. Replaced `snafu` with `thiserror`. - * BREAKING: Replaced feature `kube-runtime/schema` with attribute `#[kube(derive_schema)]` - #690 - - If you currently disable default `kube-runtime` default features to avoid this issue, add `#[kube(derive_schema = false)]` to your spec struct instead + * BREAKING: Replaced feature `kube-runtime/schema` with attribute `#[kube(schema_mode)]` - #690 + - If you currently disable default `kube-runtime` default features to avoid automatic schema generation, add `#[kube(schema_mode = "disabled")]` to your spec struct instead 0.63.2 / 2021-10-28 =================== diff --git a/examples/crd_derive_no_schema.rs b/examples/crd_derive_no_schema.rs index d72aa11b6..e9b1f5a73 100644 --- a/examples/crd_derive_no_schema.rs +++ b/examples/crd_derive_no_schema.rs @@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize}; version = "v1", kind = "Bar", namespaced, - derive_schema = false + schema_mode = "disabled" )] pub struct MyBar { bars: u32, diff --git a/kube-derive/src/custom_resource.rs b/kube-derive/src/custom_resource.rs index d426c3303..d6be4a8d1 100644 --- a/kube-derive/src/custom_resource.rs +++ b/kube-derive/src/custom_resource.rs @@ -1,4 +1,4 @@ -use darling::FromDeriveInput; +use darling::{FromDeriveInput, FromMeta}; use proc_macro2::{Ident, Span, TokenStream}; use syn::{parse_quote, Data, DeriveInput, Path, Visibility}; @@ -24,7 +24,7 @@ struct KubeAttrs { #[darling(multiple, rename = "derive")] derives: Vec, #[darling(default)] - derive_schema: Option, + schema_mode: Option, #[darling(default)] status: Option, #[darling(multiple, rename = "category")] @@ -66,6 +66,42 @@ fn default_serde_json() -> Path { parse_quote! { ::serde_json } } +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +enum SchemaMode { + Disabled, + Custom, + Derived, +} + +impl SchemaMode { + fn derive(self) -> bool { + match self { + SchemaMode::Disabled => false, + SchemaMode::Custom => false, + SchemaMode::Derived => true, + } + } + + fn use_in_crd(self) -> bool { + match self { + SchemaMode::Disabled => false, + SchemaMode::Custom => true, + SchemaMode::Derived => true, + } + } +} + +impl FromMeta for SchemaMode { + fn from_string(value: &str) -> darling::Result { + match value { + "disabled" => Ok(SchemaMode::Disabled), + "custom" => Ok(SchemaMode::Custom), + "derived" => Ok(SchemaMode::Derived), + x => Err(darling::Error::unknown_value(x)), + } + } +} + pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream { let derive_input: DeriveInput = match syn::parse2(input) { Err(err) => return err.to_compile_error(), @@ -94,7 +130,7 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea version, namespaced, derives, - derive_schema, + schema_mode, status, plural, singular, @@ -156,16 +192,20 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea } // Enable schema generation by default for v1 because it's mandatory. - let schema_gen_enabled = derive_schema.unwrap_or(apiextensions == "v1"); + let schema_mode = schema_mode.unwrap_or(if apiextensions == "v1" { + SchemaMode::Derived + } else { + SchemaMode::Disabled + }); // We exclude fields `apiVersion`, `kind`, and `metadata` from our schema because // these are validated by the API server implicitly. Also, we can't generate the // schema for `metadata` (`ObjectMeta`) because it doesn't implement `JsonSchema`. - let schemars_skip = if schema_gen_enabled { + let schemars_skip = if schema_mode.derive() { quote! { #[schemars(skip)] } } else { quote! {} }; - if schema_gen_enabled { + if schema_mode.derive() { derive_paths.push(syn::parse_quote! { #schemars::JsonSchema }); } @@ -291,7 +331,7 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea let crd_meta_name = format!("{}.{}", plural, group); let crd_meta = quote! { { "name": #crd_meta_name } }; - let schemagen = if schema_gen_enabled { + let schemagen = if schema_mode.use_in_crd() { quote! { // Don't use definitions and don't include `$schema` because these are not allowed. let gen = #schemars::gen::SchemaSettings::openapi3().with(|s| { diff --git a/kube-derive/src/lib.rs b/kube-derive/src/lib.rs index bc787b57b..9c8fcc4d0 100644 --- a/kube-derive/src/lib.rs +++ b/kube-derive/src/lib.rs @@ -111,12 +111,22 @@ mod custom_resource; /// Adding `#[kube(derive = "PartialEq")]` is required if you want your generated /// top level type to be able to `#[derive(PartialEq)]` /// -/// ### `#[kube(derive_schema = false)]` -/// Disables the automatic `#[derive(JsonSchema)]` on the top level generated type. +/// ### `#[kube(schema_mode = "mode")]` +/// Defines whether the `JsonSchema` of the top level generated type should be used when generating a `CustomResourceDefinition`. /// -/// This can be used to provide a completely custom schema, or to interact with third-party custom resources, +/// Legal values: +/// - `"derived"`: A `JsonSchema` implementation is automatically derived +/// - `"custom"`: `JsonSchema` is not derived, but used when creating the `CustomResource` object +/// - `"disabled"`: No `JsonSchema` is used +/// +/// This can be used to provide a completely custom schema, or to interact with third-party custom resources /// where you are not responsible for installing the `CustomResourceDefinition`. /// +/// Defaults to `"disabled"` when `apiextensions = "v1beta1"`, otherwise `"derived"`. +/// +/// NOTE: `apiextensions = "v1"` `CustomResourceDefinition`s require a schema. If `schema_mode = "disabled"` then +/// `Self::crd()` will not be installable into the cluster as-is. +/// /// ### `#[kube(scale = r#"json"#)]` /// Allow customizing the scale struct for the [scale subresource](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#subresources). /// From e3b1f52441609f6a2c7527b1ad82f035a51ffe60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 1 Nov 2021 12:59:05 +0100 Subject: [PATCH 05/13] Fix straggling link that still went to the old derive_schema field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Teo Klestrup Röijezon --- kube-derive/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kube-derive/src/lib.rs b/kube-derive/src/lib.rs index 9c8fcc4d0..caffb7da2 100644 --- a/kube-derive/src/lib.rs +++ b/kube-derive/src/lib.rs @@ -206,7 +206,7 @@ mod custom_resource; /// /// See [kubernetes openapi validation](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation) for the format of the OpenAPI v3 schemas. /// -/// If you have to override a lot, [you can opt-out of schema-generation entirely](#kubederive_schema--false) +/// If you have to override a lot, [you can opt-out of schema-generation entirely](#kubeschema_mode--mode) /// /// ## Advanced Features /// - **embedding k8s-openapi types** can be done by enabling the `schemars` feature of `k8s-openapi` from [`0.13.0`](https://github.com/Arnavion/k8s-openapi/blob/master/CHANGELOG.md#v0130-2021-08-09) From 24be356f281eed093ba8b381d094c7fa9866b4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 1 Nov 2021 15:32:37 +0100 Subject: [PATCH 06/13] Added example for custom JsonSchema derive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Teo Klestrup Röijezon --- examples/Cargo.toml | 6 ++- examples/crd_derive_custom_schema.rs | 79 ++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 examples/crd_derive_custom_schema.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 44a8c71aa..1c1159392 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -82,7 +82,11 @@ path = "crd_derive.rs" name = "crd_derive_schema" path = "crd_derive_schema.rs" -[[example]] # run this without --no-default-features --features="native-tls" +[[example]] +name = "crd_derive_custom_schema" +path = "crd_derive_custom_schema.rs" + +[[example]] name = "crd_derive_no_schema" path = "crd_derive_no_schema.rs" diff --git a/examples/crd_derive_custom_schema.rs b/examples/crd_derive_custom_schema.rs new file mode 100644 index 000000000..e06113176 --- /dev/null +++ b/examples/crd_derive_custom_schema.rs @@ -0,0 +1,79 @@ +use kube::CustomResourceExt; +use kube_derive::CustomResource; +use schemars::{ + schema::{InstanceType, ObjectValidation, Schema, SchemaObject}, + JsonSchema, +}; +use serde::{Deserialize, Serialize}; + +/// CustomResource with manually implemented `JsonSchema` +#[derive(CustomResource, Serialize, Deserialize, Debug, Clone)] +#[kube( + group = "clux.dev", + version = "v1", + kind = "Bar", + namespaced, + schema_mode = "custom" +)] +pub struct MyBar { + bars: u32, +} + +impl JsonSchema for Bar { + fn schema_name() -> String { + "Bar".to_string() + } + + fn json_schema(__gen: &mut schemars::gen::SchemaGenerator) -> Schema { + Schema::Object(SchemaObject { + object: Some(Box::new(ObjectValidation { + required: ["spec".to_string()].into(), + properties: [( + "spec".to_string(), + Schema::Object(SchemaObject { + instance_type: Some(InstanceType::Object.into()), + object: Some(Box::new(ObjectValidation { + required: ["bars".to_string()].into(), + properties: [( + "bars".to_string(), + Schema::Object(SchemaObject { + instance_type: Some(InstanceType::Integer.into()), + ..SchemaObject::default() + }), + )] + .into(), + ..ObjectValidation::default() + })), + ..SchemaObject::default() + }), + )] + .into(), + ..ObjectValidation::default() + })), + ..SchemaObject::default() + }) + } +} + +fn main() { + let crd = Bar::crd(); + println!("{}", serde_yaml::to_string(&crd).unwrap()); +} + +// Verify CustomResource derivable still +#[test] +fn verify_bar_is_a_custom_resource() { + use kube::Resource; + use schemars::JsonSchema; // only for ensuring it's not implemented + use static_assertions::assert_impl_all; + + println!("Kind {}", Bar::kind(&())); + let bar = Bar::new("five", MyBar { bars: 5 }); + println!("Spec: {:?}", bar.spec); + assert_impl_all!(Bar: kube::Resource, JsonSchema); + + let crd = Bar::crd_with_manual_schema(); + for v in crd.spec.versions { + assert!(v.schema.unwrap().open_api_v3_schema.is_some()); + } +} From a6a30838ba39525310432809832c4d4a1d9dad0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 1 Nov 2021 15:36:40 +0100 Subject: [PATCH 07/13] Fix error building example tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Teo Klestrup Röijezon --- examples/crd_derive_custom_schema.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/crd_derive_custom_schema.rs b/examples/crd_derive_custom_schema.rs index e06113176..8f86213dd 100644 --- a/examples/crd_derive_custom_schema.rs +++ b/examples/crd_derive_custom_schema.rs @@ -64,7 +64,6 @@ fn main() { #[test] fn verify_bar_is_a_custom_resource() { use kube::Resource; - use schemars::JsonSchema; // only for ensuring it's not implemented use static_assertions::assert_impl_all; println!("Kind {}", Bar::kind(&())); @@ -72,7 +71,7 @@ fn verify_bar_is_a_custom_resource() { println!("Spec: {:?}", bar.spec); assert_impl_all!(Bar: kube::Resource, JsonSchema); - let crd = Bar::crd_with_manual_schema(); + let crd = Bar::crd(); for v in crd.spec.versions { assert!(v.schema.unwrap().open_api_v3_schema.is_some()); } From 1d8977145eb7c97fcac4ba04c360a4ce1568d0a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 1 Nov 2021 18:38:22 +0100 Subject: [PATCH 08/13] Update CHANGELOG.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kazk Signed-off-by: Teo Klestrup Röijezon --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2a3ecf05..ae6488f56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ UNRELEASED - Replaced `kube::Error::RequestValidation(String)` variant with `kube::Error::BuildRequest(kube::core::request::Error)`. This variant includes possible errors when building an HTTP request as described above, and contains errors that was previously grouped under `kube::Error::SerdeError` and `kube::Error::HttpError`. - Removed `impl From for kube::Error` for the following types: `std::io::Error`, `hyper::Error`, `tower::BoxError`, `std::string::FromUtf8Error`, `http::Error`, `http::uri::InvalidUri`, `serde_json::Error`, `openssl::error::ErrorStack`, `kube::core::Error`, `kube::error::ConfigError`, `kube::error::DisoveryError`, `kube::error::OAuthError`. - Changed variants of error enums in `kube::runtime`. Replaced `snafu` with `thiserror`. - * BREAKING: Replaced feature `kube-runtime/schema` with attribute `#[kube(schema_mode)]` - #690 + * BREAKING: Replaced feature `kube-derive/schema` with attribute `#[kube(schema_mode)]` - #690 - If you currently disable default `kube-runtime` default features to avoid automatic schema generation, add `#[kube(schema_mode = "disabled")]` to your spec struct instead 0.63.2 / 2021-10-28 From 3083d34a337009810b2e5377515366def9fc4c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 1 Nov 2021 18:38:29 +0100 Subject: [PATCH 09/13] Update CHANGELOG.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kazk Signed-off-by: Teo Klestrup Röijezon --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae6488f56..20bb818bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ UNRELEASED - Removed `impl From for kube::Error` for the following types: `std::io::Error`, `hyper::Error`, `tower::BoxError`, `std::string::FromUtf8Error`, `http::Error`, `http::uri::InvalidUri`, `serde_json::Error`, `openssl::error::ErrorStack`, `kube::core::Error`, `kube::error::ConfigError`, `kube::error::DisoveryError`, `kube::error::OAuthError`. - Changed variants of error enums in `kube::runtime`. Replaced `snafu` with `thiserror`. * BREAKING: Replaced feature `kube-derive/schema` with attribute `#[kube(schema_mode)]` - #690 - - If you currently disable default `kube-runtime` default features to avoid automatic schema generation, add `#[kube(schema_mode = "disabled")]` to your spec struct instead + - If you currently disable default `kube-derive` default features to avoid automatic schema generation, add `#[kube(schema_mode = "disabled")]` to your spec struct instead 0.63.2 / 2021-10-28 =================== From 92090b1f121f6c2ce98fb145eeb0023fdc7fbc06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 1 Nov 2021 21:44:22 +0100 Subject: [PATCH 10/13] Move overrides into `#[kube(crates)]`, rename `schema_mode` to `schema` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Teo Klestrup Röijezon --- CHANGELOG.md | 6 ++- examples/crd_derive_custom_schema.rs | 2 +- examples/crd_derive_no_schema.rs | 2 +- kube-derive/src/custom_resource.rs | 78 ++++++++++++++++++---------- kube-derive/src/lib.rs | 16 +++--- 5 files changed, 65 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20bb818bb..477fb9b6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,10 @@ UNRELEASED - Replaced `kube::Error::RequestValidation(String)` variant with `kube::Error::BuildRequest(kube::core::request::Error)`. This variant includes possible errors when building an HTTP request as described above, and contains errors that was previously grouped under `kube::Error::SerdeError` and `kube::Error::HttpError`. - Removed `impl From for kube::Error` for the following types: `std::io::Error`, `hyper::Error`, `tower::BoxError`, `std::string::FromUtf8Error`, `http::Error`, `http::uri::InvalidUri`, `serde_json::Error`, `openssl::error::ErrorStack`, `kube::core::Error`, `kube::error::ConfigError`, `kube::error::DisoveryError`, `kube::error::OAuthError`. - Changed variants of error enums in `kube::runtime`. Replaced `snafu` with `thiserror`. - * BREAKING: Replaced feature `kube-derive/schema` with attribute `#[kube(schema_mode)]` - #690 - - If you currently disable default `kube-derive` default features to avoid automatic schema generation, add `#[kube(schema_mode = "disabled")]` to your spec struct instead + * BREAKING: Replaced feature `kube-derive/schema` with attribute `#[kube(schema)]` - #690 + - If you currently disable default `kube-derive` default features to avoid automatic schema generation, add `#[kube(schema = "disabled")]` to your spec struct instead + * BREAKING: Moved `CustomResource` derive crate overrides into subattribute `#[kube(crates(...))]` - #690 + - Replace `#[kube(kube_core = .., k8s_openapi = .., schema = .., serde = .., serde_json = ..)]` with `#[kube(crates(kube_core = .., k8s_openapi = .., schema = .., serde = .., serde_json = ..))]` 0.63.2 / 2021-10-28 =================== diff --git a/examples/crd_derive_custom_schema.rs b/examples/crd_derive_custom_schema.rs index 8f86213dd..a379d6909 100644 --- a/examples/crd_derive_custom_schema.rs +++ b/examples/crd_derive_custom_schema.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; version = "v1", kind = "Bar", namespaced, - schema_mode = "custom" + schema = "custom" )] pub struct MyBar { bars: u32, diff --git a/examples/crd_derive_no_schema.rs b/examples/crd_derive_no_schema.rs index e9b1f5a73..4795e8598 100644 --- a/examples/crd_derive_no_schema.rs +++ b/examples/crd_derive_no_schema.rs @@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize}; version = "v1", kind = "Bar", namespaced, - schema_mode = "disabled" + schema = "disabled" )] pub struct MyBar { bars: u32, diff --git a/kube-derive/src/custom_resource.rs b/kube-derive/src/custom_resource.rs index d6be4a8d1..3731abac5 100644 --- a/kube-derive/src/custom_resource.rs +++ b/kube-derive/src/custom_resource.rs @@ -24,7 +24,7 @@ struct KubeAttrs { #[darling(multiple, rename = "derive")] derives: Vec, #[darling(default)] - schema_mode: Option, + schema: Option, #[darling(default)] status: Option, #[darling(multiple, rename = "category")] @@ -35,35 +35,56 @@ struct KubeAttrs { printcolums: Vec, #[darling(default)] scale: Option, - #[darling(default = "default_kube_core")] + #[darling(default)] + crates: Crates, +} + +#[derive(Debug, FromMeta)] +struct Crates { + #[darling(default = "Self::default_kube_core")] kube_core: Path, - #[darling(default = "default_k8s_openapi")] + #[darling(default = "Self::default_k8s_openapi")] k8s_openapi: Path, - #[darling(default = "default_schemars")] + #[darling(default = "Self::default_schemars")] schemars: Path, - #[darling(default = "default_serde")] + #[darling(default = "Self::default_serde")] serde: Path, - #[darling(default = "default_serde_json")] + #[darling(default = "Self::default_serde_json")] serde_json: Path, } -fn default_apiext() -> String { - "v1".to_owned() -} -fn default_kube_core() -> Path { - parse_quote! { ::kube::core } // by default must work well with people using facade crate -} -fn default_k8s_openapi() -> Path { - parse_quote! { ::k8s_openapi } -} -fn default_schemars() -> Path { - parse_quote! { ::schemars } +// Default is required when the subattribute isn't mentioned at all +// Delegate to darling rather than deriving, so that we can piggyback off the `#[darling(default)]` clauses +impl Default for Crates { + fn default() -> Self { + Self::from_list(&[]).unwrap() + } } -fn default_serde() -> Path { - parse_quote! { ::serde } + +impl Crates { + fn default_kube_core() -> Path { + parse_quote! { ::kube::core } // by default must work well with people using facade crate + } + + fn default_k8s_openapi() -> Path { + parse_quote! { ::k8s_openapi } + } + + fn default_schemars() -> Path { + parse_quote! { ::schemars } + } + + fn default_serde() -> Path { + parse_quote! { ::serde } + } + + fn default_serde_json() -> Path { + parse_quote! { ::serde_json } + } } -fn default_serde_json() -> Path { - parse_quote! { ::serde_json } + +fn default_apiext() -> String { + "v1".to_owned() } #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -130,7 +151,7 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea version, namespaced, derives, - schema_mode, + schema: schema_mode, status, plural, singular, @@ -139,11 +160,14 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea printcolums, apiextensions, scale, - kube_core, - k8s_openapi, - schemars, - serde, - serde_json, + crates: + Crates { + kube_core, + k8s_openapi, + schemars, + serde, + serde_json, + }, } = kube_attrs; let struct_name = kind_struct.unwrap_or_else(|| kind.clone()); diff --git a/kube-derive/src/lib.rs b/kube-derive/src/lib.rs index caffb7da2..38b4242af 100644 --- a/kube-derive/src/lib.rs +++ b/kube-derive/src/lib.rs @@ -87,20 +87,20 @@ mod custom_resource; /// ### `#[kube(struct = "StructName")]` /// Customize the name of the generated root struct (defaults to `kind`). /// -/// ### `#[kube(kube_core = "::kube::core")]` +/// ### `#[kube(crates(kube_core = "::kube::core"))]` /// Customize the crate name the generated code will reach into (defaults to `::kube::core`). /// Should be one of `kube::core`, `kube_client::core` or `kube_core`. /// -/// ### `#[kube(k8s_openapi = "::k8s_openapi")]` +/// ### `#[kube(crates(k8s_openapi = "::k8s_openapi"))]` /// Customize the crate name the generated code will use for [`k8s_openapi`](https://docs.rs/k8s-openapi/) (defaults to `::k8s_openapi`). /// -/// ### `#[kube(schemars = "::schemars")]` +/// ### `#[kube(crates(schemars = "::schemars"))]` /// Customize the crate name the generated code will use for [`schemars`](https://docs.rs/schemars/) (defaults to `::schemars`). /// -/// ### `#[kube(serde = "::serde")]` +/// ### `#[kube(crates(serde = "::serde"))]` /// Customize the crate name the generated code will use for [`serde`](https://docs.rs/serde/) (defaults to `::serde`). /// -/// ### `#[kube(serde_json = "::serde_json")]` +/// ### `#[kube(crates(serde_json = "::serde_json"))]` /// Customize the crate name the generated code will use for [`serde_json`](https://docs.rs/serde_json/) (defaults to `::serde_json`). /// /// ### `#[kube(status = "StatusStructName")]` @@ -111,7 +111,7 @@ mod custom_resource; /// Adding `#[kube(derive = "PartialEq")]` is required if you want your generated /// top level type to be able to `#[derive(PartialEq)]` /// -/// ### `#[kube(schema_mode = "mode")]` +/// ### `#[kube(schema = "mode")]` /// Defines whether the `JsonSchema` of the top level generated type should be used when generating a `CustomResourceDefinition`. /// /// Legal values: @@ -124,7 +124,7 @@ mod custom_resource; /// /// Defaults to `"disabled"` when `apiextensions = "v1beta1"`, otherwise `"derived"`. /// -/// NOTE: `apiextensions = "v1"` `CustomResourceDefinition`s require a schema. If `schema_mode = "disabled"` then +/// NOTE: `apiextensions = "v1"` `CustomResourceDefinition`s require a schema. If `schema = "disabled"` then /// `Self::crd()` will not be installable into the cluster as-is. /// /// ### `#[kube(scale = r#"json"#)]` @@ -206,7 +206,7 @@ mod custom_resource; /// /// See [kubernetes openapi validation](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation) for the format of the OpenAPI v3 schemas. /// -/// If you have to override a lot, [you can opt-out of schema-generation entirely](#kubeschema_mode--mode) +/// If you have to override a lot, [you can opt-out of schema-generation entirely](#kubeschema--mode) /// /// ## Advanced Features /// - **embedding k8s-openapi types** can be done by enabling the `schemars` feature of `k8s-openapi` from [`0.13.0`](https://github.com/Arnavion/k8s-openapi/blob/master/CHANGELOG.md#v0130-2021-08-09) From adbc575b6eae682e6da1e4d96b1088f8b14e2a5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 2 Nov 2021 23:38:30 +0100 Subject: [PATCH 11/13] Update kube-derive/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Eirik A Signed-off-by: Teo Klestrup Röijezon --- kube-derive/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kube-derive/src/lib.rs b/kube-derive/src/lib.rs index 38b4242af..e6a5c803a 100644 --- a/kube-derive/src/lib.rs +++ b/kube-derive/src/lib.rs @@ -116,7 +116,7 @@ mod custom_resource; /// /// Legal values: /// - `"derived"`: A `JsonSchema` implementation is automatically derived -/// - `"custom"`: `JsonSchema` is not derived, but used when creating the `CustomResource` object +/// - `"custom"`: `JsonSchema` is not derived, but used when creating the `CustomResourceDefinition` object /// - `"disabled"`: No `JsonSchema` is used /// /// This can be used to provide a completely custom schema, or to interact with third-party custom resources From 42d817007becf7638352ad4c6b748aeb70ba6ee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 4 Nov 2021 16:19:17 +0100 Subject: [PATCH 12/13] #[kube(schema = "custom")] => #[kube(schema = "manual")] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Teo Klestrup Röijezon --- kube-derive/src/custom_resource.rs | 8 ++++---- kube-derive/src/lib.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kube-derive/src/custom_resource.rs b/kube-derive/src/custom_resource.rs index 3731abac5..c8c4fb223 100644 --- a/kube-derive/src/custom_resource.rs +++ b/kube-derive/src/custom_resource.rs @@ -90,7 +90,7 @@ fn default_apiext() -> String { #[derive(Debug, PartialEq, Eq, Clone, Copy)] enum SchemaMode { Disabled, - Custom, + Manual, Derived, } @@ -98,7 +98,7 @@ impl SchemaMode { fn derive(self) -> bool { match self { SchemaMode::Disabled => false, - SchemaMode::Custom => false, + SchemaMode::Manual => false, SchemaMode::Derived => true, } } @@ -106,7 +106,7 @@ impl SchemaMode { fn use_in_crd(self) -> bool { match self { SchemaMode::Disabled => false, - SchemaMode::Custom => true, + SchemaMode::Manual => true, SchemaMode::Derived => true, } } @@ -116,7 +116,7 @@ impl FromMeta for SchemaMode { fn from_string(value: &str) -> darling::Result { match value { "disabled" => Ok(SchemaMode::Disabled), - "custom" => Ok(SchemaMode::Custom), + "manual" => Ok(SchemaMode::Manual), "derived" => Ok(SchemaMode::Derived), x => Err(darling::Error::unknown_value(x)), } diff --git a/kube-derive/src/lib.rs b/kube-derive/src/lib.rs index e6a5c803a..2f7215482 100644 --- a/kube-derive/src/lib.rs +++ b/kube-derive/src/lib.rs @@ -116,7 +116,7 @@ mod custom_resource; /// /// Legal values: /// - `"derived"`: A `JsonSchema` implementation is automatically derived -/// - `"custom"`: `JsonSchema` is not derived, but used when creating the `CustomResourceDefinition` object +/// - `"manual"`: `JsonSchema` is not derived, but used when creating the `CustomResourceDefinition` object /// - `"disabled"`: No `JsonSchema` is used /// /// This can be used to provide a completely custom schema, or to interact with third-party custom resources From a2fe3c4d9e1f926fc53570de98f9389834a326e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 4 Nov 2021 17:38:12 +0100 Subject: [PATCH 13/13] Fix example still referring to `schema = "custom"` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Teo Klestrup Röijezon --- examples/crd_derive_custom_schema.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/crd_derive_custom_schema.rs b/examples/crd_derive_custom_schema.rs index a379d6909..c2e8e74c3 100644 --- a/examples/crd_derive_custom_schema.rs +++ b/examples/crd_derive_custom_schema.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; version = "v1", kind = "Bar", namespaced, - schema = "custom" + schema = "manual" )] pub struct MyBar { bars: u32,