apt_swarm/plumbing/
update.rs1use crate::args::ContainerUpdateCheck;
2use crate::errors::*;
3use serde::{Deserialize, Serialize};
4use tokio::process::Command;
5
6#[derive(Debug, PartialEq, Serialize, Deserialize)]
7pub struct CraneOutput {
8 pub config: ContainerConfig,
9}
10
11#[derive(Debug, PartialEq, Serialize, Deserialize)]
12pub struct ContainerConfig {
13 #[serde(rename = "Env")]
14 pub env: Vec<String>,
15}
16
17pub enum Updates {
18 Available { current: String, latest: String },
19 AlreadyLatest { commit: String },
20}
21
22pub async fn check(update: &ContainerUpdateCheck) -> Result<Updates> {
23 debug!("Checking updates for container image: {:?}", update.image);
24
25 if update.commit.is_empty() {
26 bail!(
27 "The currently running commit is not configured: {:?}",
28 update.commit
29 );
30 }
31
32 let output = Command::new("crane")
33 .arg("config")
34 .arg("--")
35 .arg(&update.image)
36 .output()
37 .await
38 .context("Failed to execute crane")?;
39
40 if !output.stderr.is_empty() {
41 let error = String::from_utf8_lossy(&output.stderr);
42 warn!("Crane stderr was non-emtpy: {:?}", error);
43 }
44
45 if !output.status.success() {
46 bail!("Crane exited with error: {:?}", output.status);
47 }
48
49 let output = serde_json::from_slice::<CraneOutput>(&output.stdout)
50 .context("Failed to deserialize crane output")?;
51
52 for env in &output.config.env {
53 trace!("Found environment variable in container image: {:?}", env);
54 if let Some(commit) = env.strip_prefix("UPDATE_CHECK_COMMIT=") {
55 debug!("Found commit in container image: {commit:?}");
56 if commit == update.commit {
57 debug!(
58 "Update check detected we're running the latest version of {:?} (commit={:?}",
59 update.image, commit
60 );
61 return Ok(Updates::AlreadyLatest {
62 commit: commit.to_string(),
63 });
64 } else {
65 debug!("Update check detected we're running an outdated version of {:?} (current={:?}, latest={:?})",
66 update.image,
67 update.commit, commit
68 );
69 return Ok(Updates::Available {
70 current: update.commit.to_string(),
71 latest: commit.to_string(),
72 });
73 }
74 }
75 }
76
77 bail!(
78 "Failed to detect commit id in specified container image: {:?}",
79 update.image
80 );
81}