Refactor current profile detection

This commit is contained in:
Zhaofeng Li 2022-01-08 01:20:36 -08:00
parent 6401ce4c3c
commit f92236da46
5 changed files with 54 additions and 37 deletions

View file

@ -428,16 +428,18 @@ impl Deployment {
if !target.config.replace_unknown_profiles {
job.message("Checking remote profile...".to_string())?;
match host.active_derivation_known().await {
Ok(_) => {
job.message("Remote profile known".to_string())?;
}
Err(e) => {
if arc_self.options.force_replace_unknown_profiles {
job.message("warning: remote profile is unknown, but unknown profiles are being ignored".to_string())?;
} else {
return Err(e);
}
let profile = host.get_main_system_profile().await?;
if profile.exists() {
job.message("Remote profile known".to_string())?;
} else {
if arc_self.options.force_replace_unknown_profiles {
job.message("Warning: Remote profile is unknown, but unknown profiles are being ignored".to_string())?;
} else {
return Err(NixError::ActiveProfileUnknown {
store_path: profile,
});
}
}
}

View file

@ -6,7 +6,7 @@ use async_trait::async_trait;
use tokio::process::Command;
use super::{CopyDirection, CopyOptions, Host, key_uploader};
use crate::nix::{StorePath, Profile, Goal, NixError, NixResult, NixCommand, Key, SYSTEM_PROFILE};
use crate::nix::{StorePath, Profile, Goal, NixError, NixResult, NixCommand, Key, SYSTEM_PROFILE, CURRENT_PROFILE};
use crate::util::CommandExecution;
use crate::job::JobHandle;
@ -90,8 +90,19 @@ impl Host for Local {
result
}
async fn active_derivation_known(&mut self) -> NixResult<bool> {
Ok(true)
async fn get_main_system_profile(&mut self) -> NixResult<StorePath> {
let paths = Command::new("sh")
.args(&["-c", &format!("readlink -e {} || readlink -e {}", SYSTEM_PROFILE, CURRENT_PROFILE)])
.capture_output()
.await?;
let path = paths.lines().into_iter().next()
.ok_or(NixError::FailedToGetCurrentProfile)?
.to_string()
.try_into()?;
Ok(path)
}
fn set_job(&mut self, job: Option<JobHandle>) {

View file

@ -110,8 +110,12 @@ pub trait Host: Send + Sync + std::fmt::Debug {
Err(NixError::Unsupported)
}
/// Check if the active profile is known to the host running Colmena
async fn active_derivation_known(&mut self) -> NixResult<bool>;
/// Returns the main system profile on the host.
///
/// This may _not_ be the system profile that's currently activated!
/// It will first try `/nix/var/nix/profiles/system`, falling back
/// to `/run/current-system` if it doesn't exist.
async fn get_main_system_profile(&mut self) -> NixResult<StorePath>;
/// Activates a system profile on the host, if it runs NixOS.
///

View file

@ -7,7 +7,7 @@ use async_trait::async_trait;
use tokio::process::Command;
use super::{CopyDirection, CopyOptions, Host, key_uploader};
use crate::nix::{StorePath, Profile, Goal, NixResult, NixCommand, NixError, Key, SYSTEM_PROFILE};
use crate::nix::{StorePath, Profile, Goal, NixResult, NixCommand, NixError, Key, SYSTEM_PROFILE, CURRENT_PROFILE};
use crate::util::CommandExecution;
use crate::job::JobHandle;
@ -78,26 +78,19 @@ impl Host for Ssh {
let command = self.ssh(command);
self.run_command(command).await
}
async fn active_derivation_known(&mut self) -> NixResult<bool> {
let paths = self.ssh(&["realpath", SYSTEM_PROFILE])
.capture_output()
.await;
async fn get_main_system_profile(&mut self) -> NixResult<StorePath> {
let command = format!("\"readlink -e {} || readlink -e {}\"", SYSTEM_PROFILE, CURRENT_PROFILE);
match paths {
Ok(paths) => {
if let Some(path) = paths.lines().into_iter().next() {
let remote_profile: StorePath = path.to_string().try_into().unwrap();
if remote_profile.exists() {
return Ok(true);
}
return Err(NixError::ActiveProfileUnknown {
store_path: path.to_string(),
});
}
return Ok(false);
}
Err(e) => Err(e),
}
let paths = self.ssh(&["sh", "-c", &command])
.capture_output()
.await?;
let path = paths.lines().into_iter().next()
.ok_or(NixError::FailedToGetCurrentProfile)?
.to_string()
.try_into()?;
Ok(path)
}
fn set_job(&mut self, job: Option<JobHandle>) {
self.job = job;

View file

@ -44,8 +44,12 @@ pub use flake::Flake;
pub mod node_filter;
pub use node_filter::NodeFilter;
/// Path to the main system profile.
pub const SYSTEM_PROFILE: &str = "/nix/var/nix/profiles/system";
/// Path to the system profile that's currently active.
pub const CURRENT_PROFILE: &str = "/run/current-system";
pub type NixResult<T> = Result<T, NixError>;
#[non_exhaustive]
@ -81,8 +85,11 @@ pub enum NixError {
#[snafu(display("Invalid NixOS system profile"))]
InvalidProfile,
#[snafu(display("Unknown active profile: {}", store_path))]
ActiveProfileUnknown { store_path: String },
#[snafu(display("Unknown active profile: {:?}", store_path))]
ActiveProfileUnknown { store_path: StorePath },
#[snafu(display("Could not determine current profile"))]
FailedToGetCurrentProfile,
#[snafu(display("Current Nix version does not support Flakes"))]
NoFlakesSupport,