Skip to content

Commit

Permalink
Merge pull request #686 from kazk/refine-errors
Browse files Browse the repository at this point in the history
  • Loading branch information
kazk authored Nov 1, 2021
2 parents e9eec90 + 567e472 commit 120d000
Show file tree
Hide file tree
Showing 38 changed files with 536 additions and 430 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ UNRELEASED
===================
* see https://github.com/kube-rs/kube-rs/compare/0.63.2...master

* BREAKING: The following breaking changes were made as a part of an effort to refine errors (#688).
- Removed `kube::core::Error` and `kube::core::Result`. `kube::core::Error` was replaced by more specific errors as described below.
- Replaced `kube::core::Error::InvalidGroupVersion` with `kube::core::gvk::ParseGroupVersionError`.
- Changed the error returned from `kube::core::admission::AdmissionRequest::with_patch` to `kube::core::admission::SerializePatchError` (was `kube::core::Error::SerdeError`).
- Changed the error associated with `TryInto<AdmissionRequest<T>` to `kube::core::admission::ConvertAdmissionReviewError` (was `kube::core::Error::RequestValidation`).
- Changed the error returned from methods of `kube::core::Request` to `kube::core::request::Error` (was `kube::core::Error`). `kube::core::request::Error` represents possible errors when building an HTTP request. The removed `kube::core::Error` had `RequestValidation(String)`, `SerdeError(serde_json::Error)`, and `HttpError(http::Error)` variants. They are now `Validation(String)`, `SerializeBody(serde_json::Error)`, and `BuildRequest(http::Error)` respectively in `kube::core::request::Error`.
- Replaced `kube::Error::RequestValidation(String)` variant with `kube::Error::BuildRequest(kube::core::request::Error)`. This variant includes possible errors when building an HTTP request as described above, and contains errors that was previously grouped under `kube::Error::SerdeError` and `kube::Error::HttpError`.
- Removed `impl From<T> for kube::Error` for the following types: `std::io::Error`, `hyper::Error`, `tower::BoxError`, `std::string::FromUtf8Error`, `http::Error`, `http::uri::InvalidUri`, `serde_json::Error`, `openssl::error::ErrorStack`, `kube::core::Error`, `kube::error::ConfigError`, `kube::error::DisoveryError`, `kube::error::OAuthError`.
- Changed variants of error enums in `kube::runtime`. Replaced `snafu` with `thiserror`.

0.63.2 / 2021-10-28
===================
* `kube::runtime::events`: fix build and hide module on kubernetes < 1.19 (events/v1 missing there) - [#685](https://github.com/kube-rs/kube-rs/issues/685)
Expand Down
2 changes: 1 addition & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ serde_json = "1.0.68"
serde_yaml = "0.8.21"
tokio = { version = "1.12.0", features = ["full"] }
color-eyre = "0.5.10"
snafu = { version = "0.6.10", features = ["futures"] }
# Some Api::delete methods use Either
either = "1.6.1"
schemars = "0.8.6"
Expand All @@ -54,6 +53,7 @@ json-patch = "0.2.6"
tower = { version = "0.4.6" }
tower-http = { version = "0.1.0", features = ["trace", "decompression-gzip"] }
hyper = { version = "0.14.13", features = ["client", "http1", "stream", "tcp"] }
thiserror = "1.0.29"

[[example]]
name = "configmapgen_controller"
Expand Down
42 changes: 18 additions & 24 deletions examples/configmapgen_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,16 @@ use kube::{
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use snafu::{Backtrace, OptionExt, ResultExt, Snafu};
use std::{collections::BTreeMap, io::BufRead};
use thiserror::Error;
use tokio::time::Duration;

#[derive(Debug, Snafu)]
#[derive(Debug, Error)]
enum Error {
#[snafu(display("Failed to create ConfigMap: {}", source))]
ConfigMapCreationFailed {
source: kube::Error,
backtrace: Backtrace,
},
MissingObjectKey {
name: &'static str,
backtrace: Backtrace,
},
#[error("Failed to create ConfigMap: {0}")]
ConfigMapCreationFailed(#[source] kube::Error),
#[error("MissingObjectKey: {0}")]
MissingObjectKey(&'static str),
}

#[derive(CustomResource, Debug, Clone, Deserialize, Serialize, JsonSchema)]
Expand All @@ -42,12 +37,8 @@ fn object_to_owner_reference<K: Resource<DynamicType = ()>>(
Ok(OwnerReference {
api_version: K::api_version(&()).to_string(),
kind: K::kind(&()).to_string(),
name: meta.name.context(MissingObjectKey {
name: ".metadata.name",
})?,
uid: meta.uid.context(MissingObjectKey {
name: ".metadata.uid",
})?,
name: meta.name.ok_or(Error::MissingObjectKey(".metadata.name"))?,
uid: meta.uid.ok_or(Error::MissingObjectKey(".metadata.uid"))?,
..OwnerReference::default()
})
}
Expand Down Expand Up @@ -76,20 +67,23 @@ async fn reconcile(generator: ConfigMapGenerator, ctx: Context<Data>) -> Result<
};
let cm_api = Api::<ConfigMap>::namespaced(
client.clone(),
generator.metadata.namespace.as_ref().context(MissingObjectKey {
name: ".metadata.namespace",
})?,
generator
.metadata
.namespace
.as_ref()
.ok_or(Error::MissingObjectKey(".metadata.namespace"))?,
);
cm_api
.patch(
cm.metadata.name.as_ref().context(MissingObjectKey {
name: ".metadata.name",
})?,
cm.metadata
.name
.as_ref()
.ok_or(Error::MissingObjectKey(".metadata.name"))?,
&PatchParams::apply("configmapgenerator.kube-rt.nullable.se"),
&Patch::Apply(&cm),
)
.await
.context(ConfigMapCreationFailed)?;
.map_err(Error::ConfigMapCreationFailed)?;
Ok(ReconcilerAction {
requeue_after: Some(Duration::from_secs(300)),
})
Expand Down
23 changes: 15 additions & 8 deletions examples/secret_syncer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,27 @@ use kube::{
finalizer::{finalizer, Event},
},
};
use snafu::{OptionExt, ResultExt, Snafu};
use std::time::Duration;
use thiserror::Error;

#[derive(Debug, Snafu)]
#[derive(Debug, Error)]
enum Error {
#[error("NoName")]
NoName,
#[error("NoNamespace")]
NoNamespace,
UpdateSecret { source: kube::Error },
DeleteSecret { source: kube::Error },
#[error("UpdateSecret: {0}")]
UpdateSecret(#[source] kube::Error),
#[error("DeleteSecret: {0}")]
DeleteSecret(#[source] kube::Error),
}
type Result<T, E = Error> = std::result::Result<T, E>;

fn secret_name_for_configmap(cm: &ConfigMap) -> Result<String> {
Ok(format!("cm---{}", cm.metadata.name.as_deref().context(NoName)?))
Ok(format!(
"cm---{}",
cm.metadata.name.as_deref().ok_or(Error::NoName)?
))
}

async fn apply(cm: ConfigMap, secrets: &kube::Api<Secret>) -> Result<ReconcilerAction> {
Expand All @@ -48,7 +55,7 @@ async fn apply(cm: ConfigMap, secrets: &kube::Api<Secret>) -> Result<ReconcilerA
}),
)
.await
.context(UpdateSecret)?;
.map_err(Error::UpdateSecret)?;
Ok(ReconcilerAction { requeue_after: None })
}

Expand All @@ -63,7 +70,7 @@ async fn cleanup(cm: ConfigMap, secrets: &kube::Api<Secret>) -> Result<Reconcile
kube::Error::Api(ErrorResponse { code: 404, .. }) => Ok(()),
err => Err(err),
})
.context(DeleteSecret)?;
.map_err(Error::DeleteSecret)?;
Ok(ReconcilerAction { requeue_after: None })
}

Expand All @@ -78,7 +85,7 @@ async fn main() -> color_eyre::Result<()> {
)
.run(
|cm, _| {
let ns = cm.meta().namespace.as_deref().context(NoNamespace).unwrap();
let ns = cm.meta().namespace.as_deref().ok_or(Error::NoNamespace).unwrap();
let cms: Api<ConfigMap> = Api::namespaced(kube.clone(), ns);
let secrets: Api<Secret> = Api::namespaced(kube.clone(), ns);
async move {
Expand Down
42 changes: 24 additions & 18 deletions kube-client/src/api/core_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use futures::Stream;
use serde::{de::DeserializeOwned, Serialize};
use std::fmt::Debug;

use crate::{api::Api, Result};
use crate::{api::Api, Error, Result};
use kube_core::{object::ObjectList, params::*, response::Status, WatchEvent};

/// PUSH/PUT/POST/GET abstractions
Expand All @@ -17,15 +17,15 @@ where
/// use kube::{Api, Client};
/// use k8s_openapi::api::core::v1::Pod;
/// #[tokio::main]
/// async fn main() -> Result<(), kube::Error> {
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::try_default().await?;
/// let pods: Api<Pod> = Api::namespaced(client, "apps");
/// let p: Pod = pods.get("blog").await?;
/// Ok(())
/// }
/// ```
pub async fn get(&self, name: &str) -> Result<K> {
let mut req = self.request.get(name)?;
let mut req = self.request.get(name).map_err(Error::BuildRequest)?;
req.extensions_mut().insert("get");
self.client.request::<K>(req).await
}
Expand All @@ -38,7 +38,7 @@ where
/// use kube::{api::{Api, ListParams, ResourceExt}, Client};
/// use k8s_openapi::api::core::v1::Pod;
/// #[tokio::main]
/// async fn main() -> Result<(), kube::Error> {
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::try_default().await?;
/// let pods: Api<Pod> = Api::namespaced(client, "apps");
/// let lp = ListParams::default().labels("app=blog"); // for this app only
Expand All @@ -49,7 +49,7 @@ where
/// }
/// ```
pub async fn list(&self, lp: &ListParams) -> Result<ObjectList<K>> {
let mut req = self.request.list(lp)?;
let mut req = self.request.list(lp).map_err(Error::BuildRequest)?;
req.extensions_mut().insert("list");
self.client.request::<ObjectList<K>>(req).await
}
Expand All @@ -74,8 +74,8 @@ where
where
K: Serialize,
{
let bytes = serde_json::to_vec(&data)?;
let mut req = self.request.create(pp, bytes)?;
let bytes = serde_json::to_vec(&data).map_err(Error::SerdeError)?;
let mut req = self.request.create(pp, bytes).map_err(Error::BuildRequest)?;
req.extensions_mut().insert("create");
self.client.request::<K>(req).await
}
Expand All @@ -93,7 +93,7 @@ where
/// use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1 as apiexts;
/// use apiexts::CustomResourceDefinition;
/// #[tokio::main]
/// async fn main() -> Result<(), kube::Error> {
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::try_default().await?;
/// let crds: Api<CustomResourceDefinition> = Api::all(client);
/// crds.delete("foos.clux.dev", &DeleteParams::default()).await?
Expand All @@ -103,7 +103,7 @@ where
/// }
/// ```
pub async fn delete(&self, name: &str, dp: &DeleteParams) -> Result<Either<K, Status>> {
let mut req = self.request.delete(name, dp)?;
let mut req = self.request.delete(name, dp).map_err(Error::BuildRequest)?;
req.extensions_mut().insert("delete");
self.client.request_status::<K>(req).await
}
Expand All @@ -120,7 +120,7 @@ where
/// use kube::{api::{Api, DeleteParams, ListParams, ResourceExt}, Client};
/// use k8s_openapi::api::core::v1::Pod;
/// #[tokio::main]
/// async fn main() -> Result<(), kube::Error> {
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::try_default().await?;
/// let pods: Api<Pod> = Api::namespaced(client, "apps");
/// match pods.delete_collection(&DeleteParams::default(), &ListParams::default()).await? {
Expand All @@ -140,7 +140,10 @@ where
dp: &DeleteParams,
lp: &ListParams,
) -> Result<Either<ObjectList<K>, Status>> {
let mut req = self.request.delete_collection(dp, lp)?;
let mut req = self
.request
.delete_collection(dp, lp)
.map_err(Error::BuildRequest)?;
req.extensions_mut().insert("delete_collection");
self.client.request_status::<ObjectList<K>>(req).await
}
Expand All @@ -153,7 +156,7 @@ where
/// use kube::{api::{Api, PatchParams, Patch, Resource}, Client};
/// use k8s_openapi::api::core::v1::Pod;
/// #[tokio::main]
/// async fn main() -> Result<(), kube::Error> {
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::try_default().await?;
/// let pods: Api<Pod> = Api::namespaced(client, "apps");
/// let patch = serde_json::json!({
Expand All @@ -180,7 +183,7 @@ where
pp: &PatchParams,
patch: &Patch<P>,
) -> Result<K> {
let mut req = self.request.patch(name, pp, patch)?;
let mut req = self.request.patch(name, pp, patch).map_err(Error::BuildRequest)?;
req.extensions_mut().insert("patch");
self.client.request::<K>(req).await
}
Expand All @@ -197,7 +200,7 @@ where
/// use kube::{api::{Api, PostParams, ResourceExt}, Client};
/// use k8s_openapi::api::batch::v1::Job;
/// #[tokio::main]
/// async fn main() -> Result<(), kube::Error> {
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::try_default().await?;
/// let jobs: Api<Job> = Api::namespaced(client, "apps");
/// let j = jobs.get("baz").await?;
Expand Down Expand Up @@ -233,8 +236,11 @@ where
where
K: Serialize,
{
let bytes = serde_json::to_vec(&data)?;
let mut req = self.request.replace(name, pp, bytes)?;
let bytes = serde_json::to_vec(&data).map_err(Error::SerdeError)?;
let mut req = self
.request
.replace(name, pp, bytes)
.map_err(Error::BuildRequest)?;
req.extensions_mut().insert("replace");
self.client.request::<K>(req).await
}
Expand All @@ -255,7 +261,7 @@ where
/// use k8s_openapi::api::batch::v1::Job;
/// use futures::{StreamExt, TryStreamExt};
/// #[tokio::main]
/// async fn main() -> Result<(), kube::Error> {
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::try_default().await?;
/// let jobs: Api<Job> = Api::namespaced(client, "apps");
/// let lp = ListParams::default()
Expand All @@ -281,7 +287,7 @@ where
lp: &ListParams,
version: &str,
) -> Result<impl Stream<Item = Result<WatchEvent<K>>>> {
let mut req = self.request.watch(lp, version)?;
let mut req = self.request.watch(lp, version).map_err(Error::BuildRequest)?;
req.extensions_mut().insert("watch");
self.client.request_events::<K>(req).await
}
Expand Down
Loading

0 comments on commit 120d000

Please sign in to comment.