mod core_methods;
#[cfg(feature = "ws")] mod remote_command;
use std::fmt::Debug;
#[cfg(feature = "ws")] pub use remote_command::{AttachedProcess, TerminalSize};
#[cfg(feature = "ws")] mod portforward;
#[cfg(feature = "ws")] pub use portforward::Portforwarder;
mod subresource;
#[cfg_attr(docsrs, doc(cfg(feature = "k8s_if_ge_1_33")))]
pub use subresource::Resize;
#[cfg(feature = "ws")]
#[cfg_attr(docsrs, doc(cfg(feature = "ws")))]
pub use subresource::{Attach, AttachParams, Ephemeral, Execute, Portforward};
pub use subresource::{Evict, EvictParams, Log, LogParams, ScaleSpec, ScaleStatus};
mod util;
pub mod entry;
#[cfg(feature = "admission")]
#[cfg_attr(docsrs, doc(cfg(feature = "admission")))]
pub use kube_core::admission;
pub(crate) use kube_core::params;
use kube_core::{DynamicResourceScope, NamespaceResourceScope};
pub use kube_core::{
Resource, ResourceExt,
dynamic::{ApiResource, DynamicObject},
gvk::{GroupVersionKind, GroupVersionResource},
metadata::{ListMeta, ObjectMeta, PartialObjectMeta, PartialObjectMetaExt, TypeMeta},
object::{NotUsed, Object, ObjectList},
request::Request,
watch::WatchEvent,
};
pub use params::{
DeleteParams, GetParams, ListParams, Patch, PatchParams, PostParams, Preconditions, PropagationPolicy,
ValidationDirective, VersionMatch, WatchParams,
};
use crate::Client;
#[cfg_attr(docsrs, doc(cfg(feature = "client")))]
#[derive(Clone)]
pub struct Api<K> {
pub(crate) request: Request,
pub(crate) client: Client,
namespace: Option<String>,
pub(crate) _phantom: std::iter::Empty<K>,
}
impl<K: Resource> Api<K> {
pub fn namespace(&self) -> Option<&str> {
self.namespace.as_deref()
}
pub fn all_with(client: Client, dyntype: &K::DynamicType) -> Self {
let url = K::url_path(dyntype, None);
Self {
client,
request: Request::new(url),
namespace: None,
_phantom: std::iter::empty(),
}
}
pub fn namespaced_with(client: Client, ns: &str, dyntype: &K::DynamicType) -> Self
where
K: Resource<Scope = DynamicResourceScope>,
{
let url = K::url_path(dyntype, Some(ns));
Self {
client,
request: Request::new(url),
namespace: Some(ns.to_string()),
_phantom: std::iter::empty(),
}
}
pub fn default_namespaced_with(client: Client, dyntype: &K::DynamicType) -> Self
where
K: Resource<Scope = DynamicResourceScope>,
{
let ns = client.default_namespace().to_string();
Self::namespaced_with(client, &ns, dyntype)
}
pub fn into_client(self) -> Client {
self.into()
}
pub fn resource_url(&self) -> &str {
&self.request.url_path
}
}
impl<K: Resource> Api<K>
where
<K as Resource>::DynamicType: Default,
{
pub fn all(client: Client) -> Self {
Self::all_with(client, &K::DynamicType::default())
}
pub fn namespaced(client: Client, ns: &str) -> Self
where
K: Resource<Scope = NamespaceResourceScope>,
{
let dyntype = K::DynamicType::default();
let url = K::url_path(&dyntype, Some(ns));
Self {
client,
request: Request::new(url),
namespace: Some(ns.to_string()),
_phantom: std::iter::empty(),
}
}
pub fn default_namespaced(client: Client) -> Self
where
K: Resource<Scope = NamespaceResourceScope>,
{
let ns = client.default_namespace().to_string();
Self::namespaced(client, &ns)
}
}
impl<K> From<Api<K>> for Client {
fn from(api: Api<K>) -> Self {
api.client
}
}
impl<K> Debug for Api<K> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self {
request,
client: _,
namespace,
_phantom,
} = self;
f.debug_struct("Api")
.field("request", &request)
.field("client", &"...")
.field("namespace", &namespace)
.finish()
}
}
#[cfg(test)]
mod test {
use crate::{Api, Client, client::Body};
use k8s_openapi::api::core::v1 as corev1;
use http::{Request, Response};
use tower_test::mock;
#[tokio::test]
async fn scopes_should_allow_correct_interface() {
let (mock_service, _handle) = mock::pair::<Request<Body>, Response<Body>>();
let client = Client::new(mock_service, "default");
let _: Api<corev1::Node> = Api::all(client.clone());
let _: Api<corev1::Pod> = Api::default_namespaced(client.clone());
let _: Api<corev1::PersistentVolume> = Api::all(client.clone());
let _: Api<corev1::ConfigMap> = Api::namespaced(client, "default");
}
}