Skip to content

Commit 120d000

Browse files
authored
Merge pull request #686 from kazk/refine-errors
2 parents e9eec90 + 567e472 commit 120d000

38 files changed

+536
-430
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@ UNRELEASED
33
===================
44
* see https://github.com/kube-rs/kube-rs/compare/0.63.2...master
55

6+
* BREAKING: The following breaking changes were made as a part of an effort to refine errors (#688).
7+
- Removed `kube::core::Error` and `kube::core::Result`. `kube::core::Error` was replaced by more specific errors as described below.
8+
- Replaced `kube::core::Error::InvalidGroupVersion` with `kube::core::gvk::ParseGroupVersionError`.
9+
- Changed the error returned from `kube::core::admission::AdmissionRequest::with_patch` to `kube::core::admission::SerializePatchError` (was `kube::core::Error::SerdeError`).
10+
- Changed the error associated with `TryInto<AdmissionRequest<T>` to `kube::core::admission::ConvertAdmissionReviewError` (was `kube::core::Error::RequestValidation`).
11+
- 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`.
12+
- 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`.
13+
- 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`.
14+
- Changed variants of error enums in `kube::runtime`. Replaced `snafu` with `thiserror`.
15+
616
0.63.2 / 2021-10-28
717
===================
818
* `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)

examples/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ serde_json = "1.0.68"
4040
serde_yaml = "0.8.21"
4141
tokio = { version = "1.12.0", features = ["full"] }
4242
color-eyre = "0.5.10"
43-
snafu = { version = "0.6.10", features = ["futures"] }
4443
# Some Api::delete methods use Either
4544
either = "1.6.1"
4645
schemars = "0.8.6"
@@ -54,6 +53,7 @@ json-patch = "0.2.6"
5453
tower = { version = "0.4.6" }
5554
tower-http = { version = "0.1.0", features = ["trace", "decompression-gzip"] }
5655
hyper = { version = "0.14.13", features = ["client", "http1", "stream", "tcp"] }
56+
thiserror = "1.0.29"
5757

5858
[[example]]
5959
name = "configmapgen_controller"

examples/configmapgen_controller.rs

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,16 @@ use kube::{
1212
};
1313
use schemars::JsonSchema;
1414
use serde::{Deserialize, Serialize};
15-
use snafu::{Backtrace, OptionExt, ResultExt, Snafu};
1615
use std::{collections::BTreeMap, io::BufRead};
16+
use thiserror::Error;
1717
use tokio::time::Duration;
1818

19-
#[derive(Debug, Snafu)]
19+
#[derive(Debug, Error)]
2020
enum Error {
21-
#[snafu(display("Failed to create ConfigMap: {}", source))]
22-
ConfigMapCreationFailed {
23-
source: kube::Error,
24-
backtrace: Backtrace,
25-
},
26-
MissingObjectKey {
27-
name: &'static str,
28-
backtrace: Backtrace,
29-
},
21+
#[error("Failed to create ConfigMap: {0}")]
22+
ConfigMapCreationFailed(#[source] kube::Error),
23+
#[error("MissingObjectKey: {0}")]
24+
MissingObjectKey(&'static str),
3025
}
3126

3227
#[derive(CustomResource, Debug, Clone, Deserialize, Serialize, JsonSchema)]
@@ -42,12 +37,8 @@ fn object_to_owner_reference<K: Resource<DynamicType = ()>>(
4237
Ok(OwnerReference {
4338
api_version: K::api_version(&()).to_string(),
4439
kind: K::kind(&()).to_string(),
45-
name: meta.name.context(MissingObjectKey {
46-
name: ".metadata.name",
47-
})?,
48-
uid: meta.uid.context(MissingObjectKey {
49-
name: ".metadata.uid",
50-
})?,
40+
name: meta.name.ok_or(Error::MissingObjectKey(".metadata.name"))?,
41+
uid: meta.uid.ok_or(Error::MissingObjectKey(".metadata.uid"))?,
5142
..OwnerReference::default()
5243
})
5344
}
@@ -76,20 +67,23 @@ async fn reconcile(generator: ConfigMapGenerator, ctx: Context<Data>) -> Result<
7667
};
7768
let cm_api = Api::<ConfigMap>::namespaced(
7869
client.clone(),
79-
generator.metadata.namespace.as_ref().context(MissingObjectKey {
80-
name: ".metadata.namespace",
81-
})?,
70+
generator
71+
.metadata
72+
.namespace
73+
.as_ref()
74+
.ok_or(Error::MissingObjectKey(".metadata.namespace"))?,
8275
);
8376
cm_api
8477
.patch(
85-
cm.metadata.name.as_ref().context(MissingObjectKey {
86-
name: ".metadata.name",
87-
})?,
78+
cm.metadata
79+
.name
80+
.as_ref()
81+
.ok_or(Error::MissingObjectKey(".metadata.name"))?,
8882
&PatchParams::apply("configmapgenerator.kube-rt.nullable.se"),
8983
&Patch::Apply(&cm),
9084
)
9185
.await
92-
.context(ConfigMapCreationFailed)?;
86+
.map_err(Error::ConfigMapCreationFailed)?;
9387
Ok(ReconcilerAction {
9488
requeue_after: Some(Duration::from_secs(300)),
9589
})

examples/secret_syncer.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,27 @@ use kube::{
1414
finalizer::{finalizer, Event},
1515
},
1616
};
17-
use snafu::{OptionExt, ResultExt, Snafu};
1817
use std::time::Duration;
18+
use thiserror::Error;
1919

20-
#[derive(Debug, Snafu)]
20+
#[derive(Debug, Error)]
2121
enum Error {
22+
#[error("NoName")]
2223
NoName,
24+
#[error("NoNamespace")]
2325
NoNamespace,
24-
UpdateSecret { source: kube::Error },
25-
DeleteSecret { source: kube::Error },
26+
#[error("UpdateSecret: {0}")]
27+
UpdateSecret(#[source] kube::Error),
28+
#[error("DeleteSecret: {0}")]
29+
DeleteSecret(#[source] kube::Error),
2630
}
2731
type Result<T, E = Error> = std::result::Result<T, E>;
2832

2933
fn secret_name_for_configmap(cm: &ConfigMap) -> Result<String> {
30-
Ok(format!("cm---{}", cm.metadata.name.as_deref().context(NoName)?))
34+
Ok(format!(
35+
"cm---{}",
36+
cm.metadata.name.as_deref().ok_or(Error::NoName)?
37+
))
3138
}
3239

3340
async fn apply(cm: ConfigMap, secrets: &kube::Api<Secret>) -> Result<ReconcilerAction> {
@@ -48,7 +55,7 @@ async fn apply(cm: ConfigMap, secrets: &kube::Api<Secret>) -> Result<ReconcilerA
4855
}),
4956
)
5057
.await
51-
.context(UpdateSecret)?;
58+
.map_err(Error::UpdateSecret)?;
5259
Ok(ReconcilerAction { requeue_after: None })
5360
}
5461

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

@@ -78,7 +85,7 @@ async fn main() -> color_eyre::Result<()> {
7885
)
7986
.run(
8087
|cm, _| {
81-
let ns = cm.meta().namespace.as_deref().context(NoNamespace).unwrap();
88+
let ns = cm.meta().namespace.as_deref().ok_or(Error::NoNamespace).unwrap();
8289
let cms: Api<ConfigMap> = Api::namespaced(kube.clone(), ns);
8390
let secrets: Api<Secret> = Api::namespaced(kube.clone(), ns);
8491
async move {

kube-client/src/api/core_methods.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use futures::Stream;
33
use serde::{de::DeserializeOwned, Serialize};
44
use std::fmt::Debug;
55

6-
use crate::{api::Api, Result};
6+
use crate::{api::Api, Error, Result};
77
use kube_core::{object::ObjectList, params::*, response::Status, WatchEvent};
88

99
/// PUSH/PUT/POST/GET abstractions
@@ -17,15 +17,15 @@ where
1717
/// use kube::{Api, Client};
1818
/// use k8s_openapi::api::core::v1::Pod;
1919
/// #[tokio::main]
20-
/// async fn main() -> Result<(), kube::Error> {
20+
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
2121
/// let client = Client::try_default().await?;
2222
/// let pods: Api<Pod> = Api::namespaced(client, "apps");
2323
/// let p: Pod = pods.get("blog").await?;
2424
/// Ok(())
2525
/// }
2626
/// ```
2727
pub async fn get(&self, name: &str) -> Result<K> {
28-
let mut req = self.request.get(name)?;
28+
let mut req = self.request.get(name).map_err(Error::BuildRequest)?;
2929
req.extensions_mut().insert("get");
3030
self.client.request::<K>(req).await
3131
}
@@ -38,7 +38,7 @@ where
3838
/// use kube::{api::{Api, ListParams, ResourceExt}, Client};
3939
/// use k8s_openapi::api::core::v1::Pod;
4040
/// #[tokio::main]
41-
/// async fn main() -> Result<(), kube::Error> {
41+
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
4242
/// let client = Client::try_default().await?;
4343
/// let pods: Api<Pod> = Api::namespaced(client, "apps");
4444
/// let lp = ListParams::default().labels("app=blog"); // for this app only
@@ -49,7 +49,7 @@ where
4949
/// }
5050
/// ```
5151
pub async fn list(&self, lp: &ListParams) -> Result<ObjectList<K>> {
52-
let mut req = self.request.list(lp)?;
52+
let mut req = self.request.list(lp).map_err(Error::BuildRequest)?;
5353
req.extensions_mut().insert("list");
5454
self.client.request::<ObjectList<K>>(req).await
5555
}
@@ -74,8 +74,8 @@ where
7474
where
7575
K: Serialize,
7676
{
77-
let bytes = serde_json::to_vec(&data)?;
78-
let mut req = self.request.create(pp, bytes)?;
77+
let bytes = serde_json::to_vec(&data).map_err(Error::SerdeError)?;
78+
let mut req = self.request.create(pp, bytes).map_err(Error::BuildRequest)?;
7979
req.extensions_mut().insert("create");
8080
self.client.request::<K>(req).await
8181
}
@@ -93,7 +93,7 @@ where
9393
/// use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1 as apiexts;
9494
/// use apiexts::CustomResourceDefinition;
9595
/// #[tokio::main]
96-
/// async fn main() -> Result<(), kube::Error> {
96+
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
9797
/// let client = Client::try_default().await?;
9898
/// let crds: Api<CustomResourceDefinition> = Api::all(client);
9999
/// crds.delete("foos.clux.dev", &DeleteParams::default()).await?
@@ -103,7 +103,7 @@ where
103103
/// }
104104
/// ```
105105
pub async fn delete(&self, name: &str, dp: &DeleteParams) -> Result<Either<K, Status>> {
106-
let mut req = self.request.delete(name, dp)?;
106+
let mut req = self.request.delete(name, dp).map_err(Error::BuildRequest)?;
107107
req.extensions_mut().insert("delete");
108108
self.client.request_status::<K>(req).await
109109
}
@@ -120,7 +120,7 @@ where
120120
/// use kube::{api::{Api, DeleteParams, ListParams, ResourceExt}, Client};
121121
/// use k8s_openapi::api::core::v1::Pod;
122122
/// #[tokio::main]
123-
/// async fn main() -> Result<(), kube::Error> {
123+
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
124124
/// let client = Client::try_default().await?;
125125
/// let pods: Api<Pod> = Api::namespaced(client, "apps");
126126
/// match pods.delete_collection(&DeleteParams::default(), &ListParams::default()).await? {
@@ -140,7 +140,10 @@ where
140140
dp: &DeleteParams,
141141
lp: &ListParams,
142142
) -> Result<Either<ObjectList<K>, Status>> {
143-
let mut req = self.request.delete_collection(dp, lp)?;
143+
let mut req = self
144+
.request
145+
.delete_collection(dp, lp)
146+
.map_err(Error::BuildRequest)?;
144147
req.extensions_mut().insert("delete_collection");
145148
self.client.request_status::<ObjectList<K>>(req).await
146149
}
@@ -153,7 +156,7 @@ where
153156
/// use kube::{api::{Api, PatchParams, Patch, Resource}, Client};
154157
/// use k8s_openapi::api::core::v1::Pod;
155158
/// #[tokio::main]
156-
/// async fn main() -> Result<(), kube::Error> {
159+
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
157160
/// let client = Client::try_default().await?;
158161
/// let pods: Api<Pod> = Api::namespaced(client, "apps");
159162
/// let patch = serde_json::json!({
@@ -180,7 +183,7 @@ where
180183
pp: &PatchParams,
181184
patch: &Patch<P>,
182185
) -> Result<K> {
183-
let mut req = self.request.patch(name, pp, patch)?;
186+
let mut req = self.request.patch(name, pp, patch).map_err(Error::BuildRequest)?;
184187
req.extensions_mut().insert("patch");
185188
self.client.request::<K>(req).await
186189
}
@@ -197,7 +200,7 @@ where
197200
/// use kube::{api::{Api, PostParams, ResourceExt}, Client};
198201
/// use k8s_openapi::api::batch::v1::Job;
199202
/// #[tokio::main]
200-
/// async fn main() -> Result<(), kube::Error> {
203+
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
201204
/// let client = Client::try_default().await?;
202205
/// let jobs: Api<Job> = Api::namespaced(client, "apps");
203206
/// let j = jobs.get("baz").await?;
@@ -233,8 +236,11 @@ where
233236
where
234237
K: Serialize,
235238
{
236-
let bytes = serde_json::to_vec(&data)?;
237-
let mut req = self.request.replace(name, pp, bytes)?;
239+
let bytes = serde_json::to_vec(&data).map_err(Error::SerdeError)?;
240+
let mut req = self
241+
.request
242+
.replace(name, pp, bytes)
243+
.map_err(Error::BuildRequest)?;
238244
req.extensions_mut().insert("replace");
239245
self.client.request::<K>(req).await
240246
}
@@ -255,7 +261,7 @@ where
255261
/// use k8s_openapi::api::batch::v1::Job;
256262
/// use futures::{StreamExt, TryStreamExt};
257263
/// #[tokio::main]
258-
/// async fn main() -> Result<(), kube::Error> {
264+
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
259265
/// let client = Client::try_default().await?;
260266
/// let jobs: Api<Job> = Api::namespaced(client, "apps");
261267
/// let lp = ListParams::default()
@@ -281,7 +287,7 @@ where
281287
lp: &ListParams,
282288
version: &str,
283289
) -> Result<impl Stream<Item = Result<WatchEvent<K>>>> {
284-
let mut req = self.request.watch(lp, version)?;
290+
let mut req = self.request.watch(lp, version).map_err(Error::BuildRequest)?;
285291
req.extensions_mut().insert("watch");
286292
self.client.request_events::<K>(req).await
287293
}

0 commit comments

Comments
 (0)