forked from lix-project/lix-installer
Use a vec for the plan instead of specifics
This commit is contained in:
parent
cdec8549ff
commit
2bd6cf1e65
7 changed files with 140 additions and 120 deletions
55
Cargo.lock
generated
55
Cargo.lock
generated
|
@ -390,6 +390,15 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "erased-serde"
|
||||
version = "0.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54558e0ba96fbe24280072642eceb9d7d442e32c7ec0ea9e7ecd7b4ea2cf4e11"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "2.5.3"
|
||||
|
@ -558,6 +567,17 @@ dependencies = [
|
|||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ghost"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb19fe8de3ea0920d282f7b77dd4227aea6b8b999b42cdf0ca41b2472b14443a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.26.2"
|
||||
|
@ -629,6 +649,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"tracing-error",
|
||||
"tracing-subscriber",
|
||||
"typetag",
|
||||
"url",
|
||||
"valuable",
|
||||
"walkdir",
|
||||
|
@ -762,6 +783,16 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e21e0a36a4dc4b469422ee17f715e8313f4a637675656d6a13637954278c6f55"
|
||||
dependencies = [
|
||||
"ctor",
|
||||
"ghost",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iovec"
|
||||
version = "0.1.4"
|
||||
|
@ -1652,6 +1683,30 @@ version = "0.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
|
||||
|
||||
[[package]]
|
||||
name = "typetag"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23c8909f61359cac318f10dc9a3f9a7ee2155b6511f2a0c973460222ae5a00bb"
|
||||
dependencies = [
|
||||
"erased-serde",
|
||||
"inventory",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"typetag-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typetag-impl"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd4d8ff674190866d3437d2f725355d49e99e3b1a513bf7ee43dcfe7effc36f4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.8"
|
||||
|
|
|
@ -34,3 +34,4 @@ walkdir = "2.3.2"
|
|||
serde = { version = "1.0.144", features = ["derive"] }
|
||||
url = { version = "2.3.1", features = ["serde"] }
|
||||
serde_json = "1.0.85"
|
||||
typetag = "0.2.3"
|
||||
|
|
|
@ -8,6 +8,7 @@ use base::{
|
|||
FetchNixError, MoveUnpackedNix, MoveUnpackedNixError, SetupDefaultProfile,
|
||||
SetupDefaultProfileError,
|
||||
};
|
||||
use futures::Future;
|
||||
use meta::{
|
||||
ConfigureNix, ConfigureNixError, ConfigureShellProfile, ConfigureShellProfileError,
|
||||
CreateNixTree, CreateNixTreeError, CreateUsersAndGroup, CreateUsersAndGroupError,
|
||||
|
|
|
@ -22,7 +22,7 @@ pub(crate) struct Execute {
|
|||
default_value = "false",
|
||||
global = true
|
||||
)]
|
||||
pub(crate) explain: bool,
|
||||
explain: bool,
|
||||
#[clap(default_value = "/dev/stdin")]
|
||||
plan: PathBuf,
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ pub(crate) struct Plan {
|
|||
env = "HARMONIC_CHANNEL",
|
||||
default_value = "nixpkgs=https://nixos.org/channels/nixpkgs-unstable"
|
||||
)]
|
||||
pub(crate) channel: Vec<crate::cli::arg::ChannelValue>,
|
||||
channel: Vec<crate::cli::arg::ChannelValue>,
|
||||
/// Don't modify the user profile to automatically load nix
|
||||
#[clap(
|
||||
long,
|
||||
|
@ -26,17 +26,17 @@ pub(crate) struct Plan {
|
|||
default_value = "false",
|
||||
global = true
|
||||
)]
|
||||
pub(crate) no_modify_profile: bool,
|
||||
no_modify_profile: bool,
|
||||
/// Number of build users to create
|
||||
#[clap(long, default_value = "32", env = "HARMONIC_NIX_DAEMON_USER_COUNT")]
|
||||
pub(crate) daemon_user_count: usize,
|
||||
daemon_user_count: usize,
|
||||
#[clap(
|
||||
long,
|
||||
action(ArgAction::SetTrue),
|
||||
default_value = "false",
|
||||
global = true
|
||||
)]
|
||||
pub(crate) force: bool,
|
||||
force: bool,
|
||||
#[clap(default_value = "/dev/stdout")]
|
||||
plan: PathBuf,
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ pub(crate) struct Uninstall {
|
|||
default_value = "false",
|
||||
global = true
|
||||
)]
|
||||
pub(crate) explain: bool,
|
||||
explain: bool,
|
||||
#[clap(default_value = "/nix/receipt.json")]
|
||||
receipt: PathBuf,
|
||||
}
|
||||
|
|
191
src/plan.rs
191
src/plan.rs
|
@ -3,7 +3,7 @@ use std::path::PathBuf;
|
|||
use crate::{
|
||||
actions::{
|
||||
meta::{ConfigureNix, ProvisionNix, StartNixDaemon},
|
||||
ActionDescription, ActionError, Actionable,
|
||||
Action, ActionDescription, ActionError, Actionable,
|
||||
},
|
||||
settings::InstallSettings,
|
||||
HarmonicError,
|
||||
|
@ -13,52 +13,33 @@ use crate::{
|
|||
pub struct InstallPlan {
|
||||
settings: InstallSettings,
|
||||
|
||||
/** Bootstrap the install
|
||||
|
||||
* There are roughly three phases:
|
||||
* "Create nix tree"":
|
||||
* download_nix --------------------------------------> move_downloaded_nix
|
||||
* create_group -> create_users -> create_directories -> move_downloaded_nix
|
||||
* place_channel_configuration
|
||||
* place_nix_configuration
|
||||
* ---
|
||||
* "Configure Nix":
|
||||
* setup_default_profile
|
||||
* configure_nix_daemon_service
|
||||
* configure_shell_profile
|
||||
* ---
|
||||
* "Start Nix"
|
||||
* start_nix_daemon_service
|
||||
*/
|
||||
provision_nix: ProvisionNix,
|
||||
configure_nix: ConfigureNix,
|
||||
start_nix_daemon: StartNixDaemon,
|
||||
actions: Vec<Action>,
|
||||
}
|
||||
|
||||
impl InstallPlan {
|
||||
pub async fn new(settings: InstallSettings) -> Result<Self, HarmonicError> {
|
||||
Ok(Self {
|
||||
settings: settings.clone(),
|
||||
provision_nix: ProvisionNix::plan(settings.clone())
|
||||
.await
|
||||
.map_err(|e| ActionError::from(e))?,
|
||||
configure_nix: ConfigureNix::plan(settings)
|
||||
.await
|
||||
.map_err(|e| ActionError::from(e))?,
|
||||
start_nix_daemon: StartNixDaemon::plan()
|
||||
.await
|
||||
.map_err(|e| ActionError::from(e))?,
|
||||
actions: vec![
|
||||
ProvisionNix::plan(settings.clone())
|
||||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
ConfigureNix::plan(settings)
|
||||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
StartNixDaemon::plan()
|
||||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub fn describe_execute(&self, explain: bool) -> String {
|
||||
let Self {
|
||||
settings,
|
||||
provision_nix,
|
||||
configure_nix,
|
||||
start_nix_daemon,
|
||||
} = self;
|
||||
let Self { settings, actions } = self;
|
||||
format!(
|
||||
"\
|
||||
This Nix install is for:\n\
|
||||
|
@ -77,66 +58,53 @@ impl InstallPlan {
|
|||
.map(|(name, url)| format!("{name}={url}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(","),
|
||||
actions = {
|
||||
let mut buf = provision_nix.describe_execute();
|
||||
buf.append(&mut configure_nix.describe_execute());
|
||||
buf.append(&mut start_nix_daemon.describe_execute());
|
||||
buf.iter()
|
||||
.map(|desc| {
|
||||
let ActionDescription {
|
||||
description,
|
||||
explanation,
|
||||
} = desc;
|
||||
actions = actions
|
||||
.iter()
|
||||
.map(|v| v.describe_execute())
|
||||
.flatten()
|
||||
.map(|desc| {
|
||||
let ActionDescription {
|
||||
description,
|
||||
explanation,
|
||||
} = desc;
|
||||
|
||||
let mut buf = String::default();
|
||||
buf.push_str(&format!("* {description}\n"));
|
||||
if explain {
|
||||
for line in explanation {
|
||||
buf.push_str(&format!(" {line}\n"));
|
||||
}
|
||||
let mut buf = String::default();
|
||||
buf.push_str(&format!("* {description}\n"));
|
||||
if explain {
|
||||
for line in explanation {
|
||||
buf.push_str(&format!(" {line}\n"));
|
||||
}
|
||||
buf
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
},
|
||||
}
|
||||
buf
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n"),
|
||||
)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn install(&mut self) -> Result<(), HarmonicError> {
|
||||
let Self {
|
||||
actions,
|
||||
settings: _,
|
||||
} = self;
|
||||
|
||||
// This is **deliberately sequential**.
|
||||
// Actions which are parallelizable are represented by "group actions" like CreateUsers
|
||||
// The plan itself represents the concept of the sequence of stages.
|
||||
|
||||
if let Err(err) = self.provision_nix.execute().await {
|
||||
write_receipt(self.clone()).await?;
|
||||
return Err(ActionError::from(err).into());
|
||||
for action in actions {
|
||||
if let Err(err) = action.execute().await {
|
||||
write_receipt(self.clone()).await?;
|
||||
return Err(ActionError::from(err).into());
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(err) = self.configure_nix.execute().await {
|
||||
write_receipt(self.clone()).await?;
|
||||
return Err(ActionError::from(err).into());
|
||||
}
|
||||
|
||||
if let Err(err) = self.start_nix_daemon.execute().await {
|
||||
write_receipt(self.clone()).await?;
|
||||
return Err(ActionError::from(err).into());
|
||||
}
|
||||
|
||||
write_receipt(self.clone()).await?;
|
||||
|
||||
Ok(())
|
||||
write_receipt(self.clone()).await
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub fn describe_revert(&self, explain: bool) -> String {
|
||||
let Self {
|
||||
settings,
|
||||
provision_nix,
|
||||
configure_nix,
|
||||
start_nix_daemon,
|
||||
} = self;
|
||||
let Self { settings, actions } = self;
|
||||
format!(
|
||||
"\
|
||||
This Nix uninstall is for:\n\
|
||||
|
@ -155,50 +123,45 @@ impl InstallPlan {
|
|||
.map(|(name, url)| format!("{name}={url}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(","),
|
||||
actions = {
|
||||
let mut buf = provision_nix.describe_revert();
|
||||
buf.append(&mut configure_nix.describe_revert());
|
||||
buf.append(&mut start_nix_daemon.describe_revert());
|
||||
buf.iter()
|
||||
.map(|desc| {
|
||||
let ActionDescription {
|
||||
description,
|
||||
explanation,
|
||||
} = desc;
|
||||
actions = actions
|
||||
.iter()
|
||||
.map(|v| v.describe_revert())
|
||||
.flatten()
|
||||
.map(|desc| {
|
||||
let ActionDescription {
|
||||
description,
|
||||
explanation,
|
||||
} = desc;
|
||||
|
||||
let mut buf = String::default();
|
||||
buf.push_str(&format!("* {description}\n"));
|
||||
if explain {
|
||||
for line in explanation {
|
||||
buf.push_str(&format!(" {line}\n"));
|
||||
}
|
||||
let mut buf = String::default();
|
||||
buf.push_str(&format!("* {description}\n"));
|
||||
if explain {
|
||||
for line in explanation {
|
||||
buf.push_str(&format!(" {line}\n"));
|
||||
}
|
||||
buf
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
},
|
||||
}
|
||||
buf
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n"),
|
||||
)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn revert(&mut self) -> Result<(), HarmonicError> {
|
||||
let Self {
|
||||
actions,
|
||||
settings: _,
|
||||
} = self;
|
||||
|
||||
// This is **deliberately sequential**.
|
||||
// Actions which are parallelizable are represented by "group actions" like CreateUsers
|
||||
// The plan itself represents the concept of the sequence of stages.
|
||||
if let Err(err) = self.start_nix_daemon.revert().await {
|
||||
write_receipt(self.clone()).await?;
|
||||
return Err(ActionError::from(err).into());
|
||||
}
|
||||
|
||||
if let Err(err) = self.configure_nix.revert().await {
|
||||
write_receipt(self.clone()).await?;
|
||||
return Err(ActionError::from(err).into());
|
||||
}
|
||||
|
||||
if let Err(err) = self.provision_nix.revert().await {
|
||||
write_receipt(self.clone()).await?;
|
||||
return Err(ActionError::from(err).into());
|
||||
for action in actions {
|
||||
if let Err(err) = action.revert().await {
|
||||
write_receipt(self.clone()).await?;
|
||||
return Err(ActionError::from(err).into());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Reference in a new issue