Skip to content

Commit

Permalink
refactor: split resource::Typed from Resource trait
Browse files Browse the repository at this point in the history
  • Loading branch information
SOF3 committed May 14, 2024
1 parent a6f4337 commit 49cf07e
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 40 deletions.
8 changes: 4 additions & 4 deletions kube-client/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub use kube_core::{
watch::WatchEvent,
Resource, ResourceExt,
};
use kube_core::{DynamicResourceScope, NamespaceResourceScope};
use kube_core::{resource, DynamicResourceScope, NamespaceResourceScope};
pub use params::{
DeleteParams, GetParams, ListParams, Patch, PatchParams, PostParams, Preconditions, PropagationPolicy,
ValidationDirective, VersionMatch, WatchParams,
Expand Down Expand Up @@ -66,7 +66,7 @@ pub struct Api<K> {
/// Api constructors for Resource implementors with custom DynamicTypes
///
/// This generally means resources created via [`DynamicObject`](crate::api::DynamicObject).
impl<K: Resource> Api<K> {
impl<K: resource::Typed> Api<K> {
/// Cluster level resources, or resources viewed across all namespaces
///
/// This function accepts `K::DynamicType` so it can be used with dynamic resources.
Expand Down Expand Up @@ -131,9 +131,9 @@ impl<K: Resource> Api<K> {
/// Api constructors for Resource implementors with Default DynamicTypes
///
/// This generally means structs implementing `k8s_openapi::Resource`.
impl<K: Resource> Api<K>
impl<K: resource::Typed> Api<K>
where
<K as Resource>::DynamicType: Default,
<K as resource::Typed>::DynamicType: Default,
{
/// Cluster level resources, or resources viewed across all namespaces
///
Expand Down
15 changes: 6 additions & 9 deletions kube-client/src/client/client_ext.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
use crate::{Client, Error, Result};
use k8s_openapi::api::core::v1::Namespace as k8sNs;
use kube_core::{
object::ObjectList,
params::{GetParams, ListParams},
request::Request,
ClusterResourceScope, DynamicResourceScope, NamespaceResourceScope, Resource,
object::ObjectList, params::{GetParams, ListParams}, request::Request, resource, ClusterResourceScope, DynamicResourceScope, NamespaceResourceScope, Resource
};
use serde::{de::DeserializeOwned, Serialize};
use std::fmt::Debug;
Expand Down Expand Up @@ -174,8 +171,8 @@ impl Client {
/// ```
pub async fn get<K>(&self, name: &str, scope: &impl ObjectUrl<K>) -> Result<K>
where
K: Resource + Serialize + DeserializeOwned + Clone + Debug,
<K as Resource>::DynamicType: Default,
K: resource::Typed + Serialize + DeserializeOwned + Clone + Debug,
<K as resource::Typed>::DynamicType: Default,
{
let mut req = Request::new(scope.url_path())
.get(name, &GetParams::default())
Expand All @@ -184,7 +181,7 @@ impl Client {
self.request::<K>(req).await
}

/// List instances of a `Resource` implementing type `K` at the specified scope.
/// List instances of a [resource](resource::Typed) implementing type `K` at the specified scope.
///
/// ```no_run
/// # use k8s_openapi::api::core::v1::Pod;
Expand All @@ -205,8 +202,8 @@ impl Client {
/// ```
pub async fn list<K>(&self, lp: &ListParams, scope: &impl CollectionUrl<K>) -> Result<ObjectList<K>>
where
K: Resource + Serialize + DeserializeOwned + Clone + Debug,
<K as Resource>::DynamicType: Default,
K: resource::Typed + Serialize + DeserializeOwned + Clone + Debug,
<K as resource::Typed>::DynamicType: Default,
{
let mut req = Request::new(scope.url_path())
.list(lp)
Expand Down
6 changes: 4 additions & 2 deletions kube-core/src/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
pub use crate::discovery::ApiResource;
use crate::{
metadata::TypeMeta,
resource::{DynamicResourceScope, Resource},
resource::{self, DynamicResourceScope, Resource},
};

use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta;
Expand Down Expand Up @@ -75,7 +75,7 @@ impl DynamicObject {
}
}

impl Resource for DynamicObject {
impl resource::Typed for DynamicObject {
type DynamicType = ApiResource;
type Scope = DynamicResourceScope;

Expand All @@ -98,7 +98,9 @@ impl Resource for DynamicObject {
fn plural(dt: &ApiResource) -> Cow<'_, str> {
dt.plural.as_str().into()
}
}

impl Resource for DynamicObject {
fn meta(&self) -> &ObjectMeta {
&self.metadata
}
Expand Down
2 changes: 1 addition & 1 deletion kube-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub mod params;
pub mod request;
pub use request::Request;

mod resource;
pub mod resource;
pub use resource::{
api_version_from_group_version, ClusterResourceScope, DynamicResourceScope, NamespaceResourceScope,
Resource, ResourceExt, ResourceScope, SubResourceScope,
Expand Down
6 changes: 4 additions & 2 deletions kube-core/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{borrow::Cow, marker::PhantomData};
pub use k8s_openapi::apimachinery::pkg::apis::meta::v1::{ListMeta, ObjectMeta};
use serde::{Deserialize, Serialize};

use crate::{DynamicObject, Resource};
use crate::{resource, DynamicObject, Resource};

/// Type information that is flattened into every kubernetes object
#[derive(Deserialize, Serialize, Clone, Default, Debug, Eq, PartialEq, Hash)]
Expand Down Expand Up @@ -146,7 +146,7 @@ impl PartialObjectMetaExt for ObjectMeta {
}
}

impl<K: Resource> Resource for PartialObjectMeta<K> {
impl<K: resource::Typed> resource::Typed for PartialObjectMeta<K> {
type DynamicType = K::DynamicType;
type Scope = K::Scope;

Expand All @@ -165,7 +165,9 @@ impl<K: Resource> Resource for PartialObjectMeta<K> {
fn plural(dt: &Self::DynamicType) -> Cow<'_, str> {
K::plural(dt)
}
}

impl<K: Resource> Resource for PartialObjectMeta<K> {
fn meta(&self) -> &ObjectMeta {
&self.metadata
}
Expand Down
10 changes: 8 additions & 2 deletions kube-core/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use crate::{
discovery::ApiResource,
metadata::{ListMeta, ObjectMeta, TypeMeta},
resource::{DynamicResourceScope, Resource},
resource::{self, DynamicResourceScope, Resource},
};
use serde::{Deserialize, Deserializer, Serialize};
use std::borrow::Cow;
Expand Down Expand Up @@ -241,7 +241,7 @@ where
}
}

impl<P, U> Resource for Object<P, U>
impl<P, U> resource::Typed for Object<P, U>
where
P: Clone,
U: Clone,
Expand All @@ -268,7 +268,13 @@ where
fn api_version(dt: &ApiResource) -> Cow<'_, str> {
dt.api_version.as_str().into()
}
}

impl<P, U> Resource for Object<P, U>
where
P: Clone,
U: Clone,
{
fn meta(&self) -> &ObjectMeta {
&self.metadata
}
Expand Down
42 changes: 27 additions & 15 deletions kube-core/src/resource.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Types representing Kubernetes resource objects.
pub use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta;
use k8s_openapi::{
api::core::v1::ObjectReference,
Expand All @@ -12,19 +14,9 @@ pub use k8s_openapi::{ClusterResourceScope, NamespaceResourceScope, ResourceScop
pub struct DynamicResourceScope {}
impl ResourceScope for DynamicResourceScope {}

/// An accessor trait for a kubernetes Resource.
///
/// This is for a subset of Kubernetes type that do not end in `List`.
/// These types, using [`ObjectMeta`], SHOULD all have required properties:
/// - `.metadata`
/// - `.metadata.name`
///
/// And these optional properties:
/// - `.metadata.namespace`
/// - `.metadata.resource_version`
///
/// This avoids a bunch of the unnecessary unwrap mechanics for apps.
pub trait Resource {
/// Represents a type that can either statically imply a Kubernetes versioned resource type
/// or resolve into one given specific data.
pub trait Typed {
/// Type information for types that do not know their resource information at compile time.
///
/// Types that know their metadata at compile time should select `DynamicType = ()`.
Expand Down Expand Up @@ -72,7 +64,21 @@ pub trait Resource {
plural = plural
)
}
}

/// An accessor trait for a kubernetes Resource.
///
/// This is for a subset of Kubernetes type that do not end in `List`.
/// These types, using [`ObjectMeta`], SHOULD all have required properties:
/// - `.metadata`
/// - `.metadata.name`
///
/// And these optional properties:
/// - `.metadata.namespace`
/// - `.metadata.resource_version`
///
/// This avoids a bunch of the unnecessary unwrap mechanics for apps.
pub trait Resource: Typed {
/// Metadata that all persisted resources must have
fn meta(&self) -> &ObjectMeta;
/// Metadata that all persisted resources must have
Expand Down Expand Up @@ -166,8 +172,7 @@ pub fn api_version_from_group_version<'a>(group: Cow<'a, str>, version: Cow<'a,
output
}

/// Implement accessor trait for any ObjectMeta-using Kubernetes Resource
impl<K, S> Resource for K
impl<K, S> Typed for K
where
K: k8s_openapi::Metadata<Ty = ObjectMeta>,
K: k8s_openapi::Resource<Scope = S>,
Expand All @@ -194,7 +199,14 @@ where
fn plural(_: &()) -> Cow<'_, str> {
K::URL_PATH_SEGMENT.into()
}
}

/// Implement accessor trait for any ObjectMeta-using Kubernetes Resource
impl<K, S> Resource for K
where
K: k8s_openapi::Metadata<Ty = ObjectMeta>,
K: k8s_openapi::Resource<Scope = S>,
{
fn meta(&self) -> &ObjectMeta {
self.metadata()
}
Expand Down
10 changes: 5 additions & 5 deletions kube-runtime/src/controller/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use futures::{
future::{self, BoxFuture},
stream, FutureExt, Stream, StreamExt, TryFuture, TryFutureExt, TryStream, TryStreamExt,
};
use kube_client::api::{Api, DynamicObject, Resource};
use kube_client::{api::{Api, DynamicObject, Resource}, core::resource};
use pin_project::pin_project;
use serde::de::DeserializeOwned;
use std::{
Expand Down Expand Up @@ -149,13 +149,13 @@ where
fn trigger_others<S, K, I>(
stream: S,
mapper: impl Fn(S::Ok) -> I + Sync + Send + 'static,
dyntype: <S::Ok as Resource>::DynamicType,
dyntype: <S::Ok as resource::Typed>::DynamicType,
) -> impl Stream<Item = Result<ReconcileRequest<K>, S::Error>>
where
// Input stream has items as some Resource (via Controller::watches)
S: TryStream,
S::Ok: Resource,
<S::Ok as Resource>::DynamicType: Clone,
<S::Ok as resource::Typed>::DynamicType: Clone,
// Output stream is requests for the root type K
K: Resource,
K::DynamicType: Clone,
Expand Down Expand Up @@ -212,12 +212,12 @@ where
pub fn trigger_owners<KOwner, S>(
stream: S,
owner_type: KOwner::DynamicType,
child_type: <S::Ok as Resource>::DynamicType,
child_type: <S::Ok as resource::Typed>::DynamicType,
) -> impl Stream<Item = Result<ReconcileRequest<KOwner>, S::Error>>
where
S: TryStream,
S::Ok: Resource,
<S::Ok as Resource>::DynamicType: Clone,
<S::Ok as resource::Typed>::DynamicType: Clone,
KOwner: Resource,
KOwner::DynamicType: Clone,
{
Expand Down

0 comments on commit 49cf07e

Please sign in to comment.