aboutsummaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
authornotgne22020-10-29 19:33:53 -0700
committernotgne22020-10-29 19:33:53 -0700
commitca86bab9e9e8a0e60cec6793147abaec44a0ea8f (patch)
tree30a834cf9b22fdffbbf52e1d778b9712357222e0 /src/utils
parentd7f0006df0e3c14a9387f5bd3e3e3acd0b39fda8 (diff)
Make all the errors work correctly (I am so so sorry)
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/deploy.rs49
-rw-r--r--src/utils/mod.rs53
-rw-r--r--src/utils/push.rs55
3 files changed, 116 insertions, 41 deletions
diff --git a/src/utils/deploy.rs b/src/utils/deploy.rs
index 8ed7d8c..f395a3a 100644
--- a/src/utils/deploy.rs
+++ b/src/utils/deploy.rs
@@ -5,6 +5,8 @@
use std::borrow::Cow;
use tokio::process::Command;
+use thiserror::Error;
+
fn build_activate_command(
activate_path_str: String,
sudo: &Option<String>,
@@ -72,10 +74,26 @@ fn test_activation_command_builder() {
);
}
+#[derive(Error, Debug)]
+pub enum DeployProfileError {
+ #[error("Failed to calculate activate bin path from deploy bin path: {0}")]
+ DeployPathToActivatePathError(#[from] super::DeployPathToActivatePathError),
+ #[error("Failed to run activation command over SSH: {0}")]
+ SSHActivateError(std::io::Error),
+ #[error("Activation over SSH resulted in a bad exit code: {0:?}")]
+ SSHActivateExitError(Option<i32>),
+ #[error("Failed to run confirmation command over SSH (the server should roll back): {0}")]
+ SSHConfirmError(std::io::Error),
+ #[error(
+ "Confirming activation over SSH resulted in a bad exit code (the server should roll back): {0:?}"
+ )]
+ SSHConfirmExitError(Option<i32>),
+}
+
pub async fn deploy_profile(
deploy_data: &super::DeployData<'_>,
deploy_defs: &super::DeployDefs<'_>,
-) -> Result<(), Box<dyn std::error::Error>> {
+) -> Result<(), DeployProfileError> {
info!(
"Activating profile `{}` for node `{}`",
deploy_data.profile_name, deploy_data.node_name
@@ -122,11 +140,16 @@ pub async fn deploy_profile(
ssh_command = ssh_command.arg(ssh_opt);
}
- let ssh_exit_status = ssh_command.arg(self_activate_command).status().await?;
+ let ssh_exit_status = ssh_command
+ .arg(self_activate_command)
+ .status()
+ .await
+ .map_err(DeployProfileError::SSHActivateError)?;
- if !ssh_exit_status.success() {
- good_panic!("Activation over SSH failed");
- }
+ match ssh_exit_status.code() {
+ Some(0) => (),
+ a => return Err(DeployProfileError::SSHActivateExitError(a)),
+ };
info!("Success activating!");
@@ -153,14 +176,16 @@ pub async fn deploy_profile(
confirm_command
);
- let ssh_exit_status = ssh_confirm_command.arg(confirm_command).status().await?;
+ let ssh_exit_status = ssh_confirm_command
+ .arg(confirm_command)
+ .status()
+ .await
+ .map_err(DeployProfileError::SSHConfirmError)?;
- if !ssh_exit_status.success() {
- good_panic!(
- "Failed to confirm deployment, the node will roll back in <{} seconds",
- confirm_timeout
- );
- }
+ match ssh_exit_status.code() {
+ Some(0) => (),
+ a => return Err(DeployProfileError::SSHConfirmExitError(a)),
+ };
info!("Deployment confirmed.");
}
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index a0e62e1..19d0948 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -7,6 +7,8 @@ use std::path::PathBuf;
use merge::Merge;
+use thiserror::Error;
+
#[macro_export]
macro_rules! good_panic {
($($tts:tt)*) => {{
@@ -112,8 +114,18 @@ pub struct DeployDefs<'a> {
pub sudo: Option<String>,
}
+#[derive(Error, Debug)]
+pub enum DeployDataDefsError {
+ #[error("Neither `user` nor `sshUser` are set for profile {0} of node {1}")]
+ NoProfileUser(String, String),
+ #[error("Error reading current executable path: {0}")]
+ ExecutablePathNotFound(std::io::Error),
+ #[error("Executable was not in the Nix store")]
+ NotNixStored,
+}
+
impl<'a> DeployData<'a> {
- pub fn defs(&'a self) -> DeployDefs<'a> {
+ pub fn defs(&'a self) -> Result<DeployDefs<'a>, DeployDataDefsError> {
let ssh_user: Cow<str> = match self.merged_settings.ssh_user {
Some(ref u) => u.into(),
None => whoami::username().into(),
@@ -123,11 +135,12 @@ impl<'a> DeployData<'a> {
Some(ref x) => x.into(),
None => match self.merged_settings.ssh_user {
Some(ref x) => x.into(),
- None => good_panic!(
- "Neither user nor sshUser set for profile `{}` of node `{}`",
- self.profile_name,
- self.node_name
- ),
+ None => {
+ return Err(DeployDataDefsError::NoProfileUser(
+ self.profile_name.to_owned(),
+ self.node_name.to_owned(),
+ ))
+ }
},
};
@@ -149,19 +162,19 @@ impl<'a> DeployData<'a> {
};
let current_exe =
- std::env::current_exe().expect("Expected to find current executable path");
+ std::env::current_exe().map_err(DeployDataDefsError::ExecutablePathNotFound)?;
if !current_exe.starts_with("/nix/store/") {
- good_panic!("The deploy binary must be in the Nix store");
+ return Err(DeployDataDefsError::NotNixStored);
}
- DeployDefs {
+ Ok(DeployDefs {
ssh_user,
profile_user,
profile_path,
current_exe,
sudo,
- }
+ })
}
}
@@ -172,7 +185,7 @@ pub fn make_deploy_data<'a, 's>(
profile: &'a data::Profile,
profile_name: &'a str,
cmd_overrides: &'a CmdOverrides,
-) -> Result<DeployData<'a>, Box<dyn std::error::Error>> {
+) -> DeployData<'a> {
let mut merged_settings = top_settings.clone();
merged_settings.merge(node.generic_settings.clone());
merged_settings.merge(profile.generic_settings.clone());
@@ -196,7 +209,7 @@ pub fn make_deploy_data<'a, 's>(
merged_settings.magic_rollback = Some(magic_rollback);
}
- Ok(DeployData {
+ DeployData {
profile,
profile_name,
node,
@@ -205,19 +218,27 @@ pub fn make_deploy_data<'a, 's>(
cmd_overrides,
merged_settings,
- })
+ }
+}
+
+#[derive(Error, Debug)]
+pub enum DeployPathToActivatePathError {
+ #[error("Deploy path did not have a parent directory")]
+ PathTooShort,
+ #[error("Deploy path was not valid utf8")]
+ InvalidUtf8,
}
pub fn deploy_path_to_activate_path_str(
deploy_path: &std::path::Path,
-) -> Result<String, Box<dyn std::error::Error>> {
+) -> Result<String, DeployPathToActivatePathError> {
Ok(format!(
"{}/activate",
deploy_path
.parent()
- .ok_or("Deploy path too short")?
+ .ok_or(DeployPathToActivatePathError::PathTooShort)?
.to_str()
- .ok_or("Deploy path is not valid utf8")?
+ .ok_or(DeployPathToActivatePathError::InvalidUtf8)?
.to_owned()
))
}
diff --git a/src/utils/push.rs b/src/utils/push.rs
index 5e87d5c..c79a004 100644
--- a/src/utils/push.rs
+++ b/src/utils/push.rs
@@ -5,6 +5,26 @@
use std::process::Stdio;
use tokio::process::Command;
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+pub enum PushProfileError {
+ #[error("Failed to calculate activate bin path from deploy bin path: {0}")]
+ DeployPathToActivatePathError(#[from] super::DeployPathToActivatePathError),
+ #[error("Failed to run Nix build command: {0}")]
+ BuildError(std::io::Error),
+ #[error("Nix build command resulted in a bad exit code: {0:?}")]
+ BuildExitError(Option<i32>),
+ #[error("Failed to run Nix sign command: {0}")]
+ SignError(std::io::Error),
+ #[error("Nix sign command resulted in a bad exit code: {0:?}")]
+ SignExitError(Option<i32>),
+ #[error("Failed to run Nix copy command: {0}")]
+ CopyError(std::io::Error),
+ #[error("Nix copy command resulted in a bad exit code: {0:?}")]
+ CopyExitError(Option<i32>),
+}
+
pub async fn push_profile(
supports_flakes: bool,
check_sigs: bool,
@@ -13,7 +33,7 @@ pub async fn push_profile(
deploy_defs: &super::DeployDefs<'_>,
keep_result: bool,
result_path: Option<&str>,
-) -> Result<(), Box<dyn std::error::Error>> {
+) -> Result<(), PushProfileError> {
info!(
"Building profile `{}` for node `{}`",
deploy_data.profile_name, deploy_data.node_name
@@ -57,11 +77,16 @@ pub async fn push_profile(
(false, true) => build_command.arg("--no-link"),
};
- let build_exit_status = build_command.stdout(Stdio::null()).status().await?;
+ let build_exit_status = build_command
+ .stdout(Stdio::null())
+ .status()
+ .await
+ .map_err(PushProfileError::BuildError)?;
- if !build_exit_status.success() {
- good_panic!("`nix build` failed");
- }
+ match build_exit_status.code() {
+ Some(0) => (),
+ a => return Err(PushProfileError::BuildExitError(a)),
+ };
if let Ok(local_key) = std::env::var("LOCAL_KEY") {
info!(
@@ -81,11 +106,13 @@ pub async fn push_profile(
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
- .await?;
+ .await
+ .map_err(PushProfileError::SignError)?;
- if !sign_exit_status.success() {
- good_panic!("`nix sign-paths` failed");
- }
+ match sign_exit_status.code() {
+ Some(0) => (),
+ a => return Err(PushProfileError::SignExitError(a)),
+ };
}
debug!(
@@ -127,11 +154,13 @@ pub async fn push_profile(
)?)
.env("NIX_SSHOPTS", ssh_opts_str)
.status()
- .await?;
+ .await
+ .map_err(PushProfileError::CopyError)?;
- if !copy_exit_status.success() {
- good_panic!("`nix copy` failed");
- }
+ match copy_exit_status.code() {
+ Some(0) => (),
+ a => return Err(PushProfileError::CopyExitError(a)),
+ };
Ok(())
}