use crate::{Client, Result};
pub use kube_core::discovery::{verbs, ApiCapabilities, ApiResource, Scope};
use kube_core::gvk::GroupVersionKind;
use std::collections::HashMap;
mod apigroup;
pub mod oneshot;
pub use apigroup::ApiGroup;
mod parse;
pub use oneshot::{group, pinned_group, pinned_kind};
enum DiscoveryMode {
Allow(Vec<String>),
Block(Vec<String>),
}
impl DiscoveryMode {
fn is_queryable(&self, group: &String) -> bool {
match &self {
Self::Allow(allowed) => allowed.contains(group),
Self::Block(blocked) => !blocked.contains(group),
}
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "client")))]
pub struct Discovery {
client: Client,
groups: HashMap<String, ApiGroup>,
mode: DiscoveryMode,
}
impl Discovery {
#[must_use]
pub fn new(client: Client) -> Self {
let groups = HashMap::new();
let mode = DiscoveryMode::Block(vec![]);
Self { client, groups, mode }
}
#[must_use]
pub fn filter(mut self, allow: &[&str]) -> Self {
self.mode = DiscoveryMode::Allow(allow.iter().map(ToString::to_string).collect());
self
}
#[must_use]
pub fn exclude(mut self, deny: &[&str]) -> Self {
self.mode = DiscoveryMode::Block(deny.iter().map(ToString::to_string).collect());
self
}
pub async fn run(mut self) -> Result<Self> {
self.groups.clear();
let api_groups = self.client.list_api_groups().await?;
for g in api_groups.groups {
let key = g.name.clone();
if self.mode.is_queryable(&key) {
let apigroup = ApiGroup::query_apis(&self.client, g).await?;
self.groups.insert(key, apigroup);
}
}
let corekey = ApiGroup::CORE_GROUP.to_string();
if self.mode.is_queryable(&corekey) {
let coreapis = self.client.list_core_api_versions().await?;
let apigroup = ApiGroup::query_core(&self.client, coreapis).await?;
self.groups.insert(corekey, apigroup);
}
Ok(self)
}
}
impl Discovery {
pub fn groups(&self) -> impl Iterator<Item = &ApiGroup> {
self.groups.values()
}
pub fn groups_alphabetical(&self) -> Vec<&ApiGroup> {
let mut values: Vec<_> = self.groups().collect();
values.sort_by_key(|g| g.name());
values
}
pub fn get(&self, group: &str) -> Option<&ApiGroup> {
self.groups.get(group)
}
pub fn has_group(&self, group: &str) -> bool {
self.groups.contains_key(group)
}
pub fn resolve_gvk(&self, gvk: &GroupVersionKind) -> Option<(ApiResource, ApiCapabilities)> {
self.get(&gvk.group)?
.versioned_resources(&gvk.version)
.into_iter()
.find(|res| res.0.kind == gvk.kind)
}
}