Skip to content

Commit

Permalink
Extend with supported values from docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Danil-Grigorev committed Oct 28, 2024
1 parent 159e746 commit 024cd08
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 8 deletions.
6 changes: 3 additions & 3 deletions examples/crd_derive_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use kube::{
runtime::wait::{await_condition, conditions},
Client, CustomResource, CustomResourceExt,
};
use kube_derive::cel_validation;
use kube::cel_validation;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -89,7 +89,7 @@ pub struct FooSpec {
set_listable: Vec<u32>,
// Field with CEL validation
#[serde(default)]
#[validated(rule = "self != 'illegal'", message = "string cannot be illegal")]
#[validated(rule = "self != 'illegal'", message_expression = "'string cannot be illegal'")]
#[validated(rule = "self != 'not legal'")]
cel_validated: Option<String>,
}
Expand Down Expand Up @@ -124,7 +124,7 @@ async fn main() -> Result<()> {
println!("Creating CRD v1");
let client = Client::try_default().await?;
delete_crd(client.clone()).await?;
assert!(create_crd(client.clone()).await.is_ok());
assert!(dbg!(create_crd(client.clone()).await).is_ok());

// Test creating Foo resource.
let foos = Api::<Foo>::default_namespaced(client.clone());
Expand Down
66 changes: 61 additions & 5 deletions kube-derive/src/custom_resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,21 @@ pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStrea
.to_compile_error()
}
}

if let Data::Struct(struct_data) = &derive_input.data {
if let syn::Fields::Named(fields) = &struct_data.fields {
for field in &fields.named {
if let Some(attr) = field.attrs.iter().find(|attr| attr.path().is_ident("validated")) {
return syn::Error::new_spanned(

Check warning on line 149 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L149

Added line #L149 was not covered by tests
attr,
r#"#[cel_validation] macro should be placed before the #[derive(JsonSchema)] macro to use with #[validated]"#,
)
.to_compile_error();

Check warning on line 153 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L153

Added line #L153 was not covered by tests
}
}
}
}

let kube_attrs = match KubeAttrs::from_derive_input(&derive_input) {
Err(err) => return err.write_errors(),
Ok(attrs) => attrs,
Expand Down Expand Up @@ -544,6 +559,9 @@ fn generate_hasspec(spec_ident: &Ident, root_ident: &Ident, kube_core: &Path) ->
struct CELAttr {
rule: String,
message: Option<String>,
message_expression: Option<String>,
field_path: Option<String>,
reason: Option<String>,
}

pub(crate) fn cel_validation(_: TokenStream, input: TokenStream) -> TokenStream {
Expand All @@ -560,8 +578,9 @@ pub(crate) fn cel_validation(_: TokenStream, input: TokenStream) -> TokenStream
.to_compile_error();

Check warning on line 578 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L578

Added line #L578 was not covered by tests
}

// Create a struct name for added validation rules, following the original struct name + "Validation"
let struct_name = ast.ident.to_string() + "Validation";
let anchor = Ident::new(&struct_name, Span::call_site());
let validation_struct = Ident::new(&struct_name, Span::call_site());

Check warning on line 583 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L582-L583

Added lines #L582 - L583 were not covered by tests

let mut validations: Vec<TokenStream> = vec![];

Check warning on line 585 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L585

Added line #L585 was not covered by tests

Expand All @@ -584,25 +603,62 @@ pub(crate) fn cel_validation(_: TokenStream, input: TokenStream) -> TokenStream
.iter()
.filter(|attr| attr.path().is_ident("validated"))

Check warning on line 604 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L604

Added line #L604 was not covered by tests
{
let CELAttr { rule, message } = match CELAttr::from_attributes(&vec![attr.clone()]) {
let CELAttr {
rule,
message,
field_path,
message_expression,
reason,

Check warning on line 611 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L606-L611

Added lines #L606 - L611 were not covered by tests
} = match CELAttr::from_attributes(&vec![attr.clone()]) {
Ok(cel) => cel,
Err(e) => return e.with_span(&attr.meta).write_errors(),

Check warning on line 614 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L613-L614

Added lines #L613 - L614 were not covered by tests
};
if let (Some(_), Some(_)) = (&message, &message_expression) {
return syn::Error::new_spanned(

Check warning on line 617 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L616-L617

Added lines #L616 - L617 were not covered by tests
attr,
r#"Either message or message_expression should be specified at once"#,
).to_compile_error()
}
let message = if let Some(message) = message {
quote! { "message": #message }
quote! { "message": #message, }

Check warning on line 623 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L622-L623

Added lines #L622 - L623 were not covered by tests
} else {
quote! {}

Check warning on line 625 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L625

Added line #L625 was not covered by tests
};
let field_path = if let Some(field_path) = field_path {
quote! { "fieldPath": #field_path, }

Check warning on line 628 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L627-L628

Added lines #L627 - L628 were not covered by tests
} else {
quote! {}

Check warning on line 630 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L630

Added line #L630 was not covered by tests
};
let message_expression = if let Some(message_expression) = message_expression {
quote! { "messageExpression": #message_expression, }

Check warning on line 633 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L632-L633

Added lines #L632 - L633 were not covered by tests
} else {
quote! {}

Check warning on line 635 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L635

Added line #L635 was not covered by tests
};
let reason = if let Some(reason) = reason {
quote! { "reason": #reason, }

Check warning on line 638 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L637-L638

Added lines #L637 - L638 were not covered by tests
} else {
quote! {}

Check warning on line 640 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L640

Added line #L640 was not covered by tests
};
rules.push(quote! {{

Check warning on line 642 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L642

Added line #L642 was not covered by tests
"rule": #rule,
#message
#field_path
#message_expression
#reason
},});
}

if rules.is_empty() {

Check warning on line 651 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L651

Added line #L651 was not covered by tests
continue;
}

field.attrs = field

Check warning on line 655 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L655

Added line #L655 was not covered by tests
.attrs
.clone()
.into_iter()
.filter(|attr| !attr.path().is_ident("validated"))
.collect();

Check warning on line 660 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L659-L660

Added lines #L659 - L660 were not covered by tests

let validation_method_name = field.ident.as_ref().map(|i| i.to_string()).unwrap_or_default();
let name = Ident::new(&validation_method_name, Span::call_site());
let field_type = &field.ty;

Check warning on line 664 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L662-L664

Added lines #L662 - L664 were not covered by tests
Expand Down Expand Up @@ -638,9 +694,9 @@ pub(crate) fn cel_validation(_: TokenStream, input: TokenStream) -> TokenStream
}

quote! {

Check warning on line 696 in kube-derive/src/custom_resource.rs

View check run for this annotation

Codecov / codecov/patch

kube-derive/src/custom_resource.rs#L696

Added line #L696 was not covered by tests
struct #anchor {}
struct #validation_struct {}

impl #anchor {
impl #validation_struct {
#(#validations)*
}

Expand Down

0 comments on commit 024cd08

Please sign in to comment.