Skip to content

Commit 8550c24

Browse files
committed
feat(operator): Add CRD established signal
This function can be used to wait for a CRD to be established. This is useful to delay the startup of operators until this is supported by upstream kube.
1 parent a16cafb commit 8550c24

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

crates/stackable-operator/src/utils/signal.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1::CustomResourceDefinition;
2+
use kube::runtime::wait;
13
use snafu::{ResultExt, Snafu};
4+
use stackable_shared::time::Duration;
25
use tokio::{
36
signal::unix::{SignalKind, signal},
47
sync::watch,
58
};
69

10+
use crate::client::Client;
11+
712
#[derive(Debug, Snafu)]
813
#[snafu(display("failed to construct signal watcher"))]
914
pub struct SignalError {
@@ -71,3 +76,46 @@ impl SignalWatcher<()> {
7176
Ok(Self { watch_rx })
7277
}
7378
}
79+
80+
pub const DEFAULT_CRD_ESTABLISHED_TIMEOUT: Duration = Duration::from_secs(5);
81+
82+
#[derive(Debug, Snafu)]
83+
pub enum CrdEstablishedError {
84+
#[snafu(display("failed to meet CRD established condition before the timeout elapsed"))]
85+
TimeoutElapsed { source: tokio::time::error::Elapsed },
86+
87+
#[snafu(display("failed to await CRD established condition due to api error"))]
88+
Api { source: kube::runtime::wait::Error },
89+
}
90+
91+
/// Waits for a CRD named `crd_name` to be established before `timeout_duration` (or by default
92+
/// [`DEFAULT_CRD_ESTABLISHED_TIMEOUT`]) is elapsed.
93+
///
94+
/// The same caveats from [`conditions::is_crd_established`](wait::conditions::is_crd_established)
95+
/// apply here as well.
96+
///
97+
/// ### Errors
98+
///
99+
/// This function returns errors either if the timeout elapsed without the condition being met or
100+
/// when the underlying API returned errors (CRD is unknown to the Kubernetes API server or due to
101+
/// missing permissions).
102+
pub async fn crd_established(
103+
client: Client,
104+
crd_name: &str,
105+
timeout_duration: impl Into<Option<Duration>>,
106+
) -> Result<(), CrdEstablishedError> {
107+
let api: kube::Api<CustomResourceDefinition> = client.get_api(&());
108+
let crd_established =
109+
wait::await_condition(api, crd_name, wait::conditions::is_crd_established());
110+
let _ = tokio::time::timeout(
111+
*timeout_duration
112+
.into()
113+
.unwrap_or(DEFAULT_CRD_ESTABLISHED_TIMEOUT),
114+
crd_established,
115+
)
116+
.await
117+
.context(TimeoutElapsedSnafu)?
118+
.context(ApiSnafu)?;
119+
120+
Ok(())
121+
}

0 commit comments

Comments
 (0)