From 9517a9dac95b163cd04c03b223b5baae2211ceea Mon Sep 17 00:00:00 2001 From: clux Date: Sun, 13 Oct 2024 11:32:36 +0100 Subject: [PATCH 1/8] Add features for serialization layer and an indireciton module Signed-off-by: clux --- Cargo.toml | 2 ++ kube-client/Cargo.toml | 5 ++++- kube-core/Cargo.toml | 5 ++++- kube-core/src/k8s.rs | 26 ++++++++++++++++++++++++++ kube/Cargo.toml | 7 +++++-- 5 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 kube-core/src/k8s.rs diff --git a/Cargo.toml b/Cargo.toml index 62b4d41be..cbb505e53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,8 @@ json-patch = "3" jsonptr = "0.6" jsonpath-rust = "0.5.0" k8s-openapi = { version = "0.23.0", default-features = false } +k8s-pb = "0.5.0" +#k8s-pb = { path = "../k8s-pb/k8s-pb" } openssl = "0.10.36" parking_lot = "0.12.0" pem = "3.0.1" diff --git a/kube-client/Cargo.toml b/kube-client/Cargo.toml index 776625513..51aaecb10 100644 --- a/kube-client/Cargo.toml +++ b/kube-client/Cargo.toml @@ -23,6 +23,8 @@ oauth = ["client", "tame-oauth"] oidc = ["client", "form_urlencoded"] gzip = ["client", "tower-http/decompression-gzip"] client = ["config", "__non_core", "hyper", "hyper-util", "http-body", "http-body-util", "tower", "tower-http", "hyper-timeout", "chrono", "jsonpath-rust", "bytes", "futures", "tokio", "tokio-util", "either"] +openapi = ["k8s-openapi", "kube-core/openapi"] +pb = ["k8s-pb", "kube-core/pb"] jsonpatch = ["kube-core/jsonpatch"] admission = ["kube-core/admission"] config = ["__non_core", "pem", "home"] @@ -78,7 +80,8 @@ secrecy = { workspace = true } tracing = { workspace = true, features = ["log"], optional = true } hyper-openssl = { workspace = true, features = ["client-legacy"], optional = true } form_urlencoded = { workspace = true, optional = true } -k8s-openapi= { workspace = true, features = [] } +k8s-openapi = { workspace = true, optional = true, features = [] } +k8s-pb = { workspace = true, optional = true } [dev-dependencies] kube = { path = "../kube", features = ["derive", "client", "ws"], version = "<1.0.0, >=0.61.0" } diff --git a/kube-core/Cargo.toml b/kube-core/Cargo.toml index 21e9edad6..eccb7b497 100644 --- a/kube-core/Cargo.toml +++ b/kube-core/Cargo.toml @@ -23,6 +23,8 @@ ws = [] admission = ["json-patch"] jsonpatch = ["json-patch"] schema = ["schemars"] +openapi = ["k8s-openapi"] +pb = ["k8s-pb"] kubelet-debug = ["ws"] [dependencies] @@ -34,7 +36,8 @@ http.workspace = true json-patch = { workspace = true, optional = true } chrono = { workspace = true, features = ["now"] } schemars = { workspace = true, optional = true } -k8s-openapi.workspace = true +k8s-openapi = { workspace = true, optional = true } +k8s-pb = { workspace = true, optional = true } serde-value.workspace = true [dev-dependencies] diff --git a/kube-core/src/k8s.rs b/kube-core/src/k8s.rs new file mode 100644 index 000000000..4f7ae163d --- /dev/null +++ b/kube-core/src/k8s.rs @@ -0,0 +1,26 @@ +//! Indirection layer for k8s-openapi / k8s-pb toggling. + +#[cfg(feature = "openapi")] +pub use k8s_openapi::{ + api::apps::v1::{DaemonSet, Deployment, ReplicaSet, StatefulSet}, + api::autoscaling::v1::{Scale, ScaleSpec, ScaleStatus}, + api::core::v1::{ConfigMap, ObjectReference, Pod}, + apiextensions_apiserver::pkg::apis::apiextensions, + apimachinery::pkg::apis::meta::v1::{ + LabelSelector, LabelSelectorRequirement, ListMeta, ManagedFieldsEntry, ObjectMeta, OwnerReference, + Time, + }, + ClusterResourceScope, Metadata, NamespaceResourceScope, Resource, ResourceScope, SubResourceScope, +}; +#[cfg(feature = "pb")] +pub use k8s_pb::{ + api::apps::v1::{DaemonSet, Deployment, ReplicaSet, StatefulSet}, + api::autoscaling::v1::{Scale, ScaleSpec, ScaleStatus}, + api::core::v1::{ConfigMap, ObjectReference, Pod}, + apiextensions_apiserver::pkg::apis::apiextensions, + apimachinery::pkg::apis::meta::v1::{ + LabelSelector, LabelSelectorRequirement, ListMeta, ManagedFieldsEntry, ObjectMeta, OwnerReference, + Time, + }, + ClusterResourceScope, Metadata, NamespaceResourceScope, Resource, ResourceScope, SubResourceScope, +}; diff --git a/kube/Cargo.toml b/kube/Cargo.toml index 8425973ab..a07aaac98 100644 --- a/kube/Cargo.toml +++ b/kube/Cargo.toml @@ -12,16 +12,18 @@ keywords = ["kubernetes", "client", "runtime", "cncf"] categories = ["network-programming", "caching", "api-bindings", "encoding"] [features] -default = ["client", "rustls-tls"] +default = ["client", "rustls-tls", "openapi"] # default features client = ["kube-client/client", "config"] config = ["kube-client/config"] rustls-tls = ["kube-client/rustls-tls", "client"] +openapi = ["k8s-openapi", "kube-client/openapi", "kube-core/openapi"] # alternative features openssl-tls = ["kube-client/openssl-tls", "client"] aws-lc-rs = ["kube-client?/aws-lc-rs"] +pb = ["k8s-pb", "kube-client/pb", "kube-core/pb"] # auxiliary features ws = ["kube-client/ws", "kube-core/ws"] @@ -54,7 +56,8 @@ kube-client = { path = "../kube-client", version = "=0.96.0", default-features = kube-runtime = { path = "../kube-runtime", version = "=0.96.0", optional = true} # Not used directly, but required by resolver 2.0 to ensure that the k8s-openapi dependency # is considered part of the "deps" graph rather than just the "dev-deps" graph -k8s-openapi.workspace = true +k8s-openapi = { workspace = true, optional = true } +k8s-pb = { workspace = true, optional = true } [dev-dependencies] tokio = { workspace = true, features = ["full"] } From 0e9be4ddc757de348849431f8fb459d22aa78d09 Mon Sep 17 00:00:00 2001 From: clux Date: Sun, 13 Oct 2024 11:33:08 +0100 Subject: [PATCH 2/8] introductory import changes in kube-core starting step towards compilation Signed-off-by: clux --- kube-core/src/crd.rs | 3 +-- kube-core/src/dynamic.rs | 13 +++++++------ kube-core/src/error_boundary.rs | 4 ++-- kube-core/src/gvk.rs | 2 +- kube-core/src/labels.rs | 2 +- kube-core/src/lib.rs | 7 ++++++- kube-core/src/metadata.rs | 4 ++-- kube-core/src/resource.rs | 14 +++++--------- kube-core/src/subresource.rs | 2 +- kube-core/src/util.rs | 2 +- 10 files changed, 27 insertions(+), 26 deletions(-) diff --git a/kube-core/src/crd.rs b/kube-core/src/crd.rs index 376e3d632..10cf2a781 100644 --- a/kube-core/src/crd.rs +++ b/kube-core/src/crd.rs @@ -1,6 +1,5 @@ //! Traits and tyes for CustomResources - -use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions as apiexts; +use crate::k8s::apiextensions as apiexts; /// Types for v1 CustomResourceDefinitions pub mod v1 { diff --git a/kube-core/src/dynamic.rs b/kube-core/src/dynamic.rs index ebaa7e3a6..ba2f51a06 100644 --- a/kube-core/src/dynamic.rs +++ b/kube-core/src/dynamic.rs @@ -2,12 +2,11 @@ //! //! For concrete usage see [examples prefixed with dynamic_](https://github.com/kube-rs/kube/tree/main/examples). pub use crate::discovery::ApiResource; +use crate::k8s::ObjectMeta; use crate::{ metadata::TypeMeta, resource::{DynamicResourceScope, Resource}, }; - -use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta; use std::borrow::Cow; use thiserror::Error; @@ -22,17 +21,18 @@ pub struct ParseDynamicObjectError { /// A dynamic representation of a kubernetes object /// /// This will work with any non-list type object. -#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "openapi", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq)] pub struct DynamicObject { /// The type fields, not always present - #[serde(flatten, default)] + #[cfg_attr(feature = "openapi", serde(flatten, default))] pub types: Option, /// Object metadata - #[serde(default)] + #[cfg_attr(feature = "openapi", serde(default))] pub metadata: ObjectMeta, /// All other keys - #[serde(flatten)] + #[cfg_attr(feature = "openapi", serde(flatten))] pub data: serde_json::Value, } @@ -68,6 +68,7 @@ impl DynamicObject { } /// Attempt to convert this `DynamicObject` to a `Resource` + #[cfg(feature = "openapi")] pub fn try_parse serde::Deserialize<'a>>( self, ) -> Result { diff --git a/kube-core/src/error_boundary.rs b/kube-core/src/error_boundary.rs index d1314f993..c6cc821c4 100644 --- a/kube-core/src/error_boundary.rs +++ b/kube-core/src/error_boundary.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; -use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta; +use crate::k8s::ObjectMeta; use serde::Deserialize; use serde_value::DeserializerError; use thiserror::Error; @@ -89,7 +89,7 @@ impl Resource for DeserializeGuard { #[cfg(test)] mod tests { - use k8s_openapi::api::core::v1::{ConfigMap, Pod}; + use crate::k8s::{ConfigMap, Pod}; use serde_json::json; use crate::{DeserializeGuard, Resource}; diff --git a/kube-core/src/gvk.rs b/kube-core/src/gvk.rs index 91b986601..4a140bc0e 100644 --- a/kube-core/src/gvk.rs +++ b/kube-core/src/gvk.rs @@ -1,8 +1,8 @@ //! Type information structs for dynamic resources. use std::str::FromStr; +use crate::k8s::{ObjectReference, OwnerReference}; use crate::TypeMeta; -use k8s_openapi::{api::core::v1::ObjectReference, apimachinery::pkg::apis::meta::v1::OwnerReference}; use serde::{Deserialize, Serialize}; use thiserror::Error; diff --git a/kube-core/src/labels.rs b/kube-core/src/labels.rs index eca0450e0..4548a40ef 100644 --- a/kube-core/src/labels.rs +++ b/kube-core/src/labels.rs @@ -1,6 +1,6 @@ //! Type safe label selector logic +use crate::k8s::{LabelSelector, LabelSelectorRequirement}; use core::fmt; -use k8s_openapi::apimachinery::pkg::apis::meta::v1::{LabelSelector, LabelSelectorRequirement}; use serde::{Deserialize, Serialize}; use std::{ cmp::PartialEq, diff --git a/kube-core/src/lib.rs b/kube-core/src/lib.rs index 969d10e0a..8ace7bd19 100644 --- a/kube-core/src/lib.rs +++ b/kube-core/src/lib.rs @@ -8,6 +8,8 @@ //! (even with zero features) under [`kube::core`]((https://docs.rs/kube/*/kube/core/index.html)). #![cfg_attr(docsrs, feature(doc_cfg))] +pub mod k8s; + #[cfg_attr(docsrs, doc(cfg(feature = "admission")))] #[cfg(feature = "admission")] pub mod admission; @@ -22,7 +24,9 @@ pub use duration::Duration; pub mod dynamic; pub use dynamic::{ApiResource, DynamicObject}; +#[cfg(feature = "openapi")] pub mod crd; +#[cfg(feature = "openapi")] pub use crd::CustomResourceExt; pub mod gvk; @@ -33,7 +37,8 @@ pub use metadata::{ListMeta, ObjectMeta, PartialObjectMeta, PartialObjectMetaExt pub mod labels; -#[cfg(feature = "kubelet-debug")] pub mod kubelet_debug; +#[cfg(feature = "kubelet-debug")] +pub mod kubelet_debug; pub mod object; pub use object::{NotUsed, Object, ObjectList}; diff --git a/kube-core/src/metadata.rs b/kube-core/src/metadata.rs index 67edf6e16..bd76a56ce 100644 --- a/kube-core/src/metadata.rs +++ b/kube-core/src/metadata.rs @@ -1,7 +1,7 @@ //! Metadata structs used in traits, lists, and dynamic objects. use std::{borrow::Cow, marker::PhantomData}; -pub use k8s_openapi::apimachinery::pkg::apis::meta::v1::{ListMeta, ObjectMeta}; +pub use crate::k8s::{ListMeta, ObjectMeta}; use serde::{Deserialize, Serialize}; use crate::{DynamicObject, Resource}; @@ -178,8 +178,8 @@ impl Resource for PartialObjectMeta { #[cfg(test)] mod test { use super::{ObjectMeta, PartialObjectMeta, PartialObjectMetaExt}; + use crate::k8s::Pod; use crate::Resource; - use k8s_openapi::api::core::v1::Pod; #[test] fn can_convert_and_derive_partial_metadata() { diff --git a/kube-core/src/resource.rs b/kube-core/src/resource.rs index 3ab1d88df..02eba3557 100644 --- a/kube-core/src/resource.rs +++ b/kube-core/src/resource.rs @@ -1,13 +1,9 @@ -pub use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta; -use k8s_openapi::{ - api::core::v1::ObjectReference, - apimachinery::pkg::apis::meta::v1::{ManagedFieldsEntry, OwnerReference, Time}, -}; +pub use crate::k8s::ObjectMeta; +pub use crate::k8s::{ClusterResourceScope, NamespaceResourceScope, ResourceScope, SubResourceScope}; +use crate::k8s::{ManagedFieldsEntry, ObjectReference, OwnerReference, Time}; use std::{borrow::Cow, collections::BTreeMap}; -pub use k8s_openapi::{ClusterResourceScope, NamespaceResourceScope, ResourceScope, SubResourceScope}; - /// Indicates that a [`Resource`] is of an indeterminate dynamic scope. pub struct DynamicResourceScope {} impl ResourceScope for DynamicResourceScope {} @@ -169,8 +165,8 @@ pub fn api_version_from_group_version<'a>(group: Cow<'a, str>, version: Cow<'a, /// Implement accessor trait for any ObjectMeta-using Kubernetes Resource impl Resource for K where - K: k8s_openapi::Metadata, - K: k8s_openapi::Resource, + K: crate::k8s::Metadata, + K: crate::k8s::Resource, { type DynamicType = (); type Scope = S; diff --git a/kube-core/src/subresource.rs b/kube-core/src/subresource.rs index d4dddce4e..b4ad62c6e 100644 --- a/kube-core/src/subresource.rs +++ b/kube-core/src/subresource.rs @@ -6,7 +6,7 @@ use crate::{ request::{Error, Request, JSON_MIME}, }; -pub use k8s_openapi::api::autoscaling::v1::{Scale, ScaleSpec, ScaleStatus}; +pub use crate::k8s::{Scale, ScaleSpec, ScaleStatus}; // ---------------------------------------------------------------------------- // Log subresource diff --git a/kube-core/src/util.rs b/kube-core/src/util.rs index 7f45e5500..e64f13ddf 100644 --- a/kube-core/src/util.rs +++ b/kube-core/src/util.rs @@ -1,11 +1,11 @@ //! Utils and helpers +use crate::k8s::{DaemonSet, Deployment, ReplicaSet, StatefulSet}; use crate::{ params::{Patch, PatchParams}, request, Request, }; use chrono::Utc; -use k8s_openapi::api::apps::v1::{DaemonSet, Deployment, ReplicaSet, StatefulSet}; /// Restartable Resource marker trait pub trait Restart {} From c3f21c855d969eb64d2abcde8b11bbf569d64773 Mon Sep 17 00:00:00 2001 From: clux Date: Sun, 13 Oct 2024 12:17:57 +0100 Subject: [PATCH 3/8] multiplex ResourceExt getters thankfully straightforward Signed-off-by: clux --- kube-core/src/dynamic.rs | 2 +- kube-core/src/gvk.rs | 6 ++-- kube-core/src/lib.rs | 9 ++--- kube-core/src/metadata.rs | 3 +- kube-core/src/resource.rs | 69 ++++++++++++++++++++++++++++++--------- kube-core/src/util.rs | 2 +- 6 files changed, 63 insertions(+), 28 deletions(-) diff --git a/kube-core/src/dynamic.rs b/kube-core/src/dynamic.rs index ba2f51a06..217a93dc0 100644 --- a/kube-core/src/dynamic.rs +++ b/kube-core/src/dynamic.rs @@ -2,8 +2,8 @@ //! //! For concrete usage see [examples prefixed with dynamic_](https://github.com/kube-rs/kube/tree/main/examples). pub use crate::discovery::ApiResource; -use crate::k8s::ObjectMeta; use crate::{ + k8s::ObjectMeta, metadata::TypeMeta, resource::{DynamicResourceScope, Resource}, }; diff --git a/kube-core/src/gvk.rs b/kube-core/src/gvk.rs index 4a140bc0e..683b2a7e7 100644 --- a/kube-core/src/gvk.rs +++ b/kube-core/src/gvk.rs @@ -1,8 +1,10 @@ //! Type information structs for dynamic resources. use std::str::FromStr; -use crate::k8s::{ObjectReference, OwnerReference}; -use crate::TypeMeta; +use crate::{ + k8s::{ObjectReference, OwnerReference}, + TypeMeta, +}; use serde::{Deserialize, Serialize}; use thiserror::Error; diff --git a/kube-core/src/lib.rs b/kube-core/src/lib.rs index 8ace7bd19..8bdd0c0b2 100644 --- a/kube-core/src/lib.rs +++ b/kube-core/src/lib.rs @@ -24,10 +24,8 @@ pub use duration::Duration; pub mod dynamic; pub use dynamic::{ApiResource, DynamicObject}; -#[cfg(feature = "openapi")] -pub mod crd; -#[cfg(feature = "openapi")] -pub use crd::CustomResourceExt; +#[cfg(feature = "openapi")] pub mod crd; +#[cfg(feature = "openapi")] pub use crd::CustomResourceExt; pub mod gvk; pub use gvk::{GroupVersion, GroupVersionKind, GroupVersionResource}; @@ -37,8 +35,7 @@ pub use metadata::{ListMeta, ObjectMeta, PartialObjectMeta, PartialObjectMetaExt pub mod labels; -#[cfg(feature = "kubelet-debug")] -pub mod kubelet_debug; +#[cfg(feature = "kubelet-debug")] pub mod kubelet_debug; pub mod object; pub use object::{NotUsed, Object, ObjectList}; diff --git a/kube-core/src/metadata.rs b/kube-core/src/metadata.rs index bd76a56ce..33b587585 100644 --- a/kube-core/src/metadata.rs +++ b/kube-core/src/metadata.rs @@ -178,8 +178,7 @@ impl Resource for PartialObjectMeta { #[cfg(test)] mod test { use super::{ObjectMeta, PartialObjectMeta, PartialObjectMetaExt}; - use crate::k8s::Pod; - use crate::Resource; + use crate::{k8s::Pod, Resource}; #[test] fn can_convert_and_derive_partial_metadata() { diff --git a/kube-core/src/resource.rs b/kube-core/src/resource.rs index 02eba3557..54642ab41 100644 --- a/kube-core/src/resource.rs +++ b/kube-core/src/resource.rs @@ -1,5 +1,6 @@ -pub use crate::k8s::ObjectMeta; -pub use crate::k8s::{ClusterResourceScope, NamespaceResourceScope, ResourceScope, SubResourceScope}; +pub use crate::k8s::{ + ClusterResourceScope, NamespaceResourceScope, ObjectMeta, ResourceScope, SubResourceScope, +}; use crate::k8s::{ManagedFieldsEntry, ObjectReference, OwnerReference, Time}; use std::{borrow::Cow, collections::BTreeMap}; @@ -260,6 +261,12 @@ pub trait ResourceExt: Resource { static EMPTY_MAP: BTreeMap = BTreeMap::new(); +#[cfg(feature = "openapi")] +type MetaMap = BTreeMap; +#[cfg(feature = "pb")] +type MetaMap = HashMap; +// TODO: needs to be HashMap for k8s-pb unless we can tweak prost output + impl ResourceExt for K { fn name_unchecked(&self) -> String { self.meta().name.clone().expect(".metadata.name missing") @@ -289,43 +296,73 @@ impl ResourceExt for K { self.meta().creation_timestamp.clone() } - fn labels(&self) -> &BTreeMap { - self.meta().labels.as_ref().unwrap_or(&EMPTY_MAP) + fn labels(&self) -> &MetaMap { + #[cfg(feature = "openapi")] + return self.meta().labels.as_ref().unwrap_or(&EMPTY_MAP); + #[cfg(feature = "pb")] + return self.meta().labels; } - fn labels_mut(&mut self) -> &mut BTreeMap { - self.meta_mut().labels.get_or_insert_with(BTreeMap::new) + fn labels_mut(&mut self) -> &mut MetaMap { + #[cfg(feature = "openapi")] + return self.meta_mut().labels.get_or_insert_with(BTreeMap::new); + #[cfg(feature = "pb")] + return &mut self.meta_mut().labels; } - fn annotations(&self) -> &BTreeMap { - self.meta().annotations.as_ref().unwrap_or(&EMPTY_MAP) + fn annotations(&self) -> &MetaMap { + #[cfg(feature = "openapi")] + return self.meta().annotations.as_ref().unwrap_or(&EMPTY_MAP); + #[cfg(feature = "pb")] + return self.meta().annotations; } - fn annotations_mut(&mut self) -> &mut BTreeMap { - self.meta_mut().annotations.get_or_insert_with(BTreeMap::new) + fn annotations_mut(&mut self) -> &mut MetaMap { + #[cfg(feature = "openapi")] + return self.meta_mut().annotations.get_or_insert_with(BTreeMap::new); + #[cfg(feature = "pb")] + return &mut self.meta_mut().annotations; } fn owner_references(&self) -> &[OwnerReference] { - self.meta().owner_references.as_deref().unwrap_or_default() + #[cfg(feature = "openapi")] + return self.meta().owner_references.as_deref().unwrap_or_default(); + #[cfg(feature = "pb")] + return self.meta().owner_references.as_ref(); } fn owner_references_mut(&mut self) -> &mut Vec { - self.meta_mut().owner_references.get_or_insert_with(Vec::new) + #[cfg(feature = "openapi")] + return self.meta_mut().owner_references.get_or_insert_with(Vec::new); + #[cfg(feature = "pb")] + return &mut self.meta_mut().owner_references; } fn finalizers(&self) -> &[String] { - self.meta().finalizers.as_deref().unwrap_or_default() + #[cfg(feature = "openapi")] + return self.meta().finalizers.as_deref().unwrap_or_default(); + #[cfg(feature = "pb")] + return self.meta().finalizers.as_ref(); } fn finalizers_mut(&mut self) -> &mut Vec { - self.meta_mut().finalizers.get_or_insert_with(Vec::new) + #[cfg(feature = "openapi")] + return self.meta_mut().finalizers.get_or_insert_with(Vec::new); + #[cfg(feature = "pb")] + return &mut self.meta_mut().finalizers; } fn managed_fields(&self) -> &[ManagedFieldsEntry] { - self.meta().managed_fields.as_deref().unwrap_or_default() + #[cfg(feature = "openapi")] + return self.meta().managed_fields.as_deref().unwrap_or_default(); + #[cfg(feature = "pb")] + return self.meta().managed_fields.as_ref(); } fn managed_fields_mut(&mut self) -> &mut Vec { - self.meta_mut().managed_fields.get_or_insert_with(Vec::new) + #[cfg(feature = "openapi")] + return self.meta_mut().managed_fields.get_or_insert_with(Vec::new); + #[cfg(feature = "pb")] + return &mut self.meta_mut().managed_fields; } } diff --git a/kube-core/src/util.rs b/kube-core/src/util.rs index e64f13ddf..797a29841 100644 --- a/kube-core/src/util.rs +++ b/kube-core/src/util.rs @@ -1,7 +1,7 @@ //! Utils and helpers -use crate::k8s::{DaemonSet, Deployment, ReplicaSet, StatefulSet}; use crate::{ + k8s::{DaemonSet, Deployment, ReplicaSet, StatefulSet}, params::{Patch, PatchParams}, request, Request, }; From a01e27d847eafb95a55389e39c2d3719101150e0 Mon Sep 17 00:00:00 2001 From: clux Date: Mon, 14 Oct 2024 21:05:49 +0100 Subject: [PATCH 4/8] avoid breaking all-features or existing setup Signed-off-by: clux --- Cargo.toml | 2 +- kube-core/src/k8s.rs | 7 ++++++- kube-core/src/resource.rs | 38 ++++++++++++++++---------------------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cbb505e53..6c32747ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,7 +61,7 @@ json-patch = "3" jsonptr = "0.6" jsonpath-rust = "0.5.0" k8s-openapi = { version = "0.23.0", default-features = false } -k8s-pb = "0.5.0" +k8s-pb = "0.6.0" #k8s-pb = { path = "../k8s-pb/k8s-pb" } openssl = "0.10.36" parking_lot = "0.12.0" diff --git a/kube-core/src/k8s.rs b/kube-core/src/k8s.rs index 4f7ae163d..0033ec3f7 100644 --- a/kube-core/src/k8s.rs +++ b/kube-core/src/k8s.rs @@ -1,5 +1,6 @@ //! Indirection layer for k8s-openapi / k8s-pb toggling. +/// Re-export k8s-openapi types by default #[cfg(feature = "openapi")] pub use k8s_openapi::{ api::apps::v1::{DaemonSet, Deployment, ReplicaSet, StatefulSet}, @@ -12,7 +13,8 @@ pub use k8s_openapi::{ }, ClusterResourceScope, Metadata, NamespaceResourceScope, Resource, ResourceScope, SubResourceScope, }; -#[cfg(feature = "pb")] +/// Re-export k8s-pb types when only pb feature enabled +#[cfg(all(not(feature = "openapi"), feature = "pb"))] pub use k8s_pb::{ api::apps::v1::{DaemonSet, Deployment, ReplicaSet, StatefulSet}, api::autoscaling::v1::{Scale, ScaleSpec, ScaleStatus}, @@ -24,3 +26,6 @@ pub use k8s_pb::{ }, ClusterResourceScope, Metadata, NamespaceResourceScope, Resource, ResourceScope, SubResourceScope, }; + +#[cfg(all(not(feature = "openapi"), not(feature = "pb")))] +compile_error!("At least one of openapi or pb feature must be enabled"); diff --git a/kube-core/src/resource.rs b/kube-core/src/resource.rs index 54642ab41..f98ca0894 100644 --- a/kube-core/src/resource.rs +++ b/kube-core/src/resource.rs @@ -261,12 +261,6 @@ pub trait ResourceExt: Resource { static EMPTY_MAP: BTreeMap = BTreeMap::new(); -#[cfg(feature = "openapi")] -type MetaMap = BTreeMap; -#[cfg(feature = "pb")] -type MetaMap = HashMap; -// TODO: needs to be HashMap for k8s-pb unless we can tweak prost output - impl ResourceExt for K { fn name_unchecked(&self) -> String { self.meta().name.clone().expect(".metadata.name missing") @@ -296,73 +290,73 @@ impl ResourceExt for K { self.meta().creation_timestamp.clone() } - fn labels(&self) -> &MetaMap { + fn labels(&self) -> &BTreeMap { #[cfg(feature = "openapi")] return self.meta().labels.as_ref().unwrap_or(&EMPTY_MAP); - #[cfg(feature = "pb")] - return self.meta().labels; + #[cfg(all(not(feature = "openapi"), feature = "pb"))] + return &self.meta().labels; } - fn labels_mut(&mut self) -> &mut MetaMap { + fn labels_mut(&mut self) -> &mut BTreeMap { #[cfg(feature = "openapi")] return self.meta_mut().labels.get_or_insert_with(BTreeMap::new); - #[cfg(feature = "pb")] + #[cfg(all(not(feature = "openapi"), feature = "pb"))] return &mut self.meta_mut().labels; } - fn annotations(&self) -> &MetaMap { + fn annotations(&self) -> &BTreeMap { #[cfg(feature = "openapi")] return self.meta().annotations.as_ref().unwrap_or(&EMPTY_MAP); - #[cfg(feature = "pb")] - return self.meta().annotations; + #[cfg(all(not(feature = "openapi"), feature = "pb"))] + return &self.meta().annotations; } - fn annotations_mut(&mut self) -> &mut MetaMap { + fn annotations_mut(&mut self) -> &mut BTreeMap { #[cfg(feature = "openapi")] return self.meta_mut().annotations.get_or_insert_with(BTreeMap::new); - #[cfg(feature = "pb")] + #[cfg(all(not(feature = "openapi"), feature = "pb"))] return &mut self.meta_mut().annotations; } fn owner_references(&self) -> &[OwnerReference] { #[cfg(feature = "openapi")] return self.meta().owner_references.as_deref().unwrap_or_default(); - #[cfg(feature = "pb")] + #[cfg(all(not(feature = "openapi"), feature = "pb"))] return self.meta().owner_references.as_ref(); } fn owner_references_mut(&mut self) -> &mut Vec { #[cfg(feature = "openapi")] return self.meta_mut().owner_references.get_or_insert_with(Vec::new); - #[cfg(feature = "pb")] + #[cfg(all(not(feature = "openapi"), feature = "pb"))] return &mut self.meta_mut().owner_references; } fn finalizers(&self) -> &[String] { #[cfg(feature = "openapi")] return self.meta().finalizers.as_deref().unwrap_or_default(); - #[cfg(feature = "pb")] + #[cfg(all(not(feature = "openapi"), feature = "pb"))] return self.meta().finalizers.as_ref(); } fn finalizers_mut(&mut self) -> &mut Vec { #[cfg(feature = "openapi")] return self.meta_mut().finalizers.get_or_insert_with(Vec::new); - #[cfg(feature = "pb")] + #[cfg(all(not(feature = "openapi"), feature = "pb"))] return &mut self.meta_mut().finalizers; } fn managed_fields(&self) -> &[ManagedFieldsEntry] { #[cfg(feature = "openapi")] return self.meta().managed_fields.as_deref().unwrap_or_default(); - #[cfg(feature = "pb")] + #[cfg(all(not(feature = "openapi"), feature = "pb"))] return self.meta().managed_fields.as_ref(); } fn managed_fields_mut(&mut self) -> &mut Vec { #[cfg(feature = "openapi")] return self.meta_mut().managed_fields.get_or_insert_with(Vec::new); - #[cfg(feature = "pb")] + #[cfg(all(not(feature = "openapi"), feature = "pb"))] return &mut self.meta_mut().managed_fields; } } From ca5ea73c9e973f3e195f479e144409b7945277e7 Mon Sep 17 00:00:00 2001 From: clux Date: Mon, 14 Oct 2024 21:16:29 +0100 Subject: [PATCH 5/8] limit to openapi feature being there for now Signed-off-by: clux --- .github/workflows/ci.yml | 4 ++-- examples/Cargo.toml | 3 ++- examples/README.md | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 66e280efa..db997a91e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,10 +48,10 @@ jobs: run: cargo build - name: Build no-features - run: cargo build -p kube --no-default-features + run: cargo build -p kube --no-default-features --features=openapi if: matrix.os == 'ubuntu-latest' # only linux tests all feature combinations - name: Build no-tls - run: cargo build -p kube --no-default-features --features=client + run: cargo build -p kube --no-default-features --features=client,openapi if: matrix.os == 'ubuntu-latest' # only linux tests all feature combinations # Workspace unit tests with various feature sets diff --git a/examples/Cargo.toml b/examples/Cargo.toml index d00395fbf..a33f010f1 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -10,12 +10,13 @@ license.workspace = true release = false [features] -default = ["rustls-tls", "kubederive", "ws", "latest", "socks5", "runtime", "refresh"] +default = ["rustls-tls", "kubederive", "ws", "latest", "socks5", "runtime", "refresh", "openapi"] kubederive = ["kube/derive"] openssl-tls = ["kube/client", "kube/openssl-tls", "kube/unstable-client"] rustls-tls = ["kube/client", "kube/rustls-tls", "kube/unstable-client"] runtime = ["kube/runtime", "kube/unstable-runtime"] socks5 = ["kube/socks5"] +openapi = ["kube/openapi"] refresh = ["kube/oauth", "kube/oidc"] kubelet-debug = ["kube/kubelet-debug"] ws = ["kube/ws"] diff --git a/examples/README.md b/examples/README.md index 21fe1ef5c..ac68ff1c5 100644 --- a/examples/README.md +++ b/examples/README.md @@ -68,7 +68,7 @@ How deriving `CustomResource` works in practice, and how it interacts with the [ cargo run --example crd_api cargo run --example crd_derive cargo run --example crd_derive_schema -cargo run --example crd_derive_no_schema --no-default-features --features=openssl-tls,latest +cargo run --example crd_derive_no_schema --no-default-features --features=openssl-tls,openapi,latest cargo run --example cert_check # showcases partial typing with Resource derive ``` @@ -143,5 +143,5 @@ The `crd_reflector` will just await changes. You can run `kubectl apply -f crd-b Disable default features and enable `openssl-tls`: ```sh -cargo run --example pod_watcher --no-default-features --features=openssl-tls,latest,runtime +cargo run --example pod_watcher --no-default-features --features=openssl-tls,openapi,latest,runtime ``` From a88d865195863295b31def7196b240fbd66455a0 Mon Sep 17 00:00:00 2001 From: clux Date: Mon, 14 Oct 2024 21:25:55 +0100 Subject: [PATCH 6/8] remaining ci fixes Signed-off-by: clux --- .github/workflows/ci.yml | 14 +++----------- deny.toml | 4 ++++ e2e/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db997a91e..3b8c0bdcd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,7 +96,7 @@ jobs: # Run `cargo check` on our minimum supported Rust version runs-on: ubuntu-latest steps: - - uses: actions/checkout@main + - uses: actions/checkout@v4 - name: Find MSRV id: msrv run: | @@ -143,11 +143,7 @@ jobs: k8s: [v1.26, v1.30] steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 - with: - override: true - toolchain: stable - profile: minimal + - uses: dtolnay/rust-toolchain@stable # Smart caching for Rust projects. # Includes workaround for macos cache corruption. # - https://github.com/rust-lang/cargo/issues/8603 @@ -201,11 +197,7 @@ jobs: exit 1 fi - - uses: actions-rs/toolchain@v1 - with: - override: true - toolchain: stable - profile: minimal + - uses: dtolnay/rust-toolchain@stable # Smart caching for Rust projects. # Includes workaround for macos cache corruption. # - https://github.com/rust-lang/cargo/issues/8603 diff --git a/deny.toml b/deny.toml index 8c1aa1545..107739ff4 100644 --- a/deny.toml +++ b/deny.toml @@ -75,6 +75,10 @@ name = "base64" # newer via tower-http (we have latest) name = "bitflags" +[[bans.skip]] +# different versions deep done in prost vs aws-lc +name = "itertools" + [[bans.skip-tree]] name = "windows-sys" diff --git a/e2e/Cargo.toml b/e2e/Cargo.toml index 3fd7b0a09..dc7b94a7a 100644 --- a/e2e/Cargo.toml +++ b/e2e/Cargo.toml @@ -27,7 +27,7 @@ openssl = ["kube/openssl-tls"] anyhow.workspace = true tracing.workspace = true tracing-subscriber.workspace = true -kube = { path = "../kube", version = "^0.96.0", default-features = false, features = ["client", "runtime", "ws", "admission", "gzip"] } +kube = { path = "../kube", version = "^0.96.0", default-features = false, features = ["client", "runtime", "ws", "admission", "gzip", "openapi"] } k8s-openapi.workspace = true serde_json.workspace = true tokio = { workspace = true, features = ["full"] } From 827ffbcc8b6140e2190bc6d167350310c8480388 Mon Sep 17 00:00:00 2001 From: clux Date: Mon, 14 Oct 2024 21:55:51 +0100 Subject: [PATCH 7/8] make kube-core build with pb Signed-off-by: clux --- kube-core/src/gvk.rs | 1 + kube-core/src/k8s.rs | 2 ++ kube-core/src/lib.rs | 7 ++++--- kube-core/src/metadata.rs | 11 ++++++----- kube-core/src/object.rs | 26 +++++++++++++++++--------- kube-core/src/params.rs | 5 ++++- kube-core/src/resource.rs | 23 +++++++++++++++++++---- kube-core/src/subresource.rs | 3 +-- 8 files changed, 54 insertions(+), 24 deletions(-) diff --git a/kube-core/src/gvk.rs b/kube-core/src/gvk.rs index 683b2a7e7..4fd37fb93 100644 --- a/kube-core/src/gvk.rs +++ b/kube-core/src/gvk.rs @@ -50,6 +50,7 @@ impl TryFrom for GroupVersionKind { } } +#[cfg(feature = "openapi")] // does not work for pb, ownerref.api_version is optional impl From for GroupVersionKind { fn from(value: OwnerReference) -> Self { let (group, version) = match value.api_version.split_once("/") { diff --git a/kube-core/src/k8s.rs b/kube-core/src/k8s.rs index 0033ec3f7..43d325e4f 100644 --- a/kube-core/src/k8s.rs +++ b/kube-core/src/k8s.rs @@ -3,6 +3,7 @@ /// Re-export k8s-openapi types by default #[cfg(feature = "openapi")] pub use k8s_openapi::{ + api, api::apps::v1::{DaemonSet, Deployment, ReplicaSet, StatefulSet}, api::autoscaling::v1::{Scale, ScaleSpec, ScaleStatus}, api::core::v1::{ConfigMap, ObjectReference, Pod}, @@ -16,6 +17,7 @@ pub use k8s_openapi::{ /// Re-export k8s-pb types when only pb feature enabled #[cfg(all(not(feature = "openapi"), feature = "pb"))] pub use k8s_pb::{ + api, api::apps::v1::{DaemonSet, Deployment, ReplicaSet, StatefulSet}, api::autoscaling::v1::{Scale, ScaleSpec, ScaleStatus}, api::core::v1::{ConfigMap, ObjectReference, Pod}, diff --git a/kube-core/src/lib.rs b/kube-core/src/lib.rs index 8bdd0c0b2..8e800a53b 100644 --- a/kube-core/src/lib.rs +++ b/kube-core/src/lib.rs @@ -33,7 +33,7 @@ pub use gvk::{GroupVersion, GroupVersionKind, GroupVersionResource}; pub mod metadata; pub use metadata::{ListMeta, ObjectMeta, PartialObjectMeta, PartialObjectMetaExt, TypeMeta}; -pub mod labels; +#[cfg(feature = "openapi")] pub mod labels; #[cfg(feature = "kubelet-debug")] pub mod kubelet_debug; @@ -54,6 +54,7 @@ pub use resource::{ pub mod response; pub use response::Status; +#[cfg(feature = "openapi")] pub use labels::{Expression, ParseExpressionError, Selector, SelectorExt}; #[cfg_attr(docsrs, doc(cfg(feature = "schema")))] @@ -73,5 +74,5 @@ pub use error::ErrorResponse; mod version; pub use version::Version; -pub mod error_boundary; -pub use error_boundary::DeserializeGuard; +#[cfg(feature = "openapi")] pub mod error_boundary; +#[cfg(feature = "openapi")] pub use error_boundary::DeserializeGuard; diff --git a/kube-core/src/metadata.rs b/kube-core/src/metadata.rs index 33b587585..ba87a3414 100644 --- a/kube-core/src/metadata.rs +++ b/kube-core/src/metadata.rs @@ -59,17 +59,18 @@ impl TypeMeta { /// schema without knowing the details of the version. /// /// See the [`PartialObjectMetaExt`] trait for how to construct one safely. -#[derive(Deserialize, Serialize, Clone, Default, Debug)] -#[serde(rename_all = "camelCase")] +#[derive(Clone, Default, Debug)] +#[cfg_attr(feature = "openapi", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "openapi", serde(rename_all = "camelCase"))] pub struct PartialObjectMeta { /// The type fields, not always present - #[serde(flatten, default)] + #[cfg_attr(feature = "openapi", serde(flatten, default))] pub types: Option, /// Standard object's metadata - #[serde(default)] + #[cfg_attr(feature = "openapi", serde(default))] pub metadata: ObjectMeta, /// Type information for static dispatch - #[serde(skip, default)] + #[cfg_attr(feature = "openapi", serde(skip, default))] pub _phantom: PhantomData, } diff --git a/kube-core/src/object.rs b/kube-core/src/object.rs index 1e81a947b..3f59146cb 100644 --- a/kube-core/src/object.rs +++ b/kube-core/src/object.rs @@ -16,25 +16,32 @@ use std::borrow::Cow; /// and is generally produced from list/watch/delete collection queries on an [`Resource`](super::Resource). /// /// This is almost equivalent to [`k8s_openapi::List`](k8s_openapi::List), but iterable. -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "openapi", derive(serde::Serialize, serde::Deserialize))] pub struct ObjectList where T: Clone, { /// The type fields, always present - #[serde(flatten, deserialize_with = "deserialize_v1_list_as_default")] + #[cfg_attr( + feature = "openapi", + serde(flatten, deserialize_with = "deserialize_v1_list_as_default") + )] pub types: TypeMeta, /// ListMeta - only really used for its `resourceVersion` /// /// See [ListMeta](k8s_openapi::apimachinery::pkg::apis::meta::v1::ListMeta) - #[serde(default)] + #[cfg_attr(feature = "openapi", serde(default))] pub metadata: ListMeta, /// The items we are actually interested in. In practice; `T := Resource`. - #[serde( - deserialize_with = "deserialize_null_as_default", - bound(deserialize = "Vec: Deserialize<'de>") + #[cfg_attr( + feature = "openapi", + serde( + deserialize_with = "deserialize_null_as_default", + bound(deserialize = "Vec: Deserialize<'de>") + ) )] pub items: Vec, } @@ -182,14 +189,15 @@ pub trait HasStatus { /// /// This can be used to tie existing resources to smaller, local struct variants to optimize for memory use. /// E.g. if you are only interested in a few fields, but you store tons of them in memory with reflectors. -#[derive(Deserialize, Serialize, Clone, Debug)] +#[derive(Clone, Debug)] +#[cfg_attr(feature = "openapi", derive(serde::Serialize, serde::Deserialize))] pub struct Object where P: Clone, U: Clone, { /// The type fields, not always present - #[serde(flatten, default)] + #[cfg_attr(feature = "openapi", serde(flatten, default))] pub types: Option, /// Resource metadata @@ -207,7 +215,7 @@ where /// /// This publishes the state of the Resource as observed by the controller. /// Use `U = NotUsed` when a status does not exist. - #[serde(default, skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "openapi", serde(default, skip_serializing_if = "Option::is_none"))] pub status: Option, } diff --git a/kube-core/src/params.rs b/kube-core/src/params.rs index fa508dc4e..4f430c447 100644 --- a/kube-core/src/params.rs +++ b/kube-core/src/params.rs @@ -1,5 +1,6 @@ //! A port of request parameter *Optionals from apimachinery/types.go -use crate::{request::Error, Selector}; +use crate::request::Error; +#[cfg(feature = "openapi")] use crate::Selector; use serde::Serialize; /// Controls how the resource version parameter is applied for list calls @@ -186,6 +187,7 @@ impl ListParams { /// # Ok::<(), ParseExpressionError>(()) ///``` #[must_use] + #[cfg(feature = "openapi")] pub fn labels_from(mut self, selector: &Selector) -> Self { self.label_selector = Some(selector.to_string()); self @@ -473,6 +475,7 @@ impl WatchParams { /// let wp = WatchParams::default().labels_from(&selector); /// # Ok::<(), ParseExpressionError>(()) ///``` + #[cfg(feature = "openapi")] #[must_use] pub fn labels_from(mut self, selector: &Selector) -> Self { self.label_selector = Some(selector.to_string()); diff --git a/kube-core/src/resource.rs b/kube-core/src/resource.rs index f98ca0894..3976eb688 100644 --- a/kube-core/src/resource.rs +++ b/kube-core/src/resource.rs @@ -141,13 +141,22 @@ pub trait Resource { /// ``` fn owner_ref(&self, dt: &Self::DynamicType) -> Option { let meta = self.meta(); - Some(OwnerReference { + #[cfg(feature = "openapi")] + return Some(OwnerReference { api_version: Self::api_version(dt).to_string(), kind: Self::kind(dt).to_string(), name: meta.name.clone()?, uid: meta.uid.clone()?, ..OwnerReference::default() - }) + }); + #[cfg(all(not(feature = "openapi"), feature = "pb"))] + return Some(OwnerReference { + api_version: Some(Self::api_version(dt).to_string()), + kind: Some(Self::kind(dt).to_string()), + name: meta.name.clone(), + uid: meta.uid.clone(), + ..OwnerReference::default() + }); } } @@ -193,11 +202,17 @@ where } fn meta(&self) -> &ObjectMeta { - self.metadata() + #[cfg(feature = "openapi")] + return self.metadata(); + #[cfg(all(not(feature = "openapi"), feature = "pb"))] + return self.metadata().unwrap(); // not great } fn meta_mut(&mut self) -> &mut ObjectMeta { - self.metadata_mut() + #[cfg(feature = "openapi")] + return self.metadata_mut(); + #[cfg(all(not(feature = "openapi"), feature = "pb"))] + return self.metadata_mut().unwrap(); } } diff --git a/kube-core/src/subresource.rs b/kube-core/src/subresource.rs index b4ad62c6e..89088bdfd 100644 --- a/kube-core/src/subresource.rs +++ b/kube-core/src/subresource.rs @@ -412,10 +412,9 @@ impl Request { /// Cheap sanity check to ensure type maps work as expected #[cfg(test)] mod test { - use crate::{request::Request, resource::Resource}; + use crate::{k8s::api as k8s, request::Request, resource::Resource}; use chrono::{DateTime, TimeZone, Utc}; use k8s::core::v1 as corev1; - use k8s_openapi::api as k8s; use crate::subresource::LogParams; From c71e5bc21c086503a6aa4d2a9f1053e26ccaa88f Mon Sep 17 00:00:00 2001 From: clux Date: Mon, 14 Oct 2024 23:10:51 +0100 Subject: [PATCH 8/8] client is harder... Signed-off-by: clux --- Cargo.toml | 2 +- kube-client/src/api/mod.rs | 13 +++++----- kube-client/src/api/subresource.rs | 34 +++++++++++++-------------- kube-client/src/api/util/csr.rs | 7 +++--- kube-client/src/api/util/mod.rs | 13 ++++++---- kube-client/src/client/mod.rs | 8 ++++--- kube-client/src/discovery/apigroup.rs | 2 +- kube-client/src/discovery/parse.rs | 2 +- kube-client/src/lib.rs | 14 +++++++---- kube-core/src/k8s.rs | 2 ++ 10 files changed, 54 insertions(+), 43 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6c32747ba..45f828d3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,7 +61,7 @@ json-patch = "3" jsonptr = "0.6" jsonpath-rust = "0.5.0" k8s-openapi = { version = "0.23.0", default-features = false } -k8s-pb = "0.6.0" +k8s-pb = "0.6.1" #k8s-pb = { path = "../k8s-pb/k8s-pb" } openssl = "0.10.36" parking_lot = "0.12.0" diff --git a/kube-client/src/api/mod.rs b/kube-client/src/api/mod.rs index 020d95337..3bc9b36bb 100644 --- a/kube-client/src/api/mod.rs +++ b/kube-client/src/api/mod.rs @@ -1,6 +1,5 @@ //! API helpers for structured interaction with the Kubernetes API - -mod core_methods; +#[cfg(feature = "openapi")] mod core_methods; #[cfg(feature = "ws")] mod remote_command; use std::fmt::Debug; @@ -8,13 +7,14 @@ use std::fmt::Debug; #[cfg(feature = "ws")] mod portforward; #[cfg(feature = "ws")] pub use portforward::Portforwarder; -mod subresource; -#[cfg(feature = "ws")] +#[cfg(feature = "openapi")] mod subresource; +#[cfg(all(feature = "ws", feature = "openapi"))] #[cfg_attr(docsrs, doc(cfg(feature = "ws")))] pub use subresource::{Attach, AttachParams, Ephemeral, Execute, Portforward}; +#[cfg(feature = "openapi")] pub use subresource::{Evict, EvictParams, Log, LogParams, ScaleSpec, ScaleStatus}; -mod util; +#[cfg(feature = "openapi")] mod util; pub mod entry; @@ -247,8 +247,7 @@ impl Debug for Api { /// Sanity test on scope restrictions #[cfg(test)] mod test { - use crate::{client::Body, Api, Client}; - use k8s_openapi::api::core::v1 as corev1; + use crate::{client::Body, core::k8s::api::core::v1 as corev1, Api, Client}; use http::{Request, Response}; use tower_test::mock; diff --git a/kube-client/src/api/subresource.rs b/kube-client/src/api/subresource.rs index c62681365..c25990608 100644 --- a/kube-client/src/api/subresource.rs +++ b/kube-client/src/api/subresource.rs @@ -14,7 +14,7 @@ pub use kube_core::subresource::{EvictParams, LogParams}; #[cfg_attr(docsrs, doc(cfg(feature = "ws")))] pub use kube_core::subresource::AttachParams; -pub use k8s_openapi::api::autoscaling::v1::{Scale, ScaleSpec, ScaleStatus}; +pub use kube_core::k8s::api::autoscaling::v1::{Scale, ScaleSpec, ScaleStatus}; #[cfg(feature = "ws")] use crate::api::portforward::Portforwarder; #[cfg(feature = "ws")] use crate::api::remote_command::AttachedProcess; @@ -136,7 +136,7 @@ where /// See [`Api::get_ephemeral_containers`] et al. pub trait Ephemeral {} -impl Ephemeral for k8s_openapi::api::core::v1::Pod {} +impl Ephemeral for kube_core::k8s::api::core::v1::Pod {} impl Api where @@ -160,7 +160,7 @@ where /// Example of using `replace_ephemeral_containers`: /// /// ```no_run - /// use k8s_openapi::api::core::v1::Pod; + /// use kube_core::k8s::api::core::v1::Pod; /// use kube::{Api, api::PostParams}; /// # async fn wrapper() -> Result<(), Box> { /// # let client = kube::Client::try_default().await?; @@ -229,7 +229,7 @@ where /// /// ```no_run /// use kube::api::{Api, PatchParams, Patch}; - /// use k8s_openapi::api::core::v1::Pod; + /// use kube_core::k8s::api::core::v1::Pod; /// # async fn wrapper() -> Result<(), Box> { /// # let client = kube::Client::try_default().await?; /// let pods: Api = Api::namespaced(client, "apps"); @@ -310,7 +310,7 @@ where /// /// ```no_run /// use kube::api::{Api, PatchParams, Patch}; - /// use k8s_openapi::api::batch::v1::Job; + /// use kube_core::k8s::api::batch::v1::Job; /// # async fn wrapper() -> Result<(), Box> { /// # let client = kube::Client::try_default().await?; /// let jobs: Api = Api::namespaced(client, "apps"); @@ -347,7 +347,7 @@ where /// /// ```no_run /// use kube::api::{Api, PostParams}; - /// use k8s_openapi::api::batch::v1::{Job, JobStatus}; + /// use kube_core::k8s::api::batch::v1::{Job, JobStatus}; /// # async fn wrapper() -> Result<(), Box> { /// # let client = kube::Client::try_default().await?; /// let jobs: Api = Api::namespaced(client, "apps"); @@ -375,7 +375,7 @@ where #[test] fn log_path() { use crate::api::{Request, Resource}; - use k8s_openapi::api::core::v1 as corev1; + use kube_core::k8s::api::core::v1 as corev1; let lp = LogParams { container: Some("blah".into()), ..LogParams::default() @@ -390,7 +390,7 @@ fn log_path() { /// See [`Api::logs`] and [`Api::log_stream`] for usage. pub trait Log {} -impl Log for k8s_openapi::api::core::v1::Pod {} +impl Log for kube_core::k8s::api::core::v1::Pod {} impl Api where @@ -412,7 +412,7 @@ where /// /// ```no_run /// # async fn wrapper() -> Result<(), Box> { - /// # use k8s_openapi::api::core::v1::Pod; + /// # use kube_core::k8s::api::core::v1::Pod; /// # use kube::{api::{Api, LogParams}, Client}; /// # let client: Client = todo!(); /// use futures::{AsyncBufReadExt, TryStreamExt}; @@ -442,7 +442,7 @@ where #[test] fn evict_path() { use crate::api::{Request, Resource}; - use k8s_openapi::api::core::v1 as corev1; + use kube_core::k8s::api::core::v1 as corev1; let ep = EvictParams::default(); let url = corev1::Pod::url_path(&(), Some("ns")); let req = Request::new(url).evict("foo", &ep).unwrap(); @@ -454,7 +454,7 @@ fn evict_path() { /// See [`Api::evic`] for usage pub trait Evict {} -impl Evict for k8s_openapi::api::core::v1::Pod {} +impl Evict for kube_core::k8s::api::core::v1::Pod {} impl Api where @@ -476,7 +476,7 @@ where #[test] fn attach_path() { use crate::api::{Request, Resource}; - use k8s_openapi::api::core::v1 as corev1; + use kube_core::k8s::api::core::v1 as corev1; let ap = AttachParams { container: Some("blah".into()), ..AttachParams::default() @@ -498,7 +498,7 @@ pub trait Attach {} #[cfg(feature = "ws")] #[cfg_attr(docsrs, doc(cfg(feature = "ws")))] -impl Attach for k8s_openapi::api::core::v1::Pod {} +impl Attach for kube_core::k8s::api::core::v1::Pod {} #[cfg(feature = "ws")] #[cfg_attr(docsrs, doc(cfg(feature = "ws")))] @@ -522,7 +522,7 @@ where #[test] fn exec_path() { use crate::api::{Request, Resource}; - use k8s_openapi::api::core::v1 as corev1; + use kube_core::k8s::api::core::v1 as corev1; let ap = AttachParams { container: Some("blah".into()), ..AttachParams::default() @@ -546,7 +546,7 @@ pub trait Execute {} #[cfg(feature = "ws")] #[cfg_attr(docsrs, doc(cfg(feature = "ws")))] -impl Execute for k8s_openapi::api::core::v1::Pod {} +impl Execute for kube_core::k8s::api::core::v1::Pod {} #[cfg(feature = "ws")] #[cfg_attr(docsrs, doc(cfg(feature = "ws")))] @@ -577,7 +577,7 @@ where #[test] fn portforward_path() { use crate::api::{Request, Resource}; - use k8s_openapi::api::core::v1 as corev1; + use kube_core::k8s::api::core::v1 as corev1; let url = corev1::Pod::url_path(&(), Some("ns")); let req = Request::new(url).portforward("foo", &[80, 1234]).unwrap(); assert_eq!( @@ -593,7 +593,7 @@ fn portforward_path() { pub trait Portforward {} #[cfg(feature = "ws")] -impl Portforward for k8s_openapi::api::core::v1::Pod {} +impl Portforward for kube_core::k8s::api::core::v1::Pod {} #[cfg(feature = "ws")] impl Api diff --git a/kube-client/src/api/util/csr.rs b/kube-client/src/api/util/csr.rs index 279e3946e..2885c8b88 100644 --- a/kube-client/src/api/util/csr.rs +++ b/kube-client/src/api/util/csr.rs @@ -1,7 +1,8 @@ use crate::{api::Api, Error, Result}; -use k8s_openapi::api::certificates::v1::CertificateSigningRequest; -use kube_core::params::{Patch, PatchParams}; - +use kube_core::{ + k8s::api::certificates::v1::CertificateSigningRequest, + params::{Patch, PatchParams}, +}; impl Api { /// Partially update approval of the specified CertificateSigningRequest. diff --git a/kube-client/src/api/util/mod.rs b/kube-client/src/api/util/mod.rs index 06923a0d6..9d86ed56b 100644 --- a/kube-client/src/api/util/mod.rs +++ b/kube-client/src/api/util/mod.rs @@ -2,11 +2,14 @@ use crate::{ api::{Api, Resource}, Error, Result, }; -use k8s_openapi::api::{ - authentication::v1::TokenRequest, - core::v1::{Node, ServiceAccount}, +use kube_core::{ + k8s::api::{ + authentication::v1::TokenRequest, + core::v1::{Node, ServiceAccount}, + }, + params::PostParams, + util::Restart, }; -use kube_core::{params::PostParams, util::Restart}; use serde::de::DeserializeOwned; mod csr; @@ -66,7 +69,7 @@ mod test { api::{Api, DeleteParams, ListParams, PostParams}, Client, }; - use k8s_openapi::api::{ + use kube_core::k8s::api::{ authentication::v1::{TokenRequest, TokenRequestSpec, TokenReview, TokenReviewSpec}, core::v1::{Node, ServiceAccount}, }; diff --git a/kube-client/src/client/mod.rs b/kube-client/src/client/mod.rs index cd6c9ac9e..6484dd77b 100644 --- a/kube-client/src/client/mod.rs +++ b/kube-client/src/client/mod.rs @@ -7,12 +7,13 @@ //! //! The [`Client`] can also be used with [`Discovery`](crate::Discovery) to dynamically //! retrieve the resources served by the kubernetes API. +use apimachinery::pkg::apis::meta::v1 as k8s_meta_v1; use either::{Either, Left, Right}; use futures::{future::BoxFuture, AsyncBufRead, StreamExt, TryStream, TryStreamExt}; use http::{self, Request, Response}; use http_body_util::BodyExt; #[cfg(feature = "ws")] use hyper_util::rt::TokioIo; -use k8s_openapi::apimachinery::pkg::apis::meta::v1 as k8s_meta_v1; +use kube_core::k8s::apimachinery; pub use kube_core::response::Status; use serde::de::DeserializeOwned; use serde_json::{self, Value}; @@ -372,7 +373,8 @@ impl Client { /// The following methods might be deprecated to avoid confusion between similarly named types within `discovery`. impl Client { /// Returns apiserver version. - pub async fn apiserver_version(&self) -> Result { + #[cfg(feature = "openapi")] // Info struct does not exist for pbs + pub async fn apiserver_version(&self) -> Result { self.request( Request::builder() .uri("/version") @@ -497,8 +499,8 @@ mod tests { use crate::{client::Body, Api, Client}; + use crate::core::k8s::api::core::v1::Pod; use http::{Request, Response}; - use k8s_openapi::api::core::v1::Pod; use tower_test::mock; #[tokio::test] diff --git a/kube-client/src/discovery/apigroup.rs b/kube-client/src/discovery/apigroup.rs index d7a7557a3..76f8b1606 100644 --- a/kube-client/src/discovery/apigroup.rs +++ b/kube-client/src/discovery/apigroup.rs @@ -1,9 +1,9 @@ use super::parse::{self, GroupVersionData}; use crate::{error::DiscoveryError, Client, Error, Result}; -use k8s_openapi::apimachinery::pkg::apis::meta::v1::{APIGroup, APIVersions}; pub use kube_core::discovery::{ApiCapabilities, ApiResource}; use kube_core::{ gvk::{GroupVersion, GroupVersionKind, ParseGroupVersionError}, + k8s::apimachinery::pkg::apis::meta::v1::{APIGroup, APIVersions}, Version, }; use std::{cmp::Reverse, collections::HashMap, iter::Iterator}; diff --git a/kube-client/src/discovery/parse.rs b/kube-client/src/discovery/parse.rs index 39f0ce58a..36898a008 100644 --- a/kube-client/src/discovery/parse.rs +++ b/kube-client/src/discovery/parse.rs @@ -1,9 +1,9 @@ //! Abstractions on top of k8s_openapi::apimachinery::pkg::apis::meta::v1 use crate::{error::DiscoveryError, Error, Result}; -use k8s_openapi::apimachinery::pkg::apis::meta::v1::{APIResource, APIResourceList}; use kube_core::{ discovery::{ApiCapabilities, ApiResource, Scope}, gvk::{GroupVersion, ParseGroupVersionError}, + k8s::apimachinery::pkg::apis::meta::v1::{APIResource, APIResourceList}, }; /// Creates an `ApiResource` from a `meta::v1::APIResource` instance + its groupversion. diff --git a/kube-client/src/lib.rs b/kube-client/src/lib.rs index f32875c0e..4886d63f4 100644 --- a/kube-client/src/lib.rs +++ b/kube-client/src/lib.rs @@ -119,7 +119,8 @@ cfg_error! { pub type Result = std::result::Result; } -pub use crate::core::{CustomResourceExt, Resource, ResourceExt}; +#[cfg(feature = "openapi")] pub use crate::core::CustomResourceExt; +pub use crate::core::{Resource, ResourceExt}; /// Re-exports from kube_core pub use kube_core as core; @@ -136,8 +137,8 @@ mod test { }; use futures::{AsyncBufRead, AsyncBufReadExt, StreamExt, TryStreamExt}; use hyper::Uri; - use k8s_openapi::api::core::v1::{EphemeralContainer, Pod, PodSpec}; use kube_core::{ + k8s::api::core::v1::{EphemeralContainer, Pod, PodSpec}, params::{DeleteParams, Patch, PatchParams, PostParams, WatchParams}, response::StatusSummary, }; @@ -558,9 +559,12 @@ mod test { #[tokio::test] #[ignore = "needs cluster (will create a CertificateSigningRequest)"] async fn csr_can_be_approved() -> Result<(), Box> { - use crate::api::PostParams; - use k8s_openapi::api::certificates::v1::{ - CertificateSigningRequest, CertificateSigningRequestCondition, CertificateSigningRequestStatus, + use crate::{ + api::PostParams, + core::k8s::api::certificates::v1::{ + CertificateSigningRequest, CertificateSigningRequestCondition, + CertificateSigningRequestStatus, + }, }; let csr_name = "fake"; diff --git a/kube-core/src/k8s.rs b/kube-core/src/k8s.rs index 43d325e4f..2afabac11 100644 --- a/kube-core/src/k8s.rs +++ b/kube-core/src/k8s.rs @@ -8,6 +8,7 @@ pub use k8s_openapi::{ api::autoscaling::v1::{Scale, ScaleSpec, ScaleStatus}, api::core::v1::{ConfigMap, ObjectReference, Pod}, apiextensions_apiserver::pkg::apis::apiextensions, + apimachinery, apimachinery::pkg::apis::meta::v1::{ LabelSelector, LabelSelectorRequirement, ListMeta, ManagedFieldsEntry, ObjectMeta, OwnerReference, Time, @@ -22,6 +23,7 @@ pub use k8s_pb::{ api::autoscaling::v1::{Scale, ScaleSpec, ScaleStatus}, api::core::v1::{ConfigMap, ObjectReference, Pod}, apiextensions_apiserver::pkg::apis::apiextensions, + apimachinery, apimachinery::pkg::apis::meta::v1::{ LabelSelector, LabelSelectorRequirement, ListMeta, ManagedFieldsEntry, ObjectMeta, OwnerReference, Time,