Skip to content

Commit

Permalink
Doc tweaks and 2 missing impls pre release (#1573)
Browse files Browse the repository at this point in the history
* Doc tweaks and 2 missing impls pre release

Mostly doc stuff that was inconsistent or looked unprofessional.

In particular, the lib re-export ones now seem to concatenate the docstrings,
so have made these cleaner on both end.

Cleaned up the cert check example a little bit to more showcase the problem.

Missing impls:

- Derive + Clone on marker `Namespace` and `Cluster` for unstable client_ext

Signed-off-by: clux <sszynrae@gmail.com>

* redundant word

Signed-off-by: clux <sszynrae@gmail.com>

* more missing links

Signed-off-by: clux <sszynrae@gmail.com>

---------

Signed-off-by: clux <sszynrae@gmail.com>
  • Loading branch information
clux authored Sep 9, 2024
1 parent 33a01c2 commit 52e4392
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 64 deletions.
5 changes: 2 additions & 3 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,10 @@ 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
# collect kube-root configmaps from each namespace, with strictly typed serialization on ca.crt key
cargo run --example cert_check
cargo run --example cert_check # showcases partial typing with Resource derive
```

The last one opts out from the default `schema` feature from `kube-derive` (and thus the need for you to derive/impl `JsonSchema`).
The `no_schema` one opts out from the default `schema` feature from `kube-derive` (and thus the need for you to derive/impl `JsonSchema`).

**However**: without the `schema` feature, it's left **up to you to fill in a valid openapi v3 schema**, as schemas are **required** for [v1::CustomResourceDefinitions](https://docs.rs/k8s-openapi/0.10.0/k8s_openapi/apiextensions_apiserver/pkg/apis/apiextensions/v1/struct.CustomResourceDefinition.html), and the generated crd will be rejected by the apiserver if it's missing. As the last example shows, you can do this directly without `schemars`.

Expand Down
70 changes: 23 additions & 47 deletions examples/cert_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,34 @@ use k8s_openapi::{
use kube::{
api::ObjectMeta,
client::scope::{Cluster, Namespace},
Client, Resource, ResourceExt,
Client, Resource,
};
use serde::{Deserialize, Serialize};
use tracing::*;

use thiserror::Error;

#[derive(Debug, Error)]
enum Error {
#[error("Failed to open client: {0}")]
ClientSetup(#[source] kube::Error),
#[error("Failed to list namespaces: {0}")]
NamespaceList(#[source] kube::Error),
#[error("Failed to get ConfigMap: {0}")]
FetchFailed(#[from] kube::Error),
#[error("Expected certificate key in ConfigMap: {0}")]
MissingKey(#[from] serde_json::Error),
}

// Variant of ConfigMap that only accepts ConfigMaps with a CA certificate
// to demonstrate manual implementation
#[derive(Serialize, Deserialize, Debug, Clone)]
struct CaConfigMapManual {
metadata: ObjectMeta,
data: CaConfigMapData,
}

// Our own way of representing data - partially typed in 2 ways
// For a ConfigMap variant that only accepts CA certificates
#[derive(Serialize, Deserialize, Debug, Clone)]
struct CaConfigMapData {
#[serde(rename = "ca.crt")]
ca_crt: String,
}

// Variant of ConfigMap that only accepts ConfigMaps with a CA certificate
// with inherited resource implementation
// Method 1 :: inherit resource implementation from k8s_openapi's ConfigMap
#[derive(Resource, Serialize, Deserialize, Debug, Clone)]
#[resource(inherit = ConfigMap)]
struct CaConfigMap {
metadata: ObjectMeta,
data: CaConfigMapData,
}

// Display of a manual implementation
// Method 2 :: manual Resource implementation
#[derive(Serialize, Deserialize, Debug, Clone)]
struct CaConfigMapManual {
metadata: ObjectMeta,
data: CaConfigMapData,
}
// Method 2 :: manual Resource implementation
impl Resource for CaConfigMapManual {
type DynamicType = ();
type Scope = NamespaceResourceScope;
Expand Down Expand Up @@ -79,33 +64,24 @@ impl Resource for CaConfigMapManual {
}
}


#[tokio::main]
async fn main() -> Result<(), Error> {
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt::init();

let client = Client::try_default().await.map_err(Error::ClientSetup)?;
let namespaces = client
.list::<Ns>(&Default::default(), &Cluster)
.await
.map_err(Error::NamespaceList)?;
let client = Client::try_default().await?;
let namespaces = client.list::<Ns>(&Default::default(), &Cluster).await?;
let kube_root = "kube-root-ca.crt";

for ns in namespaces {
let ns = Namespace::try_from(&ns)?;
// Equivalent ways to GET using different structs and different Resource impls, with added field validation on top.
let _ca: ConfigMap = client
.get("kube-root-ca.crt", &Namespace::from(ns.name_any()))
.await?;
let _ca: CaConfigMapManual = client
.get("kube-root-ca.crt", &Namespace::from(ns.name_any()))
.await?;
let ca: CaConfigMap = client
.get("kube-root-ca.crt", &Namespace::from(ns.name_any()))
.await?;
info!(
"Found correct root ca config map in {}: {}",
ns.name_any(),
ca.name_any()
);
let ca1: ConfigMap = client.get(kube_root, &ns).await?;
let ca2: CaConfigMapManual = client.get(kube_root, &ns).await?;
let ca3: CaConfigMap = client.get(kube_root, &ns).await?;
info!("Found {kube_root} in {ns:?} with all 3 methods");
debug!("ca1: {ca1:?}");
debug!("ca2: {ca2:?}");
debug!("ca3: {ca3:?}");
}

Ok(())
Expand Down
2 changes: 2 additions & 0 deletions kube-client/src/client/client_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ pub trait ObjectUrl<K> {
}

/// Marker type for cluster level queries
#[derive(Debug, Clone)]
pub struct Cluster;
/// Namespace newtype for namespace level queries
///
/// You can create this directly, or convert `From` a `String` / `&str`, or `TryFrom` an `k8s_openapi::api::core::v1::Namespace`
#[derive(Debug, Clone)]
pub struct Namespace(String);

/// Referenced object name resolution
Expand Down
2 changes: 1 addition & 1 deletion kube-client/src/client/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! A basic API client for interacting with the Kubernetes API
//! API client for interacting with the Kubernetes API
//!
//! The [`Client`] uses standard kube error handling.
//!
Expand Down
5 changes: 4 additions & 1 deletion kube-client/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ pub enum LoadDataError {
NoBase64DataOrFile,
}

/// Configuration object detailing things like cluster URL, default namespace, root certificates, and timeouts.
/// Configuration object for accessing a Kuernetes cluster
///
/// The configurable parameters for connecting like cluster URL, default namespace, root certificates, and timeouts.
/// Normally created implicitly through [`Config::infer`] or [`Client::try_default`](crate::Client::try_default).
///
/// # Usage
/// Construct a [`Config`] instance by using one of the many constructors.
Expand Down
2 changes: 1 addition & 1 deletion kube-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Crate with types and traits necessary for interacting with the Kubernetes API
//! Types and traits necessary for interacting with the Kubernetes API
//!
//! This crate provides the minimal apimachinery necessary to make requests to the kubernetes API.
//!
Expand Down
13 changes: 9 additions & 4 deletions kube-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,13 +312,13 @@ pub fn derive_custom_resource(input: proc_macro::TokenStream) -> proc_macro::Tok

/// A custom derive for inheriting Resource impl for the type.
///
/// This will generate a [`kube::Resource`] trait implementation, which inherits the specified
/// resources trait implementation.
/// This will generate a [`kube::Resource`] trait implementation,
/// inheriting from a specified resource trait implementation.
///
/// Such implementation allows to add strict typing to some typical resources like `Secret` or `ConfigMap`,
/// This allows strict typing to some typical resources like `Secret` or `ConfigMap`,
/// in cases when implementing CRD is not desirable or it does not fit the use-case.
///
/// This object can be used with [`kube::Api`].
/// Once derived, the type can be used with [`kube::Api`].
///
/// # Example
///
Expand Down Expand Up @@ -351,6 +351,11 @@ pub fn derive_custom_resource(input: proc_macro::TokenStream) -> proc_macro::Tok
/// ```
/// // impl kube::Resource for FooMap { .. }
/// ```
/// [`kube`]: https://docs.rs/kube
/// [`kube::Api`]: https://docs.rs/kube/*/kube/struct.Api.html
/// [`kube::Resource`]: https://docs.rs/kube/*/kube/trait.Resource.html
/// [`kube::core::ApiResource`]: https://docs.rs/kube/*/kube/core/struct.ApiResource.html
/// [`kube::CustomResourceExt`]: https://docs.rs/kube/*/kube/trait.CustomResourceExt.html
#[proc_macro_derive(Resource, attributes(resource))]
pub fn derive_resource(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
resource::derive(proc_macro2::TokenStream::from(input)).into()
Expand Down
10 changes: 3 additions & 7 deletions kube/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//! - [`client`] with the Kubernetes [`Client`] and its layers
//! - [`config`] for cluster [`Config`]
//! - [`api`] with the generic Kubernetes [`Api`]
//! - [`derive`](kube_derive) with the [`CustomResource`] derive for building controllers types
//! - [`derive`](kube_derive) with the [`CustomResource`] / [`Resource`](kube_derive::Resource) derive for building controllers types
//! - [`runtime`] with a [`Controller`](crate::runtime::Controller) / [`watcher`](crate::runtime::watcher()) / [`reflector`](crate::runtime::reflector::reflector) / [`Store`](crate::runtime::reflector::Store)
//! - [`core`] with generics from `apimachinery`
//!
Expand Down Expand Up @@ -160,7 +160,6 @@ cfg_error! {
pub type Result<T, E = Error> = std::result::Result<T, E>;
}

/// Re-exports from [`kube-derive`](kube_derive)
#[cfg(feature = "derive")]
#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
pub use kube_derive::CustomResource;
Expand All @@ -169,24 +168,21 @@ pub use kube_derive::CustomResource;
#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
pub use kube_derive::Resource;

/// Re-exports from `kube-runtime`
#[cfg(feature = "runtime")]
#[cfg_attr(docsrs, doc(cfg(feature = "runtime")))]
#[doc(inline)]
pub use kube_runtime as runtime;

pub use crate::core::{CustomResourceExt, Resource, ResourceExt};
/// Re-exports from `kube_core`
#[doc(inline)]
pub use kube_core as core;
#[doc(inline)] pub use kube_core as core;

// Mock tests for the runtime
#[cfg(test)]
#[cfg(all(feature = "derive", feature = "runtime"))]
mod mock_tests;

pub mod prelude {
//! A "prelude" for kube client crate. Reduces the number of duplicated imports.
//! A prelude for kube. Reduces the number of duplicated imports.
//!
//! This prelude is similar to the standard library's prelude in that you'll
//! almost always want to import its entire contents, but unlike the
Expand Down

0 comments on commit 52e4392

Please sign in to comment.