From 83cb815e76594ecdcb0e32ce3e902591139fb2a8 Mon Sep 17 00:00:00 2001 From: donpat1to Date: Tue, 23 Sep 2025 23:27:13 +0200 Subject: [PATCH] added docker image update option --- WatcherAgent/Cargo.toml | 6 ++- WatcherAgent/src/api.rs | 38 ++++-------------- WatcherAgent/src/main.rs | 1 + WatcherAgent/src/serverclientcomm.rs | 60 ++++++++++++++++++++++++++++ docker-compose.yaml | 23 +++++++++++ 5 files changed, 96 insertions(+), 32 deletions(-) create mode 100644 WatcherAgent/src/serverclientcomm.rs create mode 100644 docker-compose.yaml diff --git a/WatcherAgent/Cargo.toml b/WatcherAgent/Cargo.toml index ee090b1..e241063 100644 --- a/WatcherAgent/Cargo.toml +++ b/WatcherAgent/Cargo.toml @@ -20,8 +20,10 @@ nvml-wrapper-sys = "0.9.0" anyhow = "1.0.98" # Docker .env loading -config = "0.13" -dotenvy = "0.15" +# config = "0.13" + +# Docker API access +bollard = "0.16" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["winuser", "pdh", "ifmib", "iphlpapi", "winerror" ,"wbemcli", "combaseapi"] } diff --git a/WatcherAgent/src/api.rs b/WatcherAgent/src/api.rs index f349479..4d5d0f4 100644 --- a/WatcherAgent/src/api.rs +++ b/WatcherAgent/src/api.rs @@ -1,3 +1,6 @@ +use crate::serverclientmessage::handle_server_message; + + use std::time::Duration; use crate::hardware::HardwareInfo; @@ -7,6 +10,8 @@ use reqwest::{Client, StatusCode}; use std::error::Error; use tokio::time::sleep; + + pub async fn register_with_server( base_url: &str, ) -> Result<(i32, String), Box> { @@ -154,7 +159,7 @@ pub async fn send_metrics( Ok(()) } -pub async fn listening_to_server(base_url: &str) -> Result<(), Box>{ +pub async fn listening_to_server(docker: &Docker, base_url: &str) -> Result<(), Box>{ let url = format!("{}/api/message", base_url); loop { // Replace with your server endpoint @@ -163,7 +168,7 @@ pub async fn listening_to_server(base_url: &str) -> Result<(), Box().await { - handle_message(msg).await; + handle_server_message(docker, msg).await; } else { eprintln!("Failed to parse message"); } @@ -174,31 +179,4 @@ pub async fn listening_to_server(base_url: &str) -> Result<(), Box ServerMessage { - match raw { - "restart" => ServerMessage::Restart, - msg if msg.starts_with("log:") => ServerMessage::Log(msg[4..].to_string()), - msg if msg.starts_with("update:") => ServerMessage::Update(msg[7..].to_string()), - _ => ServerMessage::Unknown, - } -} - -fn handle_message(msg: ServerMessage) { - match msg { - ServerMessage::Restart => restart_container(), - ServerMessage::Update(ver) => update_client(&ver), - ServerMessage::Unknown => eprintln!("Unknown message"), - } -} - -fn restart_container() { - println!("Restarting..."); - std::process::exit(1); // let Docker restart it -} - -fn update_client(version: &str) { - println!("Updating to version {}", version); -} - +} \ No newline at end of file diff --git a/WatcherAgent/src/main.rs b/WatcherAgent/src/main.rs index 8ccdb00..b1a84a5 100644 --- a/WatcherAgent/src/main.rs +++ b/WatcherAgent/src/main.rs @@ -5,6 +5,7 @@ pub mod api; pub mod hardware; pub mod metrics; pub mod models; +pub mod serverclientcomm; use std::env; use std::error::Error; diff --git a/WatcherAgent/src/serverclientcomm.rs b/WatcherAgent/src/serverclientcomm.rs new file mode 100644 index 0000000..3cb49b1 --- /dev/null +++ b/WatcherAgent/src/serverclientcomm.rs @@ -0,0 +1,60 @@ +use bollard::Docker; +use bollard::image::CreateImageOptions; +use bollard::container::{RestartContainerOptions}; + +pub fn parse_message(raw: &str) -> ServerMessage { + match raw { + "restart" => ServerMessage::Restart, + "update" => ServerMessage::Update, + msg if msg.starts_with("log:") => ServerMessage::Log(msg[4..].to_string()), + msg if msg.starts_with("update:") => ServerMessage::Update(msg[7..].to_string()), + _ => ServerMessage::Unknown, + } +} + +pub async fn handle_server_message(docker: &Docker, msg: ServerMessage) { + match msg { + ServerMessage::Update(version) => update_docker_image(docker, &version).await, + ServerMessage::Restart => restart_container(docker).await, + ServerMessage::Unknown => eprintln!("Unknown message"), + } +} + +pub async fn update_docker_image(docker: &Docker, image: &str) { + println!("Updating to {}", image); + + // 1. Pull new image + let mut stream = docker.create_image( + Some(CreateImageOptions { + from_image: image, + ..Default::default() + }), + None, + None, + ); + + while let Some(progress) = stream.try_next().await.unwrap_or(None) { + if let Some(status) = progress.status { + println!("Pull status: {}", status); + } + } + + // 2. Restart the current container + if let Ok(container_id) = std::env::var("HOSTNAME") { + println!("Restarting container: {}", container_id); + docker.restart_container(&container_id, Some(RestartContainerOptions { t: 0 })) + .await + .unwrap(); + } else { + eprintln!("No container ID found (HOSTNAME not set?)"); + } +} + +pub async fn restart_container(docker: &Docker) { + if let Ok(container_id) = std::env::var("HOSTNAME") { + println!("Restarting container {}", container_id); + docker.restart_container(&container_id, Some(RestartContainerOptions { t: 0 })) + .await + .unwrap(); + } +} diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..8aa2cb3 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,23 @@ +watcher-agent: + image: git.triggermeelmo.com/donpat1to/watcher-agent:development + container_name: watcher-agent + restart: always + privileged: true # Grants full hardware access (use with caution) + env_file: .env + pid: "host" + volumes: + # Mount critical system paths for hardware monitoring + - /sys:/sys:ro # CPU/GPU temps, sensors + - /proc:/proc # Process/CPU stats + - /dev:/dev:ro # Disk/GPU device access + - /var/run/docker.sock:/var/run/docker.sock # Docker API access + - /:/root:ro # Access to for df-command + # Application volumes + - ./config:/app/config:ro + - ./logs:/app/logs + network_mode: host # Uses host network (for correct IP/interface detection) + healthcheck: + test: ["CMD", "/usr/local/bin/WatcherAgent", "healthcheck"] + interval: 30s + timeout: 3s + retries: 3 \ No newline at end of file