Skip to content

Commit ce61e71

Browse files
committed
add a versioned CustomResourceExt trait - fixes #497
1 parent 2ef5dc2 commit ce61e71

File tree

11 files changed

+66
-13
lines changed

11 files changed

+66
-13
lines changed

examples/crd_api.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1beta1 as a
1212
use kube::{
1313
api::{Api, DeleteParams, ListParams, Patch, PatchParams, PostParams, ResourceExt},
1414
Client, CustomResource,
15+
core::crd::v1beta1::CustomResourceExt
1516
};
1617

1718
// Own custom resource

examples/crd_apply.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1 as apiext
88

99
use kube::{
1010
api::{Api, ListParams, Patch, PatchParams, ResourceExt, WatchEvent},
11-
Client, CustomResource,
11+
Client, CustomResource, CustomResourceExt
1212
};
1313

1414
// NB: This example uses server side apply and beta1 customresources

examples/crd_derive.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use k8s_openapi::apimachinery::pkg::apis::meta::v1::Condition;
2-
use kube::{CustomResource, Resource};
2+
use kube::{CustomResource, CustomResourceExt, Resource};
33
use schemars::JsonSchema;
44
use serde::{Deserialize, Serialize};
55

examples/crd_derive_no_schema.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ properties:
3434
#[cfg(not(feature = "schema"))]
3535
impl Bar {
3636
fn crd_with_manual_schema() -> CustomResourceDefinition {
37+
use kube::CustomResourceExt;
3738
let schema: JSONSchemaProps = serde_yaml::from_str(MANUAL_SCHEMA).expect("invalid schema");
3839

39-
let mut crd = Self::crd();
40+
let mut crd = <Self as CustomResourceExt>::crd();
4041
crd.spec.versions.iter_mut().for_each(|v| {
4142
v.schema = Some(CustomResourceValidation {
4243
open_api_v3_schema: Some(schema.clone()),

examples/crd_derive_schema.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use kube::{
66
Api, ApiResource, DeleteParams, DynamicObject, GroupVersionKind, ListParams, Patch, PatchParams,
77
PostParams, WatchEvent,
88
},
9-
Client, CustomResource,
9+
Client, CustomResource, CustomResourceExt
1010
};
1111
use schemars::JsonSchema;
1212
use serde::{Deserialize, Serialize};

kube-core/src/crd.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//! Traits and tyes for CustomResources
2+
3+
use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions as apiexts;
4+
5+
/// Types for v1 CustomResourceDefinitions
6+
pub mod v1 {
7+
use super::apiexts;
8+
use crate::discovery::ApiResource;
9+
/// Extension trait that will be implemented by kube-derive
10+
///
11+
/// This trait variant is implemented by default (or when `#[kube(apiextensions = "v1")]`)
12+
pub trait CustomResourceExt {
13+
/// Helper to generate the CRD including the JsonSchema
14+
///
15+
/// This is using the stable v1::CustomResourceDefinitions (present in kubernetes >= 1.16)
16+
fn crd() -> apiexts::v1::CustomResourceDefinition;
17+
/// Helper to generate the api information type for use with the dynamic `Api`
18+
fn api_resource() -> ApiResource;
19+
}
20+
}
21+
22+
/// Types for legacy v1beta1 CustomResourceDefinitions
23+
pub mod v1beta1 {
24+
use super::apiexts;
25+
use crate::discovery::ApiResource;
26+
/// Extension trait that will be implemented by kube-derive for legacy v1beta1::CustomResourceDefinitions
27+
///
28+
/// This trait variant is only implemented with `#[kube(apiextensions = "v1beta1")]`
29+
pub trait CustomResourceExt {
30+
/// Helper to generate the legacy CRD without a JsonSchema
31+
///
32+
/// This is using v1beta1::CustomResourceDefinitions (which will be removed in kubernetes 1.22)
33+
fn crd() -> apiexts::v1beta1::CustomResourceDefinition;
34+
/// Helper to generate the api information type for use with the dynamic `Api`
35+
fn api_resource() -> ApiResource;
36+
}
37+
}
38+
39+
/// re-export the current latest version until a newer one is available in cloud providers
40+
pub use v1::CustomResourceExt;

kube-core/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ pub mod discovery;
1515
pub mod dynamic;
1616
pub use dynamic::DynamicObject;
1717

18+
pub mod crd;
19+
pub use crd::CustomResourceExt;
20+
1821
pub mod gvk;
1922
pub use gvk::{GroupVersion, GroupVersionKind, GroupVersionResource};
2023

kube-derive/src/custom_resource.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea
251251
let apiext = quote! {
252252
k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::#v1ident
253253
};
254+
let extver = quote! {
255+
kube::core::crd::#v1ident
256+
};
254257

255258
let short_json = serde_json::to_string(&shortnames).unwrap();
256259
let crd_meta_name = format!("{}.{}", plural, group);
@@ -329,10 +332,10 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea
329332
}
330333
};
331334

332-
// Implement the ::crd and ::api_resource methods (fine to not have in a trait as its a generated type)
335+
// Implement the CustomResourcExt trait to allow users writing generic logic on top of them
333336
let impl_crd = quote! {
334-
impl #rootident {
335-
pub fn crd() -> #apiext::CustomResourceDefinition {
337+
impl #extver::CustomResourceExt for #rootident {
338+
fn crd() -> #apiext::CustomResourceDefinition {
336339
let columns : Vec<#apiext::CustomResourceColumnDefinition> = serde_json::from_str(#printers).expect("valid printer column json");
337340
let scale: Option<#apiext::CustomResourceSubresourceScale> = if #scale_code.is_empty() {
338341
None
@@ -358,7 +361,7 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea
358361
.expect("valid custom resource from #[kube(attrs..)]")
359362
}
360363

361-
pub fn api_resource() -> kube::core::ApiResource {
364+
fn api_resource() -> kube::core::ApiResource {
362365
kube::core::ApiResource::erase::<Self>(&())
363366
}
364367
}

kube-derive/src/lib.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ mod custom_resource;
1313
/// This root object will implement the [`kube::Resource`] trait
1414
/// so it can be used with [`kube::Api`].
1515
///
16-
/// The generated type will also implement a `::crd` method to generate the crd
17-
/// at the specified api version (or `v1` if unspecified).
16+
/// The generated type will also implement kube's [`kube::CustomResourceExt`] trait to generate the crd
17+
/// and generate [`kube::core::ApiResource`] information for use with the dynamic api.
1818
///
1919
/// # Example
2020
///
2121
/// ```rust
2222
/// use serde::{Serialize, Deserialize};
23-
/// use kube::Resource;
23+
/// use kube::{Resource, CustomResourceExt};
2424
/// use kube_derive::CustomResource;
2525
/// use schemars::JsonSchema;
2626
///
@@ -72,7 +72,8 @@ mod custom_resource;
7272
/// The version for `CustomResourceDefinition` desired in the `apiextensions.k8s.io` group.
7373
/// Default is `v1` (for clusters >= 1.17). If using kubernetes <= 1.16 please use `v1beta1`.
7474
///
75-
/// **NOTE**: Support for `v1` requires deriving the openapi v3 `JsonSchema` via the `schemars` dependency.
75+
/// - **NOTE**: Support for `v1` requires deriving the openapi v3 `JsonSchema` via the `schemars` dependency.
76+
/// - **NOTE**: When using `v1beta` the associated `CustomResourceExt` trait lives in `kube::core::crd::v1beta`
7677
///
7778
/// ### `#[kube(singular = "nonstandard-singular")]`
7879
/// To specify the singular name. Defaults to lowercased `kind`.
@@ -196,6 +197,8 @@ mod custom_resource;
196197
/// [`kube`]: https://docs.rs/kube
197198
/// [`kube::Api`]: https://docs.rs/kube/*/kube/struct.Api.html
198199
/// [`kube::Resource`]: https://docs.rs/kube/*/kube/trait.Resource.html
200+
/// [`kube::core::ApiResource`]: https://docs.rs/kube/*/kube/core/struct.ApiResource.html
201+
/// [`kube::CustomResourceExt`]: https://docs.rs/kube/*/kube/trait.CustomResourceExt.html
199202
#[proc_macro_derive(CustomResource, attributes(kube))]
200203
pub fn derive_custom_resource(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
201204
custom_resource::derive(proc_macro2::TokenStream::from(input)).into()

kube-derive/tests/crd_schema_test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ fn default_nullable() -> Option<String> {
4444

4545
#[test]
4646
fn test_crd_schema_matches_expected() {
47+
use kube::core::CustomResourceExt;
4748
assert_eq!(
4849
Foo::crd(),
4950
serde_json::from_value(serde_json::json!({

kube/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ pub mod core {
139139
#[cfg_attr(docsrs, doc(cfg(feature = "admission")))]
140140
pub use kube_core::admission;
141141
pub use kube_core::{
142+
crd::{self, CustomResourceExt},
142143
dynamic::{self, ApiResource, DynamicObject},
143144
gvk::{self, GroupVersionKind, GroupVersionResource},
144145
metadata::{self, ListMeta, ObjectMeta, TypeMeta},
@@ -149,4 +150,4 @@ pub mod core {
149150
Resource, ResourceExt,
150151
};
151152
}
152-
pub use crate::core::{Resource, ResourceExt};
153+
pub use crate::core::{CustomResourceExt, Resource, ResourceExt};

0 commit comments

Comments
 (0)