Skip to content

Commit

Permalink
reafactor(configuration): Improve configuration management
Browse files Browse the repository at this point in the history
  • Loading branch information
Yag000 committed Sep 1, 2023
1 parent 127f625 commit 61dbec1
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 13 deletions.
7 changes: 4 additions & 3 deletions configuration.yml → configuration/base.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
application_port: 8000
application:
port: 8000
database:
host: "127.0.0.1"
port: 5069
host: "localhost"
port: 5432
username: "postgres"
password: "password"
database_name: "newsletter"
2 changes: 2 additions & 0 deletions configuration/local.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
application:
host: 127.0.0.1
2 changes: 2 additions & 0 deletions configuration/production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
application:
host: 0.0.0.0
64 changes: 54 additions & 10 deletions src/configurations.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use config::{Config, ConfigBuilder, FileFormat};
use secrecy::{ExposeSecret, Secret};

#[derive(serde::Deserialize)]
pub struct Settings {
pub database: DatabaseSettings,
pub application_port: u16,
pub application: ApplicationSettings,
}

#[derive(serde::Deserialize)]
Expand All @@ -15,6 +16,12 @@ pub struct DatabaseSettings {
pub database_name: String,
}

#[derive(serde::Deserialize)]
pub struct ApplicationSettings {
pub port: u16,
pub host: String,
}

impl DatabaseSettings {
pub fn get_connnection_string(&self) -> Secret<String> {
Secret::new(format!(
Expand All @@ -39,14 +46,51 @@ impl DatabaseSettings {
}

pub fn get_configuration() -> Result<Settings, config::ConfigError> {
// Initialize the configuration reader
let settings = config::Config::builder()
// Config file name
.add_source(config::File::new(
"configuration.yml",
config::FileFormat::Yaml,
))
.build()?;
let base_path = std::env::current_dir().expect("Failed to determine the current directory");
let configuration_directory = base_path.join("configuration");

let environment: Environment = std::env::var("APP_ENVIRONMENT")
.unwrap_or_else(|_| "local".into())
.try_into()
.expect("Failed to parse APP_ENVIRONMENT.");

let settings = Config::builder()
.add_source(config::File::from(configuration_directory.join("base")).required(true))
.add_source(
config::File::from(configuration_directory.join(environment.as_str())).required(true),
);

match settings.build() {
Ok(config) => config.try_deserialize::<Settings>(),
Err(e) => Err(e),
}
}

settings.try_deserialize::<Settings>()
pub enum Environment {
Production,
Local,
}

impl Environment {
pub fn as_str(&self) -> &'static str {
match self {
Environment::Production => "production",
Environment::Local => "local",
}
}
}

impl TryFrom<String> for Environment {
type Error = String;

fn try_from(value: String) -> Result<Self, Self::Error> {
match value.to_lowercase().as_str() {
"local" => Ok(Environment::Local),
"production" => Ok(Environment::Production),
_ => Err(format!(
"{} is not a supported environment. Use either `local` or `production`.",
value
)),
}
}
}

0 comments on commit 61dbec1

Please sign in to comment.