Implement git clone approach for nixos-rebuild
Replace direct directory access with git clone/pull approach: - Add git configuration options (url, branch, working_dir) to NixOS module - Update SystemConfig and AgentCommand to use git parameters - Implement ensure_git_repository() method for clone/pull operations - Agent clones nixosbox to /var/lib/cm-dashboard/nixos-config - Maintains security while solving permission denied issues The agent now manages its own copy of the configuration without needing access to /home/cm directory.
This commit is contained in:
parent
864cafd61f
commit
b3c67f4b7f
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ pub struct Dashboard {
|
||||
terminal: Option<Terminal<CrosstermBackend<io::Stdout>>>,
|
||||
headless: bool,
|
||||
initial_commands_sent: std::collections::HashSet<String>,
|
||||
config: DashboardConfig,
|
||||
}
|
||||
|
||||
impl Dashboard {
|
||||
@ -132,6 +133,7 @@ impl Dashboard {
|
||||
terminal,
|
||||
headless,
|
||||
initial_commands_sent: std::collections::HashSet::new(),
|
||||
config,
|
||||
})
|
||||
}
|
||||
|
||||
@ -298,7 +300,9 @@ 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
|
||||
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?;
|
||||
}
|
||||
|
||||
@ -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,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -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<String>,
|
||||
}
|
||||
|
||||
/// 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<P: AsRef<Path>>(path: P) -> Result<Self> {
|
||||
let path = path.as_ref();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user