Skip to content
Closed
Changes from all commits
Commits
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
170 changes: 170 additions & 0 deletions src/status/condition/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,98 @@ pub struct ClusterCondition {
pub type_: ClusterConditionType,
}

impl std::fmt::Display for ClusterCondition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let out = match self.type_ {
ClusterConditionType::Available => match self.status {
ClusterConditionStatus::True => "Available",
ClusterConditionStatus::False => "Unavailable",
ClusterConditionStatus::Unknown => "Availability unknown",
},
ClusterConditionType::Degraded => match self.status {
ClusterConditionStatus::True => "Degraded",
ClusterConditionStatus::False => "Not degraded",
ClusterConditionStatus::Unknown => "Degradation unknown",
},
ClusterConditionType::Progressing => match self.status {
ClusterConditionStatus::True => "Progressing",
ClusterConditionStatus::False => "Not progressing",
ClusterConditionStatus::Unknown => "Progression unknown",
},
ClusterConditionType::ReconciliationPaused => match self.status {
ClusterConditionStatus::True => "Reconciling",
ClusterConditionStatus::False => "Not reconciling",
ClusterConditionStatus::Unknown => "Reconciliation unknown",
},
ClusterConditionType::Stopped => match self.status {
ClusterConditionStatus::True => "Stopped",
ClusterConditionStatus::False => "Running",
ClusterConditionStatus::Unknown => "Stopped status unknown",
},
};

out.fmt(f)
}
}

impl ClusterCondition {
/// Returns if the [`ClusterCondition`] is considered to be in a good /
/// healthy state.
pub fn is_good(&self) -> bool {
match self.type_ {
ClusterConditionType::Available => match self.status {
ClusterConditionStatus::False | ClusterConditionStatus::Unknown => false,
ClusterConditionStatus::True => true,
},
ClusterConditionType::Degraded => match self.status {
ClusterConditionStatus::False | ClusterConditionStatus::Unknown => true,
ClusterConditionStatus::True => false,
},
ClusterConditionType::Progressing => match self.status {
ClusterConditionStatus::False | ClusterConditionStatus::Unknown => false,
ClusterConditionStatus::True => true,
},
ClusterConditionType::ReconciliationPaused => match self.status {
ClusterConditionStatus::False | ClusterConditionStatus::True => true,
ClusterConditionStatus::Unknown => false,
},
ClusterConditionType::Stopped => match self.status {
ClusterConditionStatus::True | ClusterConditionStatus::Unknown => false,
ClusterConditionStatus::False => true,
},
}
}

/// Returns a short display string. This method wraps the
/// [`std::fmt::Display`] implementation of the [`ClusterCondition`].
pub fn display_short(&self) -> String {
self.to_string()
}

/// Returns a long display string. This method uses the
/// [`std::fmt::Display`] implementation of the [`ClusterCondition`] and
/// combines it with the optional message to provide more context.
pub fn display_long(&self) -> String {
match &self.message {
Some(message) => format!("{}: {}", self, message),
None => self.to_string(),
}
}

/// Returns either a short or long display string, This method additionally
/// checks if the condition is considered to be in a good state and then
/// returns the short display string. In case the condition is considered
/// to be in an unhealthy state, the method returns a long display string
/// which contains the optional message to provide more context. Internally
/// this method uses the `display_short` and `display_long` methods.
pub fn display_short_or_long(&self) -> String {
match self.is_good() {
true => self.display_short(),
false => self.display_long(),
}
}
}

#[derive(
Clone,
Copy,
Expand Down Expand Up @@ -499,4 +591,82 @@ mod test {
assert_eq!(got.status, expected.status);
assert_eq!(got.message, expected.message);
}

#[test]
fn test_display_short() {
let condition = ClusterCondition {
type_: ClusterConditionType::Available,
status: ClusterConditionStatus::False,
message: Some("This should not be displayed".into()),
..Default::default()
};

assert!(!condition.is_good());
assert_eq!(condition.display_short(), "Unavailable".to_string());

let condition = ClusterCondition {
type_: ClusterConditionType::Available,
status: ClusterConditionStatus::True,
message: Some("This should not be displayed".into()),
..Default::default()
};

assert!(condition.is_good());
assert_eq!(condition.display_short(), "Available".to_string());
}

#[test]
fn test_display_long() {
let condition = ClusterCondition {
type_: ClusterConditionType::Available,
status: ClusterConditionStatus::False,
message: Some("This should be displayed".into()),
..Default::default()
};

assert!(!condition.is_good());
assert_eq!(
condition.display_long(),
"Unavailable: This should be displayed".to_string()
);

let condition = ClusterCondition {
type_: ClusterConditionType::Available,
status: ClusterConditionStatus::True,
message: Some("This should be displayed".into()),
..Default::default()
};

assert!(condition.is_good());
assert_eq!(
condition.display_long(),
"Available: This should be displayed".to_string()
);
}

#[test]
fn test_display_short_or_long() {
let condition = ClusterCondition {
type_: ClusterConditionType::Available,
status: ClusterConditionStatus::False,
message: Some("This should be displayed if unhealthy".into()),
..Default::default()
};

assert!(!condition.is_good());
assert_eq!(
condition.display_short_or_long(),
"Unavailable: This should be displayed if unhealthy".to_string()
);

let condition = ClusterCondition {
type_: ClusterConditionType::Available,
status: ClusterConditionStatus::True,
message: Some("This should not be displayed".into()),
..Default::default()
};

assert!(condition.is_good());
assert_eq!(condition.display_short_or_long(), "Available".to_string());
}
}