diff --git a/agent/src/agent.rs b/agent/src/agent.rs index c061d88..a50ee56 100644 --- a/agent/src/agent.rs +++ b/agent/src/agent.rs @@ -232,9 +232,9 @@ impl Agent { error!("Failed to execute service control: {}", e); } } - AgentCommand::SystemRebuild { nixos_path } => { - info!("Processing SystemRebuild command with path: {}", nixos_path); - if let Err(e) = self.handle_system_rebuild(&nixos_path).await { + AgentCommand::SystemRebuild { git_url, git_branch, working_dir } => { + info!("Processing SystemRebuild command: {} @ {} -> {}", git_url, git_branch, working_dir); + if let Err(e) = self.handle_system_rebuild(&git_url, &git_branch, &working_dir).await { error!("Failed to execute system rebuild: {}", e); } } @@ -281,9 +281,9 @@ impl Agent { Ok(()) } - /// Handle NixOS system rebuild commands - async fn handle_system_rebuild(&self, nixos_path: &str) -> Result<()> { - info!("Starting NixOS system rebuild from path: {}", nixos_path); + /// Handle NixOS system rebuild commands with git clone approach + async fn handle_system_rebuild(&self, git_url: &str, git_branch: &str, working_dir: &str) -> Result<()> { + info!("Starting NixOS system rebuild: {} @ {} -> {}", git_url, git_branch, working_dir); // Enable maintenance mode before rebuild let maintenance_file = "/tmp/cm-maintenance"; @@ -293,15 +293,23 @@ impl Agent { info!("Maintenance mode enabled"); } - // Change to nixos directory and execute rebuild as cm user - let output = tokio::process::Command::new("sudo") - .arg("-u") - .arg("cm") - .arg("nixos-rebuild") - .arg("switch") - .current_dir(nixos_path) - .output() - .await; + // Clone or update repository + let git_result = self.ensure_git_repository(git_url, git_branch, working_dir).await; + + // Execute nixos-rebuild if git operation succeeded + let rebuild_result = if git_result.is_ok() { + info!("Git repository ready, executing nixos-rebuild"); + tokio::process::Command::new("sudo") + .arg("-u") + .arg("cm") + .arg("nixos-rebuild") + .arg("switch") + .current_dir(working_dir) + .output() + .await + } else { + return git_result.and_then(|_| unreachable!()); + }; // Always try to remove maintenance mode file if let Err(e) = tokio::fs::remove_file(maintenance_file).await { @@ -313,7 +321,7 @@ impl Agent { } // Check rebuild result - match output { + match rebuild_result { Ok(output) => { if output.status.success() { info!("NixOS rebuild completed successfully"); @@ -335,4 +343,54 @@ impl Agent { info!("System rebuild completed, triggering metric refresh"); Ok(()) } + + /// Ensure git repository is cloned and up to date + async fn ensure_git_repository(&self, git_url: &str, git_branch: &str, working_dir: &str) -> Result<()> { + use std::path::Path; + + let git_dir = Path::new(working_dir).join(".git"); + + if git_dir.exists() { + info!("Git repository exists, updating to latest {}", git_branch); + + // Pull latest changes + let output = tokio::process::Command::new("git") + .arg("pull") + .arg("origin") + .arg(git_branch) + .current_dir(working_dir) + .output() + .await?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + error!("Git pull failed: {}", stderr); + return Err(anyhow::anyhow!("Git pull failed: {}", stderr)); + } + + info!("Git repository updated successfully"); + } else { + info!("Cloning git repository from {} (branch: {})", git_url, git_branch); + + // Clone repository + let output = tokio::process::Command::new("git") + .arg("clone") + .arg("--branch") + .arg(git_branch) + .arg(git_url) + .arg(working_dir) + .output() + .await?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + error!("Git clone failed: {}", stderr); + return Err(anyhow::anyhow!("Git clone failed: {}", stderr)); + } + + info!("Git repository cloned successfully"); + } + + Ok(()) + } } diff --git a/agent/src/communication/mod.rs b/agent/src/communication/mod.rs index 728af74..4a5a3c2 100644 --- a/agent/src/communication/mod.rs +++ b/agent/src/communication/mod.rs @@ -106,7 +106,9 @@ pub enum AgentCommand { }, /// Rebuild NixOS system SystemRebuild { - nixos_path: String, // Path to nixosbox directory + git_url: String, + git_branch: String, + working_dir: String, }, } diff --git a/dashboard/src/app.rs b/dashboard/src/app.rs index e4eccd4..ffaea83 100644 --- a/dashboard/src/app.rs +++ b/dashboard/src/app.rs @@ -22,6 +22,7 @@ pub struct Dashboard { terminal: Option>>, headless: bool, initial_commands_sent: std::collections::HashSet, + config: DashboardConfig, } impl Dashboard { @@ -132,6 +133,7 @@ impl Dashboard { terminal, headless, initial_commands_sent: std::collections::HashSet::new(), + config, }) } @@ -297,8 +299,10 @@ impl Dashboard { } UiCommand::SystemRebuild { hostname } => { info!("Sending system rebuild command to {}", hostname); - let agent_command = AgentCommand::SystemRebuild { - nixos_path: "/home/cm/nixosbox".to_string(), // Fixed path per requirements + let agent_command = AgentCommand::SystemRebuild { + git_url: self.config.system.nixos_config_git_url.clone(), + git_branch: self.config.system.nixos_config_branch.clone(), + working_dir: self.config.system.nixos_config_working_dir.clone(), }; self.zmq_command_sender.send_command(&hostname, agent_command).await?; } diff --git a/dashboard/src/communication/mod.rs b/dashboard/src/communication/mod.rs index 669074c..768fdf1 100644 --- a/dashboard/src/communication/mod.rs +++ b/dashboard/src/communication/mod.rs @@ -23,7 +23,9 @@ pub enum AgentCommand { }, /// Rebuild NixOS system SystemRebuild { - nixos_path: String, // Path to nixosbox directory + git_url: String, + git_branch: String, + working_dir: String, }, } diff --git a/dashboard/src/config/mod.rs b/dashboard/src/config/mod.rs index 3d23519..a276587 100644 --- a/dashboard/src/config/mod.rs +++ b/dashboard/src/config/mod.rs @@ -7,6 +7,7 @@ use std::path::Path; pub struct DashboardConfig { pub zmq: ZmqConfig, pub hosts: HostsConfig, + pub system: SystemConfig, } /// ZMQ consumer configuration @@ -21,6 +22,14 @@ pub struct HostsConfig { pub predefined_hosts: Vec, } +/// System configuration +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SystemConfig { + pub nixos_config_git_url: String, + pub nixos_config_branch: String, + pub nixos_config_working_dir: String, +} + impl DashboardConfig { pub fn load_from_file>(path: P) -> Result { let path = path.as_ref();