eval.nix: Adds meta.machinesFile option that is passed to Nix as builders argument

This commit is contained in:
Jason R. McNeil 2021-04-09 23:43:31 -07:00
parent 0927fe9dc1
commit e0465567b2
8 changed files with 69 additions and 6 deletions

View file

@ -54,6 +54,15 @@ Here is a sample `hive.nix` with two nodes, with some common configurations appl
nodeNixpkgs = { nodeNixpkgs = {
node-b = ./another-nixos-checkout; node-b = ./another-nixos-checkout;
}; };
# If your Colmena host has nix configured to allow for remote builds
# (for nix-daemon, your user being included in trusted-users)
# you can set a machines file that will be passed to the underlying
# nix-store command during derivation realization as a builders option.
# For example, if you support multiple orginizations each with their own
# build machine(s) you can ensure that builds only take place on your
# local machine and/or the machines specified in this file.
# machinesFile = ./machines.client-a;
}; };
defaults = { pkgs, ... }: { defaults = { pkgs, ... }: {

View file

@ -115,6 +115,8 @@ pub async fn run(_global_args: &ArgMatches<'_>, local_args: &ArgMatches<'_>) {
log::info!("Enumerating nodes..."); log::info!("Enumerating nodes...");
let all_nodes = hive.deployment_info().await.unwrap(); let all_nodes = hive.deployment_info().await.unwrap();
let nix_options = hive.nix_options().await.unwrap();
let selected_nodes = match local_args.value_of("on") { let selected_nodes = match local_args.value_of("on") {
Some(filter) => { Some(filter) => {
util::filter_nodes(&all_nodes, filter) util::filter_nodes(&all_nodes, filter)
@ -159,7 +161,7 @@ pub async fn run(_global_args: &ArgMatches<'_>, local_args: &ArgMatches<'_>) {
if build_only { if build_only {
targets.insert( targets.insert(
node.clone(), node.clone(),
Target::new(localhost(), config.clone()), Target::new(localhost(nix_options.clone()), config.clone()),
); );
} }
} }

View file

@ -100,13 +100,14 @@ pub async fn run(_global_args: &ArgMatches<'_>, local_args: &ArgMatches<'_>) {
let target: Target = { let target: Target = {
if let Some(info) = hive.deployment_info_for(&hostname).await.unwrap() { if let Some(info) = hive.deployment_info_for(&hostname).await.unwrap() {
let nix_options = hive.nix_options().await.unwrap();
if !info.allows_local_deployment() { if !info.allows_local_deployment() {
log::error!("Local deployment is not enabled for host {}.", hostname); log::error!("Local deployment is not enabled for host {}.", hostname);
log::error!("Hint: Set deployment.allowLocalDeployment to true."); log::error!("Hint: Set deployment.allowLocalDeployment to true.");
quit::with_code(2); quit::with_code(2);
} }
Target::new( Target::new(
host::local(), host::local(nix_options),
info.clone(), info.clone(),
) )
} else { } else {

View file

@ -460,8 +460,9 @@ impl Deployment {
} }
async fn build_profiles(self: Arc<Self>, chunk: &Vec<String>, derivation: StoreDerivation<ProfileMap>, progress: TaskProgress) -> Option<ProfileMap> { async fn build_profiles(self: Arc<Self>, chunk: &Vec<String>, derivation: StoreDerivation<ProfileMap>, progress: TaskProgress) -> Option<ProfileMap> {
let nix_options = self.hive.nix_options().await.unwrap();
// FIXME: Remote build? // FIXME: Remote build?
let mut builder = host::local(); let mut builder = host::local(nix_options);
builder.set_progress_bar(progress.clone()); builder.set_progress_bar(progress.clone());

View file

@ -48,6 +48,25 @@ let
type = types.attrsOf types.unspecified; type = types.attrsOf types.unspecified;
default = {}; default = {};
}; };
machinesFile = lib.mkOption {
description = ''
Use the machines listed in this file when building this hive configuration.
If your Colmena host has nix configured to allow for remote builds
(for nix-daemon, your user being included in trusted-users)
you can set a machines file that will be passed to the underlying
nix-store command during derivation realization as a builders option.
For example, if you support multiple orginizations each with their own
build machine(s) you can ensure that builds only take place on your
local machine and/or the machines specified in this file.
See https://nixos.org/manual/nix/stable/#chap-distributed-builds
for the machine specification format.
'';
default = null;
apply = value: if value == null then null else toString value;
type = types.nullOr types.path;
};
}; };
}; };
@ -311,4 +330,5 @@ let
}; };
in { in {
inherit nodes deploymentConfigJson toplevel buildAll buildSelected introspect; inherit nodes deploymentConfigJson toplevel buildAll buildSelected introspect;
meta = hive.meta;
} }

View file

@ -42,6 +42,23 @@ impl Hive {
self.show_trace = value; self.show_trace = value;
} }
pub async fn nix_options(&self) -> NixResult<Vec<String>> {
let mut options:Vec<String> = Vec::new();
if let Some(machines_file) = self.machines_file().await.unwrap() {
options.append(&mut vec![
"--option".to_owned(),
"builders".to_owned(),
format!("@{}", machines_file).to_owned()
]);
}
if self.show_trace {
options.push("--show-trace".to_owned())
}
Ok(options)
}
pub fn as_path(&self) -> &Path { pub fn as_path(&self) -> &Path {
&self.hive &self.hive
} }
@ -62,6 +79,15 @@ impl Hive {
Ok(configs) Ok(configs)
} }
/// Retrieve machinesFile setting for the hive.
pub async fn machines_file(&self) -> NixResult<Option<String>> {
let expr = "toJSON (hive.meta.machinesFile or null)";
let s: String = self.nix_instantiate(&expr).eval()
.capture_json().await?;
Ok(serde_json::from_str(&s).unwrap())
}
/// Retrieve deployment info for a single node. /// Retrieve deployment info for a single node.
pub async fn deployment_info_for(&self, node: &str) -> NixResult<Option<NodeConfig>> { pub async fn deployment_info_for(&self, node: &str) -> NixResult<Option<NodeConfig>> {
let expr = format!("toJSON (hive.nodes.\"{}\".config.deployment or null)", node); let expr = format!("toJSON (hive.nodes.\"{}\".config.deployment or null)", node);

View file

@ -18,13 +18,15 @@ use crate::progress::TaskProgress;
pub struct Local { pub struct Local {
progress_bar: TaskProgress, progress_bar: TaskProgress,
logs: String, logs: String,
nix_options: Vec<String>,
} }
impl Local { impl Local {
pub fn new() -> Self { pub fn new(nix_options: Vec<String>) -> Self {
Self { Self {
progress_bar: TaskProgress::default(), progress_bar: TaskProgress::default(),
logs: String::new(), logs: String::new(),
nix_options,
} }
} }
} }
@ -36,6 +38,8 @@ impl Host for Local {
} }
async fn realize_remote(&mut self, derivation: &StorePath) -> NixResult<Vec<StorePath>> { async fn realize_remote(&mut self, derivation: &StorePath) -> NixResult<Vec<StorePath>> {
let mut command = Command::new("nix-store"); let mut command = Command::new("nix-store");
command.args(self.nix_options.clone());
command command
.arg("--no-gc-warning") .arg("--no-gc-warning")
.arg("--realise") .arg("--realise")

View file

@ -13,8 +13,8 @@ pub use local::Local;
mod key_uploader; mod key_uploader;
pub(crate) fn local() -> Box<dyn Host + 'static> { pub(crate) fn local(nix_options: Vec<String>) -> Box<dyn Host + 'static> {
Box::new(Local::new()) Box::new(Local::new(nix_options))
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]