kube_derive/
resource.rs

1// Generated by darling macros, out of our control
2#![allow(clippy::manual_unwrap_or_default)]
3
4use darling::{FromDeriveInput, FromMeta};
5use syn::{parse_quote, Data, DeriveInput, Path};
6
7/// Values we can parse from #[kube(attrs)]
8#[derive(Debug, FromDeriveInput)]
9#[darling(attributes(resource))]
10struct InheritAttrs {
11    inherit: syn::Path,
12    #[darling(default)]
13    crates: Crates,
14}
15
16#[derive(Debug, FromMeta)]
17struct Crates {
18    #[darling(default = "Self::default_kube_core")]
19    kube_core: Path,
20    #[darling(default = "Self::default_k8s_openapi")]
21    k8s_openapi: Path,
22}
23
24// Default is required when the subattribute isn't mentioned at all
25// Delegate to darling rather than deriving, so that we can piggyback off the `#[darling(default)]` clauses
26impl Default for Crates {
27    fn default() -> Self {
28        Self::from_list(&[]).unwrap()
29    }
30}
31
32impl Crates {
33    fn default_kube_core() -> Path {
34        parse_quote! { ::kube::core } // by default must work well with people using facade crate
35    }
36
37    fn default_k8s_openapi() -> Path {
38        parse_quote! { ::k8s_openapi }
39    }
40}
41
42pub(crate) fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
43    let derive_input: DeriveInput = match syn::parse2(input) {
44        Err(err) => return err.to_compile_error(),
45        Ok(di) => di,
46    };
47    // Limit derive to structs
48    match derive_input.data {
49        Data::Struct(_) | Data::Enum(_) => {}
50        _ => {
51            return syn::Error::new_spanned(&derive_input.ident, r#"Unions can not #[derive(Resource)]"#)
52                .to_compile_error()
53        }
54    }
55    let kube_attrs = match InheritAttrs::from_derive_input(&derive_input) {
56        Err(err) => return err.write_errors(),
57        Ok(attrs) => attrs,
58    };
59
60    let InheritAttrs {
61        inherit: resource,
62        crates: Crates {
63            kube_core,
64            k8s_openapi,
65        },
66        ..
67    } = kube_attrs;
68
69    let rootident = derive_input.ident;
70
71    let inherit_resource = quote! {
72        impl #kube_core::Resource for #rootident {
73            type DynamicType = <#resource as #kube_core::Resource>::DynamicType;
74            type Scope = <#resource as #kube_core::Resource>::Scope;
75
76            fn group(_: &<#resource as #kube_core::Resource>::DynamicType) -> std::borrow::Cow<'_, str> {
77                #resource::group(&Default::default()).into_owned().into()
78            }
79
80            fn kind(_: &<#resource as #kube_core::Resource>::DynamicType) -> std::borrow::Cow<'_, str> {
81                #resource::kind(&Default::default()).into_owned().into()
82            }
83
84            fn version(_: &<#resource as #kube_core::Resource>::DynamicType) -> std::borrow::Cow<'_, str> {
85                #resource::version(&Default::default()).into_owned().into()
86            }
87
88            fn api_version(_: &<#resource as #kube_core::Resource>::DynamicType) -> std::borrow::Cow<'_, str> {
89                #resource::api_version(&Default::default()).into_owned().into()
90            }
91
92            fn plural(_: &<#resource as #kube_core::Resource>::DynamicType) -> std::borrow::Cow<'_, str> {
93                #resource::plural(&Default::default()).into_owned().into()
94            }
95
96            fn meta(&self) -> &#k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta {
97                &self.metadata
98            }
99
100            fn meta_mut(&mut self) -> &mut #k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta {
101                &mut self.metadata
102            }
103        }
104    };
105
106    // Concat output
107    quote! {
108        #inherit_resource
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use super::*;
115
116    #[test]
117    fn test_parse_inherit() {
118        let input = quote! {
119            #[derive(Resource)]
120            #[resource(inherit = "ConfigMap")]
121            struct Foo { metadata: ObjectMeta }
122        };
123
124        let input = syn::parse2(input).unwrap();
125        InheritAttrs::from_derive_input(&input).unwrap();
126    }
127}