More fleshing out
This commit is contained in:
parent
da0219deb0
commit
fcc200b9d0
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in a new issue