Agent restarts yggdrasil on changes

This commit is contained in:
Ultradesu
2025-08-26 15:01:28 +03:00
parent 4a30b441ca
commit 4bf349bfe3
2 changed files with 49 additions and 21 deletions

View File

@@ -285,7 +285,7 @@ async fn handle_server_message(msg: ServerMessage, ygg_config_path: &str, no_res
// Apply full configuration update to Yggdrasil // Apply full configuration update to Yggdrasil
match update_yggdrasil_config_full(ygg_config_path, &listen, &peers, &allowed_public_keys).await { match update_yggdrasil_config_full(ygg_config_path, &listen, &peers, &allowed_public_keys).await {
Ok(_) => { Ok(true) => {
info!("Configuration update successfully applied to {}", ygg_config_path); info!("Configuration update successfully applied to {}", ygg_config_path);
// Restart Yggdrasil service to apply updated configuration // Restart Yggdrasil service to apply updated configuration
if !no_restart { if !no_restart {
@@ -296,6 +296,9 @@ async fn handle_server_message(msg: ServerMessage, ygg_config_path: &str, no_res
info!("Skipping service restart (--no-restart flag set)"); info!("Skipping service restart (--no-restart flag set)");
} }
}, },
Ok(false) => {
info!("Configuration unchanged, skipping restart");
},
Err(e) => error!("Failed to update Yggdrasil config: {}", e), Err(e) => error!("Failed to update Yggdrasil config: {}", e),
} }
} }
@@ -444,15 +447,29 @@ async fn update_yggdrasil_config_full(
listen: &[String], listen: &[String],
peers: &[String], peers: &[String],
allowed_public_keys: &[String] allowed_public_keys: &[String]
) -> Result<()> { ) -> Result<bool> { // Returns true if config was updated
// Read current config // Read current config
let current_config = tokio::fs::read_to_string(config_path).await?; let current_config = tokio::fs::read_to_string(config_path).await?;
let mut config: serde_json::Value = serde_json::from_str(&current_config)?; let mut config: serde_json::Value = serde_json::from_str(&current_config)?;
// Check if config actually changed
let old_listen = config["Listen"].clone();
let old_peers = config["Peers"].clone();
let old_keys = config["AllowedPublicKeys"].clone();
let new_listen = serde_json::json!(listen);
let new_peers = serde_json::json!(peers);
let new_keys = serde_json::json!(allowed_public_keys);
if old_listen == new_listen && old_peers == new_peers && old_keys == new_keys {
debug!("Configuration unchanged, skipping update");
return Ok(false);
}
// Update listen, peers and allowed public keys // Update listen, peers and allowed public keys
config["Listen"] = serde_json::json!(listen); config["Listen"] = new_listen;
config["Peers"] = serde_json::json!(peers); config["Peers"] = new_peers;
config["AllowedPublicKeys"] = serde_json::json!(allowed_public_keys); config["AllowedPublicKeys"] = new_keys;
// Write updated config back // Write updated config back
let updated_config = serde_json::to_string_pretty(&config)?; let updated_config = serde_json::to_string_pretty(&config)?;
@@ -461,7 +478,7 @@ async fn update_yggdrasil_config_full(
match tokio::fs::write(config_path, &updated_config).await { match tokio::fs::write(config_path, &updated_config).await {
Ok(_) => { Ok(_) => {
info!("Yggdrasil configuration fully updated in {}", config_path); info!("Yggdrasil configuration fully updated in {}", config_path);
Ok(()) Ok(true)
} }
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => { Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
// Try with sudo if permission denied // Try with sudo if permission denied
@@ -491,7 +508,7 @@ async fn update_yggdrasil_config_full(
} }
info!("Yggdrasil configuration fully updated in {} with sudo", config_path); info!("Yggdrasil configuration fully updated in {} with sudo", config_path);
Ok(()) Ok(true)
} }
Err(e) => Err(anyhow!("Failed to write configuration: {}", e)) Err(e) => Err(anyhow!("Failed to write configuration: {}", e))
} }

View File

@@ -150,21 +150,32 @@ pub async fn handle_agent_socket(
// Get current node information // Get current node information
if let Some(current_node) = node_manager.get_node_by_id(id).await { if let Some(current_node) = node_manager.get_node_by_id(id).await {
// Update node with new addresses // Sort addresses for comparison to avoid false positives
match node_manager.update_node( let mut new_addresses = addresses.clone();
id, new_addresses.sort();
current_node.name.clone(), let mut current_addresses = current_node.addresses.clone();
current_node.listen.clone(), current_addresses.sort();
addresses
).await { // Only update if addresses actually changed
Ok(_) => { if new_addresses != current_addresses {
info!("Updated addresses for node {}", id); // Update node with new addresses
// Broadcast configuration update to all agents match node_manager.update_node(
crate::websocket_state::broadcast_configuration_update(&node_manager).await; id,
} current_node.name.clone(),
Err(e) => { current_node.listen.clone(),
error!("Failed to update addresses for node {}: {}", id, e); addresses
).await {
Ok(_) => {
info!("Updated addresses for node {}", id);
// Broadcast configuration update to all agents
crate::websocket_state::broadcast_configuration_update(&node_manager).await;
}
Err(e) => {
error!("Failed to update addresses for node {}: {}", id, e);
}
} }
} else {
debug!("Address list unchanged for node {}, skipping update", id);
} }
} else { } else {
warn!("Cannot update addresses for unknown node: {}", id); warn!("Cannot update addresses for unknown node: {}", id);