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 { if !target.config.replace_unknown_profiles {
job.message("Checking remote profile...".to_string())?; job.message("Checking remote profile...".to_string())?;
match host.active_derivation_known().await {
Ok(_) => { let profile = host.get_main_system_profile().await?;
if profile.exists() {
job.message("Remote profile known".to_string())?; 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 { } else {
return 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(NixError::ActiveProfileUnknown {
store_path: profile,
});
} }
} }
} }

View file

@ -6,7 +6,7 @@ use async_trait::async_trait;
use tokio::process::Command; use tokio::process::Command;
use super::{CopyDirection, CopyOptions, Host, key_uploader}; 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::util::CommandExecution;
use crate::job::JobHandle; use crate::job::JobHandle;
@ -90,8 +90,19 @@ impl Host for Local {
result 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>) { 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) Err(NixError::Unsupported)
} }
/// Check if the active profile is known to the host running Colmena /// Returns the main system profile on the host.
async fn active_derivation_known(&mut self) -> NixResult<bool>; ///
/// 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. /// 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 tokio::process::Command;
use super::{CopyDirection, CopyOptions, Host, key_uploader}; 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::util::CommandExecution;
use crate::job::JobHandle; use crate::job::JobHandle;
@ -78,26 +78,19 @@ impl Host for Ssh {
let command = self.ssh(command); let command = self.ssh(command);
self.run_command(command).await self.run_command(command).await
} }
async fn active_derivation_known(&mut self) -> NixResult<bool> { async fn get_main_system_profile(&mut self) -> NixResult<StorePath> {
let paths = self.ssh(&["realpath", SYSTEM_PROFILE]) let command = format!("\"readlink -e {} || readlink -e {}\"", SYSTEM_PROFILE, CURRENT_PROFILE);
.capture_output()
.await;
match paths { let paths = self.ssh(&["sh", "-c", &command])
Ok(paths) => { .capture_output()
if let Some(path) = paths.lines().into_iter().next() { .await?;
let remote_profile: StorePath = path.to_string().try_into().unwrap();
if remote_profile.exists() { let path = paths.lines().into_iter().next()
return Ok(true); .ok_or(NixError::FailedToGetCurrentProfile)?
} .to_string()
return Err(NixError::ActiveProfileUnknown { .try_into()?;
store_path: path.to_string(),
}); Ok(path)
}
return Ok(false);
}
Err(e) => Err(e),
}
} }
fn set_job(&mut self, job: Option<JobHandle>) { fn set_job(&mut self, job: Option<JobHandle>) {
self.job = job; self.job = job;

View file

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