--- a/cmds/fleet/src/cmds/build_systems.rs +++ b/cmds/fleet/src/cmds/build_systems.rs @@ -1,4 +1,4 @@ -use std::process::Command; +use std::{env::current_dir, process::Command}; use crate::{command::CommandExt, host::Config, nix::SYSTEMS_ATTRIBUTE}; use anyhow::Result; @@ -19,31 +19,64 @@ #[structopt(long)] privileged_build: bool, #[structopt(subcommand)] - subcommand: Option, + subcommand: Subcommand, } -#[derive(StructOpt)] -enum Subcommand { - /// Switch to built system until reboot +enum UploadAction { Test, - /// Switch to built system after reboot Boot, - /// test + boot Switch, } -impl Subcommand { - fn should_switch_profile(&self) -> bool { - matches!(self, Self::Test | Self::Switch) - } +impl UploadAction { fn name(&self) -> &'static str { match self { - Self::Test => "test", - Self::Boot => "boot", - Self::Switch => "switch", + UploadAction::Test => "test", + UploadAction::Boot => "boot", + UploadAction::Switch => "switch", + } + } + + pub(crate) fn should_switch_profile(&self) -> bool { + matches!(self, Self::Switch | Self::Test) + } +} + +enum PackageAction { + SdImage, +} + +enum Action { + Upload(Option), + Package(PackageAction), +} + +impl From for Action { + fn from(s: Subcommand) -> Self { + match s { + Subcommand::Upload => Self::Upload(None), + Subcommand::Test => Self::Upload(Some(UploadAction::Test)), + Subcommand::Boot => Self::Upload(Some(UploadAction::Boot)), + Subcommand::Switch => Self::Upload(Some(UploadAction::Switch)), + Subcommand::SdImage => Self::Package(PackageAction::SdImage), } } } +#[derive(StructOpt, Clone)] +enum Subcommand { + /// Upload, but do not switch + Upload, + /// Upload + switch to built system until reboot + Test, + /// Upload + switch to built system after reboot + Boot, + /// Upload + test + boot + Switch, + + /// Build sd image + SdImage, +} + impl BuildSystems { pub fn run(self, config: &Config) -> Result<()> { let hosts = config.list_hosts()?; @@ -87,35 +120,74 @@ nix_build.inherit_stdio().run()?; let built = std::fs::canonicalize(built)?; info!("Built closure: {:?}", built); - if !config.is_local(host) { - info!("Uploading system closure"); - Command::new("nix") - .args(&["copy", "--to"]) - .arg(format!("ssh://root@{}", host)) - .arg(&built) - .inherit_stdio() - .run()?; - } - if let Some(subcommand) = &self.subcommand { - if subcommand.should_switch_profile() { - info!("Switching generation"); - config - .command_on(host, "nix-env", true) - .args(&["-p", "/nix/var/nix/profiles/system", "--set"]) - .arg(&built) - .inherit_stdio() - .run()?; + + let action = Action::from(self.subcommand.clone()); + + match action { + Action::Upload(action) => { + if !config.is_local(host) { + info!("Uploading system closure"); + Command::new("nix") + .args(&["copy", "--to"]) + .arg(format!("ssh://root@{}", host)) + .arg(&built) + .inherit_stdio() + .run()?; + } + if let Some(action) = action { + if action.should_switch_profile() { + info!("Switching generation"); + config + .command_on(host, "nix-env", true) + .args(&["-p", "/nix/var/nix/profiles/system", "--set"]) + .arg(&built) + .inherit_stdio() + .run()?; + } + info!("Executing activation script"); + let mut switch_script = built.clone(); + switch_script.push("bin"); + switch_script.push("switch-to-configuration"); + config + .command_on(host, switch_script, true) + .arg(action.name()) + .inherit_stdio() + .run()?; + } + } + Action::Package(PackageAction::SdImage) => { + let mut out = current_dir()?; + out.push(format!("sd-image-{}", host)); + + info!("Building sd image to {:?}", out); + let mut nix_build = if self.privileged_build { + let mut out = Command::new("sudo"); + out.arg("nix"); + out + } else { + Command::new("nix") + }; + nix_build + .args(&["build", "--impure", "--no-link", "--out-link"]) + .arg(&out) + .arg(format!( + "{}.{}.config.system.build.sdImage", + SYSTEMS_ATTRIBUTE, host, + )); + if let Some(builders) = &self.builders { + nix_build.arg("--builders").arg(builders); + } + if let Some(jobs) = &self.jobs { + nix_build.arg("--max-jobs"); + nix_build.arg(format!("{}", jobs)); + } + if !self.fail_fast { + nix_build.arg("--keep-going"); + } + + nix_build.inherit_stdio().run()?; } - info!("Executing activation script"); - let mut switch_script = built.clone(); - switch_script.push("bin"); - switch_script.push("switch-to-configuration"); - config - .command_on(host, switch_script, true) - .arg(subcommand.name()) - .inherit_stdio() - .run()?; - } + }; } Ok(()) } --- a/lib/default.nix +++ b/lib/default.nix @@ -22,8 +22,10 @@ inherit name; value = nixpkgs.lib.nixosSystem { system = configuredHosts.${name}.system; - modules = configuredHosts.${name}.modules; - pkgs = import nixpkgs { system = configuredHosts.${name}.system; }; + modules = configuredHosts.${name}.modules ++ ( + if configuredHosts.${name}.system == "aarch64-linux" then [ (nixpkgs + "/nixos/modules/installer/sd-card/sd-image-aarch64-installer.nix") ] + else [ ] + ); }; } ) --- a/modules/nixos/fleetPkgs.nix +++ b/modules/nixos/fleetPkgs.nix @@ -1 +1,3 @@ -{ ... }: { nixpkgs.overlays = [ (import ../../pkgs) ]; } +{ ... }: { + nixpkgs.overlays = [ (import ../../pkgs) ]; +}