added docker image update option

This commit is contained in:
2025-09-23 23:27:13 +02:00
parent 755617c86f
commit 83cb815e76
5 changed files with 96 additions and 32 deletions

View File

@@ -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"] }

View File

@@ -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<dyn Error + Send + Sync>> {
@@ -154,7 +159,7 @@ pub async fn send_metrics(
Ok(())
}
pub async fn listening_to_server(base_url: &str) -> Result<(), Box<dyn Error + Send + Sync>>{
pub async fn listening_to_server(docker: &Docker, base_url: &str) -> Result<(), Box<dyn Error + Send + Sync>>{
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<dyn Error + S
if let Ok(resp) = resp {
if let Ok(msg) = resp.json::<ServerMessage>().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<dyn Error + S
// Poll every 5 seconds (or use WebSocket for real-time)
sleep(Duration::from_secs(5)).await;
}
}
fn parse_message(raw: &str) -> 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);
}
}

View File

@@ -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;

View File

@@ -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();
}
}

23
docker-compose.yaml Normal file
View File

@@ -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