1use std::process::Command;23use crate::{4 command::CommandExt,5 db::{keys::list_hosts, secret::SecretDb, Db, DbData},6 nix::SYSTEMS_ATTRIBUTE,7};8use anyhow::Result;9use clap::Clap;10use log::{info, warn};1112#[derive(Clap)]13pub struct BuildSystems {14 15 #[clap(long, number_of_values = 1)]16 skip: Vec<String>,17 #[clap(subcommand)]18 subcommand: Option<Subcommand>,19}2021#[derive(Clap)]22enum Subcommand {23 24 Test,25 26 Boot,27 28 Switch,29}3031impl BuildSystems {32 pub fn run(self) -> Result<()> {33 let db = Db::new(".fleet")?;34 let hosts = list_hosts()?;35 let data = SecretDb::open(&db)?.generate_nix_data()?;3637 for host in hosts.iter() {38 if self.skip.contains(host) {39 warn!("Skipping host {}", host);40 continue;41 }42 info!("Building host {}", host);43 let built = tempfile::tempdir()?;44 Command::new("nix")45 .inherit_stdio()46 .arg("build")47 .arg(format!(48 "{}.{}.config.system.build.toplevel",49 SYSTEMS_ATTRIBUTE, host,50 ))51 .arg("--no-link")52 .arg("--out-link")53 .arg(built.path())54 .arg("--impure")55 .env("SECRET_DATA", data.clone())56 .run()?;57 info!("Uploading system closure");58 let full_path = std::fs::canonicalize(built.path())?;59 info!("{:?}", full_path);60 Command::new("nix")61 .inherit_stdio()62 .arg("copy")63 .arg(full_path)64 .arg("--to")65 .arg(format!("ssh://root@{}", host))66 .run()?;67 match self.subcommand {68 Some(Subcommand::Test) => {69 info!("Setting system to test")70 }71 Some(Subcommand::Boot) => {72 info!("Setting system to switch on boot")73 }74 Some(Subcommand::Switch) => {75 info!("Switching to configuration")76 }77 _ => {}78 }79 }80 Ok(())81 }82}