Skip to content

Commit 74b694c

Browse files
committed
Add an in-between mode where schema is still used but not derived
Signed-off-by: Teo Klestrup Röijezon <[email protected]>
1 parent 9cb84ea commit 74b694c

File tree

4 files changed

+63
-13
lines changed

4 files changed

+63
-13
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ UNRELEASED
1212
- 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`.
1313
- Removed `impl From<T> 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`.
1414
- Changed variants of error enums in `kube::runtime`. Replaced `snafu` with `thiserror`.
15-
* BREAKING: Replaced feature `kube-runtime/schema` with attribute `#[kube(derive_schema)]` - #690
16-
- If you currently disable default `kube-runtime` default features to avoid this issue, add `#[kube(derive_schema = false)]` to your spec struct instead
15+
* BREAKING: Replaced feature `kube-runtime/schema` with attribute `#[kube(schema_mode)]` - #690
16+
- If you currently disable default `kube-runtime` default features to avoid automatic schema generation, add `#[kube(schema_mode = "disabled")]` to your spec struct instead
1717

1818
0.63.2 / 2021-10-28
1919
===================

examples/crd_derive_no_schema.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize};
1414
version = "v1",
1515
kind = "Bar",
1616
namespaced,
17-
derive_schema = false
17+
schema_mode = "disabled"
1818
)]
1919
pub struct MyBar {
2020
bars: u32,

kube-derive/src/custom_resource.rs

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use darling::FromDeriveInput;
1+
use darling::{FromDeriveInput, FromMeta};
22
use proc_macro2::{Ident, Span, TokenStream};
33
use syn::{parse_quote, Data, DeriveInput, Path, Visibility};
44

@@ -24,7 +24,7 @@ struct KubeAttrs {
2424
#[darling(multiple, rename = "derive")]
2525
derives: Vec<String>,
2626
#[darling(default)]
27-
derive_schema: Option<bool>,
27+
schema_mode: Option<SchemaMode>,
2828
#[darling(default)]
2929
status: Option<String>,
3030
#[darling(multiple, rename = "category")]
@@ -66,6 +66,42 @@ fn default_serde_json() -> Path {
6666
parse_quote! { ::serde_json }
6767
}
6868

69+
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
70+
enum SchemaMode {
71+
Disabled,
72+
Custom,
73+
Derived,
74+
}
75+
76+
impl SchemaMode {
77+
fn derive(self) -> bool {
78+
match self {
79+
SchemaMode::Disabled => false,
80+
SchemaMode::Custom => false,
81+
SchemaMode::Derived => true,
82+
}
83+
}
84+
85+
fn use_in_crd(self) -> bool {
86+
match self {
87+
SchemaMode::Disabled => false,
88+
SchemaMode::Custom => true,
89+
SchemaMode::Derived => true,
90+
}
91+
}
92+
}
93+
94+
impl FromMeta for SchemaMode {
95+
fn from_string(value: &str) -> darling::Result<Self> {
96+
match value {
97+
"disabled" => Ok(SchemaMode::Disabled),
98+
"custom" => Ok(SchemaMode::Custom),
99+
"derived" => Ok(SchemaMode::Derived),
100+
x => Err(darling::Error::unknown_value(x)),
101+
}
102+
}
103+
}
104+
69105
pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
70106
let derive_input: DeriveInput = match syn::parse2(input) {
71107
Err(err) => return err.to_compile_error(),
@@ -94,7 +130,7 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea
94130
version,
95131
namespaced,
96132
derives,
97-
derive_schema,
133+
schema_mode,
98134
status,
99135
plural,
100136
singular,
@@ -156,16 +192,20 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea
156192
}
157193

158194
// Enable schema generation by default for v1 because it's mandatory.
159-
let schema_gen_enabled = derive_schema.unwrap_or(apiextensions == "v1");
195+
let schema_mode = schema_mode.unwrap_or(if apiextensions == "v1" {
196+
SchemaMode::Derived
197+
} else {
198+
SchemaMode::Disabled
199+
});
160200
// We exclude fields `apiVersion`, `kind`, and `metadata` from our schema because
161201
// these are validated by the API server implicitly. Also, we can't generate the
162202
// schema for `metadata` (`ObjectMeta`) because it doesn't implement `JsonSchema`.
163-
let schemars_skip = if schema_gen_enabled {
203+
let schemars_skip = if schema_mode.derive() {
164204
quote! { #[schemars(skip)] }
165205
} else {
166206
quote! {}
167207
};
168-
if schema_gen_enabled {
208+
if schema_mode.derive() {
169209
derive_paths.push(syn::parse_quote! { #schemars::JsonSchema });
170210
}
171211

@@ -291,7 +331,7 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea
291331
let crd_meta_name = format!("{}.{}", plural, group);
292332
let crd_meta = quote! { { "name": #crd_meta_name } };
293333

294-
let schemagen = if schema_gen_enabled {
334+
let schemagen = if schema_mode.use_in_crd() {
295335
quote! {
296336
// Don't use definitions and don't include `$schema` because these are not allowed.
297337
let gen = #schemars::gen::SchemaSettings::openapi3().with(|s| {

kube-derive/src/lib.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,22 @@ mod custom_resource;
111111
/// Adding `#[kube(derive = "PartialEq")]` is required if you want your generated
112112
/// top level type to be able to `#[derive(PartialEq)]`
113113
///
114-
/// ### `#[kube(derive_schema = false)]`
115-
/// Disables the automatic `#[derive(JsonSchema)]` on the top level generated type.
114+
/// ### `#[kube(schema_mode = "mode")]`
115+
/// Defines whether the `JsonSchema` of the top level generated type should be used when generating a `CustomResourceDefinition`.
116116
///
117-
/// This can be used to provide a completely custom schema, or to interact with third-party custom resources,
117+
/// Legal values:
118+
/// - `"derived"`: A `JsonSchema` implementation is automatically derived
119+
/// - `"custom"`: `JsonSchema` is not derived, but used when creating the `CustomResource` object
120+
/// - `"disabled"`: No `JsonSchema` is used
121+
///
122+
/// This can be used to provide a completely custom schema, or to interact with third-party custom resources
118123
/// where you are not responsible for installing the `CustomResourceDefinition`.
119124
///
125+
/// Defaults to `"disabled"` when `apiextensions = "v1beta1"`, otherwise `"derived"`.
126+
///
127+
/// NOTE: `apiextensions = "v1"` `CustomResourceDefinition`s require a schema. If `schema_mode = "disabled"` then
128+
/// `Self::crd()` will not be installable into the cluster as-is.
129+
///
120130
/// ### `#[kube(scale = r#"json"#)]`
121131
/// Allow customizing the scale struct for the [scale subresource](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#subresources).
122132
///

0 commit comments

Comments
 (0)