Skip to content

Commit

Permalink
feat(deployer): split up deployer error enum (#339)
Browse files Browse the repository at this point in the history
* feat(deployer): split up deployer error enum

* fix: unsafe unwrap
  • Loading branch information
oddgrd authored Sep 16, 2022
1 parent 4e00a03 commit d4bf86c
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 52 deletions.
34 changes: 0 additions & 34 deletions deployer/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
use std::error::Error as StdError;
use std::io;

use axum::http::{header, HeaderValue, StatusCode};
use axum::response::{IntoResponse, Response};
use axum::Json;

use serde::{ser::SerializeMap, Serialize};
use serde_json::json;
use shuttle_service::loader::LoaderError;

use cargo::util::errors::CargoTestError;
Expand All @@ -31,34 +25,6 @@ pub enum Error {
SecretsParse(#[from] toml::de::Error),
#[error("Failed to set secrets: {0}")]
SecretsSet(#[source] Box<dyn StdError + Send>),
#[error("Failed to parse secrets: {0}")]
Persistence(#[from] crate::persistence::PersistenceError),
}

impl Serialize for Error {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut map = serializer.serialize_map(Some(2))?;
map.serialize_entry("type", &format!("{:?}", self))?;
map.serialize_entry("msg", &self.source().unwrap().to_string())?;
map.end()
}
}

impl IntoResponse for Error {
fn into_response(self) -> Response {
(
StatusCode::INTERNAL_SERVER_ERROR,
[(
header::CONTENT_TYPE,
HeaderValue::from_static("application/json"),
)],
Json(json!({ "message": self })),
)
.into_response()
}
}

pub type Result<T> = std::result::Result<T, Error>;
8 changes: 2 additions & 6 deletions deployer/src/handlers/deployment.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use std::sync::Arc;

use crate::{
error::Result,
persistence::{Deployment, State},
};
use crate::persistence::{Deployment, State};
use async_trait::async_trait;
use axum::{
extract::{FromRequest, Path},
Expand All @@ -15,7 +12,6 @@ use serde::Serialize;
use uuid::Uuid;

use super::user::UserGuard;

/// Guard used to make sure a request has a valid api key set on the Basic Auth and that it owns a service's deployment
///
/// *Note*
Expand Down Expand Up @@ -94,7 +90,7 @@ pub trait DeploymentAuthorizer: Sync + Send {
&self,
api_key: &str,
deployment_id: &Uuid,
) -> Result<Option<Deployment>>;
) -> super::Result<Option<Deployment>>;
}

impl From<Deployment> for DeploymentGuard {
Expand Down
43 changes: 43 additions & 0 deletions deployer/src/handlers/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use std::error::Error as StdError;

use axum::http::{header, HeaderValue, StatusCode};
use axum::response::{IntoResponse, Response};
use axum::Json;

use serde::{ser::SerializeMap, Serialize};
use serde_json::json;

#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Persistence failure: {0}")]
Persistence(#[from] crate::persistence::PersistenceError),
}

impl Serialize for Error {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut map = serializer.serialize_map(Some(2))?;
map.serialize_entry("type", &format!("{:?}", self))?;
// use the error source if available, if not use display implementation
map.serialize_entry("msg", &self.source().unwrap_or(self).to_string())?;
map.end()
}
}

impl IntoResponse for Error {
fn into_response(self) -> Response {
(
StatusCode::INTERNAL_SERVER_ERROR,
[(
header::CONTENT_TYPE,
HeaderValue::from_static("application/json"),
)],
Json(json!({ "message": self })),
)
.into_response()
}
}

pub type Result<T> = std::result::Result<T, Error>;
5 changes: 3 additions & 2 deletions deployer/src/handlers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod admin;
mod deployment;
mod error;
mod service;
mod user;

Expand All @@ -18,7 +19,6 @@ use tracing::{debug, debug_span, error, field, Span};
use uuid::Uuid;

use crate::deployment::{DeploymentManager, Queued};
use crate::error::{Error, Result};
use crate::persistence::{self, Deployment, Log, Persistence, SecretGetter, State};

use std::collections::HashMap;
Expand All @@ -32,6 +32,7 @@ pub use self::service::ServiceAuthorizer;
use self::service::ServiceGuard;
use self::user::UserGuard;
pub use self::user::UserValidator;
pub use {self::error::Error, self::error::Result};

pub fn make_router(
persistence: Persistence,
Expand Down Expand Up @@ -185,7 +186,7 @@ async fn post_service(
id,
service_name: service.name,
service_id: service.id,
data_stream: Box::pin(stream.map_err(Error::Streaming)),
data_stream: Box::pin(stream.map_err(crate::error::Error::Streaming)),
will_run_tests: !params.contains_key("no-test"),
};

Expand Down
4 changes: 2 additions & 2 deletions deployer/src/handlers/service.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::sync::Arc;

use crate::{error::Result, persistence::Service};
use crate::persistence::Service;
use async_trait::async_trait;
use axum::{
extract::{FromRequest, Path},
Expand Down Expand Up @@ -88,7 +88,7 @@ pub trait ServiceAuthorizer: Sync + Send {
&self,
api_key: &str,
service_name: &str,
) -> Result<Option<Service>>;
) -> super::Result<Option<Service>>;
}

impl From<Service> for ServiceGuard {
Expand Down
4 changes: 2 additions & 2 deletions deployer/src/handlers/user.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::sync::Arc;

use crate::{error::Result, persistence::User};
use crate::persistence::User;
use async_trait::async_trait;
use axum::{
extract::FromRequest,
Expand Down Expand Up @@ -78,7 +78,7 @@ pub struct UserGuardError {

#[async_trait::async_trait]
pub trait UserValidator: Sync + Send {
async fn is_user_valid(&self, api_key: &str) -> Result<Option<User>>;
async fn is_user_valid(&self, api_key: &str) -> super::Result<Option<User>>;
}

impl From<User> for UserGuard {
Expand Down
12 changes: 6 additions & 6 deletions deployer/src/persistence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,13 +463,13 @@ impl SecretGetter for Persistence {

#[async_trait::async_trait]
impl UserValidator for Persistence {
async fn is_user_valid(&self, api_key: &str) -> crate::error::Result<Option<User>> {
async fn is_user_valid(&self, api_key: &str) -> crate::handlers::Result<Option<User>> {
sqlx::query_as("SELECT * FROM users WHERE api_key = ?")
.bind(api_key)
.fetch_optional(&self.pool)
.await
.map_err(Error::from)
.map_err(crate::error::Error::Persistence)
.map_err(crate::handlers::Error::Persistence)
}
}

Expand All @@ -479,14 +479,14 @@ impl ServiceAuthorizer for Persistence {
&self,
api_key: &str,
service_name: &str,
) -> crate::error::Result<Option<Service>> {
) -> crate::handlers::Result<Option<Service>> {
sqlx::query_as("SELECT * FROM services WHERE user_id = ? AND name = ?")
.bind(api_key)
.bind(service_name)
.fetch_optional(&self.pool)
.await
.map_err(Error::from)
.map_err(crate::error::Error::Persistence)
.map_err(crate::handlers::Error::Persistence)
}
}

Expand All @@ -496,7 +496,7 @@ impl DeploymentAuthorizer for Persistence {
&self,
api_key: &str,
deployment_id: &Uuid,
) -> crate::error::Result<Option<Deployment>> {
) -> crate::handlers::Result<Option<Deployment>> {
sqlx::query_as(
r#"SELECT d.id AS id, service_id, state, last_update
FROM deployments AS d
Expand All @@ -508,7 +508,7 @@ impl DeploymentAuthorizer for Persistence {
.fetch_optional(&self.pool)
.await
.map_err(Error::from)
.map_err(crate::error::Error::Persistence)
.map_err(crate::handlers::Error::Persistence)
}
}

Expand Down

0 comments on commit d4bf86c

Please sign in to comment.