git.delta.rocks / jrsonnet / refs/commits / 238480b57dc1

difftreelog

refactor(build-systems) host abstraction

Yaroslav Bolyukin2021-02-07parent: #29a1aae.patch.diff
in: trunk

1 file changed

modifiedsrc/cmds/build_systems.rsdiffbeforeafterboth
before · src/cmds/build_systems.rs
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)]13#[clap(group = clap::ArgGroup::new("target"))]14pub struct BuildSystems {15	/// Hosts to skip16	#[clap(long, number_of_values = 1, group = "target")]17	skip: Vec<String>,18	/// Hosts to build19	#[clap(long, number_of_values = 1, group = "target")]20	only: Vec<String>,21	/// Host, which should be threaten as localhost22	#[clap(long, env = "FLEET_LOCALHOST")]23	localhost: Option<String>,24	/// --builders arg for nix25	#[clap(long)]26	builders: Option<String>,27	/// Jobs to run locally28	#[clap(long)]29	jobs: Option<usize>,30	/// Do not continue on error31	#[clap(long)]32	fail_fast: bool,33	#[clap(subcommand)]34	subcommand: Option<Subcommand>,35}3637#[derive(Clap)]38enum Subcommand {39	/// Switch to built system until reboot40	Test,41	/// Switch to built system after reboot42	Boot,43	/// test + boot44	Switch,45}46impl Subcommand {47	fn should_switch_profile(&self) -> bool {48		matches!(self, Self::Test | Self::Switch)49	}50	fn name(&self) -> &'static str {51		match self {52			Self::Test => "test",53			Self::Boot => "boot",54			Self::Switch => "switch",55		}56	}57}5859impl BuildSystems {60	pub fn run(self) -> Result<()> {61		let db = Db::new(".fleet")?;62		let hosts = list_hosts()?;63		let data = SecretDb::open(&db)?.generate_nix_data()?;6465		for host in hosts.iter() {66			if self.only.len() > 0 && !self.only.contains(host) || self.skip.contains(host) {67				warn!("Skipping host {}", host);68				continue;69			}70			let is_local = Some(host) == self.localhost.as_ref();71			info!("Building host {}", host);72			let built = {73				let dir = tempfile::tempdir()?;74				dir.path().to_owned()75			};7677			let mut nix_build = Command::new("nix");78			nix_build79				.args(&["build", "--impure", "--no-link", "--out-link"])80				.arg(&built)81				.arg(format!(82					"{}.{}.config.system.build.toplevel",83					SYSTEMS_ATTRIBUTE, host,84				))85				.env("SECRET_DATA", data.clone());8687			if let Some(builders) = &self.builders {88				println!("Using builders: {}", builders);89				nix_build.arg("--builders").arg(builders);90			}91			if let Some(jobs) = &self.jobs {92				nix_build.arg("--max-jobs");93				nix_build.arg(format!("{}", jobs));94			}95			if !self.fail_fast {96				nix_build.arg("--keep-going");97			}9899			nix_build.inherit_stdio().run()?;100			let built = std::fs::canonicalize(built)?;101			info!("Built closure: {:?}", built);102			if !is_local {103				info!("Uploading system closure");104				Command::new("nix")105					.args(&["copy", "--to"])106					.arg(format!("ssh://root@{}", host))107					.arg(&built)108					.inherit_stdio()109					.run()?;110			}111			if let Some(subcommand) = &self.subcommand {112				if subcommand.should_switch_profile() {113					info!("Switching generation");114					if !is_local {115						Command::ssh_on(host, "sudo")116					} else {117						Command::new("sudo")118					}119					.args(&["nix-env", "-p", "/nix/var/nix/profiles/system", "--set"])120					.arg(&built)121					.inherit_stdio()122					.run()?;123				}124				info!("Executing activation script");125				let mut switch_script = built.clone();126				switch_script.push("bin");127				switch_script.push("switch-to-configuration");128				info!("{:?}", switch_script);129				if !is_local {130					Command::ssh_on(host, "sudo")131				} else {132					Command::new("sudo")133				}134				.arg(switch_script)135				.arg(subcommand.name())136				.inherit_stdio()137				.run()?;138			}139		}140		Ok(())141	}142}
after · src/cmds/build_systems.rs
1use std::process::Command;23use crate::{4	command::CommandExt,5	db::{secret::SecretDb, Db, DbData},6	host::FleetOpts,7	nix::SYSTEMS_ATTRIBUTE,8};9use anyhow::Result;10use clap::Clap;11use log::{info, warn};1213#[derive(Clap)]14#[clap(group = clap::ArgGroup::new("target"))]15pub struct BuildSystems {16	#[clap(flatten)]17	fleet_opts: FleetOpts,18	/// --builders arg for nix19	#[clap(long)]20	builders: Option<String>,21	/// Jobs to run locally22	#[clap(long)]23	jobs: Option<usize>,24	/// Do not continue on error25	#[clap(long)]26	fail_fast: bool,27	#[clap(long)]28	privileged_build: bool,29	#[clap(subcommand)]30	subcommand: Option<Subcommand>,31}3233#[derive(Clap)]34enum Subcommand {35	/// Switch to built system until reboot36	Test,37	/// Switch to built system after reboot38	Boot,39	/// test + boot40	Switch,41}42impl Subcommand {43	fn should_switch_profile(&self) -> bool {44		matches!(self, Self::Test | Self::Switch)45	}46	fn name(&self) -> &'static str {47		match self {48			Self::Test => "test",49			Self::Boot => "boot",50			Self::Switch => "switch",51		}52	}53}5455impl BuildSystems {56	pub fn run(self) -> Result<()> {57		let fleet = self.fleet_opts.build()?;58		let db = Db::new(".fleet")?;59		let hosts = fleet.list_hosts()?;60		let data = SecretDb::open(&db)?.generate_nix_data()?;6162		for host in hosts.iter() {63			if host.skip() {64				warn!("Skipping host {}", host.hostname);65				continue;66			}67			info!("Building host {}", host.hostname);68			let built = {69				let dir = tempfile::tempdir()?;70				dir.path().to_owned()71			};7273			let mut nix_build = if self.privileged_build {74				let mut out = Command::new("sudo");75				out.arg("nix");76				out77			} else {78				Command::new("nix")79			};80			nix_build81				.args(&["build", "--impure", "--no-link", "--out-link"])82				.arg(&built)83				.arg(format!(84					"{}.{}.config.system.build.toplevel",85					SYSTEMS_ATTRIBUTE, host.hostname,86				))87				.env("SECRET_DATA", data.clone());8889			if let Some(builders) = &self.builders {90				println!("Using builders: {}", builders);91				nix_build.arg("--builders").arg(builders);92			}93			if let Some(jobs) = &self.jobs {94				nix_build.arg("--max-jobs");95				nix_build.arg(format!("{}", jobs));96			}97			if !self.fail_fast {98				nix_build.arg("--keep-going");99			}100101			nix_build.inherit_stdio().run()?;102			let built = std::fs::canonicalize(built)?;103			info!("Built closure: {:?}", built);104			if !host.is_local() {105				info!("Uploading system closure");106				Command::new("nix")107					.args(&["copy", "--to"])108					.arg(format!("ssh://root@{}", host.hostname))109					.arg(&built)110					.inherit_stdio()111					.run()?;112			}113			if let Some(subcommand) = &self.subcommand {114				if subcommand.should_switch_profile() {115					info!("Switching generation");116					host.command_on("nix-env", true)117						.args(&["-p", "/nix/var/nix/profiles/system", "--set"])118						.arg(&built)119						.inherit_stdio()120						.run()?;121				}122				info!("Executing activation script");123				let mut switch_script = built.clone();124				switch_script.push("bin");125				switch_script.push("switch-to-configuration");126				info!("{:?}", switch_script);127				host.command_on(switch_script, true)128					.arg(subcommand.name())129					.inherit_stdio()130					.run()?;131			}132		}133		Ok(())134	}135}