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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,9 +1,8 @@
use serde::Serialize;
use tokio::process::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)]
pub struct KickstartLaunchctlService {
@ -23,7 +22,7 @@ impl KickstartLaunchctlService {
#[async_trait::async_trait]
#[typetag::serde(name = "kickstart-launchctl-service")]
impl Actionable for KickstartLaunchctlService {
impl Action for KickstartLaunchctlService {
fn describe_execute(&self) -> Vec<ActionDescription> {
let Self { unit, action_state } = self;
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 {
#[error("Failed to execute command")]
Command(
#[source]
#[serde(serialize_with = "crate::serialize_error_to_display")]
std::io::Error,
),
Command(#[source] std::io::Error),
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -11,7 +11,7 @@ mod place_nix_configuration;
mod provision_nix;
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_systemd_sysext::{CreateSystemdSysext, CreateSystemdSysextError};
pub use create_users_and_group::{CreateUsersAndGroup, CreateUsersAndGroupError};

View file

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

View file

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

View file

@ -1,22 +1,7 @@
pub mod base;
pub mod meta;
use base::{
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};
use serde::{Deserialize, Serialize};
pub trait ActionError: 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]
#[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_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>>;
}
dyn_clone::clone_trait_object!(Actionable);
dyn_clone::clone_trait_object!(Action);
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub enum ActionState {

View file

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

View file

@ -25,10 +25,12 @@ impl CommandExecute for Plan {
let planner = match 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)?;
tokio::fs::write(plan, json)

View file

@ -1,18 +1,18 @@
mod actions;
pub mod action;
pub mod cli;
mod error;
mod interaction;
mod os;
mod plan;
mod planner;
pub mod planner;
mod settings;
use std::{ffi::OsStr, fmt::Display, process::Output};
use std::{ffi::OsStr, process::Output};
pub use error::HarmonicError;
pub use plan::InstallPlan;
pub use planner::BuiltinPlanner;
use serde::Serializer;
use planner::BuiltinPlanner;
pub use settings::CommonSettings;
use tokio::process::Command;
@ -42,11 +42,3 @@ fn set_env(k: impl AsRef<OsStr>, v: impl AsRef<OsStr>) {
tracing::trace!("Setting env");
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 crate::{
actions::{ActionDescription, Actionable},
action::{Action, ActionDescription},
planner::Planner,
BuiltinPlanner, HarmonicError,
};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
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 {

View file

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

View file

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

View file

@ -2,7 +2,18 @@ pub mod darwin;
pub mod linux;
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)]
pub enum BuiltinPlanner {
@ -12,7 +23,7 @@ pub enum 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};
match (Architecture::host(), OperatingSystem::host()) {
(Architecture::X86_64, OperatingSystem::Linux) => {
@ -29,13 +40,11 @@ impl BuiltinPlanner {
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => {
Ok(Self::DarwinMulti(darwin::DarwinMulti::default().await?))
},
_ => Err(BuiltinPlannerError::UnsupportedArchitecture(
target_lexicon::HOST,
)),
_ => Err(BuiltinPlannerError::UnsupportedArchitecture(target_lexicon::HOST).boxed()),
}
}
pub async fn plan(self) -> Result<InstallPlan, BuiltinPlannerError> {
pub async fn plan(self) -> Result<InstallPlan, Box<dyn std::error::Error + Sync + Send>> {
match self {
BuiltinPlanner::LinuxMulti(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)]
pub enum BuiltinPlannerError {
#[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::{
actions::{
action::{
base::{CreateDirectory, StartSystemdUnit},
meta::{CreateSystemdSysext, ProvisionNix},
},
planner::{BuiltinPlannerError, Plannable},
planner::{BuiltinPlannerError, Planner},
BuiltinPlanner, CommonSettings, InstallPlan,
};
@ -14,20 +14,17 @@ pub struct SteamDeck {
}
#[async_trait::async_trait]
impl Plannable for SteamDeck {
const DISPLAY_STRING: &'static str = "Steam Deck (x86_64 Linux Multi-User)";
const SLUG: &'static str = "steam-deck";
type Error = BuiltinPlannerError;
async fn default() -> Result<Self, Self::Error> {
#[typetag::serde(name = "steam-deck")]
impl Planner for SteamDeck {
async fn default() -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
Ok(Self {
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 {
planner: self.clone().into(),
planner: Box::new(self.clone()),
actions: vec![
Box::new(CreateSystemdSysext::plan("/var/lib/extensions").await?),
Box::new(CreateDirectory::plan("/nix", None, None, 0o0755, true).await?),