kube_client/discovery/
oneshot.rs

1//! single use discovery utils
2//!
3//! These helpers provides a simpler discovery interface, but do not offer any built-in caching.
4//!
5//! This can provide specific information for 3 cases:
6//! - single kind in a particular group at a pinned version via [`oneshot::pinned_kind`]
7//! - all kinds in a group at pinned version: "apiregistration.k8s.io/v1" via [`oneshot::pinned_group`]
8//! - all kinds/version combinations in a group: "apiregistration.k8s.io" via [`oneshot::group`]
9//!
10//! [`oneshot::group`]: crate::discovery::group
11//! [`oneshot::pinned_group`]: crate::discovery::pinned_group
12//! [`oneshot::pinned_kind`]: crate::discovery::pinned_kind
13
14use super::ApiGroup;
15use crate::{error::DiscoveryError, Client, Error, Result};
16use kube_core::{
17    discovery::{ApiCapabilities, ApiResource},
18    gvk::{GroupVersion, GroupVersionKind},
19};
20
21/// Discovers all APIs available under a certain group at all versions
22///
23/// This is recommended if you work with one group, but do not want to pin the version
24/// of the apigroup. You can instead work with a recommended version (preferred or latest).
25///
26/// ```no_run
27/// use kube::{Client, api::{Api, DynamicObject}, discovery, ResourceExt};
28/// #[tokio::main]
29/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
30///     let client = Client::try_default().await?;
31///     let apigroup = discovery::group(&client, "apiregistration.k8s.io").await?;
32///     let (ar, caps) = apigroup.recommended_kind("APIService").unwrap();
33///     let api: Api<DynamicObject> = Api::all_with(client.clone(), &ar);
34///     for service in api.list(&Default::default()).await? {
35///         println!("Found APIService: {}", service.name_any());
36///     }
37///     Ok(())
38/// }
39/// ```
40pub async fn group(client: &Client, apigroup: &str) -> Result<ApiGroup> {
41    if apigroup == ApiGroup::CORE_GROUP {
42        let coreapis = client.list_core_api_versions().await?;
43        return ApiGroup::query_core(client, coreapis).await;
44    } else {
45        let api_groups = client.list_api_groups().await?;
46        for g in api_groups.groups {
47            if g.name != apigroup {
48                continue;
49            }
50            return ApiGroup::query_apis(client, g).await;
51        }
52    }
53    Err(Error::Discovery(DiscoveryError::MissingApiGroup(
54        apigroup.to_string(),
55    )))
56}
57
58/// Discovers all APIs available under a certain group at a pinned version
59///
60/// This is a cheaper variant of [`oneshot::group`](crate::discovery::oneshot::group) when you know what version you want.
61///
62/// ```no_run
63/// use kube::{Client, api::{Api, DynamicObject}, discovery, ResourceExt};
64/// #[tokio::main]
65/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
66///     let client = Client::try_default().await?;
67///     let gv = "apiregistration.k8s.io/v1".parse()?;
68///     let apigroup = discovery::pinned_group(&client, &gv).await?;
69///     let (ar, caps) = apigroup.recommended_kind("APIService").unwrap();
70///     let api: Api<DynamicObject> = Api::all_with(client.clone(), &ar);
71///     for service in api.list(&Default::default()).await? {
72///         println!("Found APIService: {}", service.name_any());
73///     }
74///     Ok(())
75/// }
76/// ```
77///
78/// While this example only uses a single kind, this type of discovery works best when you need more
79/// than a single `kind`.
80/// If you only need a single `kind`, [`oneshot::pinned_kind`](crate::discovery::pinned_kind) is the best solution.
81pub async fn pinned_group(client: &Client, gv: &GroupVersion) -> Result<ApiGroup> {
82    ApiGroup::query_gv(client, gv).await
83}
84
85/// Single discovery for a single GVK
86///
87/// This is an optimized function that avoids the unnecessary listing of api groups.
88/// It merely requests the api group resources for the specified apigroup, and then resolves the kind.
89///
90/// ```no_run
91/// use kube::{Client, api::{Api, DynamicObject, GroupVersionKind}, discovery, ResourceExt};
92/// #[tokio::main]
93/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
94///     let client = Client::try_default().await?;
95///     let gvk = GroupVersionKind::gvk("apiregistration.k8s.io", "v1", "APIService");
96///     let (ar, caps) = discovery::pinned_kind(&client, &gvk).await?;
97///     let api: Api<DynamicObject> = Api::all_with(client.clone(), &ar);
98///     for service in api.list(&Default::default()).await? {
99///         println!("Found APIService: {}", service.name_any());
100///     }
101///     Ok(())
102/// }
103/// ```
104pub async fn pinned_kind(client: &Client, gvk: &GroupVersionKind) -> Result<(ApiResource, ApiCapabilities)> {
105    ApiGroup::query_gvk(client, gvk).await
106}