Permalink
Browse files

Load config at start up

- Parse and load config file at start up and fail if config is invalid
- Use rocket app state to share config
  • Loading branch information...
schrieveslaach committed Feb 1, 2019
1 parent a8ff2c7 commit fd920e55038c0e3e7e3d88a4fa42b746f42ccb41
@@ -30,33 +30,38 @@ use crate::commands::list_apps_command::{ListAppsCommand, ListAppsError};
use crate::commands::list_tickets_command::{ListTicketsCommand, ListTicketsError};
use crate::models::service::Service;
use crate::models::ticket_info::TicketInfo;
use crate::services::config_service::Config;
use multimap::MultiMap;
use rocket::http::RawStr;
use rocket::State;
use rocket_contrib::json::Json;
use std::collections::HashMap;

#[get("/apps", format = "application/json")]
pub fn apps(
config_state: State<Config>,
list_apps_command: ListAppsCommand,
) -> Result<Json<MultiMap<String, Service>>, ListAppsError> {
let apps = list_apps_command.list_apps()?;
let apps = list_apps_command.list_apps(&config_state)?;
Ok(Json(apps))
}

#[get("/apps/tickets", format = "application/json")]
pub fn tickets(
config_state: State<Config>,
list_tickets_command: ListTicketsCommand,
) -> Result<Json<HashMap<String, TicketInfo>>, ListTicketsError> {
let apps = list_tickets_command.list_ticket_infos()?;
let apps = list_tickets_command.list_ticket_infos(&config_state)?;
Ok(Json(apps))
}

#[delete("/apps/<app_name>", format = "application/json")]
pub fn delete_app(
app_name: &RawStr,
config_state: State<Config>,
delete_app_command: DeleteAppCommand,
) -> Result<Json<Vec<Service>>, DeleteAppError> {
let services = delete_app_command.delete_app(&app_name.to_string())?;
let services = delete_app_command.delete_app(&config_state, &app_name.to_string())?;
Ok(Json(services))
}

@@ -67,8 +72,9 @@ pub fn delete_app(
)]
pub fn create_app(
app_name: &RawStr,
config_state: State<Config>,
app_command: CreateOrUpdateAppCommand,
) -> Result<Json<Vec<Service>>, CreateOrUpdateError> {
let services = app_command.create_or_update_app(&app_name.to_string())?;
let services = app_command.create_or_update_app(&config_state, &app_name.to_string())?;
Ok(Json(services))
}
@@ -27,6 +27,7 @@
use crate::models::request_info::RequestInfo;
use crate::models::service::{Service, ServiceConfig, ServiceError};
use crate::services::apps_service::{AppsService, AppsServiceError};
use crate::services::config_service::Config;
use rocket::data::{self, FromDataSimple};
use rocket::http::{ContentType, Status};
use rocket::request::{FromRequest, Request};
@@ -84,9 +85,10 @@ impl CreateOrUpdateAppCommand {
/// and then it starts a new instance.
pub fn create_or_update_app(
&self,
config: &Config,
app_name: &String,
) -> Result<Vec<Service>, CreateOrUpdateError> {
let apps_service = AppsService::new()?;
let apps_service = AppsService::new(config)?;
let mut services = apps_service.create_or_update(app_name, &self.data)?;

for service in services.iter_mut() {
@@ -27,6 +27,7 @@
use crate::models::request_info::RequestInfo;
use crate::models::service::Service;
use crate::services::apps_service::{AppsService, AppsServiceError};
use crate::services::config_service::Config;
use rocket::http::{ContentType, Status};
use rocket::request::{self, FromRequest, Request};
use rocket::response::{self, Responder, Response};
@@ -54,8 +55,12 @@ impl<'a, 'r> FromRequest<'a, 'r> for DeleteAppCommand {
}

impl DeleteAppCommand {
pub fn delete_app(&self, app_name: &String) -> Result<Vec<Service>, DeleteAppError> {
let apps_service = AppsService::new()?;
pub fn delete_app(
&self,
config: &Config,
app_name: &String,
) -> Result<Vec<Service>, DeleteAppError> {
let apps_service = AppsService::new(config)?;
let mut services = apps_service.delete_app(app_name)?;

for service in services.iter_mut() {
@@ -27,6 +27,7 @@
use crate::models::request_info::RequestInfo;
use crate::models::service::Service;
use crate::services::apps_service::{AppsService, AppsServiceError};
use crate::services::config_service::Config;
use multimap::MultiMap;
use rocket::http::{ContentType, Status};
use rocket::request::{self, FromRequest, Request};
@@ -57,8 +58,8 @@ impl<'a, 'r> FromRequest<'a, 'r> for ListAppsCommand {
impl ListAppsCommand {
/// Analyzes running containers and returns a map of `review-app-name` with the
/// corresponding list of `Service`s.
pub fn list_apps(&self) -> Result<MultiMap<String, Service>, ListAppsError> {
let apps_service = AppsService::new()?;
pub fn list_apps(&self, config: &Config) -> Result<MultiMap<String, Service>, ListAppsError> {
let apps_service = AppsService::new(config)?;
let mut apps = apps_service.get_apps()?;

for (_, services) in apps.iter_all_mut() {
@@ -46,17 +46,20 @@ impl<'a, 'r> FromRequest<'a, 'r> for ListTicketsCommand {
impl ListTicketsCommand {
/// Analyzes running containers and returns a map of `review-app-name` with the
/// corresponding `TicketInfo`.
pub fn list_ticket_infos(&self) -> Result<HashMap<String, TicketInfo>, ListTicketsError> {
pub fn list_ticket_infos(
&self,
config: &Config,
) -> Result<HashMap<String, TicketInfo>, ListTicketsError> {
let mut tickets: HashMap<String, TicketInfo> = HashMap::new();

match Config::load()?.get_jira_config() {
match config.get_jira_config() {
None => {
return Err(ListTicketsError::MissingIssueTrackingConfiguration(
"".to_string(),
));
}
Some(jira_config) => {
let apps_service = AppsService::new()?;
let apps_service = AppsService::new(config)?;
let services = apps_service.get_apps()?;

let jira = Jira::new(
@@ -52,10 +52,12 @@ extern crate toml;
extern crate url;

use crate::models::request_info::RequestInfo;
use crate::services::config_service::Config;
use rocket_contrib::json::Json;
use serde_yaml::{from_reader, to_string, Value};
use shiplift::{ContainerListOptions, Docker};
use std::fs::File;
use std::process;
use tokio::prelude::Future;
use tokio::runtime::Runtime;

@@ -118,7 +120,16 @@ fn swagger(request_info: RequestInfo) -> String {
fn main() {
env_logger::init();

let config = match Config::load() {
Ok(config) => config,
Err(e) => {
error!("Cannot load config: {}", e);
process::exit(0x0100);
}
};

rocket::ignite()
.manage(config)
.mount("/", routes![index])
.mount("/", routes![swagger])
.mount("/", routes![apps::apps])
@@ -38,15 +38,15 @@ use handlebars::TemplateRenderError;
use multimap::MultiMap;
use std::convert::From;

pub struct AppsService {
config: Config,
pub struct AppsService<'a> {
config: &'a Config,
infrastructure: Box<dyn Infrastructure>,
}

impl AppsService {
pub fn new() -> Result<AppsService, AppsServiceError> {
impl<'a> AppsService<'a> {
pub fn new(config: &'a Config) -> Result<AppsService, AppsServiceError> {
Ok(AppsService {
config: Config::load()?,
config,
infrastructure: Box::new(DockerInfrastructure::new()),
})
}
@@ -188,22 +188,25 @@ impl ContainerConfig {
}
}

#[derive(Debug)]
#[derive(Debug, Fail)]
pub enum ConfigError {
CannotOpenConfigFile(IOError),
ConfigFormatError(TomlError),
#[fail(display = "Cannot open config file. {}", error)]
CannotOpenConfigFile { error: IOError },
#[fail(display = "Invalid config file format. {}", error)]
ConfigFormatError { error: TomlError },
#[fail(display = "Unable to parse image.")]
UnableToParseImage,
}

impl From<IOError> for ConfigError {
fn from(err: IOError) -> Self {
ConfigError::CannotOpenConfigFile(err)
fn from(error: IOError) -> Self {
ConfigError::CannotOpenConfigFile { error }
}
}

impl From<TomlError> for ConfigError {
fn from(err: TomlError) -> Self {
ConfigError::ConfigFormatError(err)
fn from(error: TomlError) -> Self {
ConfigError::ConfigFormatError { error }
}
}

@@ -27,10 +27,13 @@
use crate::commands::delete_app_command::{DeleteAppCommand, DeleteAppError};
use crate::models::service::Service;
use crate::models::web_hook_info::WebHookInfo;
use crate::services::config_service::Config;
use rocket::State;
use rocket_contrib::json::Json;

#[post("/webhooks", format = "application/json", data = "<web_hook_info>")]
pub fn webhooks(
config_state: State<Config>,
web_hook_info: WebHookInfo,
delete_app_command: DeleteAppCommand,
) -> Result<Json<Vec<Service>>, DeleteAppError> {
@@ -41,6 +44,6 @@ pub fn webhooks(
web_hook_info.get_event_key()
);

let services = delete_app_command.delete_app(&web_hook_info.get_app_name())?;
let services = delete_app_command.delete_app(&config_state, &web_hook_info.get_app_name())?;
Ok(Json(services))
}

0 comments on commit fd920e5

Please sign in to comment.