Ensure Planners and Actions can be created externally

Signed-off-by: Ana Hobden <operator@hoverbear.org>
This commit is contained in:
Ana Hobden 2022-10-26 15:13:42 -07:00
parent cc1cbe109a
commit f49c155117
40 changed files with 195 additions and 452 deletions

View file

@ -1,13 +1,12 @@
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use serde::Serialize;
use target_lexicon::OperatingSystem; use target_lexicon::OperatingSystem;
use tokio::fs::remove_file; use tokio::fs::remove_file;
use tokio::process::Command; use tokio::process::Command;
use crate::execute_command; use crate::execute_command;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
const SERVICE_SRC: &str = "/nix/var/nix/profiles/default/lib/systemd/system/nix-daemon.service"; const SERVICE_SRC: &str = "/nix/var/nix/profiles/default/lib/systemd/system/nix-daemon.service";
const SOCKET_SRC: &str = "/nix/var/nix/profiles/default/lib/systemd/system/nix-daemon.socket"; const SOCKET_SRC: &str = "/nix/var/nix/profiles/default/lib/systemd/system/nix-daemon.socket";
@ -44,7 +43,7 @@ impl ConfigureNixDaemonService {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "configure-nix-daemon")] #[typetag::serde(name = "configure-nix-daemon")]
impl Actionable for ConfigureNixDaemonService { impl Action for ConfigureNixDaemonService {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -196,36 +195,23 @@ impl Actionable for ConfigureNixDaemonService {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum ConfigureNixDaemonServiceError { pub enum ConfigureNixDaemonServiceError {
#[error("Symlinking from `{0}` to `{1}`")] #[error("Symlinking from `{0}` to `{1}`")]
Symlink( Symlink(
std::path::PathBuf, std::path::PathBuf,
std::path::PathBuf, std::path::PathBuf,
#[source] #[source] std::io::Error,
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
), ),
#[error("Command failed to execute")] #[error("Command failed to execute")]
CommandFailed( CommandFailed(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Remove file `{0}`")] #[error("Remove file `{0}`")]
RemoveFile( RemoveFile(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Copying file `{0}` to `{1}`")] #[error("Copying file `{0}` to `{1}`")]
Copy( Copy(
std::path::PathBuf, std::path::PathBuf,
std::path::PathBuf, std::path::PathBuf,
#[source] #[source] std::io::Error,
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
), ),
#[error("No supported init system found")] #[error("No supported init system found")]
InitNotSupported, InitNotSupported,

View file

@ -2,10 +2,10 @@ use std::os::unix::prelude::PermissionsExt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use nix::unistd::{chown, Group, User}; use nix::unistd::{chown, Group, User};
use serde::Serialize;
use tokio::fs::{create_dir, remove_dir_all}; use tokio::fs::{create_dir, remove_dir_all};
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct CreateDirectory { pub struct CreateDirectory {
@ -65,7 +65,7 @@ impl CreateDirectory {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "create-directory")] #[typetag::serde(name = "create-directory")]
impl Actionable for CreateDirectory { impl Action for CreateDirectory {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { let Self {
path, path,
@ -213,69 +213,28 @@ impl Actionable for CreateDirectory {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum CreateDirectoryError { pub enum CreateDirectoryError {
#[error(transparent)] #[error(transparent)]
Exists(#[serde(serialize_with = "crate::serialize_error_to_display")] std::io::Error), Exists(std::io::Error),
#[error("Creating directory `{0}`")] #[error("Creating directory `{0}`")]
Creating( Creating(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Removing directory `{0}`")] #[error("Removing directory `{0}`")]
Removing( Removing(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Getting metadata for {0}`")] #[error("Getting metadata for {0}`")]
GettingMetadata( GettingMetadata(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Reading directory `{0}``")] #[error("Reading directory `{0}``")]
ReadDir( ReadDir(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Set mode `{0}` on `{1}`")] #[error("Set mode `{0}` on `{1}`")]
SetPermissions( SetPermissions(u32, std::path::PathBuf, #[source] std::io::Error),
u32,
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Chowning directory `{0}`")] #[error("Chowning directory `{0}`")]
Chown( Chown(std::path::PathBuf, #[source] nix::errno::Errno),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
nix::errno::Errno,
),
#[error("Getting uid for user `{0}`")] #[error("Getting uid for user `{0}`")]
UserId( UserId(String, #[source] nix::errno::Errno),
String,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
nix::errno::Errno,
),
#[error("Getting user `{0}`")] #[error("Getting user `{0}`")]
NoUser(String), NoUser(String),
#[error("Getting gid for group `{0}`")] #[error("Getting gid for group `{0}`")]
GroupId( GroupId(String, #[source] nix::errno::Errno),
String,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
nix::errno::Errno,
),
#[error("Getting group `{0}`")] #[error("Getting group `{0}`")]
NoGroup(String), NoGroup(String),
} }

View file

@ -1,14 +1,14 @@
use nix::unistd::{chown, Group, User}; use nix::unistd::{chown, Group, User};
use serde::Serialize;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use tokio::{ use tokio::{
fs::{remove_file, OpenOptions}, fs::{remove_file, OpenOptions},
io::AsyncWriteExt, io::AsyncWriteExt,
}; };
use crate::actions::{ActionError, ActionState}; use crate::action::{ActionError, ActionState};
use crate::actions::{ActionDescription, Actionable}; use crate::action::{Action, ActionDescription};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct CreateFile { pub struct CreateFile {
@ -51,7 +51,7 @@ impl CreateFile {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "create-file")] #[typetag::serde(name = "create-file")]
impl Actionable for CreateFile { impl Action for CreateFile {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { let Self {
path, path,
@ -189,54 +189,24 @@ impl Actionable for CreateFile {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum CreateFileError { pub enum CreateFileError {
#[error("File exists `{0}`")] #[error("File exists `{0}`")]
Exists(std::path::PathBuf), Exists(std::path::PathBuf),
#[error("Remove file `{0}`")] #[error("Remove file `{0}`")]
RemoveFile( RemoveFile(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Open file `{0}`")] #[error("Open file `{0}`")]
OpenFile( OpenFile(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Write file `{0}`")] #[error("Write file `{0}`")]
WriteFile( WriteFile(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Getting uid for user `{0}`")] #[error("Getting uid for user `{0}`")]
UserId( UserId(String, #[source] nix::errno::Errno),
String,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
nix::errno::Errno,
),
#[error("Getting user `{0}`")] #[error("Getting user `{0}`")]
NoUser(String), NoUser(String),
#[error("Getting gid for group `{0}`")] #[error("Getting gid for group `{0}`")]
GroupId( GroupId(String, #[source] nix::errno::Errno),
String,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
nix::errno::Errno,
),
#[error("Getting group `{0}`")] #[error("Getting group `{0}`")]
NoGroup(String), NoGroup(String),
#[error("Chowning directory `{0}`")] #[error("Chowning directory `{0}`")]
Chown( Chown(std::path::PathBuf, #[source] nix::errno::Errno),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
nix::errno::Errno,
),
} }

View file

@ -1,9 +1,8 @@
use serde::Serialize;
use tokio::process::Command; use tokio::process::Command;
use crate::execute_command; use crate::execute_command;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct CreateGroup { pub struct CreateGroup {
@ -25,7 +24,7 @@ impl CreateGroup {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "create-group")] #[typetag::serde(name = "create-group")]
impl Actionable for CreateGroup { impl Action for CreateGroup {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { let Self {
name, name,
@ -156,12 +155,8 @@ impl Actionable for CreateGroup {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum CreateGroupError { pub enum CreateGroupError {
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -1,5 +1,5 @@
use nix::unistd::{chown, Group, User}; use nix::unistd::{chown, Group, User};
use serde::Serialize;
use std::{ use std::{
io::SeekFrom, io::SeekFrom,
os::unix::prelude::PermissionsExt, os::unix::prelude::PermissionsExt,
@ -10,9 +10,9 @@ use tokio::{
io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt}, io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt},
}; };
use crate::actions::{ActionError, ActionState}; use crate::action::{ActionError, ActionState};
use crate::actions::{ActionDescription, Actionable}; use crate::action::{Action, ActionDescription};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct CreateOrAppendFile { pub struct CreateOrAppendFile {
@ -48,7 +48,7 @@ impl CreateOrAppendFile {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "create-or-append-file")] #[typetag::serde(name = "create-or-append-file")]
impl Actionable for CreateOrAppendFile { impl Action for CreateOrAppendFile {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { let Self {
path, path,
@ -224,74 +224,28 @@ impl Actionable for CreateOrAppendFile {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum CreateOrAppendFileError { pub enum CreateOrAppendFileError {
#[error("Remove file `{0}`")] #[error("Remove file `{0}`")]
RemoveFile( RemoveFile(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Remove file `{0}`")] #[error("Remove file `{0}`")]
ReadFile( ReadFile(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Open file `{0}`")] #[error("Open file `{0}`")]
OpenFile( OpenFile(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Write file `{0}`")] #[error("Write file `{0}`")]
WriteFile( WriteFile(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Seek file `{0}`")] #[error("Seek file `{0}`")]
SeekFile( SeekFile(std::path::PathBuf, #[source] std::io::Error),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Getting uid for user `{0}`")] #[error("Getting uid for user `{0}`")]
UserId( UserId(String, #[source] nix::errno::Errno),
String,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
nix::errno::Errno,
),
#[error("Getting user `{0}`")] #[error("Getting user `{0}`")]
NoUser(String), NoUser(String),
#[error("Getting gid for group `{0}`")] #[error("Getting gid for group `{0}`")]
GroupId( GroupId(String, #[source] nix::errno::Errno),
String,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
nix::errno::Errno,
),
#[error("Getting group `{0}`")] #[error("Getting group `{0}`")]
NoGroup(String), NoGroup(String),
#[error("Set mode `{0}` on `{1}`")] #[error("Set mode `{0}` on `{1}`")]
SetPermissions( SetPermissions(u32, std::path::PathBuf, #[source] std::io::Error),
u32,
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("Chowning directory `{0}`")] #[error("Chowning directory `{0}`")]
Chown( Chown(std::path::PathBuf, #[source] nix::errno::Errno),
std::path::PathBuf,
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
nix::errno::Errno,
),
} }

View file

@ -1,9 +1,8 @@
use serde::Serialize;
use tokio::process::Command; use tokio::process::Command;
use crate::execute_command; use crate::execute_command;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct CreateUser { pub struct CreateUser {
@ -29,7 +28,7 @@ impl CreateUser {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "create-user")] #[typetag::serde(name = "create-user")]
impl Actionable for CreateUser { impl Action for CreateUser {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -254,12 +253,8 @@ impl Actionable for CreateUser {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum CreateUserError { pub enum CreateUserError {
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -1,11 +1,10 @@
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use serde::Serialize;
use tokio::process::Command; use tokio::process::Command;
use crate::execute_command; use crate::execute_command;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct BootstrapVolume { pub struct BootstrapVolume {
@ -27,7 +26,7 @@ impl BootstrapVolume {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "bootstrap-volume")] #[typetag::serde(name = "bootstrap-volume")]
impl Actionable for BootstrapVolume { impl Action for BootstrapVolume {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -106,12 +105,8 @@ impl Actionable for BootstrapVolume {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum BootstrapVolumeError { pub enum BootstrapVolumeError {
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -1,9 +1,8 @@
use serde::Serialize;
use tokio::process::Command; use tokio::process::Command;
use crate::execute_command; use crate::execute_command;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionState};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct CreateSyntheticObjects { pub struct CreateSyntheticObjects {
@ -21,7 +20,7 @@ impl CreateSyntheticObjects {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "create-synthetic-objects")] #[typetag::serde(name = "create-synthetic-objects")]
impl Actionable for CreateSyntheticObjects { impl Action for CreateSyntheticObjects {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -101,12 +100,8 @@ impl Actionable for CreateSyntheticObjects {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum CreateSyntheticObjectsError { pub enum CreateSyntheticObjectsError {
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -1,11 +1,10 @@
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use serde::Serialize;
use tokio::process::Command; use tokio::process::Command;
use crate::execute_command; use crate::execute_command;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct CreateVolume { pub struct CreateVolume {
@ -33,7 +32,7 @@ impl CreateVolume {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "create-volume")] #[typetag::serde(name = "create-volume")]
impl Actionable for CreateVolume { impl Action for CreateVolume {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -130,12 +129,8 @@ impl Actionable for CreateVolume {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum CreateVolumeError { pub enum CreateVolumeError {
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -1,12 +1,11 @@
use std::io::Cursor; use std::io::Cursor;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use serde::Serialize;
use tokio::process::Command; use tokio::process::Command;
use crate::execute_command; use crate::execute_command;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
use crate::os::darwin::DiskUtilOutput; use crate::os::darwin::DiskUtilOutput;
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
@ -29,7 +28,7 @@ impl EnableOwnership {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "enable-ownership")] #[typetag::serde(name = "enable-ownership")]
impl Actionable for EnableOwnership { impl Action for EnableOwnership {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -109,12 +108,8 @@ impl Actionable for EnableOwnership {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum EnableOwnershipError { pub enum EnableOwnershipError {
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -1,7 +1,6 @@
use serde::Serialize;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionState};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct EncryptVolume { pub struct EncryptVolume {
@ -26,7 +25,7 @@ impl EncryptVolume {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "encrypt-volume")] #[typetag::serde(name = "encrypt-volume")]
impl Actionable for EncryptVolume { impl Action for EncryptVolume {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -89,12 +88,8 @@ impl Actionable for EncryptVolume {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum EncryptVolumeError { pub enum EncryptVolumeError {
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -1,9 +1,8 @@
use serde::Serialize;
use tokio::process::Command; use tokio::process::Command;
use crate::execute_command; use crate::execute_command;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct KickstartLaunchctlService { pub struct KickstartLaunchctlService {
@ -23,7 +22,7 @@ impl KickstartLaunchctlService {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "kickstart-launchctl-service")] #[typetag::serde(name = "kickstart-launchctl-service")]
impl Actionable for KickstartLaunchctlService { impl Action for KickstartLaunchctlService {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { unit, action_state } = self; let Self { unit, action_state } = self;
if *action_state == ActionState::Completed { if *action_state == ActionState::Completed {
@ -97,12 +96,8 @@ impl Actionable for KickstartLaunchctlService {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum KickstartLaunchctlServiceError { pub enum KickstartLaunchctlServiceError {
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -1,11 +1,10 @@
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use serde::Serialize;
use tokio::process::Command; use tokio::process::Command;
use crate::execute_command; use crate::execute_command;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct UnmountVolume { pub struct UnmountVolume {
@ -31,7 +30,7 @@ impl UnmountVolume {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "unmount-volume")] #[typetag::serde(name = "unmount-volume")]
impl Actionable for UnmountVolume { impl Action for UnmountVolume {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -117,12 +116,8 @@ impl Actionable for UnmountVolume {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum UnmountVolumeError { pub enum UnmountVolumeError {
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -2,10 +2,10 @@ use std::path::PathBuf;
use bytes::Buf; use bytes::Buf;
use reqwest::Url; use reqwest::Url;
use serde::Serialize;
use tokio::task::JoinError; use tokio::task::JoinError;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct FetchNix { pub struct FetchNix {
@ -30,7 +30,7 @@ impl FetchNix {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "fetch-nix")] #[typetag::serde(name = "fetch-nix")]
impl Actionable for FetchNix { impl Action for FetchNix {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { let Self {
url, url,
@ -114,26 +114,20 @@ impl Actionable for FetchNix {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum FetchNixError { pub enum FetchNixError {
#[error("Joining spawned async task")] #[error("Joining spawned async task")]
Join( Join(
#[source] #[source]
#[from] #[from]
#[serde(serialize_with = "crate::serialize_error_to_display")]
JoinError, JoinError,
), ),
#[error("Request error")] #[error("Request error")]
Reqwest( Reqwest(
#[from] #[from]
#[source] #[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
reqwest::Error, reqwest::Error,
), ),
#[error("Unarchiving error")] #[error("Unarchiving error")]
Unarchive( Unarchive(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -1,8 +1,6 @@
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use serde::Serialize; use crate::action::{Action, ActionDescription, ActionError, ActionState};
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable};
const DEST: &str = "/nix/store"; const DEST: &str = "/nix/store";
@ -25,7 +23,7 @@ impl MoveUnpackedNix {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "mount-unpacked-nix")] #[typetag::serde(name = "mount-unpacked-nix")]
impl Actionable for MoveUnpackedNix { impl Action for MoveUnpackedNix {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -107,28 +105,24 @@ impl Actionable for MoveUnpackedNix {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum MoveUnpackedNixError { pub enum MoveUnpackedNixError {
#[error("Glob pattern error")] #[error("Glob pattern error")]
GlobPatternError( GlobPatternError(
#[from] #[from]
#[source] #[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
glob::PatternError, glob::PatternError,
), ),
#[error("Glob globbing error")] #[error("Glob globbing error")]
GlobGlobError( GlobGlobError(
#[from] #[from]
#[source] #[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
glob::GlobError, glob::GlobError,
), ),
#[error("Rename `{0}` to `{1}`")] #[error("Rename `{0}` to `{1}`")]
Rename( Rename(
std::path::PathBuf, std::path::PathBuf,
std::path::PathBuf, std::path::PathBuf,
#[source] #[source] std::io::Error,
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
), ),
} }

View file

@ -1,13 +1,13 @@
use crate::{ use crate::{
actions::{ActionError, ActionState}, action::{ActionError, ActionState},
execute_command, set_env, execute_command, set_env,
}; };
use glob::glob; use glob::glob;
use serde::Serialize;
use tokio::process::Command; use tokio::process::Command;
use crate::actions::{ActionDescription, Actionable}; use crate::action::{Action, ActionDescription};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct SetupDefaultProfile { pub struct SetupDefaultProfile {
@ -27,7 +27,7 @@ impl SetupDefaultProfile {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "setup-default-profile")] #[typetag::serde(name = "setup-default-profile")]
impl Actionable for SetupDefaultProfile { impl Action for SetupDefaultProfile {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -184,30 +184,24 @@ impl Actionable for SetupDefaultProfile {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum SetupDefaultProfileError { pub enum SetupDefaultProfileError {
#[error("Glob pattern error")] #[error("Glob pattern error")]
GlobPatternError( GlobPatternError(
#[from] #[from]
#[source] #[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
glob::PatternError, glob::PatternError,
), ),
#[error("Glob globbing error")] #[error("Glob globbing error")]
GlobGlobError( GlobGlobError(
#[from] #[from]
#[source] #[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
glob::GlobError, glob::GlobError,
), ),
#[error("Unarchived Nix store did not appear to include a `nss-cacert` location")] #[error("Unarchived Nix store did not appear to include a `nss-cacert` location")]
NoNssCacert, NoNssCacert,
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
#[error("No root home found to place channel configuration in")] #[error("No root home found to place channel configuration in")]
NoRootHome, NoRootHome,
} }

View file

@ -1,9 +1,8 @@
use serde::Serialize;
use tokio::process::Command; use tokio::process::Command;
use crate::execute_command; use crate::execute_command;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct StartSystemdUnit { pub struct StartSystemdUnit {
@ -23,7 +22,7 @@ impl StartSystemdUnit {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "start-systemd-unit")] #[typetag::serde(name = "start-systemd-unit")]
impl Actionable for StartSystemdUnit { impl Action for StartSystemdUnit {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -98,12 +97,8 @@ impl Actionable for StartSystemdUnit {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum StartSystemdUnitError { pub enum StartSystemdUnitError {
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -1,11 +1,10 @@
use std::path::PathBuf; use std::path::PathBuf;
use serde::Serialize;
use tokio::process::Command; use tokio::process::Command;
use crate::execute_command; use crate::execute_command;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct SystemdSysextMerge { pub struct SystemdSysextMerge {
@ -25,7 +24,7 @@ impl SystemdSysextMerge {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "systemd-sysext-merge")] #[typetag::serde(name = "systemd-sysext-merge")]
impl Actionable for SystemdSysextMerge { impl Action for SystemdSysextMerge {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { let Self {
action_state, action_state,
@ -102,12 +101,8 @@ impl Actionable for SystemdSysextMerge {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum SystemdSysextMergeError { pub enum SystemdSysextMergeError {
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -1,23 +1,16 @@
use reqwest::Url; use reqwest::Url;
use serde::Serialize;
use crate::CommonSettings; use crate::CommonSettings;
use crate::{ use crate::{
actions::{ action::{
base::{ base::{ConfigureNixDaemonService, SetupDefaultProfile},
ConfigureNixDaemonService, ConfigureNixDaemonServiceError, SetupDefaultProfile, meta::{ConfigureShellProfile, PlaceChannelConfiguration, PlaceNixConfiguration},
SetupDefaultProfileError,
},
meta::{
ConfigureShellProfile, ConfigureShellProfileError, PlaceChannelConfiguration,
PlaceChannelConfigurationError, PlaceNixConfiguration, PlaceNixConfigurationError,
},
ActionState, ActionState,
}, },
cli::arg::ChannelValue, cli::arg::ChannelValue,
}; };
use crate::actions::{ActionDescription, ActionError, Actionable}; use crate::action::{Action, ActionDescription, ActionError};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct ConfigureNix { pub struct ConfigureNix {
@ -73,7 +66,7 @@ impl ConfigureNix {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "configure-nix")] #[typetag::serde(name = "configure-nix")]
impl Actionable for ConfigureNix { impl Action for ConfigureNix {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { let Self {
setup_default_profile, setup_default_profile,

View file

@ -1,10 +1,9 @@
use std::path::Path; use std::path::Path;
use serde::Serialize;
use tokio::task::{JoinError, JoinSet}; use tokio::task::{JoinError, JoinSet};
use crate::actions::base::{CreateOrAppendFile, CreateOrAppendFileError}; use crate::action::base::{CreateOrAppendFile, CreateOrAppendFileError};
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
const PROFILE_TARGETS: &[&str] = &[ const PROFILE_TARGETS: &[&str] = &[
"/etc/bashrc", "/etc/bashrc",
@ -57,7 +56,7 @@ impl ConfigureShellProfile {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "configure-shell-profile")] #[typetag::serde(name = "configure-shell-profile")]
impl Actionable for ConfigureShellProfile { impl Action for ConfigureShellProfile {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]

View file

@ -1,7 +1,5 @@
use serde::Serialize; use crate::action::base::{CreateDirectory, CreateDirectoryError};
use crate::action::{Action, ActionDescription, ActionState};
use crate::actions::base::{CreateDirectory, CreateDirectoryError};
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable};
const PATHS: &[&str] = &[ const PATHS: &[&str] = &[
"/nix/var", "/nix/var",
@ -43,7 +41,7 @@ impl CreateNixTree {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "creat-nix-tree")] #[typetag::serde(name = "creat-nix-tree")]
impl Actionable for CreateNixTree { impl Action for CreateNixTree {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -138,7 +136,7 @@ impl Actionable for CreateNixTree {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum CreateNixTreeError { pub enum CreateNixTreeError {
#[error("Creating directory")] #[error("Creating directory")]
CreateDirectory( CreateDirectory(

View file

@ -1,8 +1,7 @@
use serde::Serialize;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use crate::actions::base::{CreateDirectory, CreateDirectoryError, CreateFile, CreateFileError}; use crate::action::base::{CreateDirectory, CreateDirectoryError, CreateFile, CreateFileError};
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
const PATHS: &[&str] = &[ const PATHS: &[&str] = &[
"usr", "usr",
@ -91,7 +90,7 @@ impl CreateSystemdSysext {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "create-systemd-sysext")] #[typetag::serde(name = "create-systemd-sysext")]
impl Actionable for CreateSystemdSysext { impl Action for CreateSystemdSysext {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { let Self {
action_state: _, action_state: _,
@ -185,7 +184,7 @@ impl Actionable for CreateSystemdSysext {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum CreateSystemdSysextError { pub enum CreateSystemdSysextError {
#[error(transparent)] #[error(transparent)]
CreateDirectory(#[from] CreateDirectoryError), CreateDirectory(#[from] CreateDirectoryError),
@ -195,7 +194,6 @@ pub enum CreateSystemdSysextError {
ReadingOsRelease( ReadingOsRelease(
#[source] #[source]
#[from] #[from]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error, std::io::Error,
), ),
#[error("No `VERSION_ID` line in /etc/os-release")] #[error("No `VERSION_ID` line in /etc/os-release")]

View file

@ -1,10 +1,11 @@
use serde::Serialize;
use tokio::task::{JoinError, JoinSet}; use tokio::task::{JoinError, JoinSet};
use crate::CommonSettings; use crate::CommonSettings;
use crate::actions::base::{CreateGroup, CreateGroupError, CreateUserError}; use crate::action::{
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable, CreateUser}; base::{CreateGroup, CreateGroupError, CreateUser, CreateUserError},
Action, ActionDescription, ActionError, ActionState,
};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct CreateUsersAndGroup { pub struct CreateUsersAndGroup {
@ -52,7 +53,7 @@ impl CreateUsersAndGroup {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "create-users-and-group")] #[typetag::serde(name = "create-users-and-group")]
impl Actionable for CreateUsersAndGroup { impl Action for CreateUsersAndGroup {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { let Self {
daemon_user_count, daemon_user_count,

View file

@ -1,11 +1,10 @@
use serde::Serialize;
use std::{ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
time::Duration, time::Duration,
}; };
use tokio::process::Command; use tokio::process::Command;
use crate::actions::{ use crate::action::{
base::{ base::{
darwin::{ darwin::{
BootstrapVolume, BootstrapVolumeError, CreateSyntheticObjects, BootstrapVolume, BootstrapVolumeError, CreateSyntheticObjects,
@ -17,7 +16,7 @@ use crate::actions::{
}, },
ActionError, ActionError,
}; };
use crate::actions::{ActionDescription, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionState};
const NIX_VOLUME_MOUNTD_DEST: &str = "/Library/LaunchDaemons/org.nixos.darwin-store.plist"; const NIX_VOLUME_MOUNTD_DEST: &str = "/Library/LaunchDaemons/org.nixos.darwin-store.plist";
@ -147,7 +146,7 @@ impl CreateApfsVolume {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "create-apfs-volume")] #[typetag::serde(name = "create-apfs-volume")]
impl Actionable for CreateApfsVolume { impl Action for CreateApfsVolume {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { let Self {
disk, disk,
@ -292,7 +291,7 @@ impl Actionable for CreateApfsVolume {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum CreateApfsVolumeError { pub enum CreateApfsVolumeError {
#[error(transparent)] #[error(transparent)]
CreateFile(#[from] CreateFileError), CreateFile(#[from] CreateFileError),
@ -311,9 +310,5 @@ pub enum CreateApfsVolumeError {
#[error(transparent)] #[error(transparent)]
CreateOrAppendFile(#[from] CreateOrAppendFileError), CreateOrAppendFile(#[from] CreateOrAppendFileError),
#[error("Failed to execute command")] #[error("Failed to execute command")]
Command( Command(#[source] std::io::Error),
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
} }

View file

@ -11,7 +11,7 @@ mod place_nix_configuration;
mod provision_nix; mod provision_nix;
pub use configure_nix::ConfigureNix; pub use configure_nix::ConfigureNix;
pub use configure_shell_profile::{ConfigureShellProfile, ConfigureShellProfileError}; pub use configure_shell_profile::ConfigureShellProfile;
pub use create_nix_tree::{CreateNixTree, CreateNixTreeError}; pub use create_nix_tree::{CreateNixTree, CreateNixTreeError};
pub use create_systemd_sysext::{CreateSystemdSysext, CreateSystemdSysextError}; pub use create_systemd_sysext::{CreateSystemdSysext, CreateSystemdSysextError};
pub use create_users_and_group::{CreateUsersAndGroup, CreateUsersAndGroupError}; pub use create_users_and_group::{CreateUsersAndGroup, CreateUsersAndGroupError};

View file

@ -1,9 +1,8 @@
use reqwest::Url; use reqwest::Url;
use serde::Serialize;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
use crate::actions::base::{CreateFile, CreateFileError}; use crate::action::base::{CreateFile, CreateFileError};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct PlaceChannelConfiguration { pub struct PlaceChannelConfiguration {
@ -44,7 +43,7 @@ impl PlaceChannelConfiguration {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "place-channel-configuration")] #[typetag::serde(name = "place-channel-configuration")]
impl Actionable for PlaceChannelConfiguration { impl Action for PlaceChannelConfiguration {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { let Self {
channels: _, channels: _,
@ -130,7 +129,7 @@ impl Actionable for PlaceChannelConfiguration {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum PlaceChannelConfigurationError { pub enum PlaceChannelConfigurationError {
#[error("Creating file")] #[error("Creating file")]
CreateFile( CreateFile(

View file

@ -1,8 +1,6 @@
use serde::Serialize; use crate::action::{Action, ActionDescription, ActionState};
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::base::{CreateDirectory, CreateDirectoryError, CreateFile, CreateFileError};
use crate::actions::base::{CreateDirectory, CreateDirectoryError, CreateFile, CreateFileError};
const NIX_CONF_FOLDER: &str = "/etc/nix"; const NIX_CONF_FOLDER: &str = "/etc/nix";
const NIX_CONF: &str = "/etc/nix/nix.conf"; const NIX_CONF: &str = "/etc/nix/nix.conf";
@ -45,7 +43,7 @@ impl PlaceNixConfiguration {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "place-nix-configuration")] #[typetag::serde(name = "place-nix-configuration")]
impl Actionable for PlaceNixConfiguration { impl Action for PlaceNixConfiguration {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
if self.action_state == ActionState::Completed { if self.action_state == ActionState::Completed {
vec![] vec![]
@ -119,7 +117,7 @@ impl Actionable for PlaceNixConfiguration {
} }
} }
#[derive(Debug, thiserror::Error, Serialize)] #[derive(Debug, thiserror::Error)]
pub enum PlaceNixConfigurationError { pub enum PlaceNixConfigurationError {
#[error("Creating file")] #[error("Creating file")]
CreateFile( CreateFile(

View file

@ -1,14 +1,13 @@
use std::path::PathBuf; use std::path::PathBuf;
use serde::Serialize;
use tokio::task::JoinError; use tokio::task::JoinError;
use crate::actions::base::{ use crate::action::base::{
CreateDirectoryError, FetchNix, FetchNixError, MoveUnpackedNix, MoveUnpackedNixError, CreateDirectoryError, FetchNix, FetchNixError, MoveUnpackedNix, MoveUnpackedNixError,
}; };
use crate::CommonSettings; use crate::CommonSettings;
use crate::actions::{ActionDescription, ActionError, ActionState, Actionable}; use crate::action::{Action, ActionDescription, ActionError, ActionState};
use super::{CreateNixTree, CreateNixTreeError, CreateUsersAndGroup, CreateUsersAndGroupError}; use super::{CreateNixTree, CreateNixTreeError, CreateUsersAndGroup, CreateUsersAndGroupError};
@ -51,7 +50,7 @@ impl ProvisionNix {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "provision-nix")] #[typetag::serde(name = "provision-nix")]
impl Actionable for ProvisionNix { impl Action for ProvisionNix {
fn describe_execute(&self) -> Vec<ActionDescription> { fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { let Self {
fetch_nix, fetch_nix,

View file

@ -1,22 +1,7 @@
pub mod base; pub mod base;
pub mod meta; pub mod meta;
use base::{ use serde::{Deserialize, Serialize};
ConfigureNixDaemonService, ConfigureNixDaemonServiceError, CreateDirectory,
CreateDirectoryError, CreateFile, CreateFileError, CreateGroup, CreateGroupError,
CreateOrAppendFile, CreateOrAppendFileError, CreateUser, CreateUserError, FetchNix,
FetchNixError, MoveUnpackedNix, MoveUnpackedNixError, SetupDefaultProfile,
SetupDefaultProfileError, StartSystemdUnit, StartSystemdUnitError, SystemdSysextMerge,
SystemdSysextMergeError,
};
use meta::{
darwin::{CreateApfsVolume, CreateApfsVolumeError},
ConfigureNix, ConfigureShellProfile, ConfigureShellProfileError, CreateNixTree,
CreateNixTreeError, CreateSystemdSysext, CreateSystemdSysextError, CreateUsersAndGroup,
CreateUsersAndGroupError, PlaceChannelConfiguration, PlaceChannelConfigurationError,
PlaceNixConfiguration, PlaceNixConfigurationError, ProvisionNix, ProvisionNixError,
};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
pub trait ActionError: std::error::Error + Send + Sync { pub trait ActionError: std::error::Error + Send + Sync {
fn boxed(self) -> Box<dyn std::error::Error + Send + Sync> fn boxed(self) -> Box<dyn std::error::Error + Send + Sync>
@ -31,7 +16,7 @@ impl<E> ActionError for E where E: std::error::Error + Send + Sized + Sync {}
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(tag = "action")] #[typetag::serde(tag = "action")]
pub trait Actionable: Send + Sync + std::fmt::Debug + dyn_clone::DynClone { pub trait Action: Send + Sync + std::fmt::Debug + dyn_clone::DynClone {
fn describe_execute(&self) -> Vec<ActionDescription>; fn describe_execute(&self) -> Vec<ActionDescription>;
fn describe_revert(&self) -> Vec<ActionDescription>; fn describe_revert(&self) -> Vec<ActionDescription>;
@ -40,7 +25,7 @@ pub trait Actionable: Send + Sync + std::fmt::Debug + dyn_clone::DynClone {
async fn revert(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>>; async fn revert(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
} }
dyn_clone::clone_trait_object!(Actionable); dyn_clone::clone_trait_object!(Action);
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub enum ActionState { pub enum ActionState {

View file

@ -50,7 +50,7 @@ impl CommandExecute for Install {
.wrap_err("Reading plan")?; .wrap_err("Reading plan")?;
serde_json::from_str(&install_plan_string)? serde_json::from_str(&install_plan_string)?
}, },
None => planner.plan().await?, None => planner.plan().await.map_err(|e| eyre!(e))?,
}; };
if !no_confirm { if !no_confirm {

View file

@ -25,10 +25,12 @@ impl CommandExecute for Plan {
let planner = match planner { let planner = match planner {
Some(planner) => planner, Some(planner) => planner,
None => BuiltinPlanner::default().await?, None => BuiltinPlanner::default()
.await
.map_err(|e| eyre::eyre!(e))?,
}; };
let install_plan = planner.plan().await?; let install_plan = planner.plan().await.map_err(|e| eyre::eyre!(e))?;
let json = serde_json::to_string_pretty(&install_plan)?; let json = serde_json::to_string_pretty(&install_plan)?;
tokio::fs::write(plan, json) tokio::fs::write(plan, json)

View file

@ -1,18 +1,18 @@
mod actions; pub mod action;
pub mod cli; pub mod cli;
mod error; mod error;
mod interaction; mod interaction;
mod os; mod os;
mod plan; mod plan;
mod planner; pub mod planner;
mod settings; mod settings;
use std::{ffi::OsStr, fmt::Display, process::Output}; use std::{ffi::OsStr, process::Output};
pub use error::HarmonicError; pub use error::HarmonicError;
pub use plan::InstallPlan; pub use plan::InstallPlan;
pub use planner::BuiltinPlanner; use planner::BuiltinPlanner;
use serde::Serializer;
pub use settings::CommonSettings; pub use settings::CommonSettings;
use tokio::process::Command; use tokio::process::Command;
@ -42,11 +42,3 @@ fn set_env(k: impl AsRef<OsStr>, v: impl AsRef<OsStr>) {
tracing::trace!("Setting env"); tracing::trace!("Setting env");
std::env::set_var(k.as_ref(), v.as_ref()); std::env::set_var(k.as_ref(), v.as_ref());
} }
fn serialize_error_to_display<E, S>(err: &E, ser: S) -> Result<S::Ok, S::Error>
where
E: Display,
S: Serializer,
{
ser.serialize_str(&format!("{err:#}"))
}

View file

@ -1,15 +1,16 @@
use std::path::PathBuf; use std::path::PathBuf;
use crate::{ use crate::{
actions::{ActionDescription, Actionable}, action::{Action, ActionDescription},
planner::Planner,
BuiltinPlanner, HarmonicError, BuiltinPlanner, HarmonicError,
}; };
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct InstallPlan { pub struct InstallPlan {
pub(crate) actions: Vec<Box<dyn Actionable>>, pub(crate) actions: Vec<Box<dyn Action>>,
pub(crate) planner: BuiltinPlanner, pub(crate) planner: Box<dyn Planner>,
} }
impl InstallPlan { impl InstallPlan {

View file

@ -4,13 +4,13 @@ use clap::ArgAction;
use tokio::process::Command; use tokio::process::Command;
use crate::{ use crate::{
actions::{ action::{
base::darwin::KickstartLaunchctlService, base::darwin::KickstartLaunchctlService,
meta::{darwin::CreateApfsVolume, ConfigureNix, ProvisionNix}, meta::{darwin::CreateApfsVolume, ConfigureNix, ProvisionNix},
}, },
execute_command, execute_command,
os::darwin::DiskUtilOutput, os::darwin::DiskUtilOutput,
planner::{BuiltinPlannerError, Plannable}, planner::{BuiltinPlannerError, Planner},
BuiltinPlanner, CommonSettings, InstallPlan, BuiltinPlanner, CommonSettings, InstallPlan,
}; };
@ -42,12 +42,9 @@ async fn default_root_disk() -> Result<String, BuiltinPlannerError> {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl Plannable for DarwinMulti { #[typetag::serde(name = "darwin-multi")]
const DISPLAY_STRING: &'static str = "Darwin Multi-User"; impl Planner for DarwinMulti {
const SLUG: &'static str = "darwin-multi"; async fn default() -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
type Error = BuiltinPlannerError;
async fn default() -> Result<Self, Self::Error> {
Ok(Self { Ok(Self {
settings: CommonSettings::default()?, settings: CommonSettings::default()?,
root_disk: Some(default_root_disk().await?), root_disk: Some(default_root_disk().await?),
@ -56,7 +53,7 @@ impl Plannable for DarwinMulti {
}) })
} }
async fn plan(self) -> Result<crate::InstallPlan, Self::Error> { async fn plan(self) -> Result<crate::InstallPlan, Box<dyn std::error::Error + Sync + Send>> {
let root_disk = { let root_disk = {
let buf = let buf =
execute_command(Command::new("/usr/sbin/diskutil").args(["info", "-plist", "/"])) execute_command(Command::new("/usr/sbin/diskutil").args(["info", "-plist", "/"]))
@ -71,7 +68,7 @@ impl Plannable for DarwinMulti {
let volume_label = "Nix Store".into(); let volume_label = "Nix Store".into();
Ok(InstallPlan { Ok(InstallPlan {
planner: self.clone().into(), planner: Box::new(self.clone()),
actions: vec![ actions: vec![
// Create Volume step: // Create Volume step:
// //

View file

@ -1,9 +1,9 @@
use crate::{ use crate::{
actions::{ action::{
base::{CreateDirectory, StartSystemdUnit}, base::{CreateDirectory, StartSystemdUnit},
meta::{ConfigureNix, ProvisionNix}, meta::{ConfigureNix, ProvisionNix},
}, },
planner::{BuiltinPlannerError, Plannable}, planner::{BuiltinPlannerError, Planner},
BuiltinPlanner, CommonSettings, InstallPlan, BuiltinPlanner, CommonSettings, InstallPlan,
}; };
@ -14,20 +14,17 @@ pub struct LinuxMulti {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl Plannable for LinuxMulti { #[typetag::serde(name = "linux-multi")]
const DISPLAY_STRING: &'static str = "Linux Multi-User"; impl Planner for LinuxMulti {
const SLUG: &'static str = "linux-multi"; async fn default() -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
type Error = BuiltinPlannerError;
async fn default() -> Result<Self, Self::Error> {
Ok(Self { Ok(Self {
settings: CommonSettings::default()?, settings: CommonSettings::default()?,
}) })
} }
async fn plan(self) -> Result<InstallPlan, Self::Error> { async fn plan(self) -> Result<InstallPlan, Box<dyn std::error::Error + Sync + Send>> {
Ok(InstallPlan { Ok(InstallPlan {
planner: self.clone().into(), planner: Box::new(self.clone()),
actions: vec![ actions: vec![
Box::new(CreateDirectory::plan("/nix", None, None, 0o0755, true).await?), Box::new(CreateDirectory::plan("/nix", None, None, 0o0755, true).await?),
Box::new(ProvisionNix::plan(self.settings.clone()).await?), Box::new(ProvisionNix::plan(self.settings.clone()).await?),

View file

@ -2,7 +2,18 @@ pub mod darwin;
pub mod linux; pub mod linux;
pub mod specific; pub mod specific;
use crate::{actions::ActionError, settings::InstallSettingsError, InstallPlan}; use crate::{action::ActionError, settings::InstallSettingsError, InstallPlan};
#[async_trait::async_trait]
#[typetag::serde(tag = "planner")]
pub trait Planner: std::fmt::Debug + Send + Sync + dyn_clone::DynClone {
async fn default() -> Result<Self, Box<dyn std::error::Error + Sync + Send>>
where
Self: Sized;
async fn plan(self) -> Result<InstallPlan, Box<dyn std::error::Error + Sync + Send>>;
}
dyn_clone::clone_trait_object!(Planner);
#[derive(Debug, Clone, clap::Subcommand, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, clap::Subcommand, serde::Serialize, serde::Deserialize)]
pub enum BuiltinPlanner { pub enum BuiltinPlanner {
@ -12,7 +23,7 @@ pub enum BuiltinPlanner {
} }
impl BuiltinPlanner { impl BuiltinPlanner {
pub async fn default() -> Result<Self, BuiltinPlannerError> { pub async fn default() -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
use target_lexicon::{Architecture, OperatingSystem}; use target_lexicon::{Architecture, OperatingSystem};
match (Architecture::host(), OperatingSystem::host()) { match (Architecture::host(), OperatingSystem::host()) {
(Architecture::X86_64, OperatingSystem::Linux) => { (Architecture::X86_64, OperatingSystem::Linux) => {
@ -29,13 +40,11 @@ impl BuiltinPlanner {
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => { | (Architecture::Aarch64(_), OperatingSystem::Darwin) => {
Ok(Self::DarwinMulti(darwin::DarwinMulti::default().await?)) Ok(Self::DarwinMulti(darwin::DarwinMulti::default().await?))
}, },
_ => Err(BuiltinPlannerError::UnsupportedArchitecture( _ => Err(BuiltinPlannerError::UnsupportedArchitecture(target_lexicon::HOST).boxed()),
target_lexicon::HOST,
)),
} }
} }
pub async fn plan(self) -> Result<InstallPlan, BuiltinPlannerError> { pub async fn plan(self) -> Result<InstallPlan, Box<dyn std::error::Error + Sync + Send>> {
match self { match self {
BuiltinPlanner::LinuxMulti(planner) => planner.plan().await, BuiltinPlanner::LinuxMulti(planner) => planner.plan().await,
BuiltinPlanner::DarwinMulti(planner) => planner.plan().await, BuiltinPlanner::DarwinMulti(planner) => planner.plan().await,
@ -44,19 +53,6 @@ impl BuiltinPlanner {
} }
} }
#[async_trait::async_trait]
trait Plannable
where
Self: Sized,
{
const DISPLAY_STRING: &'static str;
const SLUG: &'static str;
type Error: std::error::Error;
async fn default() -> Result<Self, Self::Error>;
async fn plan(self) -> Result<InstallPlan, Self::Error>;
}
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum BuiltinPlannerError { pub enum BuiltinPlannerError {
#[error("Harmonic does not have a default planner for the `{0}` architecture right now, pass a specific archetype")] #[error("Harmonic does not have a default planner for the `{0}` architecture right now, pass a specific archetype")]

View file

@ -1,9 +1,9 @@
use crate::{ use crate::{
actions::{ action::{
base::{CreateDirectory, StartSystemdUnit}, base::{CreateDirectory, StartSystemdUnit},
meta::{CreateSystemdSysext, ProvisionNix}, meta::{CreateSystemdSysext, ProvisionNix},
}, },
planner::{BuiltinPlannerError, Plannable}, planner::{BuiltinPlannerError, Planner},
BuiltinPlanner, CommonSettings, InstallPlan, BuiltinPlanner, CommonSettings, InstallPlan,
}; };
@ -14,20 +14,17 @@ pub struct SteamDeck {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl Plannable for SteamDeck { #[typetag::serde(name = "steam-deck")]
const DISPLAY_STRING: &'static str = "Steam Deck (x86_64 Linux Multi-User)"; impl Planner for SteamDeck {
const SLUG: &'static str = "steam-deck"; async fn default() -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
type Error = BuiltinPlannerError;
async fn default() -> Result<Self, Self::Error> {
Ok(Self { Ok(Self {
settings: CommonSettings::default()?, settings: CommonSettings::default()?,
}) })
} }
async fn plan(self) -> Result<crate::InstallPlan, Self::Error> { async fn plan(self) -> Result<crate::InstallPlan, Box<dyn std::error::Error + Sync + Send>> {
Ok(InstallPlan { Ok(InstallPlan {
planner: self.clone().into(), planner: Box::new(self.clone()),
actions: vec![ actions: vec![
Box::new(CreateSystemdSysext::plan("/var/lib/extensions").await?), Box::new(CreateSystemdSysext::plan("/var/lib/extensions").await?),
Box::new(CreateDirectory::plan("/nix", None, None, 0o0755, true).await?), Box::new(CreateDirectory::plan("/nix", None, None, 0o0755, true).await?),