git.delta.rocks / jrsonnet / refs/commits / d58560c49134

difftreelog

refactor! disable sd-image module from sd-image target

Yaroslav Bolyukin2023-05-01parent: #15ef984.patch.diff
in: trunk

3 files changed

modifiedcmds/fleet/src/cmds/build_systems.rsdiffbeforeafterboth
before · cmds/fleet/src/cmds/build_systems.rs
1use std::{env::current_dir, process::Stdio, time::Duration};23use crate::{command::CommandExt, host::Config};4use anyhow::Result;5use clap::Parser;6use tokio::{process::Command, task::LocalSet, time::sleep};7use tracing::{error, field, info, info_span, warn, Instrument};89#[derive(Parser, Clone)]10pub struct BuildSystems {11	/// Do not continue on error12	#[clap(long)]13	fail_fast: bool,14	/// Run builds as sudo15	#[clap(long)]16	privileged_build: bool,17	#[clap(subcommand)]18	subcommand: Subcommand,19}2021enum UploadAction {22	Test,23	Boot,24	Switch,25}26impl UploadAction {27	fn name(&self) -> &'static str {28		match self {29			UploadAction::Test => "test",30			UploadAction::Boot => "boot",31			UploadAction::Switch => "switch",32		}33	}3435	pub(crate) fn should_switch_profile(&self) -> bool {36		matches!(self, Self::Switch | Self::Test)37	}38}3940enum PackageAction {41	SdImage,42	InstallationCd,43}44impl PackageAction {45	fn build_attr(&self) -> String {46		match self {47			PackageAction::SdImage => "sdImage".to_owned(),48			PackageAction::InstallationCd => "installationCd".to_owned(),49		}50	}51}5253enum Action {54	Upload { action: Option<UploadAction> },55	Package(PackageAction),56}57impl Action {58	fn build_attr(&self) -> String {59		match self {60			Action::Upload { .. } => "toplevel".to_owned(),61			Action::Package(p) => p.build_attr(),62		}63	}64}6566impl From<Subcommand> for Action {67	fn from(s: Subcommand) -> Self {68		match s {69			Subcommand::Upload => Self::Upload { action: None },70			Subcommand::Test => Self::Upload {71				action: Some(UploadAction::Test),72			},73			Subcommand::Boot => Self::Upload {74				action: Some(UploadAction::Boot),75			},76			Subcommand::Switch => Self::Upload {77				action: Some(UploadAction::Switch),78			},79			Subcommand::SdImage => Self::Package(PackageAction::SdImage),80			Subcommand::InstallationCd => Self::Package(PackageAction::InstallationCd),81		}82	}83}8485#[derive(Parser, Clone)]86enum Subcommand {87	/// Upload, but do not switch88	Upload,89	/// Upload + switch to built system until reboot90	Test,91	/// Upload + switch to built system after reboot92	Boot,93	/// Upload + test + boot94	Switch,9596	/// Build SD .img image97	SdImage,98	/// Build an installation cd ISO image99	InstallationCd,100}101102impl BuildSystems {103	async fn build_task(self, config: Config, host: String) -> Result<()> {104		info!("building");105		let action = Action::from(self.subcommand.clone());106		let built = {107			let dir = tempfile::tempdir()?;108			dir.path().to_owned()109		};110111		let mut nix_build = if self.privileged_build {112			let mut out = Command::new("sudo");113			out.arg("nix");114			out115		} else {116			Command::new("nix")117		};118		nix_build119			.args([120				"build",121				"--impure",122				"--json",123				// "--show-trace",124				"--no-link",125				"--out-link",126			])127			.arg(&built)128			.arg(129				config.configuration_attr_name(&format!(130					"buildSystems.{}.{host}",131					action.build_attr()132				)),133			)134			.args(&config.nix_args);135136		nix_build.run_nix().await?;137		let built = std::fs::canonicalize(built)?;138139		match action {140			Action::Upload { action } => {141				if !config.is_local(&host) {142					info!("uploading system closure");143					let mut tries = 0;144					loop {145						match Command::new("nix")146							.args(["copy", "--to"])147							.arg(format!("ssh://root@{}", host))148							.arg(&built)149							.inherit_stdio()150							.run_nix()151							.await152						{153							Ok(()) => break,154							Err(e) if tries < 3 => {155								tries += 1;156								warn!("Copy failure ({}/3): {}", tries, e);157								sleep(Duration::from_millis(5000)).await;158							}159							Err(e) => return Err(e),160						}161					}162				}163				if let Some(action) = action {164					if action.should_switch_profile() {165						info!("switching generation");166						config167							.command_on(&host, "nix-env", true)168							.args(["-p", "/nix/var/nix/profiles/system", "--set"])169							.arg(&built)170							.inherit_stdio()171							.run()172							.await?;173					}174					info!("executing activation script");175					let mut switch_script = built.clone();176					switch_script.push("bin");177					switch_script.push("switch-to-configuration");178					config179						.command_on(&host, switch_script, true)180						.arg(action.name())181						.stdout(Stdio::inherit())182						.run()183						.await?;184				}185			}186			Action::Package(PackageAction::SdImage) => {187				let mut out = current_dir()?;188				out.push(format!("sd-image-{}", host));189190				info!("building sd image to {:?}", out);191				let mut nix_build = if self.privileged_build {192					let mut out = Command::new("sudo");193					out.arg("nix");194					out195				} else {196					Command::new("nix")197				};198				nix_build199					.args(["build", "--impure", "--no-link", "--out-link"])200					.arg(&out)201					.arg(config.configuration_attr_name(&format!("buildSystems.sdImage.{}", host,)))202					.args(&config.nix_args);203				if !self.fail_fast {204					nix_build.arg("--keep-going");205				}206207				nix_build.inherit_stdio().run_nix().await?;208			}209			Action::Package(PackageAction::InstallationCd) => {210				let mut out = current_dir()?;211				out.push(format!("installation-cd-{}", host));212213				info!("building sd image to {:?}", out);214				let mut nix_build = if self.privileged_build {215					let mut out = Command::new("sudo");216					out.arg("nix");217					out218				} else {219					Command::new("nix")220				};221				nix_build222					.args(["build", "--impure", "--no-link", "--out-link"])223					.arg(&out)224					.arg(225						config.configuration_attr_name(&format!(226							"buildSystems.installationCd.{}",227							host,228						)),229					)230					.args(&config.nix_args);231				if !self.fail_fast {232					nix_build.arg("--keep-going");233				}234235				nix_build.inherit_stdio().run_nix().await?;236			}237		};238		Ok(())239	}240241	pub async fn run(self, config: &Config) -> Result<()> {242		let hosts = config.list_hosts().await?;243		let set = LocalSet::new();244		let this = &self;245		for host in hosts.iter() {246			if config.should_skip(host) {247				continue;248			}249			let config = config.clone();250			let host = host.clone();251			let this = this.clone();252			let span = info_span!("deployment", host = field::display(&host));253			set.spawn_local(254				(async move {255					match this.build_task(config, host).await {256						Ok(_) => {}257						Err(e) => {258							error!("failed to deploy host: {}", e)259						}260					}261				})262				.instrument(span),263			);264		}265		set.await;266		Ok(())267	}268}
after · cmds/fleet/src/cmds/build_systems.rs
1use std::{env::current_dir, process::Stdio, time::Duration};23use crate::{command::CommandExt, host::Config};4use anyhow::Result;5use clap::Parser;6use tokio::{process::Command, task::LocalSet, time::sleep};7use tracing::{error, field, info, info_span, warn, Instrument};89#[derive(Parser, Clone)]10pub struct BuildSystems {11	/// Do not continue on error12	#[clap(long)]13	fail_fast: bool,14	/// Run builds as sudo15	#[clap(long)]16	privileged_build: bool,17	#[clap(subcommand)]18	subcommand: Subcommand,19}2021enum UploadAction {22	Test,23	Boot,24	Switch,25}26impl UploadAction {27	fn name(&self) -> &'static str {28		match self {29			UploadAction::Test => "test",30			UploadAction::Boot => "boot",31			UploadAction::Switch => "switch",32		}33	}3435	pub(crate) fn should_switch_profile(&self) -> bool {36		matches!(self, Self::Switch | Self::Test)37	}38}3940enum PackageAction {41	SdImage,42	InstallationCd,43}44impl PackageAction {45	fn build_attr(&self) -> String {46		match self {47			PackageAction::SdImage => "sdImage".to_owned(),48			PackageAction::InstallationCd => "installationCd".to_owned(),49		}50	}51}5253enum Action {54	Upload { action: Option<UploadAction> },55	Package(PackageAction),56}57impl Action {58	fn build_attr(&self) -> String {59		match self {60			Action::Upload { .. } => "toplevel".to_owned(),61			Action::Package(p) => p.build_attr(),62		}63	}64}6566impl From<Subcommand> for Action {67	fn from(s: Subcommand) -> Self {68		match s {69			Subcommand::Upload => Self::Upload { action: None },70			Subcommand::Test => Self::Upload {71				action: Some(UploadAction::Test),72			},73			Subcommand::Boot => Self::Upload {74				action: Some(UploadAction::Boot),75			},76			Subcommand::Switch => Self::Upload {77				action: Some(UploadAction::Switch),78			},79			Subcommand::SdImage => Self::Package(PackageAction::SdImage),80			Subcommand::InstallationCd => Self::Package(PackageAction::InstallationCd),81		}82	}83}8485#[derive(Parser, Clone)]86enum Subcommand {87	/// Upload, but do not switch88	Upload,89	/// Upload + switch to built system until reboot90	Test,91	/// Upload + switch to built system after reboot92	Boot,93	/// Upload + test + boot94	Switch,9596	/// Build SD .img image97	SdImage,98	/// Build an installation cd ISO image99	InstallationCd,100}101102impl BuildSystems {103	async fn build_task(self, config: Config, host: String) -> Result<()> {104		info!("building");105		let action = Action::from(self.subcommand.clone());106		let built = {107			let dir = tempfile::tempdir()?;108			dir.path().to_owned()109		};110111		let mut nix_build = if self.privileged_build {112			let mut out = Command::new("sudo");113			out.arg("nix");114			out115		} else {116			Command::new("nix")117		};118		nix_build119			.args([120				"build",121				"--impure",122				"--json",123				// "--show-trace",124				"--no-link",125				"--out-link",126			])127			.arg(&built)128			.arg(129				config.configuration_attr_name(&format!(130					"buildSystems.{}.{host}",131					action.build_attr()132				)),133			)134			.args(&config.nix_args);135136		nix_build.run_nix().await.map_err(|e| {137			if action.build_attr() == "sdImage" {138				info!("sd-image build failed");139				info!("Make sure you have imported modulesPath/installer/sd-card/sd-image-<arch>[-installer].nix (For installer, you may want to check config)");140				info!("This module was automatically imported before, but was removed for better customization")141			}142			e143		})?;144		let built = std::fs::canonicalize(built)?;145146		match action {147			Action::Upload { action } => {148				if !config.is_local(&host) {149					info!("uploading system closure");150					let mut tries = 0;151					loop {152						match Command::new("nix")153							.args(["copy", "--to"])154							.arg(format!("ssh://root@{}", host))155							.arg(&built)156							.inherit_stdio()157							.run_nix()158							.await159						{160							Ok(()) => break,161							Err(e) if tries < 3 => {162								tries += 1;163								warn!("Copy failure ({}/3): {}", tries, e);164								sleep(Duration::from_millis(5000)).await;165							}166							Err(e) => return Err(e),167						}168					}169				}170				if let Some(action) = action {171					if action.should_switch_profile() {172						info!("switching generation");173						config174							.command_on(&host, "nix-env", true)175							.args(["-p", "/nix/var/nix/profiles/system", "--set"])176							.arg(&built)177							.inherit_stdio()178							.run()179							.await?;180					}181					info!("executing activation script");182					let mut switch_script = built.clone();183					switch_script.push("bin");184					switch_script.push("switch-to-configuration");185					config186						.command_on(&host, switch_script, true)187						.arg(action.name())188						.stdout(Stdio::inherit())189						.run()190						.await?;191				}192			}193			Action::Package(PackageAction::SdImage) => {194				let mut out = current_dir()?;195				out.push(format!("sd-image-{}", host));196197				info!("building sd image to {:?}", out);198				let mut nix_build = if self.privileged_build {199					let mut out = Command::new("sudo");200					out.arg("nix");201					out202				} else {203					Command::new("nix")204				};205				nix_build206					.args(["build", "--impure", "--no-link", "--out-link"])207					.arg(&out)208					.arg(config.configuration_attr_name(&format!("buildSystems.sdImage.{}", host,)))209					.args(&config.nix_args);210				if !self.fail_fast {211					nix_build.arg("--keep-going");212				}213214				nix_build.inherit_stdio().run_nix().await?;215			}216			Action::Package(PackageAction::InstallationCd) => {217				let mut out = current_dir()?;218				out.push(format!("installation-cd-{}", host));219220				info!("building sd image to {:?}", out);221				let mut nix_build = if self.privileged_build {222					let mut out = Command::new("sudo");223					out.arg("nix");224					out225				} else {226					Command::new("nix")227				};228				nix_build229					.args(["build", "--impure", "--no-link", "--out-link"])230					.arg(&out)231					.arg(232						config.configuration_attr_name(&format!(233							"buildSystems.installationCd.{}",234							host,235						)),236					)237					.args(&config.nix_args);238				if !self.fail_fast {239					nix_build.arg("--keep-going");240				}241242				nix_build.inherit_stdio().run_nix().await?;243			}244		};245		Ok(())246	}247248	pub async fn run(self, config: &Config) -> Result<()> {249		let hosts = config.list_hosts().await?;250		let set = LocalSet::new();251		let this = &self;252		for host in hosts.iter() {253			if config.should_skip(host) {254				continue;255			}256			let config = config.clone();257			let host = host.clone();258			let this = this.clone();259			let span = info_span!("deployment", host = field::display(&host));260			set.spawn_local(261				(async move {262					match this.build_task(config, host).await {263						Ok(_) => {}264						Err(e) => {265							error!("failed to deploy host: {}", e)266						}267					}268				})269				.instrument(span),270			);271		}272		set.await;273		Ok(())274	}275}
modifiedlib/default.nixdiffbeforeafterboth
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -53,13 +53,21 @@
         inherit configuredHosts configuredSecrets configuredSystems;
         configUnchecked = root.config;
         buildSystems = {
-          toplevel = builtins.mapAttrs (_name: value: value.config.system.build.toplevel) (configuredSystemsWithExtraModules [ ]);
+          toplevel = builtins.mapAttrs (_name: value: value.config.system.build.toplevel) (configuredSystemsWithExtraModules [
+            ({...}: {
+              buildTarget = "toplevel";
+            })
+          ]);
           sdImage = builtins.mapAttrs (_name: value: value.config.system.build.sdImage) (configuredSystemsWithExtraModules [
-            (nixpkgs + "/nixos/modules/installer/sd-card/sd-image-aarch64-installer.nix")
+            #(nixpkgs + "/nixos/modules/installer/sd-card/sd-image-aarch64-installer.nix")
+            ({...}: {
+              buildTarget = "sd-image";
+            })
           ]);
           installationCd = builtins.mapAttrs (_name: value: value.config.system.build.isoImage) (configuredSystemsWithExtraModules [
             (nixpkgs + "/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix")
             ({ lib, ... }: {
+              buildTarget = "installation-cd";
               # Needed for https://github.com/NixOS/nixpkgs/issues/58959
               boot.supportedFilesystems = lib.mkForce [ "btrfs" "reiserfs" "vfat" "f2fs" "xfs" "ntfs" "cifs" ];
             })
modifiednixos/meta.nixdiffbeforeafterboth
--- a/nixos/meta.nix
+++ b/nixos/meta.nix
@@ -24,6 +24,9 @@
       };
       description = "Network definition of host";
     };
+    buildTarget = mkOption {
+      type = enum ["toplevel" "sd-image" "installation-cd"];
+    };
   };
   config = {
     tags = [ "all" ];