Skip to content

Commit e8e401a

Browse files
authored
feat: Add StatefulSet rollout tracker (#833)
* Add StatefulSet rollout tracker * Actually add the new module * Changelog * Move rollout module into status
1 parent fb6f66f commit e8e401a

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

crates/stackable-operator/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
44

55
## [Unreleased]
66

7+
### Added
8+
9+
- Rollout tracker for `StatefulSet` ([#833]).
10+
11+
[#833]: https://github.com/stackabletech/operator-rs/pull/833
12+
713
## [0.72.0] - 2024-08-05
814

915
### Changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub mod condition;
2+
pub mod rollout;
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//! Tools for managing rollouts of Pod controllers (such as [`StatefulSet`]).
2+
3+
use std::borrow::Cow;
4+
5+
use k8s_openapi::api::apps::v1::StatefulSet;
6+
use snafu::Snafu;
7+
8+
/// The reason for why a [`StatefulSet`] is still rolling out. Returned by [`check_statefulset_rollout_complete`].
9+
#[derive(Debug, Snafu)]
10+
#[snafu(module(outdated_statefulset))]
11+
pub enum StatefulSetRolloutInProgress {
12+
/// Indicates that the latest version of the [`StatefulSet`] has not yet been observed by Kubernetes' StatefulSet controller.
13+
///
14+
/// Kubernetes' controllers run asynchronously in the background, so this is expected when the `spec` has just been modified.
15+
#[snafu(display("generation {current_generation:?} not yet observed by statefulset controller, last seen was {observed_generation:?}"))]
16+
NotYetObserved {
17+
current_generation: Option<i64>,
18+
observed_generation: Option<i64>,
19+
},
20+
21+
/// Indicates that outdated replicas still exist.
22+
#[snafu(display("only {updated_replicas} out of {total_replicas} are updated"))]
23+
HasOutdatedReplicas {
24+
total_replicas: i32,
25+
updated_replicas: i32,
26+
},
27+
}
28+
29+
/// Checks whether all ReplicaSet replicas are up-to-date according to `sts.spec`.
30+
///
31+
/// "Success" here means that there are no replicas running an old version,
32+
/// *not* that all updated replicas are available yet.
33+
pub fn check_statefulset_rollout_complete(
34+
sts: &StatefulSet,
35+
) -> Result<(), StatefulSetRolloutInProgress> {
36+
use outdated_statefulset::*;
37+
38+
let status = sts.status.as_ref().map_or_else(Cow::default, Cow::Borrowed);
39+
40+
let current_generation = sts.metadata.generation;
41+
let observed_generation = status.observed_generation;
42+
if current_generation != observed_generation {
43+
return NotYetObservedSnafu {
44+
current_generation,
45+
observed_generation,
46+
}
47+
.fail();
48+
}
49+
50+
let total_replicas = status.replicas;
51+
let updated_replicas = status.updated_replicas.unwrap_or(0);
52+
if total_replicas != updated_replicas {
53+
return HasOutdatedReplicasSnafu {
54+
total_replicas,
55+
updated_replicas,
56+
}
57+
.fail();
58+
}
59+
60+
Ok(())
61+
}

0 commit comments

Comments
 (0)