Skip to content

[Merged by Bors] - Add status field support #571

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
30191c8
added status mod
razvan Mar 14, 2023
c0c36c9
wip
razvan Mar 15, 2023
5a80e16
wip
razvan Mar 20, 2023
46ac63d
reset cluster_resources.rs to main version
razvan Mar 21, 2023
35fdb88
wip
maltesander Mar 21, 2023
e130737
fix yaml representation and some refactoring
maltesander Mar 21, 2023
854a283
refactoring
maltesander Mar 21, 2023
867f12c
refactor for simplification
razvan Mar 22, 2023
0548543
sync sts with daemon sets.
razvan Mar 22, 2023
8e0a1b0
Added clusterconditionset
razvan Mar 22, 2023
ccd7985
make ClusterConditionSet vector size depend on ClusterConditionType e…
maltesander Mar 22, 2023
cfea057
some refactoring
maltesander Mar 22, 2023
26d6b44
added one test
razvan Mar 22, 2023
8788e63
removed clones
maltesander Mar 22, 2023
62268eb
Merge remote-tracking branch 'origin/feat/status' into feat/status
maltesander Mar 22, 2023
3acce6f
Use vec! macro to initialize conditions.
razvan Mar 23, 2023
f20a05e
refactoring & comments
maltesander Mar 23, 2023
b2ba70a
move status condition definitions to correct mod definition
maltesander Mar 23, 2023
eda6d33
wip
maltesander Mar 23, 2023
a2ecfd2
merge/combine and fix tests.
razvan Mar 23, 2023
94aec8d
Use callback instead of bool parameter.
razvan Mar 23, 2023
9fdcd3c
Fix doctest
razvan Mar 24, 2023
280d150
update changelog
razvan Mar 24, 2023
aa6d011
added another test case
maltesander Mar 24, 2023
f5c4528
update pr number
razvan Mar 24, 2023
347f788
more tests
maltesander Mar 24, 2023
097fe83
Merge remote-tracking branch 'origin/feat/status' into feat/status
maltesander Mar 24, 2023
2796ee9
clippy
maltesander Mar 24, 2023
fb24f72
added tests for statefulset condition builder
maltesander Mar 24, 2023
f62bcd9
added tests for daemonset condition builder
maltesander Mar 24, 2023
419cdb9
added comment for daemonset and statefulset condition builder that on…
maltesander Mar 24, 2023
b5ff959
Merge remote-tracking branch 'origin/main' into feat/status
maltesander Mar 24, 2023
cdaffc3
Rename Paused to ReconciliationPaused.
razvan Mar 27, 2023
ef52649
Update availability tests for daemonsets and statefulsets.
razvan Mar 29, 2023
600837d
Merge remote-tracking branch 'origin/main' into feat/status
maltesander Mar 30, 2023
b151030
use ClusterConditionType as index
maltesander Mar 30, 2023
063140a
added ClusterOperationsConditionBuilder
maltesander Mar 30, 2023
842bec8
improved docs
maltesander Mar 30, 2023
0b61613
added some more inline comments
maltesander Mar 31, 2023
ef2462b
implemented From<ClusterConditionType> for usize
maltesander Mar 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ All notable changes to this project will be documented in this file.

### Added

- status::condition module to compute the cluster resource status ([#571]).
- Helper function to build RBAC resources ([#572]).
- Add `ClusterResourceApplyStrategy` to `ClusterResource` ([#573]).
- Add `ClusterOperation` common struct with `reconcilation_paused` and `stopped` flags ([#573]).

[#571]: https://github.com/stackabletech/operator-rs/pull/571
[#572]: https://github.com/stackabletech/operator-rs/pull/572
[#573]: https://github.com/stackabletech/operator-rs/pull/573

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub mod pod_utils;
pub mod product_config_utils;
pub mod product_logging;
pub mod role_utils;
pub mod status;
pub mod utils;
pub mod validation;
pub mod yaml;
Expand Down
173 changes: 173 additions & 0 deletions src/status/condition/daemonset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
use crate::status::condition::{
ClusterCondition, ClusterConditionSet, ClusterConditionStatus, ClusterConditionType,
ConditionBuilder,
};

use k8s_openapi::api::apps::v1::DaemonSet;
use kube::ResourceExt;
use std::cmp;

/// Default implementation to build [`ClusterCondition`]s for
/// `DaemonSet` resources.
///
/// Currently only the `ClusterConditionType::Available` is implemented. This will be extended
/// to support all `ClusterConditionType`s in the future.
#[derive(Default)]
pub struct DaemonSetConditionBuilder {
daemon_sets: Vec<DaemonSet>,
}

impl ConditionBuilder for DaemonSetConditionBuilder {
fn build_conditions(&self) -> ClusterConditionSet {
vec![self.available()].into()
}
}

impl DaemonSetConditionBuilder {
pub fn add(&mut self, ds: DaemonSet) {
self.daemon_sets.push(ds);
}

fn available(&self) -> ClusterCondition {
let mut available = ClusterConditionStatus::True;
let mut unavailable_resources = vec![];

for ds in &self.daemon_sets {
let current_status = Self::daemon_set_available(ds);

if current_status != ClusterConditionStatus::True {
unavailable_resources.push(ds.name_any())
}

available = cmp::max(available, current_status);
}

// We need to sort here to make sure roles and role groups are not changing position
// due to the HashMap (random order) logic.
unavailable_resources.sort();

let message = match available {
ClusterConditionStatus::True => {
"All DaemonSet have the requested amount of ready replicas.".to_string()
}
ClusterConditionStatus::False => {
format!("DaemonSet {unavailable_resources:?} missing ready replicas.")
}
ClusterConditionStatus::Unknown => "DaemonSet status cannot be determined.".to_string(),
};

ClusterCondition {
reason: None,
message: Some(message),
status: available,
type_: ClusterConditionType::Available,
last_transition_time: None,
last_update_time: None,
}
}

/// Returns a condition "Available: True" if the number of ready Pods is greater than zero.
/// This is an heuristic that doesn't take into consideration if *all* eligible nodes have
/// running Pods.
/// Other fields of the daemon set status have been considered and discarded for being even less
/// reliable/informative.
fn daemon_set_available(ds: &DaemonSet) -> ClusterConditionStatus {
let number_ready = ds
.status
.as_ref()
.map(|status| status.number_ready)
.unwrap_or_default();

if number_ready > 0 {
ClusterConditionStatus::True
} else {
ClusterConditionStatus::False
}
}
}

#[cfg(test)]
mod test {
use crate::status::condition::daemonset::DaemonSetConditionBuilder;
use crate::status::condition::{
ClusterCondition, ClusterConditionStatus, ClusterConditionType, ConditionBuilder,
};
use k8s_openapi::api::apps::v1::{DaemonSet, DaemonSetStatus};

fn build_ds(number_ready: i32) -> DaemonSet {
DaemonSet {
status: Some(DaemonSetStatus {
number_ready,
..DaemonSetStatus::default()
}),
..DaemonSet::default()
}
}

#[test]
fn test_daemon_set_available_true() {
let ds = build_ds(1);

assert_eq!(
DaemonSetConditionBuilder::daemon_set_available(&ds),
ClusterConditionStatus::True
);
}

#[test]
fn test_daemon_set_available_false() {
let ds = build_ds(0);
assert_eq!(
DaemonSetConditionBuilder::daemon_set_available(&ds),
ClusterConditionStatus::False
);
}

#[test]
fn test_daemon_set_available_condition_true() {
let mut ds_condition_builder = DaemonSetConditionBuilder::default();
ds_condition_builder.add(build_ds(1));

let conditions = ds_condition_builder.build_conditions();

let got = conditions
.conditions
.get::<usize>(ClusterConditionType::Available.into())
.cloned()
.unwrap()
.unwrap();

let expected = ClusterCondition {
type_: ClusterConditionType::Available,
status: ClusterConditionStatus::True,
..ClusterCondition::default()
};

assert_eq!(got.type_, expected.type_);
assert_eq!(got.status, expected.status);
}

#[test]
fn test_daemon_set_available_condition_false() {
let mut ds_condition_builder = DaemonSetConditionBuilder::default();
ds_condition_builder.add(build_ds(0));

let conditions = ds_condition_builder.build_conditions();

let got = conditions
.conditions
.get::<usize>(ClusterConditionType::Available.into())
.cloned()
.unwrap()
.unwrap();

let expected = ClusterCondition {
type_: ClusterConditionType::Available,
status: ClusterConditionStatus::False,
..ClusterCondition::default()
};

assert_eq!(got.type_, expected.type_);
assert_eq!(got.status, expected.status);
}
}
Loading