2022-10-18 18:03:19 +00:00
|
|
|
use serde::Serialize;
|
2022-10-19 20:32:15 +00:00
|
|
|
use std::path::{Path, PathBuf};
|
2022-10-18 18:03:19 +00:00
|
|
|
use tokio::process::Command;
|
|
|
|
|
|
|
|
use crate::execute_command;
|
|
|
|
|
|
|
|
use crate::actions::{Action, ActionDescription, ActionState, Actionable};
|
|
|
|
|
|
|
|
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
|
|
|
pub struct EncryptVolume {
|
2022-10-19 20:32:15 +00:00
|
|
|
disk: PathBuf,
|
|
|
|
password: String,
|
2022-10-18 18:03:19 +00:00
|
|
|
action_state: ActionState,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EncryptVolume {
|
|
|
|
#[tracing::instrument(skip_all)]
|
2022-10-19 20:32:15 +00:00
|
|
|
pub async fn plan(
|
|
|
|
disk: impl AsRef<Path>,
|
|
|
|
password: String,
|
|
|
|
) -> Result<Self, EncryptVolumeError> {
|
2022-10-18 18:03:19 +00:00
|
|
|
Ok(Self {
|
2022-10-19 20:32:15 +00:00
|
|
|
disk: disk.as_ref().to_path_buf(),
|
|
|
|
password,
|
2022-10-18 18:03:19 +00:00
|
|
|
action_state: ActionState::Uncompleted,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait::async_trait]
|
|
|
|
impl Actionable for EncryptVolume {
|
|
|
|
type Error = EncryptVolumeError;
|
|
|
|
|
|
|
|
fn describe_execute(&self) -> Vec<ActionDescription> {
|
|
|
|
if self.action_state == ActionState::Completed {
|
|
|
|
vec![]
|
|
|
|
} else {
|
|
|
|
vec![ActionDescription::new(
|
2022-10-19 20:32:15 +00:00
|
|
|
format!("Encrypt volume `{}`", self.disk.display()),
|
|
|
|
vec![],
|
2022-10-18 18:03:19 +00:00
|
|
|
)]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tracing::instrument(skip_all, fields(
|
2022-10-19 20:32:15 +00:00
|
|
|
disk = %self.disk.display(),
|
2022-10-18 18:03:19 +00:00
|
|
|
))]
|
|
|
|
async fn execute(&mut self) -> Result<(), Self::Error> {
|
2022-10-19 20:32:15 +00:00
|
|
|
let Self {
|
|
|
|
disk,
|
|
|
|
password,
|
|
|
|
action_state,
|
|
|
|
} = self;
|
2022-10-18 18:03:19 +00:00
|
|
|
if *action_state == ActionState::Completed {
|
2022-10-19 20:32:15 +00:00
|
|
|
tracing::trace!("Already completed: Encrypting volume");
|
2022-10-18 18:03:19 +00:00
|
|
|
return Ok(());
|
|
|
|
}
|
2022-10-19 20:32:15 +00:00
|
|
|
tracing::debug!("Encrypting volume");
|
2022-10-18 18:03:19 +00:00
|
|
|
|
2022-10-19 20:32:15 +00:00
|
|
|
todo!();
|
2022-10-18 18:03:19 +00:00
|
|
|
|
2022-10-19 20:32:15 +00:00
|
|
|
tracing::trace!("Encrypted volume");
|
2022-10-18 18:03:19 +00:00
|
|
|
*action_state = ActionState::Completed;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn describe_revert(&self) -> Vec<ActionDescription> {
|
|
|
|
if self.action_state == ActionState::Uncompleted {
|
|
|
|
vec![]
|
|
|
|
} else {
|
2022-10-19 20:32:15 +00:00
|
|
|
vec![]
|
2022-10-18 18:03:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tracing::instrument(skip_all, fields(
|
2022-10-19 20:32:15 +00:00
|
|
|
disk = %self.disk.display(),
|
2022-10-18 18:03:19 +00:00
|
|
|
))]
|
|
|
|
async fn revert(&mut self) -> Result<(), Self::Error> {
|
2022-10-19 20:32:15 +00:00
|
|
|
let Self {
|
|
|
|
disk,
|
|
|
|
password,
|
|
|
|
action_state,
|
|
|
|
} = self;
|
2022-10-18 18:03:19 +00:00
|
|
|
if *action_state == ActionState::Uncompleted {
|
2022-10-19 20:32:15 +00:00
|
|
|
tracing::trace!("Already reverted: Unencrypted volume (noop)");
|
2022-10-18 18:03:19 +00:00
|
|
|
return Ok(());
|
|
|
|
}
|
2022-10-19 20:32:15 +00:00
|
|
|
tracing::debug!("Unencrypted volume (noop)");
|
2022-10-18 18:03:19 +00:00
|
|
|
|
2022-10-19 20:32:15 +00:00
|
|
|
tracing::trace!("Unencrypted volume (noop)");
|
2022-10-18 18:03:19 +00:00
|
|
|
*action_state = ActionState::Completed;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<EncryptVolume> for Action {
|
|
|
|
fn from(v: EncryptVolume) -> Self {
|
|
|
|
Action::DarwinEncryptVolume(v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, thiserror::Error, Serialize)]
|
|
|
|
pub enum EncryptVolumeError {
|
|
|
|
#[error("Failed to execute command")]
|
|
|
|
Command(
|
|
|
|
#[source]
|
|
|
|
#[serde(serialize_with = "crate::serialize_error_to_display")]
|
|
|
|
std::io::Error,
|
|
|
|
),
|
|
|
|
}
|