Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move ApiCapabilities into ApiResource and add Scope trait #1038

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
2 changes: 0 additions & 2 deletions examples/crd_derive_multi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ async fn main() -> anyhow::Result<()> {
let newvarv2_2 = v2api.patch("new", &ssapply, &Patch::Apply(&v2m)).await?;
info!("new on v2 correct on reapply to v2: {:?}", newvarv2_2.spec);


// note we can apply old versions without them being truncated to the v2 schema
// in our case this means we cannot fetch them with our v1 schema (breaking change to not have oldprop)
let v1m2 = v1::ManyDerive::new("old", v1::ManyDeriveSpec {
Expand All @@ -101,7 +100,6 @@ async fn main() -> anyhow::Result<()> {
Ok(())
}


async fn apply_crd(client: Client, crd: CustomResourceDefinition) -> anyhow::Result<()> {
let crds: Api<CustomResourceDefinition> = Api::all(client.clone());
info!("Creating crd: {}", serde_yaml::to_string(&crd)?);
Expand Down
13 changes: 7 additions & 6 deletions examples/dynamic_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use kube::{
api::{Api, DynamicObject, ResourceExt},
discovery::{verbs, Discovery, Scope},
discovery::{verbs, Discovery},
Client,
};
use tracing::*;
Expand All @@ -14,14 +14,15 @@ async fn main() -> anyhow::Result<()> {

let discovery = Discovery::new(client.clone()).run().await?;
for group in discovery.groups() {
for (ar, caps) in group.recommended_resources() {
if !caps.supports_operation(verbs::LIST) {
for ar in group.recommended_resources() {
if !ar.supports_operation(verbs::LIST) {
continue;
}
let api: Api<DynamicObject> = if caps.scope == Scope::Cluster {
Api::all_with(client.clone(), &ar)
} else {

let api: Api<DynamicObject> = if ar.namespaced() {
Api::default_namespaced_with(client.clone(), &ar)
} else {
Api::all_with(client.clone(), &ar)
};

info!("{}/{} : {}", group.name(), ar.version, ar.kind);
Expand Down
10 changes: 5 additions & 5 deletions examples/dynamic_watcher.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use futures::{StreamExt, TryStreamExt};
use kube::{
api::{Api, DynamicObject, GroupVersionKind, ListParams, ResourceExt},
discovery::{self, Scope},
discovery,
runtime::{watcher, WatchStreamExt},
Client,
};
Expand All @@ -22,18 +22,18 @@ async fn main() -> anyhow::Result<()> {
// Turn them into a GVK
let gvk = GroupVersionKind::gvk(&group, &version, &kind);
// Use API discovery to identify more information about the type (like its plural)
let (ar, caps) = discovery::pinned_kind(&client, &gvk).await?;
let ar = discovery::pinned_kind(&client, &gvk).await?;

// Use the full resource info to create an Api with the ApiResource as its DynamicType
let api = Api::<DynamicObject>::all_with(client, &ar);

// Fully compatible with kube-runtime
let mut items = watcher(api, ListParams::default()).applied_objects().boxed();
while let Some(p) = items.try_next().await? {
if caps.scope == Scope::Cluster {
info!("saw {}", p.name_any());
if let Some(ns) = p.namespace() {
info!("saw {} in {}", p.name_any(), ns);
} else {
info!("saw {} in {}", p.name_any(), p.namespace().unwrap());
info!("saw {}", p.name_any());
}
}
Ok(())
Expand Down
24 changes: 9 additions & 15 deletions examples/kubectl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use k8s_openapi::{
use kube::{
api::{Api, DynamicObject, ListParams, Patch, PatchParams, ResourceExt},
core::GroupVersionKind,
discovery::{ApiCapabilities, ApiResource, Discovery, Scope},
discovery::{ApiResource, Discovery},
runtime::{
wait::{await_condition, conditions::is_deleted},
watcher, WatchStreamExt,
Expand Down Expand Up @@ -66,7 +66,7 @@ enum Verb {
Apply,
}

fn resolve_api_resource(discovery: &Discovery, name: &str) -> Option<(ApiResource, ApiCapabilities)> {
fn resolve_api_resource(discovery: &Discovery, name: &str) -> Option<ApiResource> {
// iterate through groups to find matching kind/plural names at recommended versions
// and then take the minimal match by group.name (equivalent to sorting groups by group.name).
// this is equivalent to kubectl's api group preference
Expand All @@ -78,7 +78,7 @@ fn resolve_api_resource(discovery: &Discovery, name: &str) -> Option<(ApiResourc
.into_iter()
.map(move |res| (group, res))
})
.filter(|(_, (res, _))| {
.filter(|(_, res)| {
// match on both resource name and kind name
// ideally we should allow shortname matches as well
name.eq_ignore_ascii_case(&res.kind) || name.eq_ignore_ascii_case(&res.plural)
Expand Down Expand Up @@ -169,8 +169,8 @@ impl App {
bail!("cannot apply object without valid TypeMeta {:?}", obj);
};
let name = obj.name_any();
if let Some((ar, caps)) = discovery.resolve_gvk(&gvk) {
let api = dynamic_api(ar, caps, client.clone(), &self.namespace, false);
if let Some(ar) = discovery.resolve_gvk(&gvk) {
let api = dynamic_api(ar, client.clone(), &self.namespace, false);
trace!("Applying {}: \n{}", gvk.kind, serde_yaml::to_string(&obj)?);
let data: serde_json::Value = serde_json::to_value(&obj)?;
let _r = api.patch(&name, &ssapply, &Patch::Apply(data)).await?;
Expand All @@ -195,13 +195,13 @@ async fn main() -> Result<()> {
// Defer to methods for verbs
if let Some(resource) = &app.resource {
// Common discovery, parameters, and api configuration for a single resource
let (ar, caps) = resolve_api_resource(&discovery, resource)
let ar = resolve_api_resource(&discovery, resource)
.with_context(|| format!("resource {:?} not found in cluster", resource))?;
let mut lp = ListParams::default();
if let Some(label) = &app.selector {
lp = lp.labels(label);
}
let api = dynamic_api(ar, caps, client, &app.namespace, app.all);
let api = dynamic_api(ar, client, &app.namespace, app.all);

tracing::info!(?app.verb, ?resource, name = ?app.name.clone().unwrap_or_default(), "requested objects");
match app.verb {
Expand All @@ -217,14 +217,8 @@ async fn main() -> Result<()> {
Ok(())
}

fn dynamic_api(
ar: ApiResource,
caps: ApiCapabilities,
client: Client,
ns: &Option<String>,
all: bool,
) -> Api<DynamicObject> {
if caps.scope == Scope::Cluster || all {
fn dynamic_api(ar: ApiResource, client: Client, ns: &Option<String>, all: bool) -> Api<DynamicObject> {
if !ar.namespaced() || all {
Api::all_with(client, &ar)
} else if let Some(namespace) = ns {
Api::namespaced_with(client, namespace, &ar)
Expand Down
Loading