@@ -5,9 +5,10 @@ use k8s_openapi::{
55} ;
66use kube_core:: {
77 object:: ObjectList ,
8- params:: { GetParams , ListParams } ,
8+ params:: { GetParams , ListParams , Patch , PatchParams } ,
99 request:: Request ,
10- ApiResource , ClusterResourceScope , DynamicResourceScope , NamespaceResourceScope , Resource ,
10+ ApiResource , ClusterResourceScope , DynamicResourceScope , NamespaceResourceScope , ObjectMeta , Resource ,
11+ ResourceExt ,
1112} ;
1213use serde:: { de:: DeserializeOwned , Serialize } ;
1314use std:: fmt:: Debug ;
@@ -149,7 +150,7 @@ where
149150
150151/// Scopes for `unstable-client` [`Client#impl-Client`] extension methods
151152pub mod scope {
152- pub use super :: { Cluster , Namespace , NamespacedRef } ;
153+ pub use super :: { Cluster , Namespace , NamespacedRef , Subresource } ;
153154}
154155
155156// All objects can be listed cluster-wide
@@ -230,6 +231,15 @@ pub enum NamespaceError {
230231 MissingName ,
231232}
232233
234+ #[ derive( Default ) ]
235+ pub enum Subresource {
236+ #[ default]
237+ Core ,
238+ Status ,
239+ Scale ,
240+ Custom ( String ) ,
241+ }
242+
233243/// Generic client extensions for the `unstable-client` feature
234244///
235245/// These methods allow users to query across a wide-array of resources without needing
@@ -385,6 +395,54 @@ impl Client {
385395 req. extensions_mut ( ) . insert ( "list" ) ;
386396 self . request :: < ObjectList < K > > ( req) . await
387397 }
398+
399+ /// Patch provided `Resource` implementing type `K`
400+ ///
401+ /// ```no_run
402+ /// # use k8s_openapi::api::core::v1::Pod;
403+ /// # use k8s_openapi::api::core::v1::Service;
404+ /// # use kube::client::scope::{Namespace, Subresource};
405+ /// # use kube::prelude::*;
406+ /// # use kube::api::{PatchParams, Patch};
407+ /// # async fn wrapper() -> Result<(), Box<dyn std::error::Error>> {
408+ /// # let client: kube::Client = todo!();
409+ /// let pod: Pod = client.get("some_pod", &Namespace::from("default")).await?;
410+ /// let pp = &PatchParams::apply("controller").force();
411+ /// // Perform an apply patch on the resource
412+ /// client.patch(pod, pp, &Patch::Apply(&pod), &Default::default()).await?;
413+ /// // Perform an apply patch on the resource status
414+ /// client.patch(pod, pp, &Patch::Apply(&pod), &Subresource::Status).await?;
415+ /// # Ok(())
416+ /// # }
417+ /// ```
418+ pub async fn patch < K , P : Serialize + Debug > (
419+ & self ,
420+ resource : & K ,
421+ pp : & PatchParams ,
422+ patch : & Patch < P > ,
423+ subresource : & Subresource ,
424+ ) -> Result < K >
425+ where
426+ K : ResourceExt + Serialize + DeserializeOwned + Clone + Debug ,
427+ <K as Resource >:: DynamicType : Default ,
428+ {
429+ let name = resource. meta ( ) . name . as_ref ( ) . ok_or ( Error :: NameResolve ) ?;
430+ let url = K :: url_path ( & Default :: default ( ) , resource. meta ( ) . namespace . as_deref ( ) ) ;
431+ let req = Request :: new ( url) ;
432+ let req = match subresource {
433+ Subresource :: Core => req. patch ( name, pp, patch) . map_err ( Error :: BuildRequest ) ?,
434+ Subresource :: Status => req
435+ . patch_subresource ( "status" , name, pp, patch)
436+ . map_err ( Error :: BuildRequest ) ?,
437+ Subresource :: Scale => req
438+ . patch_subresource ( "scale" , name, pp, patch)
439+ . map_err ( Error :: BuildRequest ) ?,
440+ Subresource :: Custom ( subresource) => req
441+ . patch_subresource ( subresource, name, pp, patch)
442+ . map_err ( Error :: BuildRequest ) ?,
443+ } ;
444+ self . request :: < K > ( req) . await
445+ }
388446}
389447
390448// Resource url_path resolver
0 commit comments