More fleshing out

This commit is contained in:
Ana Hobden 2022-10-19 13:32:15 -07:00
parent da0219deb0
commit fcc200b9d0
10 changed files with 366 additions and 256 deletions

View file

@ -61,9 +61,36 @@ impl Actionable for CreateGroup {
}
tracing::debug!("Creating group");
execute_command(Command::new("groupadd").args(["-g", &gid.to_string(), "--system", &name]))
.await
.map_err(CreateGroupError::Command)?;
use target_lexicon::OperatingSystem;
match target_lexicon::HOST.operating_system {
OperatingSystem::MacOSX {
major: _,
minor: _,
patch: _,
} => {
execute_command(Command::new("/usr/sbin/dseditgroup").args([
"-o",
"create",
"-r",
"Nix build group for nix-daemon",
"-i",
&format!("{gid}"),
name.as_str(),
]))
.await
.map_err(Self::Error::Command)?;
},
_ => {
execute_command(Command::new("groupadd").args([
"-g",
&gid.to_string(),
"--system",
&name,
]))
.await
.map_err(CreateGroupError::Command)?;
},
};
tracing::trace!("Created group");
*action_state = ActionState::Completed;

View file

@ -67,27 +67,49 @@ impl Actionable for CreateUser {
}
tracing::debug!("Creating user");
execute_command(Command::new("useradd").args([
"--home-dir",
"/var/empty",
"--comment",
&format!("\"Nix build user\""),
"--gid",
&gid.to_string(),
"--groups",
&gid.to_string(),
"--no-user-group",
"--system",
"--shell",
"/sbin/nologin",
"--uid",
&uid.to_string(),
"--password",
"\"!\"",
&name.to_string(),
]))
.await
.map_err(Self::Error::Command)?;
use target_lexicon::OperatingSystem;
match target_lexicon::HOST.operating_system {
OperatingSystem::MacOSX {
major: _,
minor: _,
patch: _,
} => {
execute_command(Command::new("/usr/bin/dscl").args([
".",
"create",
&format!("/Users/{name}"),
"UniqueId",
&format!("{uid}"),
"PrimaryGroupID",
&format!("{gid}"),
]))
.await
.map_err(Self::Error::Command)?;
},
_ => {
execute_command(Command::new("useradd").args([
"--home-dir",
"/var/empty",
"--comment",
&format!("\"Nix build user\""),
"--gid",
&gid.to_string(),
"--groups",
&gid.to_string(),
"--no-user-group",
"--system",
"--shell",
"/sbin/nologin",
"--uid",
&uid.to_string(),
"--password",
"\"!\"",
&name.to_string(),
]))
.await
.map_err(Self::Error::Command)?;
},
}
tracing::trace!("Created user");
*action_state = ActionState::Completed;
@ -132,9 +154,21 @@ impl Actionable for CreateUser {
}
tracing::debug!("Deleting user");
execute_command(Command::new("userdel").args([&name.to_string()]))
.await
.map_err(Self::Error::Command)?;
use target_lexicon::OperatingSystem;
match target_lexicon::HOST.operating_system {
OperatingSystem::MacOSX {
major: _,
minor: _,
patch: _,
} => {
todo!()
},
_ => {
execute_command(Command::new("userdel").args([&name.to_string()]))
.await
.map_err(Self::Error::Command)?;
},
};
tracing::trace!("Deleted user");
*action_state = ActionState::Uncompleted;

View file

@ -1,3 +1,5 @@
use std::path::{Path, PathBuf};
use serde::Serialize;
use tokio::process::Command;
@ -7,15 +9,15 @@ use crate::actions::{Action, ActionDescription, ActionState, Actionable};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct BootstrapVolume {
unit: String,
path: PathBuf,
action_state: ActionState,
}
impl BootstrapVolume {
#[tracing::instrument(skip_all)]
pub async fn plan(unit: String) -> Result<Self, BootstrapVolumeError> {
pub async fn plan(path: impl AsRef<Path>) -> Result<Self, BootstrapVolumeError> {
Ok(Self {
unit,
path: path.as_ref().to_path_buf(),
action_state: ActionState::Uncompleted,
})
}
@ -30,36 +32,35 @@ impl Actionable for BootstrapVolume {
vec![]
} else {
vec![ActionDescription::new(
"Start the systemd Nix service and socket".to_string(),
vec![
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
]
format!("Bootstrap and kickstart `{}`", self.path.display()),
vec![],
)]
}
}
#[tracing::instrument(skip_all, fields(
unit = %self.unit,
path = %self.path.display(),
))]
async fn execute(&mut self) -> Result<(), Self::Error> {
let Self { unit, action_state } = self;
let Self { path, action_state } = self;
if *action_state == ActionState::Completed {
tracing::trace!("Already completed: Starting systemd unit");
tracing::trace!("Already completed: Bootstrapping volume");
return Ok(());
}
tracing::debug!("Starting systemd unit");
tracing::debug!("Bootstrapping volume");
// TODO(@Hoverbear): Handle proxy vars
execute_command(
Command::new("systemctl")
.arg("enable")
.arg("--now")
.arg(format!("{unit}")),
Command::new("launchctl")
.args(["bootstrap", "system"])
.arg(path),
)
.await
.map_err(BootstrapVolumeError::Command)?;
.map_err(Self::Error::Command)?;
execute_command(Command::new("launchctl").args(["-k", "system/org.nixos.darwin-store"]))
.await
.map_err(Self::Error::Command)?;
tracing::trace!("Started systemd unit");
tracing::trace!("Bootstrapped volume");
*action_state = ActionState::Completed;
Ok(())
}
@ -69,31 +70,32 @@ impl Actionable for BootstrapVolume {
vec![]
} else {
vec![ActionDescription::new(
"Stop the systemd Nix service and socket".to_string(),
vec![
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
]
format!("Stop `{}`", self.path.display()),
vec![],
)]
}
}
#[tracing::instrument(skip_all, fields(
unit = %self.unit,
path = %self.path.display(),
))]
async fn revert(&mut self) -> Result<(), Self::Error> {
let Self { unit, action_state } = self;
let Self { path, action_state } = self;
if *action_state == ActionState::Uncompleted {
tracing::trace!("Already reverted: Stopping systemd unit");
tracing::trace!("Already reverted: Stop volume");
return Ok(());
}
tracing::debug!("Stopping systemd unit");
tracing::debug!("Stop volume");
// TODO(@Hoverbear): Handle proxy vars
execute_command(Command::new("systemctl").arg("stop").arg(format!("{unit}")))
.await
.map_err(BootstrapVolumeError::Command)?;
execute_command(
Command::new("launchctl")
.args(["bootout", "system"])
.arg(path),
)
.await
.map_err(Self::Error::Command)?;
tracing::trace!("Stopped systemd unit");
tracing::trace!("Stopped volume");
*action_state = ActionState::Completed;
Ok(())
}

View file

@ -7,15 +7,13 @@ use crate::actions::{Action, ActionDescription, ActionState, Actionable};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct CreateSyntheticObjects {
unit: String,
action_state: ActionState,
}
impl CreateSyntheticObjects {
#[tracing::instrument(skip_all)]
pub async fn plan(unit: String) -> Result<Self, CreateSyntheticObjectsError> {
pub async fn plan() -> Result<Self, CreateSyntheticObjectsError> {
Ok(Self {
unit,
action_state: ActionState::Uncompleted,
})
}
@ -30,36 +28,36 @@ impl Actionable for CreateSyntheticObjects {
vec![]
} else {
vec![ActionDescription::new(
"Start the systemd Nix service and socket".to_string(),
vec![
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
]
"Create objects defined in `/etc/synthetic.conf`".to_string(),
vec!["Populates the `/nix` path".to_string()],
)]
}
}
#[tracing::instrument(skip_all, fields(
unit = %self.unit,
))]
#[tracing::instrument(skip_all, fields())]
async fn execute(&mut self) -> Result<(), Self::Error> {
let Self { unit, action_state } = self;
let Self { action_state } = self;
if *action_state == ActionState::Completed {
tracing::trace!("Already completed: Starting systemd unit");
tracing::trace!("Already completed: Creating synthetic objects");
return Ok(());
}
tracing::debug!("Starting systemd unit");
tracing::debug!("Creating synthetic objects");
// TODO(@Hoverbear): Handle proxy vars
// Yup we literally call both and ignore the error! Reasoning: https://github.com/NixOS/nix/blob/95331cb9c99151cbd790ceb6ddaf49fc1c0da4b3/scripts/create-darwin-volume.sh#L261
execute_command(
Command::new("systemctl")
.arg("enable")
.arg("--now")
.arg(format!("{unit}")),
Command::new("/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util")
.arg("-t"),
)
.await
.map_err(CreateSyntheticObjectsError::Command)?;
.ok(); // Deliberate
execute_command(
Command::new("/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util")
.arg("-B"),
)
.await
.ok(); // Deliberate
tracing::trace!("Started systemd unit");
tracing::trace!("Created synthetic objects");
*action_state = ActionState::Completed;
Ok(())
}
@ -69,31 +67,36 @@ impl Actionable for CreateSyntheticObjects {
vec![]
} else {
vec![ActionDescription::new(
"Stop the systemd Nix service and socket".to_string(),
vec![
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
]
"Refresh the objects defined in `/etc/synthetic.conf`".to_string(),
vec!["Will remove the `/nix` path".to_string()],
)]
}
}
#[tracing::instrument(skip_all, fields(
unit = %self.unit,
))]
#[tracing::instrument(skip_all, fields())]
async fn revert(&mut self) -> Result<(), Self::Error> {
let Self { unit, action_state } = self;
let Self { action_state } = self;
if *action_state == ActionState::Uncompleted {
tracing::trace!("Already reverted: Stopping systemd unit");
tracing::trace!("Already reverted: Refreshing synthetic objects");
return Ok(());
}
tracing::debug!("Stopping systemd unit");
tracing::debug!("Refreshing synthetic objects");
// TODO(@Hoverbear): Handle proxy vars
execute_command(Command::new("systemctl").arg("stop").arg(format!("{unit}")))
.await
.map_err(CreateSyntheticObjectsError::Command)?;
// Yup we literally call both and ignore the error! Reasoning: https://github.com/NixOS/nix/blob/95331cb9c99151cbd790ceb6ddaf49fc1c0da4b3/scripts/create-darwin-volume.sh#L261
execute_command(
Command::new("/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util")
.arg("-t"),
)
.await
.ok(); // Deliberate
execute_command(
Command::new("/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util")
.arg("-B"),
)
.await
.ok(); // Deliberate
tracing::trace!("Stopped systemd unit");
tracing::trace!("Refreshed synthetic objects");
*action_state = ActionState::Completed;
Ok(())
}

View file

@ -1,3 +1,5 @@
use std::path::{Path, PathBuf};
use serde::Serialize;
use tokio::process::Command;
@ -7,15 +9,23 @@ use crate::actions::{Action, ActionDescription, ActionState, Actionable};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct CreateVolume {
unit: String,
disk: PathBuf,
name: String,
case_sensitive: bool,
action_state: ActionState,
}
impl CreateVolume {
#[tracing::instrument(skip_all)]
pub async fn plan(unit: String) -> Result<Self, CreateVolumeError> {
pub async fn plan(
disk: impl AsRef<Path>,
name: String,
case_sensitive: bool,
) -> Result<Self, CreateVolumeError> {
Ok(Self {
unit,
disk: disk.as_ref().to_path_buf(),
name,
case_sensitive,
action_state: ActionState::Uncompleted,
})
}
@ -30,36 +40,50 @@ impl Actionable for CreateVolume {
vec![]
} else {
vec![ActionDescription::new(
"Start the systemd Nix service and socket".to_string(),
vec![
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
]
format!(
"Create a volumne on `{}` named `{}`",
self.disk.display(),
self.name
),
vec![],
)]
}
}
#[tracing::instrument(skip_all, fields(
unit = %self.unit,
disk = %self.disk.display(),
name = %self.name,
case_sensitive = %self.case_sensitive,
))]
async fn execute(&mut self) -> Result<(), Self::Error> {
let Self { unit, action_state } = self;
let Self {
disk,
name,
case_sensitive,
action_state,
} = self;
if *action_state == ActionState::Completed {
tracing::trace!("Already completed: Starting systemd unit");
tracing::trace!("Already completed: Creating volume");
return Ok(());
}
tracing::debug!("Starting systemd unit");
tracing::debug!("Creating volume");
// TODO(@Hoverbear): Handle proxy vars
execute_command(
Command::new("systemctl")
.arg("enable")
.arg("--now")
.arg(format!("{unit}")),
)
execute_command(Command::new("/usr/sbin/diskutil").args([
"apfs",
"addVolume",
&format!("{}", disk.display()),
if !*case_sensitive {
"APFS"
} else {
"Case-sensitive APFS"
},
name,
"-nomount",
]))
.await
.map_err(CreateVolumeError::Command)?;
.map_err(Self::Error::Command)?;
tracing::trace!("Started systemd unit");
tracing::trace!("Created volume");
*action_state = ActionState::Completed;
Ok(())
}
@ -69,31 +93,44 @@ impl Actionable for CreateVolume {
vec![]
} else {
vec![ActionDescription::new(
"Stop the systemd Nix service and socket".to_string(),
vec![
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
]
format!(
"Remove the volume on `{}` named `{}`",
self.disk.display(),
self.name
),
vec![],
)]
}
}
#[tracing::instrument(skip_all, fields(
unit = %self.unit,
disk = %self.disk.display(),
name = %self.name,
case_sensitive = %self.case_sensitive,
))]
async fn revert(&mut self) -> Result<(), Self::Error> {
let Self { unit, action_state } = self;
let Self {
disk,
name,
case_sensitive: _,
action_state,
} = self;
if *action_state == ActionState::Uncompleted {
tracing::trace!("Already reverted: Stopping systemd unit");
tracing::trace!("Already reverted: Deleting volume");
return Ok(());
}
tracing::debug!("Stopping systemd unit");
tracing::debug!("Deleting volume");
// TODO(@Hoverbear): Handle proxy vars
execute_command(Command::new("systemctl").arg("stop").arg(format!("{unit}")))
.await
.map_err(CreateVolumeError::Command)?;
execute_command(Command::new("/usr/sbin/diskutil").args([
"apfs",
"deleteVolume",
&format!("{}", disk.display()),
name,
]))
.await
.map_err(Self::Error::Command)?;
tracing::trace!("Stopped systemd unit");
tracing::trace!("Deleted volume");
*action_state = ActionState::Completed;
Ok(())
}

View file

@ -1,3 +1,5 @@
use std::path::{Path, PathBuf};
use serde::Serialize;
use tokio::process::Command;
@ -7,15 +9,15 @@ use crate::actions::{Action, ActionDescription, ActionState, Actionable};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct EnableOwnership {
unit: String,
path: PathBuf,
action_state: ActionState,
}
impl EnableOwnership {
#[tracing::instrument(skip_all)]
pub async fn plan(unit: String) -> Result<Self, EnableOwnershipError> {
pub async fn plan(path: impl AsRef<Path>) -> Result<Self, EnableOwnershipError> {
Ok(Self {
unit,
path: path.as_ref().to_path_buf(),
action_state: ActionState::Uncompleted,
})
}
@ -30,36 +32,56 @@ impl Actionable for EnableOwnership {
vec![]
} else {
vec![ActionDescription::new(
"Start the systemd Nix service and socket".to_string(),
vec![
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
]
format!("Enable ownership on {}", self.path.display()),
vec![],
)]
}
}
#[tracing::instrument(skip_all, fields(
unit = %self.unit,
path = %self.path.display(),
))]
async fn execute(&mut self) -> Result<(), Self::Error> {
let Self { unit, action_state } = self;
let Self { path, action_state } = self;
if *action_state == ActionState::Completed {
tracing::trace!("Already completed: Starting systemd unit");
tracing::trace!("Already completed: Enabling ownership");
return Ok(());
}
tracing::debug!("Starting systemd unit");
tracing::debug!("Enabling ownership");
// TODO(@Hoverbear): Handle proxy vars
execute_command(
Command::new("systemctl")
.arg("enable")
.arg("--now")
.arg(format!("{unit}")),
)
.await
.map_err(EnableOwnershipError::Command)?;
let should_enable_ownership = {
let buf = execute_command(
Command::new("/usr/sbin/diskutil")
.args(["info", "-plist"])
.arg(&path),
)
.await
.unwrap()
.stdout;
let package = sxd_document::parser::parse(&String::from_utf8(buf).unwrap()).unwrap();
tracing::trace!("Started systemd unit");
match sxd_xpath::evaluate_xpath(
&package.as_document(),
"(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1]",
)
.unwrap()
{
sxd_xpath::Value::Boolean(bool) => bool,
_ => panic!("At the other disk i/o!!!"),
}
};
if should_enable_ownership {
execute_command(
Command::new("/usr/sbin/diskutil")
.arg("enableOwnership")
.arg(path),
)
.await
.map_err(Self::Error::Command)?;
}
tracing::trace!("Enabled ownership");
*action_state = ActionState::Completed;
Ok(())
}
@ -68,32 +90,25 @@ impl Actionable for EnableOwnership {
if self.action_state == ActionState::Uncompleted {
vec![]
} else {
vec![ActionDescription::new(
"Stop the systemd Nix service and socket".to_string(),
vec![
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
]
)]
vec![]
}
}
#[tracing::instrument(skip_all, fields(
unit = %self.unit,
path = %self.path.display(),
))]
async fn revert(&mut self) -> Result<(), Self::Error> {
let Self { unit, action_state } = self;
let Self {
path: _,
action_state,
} = self;
if *action_state == ActionState::Uncompleted {
tracing::trace!("Already reverted: Stopping systemd unit");
tracing::trace!("Already reverted: Unenabling ownership (noop)");
return Ok(());
}
tracing::debug!("Stopping systemd unit");
tracing::debug!("Unenabling ownership (noop)");
// TODO(@Hoverbear): Handle proxy vars
execute_command(Command::new("systemctl").arg("stop").arg(format!("{unit}")))
.await
.map_err(EnableOwnershipError::Command)?;
tracing::trace!("Stopped systemd unit");
tracing::trace!("Unenabled ownership (noop)");
*action_state = ActionState::Completed;
Ok(())
}

View file

@ -1,4 +1,5 @@
use serde::Serialize;
use std::path::{Path, PathBuf};
use tokio::process::Command;
use crate::execute_command;
@ -7,15 +8,20 @@ use crate::actions::{Action, ActionDescription, ActionState, Actionable};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct EncryptVolume {
unit: String,
disk: PathBuf,
password: String,
action_state: ActionState,
}
impl EncryptVolume {
#[tracing::instrument(skip_all)]
pub async fn plan(unit: String) -> Result<Self, EncryptVolumeError> {
pub async fn plan(
disk: impl AsRef<Path>,
password: String,
) -> Result<Self, EncryptVolumeError> {
Ok(Self {
unit,
disk: disk.as_ref().to_path_buf(),
password,
action_state: ActionState::Uncompleted,
})
}
@ -30,36 +36,30 @@ impl Actionable for EncryptVolume {
vec![]
} else {
vec![ActionDescription::new(
"Start the systemd Nix service and socket".to_string(),
vec![
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
]
format!("Encrypt volume `{}`", self.disk.display()),
vec![],
)]
}
}
#[tracing::instrument(skip_all, fields(
unit = %self.unit,
disk = %self.disk.display(),
))]
async fn execute(&mut self) -> Result<(), Self::Error> {
let Self { unit, action_state } = self;
let Self {
disk,
password,
action_state,
} = self;
if *action_state == ActionState::Completed {
tracing::trace!("Already completed: Starting systemd unit");
tracing::trace!("Already completed: Encrypting volume");
return Ok(());
}
tracing::debug!("Starting systemd unit");
tracing::debug!("Encrypting volume");
// TODO(@Hoverbear): Handle proxy vars
execute_command(
Command::new("systemctl")
.arg("enable")
.arg("--now")
.arg(format!("{unit}")),
)
.await
.map_err(EncryptVolumeError::Command)?;
todo!();
tracing::trace!("Started systemd unit");
tracing::trace!("Encrypted volume");
*action_state = ActionState::Completed;
Ok(())
}
@ -68,32 +68,26 @@ impl Actionable for EncryptVolume {
if self.action_state == ActionState::Uncompleted {
vec![]
} else {
vec![ActionDescription::new(
"Stop the systemd Nix service and socket".to_string(),
vec![
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
]
)]
vec![]
}
}
#[tracing::instrument(skip_all, fields(
unit = %self.unit,
disk = %self.disk.display(),
))]
async fn revert(&mut self) -> Result<(), Self::Error> {
let Self { unit, action_state } = self;
let Self {
disk,
password,
action_state,
} = self;
if *action_state == ActionState::Uncompleted {
tracing::trace!("Already reverted: Stopping systemd unit");
tracing::trace!("Already reverted: Unencrypted volume (noop)");
return Ok(());
}
tracing::debug!("Stopping systemd unit");
tracing::debug!("Unencrypted volume (noop)");
// TODO(@Hoverbear): Handle proxy vars
execute_command(Command::new("systemctl").arg("stop").arg(format!("{unit}")))
.await
.map_err(EncryptVolumeError::Command)?;
tracing::trace!("Stopped systemd unit");
tracing::trace!("Unencrypted volume (noop)");
*action_state = ActionState::Completed;
Ok(())
}

View file

@ -1,3 +1,5 @@
use std::path::{Path, PathBuf};
use serde::Serialize;
use tokio::process::Command;
@ -7,15 +9,18 @@ use crate::actions::{Action, ActionDescription, ActionState, Actionable};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct UnmountVolume {
unit: String,
disk: PathBuf,
name: String,
action_state: ActionState,
}
impl UnmountVolume {
#[tracing::instrument(skip_all)]
pub async fn plan(unit: String) -> Result<Self, UnmountVolumeError> {
pub async fn plan(disk: impl AsRef<Path>, name: String) -> Result<Self, UnmountVolumeError> {
let disk = disk.as_ref().to_owned();
Ok(Self {
unit,
disk,
name,
action_state: ActionState::Uncompleted,
})
}
@ -39,27 +44,30 @@ impl Actionable for UnmountVolume {
}
#[tracing::instrument(skip_all, fields(
unit = %self.unit,
disk = %self.disk.display(),
name = %self.name,
))]
async fn execute(&mut self) -> Result<(), Self::Error> {
let Self { unit, action_state } = self;
let Self {
disk,
name,
action_state,
} = self;
if *action_state == ActionState::Completed {
tracing::trace!("Already completed: Starting systemd unit");
tracing::trace!("Already completed: Unmounting volume");
return Ok(());
}
tracing::debug!("Starting systemd unit");
tracing::debug!("Unmounting volume");
// TODO(@Hoverbear): Handle proxy vars
execute_command(
Command::new("systemctl")
.arg("enable")
.arg("--now")
.arg(format!("{unit}")),
Command::new(" /usr/sbin/diskutil")
.args(["unmount", "force"])
.arg(name),
)
.await
.map_err(UnmountVolumeError::Command)?;
.map_err(Self::Error::Command)?;
tracing::trace!("Started systemd unit");
tracing::trace!("Unmounted volume");
*action_state = ActionState::Completed;
Ok(())
}
@ -78,20 +86,28 @@ impl Actionable for UnmountVolume {
}
#[tracing::instrument(skip_all, fields(
unit = %self.unit,
disk = %self.disk.display(),
name = %self.name,
))]
async fn revert(&mut self) -> Result<(), Self::Error> {
let Self { unit, action_state } = self;
let Self {
disk,
name,
action_state,
} = self;
if *action_state == ActionState::Uncompleted {
tracing::trace!("Already reverted: Stopping systemd unit");
return Ok(());
}
tracing::debug!("Stopping systemd unit");
// TODO(@Hoverbear): Handle proxy vars
execute_command(Command::new("systemctl").arg("stop").arg(format!("{unit}")))
.await
.map_err(UnmountVolumeError::Command)?;
execute_command(
Command::new(" /usr/sbin/diskutil")
.args(["unmount", "force"])
.arg(name),
)
.await
.map_err(Self::Error::Command)?;
tracing::trace!("Stopped systemd unit");
*action_state = ActionState::Completed;

View file

@ -58,7 +58,7 @@ impl Actionable for SystemdSysextMerge {
execute_command(Command::new("systemd-sysext").arg("merge").arg(device))
.await
.map_err(SystemdSysextMergeError::Command)?;
.map_err(Self::Error::Command)?;
tracing::trace!("Merged systemd-sysext");
*action_state = ActionState::Completed;

View file

@ -7,8 +7,7 @@ use crate::actions::base::{
CreateVolume, CreateVolumeError, EnableOwnership, EnableOwnershipError, EncryptVolume,
EncryptVolumeError, UnmountVolume, UnmountVolumeError,
},
CreateDirectory, CreateDirectoryError, CreateFile, CreateFileError, CreateOrAppendFile,
CreateOrAppendFileError,
CreateOrAppendFile, CreateOrAppendFileError,
};
use crate::actions::{base::darwin, Action, ActionDescription, ActionState, Actionable};
@ -51,10 +50,9 @@ impl CreateApfsVolume {
let create_synthetic_objects = CreateSyntheticObjects::plan().await?;
let unmount_volume =
UnmountVolume::plan(disk, name.clone(), case_sensitive, encrypt).await?;
let unmount_volume = UnmountVolume::plan(disk, name.clone()).await?;
let create_volume = CreateVolume::plan(disk, name.clone(), case_sensitive, encrypt).await?;
let create_volume = CreateVolume::plan(disk, name.clone(), case_sensitive).await?;
let create_or_append_fstab = CreateOrAppendFile::plan(
"/etc/fstab",
@ -65,13 +63,13 @@ impl CreateApfsVolume {
)
.await?;
let encrypt_volume = if let Some(password) = encrypt {
Some(EncryptVolume::plan(disk, password).await)
let encrypt_volume = if let Some(password) = encrypt.as_ref() {
Some(EncryptVolume::plan(disk, password.to_string()).await?)
} else {
None
};
let bootstrap_volume = BootstrapVolume::plan(NIX_VOLUME_MOUNTD_DEST, disk, name).await?;
let bootstrap_volume = BootstrapVolume::plan(NIX_VOLUME_MOUNTD_DEST).await?;
let enable_ownership = EnableOwnership::plan("/nix").await?;
Ok(Self {
@ -100,17 +98,8 @@ impl Actionable for CreateApfsVolume {
let Self {
disk,
name,
case_sensitive,
encrypt,
create_or_append_synthetic_conf,
create_synthetic_objects,
unmount_volume,
create_volume,
create_or_append_fstab,
encrypt_volume,
bootstrap_volume,
enable_ownership,
action_state: _,
..
} = &self;
if self.action_state == ActionState::Completed {
vec![]
@ -127,10 +116,10 @@ impl Actionable for CreateApfsVolume {
#[tracing::instrument(skip_all, fields(destination,))]
async fn execute(&mut self) -> Result<(), Self::Error> {
let Self {
disk,
name,
case_sensitive,
encrypt,
disk: _,
name: _,
case_sensitive: _,
encrypt: _,
create_or_append_synthetic_conf,
create_synthetic_objects,
unmount_volume,
@ -152,7 +141,9 @@ impl Actionable for CreateApfsVolume {
unmount_volume.execute().await?;
create_volume.execute().await?;
create_or_append_fstab.execute().await?;
encrypt_volume.execute().await?;
if let Some(encrypt_volume) = encrypt_volume {
encrypt_volume.execute().await?;
}
bootstrap_volume.execute().await?;
enable_ownership.execute().await?;
@ -165,19 +156,10 @@ impl Actionable for CreateApfsVolume {
let Self {
disk,
name,
case_sensitive,
encrypt,
create_or_append_synthetic_conf,
create_synthetic_objects,
unmount_volume,
create_volume,
create_or_append_fstab,
encrypt_volume,
bootstrap_volume,
enable_ownership,
action_state: _,
action_state,
..
} = &self;
if self.action_state == ActionState::Uncompleted {
if *action_state == ActionState::Uncompleted {
vec![]
} else {
vec![ActionDescription::new(