diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a56fce55..be8b1ee21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. - Cluster resources can be added to a struct which determines the orphaned resources and deletes them ([#436]). +- Added `Client::get_opt` for trying to get an object that may not exist ([#451]). ### Changed @@ -15,6 +16,7 @@ All notable changes to this project will be documented in this file. `ObjectMetaBuilder::with_recommended_labels` function ([#436]). [#436]: https://github.com/stackabletech/operator-rs/pull/436 +[#451]: https://github.com/stackabletech/operator-rs/pull/451 ## [0.23.0] - 2022-07-26 diff --git a/src/client.rs b/src/client.rs index 48715843f..cbf0437c3 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,4 +1,4 @@ -use crate::error::{Error, OperatorResult}; +use crate::error::OperatorResult; use crate::label_selector; use backoff::backoff::Backoff; @@ -9,7 +9,6 @@ use k8s_openapi::apimachinery::pkg::apis::meta::v1::LabelSelector; use kube::api::{DeleteParams, ListParams, Patch, PatchParams, PostParams, Resource, ResourceExt}; use kube::client::Client as KubeClient; use kube::core::Status; -use kube::error::ErrorResponse; use kube::runtime::WatchStreamExt; use kube::{Api, Config}; use serde::de::DeserializeOwned; @@ -78,12 +77,26 @@ impl Client { Ok(self.get_api(namespace).get(resource_name).await?) } + /// Retrieves a single instance of the requested resource type with the given name, if it exists. + pub async fn get_opt( + &self, + resource_name: &str, + namespace: Option<&str>, + ) -> OperatorResult> + where + T: Clone + Debug + DeserializeOwned + Resource, + ::DynamicType: Default, + { + Ok(self.get_api(namespace).get_opt(resource_name).await?) + } + /// Returns Ok(true) if the resource has been registered in Kubernetes, Ok(false) if it could /// not be found and Error in any other case (e.g. connection to Kubernetes failed in some way). /// Kubernetes does not offer a pure exists check. Therefore we currently use the get() method /// and ignore the (in case of existing) returned resource. We should replace this with a pure /// exists method as soon as it becomes available (e.g. only returning Ok/Success) to reduce /// network traffic. + #[deprecated(since = "0.24.0", note = "Replaced by `get_opt`")] pub async fn exists( &self, resource_name: &str, @@ -93,14 +106,9 @@ impl Client { T: Clone + Debug + DeserializeOwned + Resource, ::DynamicType: Default, { - let resource: OperatorResult = self.get(resource_name, namespace).await; - match resource { - Ok(_) => Ok(true), - Err(Error::KubeError { - source: kube::error::Error::Api(ErrorResponse { reason, .. }), - }) if reason == "NotFound" => Ok(false), - Err(err) => Err(err), - } + self.get_opt::(resource_name, namespace) + .await + .map(|obj| obj.is_some()) } /// Retrieves all instances of the requested resource type. @@ -373,9 +381,10 @@ impl Client { self.delete(&resource).await?; loop { - if !self - .exists::(&resource.name_any(), resource.namespace().as_deref()) + if self + .get_opt::(&resource.name_any(), resource.namespace().as_deref()) .await? + .is_none() { return Ok(()); }