Skip to content

Commit

Permalink
feat: controller error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
MaloPolese committed Apr 24, 2023
1 parent 1f33724 commit f66d053
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 113 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions controller/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ rstest = "0.16.0"
uuid = { version = "1.3.1", features = ["serde", "v4"] }
backoff = { version = "0.4.0", features = ["tokio"]}
rand = "0.8.4"
thiserror = "1.0.40"
anyhow = "1.0.70"

# Instrumentation
tracing = { workspace = true }
Expand Down
56 changes: 36 additions & 20 deletions controller/src/api/external/routes/instance.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
use definition::workload::WorkloadDefinition;
use route_recognizer;
use rusqlite::Connection;
use std::io;
use std::str::FromStr;
use std::sync::mpsc::Sender;
use tracing::{event, info, Level};
use tracing::{event, Level};

use crate::api;
use crate::api::external::services::element::elements_set_right_name;
use crate::api::external::services::instance::send_create_instance;
use crate::api::types::element::OnlyId;
use crate::api::types::instance::InstanceDefinition;
use crate::api::{ApiChannel, Crud};
use crate::api::{ApiChannel, Crud, RikError};
use crate::core::instance::Instance;
use crate::database::RikRepository;

use super::HttpResult;

pub fn get(
_: &mut tiny_http::Request,
_: &route_recognizer::Params,
connection: &Connection,
_: &Sender<ApiChannel>,
) -> Result<tiny_http::Response<io::Cursor<Vec<u8>>>, api::RikError> {
) -> HttpResult {
if let Ok(mut instances) = RikRepository::find_all(connection, "/instance") {
instances = elements_set_right_name(instances.clone());
let instances_json = serde_json::to_string(&instances).unwrap();
let instances_json = serde_json::to_string(&instances).map_err(RikError::ParsingError)?;

event!(Level::INFO, "instances.get, instances found");

Ok(tiny_http::Response::from_string(instances_json)
.with_header(tiny_http::Header::from_str("Content-Type: application/json").unwrap())
.with_header(
tiny_http::Header::from_str("Content-Type: application/json").map_err(|_| {
RikError::Error("tiny_http::Header failed to add header".to_string())
})?,
)
.with_status_code(tiny_http::StatusCode::from(200)))
} else {
Ok(tiny_http::Response::from_string("Cannot find instances")
Expand All @@ -39,11 +45,14 @@ pub fn create(
_: &route_recognizer::Params,
connection: &Connection,
internal_sender: &Sender<ApiChannel>,
) -> Result<tiny_http::Response<io::Cursor<Vec<u8>>>, api::RikError> {
) -> HttpResult {
let mut content = String::new();
req.as_reader().read_to_string(&mut content).unwrap();
req.as_reader()
.read_to_string(&mut content)
.map_err(RikError::IoError)?;

let mut instance: InstanceDefinition = serde_json::from_str(&content)?;
let mut instance: InstanceDefinition =
serde_json::from_str(&content).map_err(RikError::ParsingError)?;

//Workload not found
if RikRepository::find_one(connection, &instance.workload_id, "/workload").is_err() {
Expand Down Expand Up @@ -98,26 +107,32 @@ pub fn create(
);
}

Ok(
tiny_http::Response::from_string(serde_json::to_string(&instance_names).unwrap())
.with_header(tiny_http::Header::from_str("Content-Type: application/json").unwrap())
.with_status_code(tiny_http::StatusCode::from(201)),
Ok(tiny_http::Response::from_string(
serde_json::to_string(&instance_names).map_err(RikError::ParsingError)?,
)
.with_header(
tiny_http::Header::from_str("Content-Type: application/json")
.map_err(|_| RikError::Error("tiny_http::Header failed to add header".to_string()))?,
)
.with_status_code(tiny_http::StatusCode::from(201)))
}

pub fn delete(
req: &mut tiny_http::Request,
_: &route_recognizer::Params,
connection: &Connection,
internal_sender: &Sender<ApiChannel>,
) -> Result<tiny_http::Response<io::Cursor<Vec<u8>>>, api::RikError> {
) -> HttpResult {
let mut content = String::new();
req.as_reader().read_to_string(&mut content).unwrap();
let OnlyId { id: delete_id } = serde_json::from_str(&content)?;
req.as_reader()
.read_to_string(&mut content)
.map_err(RikError::IoError)?;
let OnlyId { id: delete_id } =
serde_json::from_str(&content).map_err(RikError::ParsingError)?;

if let Ok(instance) = RikRepository::find_one(connection, &delete_id, "/instance") {
let instance_def: InstanceDefinition =
serde_json::from_value(instance.value.clone()).unwrap();
serde_json::from_value(instance.value.clone()).map_err(RikError::ParsingError)?;

let workload_def_rs =
RikRepository::find_one(connection, &instance_def.workload_id, "/workload");
Expand All @@ -135,15 +150,16 @@ pub fn delete(
.with_status_code(tiny_http::StatusCode::from(404)));
}
let workload_def: WorkloadDefinition =
serde_json::from_value(workload_def_rs.unwrap().value).unwrap();
serde_json::from_value(workload_def_rs.map_err(RikError::DataBaseError)?.value)
.map_err(RikError::ParsingError)?;
internal_sender
.send(ApiChannel {
action: Crud::Delete,
workload_id: Some(instance_def.workload_id),
workload_definition: Some(workload_def),
instance_id: Some(delete_id),
})
.unwrap();
.map_err(|e| RikError::InternalCommunicationError(e.to_string()))?;

event!(
Level::INFO,
Expand Down
3 changes: 3 additions & 0 deletions controller/src/api/external/routes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use rusqlite::Connection;
use std::io;
use std::sync::mpsc::Sender;
use tiny_http::Method;
use tiny_http::Response;
use tracing::{event, Level};

use crate::api;
Expand All @@ -19,6 +20,8 @@ type Handler = fn(
&Sender<ApiChannel>,
) -> Result<tiny_http::Response<io::Cursor<Vec<u8>>>, api::RikError>;

type HttpResult<T = io::Cursor<Vec<u8>>> = Result<Response<T>, api::RikError>;

pub struct Router {
routes: Vec<(tiny_http::Method, route_recognizer::Router<Handler>)>,
}
Expand Down
40 changes: 26 additions & 14 deletions controller/src/api/external/routes/tenant.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
use route_recognizer;
use rusqlite::Connection;
use std::io;
use std::str::FromStr;
use std::sync::mpsc::Sender;
use tracing::{event, Level};

use crate::api;
use super::HttpResult;
use crate::api::external::services::element::elements_set_right_name;
use crate::api::types::element::OnlyId;
use crate::api::types::tenant::Tenant;
use crate::api::ApiChannel;
use crate::api::{ApiChannel, RikError};
use crate::database::RikRepository;

pub fn get(
_: &mut tiny_http::Request,
_: &route_recognizer::Params,
connection: &Connection,
_: &Sender<ApiChannel>,
) -> Result<tiny_http::Response<io::Cursor<Vec<u8>>>, api::RikError> {
) -> HttpResult {
if let Ok(mut tenants) = RikRepository::find_all(connection, "/tenant") {
tenants = elements_set_right_name(tenants.clone());
let tenants_json = serde_json::to_string(&tenants).unwrap();
let tenants_json = serde_json::to_string(&tenants).map_err(RikError::ParsingError)?;
event!(Level::INFO, "tenants.get, tenants found");
Ok(tiny_http::Response::from_string(tenants_json)
.with_header(tiny_http::Header::from_str("Content-Type: application/json").unwrap())
.with_header(
tiny_http::Header::from_str("Content-Type: application/json").map_err(|_| {
RikError::Error("tiny_http::Header failed to add header".to_string())
})?,
)
.with_status_code(tiny_http::StatusCode::from(200)))
} else {
Ok(tiny_http::Response::from_string("Cannot find tenant")
Expand All @@ -36,15 +39,21 @@ pub fn create(
_: &route_recognizer::Params,
connection: &Connection,
_: &Sender<ApiChannel>,
) -> Result<tiny_http::Response<io::Cursor<Vec<u8>>>, api::RikError> {
) -> HttpResult {
let mut content = String::new();
req.as_reader().read_to_string(&mut content).unwrap();
let tenant: Tenant = serde_json::from_str(&content)?;
req.as_reader()
.read_to_string(&mut content)
.map_err(RikError::IoError)?;
let tenant: Tenant = serde_json::from_str(&content).map_err(RikError::ParsingError)?;

if RikRepository::insert(connection, &tenant.name, &tenant.value).is_ok() {
event!(Level::INFO, "Create tenant");
Ok(tiny_http::Response::from_string(content)
.with_header(tiny_http::Header::from_str("Content-Type: application/json").unwrap())
.with_header(
tiny_http::Header::from_str("Content-Type: application/json").map_err(|_| {
RikError::Error("tiny_http::Header failed to add header".to_string())
})?,
)
.with_status_code(tiny_http::StatusCode::from(200)))
} else {
event!(Level::ERROR, "Cannot create tenant");
Expand All @@ -58,13 +67,16 @@ pub fn delete(
_: &route_recognizer::Params,
connection: &Connection,
_: &Sender<ApiChannel>,
) -> Result<tiny_http::Response<io::Cursor<Vec<u8>>>, api::RikError> {
) -> HttpResult {
let mut content = String::new();
req.as_reader().read_to_string(&mut content).unwrap();
let OnlyId { id: delete_id } = serde_json::from_str(&content)?;
req.as_reader()
.read_to_string(&mut content)
.map_err(RikError::IoError)?;
let OnlyId { id: delete_id } =
serde_json::from_str(&content).map_err(RikError::ParsingError)?;

if let Ok(tenant) = RikRepository::find_one(connection, &delete_id, "/tenant") {
RikRepository::delete(connection, &tenant.id).unwrap();
RikRepository::delete(connection, &tenant.id).map_err(RikError::DataBaseError)?;
event!(Level::INFO, "Delete tenant");
Ok(tiny_http::Response::from_string("").with_status_code(tiny_http::StatusCode::from(204)))
} else {
Expand Down
26 changes: 12 additions & 14 deletions controller/src/api/external/routes/workload.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
use crate::api;
use super::HttpResult;
use crate::api::external::services::element::elements_set_right_name;
use crate::api::types::element::OnlyId;
use crate::api::{ApiChannel, Crud};
use crate::api::{ApiChannel, Crud, RikError};
use crate::core::instance::Instance;
use crate::database::RikRepository;
use definition::workload::WorkloadDefinition;
use route_recognizer;
use rusqlite::Connection;
use serde_json::json;
use std::io;
use std::str::FromStr;
use std::sync::mpsc::Sender;
use tiny_http::Response;
use tracing::{event, Level};

type HttpResult<T = io::Cursor<Vec<u8>>> = Result<Response<T>, api::RikError>;

pub fn get(
_: &mut tiny_http::Request,
_: &route_recognizer::Params,
Expand All @@ -24,7 +20,7 @@ pub fn get(
) -> HttpResult {
if let Ok(mut workloads) = RikRepository::find_all(connection, "/workload") {
workloads = elements_set_right_name(workloads.clone());
let workloads_json = serde_json::to_string(&workloads).unwrap();
let workloads_json = serde_json::to_string(&workloads).map_err(RikError::ParsingError)?;
event!(Level::INFO, "workloads.get, workloads found");

Ok(tiny_http::Response::from_string(workloads_json)
Expand Down Expand Up @@ -84,7 +80,8 @@ pub fn create(
let mut content = String::new();
req.as_reader().read_to_string(&mut content).unwrap();

let mut workload: WorkloadDefinition = serde_json::from_str(&content)?;
let mut workload: WorkloadDefinition =
serde_json::from_str(&content).map_err(RikError::ParsingError)?;
if workload.replicas.is_none() {
workload.replicas = Some(1);
}
Expand All @@ -104,18 +101,18 @@ pub fn create(
if let Ok(inserted_id) = RikRepository::insert(
connection,
&name,
&serde_json::to_string(&workload).unwrap(),
&serde_json::to_string(&workload).map_err(RikError::ParsingError)?,
) {
let workload_id: OnlyId = OnlyId { id: inserted_id };
event!(
Level::INFO,
"workload.create, workload successfully created"
);
Ok(
tiny_http::Response::from_string(serde_json::to_string(&workload_id).unwrap())
.with_header(tiny_http::Header::from_str("Content-Type: application/json").unwrap())
.with_status_code(tiny_http::StatusCode::from(200)),
Ok(tiny_http::Response::from_string(
serde_json::to_string(&workload_id).map_err(RikError::ParsingError)?,
)
.with_header(tiny_http::Header::from_str("Content-Type: application/json").unwrap())
.with_status_code(tiny_http::StatusCode::from(200)))
} else {
event!(Level::ERROR, "workload.create, cannot create workload");
Ok(tiny_http::Response::from_string("Cannot create workload")
Expand All @@ -131,7 +128,8 @@ pub fn delete(
) -> HttpResult {
let mut content = String::new();
req.as_reader().read_to_string(&mut content).unwrap();
let OnlyId { id: delete_id } = serde_json::from_str(&content)?;
let OnlyId { id: delete_id } =
serde_json::from_str(&content).map_err(RikError::ParsingError)?;

if let Ok(workload) = RikRepository::find_one(connection, &delete_id, "/workload") {
let definition: WorkloadDefinition = serde_json::from_value(workload.value).unwrap();
Expand Down
Loading

0 comments on commit f66d053

Please sign in to comment.