@@ -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,53 @@ 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+ /// // Perform an apply patch on the resource
411+ /// client.patch(pod, &PatchParams::apply("controller").force(), &Patch::Apply(&pod), &Default::default()).await?;
412+ /// // Perform an apply patch on the resource status
413+ /// client.patch(pod, &PatchParams::apply("controller").force(), &Patch::Apply(&pod), &Subresource::Status).await?;
414+ /// # Ok(())
415+ /// # }
416+ /// ```
417+ pub async fn patch < K , P : Serialize + Debug > (
418+ & self ,
419+ resource : & K ,
420+ pp : & PatchParams ,
421+ patch : & Patch < P > ,
422+ subresource : & Subresource ,
423+ ) -> Result < K >
424+ where
425+ K : ResourceExt + Serialize + DeserializeOwned + Clone + Debug ,
426+ <K as Resource >:: DynamicType : Default ,
427+ {
428+ let name = resource. meta ( ) . name . as_ref ( ) . ok_or ( Error :: NameResolve ) ?;
429+ let url = K :: url_path ( & Default :: default ( ) , resource. meta ( ) . namespace . as_deref ( ) ) ;
430+ let req = Request :: new ( url) ;
431+ let req = match subresource {
432+ Subresource :: Core => req. patch ( name, pp, patch) . map_err ( Error :: BuildRequest ) ?,
433+ Subresource :: Status => req
434+ . patch_subresource ( "status" , name, pp, patch)
435+ . map_err ( Error :: BuildRequest ) ?,
436+ Subresource :: Scale => req
437+ . patch_subresource ( "scale" , name, pp, patch)
438+ . map_err ( Error :: BuildRequest ) ?,
439+ Subresource :: Custom ( subresource) => req
440+ . patch_subresource ( subresource, name, pp, patch)
441+ . map_err ( Error :: BuildRequest ) ?,
442+ } ;
443+ self . request :: < K > ( req) . await
444+ }
388445}
389446
390447// Resource url_path resolver
0 commit comments