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

refactor: split resource::Typed from Resource trait #1495

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading