git.delta.rocks / jrsonnet / refs/commits / 81e3c77f96ff

difftreelog

feat parallel host builds

Yaroslav Bolyukin2021-12-26parent: #6a5196a.patch.diff
in: trunk

6 files changed

modifiedcmds/fleet/src/cmds/build_systems.rsdiffbeforeafterboth
1use std::{env::current_dir, time::Duration};1use std::{env::current_dir, time::Duration};
22
3use crate::{command::CommandExt, host::Config, nix::SYSTEMS_ATTRIBUTE};3use crate::{command::CommandExt, host::Config};
4use anyhow::Result;4use anyhow::Result;
5use structopt::StructOpt;5use structopt::StructOpt;
6use tokio::{process::Command, task::LocalSet, time::sleep};6use tokio::{process::Command, task::LocalSet, time::sleep};
21 privileged_build: bool,21 privileged_build: bool,
22 #[structopt(subcommand)]22 #[structopt(subcommand)]
23 subcommand: Subcommand,23 subcommand: Subcommand,
24 #[structopt(long)]
25 show_trace: bool,
24}26}
2527
26enum UploadAction {28enum UploadAction {
79}81}
8082
81impl BuildSystems {83impl BuildSystems {
82 pub async fn run(self, config: &Config) -> Result<()> {84 async fn build_task(self, config: Config, host: String) -> Result<()> {
83 let hosts = config.list_hosts().await?;
84 let set = LocalSet::new();
85 let this = &self;
86 for host in hosts.iter() {
87 if config.should_skip(host) {
88 continue;
89 }
90 let config = config.clone();
91 let host = host.clone();
92 let this = this.clone();
93 let span = info_span!("deployment", host = field::display(&host));
94 set.spawn_local(
95 (async move {
96 let res: Result<()> = try {
97 info!("building");85 info!("building");
98 let built = {86 let built = {
99 let dir = tempfile::tempdir()?;87 let dir = tempfile::tempdir()?;
100 dir.path().to_owned()88 dir.path().to_owned()
101 };89 };
10290
103 let mut nix_build = if this.privileged_build {91 let mut nix_build = if self.privileged_build {
104 let mut out = Command::new("sudo");92 let mut out = Command::new("sudo");
105 out.arg("nix");93 out.arg("nix");
106 out94 out
117 "--out-link",105 "--out-link",
118 ])106 ])
119 .arg(&built)107 .arg(&built)
120 .arg(format!(108 .arg(config.configuration_attr_name(&format!(
121 "{}.{}.config.system.build.toplevel",109 "configuredSystems.{}.config.system.build.toplevel",
122 SYSTEMS_ATTRIBUTE, host,110 host
123 ));111 )));
124112
113 if self.show_trace {
114 nix_build.arg("--show-trace");
115 }
125 if let Some(builders) = &this.builders {116 if let Some(builders) = &self.builders {
126 nix_build.arg("--builders").arg(builders);117 nix_build.arg("--builders").arg(builders);
127 }118 }
128 if let Some(jobs) = &this.jobs {119 if let Some(jobs) = &self.jobs {
129 nix_build.arg("--max-jobs");120 nix_build.arg("--max-jobs");
130 nix_build.arg(format!("{}", jobs));121 nix_build.arg(format!("{}", jobs));
131 }122 }
132 if !this.fail_fast {123 if !self.fail_fast {
133 nix_build.arg("--keep-going");124 nix_build.arg("--keep-going");
134 }125 }
135126
136 nix_build.run_nix().await?;127 nix_build.run_nix().await?;
137 let built = std::fs::canonicalize(built)?;128 let built = std::fs::canonicalize(built)?;
138129
139 let action = Action::from(this.subcommand.clone());130 let action = Action::from(self.subcommand.clone());
140131
141 match action {132 match action {
142 Action::Upload(action) => {133 Action::Upload(action) => {
190 out.push(format!("sd-image-{}", host));181 out.push(format!("sd-image-{}", host));
191182
192 info!("building sd image to {:?}", out);183 info!("building sd image to {:?}", out);
193 let mut nix_build = if this.privileged_build {184 let mut nix_build = if self.privileged_build {
194 let mut out = Command::new("sudo");185 let mut out = Command::new("sudo");
195 out.arg("nix");186 out.arg("nix");
196 out187 out
200 nix_build191 nix_build
201 .args(&["build", "--impure", "--no-link", "--out-link"])192 .args(&["build", "--impure", "--no-link", "--out-link"])
202 .arg(&out)193 .arg(&out)
203 .arg(format!(194 .arg(config.configuration_attr_name(&format!(
204 "{}.{}.config.system.build.sdImage",195 "configuredSystems.{}.config.system.build.sdImage",
205 SYSTEMS_ATTRIBUTE, host,196 host,
206 ));197 )));
207 if let Some(builders) = &this.builders {198 if let Some(builders) = &self.builders {
208 nix_build.arg("--builders").arg(builders);199 nix_build.arg("--builders").arg(builders);
209 }200 }
210 if let Some(jobs) = &this.jobs {201 if let Some(jobs) = &self.jobs {
211 nix_build.arg("--max-jobs");202 nix_build.arg("--max-jobs");
212 nix_build.arg(format!("{}", jobs));203 nix_build.arg(format!("{}", jobs));
213 }204 }
214 if !this.fail_fast {205 if !self.fail_fast {
215 nix_build.arg("--keep-going");206 nix_build.arg("--keep-going");
216 }207 }
217208
218 nix_build.inherit_stdio().run_nix().await?;209 nix_build.inherit_stdio().run_nix().await?;
219 }210 }
220 };211 };
221 };
222 match res {
223 Ok(_) => {}
224 Err(e) => {
225 error!("failed to deploy host: {}", e)
226 }
227 }
228 Ok(())
229 })
230 .instrument(span),
231 );
232 }
233 set.await;
234 Ok(())212 Ok(())
235 }213 }
214
215 pub async fn run(self, config: &Config) -> Result<()> {
216 let hosts = config.list_hosts().await?;
217 let set = LocalSet::new();
218 let this = &self;
219 for host in hosts.iter() {
220 if config.should_skip(host) {
221 continue;
222 }
223 let config = config.clone();
224 let host = host.clone();
225 let this = this.clone();
226 let span = info_span!("deployment", host = field::display(&host));
227 set.spawn_local(
228 (async move {
229 match this.build_task(config, host).await {
230 Ok(_) => {}
231 Err(e) => {
232 error!("failed to deploy host: {}", e)
233 }
234 }
235 })
236 .instrument(span),
237 );
238 }
239 set.await;
240 Ok(())
241 }
236}242}
237243
modifiedcmds/fleet/src/command.rsdiffbeforeafterboth
--- a/cmds/fleet/src/command.rs
+++ b/cmds/fleet/src/command.rs
@@ -150,6 +150,12 @@
 										info!(target: "nix", "{}", text)
 									}
 								},
+								NixLog::Start { text, level: 0, typ: 108, .. } if text == "" => {
+									// Cache lookup? Coupled with copy log
+								},
+								NixLog::Start { text, level: 4, typ: 101, .. } if text.starts_with("downloading ") => {
+									// NAR downloading, coupled with copy log
+								}
 								NixLog::Stop { .. } => {},
 								NixLog::Result { .. } => {},
 								_ => warn!("unknown log: {:?}", log)
modifiedcmds/fleet/src/host.rsdiffbeforeafterboth
--- a/cmds/fleet/src/host.rs
+++ b/cmds/fleet/src/host.rs
@@ -16,6 +16,7 @@
 use crate::{command::CommandExt, fleetdata::FleetData};
 
 pub struct FleetConfigInternals {
+	pub local_system: String,
 	pub directory: PathBuf,
 	pub opts: FleetOpts,
 	pub data: RefCell<FleetData>,
@@ -66,17 +67,21 @@
 		}
 	}
 
-	pub fn full_attr_name(&self, attr_name: &str) -> OsString {
+	pub fn configuration_attr_name(&self, name: &str) -> OsString {
 		let mut str = self.directory.as_os_str().to_owned();
 		str.push("#");
-		str.push(attr_name);
+		str.push(&format!(
+			"fleetConfigurations.default.{}.{}",
+			self.local_system,
+			name
+		));
 		str
 	}
 
 	pub async fn list_hosts(&self) -> Result<Vec<String>> {
 		Command::new("nix")
 			.arg("eval")
-			.arg(self.full_attr_name("fleetConfigurations.default.configuredHosts"))
+			.arg(self.configuration_attr_name("configuredHosts"))
 			.args(&["--apply", "builtins.attrNames", "--json", "--show-trace"])
 			.run_nix_json()
 			.await
@@ -84,10 +89,7 @@
 	pub async fn config_attr<T: DeserializeOwned>(&self, host: &str, attr: &str) -> Result<T> {
 		Command::new("nix")
 			.arg("eval")
-			.arg(self.full_attr_name(&format!(
-				"fleetConfigurations.default.configuredSystems.{}.config.{}",
-				host, attr
-			)))
+			.arg(self.configuration_attr_name(&format!("configuredSystems.{}.config.{}", host, attr)))
 			.args(&["--json", "--show-trace"])
 			.run_nix_json()
 			.await
@@ -129,10 +131,14 @@
 	/// Host, which should be threaten as current machine
 	#[structopt(long)]
 	pub localhost: Option<String>,
+
+	#[structopt(long, default_value = "x86_64-linux")]
+	pub local_system: String,
 }
 
 impl FleetOpts {
 	pub fn build(mut self) -> Result<Config> {
+		let local_system = self.local_system.clone();
 		if self.localhost.is_none() {
 			self.localhost
 				.replace(hostname::get().unwrap().to_str().unwrap().to_owned());
@@ -148,6 +154,7 @@
 			opts: self,
 			directory,
 			data,
+			local_system,
 		})))
 	}
 }
modifiedcmds/fleet/src/main.rsdiffbeforeafterboth
--- a/cmds/fleet/src/main.rs
+++ b/cmds/fleet/src/main.rs
@@ -1,11 +1,7 @@
-#![feature(try_blocks)]
-
 pub mod command;
 pub mod host;
 pub mod keys;
-
 pub mod cmds;
-pub mod nix;
 
 mod fleetdata;
 
deletedcmds/fleet/src/nix.rsdiffbeforeafterboth
--- a/cmds/fleet/src/nix.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub const HOSTS_ATTRIBUTE: &str = ".#fleetConfigurations.default.configuredHosts";
-pub const SECRETS_ATTRIBUTE: &str = ".#fleetConfigurations.default.configuredSecrets";
-pub const SYSTEMS_ATTRIBUTE: &str = ".#fleetConfigurations.default.configuredSystems";
modifiedlib/default.nixdiffbeforeafterboth
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -2,15 +2,16 @@
   fleetConfiguration = { data, nixpkgs, hosts, ... }@allConfig:
     let
       config = builtins.removeAttrs allConfig [ "nixpkgs" "data" ];
+      fleetLib = import ./fleetLib.nix {
+        inherit nixpkgs hosts;
+      };
     in
-    flake-utils.lib.eachDefaultSystem (system: rec {
+    nixpkgs.lib.genAttrs flake-utils.lib.defaultSystems (system: rec {
       root = nixpkgs.lib.evalModules {
         modules = (import ../modules/fleet/_modules.nix) ++ [ config data ];
         specialArgs = {
           inherit nixpkgs;
-          fleet = import ./fleetLib.nix {
-            inherit nixpkgs hosts;
-          };
+          fleet = fleetLib;
         };
       };
       configuredHosts = root.config.hosts;
@@ -27,12 +28,16 @@
                   else [ ]
                 ) ++ [
                   ({ ... }: {
+                    nixpkgs.system = system;
                     nixpkgs.localSystem.system = system;
                     nixpkgs.crossSystem = if system == configuredHosts.${name}.system then null else {
                       system = configuredHosts.${name}.system;
                     };
                   })
                 ];
+                specialArgs = {
+                  fleet = fleetLib.hostsToAttrs (host: configuredSystems.${host}.config);
+                };
               };
             }
           )