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