From cb97d2fe9d0ca8deda0cf8f2db6a086f992f2a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 26 Oct 2021 15:51:43 +0200 Subject: [PATCH 1/2] Generic wait-for-condition Condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Super unhappy with the API, but it's a start... Fixes #669 Signed-off-by: Teo Klestrup Röijezon --- kube-runtime/src/wait.rs | 74 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/kube-runtime/src/wait.rs b/kube-runtime/src/wait.rs index 20fca6b93..5f66616e5 100644 --- a/kube-runtime/src/wait.rs +++ b/kube-runtime/src/wait.rs @@ -85,11 +85,11 @@ where /// } /// } /// ``` -pub trait Condition { +pub trait Condition { fn matches_object(&self, obj: Option<&K>) -> bool; } -impl) -> bool> Condition for F { +impl) -> bool> Condition for F { fn matches_object(&self, obj: Option<&K>) -> bool { (self)(obj) } @@ -100,6 +100,7 @@ pub mod conditions { pub use super::Condition; use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1::CustomResourceDefinition; use kube_client::Resource; + use serde::Serialize; /// An await condition that returns `true` once the object has been deleted. /// @@ -134,6 +135,75 @@ pub mod conditions { false } } + + /// An await condition that returns `true` if the object exists. + /// + /// NOTE: If waiting for an object to be deleted, do _not_ [invert](`Condition::not`) this [`Condition`]. + /// Instead, use [`is_deleted`], which considers a deleted-then-recreated object to have been deleted. + #[must_use] + pub fn exists() -> impl Condition { + |obj: Option<&K>| obj.is_some() + } + + /// An await condition for [`Resource`] that returns `true` if the object's condition of the given type holds true + /// for the given `value_cond`. + /// + /// # Value condition + /// + /// The value condition is passed `None` if the object does not exist or does not have the given condition (combine with + /// [`exists`] if you need to validate whether the object exists). Otherwise, the value should be one of `"True"`, `"False"`, or `"Unknown"` + /// (see for more details). + /// + /// # Stability + /// + /// This is an experimental API that should be expected to change. It has a few particular problems: + /// + /// 1. It is completely untyped + /// 2. It makes fairly deep assumptions about the structure of the object and its status + /// 3. It doesn't have any way to signal errors gracefully + /// 4. It has some unfortunate lifetime problems that prevent bringing in a closure context + /// + /// # Usage + /// + /// ```rust + /// # use k8s_openapi::api::core::v1::{Pod, PodCondition, PodStatus}; + /// # use kube_runtime::wait::{conditions::unstable_has_status_condition, Condition}; + /// let pod = |ready: String| Pod { + /// status: Some(PodStatus { + /// conditions: Some(vec![PodCondition { + /// type_: "Ready".to_string(), + /// status: ready, + /// ..PodCondition::default() + /// }]), + /// ..PodStatus::default() + /// }), + /// ..Pod::default() + /// }; + /// let cond_status_ready: fn(Option<&str>) -> bool = |status| status == Some("True"); + /// let cond_pod_ready = unstable_has_status_condition("Ready", cond_status_ready); + /// assert!(!cond_pod_ready.matches_object(Some(&pod("False".to_string())))); + /// assert!(cond_pod_ready.matches_object(Some(&pod("True".to_string())))); + /// ``` + #[must_use] + pub fn unstable_has_status_condition<'a, K: Serialize + Resource, StatusCond: Condition + 'a>( + condition_type: &'a str, + status_cond: StatusCond, + ) -> impl Condition + 'a { + move |obj: Option<&K>| { + let serialized_obj = serde_json::to_value(obj).ok(); + status_cond.matches_object(serialized_obj.as_ref().and_then(|obj| { + obj.get("status")? + .get("conditions")? + .as_array()? + .iter() + .find(|cond| { + cond.get("type").and_then(serde_json::Value::as_str) == Some(condition_type) + })? + .get("status")? + .as_str() + })) + } + } } /// Utilities for deleting objects From b3c82cf37083b9e9f87955b988ebb420d1b57db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 18 Nov 2021 16:59:09 +0100 Subject: [PATCH 2/2] Update kube-runtime/src/wait.rs Co-authored-by: Eirik A --- kube-runtime/src/wait.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kube-runtime/src/wait.rs b/kube-runtime/src/wait.rs index 4751b2303..e614645f9 100644 --- a/kube-runtime/src/wait.rs +++ b/kube-runtime/src/wait.rs @@ -202,8 +202,7 @@ pub mod conditions { |obj: Option<&K>| obj.is_some() } - /// An await condition for [`Resource`] that returns `true` if the object's condition of the given type holds true - /// for the given `value_cond`. + /// A condition that returns true if an arbitrary condition matches a condition value /// /// # Value condition ///