Skip to content

Commit

Permalink
Merge pull request #735 from kristof-mattei/simplify-model
Browse files Browse the repository at this point in the history
chore: just retain all names
  • Loading branch information
kristof-mattei authored Nov 8, 2023
2 parents ce9ce56 + e33b280 commit e4e909e
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 79 deletions.
83 changes: 14 additions & 69 deletions src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fmt;
use std::marker::PhantomData;
use std::str::FromStr;

use serde::de::{MapAccess, SeqAccess, Visitor};
use serde::de::{MapAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize};

fn deserialize_timeout<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
Expand Down Expand Up @@ -43,49 +43,12 @@ where
deserializer.deserialize_map(visitor)
}

fn deserialize_first<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
where
T: Deserialize<'de> + Ord,
D: Deserializer<'de>,
{
struct MaxVisitor<T>(PhantomData<fn() -> T>);

impl<'de, T> Visitor<'de> for MaxVisitor<T>
where
T: Deserialize<'de> + Ord,
{
type Value = Option<T>;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a nonempty sequence of items")
}

fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
where
S: SeqAccess<'de>,
{
if let Some(first) = seq.next_element()? {
// SeqAccess requires us to visit all elements
while (seq.next_element::<T>()?).is_some() {}

Ok(first)
} else {
Ok(None)
}
}
}

let visitor = MaxVisitor(PhantomData);
deserializer.deserialize_seq(visitor)
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Container {
pub id: String,
#[serde(deserialize_with = "deserialize_first")]
#[serde(rename(deserialize = "Names"), default)]
pub name: Option<String>,
pub names: Vec<String>,
pub state: String,
#[serde(deserialize_with = "deserialize_timeout")]
#[serde(rename(deserialize = "Labels"), default)]
Expand All @@ -108,13 +71,13 @@ mod tests {
&[
Container {
id: "582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae".into(),
name: Some("/photoprism".into()),
names: vec!["/photoprism".into()],
state: "running".into(),
timeout: None,
},
Container {
id: "281ea0c72e2e4a41fd2f81df945da9dfbfbc7ea0fe5e59c3d2a8234552e367cf".into(),
name: Some("/whoogle-search".into()),
names: vec!["/whoogle-search".into()],
state: "running".into(),
timeout: None,
}
Expand All @@ -125,7 +88,7 @@ mod tests {

#[test]
fn test_deserialize_multiple_names() {
let input = r#"[{"Id":"582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae","Names":["/photoprism","/photoprism-name-2"],"State":"running"}]"#;
let input = r#"[{"Id":"582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae","Names":["/photoprism-1","/photoprism-2"],"State":"running"}]"#;

let deserialized: Result<Vec<Container>, _> = serde_json::from_reader(input.as_bytes());

Expand All @@ -134,7 +97,7 @@ mod tests {
assert_eq!(
&[Container {
id: "582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae".into(),
name: Some("/photoprism".into()),
names: vec!["/photoprism-1".into(), "/photoprism-2".into()],
state: "running".into(),
timeout: None,
}] as &[Container],
Expand All @@ -153,13 +116,14 @@ mod tests {
assert_eq!(
&[Container {
id: "582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae".into(),
name: Some("/photoprism".into()),
names: vec!["/photoprism".into()],
state: "running".into(),
timeout: Some(12),
}] as &[Container],
deserialized.unwrap()
);
}

#[test]
fn test_deserialize_no_labels() {
let input = r#"[{"Id":"582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae","Names":["/photoprism"],"State":"running"}]"#;
Expand All @@ -171,7 +135,7 @@ mod tests {
assert_eq!(
&[Container {
id: "582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae".into(),
name: Some("/photoprism".into()),
names: vec!["/photoprism".into()],
state: "running".into(),
timeout: None,
}] as &[Container],
Expand All @@ -190,7 +154,7 @@ mod tests {
assert_eq!(
&[Container {
id: "582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae".into(),
name: Some("/photoprism".into()),
names: vec!["/photoprism".into()],
state: "running".into(),
timeout: None,
}] as &[Container],
Expand All @@ -199,7 +163,7 @@ mod tests {
}

#[test]
fn test_deserialize_with_no_name_array() {
fn test_deserialize_with_no_names_array() {
let input = r#"[{"Id":"582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae","State":"running","Labels":{"autoheal.stop.other_label":"some_value"}}]"#;

let deserialized: Result<Vec<Container>, _> = serde_json::from_reader(input.as_bytes());
Expand All @@ -209,26 +173,7 @@ mod tests {
assert_eq!(
&[Container {
id: "582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae".into(),
name: None,
state: "running".into(),
timeout: None,
}] as &[Container],
deserialized.unwrap()
);
}

#[test]
fn test_deserialize_name_array_with_1_null() {
let input = r#"[{"Id":"582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae","Names":[null],"State":"running","Labels":{"autoheal.stop.other_label":"some_value"}}]"#;

let deserialized: Result<Vec<Container>, _> = serde_json::from_reader(input.as_bytes());

assert!(deserialized.is_ok());

assert_eq!(
&[Container {
id: "582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae".into(),
name: None,
names: vec![],
state: "running".into(),
timeout: None,
}] as &[Container],
Expand All @@ -237,7 +182,7 @@ mod tests {
}

#[test]
fn test_deserialize_name_empty_name_array() {
fn test_deserialize_names_empty_names_array() {
let input = r#"[{"Id":"582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae","Names":[],"State":"running","Labels":{"autoheal.stop.other_label":"some_value"}}]"#;

let deserialized: Result<Vec<Container>, _> = serde_json::from_reader(input.as_bytes());
Expand All @@ -247,7 +192,7 @@ mod tests {
assert_eq!(
&[Container {
id: "582036c7a5e8719bbbc9476e4216bfaf4fd318b61723f41f2e8fe3b60d8182ae".into(),
name: None,
names: vec![],
state: "running".into(),
timeout: None,
}] as &[Container],
Expand Down
20 changes: 12 additions & 8 deletions src/docker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,15 @@ impl Docker {
pub async fn check_container_health(&self, app_config: &AppConfig, container_info: Container) {
let container_short_id = &container_info.id[0..12];

match &container_info.name {
None => {
match &container_info.names[..] {
[] => {
tracing::error!("Container name of {} is null, which implies container does not exist - don't restart.", container_short_id);
},
Some(container_name) => {
container_names => {
if container_info.state == "restarting" {
tracing::info!(
"Container {} ({}) found to be restarting - don't restart.",
container_name,
container_names.join(", "),
container_short_id
);
} else {
Expand All @@ -118,25 +118,29 @@ impl Docker {

tracing::info!(
"Container {} ({}) found to be unhealthy - Restarting container now with {}s timeout.",
container_name,
container_names.join(", "),
container_short_id, timeout
);

match self.restart_container(container_short_id, timeout).await {
Ok(()) => {
notify_webhook_success(app_config, container_short_id, container_name);
notify_webhook_success(
app_config,
container_short_id,
&container_names.join(", "),
);
},
Err(e) => {
tracing::info!(
error = ?e,
"Restarting container {} ({}) failed.",
container_name,
container_names.join(", "),
container_short_id
);

notify_webhook_failure(
app_config,
container_name,
&container_names.join(", "),
container_short_id,
&e,
);
Expand Down
4 changes: 2 additions & 2 deletions src/webhook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub fn notify_webhook_success(
};

let message = format!(
"Container {} ({}) found to be unhealthy. Successfully restarted the container!",
"Container \"{}\" ({}) found to be unhealthy. Successfully restarted the container!",
container_name, container_short_id
);

Expand All @@ -40,7 +40,7 @@ pub fn notify_webhook_failure(
};

let message = format!(
"Container {} ({}) found to be unhealthy. Failed to restart the container! Error: {:?}",
"Container \"{}\" ({}) found to be unhealthy. Failed to restart the container! Error: {:?}",
container_name, container_short_id, error
);

Expand Down

0 comments on commit e4e909e

Please sign in to comment.