Skip to content

Commit

Permalink
Setup channels
Browse files Browse the repository at this point in the history
Add a SetupChannels field to ConfigureNix that:
- Creates $ROOT_HOME/.nix-channels
- Runs `nix-channels --update nixpkgs`

Setting up channels can be disabled with a command line flag or
NIX_INSTALLER_NO_CHANNEL_ADD.
  • Loading branch information
mkenigs committed Jan 16, 2024
1 parent 8a19975 commit f1857ad
Show file tree
Hide file tree
Showing 5 changed files with 295 additions and 113 deletions.
71 changes: 3 additions & 68 deletions src/action/base/setup_default_profile.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use std::path::PathBuf;

use crate::{
action::{ActionError, ActionErrorKind, ActionTag, StatefulAction},
action::{common::ConfigureNix, ActionError, ActionErrorKind, ActionTag, StatefulAction},
execute_command, set_env,
};

use glob::glob;

use tokio::{io::AsyncWriteExt, process::Command};
use tracing::{span, Span};

Expand Down Expand Up @@ -51,63 +49,8 @@ impl Action for SetupDefaultProfile {

#[tracing::instrument(level = "debug", skip_all)]
async fn execute(&mut self) -> Result<(), ActionError> {
// Find an `nix` package
let nix_pkg_glob = format!("{}/nix-*/store/*-nix-*.*.*", self.unpacked_path.display());
let mut found_nix_pkg = None;
for entry in glob(&nix_pkg_glob).map_err(Self::error)? {
match entry {
Ok(path) => {
// If we are curing, the user may have multiple of these installed
if let Some(_existing) = found_nix_pkg {
return Err(Self::error(SetupDefaultProfileError::MultipleNixPackages))?;
} else {
found_nix_pkg = Some(path);
}
break;
},
Err(_) => continue, /* Ignore it */
};
}
let nix_pkg = if let Some(nix_pkg) = found_nix_pkg {
tokio::fs::read_link(&nix_pkg)
.await
.map_err(|e| ActionErrorKind::ReadSymlink(nix_pkg, e))
.map_err(Self::error)?
} else {
return Err(Self::error(SetupDefaultProfileError::NoNix));
};

// Find an `nss-cacert` package, add it too.
let nss_ca_cert_pkg_glob = format!(
"{}/nix-*/store/*-nss-cacert-*.*",
self.unpacked_path.display()
);
let mut found_nss_ca_cert_pkg = None;
for entry in glob(&nss_ca_cert_pkg_glob).map_err(Self::error)? {
match entry {
Ok(path) => {
// If we are curing, the user may have multiple of these installed
if let Some(_existing) = found_nss_ca_cert_pkg {
return Err(Self::error(
SetupDefaultProfileError::MultipleNssCaCertPackages,
))?;
} else {
found_nss_ca_cert_pkg = Some(path);
}
break;
},
Err(_) => continue, /* Ignore it */
};
}
let nss_ca_cert_pkg = if let Some(nss_ca_cert_pkg) = found_nss_ca_cert_pkg {
tokio::fs::read_link(&nss_ca_cert_pkg)
.await
.map_err(|e| ActionErrorKind::ReadSymlink(nss_ca_cert_pkg, e))
.map_err(Self::error)?
} else {
return Err(Self::error(SetupDefaultProfileError::NoNssCacert));
};

let (nix_pkg, nss_ca_cert_pkg) =
ConfigureNix::find_nix_and_ca_cert(&self.unpacked_path).await?;
let found_nix_paths = glob::glob(&format!("{}/nix-*", self.unpacked_path.display()))
.map_err(Self::error)?
.collect::<Result<Vec<_>, _>>()
Expand Down Expand Up @@ -236,16 +179,8 @@ impl Action for SetupDefaultProfile {
#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
pub enum SetupDefaultProfileError {
#[error("Unarchived Nix store did not appear to include a `nss-cacert` location")]
NoNssCacert,
#[error("Unarchived Nix store did not appear to include a `nix` location")]
NoNix,
#[error("No root home found to place channel configuration in")]
NoRootHome,
#[error("Unarchived Nix store appears to contain multiple `nss-ca-cert` packages, cannot select one")]
MultipleNssCaCertPackages,
#[error("Unarchived Nix store appears to contain multiple `nix` packages, cannot select one")]
MultipleNixPackages,
}

impl From<SetupDefaultProfileError> for ActionErrorKind {
Expand Down
190 changes: 145 additions & 45 deletions src/action/common/configure_nix.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::path::PathBuf;
use std::path::{Path, PathBuf};

use crate::{
action::{
Expand All @@ -9,6 +9,9 @@ use crate::{
planner::ShellProfileLocations,
settings::{CommonSettings, SCRATCH_DIR},
};
use glob::glob;

use crate::action::common::SetupChannels;

use tracing::{span, Instrument, Span};

Expand All @@ -20,6 +23,7 @@ pub struct ConfigureNix {
setup_default_profile: StatefulAction<SetupDefaultProfile>,
configure_shell_profile: Option<StatefulAction<ConfigureShellProfile>>,
place_nix_configuration: StatefulAction<PlaceNixConfiguration>,
setup_channels: Option<StatefulAction<SetupChannels>>,
}

impl ConfigureNix {
Expand Down Expand Up @@ -51,13 +55,83 @@ impl ConfigureNix {
.await
.map_err(Self::error)?;

let setup_channels = if settings.no_channel_add {
None
} else {
Some(
SetupChannels::plan(PathBuf::from(SCRATCH_DIR))
.await
.map_err(Self::error)?,
)
};

Ok(Self {
place_nix_configuration,
setup_default_profile,
configure_shell_profile,
setup_channels,
}
.into())
}

pub async fn find_nix_and_ca_cert(
unpacked_path: &Path,
) -> Result<(PathBuf, PathBuf), ActionError> {
// Find a `nix` package
let nix_pkg_glob = format!("{}/nix-*/store/*-nix-*.*.*", unpacked_path.display());
let mut found_nix_pkg = None;
for entry in glob(&nix_pkg_glob).map_err(Self::error)? {
match entry {
Ok(path) => {
// If we are curing, the user may have multiple of these installed
if let Some(_existing) = found_nix_pkg {
return Err(Self::error(ConfigureNixError::MultipleNixPackages))?;
} else {
found_nix_pkg = Some(path);
}
break;
},
Err(_) => continue, /* Ignore it */
};
}
let nix_pkg = if let Some(nix_pkg) = found_nix_pkg {
tokio::fs::read_link(&nix_pkg)
.await
.map_err(|e| ActionErrorKind::ReadSymlink(nix_pkg, e))
.map_err(Self::error)?
} else {
return Err(Self::error(ConfigureNixError::NoNix));
};

// Find an `nss-cacert` package
let nss_ca_cert_pkg_glob =
format!("{}/nix-*/store/*-nss-cacert-*.*", unpacked_path.display());
let mut found_nss_ca_cert_pkg = None;
for entry in glob(&nss_ca_cert_pkg_glob).map_err(Self::error)? {
match entry {
Ok(path) => {
// If we are curing, the user may have multiple of these installed
if let Some(_existing) = found_nss_ca_cert_pkg {
return Err(Self::error(ConfigureNixError::MultipleNssCaCertPackages))?;
} else {
found_nss_ca_cert_pkg = Some(path);
}
break;
},
Err(_) => continue, /* Ignore it */
};
}
let nss_ca_cert_pkg = if let Some(nss_ca_cert_pkg) = found_nss_ca_cert_pkg {
tokio::fs::read_link(&nss_ca_cert_pkg)
.await
.map_err(|e| ActionErrorKind::ReadSymlink(nss_ca_cert_pkg, e))
.map_err(Self::error)?
} else {
return Err(Self::error(ConfigureNixError::NoNssCacert));
};

Ok((nix_pkg, nss_ca_cert_pkg))
}
}

#[async_trait::async_trait]
Expand All @@ -79,10 +153,14 @@ impl Action for ConfigureNix {
setup_default_profile,
place_nix_configuration,
configure_shell_profile,
setup_channels,
} = &self;

let mut buf = setup_default_profile.describe_execute();
buf.append(&mut place_nix_configuration.describe_execute());
if let Some(setup_channels) = setup_channels {
buf.append(&mut setup_channels.describe_execute());
}
if let Some(configure_shell_profile) = configure_shell_profile {
buf.append(&mut configure_shell_profile.describe_execute());
}
Expand All @@ -95,57 +173,51 @@ impl Action for ConfigureNix {
setup_default_profile,
place_nix_configuration,
configure_shell_profile,
setup_channels,
} = self;

if let Some(configure_shell_profile) = configure_shell_profile {
let setup_default_profile_span = tracing::Span::current().clone();
let (place_nix_configuration_span, configure_shell_profile_span) = (
setup_default_profile_span.clone(),
setup_default_profile_span.clone(),
);
tokio::try_join!(
async move {
setup_default_profile
.try_execute()
.instrument(setup_default_profile_span)
.await
.map_err(Self::error)
},
async move {
place_nix_configuration
.try_execute()
.instrument(place_nix_configuration_span)
.await
.map_err(Self::error)
},
async move {
configure_shell_profile
let setup_default_profile_span = tracing::Span::current().clone();
let (place_nix_configuration_span, configure_shell_profile_span, setup_channels_span) = (
setup_default_profile_span.clone(),
setup_default_profile_span.clone(),
setup_default_profile_span.clone(),
);
tokio::try_join!(
async move {
setup_default_profile
.try_execute()
.instrument(setup_default_profile_span)
.await
.map_err(Self::error)
},
async move {
place_nix_configuration
.try_execute()
.instrument(place_nix_configuration_span)
.await
.map_err(Self::error)
},
async move {
match configure_shell_profile {
Some(configure_shell_profile) => configure_shell_profile
.try_execute()
.instrument(configure_shell_profile_span)
.await
.map_err(Self::error)
},
)?;
} else {
let setup_default_profile_span = tracing::Span::current().clone();
let place_nix_configuration_span = setup_default_profile_span.clone();
tokio::try_join!(
async move {
setup_default_profile
.try_execute()
.instrument(setup_default_profile_span)
.await
.map_err(Self::error)
},
async move {
place_nix_configuration
.map_err(Self::error),
None => Ok(()),
}
},
async move {
match setup_channels {
Some(setup_channels) => setup_channels
.try_execute()
.instrument(place_nix_configuration_span)
.instrument(setup_channels_span)
.await
.map_err(Self::error)
},
)?;
};
.map_err(Self::error),
None => Ok(()),
}
},
)?;

Ok(())
}
Expand All @@ -155,6 +227,7 @@ impl Action for ConfigureNix {
setup_default_profile,
place_nix_configuration,
configure_shell_profile,
setup_channels,
} = &self;

let mut buf = Vec::default();
Expand All @@ -163,6 +236,9 @@ impl Action for ConfigureNix {
}
buf.append(&mut place_nix_configuration.describe_revert());
buf.append(&mut setup_default_profile.describe_revert());
if let Some(setup_channels) = setup_channels {
buf.append(&mut setup_channels.describe_revert());
}

buf
}
Expand All @@ -181,6 +257,11 @@ impl Action for ConfigureNix {
if let Err(err) = self.setup_default_profile.try_revert().await {
errors.push(err);
}
if let Some(setup_channels) = &mut self.setup_channels {
if let Err(err) = setup_channels.try_revert().await {
errors.push(err);
}
}

if errors.is_empty() {
Ok(())
Expand All @@ -194,3 +275,22 @@ impl Action for ConfigureNix {
}
}
}

#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
pub enum ConfigureNixError {
#[error("Unarchived Nix store did not appear to include a `nss-cacert` location")]
NoNssCacert,
#[error("Unarchived Nix store did not appear to include a `nix` location")]
NoNix,
#[error("Unarchived Nix store appears to contain multiple `nss-ca-cert` packages, cannot select one")]
MultipleNssCaCertPackages,
#[error("Unarchived Nix store appears to contain multiple `nix` packages, cannot select one")]
MultipleNixPackages,
}

impl From<ConfigureNixError> for ActionErrorKind {
fn from(val: ConfigureNixError) -> Self {
ActionErrorKind::Custom(Box::new(val))
}
}
2 changes: 2 additions & 0 deletions src/action/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub(crate) mod create_users_and_groups;
pub(crate) mod delete_users;
pub(crate) mod place_nix_configuration;
pub(crate) mod provision_nix;
pub(crate) mod setup_channels;

pub use configure_init_service::{ConfigureInitService, ConfigureNixDaemonServiceError};
pub use configure_nix::ConfigureNix;
Expand All @@ -17,3 +18,4 @@ pub use create_users_and_groups::CreateUsersAndGroups;
pub use delete_users::DeleteUsersInGroup;
pub use place_nix_configuration::PlaceNixConfiguration;
pub use provision_nix::ProvisionNix;
pub use setup_channels::SetupChannels;
Loading

0 comments on commit f1857ad

Please sign in to comment.