Use configuration file

This commit is contained in:
2022-02-19 20:37:30 +01:00
parent 3e27c21565
commit f090741944
11 changed files with 356 additions and 39 deletions

42
src/configuration.rs Normal file
View File

@@ -0,0 +1,42 @@
use config::{Config, ConfigError, Environment, File};
use serde::Deserialize;
use std::env;
#[derive(Deserialize)]
pub struct Settings {
pub application: ApplicationSettings,
pub taskwarrior: TaskwarriorSettings,
}
#[derive(Deserialize)]
pub struct ApplicationSettings {
pub port: u16,
pub log_directive: String,
}
#[derive(Deserialize)]
pub struct TaskwarriorSettings {
pub data_location: Option<String>,
pub taskrc: Option<String>,
}
impl Settings {
pub fn new_from_file(file: Option<String>) -> Result<Self, ConfigError> {
let config_file_required = file.is_some();
let config_file =
file.unwrap_or_else(|| env::var("CONFIG").unwrap_or_else(|_| "dev".into()));
let config = Config::builder()
.add_source(File::with_name("config/default"))
.add_source(File::with_name("config/local").required(false))
.add_source(File::with_name(&config_file).required(config_file_required))
.add_source(Environment::with_prefix("cs"))
.build()?;
config.try_deserialize()
}
pub fn new() -> Result<Self, ConfigError> {
Settings::new_from_file(None)
}
}

View File

@@ -1,3 +1,4 @@
use crate::configuration::TaskwarriorSettings;
use anyhow::{anyhow, Context};
use chrono::{DateTime, Utc};
use configparser::ini::Ini;
@@ -156,8 +157,8 @@ fn write_default_config(data_location: &str) -> String {
taskrc_location.into()
}
pub fn load_config(task_data_location: Option<&str>) -> String {
if let Ok(taskrc_location) = env::var("TASKRC") {
pub fn load_config(settings: &TaskwarriorSettings) -> String {
if let Some(taskrc_location) = &settings.taskrc {
let mut taskrc = Ini::new();
taskrc
.load(&taskrc_location)
@@ -168,6 +169,8 @@ pub fn load_config(task_data_location: Option<&str>) -> String {
taskrc_location
)
});
env::set_var("TASKRC", &taskrc_location);
debug!(
"Extracted data location `{}` from existing taskrc `{}`",
data_location, taskrc_location
@@ -175,12 +178,11 @@ pub fn load_config(task_data_location: Option<&str>) -> String {
data_location
} else {
let data_location = task_data_location
.map(|s| s.to_string())
.unwrap_or_else(|| {
env::var("TASK_DATA_LOCATION")
.expect("Expecting TASKRC or TASK_DATA_LOCATION environment variable value")
});
let data_location = settings
.data_location
.as_ref()
.expect("Expecting taskwarrior.taskrc or taskwarrior.data_location setting to be set")
.to_string();
let taskrc_location = write_default_config(&data_location);
env::set_var("TASKRC", &taskrc_location);

View File

@@ -7,6 +7,7 @@ use tracing_actix_web::TracingLogger;
#[macro_use]
extern crate lazy_static;
pub mod configuration;
pub mod contextswitch;
pub mod observability;
pub mod routes;

View File

@@ -1,22 +1,19 @@
extern crate dotenv;
extern crate listenfd;
use contextswitch_api::configuration::Settings;
use contextswitch_api::observability::{get_subscriber, init_subscriber};
use contextswitch_api::{contextswitch::taskwarrior, run};
use dotenv::dotenv;
use std::env;
use std::net::TcpListener;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let subscriber = get_subscriber("info".into());
let settings = Settings::new().expect("Cannot load Contextswitch configuration");
let subscriber = get_subscriber(&settings.application.log_directive);
init_subscriber(subscriber);
dotenv().ok();
taskwarrior::load_config(&settings.taskwarrior);
let port = env::var("PORT").unwrap_or_else(|_| "8000".to_string());
taskwarrior::load_config(None);
let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).expect("Failed to bind port");
let listener = TcpListener::bind(format!("0.0.0.0:{}", settings.application.port))
.expect("Failed to bind port");
run(listener)?.await
}

View File

@@ -4,7 +4,7 @@ use tracing_log::LogTracer;
use tracing_subscriber::fmt::TestWriter;
use tracing_subscriber::{layer::SubscriberExt, EnvFilter};
pub fn get_subscriber(env_filter_str: String) -> impl Subscriber + Send + Sync {
pub fn get_subscriber(env_filter_str: &str) -> impl Subscriber + Send + Sync {
let formatting_layer = BunyanFormattingLayer::new("contextswitch-api".into(), TestWriter::new);
let env_filter =