Create all actions
This commit is contained in:
parent
0e843d3e5d
commit
38cc094381
12
rustfmt.toml
Normal file
12
rustfmt.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Put a trailing comma after a block based match arm (non-block arms are not affected)
|
||||
match_block_trailing_comma = true
|
||||
# Merge multiple derives into a single one.
|
||||
merge_derives = true
|
||||
# Reorder import and extern crate statements alphabetically in groups (a group is separated by a newline).
|
||||
reorder_imports = true
|
||||
# Reorder mod declarations alphabetically in group.
|
||||
reorder_modules = true
|
||||
# Use field initialize shorthand if possible.
|
||||
use_field_init_shorthand = true
|
||||
# Replace uses of the try! macro by the ? shorthand
|
||||
use_try_shorthand = true
|
53
src/actions/configure_nix.rs
Normal file
53
src/actions/configure_nix.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use crate::{HarmonicError, InstallSettings};
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct ConfigureNix {}
|
||||
|
||||
impl ConfigureNix {
|
||||
pub fn plan(settings: InstallSettings) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for ConfigureNix {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Start the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct ConfigureNixReceipt {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for ConfigureNixReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Stop the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
todo!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
53
src/actions/configure_nix_daemon_service.rs
Normal file
53
src/actions/configure_nix_daemon_service.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use crate::HarmonicError;
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct ConfigureNixDaemonService {}
|
||||
|
||||
impl ConfigureNixDaemonService {
|
||||
pub fn plan() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for ConfigureNixDaemonService {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Start the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct ConfigureNixDaemonServiceReceipt {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for ConfigureNixDaemonServiceReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Stop the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
todo!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
53
src/actions/configure_shell_profile.rs
Normal file
53
src/actions/configure_shell_profile.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use crate::HarmonicError;
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct ConfigureShellProfile {}
|
||||
|
||||
impl ConfigureShellProfile {
|
||||
pub fn plan() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for ConfigureShellProfile {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Start the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct ConfigureShellProfileReceipt {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for ConfigureShellProfileReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Stop the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
todo!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
89
src/actions/create_directory.rs
Normal file
89
src/actions/create_directory.rs
Normal file
|
@ -0,0 +1,89 @@
|
|||
use std::{
|
||||
fs::Permissions,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use crate::HarmonicError;
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateDirectory {
|
||||
path: PathBuf,
|
||||
user: String,
|
||||
group: String,
|
||||
mode: u32,
|
||||
}
|
||||
|
||||
impl CreateDirectory {
|
||||
pub fn plan(path: impl AsRef<Path>, user: String, group: String, mode: u32) -> Self {
|
||||
let path = path.as_ref().to_path_buf();
|
||||
Self {
|
||||
path,
|
||||
user,
|
||||
group,
|
||||
mode,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for CreateDirectory {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(
|
||||
format!("Create the directory `/nix`"),
|
||||
vec![format!(
|
||||
"Nix and the Nix daemon require a Nix Store, which will be stored at `/nix`"
|
||||
)],
|
||||
)]
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
let Self {
|
||||
path,
|
||||
user,
|
||||
group,
|
||||
mode,
|
||||
} = self;
|
||||
todo!();
|
||||
Ok(ActionReceipt::CreateDirectory(CreateDirectoryReceipt {
|
||||
path,
|
||||
user,
|
||||
group,
|
||||
mode,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateDirectoryReceipt {
|
||||
path: PathBuf,
|
||||
user: String,
|
||||
group: String,
|
||||
mode: u32,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for CreateDirectoryReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(
|
||||
format!("Create the directory `/nix`"),
|
||||
vec![format!(
|
||||
"Nix and the Nix daemon require a Nix Store, which will be stored at `/nix`"
|
||||
)],
|
||||
)]
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
let Self {
|
||||
path,
|
||||
user,
|
||||
group,
|
||||
mode,
|
||||
} = self;
|
||||
|
||||
todo!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
53
src/actions/create_group.rs
Normal file
53
src/actions/create_group.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use crate::HarmonicError;
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateGroup {
|
||||
name: String,
|
||||
uid: usize,
|
||||
}
|
||||
|
||||
impl CreateGroup {
|
||||
pub fn plan(name: String, uid: usize) -> Self {
|
||||
Self { name, uid }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for CreateGroup {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
let name = &self.name;
|
||||
let uid = &self.uid;
|
||||
vec![ActionDescription::new(
|
||||
format!("Create group {name} with UID {uid}"),
|
||||
vec![format!(
|
||||
"The nix daemon requires a system user group its system users can be part of"
|
||||
)],
|
||||
)]
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
let Self { name, uid } = self;
|
||||
Ok(ActionReceipt::CreateGroup(CreateGroupReceipt { name, uid }))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateGroupReceipt {
|
||||
name: String,
|
||||
uid: usize,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for CreateGroupReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
todo!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
47
src/actions/create_nix_tree.rs
Normal file
47
src/actions/create_nix_tree.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
use crate::{HarmonicError, InstallSettings};
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateNixTree {
|
||||
settings: InstallSettings,
|
||||
}
|
||||
|
||||
impl CreateNixTree {
|
||||
pub fn plan(settings: InstallSettings) -> Self {
|
||||
Self { settings }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for CreateNixTree {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(
|
||||
format!("Create a directory tree in `/nix`"),
|
||||
vec![format!(
|
||||
"Nix and the Nix daemon require a Nix Store, which will be stored at `/nix`"
|
||||
)],
|
||||
)]
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
let Self { settings: _ } = self;
|
||||
Ok(ActionReceipt::CreateNixTree(CreateNixTreeReceipt {}))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateNixTreeReceipt {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for CreateNixTreeReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
todo!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
47
src/actions/create_nix_tree_dirs.rs
Normal file
47
src/actions/create_nix_tree_dirs.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
use crate::HarmonicError;
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateNixTreeDirs {}
|
||||
|
||||
impl CreateNixTreeDirs {
|
||||
pub fn plan(name: String, uid: usize) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for CreateNixTreeDirs {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(
|
||||
format!("Create a directory tree in `/nix`"),
|
||||
vec![format!(
|
||||
"Nix and the Nix daemon require a Nix Store, which will be stored at `/nix`"
|
||||
)],
|
||||
)]
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
let Self {} = self;
|
||||
Ok(ActionReceipt::CreateNixTreeDirs(
|
||||
CreateNixTreeDirsReceipt {},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateNixTreeDirsReceipt {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for CreateNixTreeDirsReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
todo!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
use crate::{settings::InstallSettings, HarmonicError};
|
||||
|
||||
use super::{Actionable, ActionReceipt, Revertable, ActionDescription};
|
||||
use crate::HarmonicError;
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateUser {
|
||||
|
@ -9,12 +8,6 @@ pub struct CreateUser {
|
|||
uid: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateUserReceipt {
|
||||
name: String,
|
||||
uid: usize,
|
||||
}
|
||||
|
||||
impl CreateUser {
|
||||
pub fn plan(name: String, uid: usize) -> Self {
|
||||
Self { name, uid }
|
||||
|
@ -26,14 +19,12 @@ impl<'a> Actionable<'a> for CreateUser {
|
|||
fn description(&self) -> Vec<ActionDescription> {
|
||||
let name = &self.name;
|
||||
let uid = &self.uid;
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
vec![ActionDescription::new(
|
||||
format!("Create user {name} with UID {uid}"),
|
||||
vec![
|
||||
format!("The nix daemon requires system users it can act as in order to build"),
|
||||
]
|
||||
)
|
||||
]
|
||||
vec![format!(
|
||||
"The nix daemon requires system users it can act as in order to build"
|
||||
)],
|
||||
)]
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
|
@ -42,6 +33,11 @@ impl<'a> Actionable<'a> for CreateUser {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateUserReceipt {
|
||||
name: String,
|
||||
uid: usize,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for CreateUserReceipt {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use tokio::task::JoinSet;
|
||||
|
||||
use crate::{settings::InstallSettings, HarmonicError};
|
||||
|
||||
use super::{Actionable, CreateUser, ActionReceipt, create_user::CreateUserReceipt, Revertable, ActionDescription};
|
||||
use crate::HarmonicError;
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, CreateUser, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateUsers {
|
||||
|
@ -13,18 +12,26 @@ pub struct CreateUsers {
|
|||
children: Vec<CreateUser>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateUsersReceipt {
|
||||
children: Vec<ActionReceipt>,
|
||||
}
|
||||
|
||||
impl CreateUsers {
|
||||
pub fn plan(nix_build_user_prefix: String, nix_build_user_id_base: usize, daemon_user_count: usize) -> Self {
|
||||
let children = (0..daemon_user_count).map(|count| CreateUser::plan(
|
||||
pub fn plan(
|
||||
nix_build_user_prefix: String,
|
||||
nix_build_user_id_base: usize,
|
||||
daemon_user_count: usize,
|
||||
) -> Self {
|
||||
let children = (0..daemon_user_count)
|
||||
.map(|count| {
|
||||
CreateUser::plan(
|
||||
format!("{nix_build_user_prefix}{count}"),
|
||||
nix_build_user_id_base + count
|
||||
)).collect();
|
||||
Self { nix_build_user_prefix, nix_build_user_id_base, daemon_user_count, children }
|
||||
nix_build_user_id_base + count,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
Self {
|
||||
nix_build_user_prefix,
|
||||
nix_build_user_id_base,
|
||||
daemon_user_count,
|
||||
children,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,16 +86,22 @@ impl<'a> Actionable<'a> for CreateUsers {
|
|||
}
|
||||
|
||||
if errors.len() == 1 {
|
||||
return Err(errors.into_iter().next().unwrap())
|
||||
return Err(errors.into_iter().next().unwrap());
|
||||
} else {
|
||||
return Err(HarmonicError::Multiple(errors))
|
||||
return Err(HarmonicError::Multiple(errors));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ActionReceipt::CreateUsers(CreateUsersReceipt{ children: successes }))
|
||||
Ok(ActionReceipt::CreateUsers(CreateUsersReceipt {
|
||||
children: successes,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateUsersReceipt {
|
||||
children: Vec<ActionReceipt>,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for CreateUsersReceipt {
|
||||
|
|
|
@ -1,77 +1,38 @@
|
|||
mod start_nix_daemon_service;
|
||||
mod create_users;
|
||||
mod configure_nix;
|
||||
mod configure_nix_daemon_service;
|
||||
mod configure_shell_profile;
|
||||
mod create_directory;
|
||||
mod create_group;
|
||||
mod create_nix_tree;
|
||||
mod create_nix_tree_dirs;
|
||||
mod create_user;
|
||||
pub use start_nix_daemon_service::{StartNixDaemonService, StartNixDaemonServiceReceipt};
|
||||
mod create_users;
|
||||
mod place_channel_configuration;
|
||||
mod place_nix_configuration;
|
||||
mod setup_default_profile;
|
||||
mod start_nix_daemon;
|
||||
mod start_systemd_service;
|
||||
|
||||
pub use configure_nix::{ConfigureNix, ConfigureNixReceipt};
|
||||
pub use configure_nix_daemon_service::{
|
||||
ConfigureNixDaemonService, ConfigureNixDaemonServiceReceipt,
|
||||
};
|
||||
pub use configure_shell_profile::{ConfigureShellProfile, ConfigureShellProfileReceipt};
|
||||
pub use create_directory::{CreateDirectory, CreateDirectoryReceipt};
|
||||
pub use create_group::{CreateGroup, CreateGroupReceipt};
|
||||
pub use create_nix_tree::{CreateNixTree, CreateNixTreeReceipt};
|
||||
pub use create_nix_tree_dirs::{CreateNixTreeDirs, CreateNixTreeDirsReceipt};
|
||||
pub use create_user::{CreateUser, CreateUserReceipt};
|
||||
pub use create_users::{CreateUsers, CreateUsersReceipt};
|
||||
pub use place_channel_configuration::{
|
||||
PlaceChannelConfiguration, PlaceChannelConfigurationReceipt,
|
||||
};
|
||||
pub use place_nix_configuration::{PlaceNixConfiguration, PlaceNixConfigurationReceipt};
|
||||
pub use setup_default_profile::{SetupDefaultProfile, SetupDefaultProfileReceipt};
|
||||
pub use start_nix_daemon::{StartNixDaemon, StartNixDaemonReceipt};
|
||||
pub use start_systemd_service::{StartSystemdService, StartSystemdServiceReceipt};
|
||||
|
||||
use crate::{HarmonicError, settings::InstallSettings};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
|
||||
pub struct ActionDescription {
|
||||
pub description: String,
|
||||
pub explanation: Vec<String>,
|
||||
}
|
||||
|
||||
impl ActionDescription {
|
||||
fn new(description: String, explanation: Vec<String>) -> Self {
|
||||
Self { description, explanation }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub enum Action {
|
||||
CreateUsers(CreateUsers),
|
||||
CreateUser(CreateUser),
|
||||
StartNixDaemonService(StartNixDaemonService),
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub enum ActionReceipt {
|
||||
CreateUsers(CreateUsersReceipt),
|
||||
CreateUser(CreateUserReceipt),
|
||||
StartNixDaemonService(StartNixDaemonServiceReceipt),
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for Action {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
match self {
|
||||
Action::StartNixDaemonService(i) => i.description(),
|
||||
Action::CreateUser(i) => i.description(),
|
||||
Action::CreateUsers(i) => i.description(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
match self {
|
||||
Action::StartNixDaemonService(i) => i.execute().await,
|
||||
Action::CreateUser(i) => i.execute().await,
|
||||
Action::CreateUsers(i) => i.execute().await,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for ActionReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
match self {
|
||||
ActionReceipt::StartNixDaemonService(i) => i.description(),
|
||||
ActionReceipt::CreateUser(i) => i.description(),
|
||||
ActionReceipt::CreateUsers(i) => i.description(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
match self {
|
||||
ActionReceipt::StartNixDaemonService(i) => i.revert().await,
|
||||
ActionReceipt::CreateUser(i) => i.revert().await,
|
||||
ActionReceipt::CreateUsers(i) => i.revert().await,
|
||||
}
|
||||
}
|
||||
}
|
||||
use crate::HarmonicError;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait Actionable<'a>: serde::de::Deserialize<'a> + serde::Serialize {
|
||||
|
@ -84,3 +45,137 @@ pub trait Revertable<'a>: serde::de::Deserialize<'a> + serde::Serialize {
|
|||
fn description(&self) -> Vec<ActionDescription>;
|
||||
async fn revert(self) -> Result<(), HarmonicError>;
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
|
||||
pub struct ActionDescription {
|
||||
pub description: String,
|
||||
pub explanation: Vec<String>,
|
||||
}
|
||||
|
||||
impl ActionDescription {
|
||||
fn new(description: String, explanation: Vec<String>) -> Self {
|
||||
Self {
|
||||
description,
|
||||
explanation,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub enum Action {
|
||||
ConfigureNixDaemonService(ConfigureNixDaemonService),
|
||||
ConfigureNix(ConfigureNix),
|
||||
ConfigureShellProfile(ConfigureShellProfile),
|
||||
CreateDirectory(CreateUser),
|
||||
CreateGroup(CreateGroup),
|
||||
CreateNixTreeDirs(CreateNixTreeDirs),
|
||||
CreateNixTree(CreateNixTree),
|
||||
CreateUser(CreateUser),
|
||||
CreateUsers(CreateUsers),
|
||||
PlaceChannelConfiguration(PlaceChannelConfiguration),
|
||||
PlaceNixConfiguration(PlaceNixConfiguration),
|
||||
SetupDefaultProfile(SetupDefaultProfile),
|
||||
StartNixDaemon(StartNixDaemon),
|
||||
StartSystemdService(StartNixDaemon),
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub enum ActionReceipt {
|
||||
ConfigureNixDaemonService(ConfigureNixDaemonServiceReceipt),
|
||||
ConfigureNix(ConfigureNixReceipt),
|
||||
ConfigureShellProfile(ConfigureShellProfileReceipt),
|
||||
CreateDirectory(CreateDirectoryReceipt),
|
||||
CreateGroup(CreateGroupReceipt),
|
||||
CreateNixTreeDirs(CreateNixTreeDirsReceipt),
|
||||
CreateNixTree(CreateNixTreeReceipt),
|
||||
CreateUser(CreateUserReceipt),
|
||||
CreateUsers(CreateUsersReceipt),
|
||||
PlaceChannelConfiguration(PlaceChannelConfigurationReceipt),
|
||||
PlaceNixConfiguration(PlaceNixConfigurationReceipt),
|
||||
SetupDefaultProfile(SetupDefaultProfileReceipt),
|
||||
StartNixDaemon(StartNixDaemonReceipt),
|
||||
StartSystemdService(StartNixDaemonReceipt),
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for Action {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
match self {
|
||||
Action::ConfigureNixDaemonService(i) => i.description(),
|
||||
Action::ConfigureNix(i) => i.description(),
|
||||
Action::ConfigureShellProfile(i) => i.description(),
|
||||
Action::CreateDirectory(i) => i.description(),
|
||||
Action::CreateGroup(i) => i.description(),
|
||||
Action::CreateNixTreeDirs(i) => i.description(),
|
||||
Action::CreateNixTree(i) => i.description(),
|
||||
Action::CreateUser(i) => i.description(),
|
||||
Action::CreateUsers(i) => i.description(),
|
||||
Action::PlaceChannelConfiguration(i) => i.description(),
|
||||
Action::PlaceNixConfiguration(i) => i.description(),
|
||||
Action::SetupDefaultProfile(i) => i.description(),
|
||||
Action::StartNixDaemon(i) => i.description(),
|
||||
Action::StartSystemdService(i) => i.description(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
match self {
|
||||
Action::ConfigureNixDaemonService(i) => i.execute().await,
|
||||
Action::ConfigureNix(i) => i.execute().await,
|
||||
Action::ConfigureShellProfile(i) => i.execute().await,
|
||||
Action::CreateDirectory(i) => i.execute().await,
|
||||
Action::CreateGroup(i) => i.execute().await,
|
||||
Action::CreateNixTreeDirs(i) => i.execute().await,
|
||||
Action::CreateNixTree(i) => i.execute().await,
|
||||
Action::CreateUser(i) => i.execute().await,
|
||||
Action::CreateUsers(i) => i.execute().await,
|
||||
Action::PlaceChannelConfiguration(i) => i.execute().await,
|
||||
Action::PlaceNixConfiguration(i) => i.execute().await,
|
||||
Action::SetupDefaultProfile(i) => i.execute().await,
|
||||
Action::StartNixDaemon(i) => i.execute().await,
|
||||
Action::StartSystemdService(i) => i.execute().await,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for ActionReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
match self {
|
||||
ActionReceipt::ConfigureNixDaemonService(i) => i.description(),
|
||||
ActionReceipt::ConfigureNix(i) => i.description(),
|
||||
ActionReceipt::ConfigureShellProfile(i) => i.description(),
|
||||
ActionReceipt::CreateDirectory(i) => i.description(),
|
||||
ActionReceipt::CreateGroup(i) => i.description(),
|
||||
ActionReceipt::CreateNixTreeDirs(i) => i.description(),
|
||||
ActionReceipt::CreateNixTree(i) => i.description(),
|
||||
ActionReceipt::CreateUser(i) => i.description(),
|
||||
ActionReceipt::CreateUsers(i) => i.description(),
|
||||
ActionReceipt::PlaceChannelConfiguration(i) => i.description(),
|
||||
ActionReceipt::PlaceNixConfiguration(i) => i.description(),
|
||||
ActionReceipt::SetupDefaultProfile(i) => i.description(),
|
||||
ActionReceipt::StartNixDaemon(i) => i.description(),
|
||||
ActionReceipt::StartSystemdService(i) => i.description(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
match self {
|
||||
ActionReceipt::ConfigureNixDaemonService(i) => i.revert().await,
|
||||
ActionReceipt::ConfigureNix(i) => i.revert().await,
|
||||
ActionReceipt::ConfigureShellProfile(i) => i.revert().await,
|
||||
ActionReceipt::CreateDirectory(i) => i.revert().await,
|
||||
ActionReceipt::CreateGroup(i) => i.revert().await,
|
||||
ActionReceipt::CreateNixTreeDirs(i) => i.revert().await,
|
||||
ActionReceipt::CreateNixTree(i) => i.revert().await,
|
||||
ActionReceipt::CreateUser(i) => i.revert().await,
|
||||
ActionReceipt::CreateUsers(i) => i.revert().await,
|
||||
ActionReceipt::PlaceChannelConfiguration(i) => i.revert().await,
|
||||
ActionReceipt::PlaceNixConfiguration(i) => i.revert().await,
|
||||
ActionReceipt::SetupDefaultProfile(i) => i.revert().await,
|
||||
ActionReceipt::StartNixDaemon(i) => i.revert().await,
|
||||
ActionReceipt::StartSystemdService(i) => i.revert().await,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
53
src/actions/place_channel_configuration.rs
Normal file
53
src/actions/place_channel_configuration.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use crate::HarmonicError;
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct PlaceChannelConfiguration {}
|
||||
|
||||
impl PlaceChannelConfiguration {
|
||||
pub fn plan() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for PlaceChannelConfiguration {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Start the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct PlaceChannelConfigurationReceipt {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for PlaceChannelConfigurationReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Stop the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
todo!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
53
src/actions/place_nix_configuration.rs
Normal file
53
src/actions/place_nix_configuration.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use crate::HarmonicError;
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct PlaceNixConfiguration {}
|
||||
|
||||
impl PlaceNixConfiguration {
|
||||
pub fn plan() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for PlaceNixConfiguration {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Start the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct PlaceNixConfigurationReceipt {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for PlaceNixConfigurationReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Stop the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
todo!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,28 +1,18 @@
|
|||
use reqwest::redirect::Action;
|
||||
|
||||
use crate::{settings::InstallSettings, HarmonicError};
|
||||
|
||||
use super::{Actionable, ActionReceipt, Revertable, ActionDescription};
|
||||
use crate::HarmonicError;
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct StartNixDaemonService {
|
||||
pub struct SetupDefaultProfile {}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct StartNixDaemonServiceReceipt {
|
||||
}
|
||||
|
||||
impl StartNixDaemonService {
|
||||
impl SetupDefaultProfile {
|
||||
pub fn plan() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for StartNixDaemonService {
|
||||
impl<'a> Actionable<'a> for SetupDefaultProfile {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
|
@ -39,11 +29,20 @@ impl<'a> Actionable<'a> for StartNixDaemonService {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct SetupDefaultProfileReceipt {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for StartNixDaemonServiceReceipt {
|
||||
impl<'a> Revertable<'a> for SetupDefaultProfileReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
todo!()
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Stop the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
53
src/actions/start_nix_daemon.rs
Normal file
53
src/actions/start_nix_daemon.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use crate::{settings, HarmonicError, InstallSettings};
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct StartNixDaemon {}
|
||||
|
||||
impl StartNixDaemon {
|
||||
pub fn plan(settings: InstallSettings) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for StartNixDaemon {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Start the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct StartNixDaemonReceipt {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for StartNixDaemonReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Stop the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
todo!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
53
src/actions/start_systemd_service.rs
Normal file
53
src/actions/start_systemd_service.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use crate::HarmonicError;
|
||||
|
||||
use super::{ActionDescription, ActionReceipt, Actionable, Revertable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct StartSystemdService {}
|
||||
|
||||
impl StartSystemdService {
|
||||
pub fn plan() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Actionable<'a> for StartSystemdService {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Start the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn execute(self) -> Result<ActionReceipt, HarmonicError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct StartSystemdServiceReceipt {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a> Revertable<'a> for StartSystemdServiceReceipt {
|
||||
fn description(&self) -> Vec<ActionDescription> {
|
||||
vec![
|
||||
ActionDescription::new(
|
||||
"Stop the systemd Nix daemon".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
async fn revert(self) -> Result<(), HarmonicError> {
|
||||
todo!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -57,7 +57,7 @@ impl<'a> Instrumentation {
|
|||
}
|
||||
}
|
||||
EnvFilter::try_new(&format!("{}={}", env!("CARGO_PKG_NAME"), self.log_level()))?
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Ok(filter_layer)
|
||||
|
|
|
@ -8,7 +8,6 @@ use std::process::ExitCode;
|
|||
|
||||
use self::subcommand::HarmonicSubcommand;
|
||||
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub(crate) trait CommandExecute {
|
||||
async fn execute(self) -> eyre::Result<ExitCode>;
|
||||
|
@ -70,23 +69,13 @@ impl CommandExecute for HarmonicCli {
|
|||
} = self;
|
||||
|
||||
match subcommand {
|
||||
Some(HarmonicSubcommand::Plan(plan)) => {
|
||||
return plan.execute().await
|
||||
},
|
||||
Some(HarmonicSubcommand::Execute(execute)) => {
|
||||
return execute.execute().await
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
|
||||
Some(HarmonicSubcommand::Plan(plan)) => plan.execute().await,
|
||||
Some(HarmonicSubcommand::Execute(execute)) => execute.execute().await,
|
||||
None => {
|
||||
let mut settings = InstallSettings::default();
|
||||
|
||||
settings.explain(explain);
|
||||
settings.daemon_user_count(daemon_user_count);
|
||||
settings.nix_build_group_name("nixbld".to_string());
|
||||
settings.nix_build_group_id(30000);
|
||||
settings.nix_build_user_prefix("nixbld".to_string());
|
||||
settings.nix_build_user_id_base(30001);
|
||||
settings.channels(
|
||||
channel
|
||||
.into_iter()
|
||||
|
@ -96,16 +85,16 @@ impl CommandExecute for HarmonicCli {
|
|||
|
||||
let plan = InstallPlan::new(settings).await?;
|
||||
|
||||
|
||||
// TODO(@Hoverbear): Make this smarter
|
||||
if !interaction::confirm(
|
||||
plan.description()
|
||||
)
|
||||
.await?
|
||||
{
|
||||
if !interaction::confirm(plan.description()).await? {
|
||||
interaction::clean_exit_with_message("Okay, didn't do anything! Bye!").await;
|
||||
}
|
||||
|
||||
let _receipt = plan.install().await?;
|
||||
|
||||
Ok(ExitCode::SUCCESS)
|
||||
},
|
||||
}
|
||||
// let mut harmonic = Harmonic::default();
|
||||
|
||||
// harmonic.dry_run(dry_run);
|
||||
|
@ -118,8 +107,6 @@ impl CommandExecute for HarmonicCli {
|
|||
// );
|
||||
// harmonic.modify_profile(!no_modify_profile);
|
||||
|
||||
|
||||
|
||||
// // TODO(@Hoverbear): Make this smarter
|
||||
// if !interaction::confirm(
|
||||
// "\
|
||||
|
@ -151,7 +138,5 @@ impl CommandExecute for HarmonicCli {
|
|||
// harmonic.setup_default_profile().await?;
|
||||
// harmonic.place_nix_configuration().await?;
|
||||
// harmonic.configure_nix_daemon_service().await?;
|
||||
|
||||
Ok(ExitCode::SUCCESS)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
use std::process::ExitCode;
|
||||
|
||||
use clap::{Parser, ArgAction};
|
||||
use harmonic::{InstallSettings, InstallPlan};
|
||||
use tokio::io::{AsyncWriteExt, AsyncReadExt};
|
||||
use clap::{ArgAction, Parser};
|
||||
use harmonic::{InstallPlan, InstallSettings};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
|
||||
use crate::{cli::{arg::ChannelValue, CommandExecute}, interaction};
|
||||
use crate::{
|
||||
cli::{arg::ChannelValue, CommandExecute},
|
||||
interaction,
|
||||
};
|
||||
|
||||
/// An opinionated, experimental Nix installer
|
||||
#[derive(Debug, Parser)]
|
||||
|
@ -15,14 +18,12 @@ pub(crate) struct Execute {
|
|||
default_value = "false",
|
||||
global = true
|
||||
)]
|
||||
no_confirm: bool
|
||||
no_confirm: bool,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl CommandExecute for Execute {
|
||||
#[tracing::instrument(skip_all, fields(
|
||||
|
||||
))]
|
||||
#[tracing::instrument(skip_all, fields())]
|
||||
async fn execute(self) -> eyre::Result<ExitCode> {
|
||||
let Self { no_confirm } = self;
|
||||
|
||||
|
@ -32,17 +33,11 @@ impl CommandExecute for Execute {
|
|||
let plan: InstallPlan = serde_json::from_str(&json)?;
|
||||
|
||||
if !no_confirm {
|
||||
if !interaction::confirm(
|
||||
plan.description()
|
||||
)
|
||||
.await?
|
||||
{
|
||||
if !interaction::confirm(plan.description()).await? {
|
||||
interaction::clean_exit_with_message("Okay, didn't do anything! Bye!").await;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Ok(ExitCode::SUCCESS)
|
||||
}
|
||||
}
|
|
@ -3,10 +3,8 @@ use plan::Plan;
|
|||
mod execute;
|
||||
use execute::Execute;
|
||||
|
||||
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
pub(crate) enum HarmonicSubcommand {
|
||||
Plan(Plan),
|
||||
Execute(Execute),
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::process::ExitCode;
|
||||
|
||||
use clap::{Parser, ArgAction};
|
||||
use harmonic::{InstallSettings, InstallPlan};
|
||||
use clap::{ArgAction, Parser};
|
||||
use harmonic::{InstallPlan, InstallSettings};
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
use crate::cli::{arg::ChannelValue, CommandExecute};
|
||||
|
@ -39,15 +39,15 @@ impl CommandExecute for Plan {
|
|||
no_modify_profile = %self.no_modify_profile,
|
||||
))]
|
||||
async fn execute(self) -> eyre::Result<ExitCode> {
|
||||
let Self { channel, no_modify_profile, daemon_user_count } = self;
|
||||
let Self {
|
||||
channel,
|
||||
no_modify_profile,
|
||||
daemon_user_count,
|
||||
} = self;
|
||||
|
||||
let mut settings = InstallSettings::default();
|
||||
|
||||
settings.daemon_user_count(daemon_user_count);
|
||||
settings.nix_build_group_name("nixbld".to_string());
|
||||
settings.nix_build_group_id(30000);
|
||||
settings.nix_build_user_prefix("nixbld".to_string());
|
||||
settings.nix_build_user_id_base(30001);
|
||||
settings.channels(
|
||||
channel
|
||||
.into_iter()
|
||||
|
|
|
@ -52,5 +52,5 @@ pub enum HarmonicError {
|
|||
#[error("Errors with additional failures during reverts: {}\nDuring Revert:{}", .0.iter().map(|v| format!("{v}")).collect::<Vec<_>>().join(" & "), .1.iter().map(|v| format!("{v}")).collect::<Vec<_>>().join(" & "))]
|
||||
FailedReverts(Vec<HarmonicError>, Vec<HarmonicError>),
|
||||
#[error("Multiple errors: {}", .0.iter().map(|v| format!("{v}")).collect::<Vec<_>>().join(" & "))]
|
||||
Multiple(Vec<HarmonicError>)
|
||||
Multiple(Vec<HarmonicError>),
|
||||
}
|
||||
|
|
|
@ -34,10 +34,10 @@ pub(crate) async fn confirm(question: impl AsRef<str>) -> eyre::Result<bool> {
|
|||
.await?;
|
||||
stdout.flush().await?;
|
||||
break Ok(false);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(Err(err)) => return Err(err).wrap_err("Getting response"),
|
||||
None => return Err(eyre!("Bailed, no confirmation event")),
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
mod error;
|
||||
mod actions;
|
||||
mod error;
|
||||
mod plan;
|
||||
mod settings;
|
||||
|
||||
|
@ -258,7 +258,7 @@ impl Harmonic {
|
|||
// TODO(@Hoverbear): Should probably ensure is unique
|
||||
found_pkg = Some(path);
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(_) => continue, /* Ignore it */
|
||||
};
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ impl Harmonic {
|
|||
// TODO(@Hoverbear): Should probably ensure is unique
|
||||
found_pkg = Some(path);
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(_) => continue, /* Ignore it */
|
||||
};
|
||||
}
|
||||
|
|
48
src/plan.rs
48
src/plan.rs
|
@ -1,8 +1,13 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{settings::InstallSettings, actions::{Action, StartNixDaemonService, Actionable, ActionReceipt, Revertable, CreateUsers, ActionDescription}, HarmonicError};
|
||||
|
||||
|
||||
use crate::{
|
||||
actions::{
|
||||
Action, ActionDescription, ActionReceipt, Actionable, ConfigureNix, CreateNixTree,
|
||||
Revertable, StartNixDaemon,
|
||||
},
|
||||
settings::InstallSettings,
|
||||
HarmonicError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct InstallPlan {
|
||||
|
@ -11,15 +16,18 @@ pub struct InstallPlan {
|
|||
/** 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
|
||||
*/
|
||||
actions: Vec<Action>,
|
||||
|
@ -27,7 +35,8 @@ pub struct InstallPlan {
|
|||
|
||||
impl InstallPlan {
|
||||
pub fn description(&self) -> String {
|
||||
format!("\
|
||||
format!(
|
||||
"\
|
||||
This Nix install is for:\n\
|
||||
Operating System: {os_type}\n\
|
||||
Init system: {init_type}\n\
|
||||
|
@ -38,8 +47,18 @@ impl InstallPlan {
|
|||
",
|
||||
os_type = "Linux",
|
||||
init_type = "systemd",
|
||||
nix_channels = self.settings.channels.iter().map(|(name,url)| format!("{name}={url}")).collect::<Vec<_>>().join(","),
|
||||
actions = self.actions.iter().flat_map(|action| action.description()).map(|desc| {
|
||||
nix_channels = self
|
||||
.settings
|
||||
.channels
|
||||
.iter()
|
||||
.map(|(name, url)| format!("{name}={url}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(","),
|
||||
actions = self
|
||||
.actions
|
||||
.iter()
|
||||
.flat_map(|action| action.description())
|
||||
.map(|desc| {
|
||||
let ActionDescription {
|
||||
description,
|
||||
explanation,
|
||||
|
@ -53,16 +72,16 @@ impl InstallPlan {
|
|||
}
|
||||
}
|
||||
buf
|
||||
}).collect::<Vec<_>>().join("\n"),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n"),
|
||||
)
|
||||
}
|
||||
pub async fn new(settings: InstallSettings) -> Result<Self, HarmonicError> {
|
||||
let start_nix_daemon_service = StartNixDaemonService::plan();
|
||||
let create_users = CreateUsers::plan(settings.nix_build_user_prefix.clone(), settings.nix_build_user_id_base, settings.daemon_user_count);
|
||||
|
||||
let actions = vec![
|
||||
Action::CreateUsers(create_users),
|
||||
Action::StartNixDaemonService(start_nix_daemon_service),
|
||||
Action::CreateNixTree(CreateNixTree::plan(settings.clone())),
|
||||
Action::ConfigureNix(ConfigureNix::plan(settings.clone())),
|
||||
Action::StartNixDaemon(StartNixDaemon::plan(settings.clone())),
|
||||
];
|
||||
Ok(Self { settings, actions })
|
||||
}
|
||||
|
@ -83,11 +102,10 @@ impl InstallPlan {
|
|||
}
|
||||
}
|
||||
if !revert_errs.is_empty() {
|
||||
return Err(HarmonicError::FailedReverts(vec![err], revert_errs))
|
||||
return Err(HarmonicError::FailedReverts(vec![err], revert_errs));
|
||||
}
|
||||
|
||||
return Err(err)
|
||||
|
||||
return Err(err);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use url::Url;
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, Default)]
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct InstallSettings {
|
||||
pub(crate) dry_run: bool,
|
||||
pub(crate) explain: bool,
|
||||
pub(crate) daemon_user_count: usize,
|
||||
pub(crate) channels: Vec<(String, Url)>,
|
||||
|
@ -13,16 +12,27 @@ pub struct InstallSettings {
|
|||
pub(crate) nix_build_user_id_base: usize,
|
||||
}
|
||||
|
||||
impl Default for InstallSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
explain: Default::default(),
|
||||
daemon_user_count: Default::default(),
|
||||
channels: Default::default(),
|
||||
modify_profile: Default::default(),
|
||||
nix_build_group_name: String::from("nixbld"),
|
||||
nix_build_group_id: 3000,
|
||||
nix_build_user_prefix: String::from("nixbld"),
|
||||
nix_build_user_id_base: 3001,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Builder Pattern
|
||||
impl InstallSettings {
|
||||
pub fn explain(&mut self, explain: bool) -> &mut Self {
|
||||
self.explain = explain;
|
||||
self
|
||||
}
|
||||
pub fn dry_run(&mut self, dry_run: bool) -> &mut Self {
|
||||
self.dry_run = dry_run;
|
||||
self
|
||||
}
|
||||
pub fn daemon_user_count(&mut self, count: usize) -> &mut Self {
|
||||
self.daemon_user_count = count;
|
||||
self
|
||||
|
|
Loading…
Reference in a new issue