forked from DGNum/colmena
Refactor NixOptions
This commit is contained in:
parent
31fd1e49ac
commit
deca292b53
6 changed files with 96 additions and 50 deletions
|
@ -105,7 +105,7 @@ pub async fn run(_global_args: &ArgMatches, local_args: &ArgMatches) -> Result<(
|
||||||
|
|
||||||
let target = {
|
let target = {
|
||||||
if let Some(info) = hive.deployment_info_single(&hostname).await.unwrap() {
|
if let Some(info) = hive.deployment_info_single(&hostname).await.unwrap() {
|
||||||
let nix_options = hive.nix_options().await.unwrap();
|
let nix_options = hive.nix_options_with_builders().await.unwrap();
|
||||||
if !info.allows_local_deployment() {
|
if !info.allows_local_deployment() {
|
||||||
log::error!("Local deployment is not enabled for host {}.", hostname.as_str());
|
log::error!("Local deployment is not enabled for host {}.", hostname.as_str());
|
||||||
log::error!("Hint: Set deployment.allowLocalDeployment to true.");
|
log::error!("Hint: Set deployment.allowLocalDeployment to true.");
|
||||||
|
|
|
@ -20,6 +20,7 @@ use itertools::Itertools;
|
||||||
use crate::progress::Sender as ProgressSender;
|
use crate::progress::Sender as ProgressSender;
|
||||||
use crate::job::{JobMonitor, JobHandle, JobType, JobState};
|
use crate::job::{JobMonitor, JobHandle, JobType, JobState};
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
use super::NixOptions;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Hive,
|
Hive,
|
||||||
|
@ -55,7 +56,7 @@ pub struct Deployment {
|
||||||
options: Options,
|
options: Options,
|
||||||
|
|
||||||
/// Options passed to Nix invocations.
|
/// Options passed to Nix invocations.
|
||||||
nix_options: Vec<String>,
|
nix_options: NixOptions,
|
||||||
|
|
||||||
/// Handle to send messages to the ProgressOutput.
|
/// Handle to send messages to the ProgressOutput.
|
||||||
progress: Option<ProgressSender>,
|
progress: Option<ProgressSender>,
|
||||||
|
@ -106,7 +107,7 @@ impl Deployment {
|
||||||
hive,
|
hive,
|
||||||
goal,
|
goal,
|
||||||
options: Options::default(),
|
options: Options::default(),
|
||||||
nix_options: Vec::new(),
|
nix_options: NixOptions::default(),
|
||||||
progress,
|
progress,
|
||||||
nodes: targets.keys().cloned().collect(),
|
nodes: targets.keys().cloned().collect(),
|
||||||
targets,
|
targets,
|
||||||
|
@ -133,7 +134,7 @@ impl Deployment {
|
||||||
monitor.set_label_width(width);
|
monitor.set_label_width(width);
|
||||||
}
|
}
|
||||||
|
|
||||||
let nix_options = self.hive.nix_options().await?;
|
let nix_options = self.hive.nix_options_with_builders().await?;
|
||||||
self.nix_options = nix_options;
|
self.nix_options = nix_options;
|
||||||
|
|
||||||
if self.goal == Goal::UploadKeys {
|
if self.goal == Goal::UploadKeys {
|
||||||
|
|
|
@ -11,7 +11,7 @@ use validator::Validate;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Flake,
|
Flake,
|
||||||
ColmenaResult,
|
NixOptions,
|
||||||
NodeName,
|
NodeName,
|
||||||
NodeConfig,
|
NodeConfig,
|
||||||
NodeFilter,
|
NodeFilter,
|
||||||
|
@ -19,6 +19,7 @@ use super::{
|
||||||
StorePath,
|
StorePath,
|
||||||
};
|
};
|
||||||
use super::deployment::TargetNode;
|
use super::deployment::TargetNode;
|
||||||
|
use crate::error::ColmenaResult;
|
||||||
use crate::util::{CommandExecution, CommandExt};
|
use crate::util::{CommandExecution, CommandExt};
|
||||||
use crate::job::JobHandle;
|
use crate::job::JobHandle;
|
||||||
|
|
||||||
|
@ -82,8 +83,8 @@ pub struct Hive {
|
||||||
/// Whether to pass --show-trace in Nix commands.
|
/// Whether to pass --show-trace in Nix commands.
|
||||||
show_trace: bool,
|
show_trace: bool,
|
||||||
|
|
||||||
/// The cached --builders expression.
|
/// The cached machines_file expression.
|
||||||
builders: RwLock<Option<Option<String>>>,
|
machines_file: RwLock<Option<Option<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hive {
|
impl Hive {
|
||||||
|
@ -98,7 +99,7 @@ impl Hive {
|
||||||
context_dir,
|
context_dir,
|
||||||
eval_nix: eval_nix.into_temp_path(),
|
eval_nix: eval_nix.into_temp_path(),
|
||||||
show_trace: false,
|
show_trace: false,
|
||||||
builders: RwLock::new(None),
|
machines_file: RwLock::new(None),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,11 +111,20 @@ impl Hive {
|
||||||
self.show_trace = value;
|
self.show_trace = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn nix_options(&self) -> ColmenaResult<Vec<String>> {
|
/// Returns Nix options to set for this Hive.
|
||||||
let mut options = self.builder_args().await?;
|
pub fn nix_options(&self) -> NixOptions {
|
||||||
|
let mut options = NixOptions::default();
|
||||||
|
options.set_show_trace(self.show_trace);
|
||||||
|
options
|
||||||
|
}
|
||||||
|
|
||||||
if self.show_trace {
|
/// Returns Nix options to set for this Hive, with configured remote builders.
|
||||||
options.push("--show-trace".to_owned());
|
pub async fn nix_options_with_builders(&self) -> ColmenaResult<NixOptions> {
|
||||||
|
let mut options = NixOptions::default();
|
||||||
|
options.set_show_trace(self.show_trace);
|
||||||
|
|
||||||
|
if let Some(machines_file) = self.machines_file().await? {
|
||||||
|
options.set_builders(Some(format!("@{}", machines_file)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(options)
|
Ok(options)
|
||||||
|
@ -266,7 +276,7 @@ impl Hive {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluates an expression using values from the configuration
|
/// Evaluates an expression using values from the configuration.
|
||||||
pub async fn introspect(&self, expression: String, instantiate: bool) -> ColmenaResult<String> {
|
pub async fn introspect(&self, expression: String, instantiate: bool) -> ColmenaResult<String> {
|
||||||
if instantiate {
|
if instantiate {
|
||||||
let expression = format!("hive.introspect ({})", expression);
|
let expression = format!("hive.introspect ({})", expression);
|
||||||
|
@ -279,10 +289,10 @@ impl Hive {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve machinesFile setting for the hive.
|
/// Retrieve the machinesFile setting for the Hive.
|
||||||
async fn machines_file(&self) -> ColmenaResult<Option<String>> {
|
async fn machines_file(&self) -> ColmenaResult<Option<String>> {
|
||||||
if let Some(builders_opt) = &*self.builders.read().await {
|
if let Some(machines_file) = &*self.machines_file.read().await {
|
||||||
return Ok(builders_opt.clone());
|
return Ok(machines_file.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let expr = "toJSON (hive.meta.machinesFile or null)";
|
let expr = "toJSON (hive.meta.machinesFile or null)";
|
||||||
|
@ -290,26 +300,11 @@ impl Hive {
|
||||||
.capture_json().await?;
|
.capture_json().await?;
|
||||||
|
|
||||||
let parsed: Option<String> = serde_json::from_str(&s).unwrap();
|
let parsed: Option<String> = serde_json::from_str(&s).unwrap();
|
||||||
self.builders.write().await.replace(parsed.clone());
|
self.machines_file.write().await.replace(parsed.clone());
|
||||||
|
|
||||||
Ok(parsed)
|
Ok(parsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns Nix arguments to set builders.
|
|
||||||
async fn builder_args(&self) -> ColmenaResult<Vec<String>> {
|
|
||||||
let mut options = Vec::new();
|
|
||||||
|
|
||||||
if let Some(machines_file) = self.machines_file().await? {
|
|
||||||
options.append(&mut vec![
|
|
||||||
"--option".to_owned(),
|
|
||||||
"builders".to_owned(),
|
|
||||||
format!("@{}", machines_file),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn nix_instantiate(&self, expression: &str) -> NixInstantiate {
|
fn nix_instantiate(&self, expression: &str) -> NixInstantiate {
|
||||||
NixInstantiate::new(self, expression.to_owned())
|
NixInstantiate::new(self, expression.to_owned())
|
||||||
}
|
}
|
||||||
|
@ -332,7 +327,7 @@ impl<'hive> NixInstantiate<'hive> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn instantiate(self) -> Command {
|
fn instantiate(&self) -> Command {
|
||||||
// FIXME: unwrap
|
// FIXME: unwrap
|
||||||
// Technically filenames can be arbitrary byte strings (OsStr),
|
// Technically filenames can be arbitrary byte strings (OsStr),
|
||||||
// but Nix may not like it...
|
// but Nix may not like it...
|
||||||
|
@ -365,38 +360,34 @@ impl<'hive> NixInstantiate<'hive> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.hive.show_trace {
|
|
||||||
command.arg("--show-trace");
|
|
||||||
}
|
|
||||||
|
|
||||||
command
|
command
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval(self) -> Command {
|
fn eval(self) -> Command {
|
||||||
let mut command = self.instantiate();
|
let mut command = self.instantiate();
|
||||||
|
let options = self.hive.nix_options();
|
||||||
command.arg("--eval").arg("--json").arg("--strict")
|
command.arg("--eval").arg("--json").arg("--strict")
|
||||||
// Ensures the derivations are instantiated
|
// Ensures the derivations are instantiated
|
||||||
// Required for system profile evaluation and IFD
|
// Required for system profile evaluation and IFD
|
||||||
.arg("--read-write-mode");
|
.arg("--read-write-mode")
|
||||||
|
.args(options.to_args());
|
||||||
command
|
command
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn instantiate_with_builders(self) -> ColmenaResult<Command> {
|
async fn instantiate_with_builders(self) -> ColmenaResult<Command> {
|
||||||
let hive = self.hive;
|
let options = self.hive.nix_options_with_builders().await?;
|
||||||
let mut command = self.instantiate();
|
let mut command = self.instantiate();
|
||||||
|
|
||||||
let builder_args = hive.builder_args().await?;
|
command.args(options.to_args());
|
||||||
command.args(&builder_args);
|
|
||||||
|
|
||||||
Ok(command)
|
Ok(command)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn eval_with_builders(self) -> ColmenaResult<Command> {
|
async fn eval_with_builders(self) -> ColmenaResult<Command> {
|
||||||
let hive = self.hive;
|
let options = self.hive.nix_options_with_builders().await?;
|
||||||
let mut command = self.eval();
|
let mut command = self.eval();
|
||||||
|
|
||||||
let builder_args = hive.builder_args().await?;
|
command.args(options.to_args());
|
||||||
command.args(&builder_args);
|
|
||||||
|
|
||||||
Ok(command)
|
Ok(command)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use async_trait::async_trait;
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
|
|
||||||
use crate::error::{ColmenaResult, ColmenaError};
|
use crate::error::{ColmenaResult, ColmenaError};
|
||||||
use crate::nix::{StorePath, Profile, Goal, Key, SYSTEM_PROFILE, CURRENT_PROFILE};
|
use crate::nix::{StorePath, Profile, Goal, Key, NixOptions, SYSTEM_PROFILE, CURRENT_PROFILE};
|
||||||
use crate::util::{CommandExecution, CommandExt};
|
use crate::util::{CommandExecution, CommandExt};
|
||||||
use crate::job::JobHandle;
|
use crate::job::JobHandle;
|
||||||
use super::{CopyDirection, CopyOptions, Host, key_uploader};
|
use super::{CopyDirection, CopyOptions, Host, key_uploader};
|
||||||
|
@ -18,11 +18,11 @@ use super::{CopyDirection, CopyOptions, Host, key_uploader};
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Local {
|
pub struct Local {
|
||||||
job: Option<JobHandle>,
|
job: Option<JobHandle>,
|
||||||
nix_options: Vec<String>,
|
nix_options: NixOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Local {
|
impl Local {
|
||||||
pub fn new(nix_options: Vec<String>) -> Self {
|
pub fn new(nix_options: NixOptions) -> Self {
|
||||||
Self {
|
Self {
|
||||||
job: None,
|
job: None,
|
||||||
nix_options,
|
nix_options,
|
||||||
|
@ -39,7 +39,7 @@ impl Host for Local {
|
||||||
async fn realize_remote(&mut self, derivation: &StorePath) -> ColmenaResult<Vec<StorePath>> {
|
async fn realize_remote(&mut self, derivation: &StorePath) -> ColmenaResult<Vec<StorePath>> {
|
||||||
let mut command = Command::new("nix-store");
|
let mut command = Command::new("nix-store");
|
||||||
|
|
||||||
command.args(self.nix_options.clone());
|
command.args(self.nix_options.to_args());
|
||||||
command
|
command
|
||||||
.arg("--no-gc-warning")
|
.arg("--no-gc-warning")
|
||||||
.arg("--realise")
|
.arg("--realise")
|
||||||
|
|
|
@ -2,8 +2,9 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use super::{StorePath, Profile, Goal, ColmenaResult, ColmenaError, Key};
|
use crate::error::{ColmenaError, ColmenaResult};
|
||||||
use crate::job::JobHandle;
|
use crate::job::JobHandle;
|
||||||
|
use super::{StorePath, Profile, Goal, Key, NixOptions};
|
||||||
|
|
||||||
mod ssh;
|
mod ssh;
|
||||||
pub use ssh::Ssh;
|
pub use ssh::Ssh;
|
||||||
|
@ -13,7 +14,7 @@ pub use local::Local;
|
||||||
|
|
||||||
mod key_uploader;
|
mod key_uploader;
|
||||||
|
|
||||||
pub(crate) fn local(nix_options: Vec<String>) -> Box<dyn Host + 'static> {
|
pub(crate) fn local(nix_options: NixOptions) -> Box<dyn Host + 'static> {
|
||||||
Box::new(Local::new(nix_options))
|
Box::new(Local::new(nix_options))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,22 @@ pub struct NodeConfig {
|
||||||
keys: HashMap<String, Key>,
|
keys: HashMap<String, Key>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Nix options.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct NixOptions {
|
||||||
|
/// Whether to pass --show-trace.
|
||||||
|
show_trace: bool,
|
||||||
|
|
||||||
|
/// Designated builders.
|
||||||
|
///
|
||||||
|
/// See <https://nixos.org/manual/nix/stable/advanced-topics/distributed-builds.html>.
|
||||||
|
///
|
||||||
|
/// Valid examples:
|
||||||
|
/// - `@/path/to/machines`
|
||||||
|
/// - `builder@host.tld riscv64-linux /home/nix/.ssh/keys/builder.key 8 1 kvm`
|
||||||
|
builders: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
impl NodeName {
|
impl NodeName {
|
||||||
/// Returns the string.
|
/// Returns the string.
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
|
@ -150,6 +166,43 @@ impl NodeConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for NixOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
show_trace: false,
|
||||||
|
builders: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NixOptions {
|
||||||
|
pub fn set_show_trace(&mut self, show_trace: bool) {
|
||||||
|
self.show_trace = show_trace;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_builders(&mut self, builders: Option<String>) {
|
||||||
|
self.builders = builders;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_args(&self) -> Vec<String> {
|
||||||
|
let mut options = Vec::new();
|
||||||
|
|
||||||
|
if let Some(builders) = &self.builders {
|
||||||
|
options.append(&mut vec![
|
||||||
|
"--option".to_string(),
|
||||||
|
"builders".to_string(),
|
||||||
|
builders.clone(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.show_trace {
|
||||||
|
options.push("--show-trace".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn validate_keys(keys: &HashMap<String, Key>) -> Result<(), ValidationErrorType> {
|
fn validate_keys(keys: &HashMap<String, Key>) -> Result<(), ValidationErrorType> {
|
||||||
// Bad secret names:
|
// Bad secret names:
|
||||||
// - /etc/passwd
|
// - /etc/passwd
|
||||||
|
|
Loading…
Reference in a new issue