Skip to content

Commit

Permalink
add a versioned CustomResourceExt trait - fixes #497
Browse files Browse the repository at this point in the history
  • Loading branch information
clux committed Jun 8, 2021
1 parent 2ef5dc2 commit ce61e71
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 13 deletions.
1 change: 1 addition & 0 deletions examples/crd_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1beta1 as a
use kube::{
api::{Api, DeleteParams, ListParams, Patch, PatchParams, PostParams, ResourceExt},
Client, CustomResource,
core::crd::v1beta1::CustomResourceExt
};

// Own custom resource
Expand Down
2 changes: 1 addition & 1 deletion examples/crd_apply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1 as apiext

use kube::{
api::{Api, ListParams, Patch, PatchParams, ResourceExt, WatchEvent},
Client, CustomResource,
Client, CustomResource, CustomResourceExt
};

// NB: This example uses server side apply and beta1 customresources
Expand Down
2 changes: 1 addition & 1 deletion examples/crd_derive.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use k8s_openapi::apimachinery::pkg::apis::meta::v1::Condition;
use kube::{CustomResource, Resource};
use kube::{CustomResource, CustomResourceExt, Resource};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

Expand Down
3 changes: 2 additions & 1 deletion examples/crd_derive_no_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ properties:
#[cfg(not(feature = "schema"))]
impl Bar {
fn crd_with_manual_schema() -> CustomResourceDefinition {
use kube::CustomResourceExt;
let schema: JSONSchemaProps = serde_yaml::from_str(MANUAL_SCHEMA).expect("invalid schema");

let mut crd = Self::crd();
let mut crd = <Self as CustomResourceExt>::crd();
crd.spec.versions.iter_mut().for_each(|v| {
v.schema = Some(CustomResourceValidation {
open_api_v3_schema: Some(schema.clone()),
Expand Down
2 changes: 1 addition & 1 deletion examples/crd_derive_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use kube::{
Api, ApiResource, DeleteParams, DynamicObject, GroupVersionKind, ListParams, Patch, PatchParams,
PostParams, WatchEvent,
},
Client, CustomResource,
Client, CustomResource, CustomResourceExt
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
Expand Down
40 changes: 40 additions & 0 deletions kube-core/src/crd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//! Traits and tyes for CustomResources
use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions as apiexts;

/// Types for v1 CustomResourceDefinitions
pub mod v1 {
use super::apiexts;
use crate::discovery::ApiResource;
/// Extension trait that will be implemented by kube-derive
///
/// This trait variant is implemented by default (or when `#[kube(apiextensions = "v1")]`)
pub trait CustomResourceExt {
/// Helper to generate the CRD including the JsonSchema
///
/// This is using the stable v1::CustomResourceDefinitions (present in kubernetes >= 1.16)
fn crd() -> apiexts::v1::CustomResourceDefinition;
/// Helper to generate the api information type for use with the dynamic `Api`
fn api_resource() -> ApiResource;
}
}

/// Types for legacy v1beta1 CustomResourceDefinitions
pub mod v1beta1 {
use super::apiexts;
use crate::discovery::ApiResource;
/// Extension trait that will be implemented by kube-derive for legacy v1beta1::CustomResourceDefinitions
///
/// This trait variant is only implemented with `#[kube(apiextensions = "v1beta1")]`
pub trait CustomResourceExt {
/// Helper to generate the legacy CRD without a JsonSchema
///
/// This is using v1beta1::CustomResourceDefinitions (which will be removed in kubernetes 1.22)
fn crd() -> apiexts::v1beta1::CustomResourceDefinition;
/// Helper to generate the api information type for use with the dynamic `Api`
fn api_resource() -> ApiResource;
}
}

/// re-export the current latest version until a newer one is available in cloud providers
pub use v1::CustomResourceExt;
3 changes: 3 additions & 0 deletions kube-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ pub mod discovery;
pub mod dynamic;
pub use dynamic::DynamicObject;

pub mod crd;
pub use crd::CustomResourceExt;

pub mod gvk;
pub use gvk::{GroupVersion, GroupVersionKind, GroupVersionResource};

Expand Down
11 changes: 7 additions & 4 deletions kube-derive/src/custom_resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea
let apiext = quote! {
k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::#v1ident
};
let extver = quote! {
kube::core::crd::#v1ident
};

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

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

pub fn api_resource() -> kube::core::ApiResource {
fn api_resource() -> kube::core::ApiResource {
kube::core::ApiResource::erase::<Self>(&())
}
}
Expand Down
11 changes: 7 additions & 4 deletions kube-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ mod custom_resource;
/// This root object will implement the [`kube::Resource`] trait
/// so it can be used with [`kube::Api`].
///
/// The generated type will also implement a `::crd` method to generate the crd
/// at the specified api version (or `v1` if unspecified).
/// The generated type will also implement kube's [`kube::CustomResourceExt`] trait to generate the crd
/// and generate [`kube::core::ApiResource`] information for use with the dynamic api.
///
/// # Example
///
/// ```rust
/// use serde::{Serialize, Deserialize};
/// use kube::Resource;
/// use kube::{Resource, CustomResourceExt};
/// use kube_derive::CustomResource;
/// use schemars::JsonSchema;
///
Expand Down Expand Up @@ -72,7 +72,8 @@ mod custom_resource;
/// The version for `CustomResourceDefinition` desired in the `apiextensions.k8s.io` group.
/// Default is `v1` (for clusters >= 1.17). If using kubernetes <= 1.16 please use `v1beta1`.
///
/// **NOTE**: Support for `v1` requires deriving the openapi v3 `JsonSchema` via the `schemars` dependency.
/// - **NOTE**: Support for `v1` requires deriving the openapi v3 `JsonSchema` via the `schemars` dependency.
/// - **NOTE**: When using `v1beta` the associated `CustomResourceExt` trait lives in `kube::core::crd::v1beta`
///
/// ### `#[kube(singular = "nonstandard-singular")]`
/// To specify the singular name. Defaults to lowercased `kind`.
Expand Down Expand Up @@ -196,6 +197,8 @@ mod custom_resource;
/// [`kube`]: https://docs.rs/kube
/// [`kube::Api`]: https://docs.rs/kube/*/kube/struct.Api.html
/// [`kube::Resource`]: https://docs.rs/kube/*/kube/trait.Resource.html
/// [`kube::core::ApiResource`]: https://docs.rs/kube/*/kube/core/struct.ApiResource.html
/// [`kube::CustomResourceExt`]: https://docs.rs/kube/*/kube/trait.CustomResourceExt.html
#[proc_macro_derive(CustomResource, attributes(kube))]
pub fn derive_custom_resource(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
custom_resource::derive(proc_macro2::TokenStream::from(input)).into()
Expand Down
1 change: 1 addition & 0 deletions kube-derive/tests/crd_schema_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ fn default_nullable() -> Option<String> {

#[test]
fn test_crd_schema_matches_expected() {
use kube::core::CustomResourceExt;
assert_eq!(
Foo::crd(),
serde_json::from_value(serde_json::json!({
Expand Down
3 changes: 2 additions & 1 deletion kube/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ pub mod core {
#[cfg_attr(docsrs, doc(cfg(feature = "admission")))]
pub use kube_core::admission;
pub use kube_core::{
crd::{self, CustomResourceExt},
dynamic::{self, ApiResource, DynamicObject},
gvk::{self, GroupVersionKind, GroupVersionResource},
metadata::{self, ListMeta, ObjectMeta, TypeMeta},
Expand All @@ -149,4 +150,4 @@ pub mod core {
Resource, ResourceExt,
};
}
pub use crate::core::{Resource, ResourceExt};
pub use crate::core::{CustomResourceExt, Resource, ResourceExt};

0 comments on commit ce61e71

Please sign in to comment.