Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 14 additions & 27 deletions packages/configuration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,14 +228,11 @@
//!```
use std::collections::{HashMap, HashSet};
use std::net::IpAddr;
use std::panic::Location;
use std::path::Path;
use std::str::FromStr;
use std::sync::Arc;
use std::{env, fs};

use config::{Config, ConfigError, File, FileFormat};
use log::warn;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, NoneAsEmptyString};
use thiserror::Error;
Expand Down Expand Up @@ -414,17 +411,6 @@ pub enum Error {
source: LocatedError<'static, dyn std::error::Error + Send + Sync>,
},

/// If you run the tracker without providing the configuration (via the
/// `TORRUST_TRACKER_CONFIG` environment variable or configuration file),
/// the tracker will create a default configuration file but it will not
/// load it. It will return this error instead and you have to restart the
/// it.
#[error("Default configuration created at: `{path}`, please review and reload tracker, {location}")]
CreatedNewConfigHalt {
location: &'static Location<'static>,
path: String,
},

/// Unable to load the configuration from the configuration file.
#[error("Failed processing the configuration: {source}")]
ConfigError { source: LocatedError<'static, ConfigError> },
Expand Down Expand Up @@ -502,31 +488,32 @@ impl Configuration {
///
/// # Errors
///
/// Will return `Err` if `path` does not exist or has a bad configuration.
/// Will return `Err` if `path` does not exist or has a bad configuration.
pub fn load_from_file(path: &str) -> Result<Configuration, Error> {
let config_builder = Config::builder();

#[allow(unused_assignments)]
let mut config = Config::default();

if Path::new(path).exists() {
config = config_builder.add_source(File::with_name(path)).build()?;
} else {
warn!("No config file found.");
warn!("Creating config file..");
let config = Configuration::default();
config.save_to_file(path)?;
return Err(Error::CreatedNewConfigHalt {
location: Location::caller(),
path: path.to_string(),
});
}
config = config_builder.add_source(File::with_name(path)).build()?;

let torrust_config: Configuration = config.try_deserialize()?;

Ok(torrust_config)
}

/// Saves the default configuration at the given path.
///
/// # Errors
///
/// Will return `Err` if `path` is not a valid path or the configuration
/// file cannot be created.
pub fn create_default_configuration_file(path: &str) -> Result<Configuration, Error> {
let config = Configuration::default();
config.save_to_file(path)?;
Ok(config)
}

/// Loads the configuration from the environment variable. The whole
/// configuration must be in the environment variable. It contains the same
/// configuration as the configuration file with the same format.
Expand Down
31 changes: 1 addition & 30 deletions src/bootstrap/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
//! 2. Initialize static variables.
//! 3. Initialize logging.
//! 4. Initialize the domain tracker.
use std::env;
use std::sync::Arc;

use torrust_tracker_configuration::Configuration;

use super::config::initialize_configuration;
use crate::bootstrap;
use crate::shared::clock::static_time;
use crate::shared::crypto::ephemeral_instance_keys;
Expand Down Expand Up @@ -55,35 +55,6 @@ pub fn initialize_static() {
lazy_static::initialize(&ephemeral_instance_keys::RANDOM_SEED);
}

/// It loads the application configuration from the environment.
///
/// There are two methods to inject the configuration:
///
/// 1. By using a config file: `config.toml`. The file must be in the same folder where you are running the tracker.
/// 2. Environment variable: `TORRUST_TRACKER_CONFIG`. The variable contains the same contents as the `config.toml` file.
///
/// Environment variable has priority over the config file.
///
/// Refer to the [configuration documentation](https://docs.rs/torrust-tracker-configuration) for the configuration options.
///
/// # Panics
///
/// Will panic if it can't load the configuration from either
/// `./config.toml` file or the env var `TORRUST_TRACKER_CONFIG`.
#[must_use]
fn initialize_configuration() -> Configuration {
const CONFIG_PATH: &str = "./config.toml";
const CONFIG_ENV_VAR_NAME: &str = "TORRUST_TRACKER_CONFIG";

if env::var(CONFIG_ENV_VAR_NAME).is_ok() {
println!("Loading configuration from env var {CONFIG_ENV_VAR_NAME}");
Configuration::load_from_env_var(CONFIG_ENV_VAR_NAME).unwrap()
} else {
println!("Loading configuration from config file {CONFIG_PATH}");
Configuration::load_from_file(CONFIG_PATH).unwrap()
}
}

/// It builds the domain tracker
///
/// The tracker is the domain layer service. It's the entrypoint to make requests to the domain layer.
Expand Down
69 changes: 69 additions & 0 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//! Initialize configuration from file or env var.
//!
//! All environment variables are prefixed with `TORRUST_TRACKER_BACK_`.
use std::env;
use std::path::Path;

use torrust_tracker_configuration::{Configuration, Error};

// Environment variables

/// The whole `config.toml` file content. It has priority over the config file.
/// Even if the file is not on the default path.
const ENV_VAR_CONFIG: &str = "TORRUST_TRACKER_CONFIG";

/// The `config.toml` file location.
pub const ENV_VAR_CONFIG_PATH: &str = "TORRUST_TRACKER_CONFIG_PATH";

// Default values

const ENV_VAR_DEFAULT_CONFIG_PATH: &str = "./config.toml";

/// It loads the application configuration from the environment.
///
/// There are two methods to inject the configuration:
///
/// 1. By using a config file: `config.toml`.
/// 2. Environment variable: `TORRUST_TRACKER_CONFIG`. The variable contains the same contents as the `config.toml` file.
///
/// Environment variable has priority over the config file.
///
/// Refer to the [configuration documentation](https://docs.rs/torrust-tracker-configuration) for the configuration options.
///
/// # Panics
///
/// Will panic if it can't load the configuration from either
/// `./config.toml` file or the env var `TORRUST_TRACKER_CONFIG`.
#[must_use]
pub fn initialize_configuration() -> Configuration {
if env::var(ENV_VAR_CONFIG).is_ok() {
println!("Loading configuration from env var {ENV_VAR_CONFIG} ...");

Configuration::load_from_env_var(ENV_VAR_CONFIG).unwrap()
} else {
let config_path = env::var(ENV_VAR_CONFIG_PATH).unwrap_or_else(|_| ENV_VAR_DEFAULT_CONFIG_PATH.to_string());

println!("Loading configuration from configuration file: `{config_path}` ...");

load_from_file_or_create_default(&config_path).unwrap()
}
}

/// Loads the configuration from the configuration file. If the file does
/// not exist, it will create a default configuration file and return an
/// error.
///
/// # Errors
///
/// Will return `Err` if `path` does not exist or has a bad configuration.
fn load_from_file_or_create_default(path: &str) -> Result<Configuration, Error> {
if Path::new(&path).is_file() {
Configuration::load_from_file(path)
} else {
println!("Missing configuration file.");
println!("Creating a default configuration file: `{path}` ...");
let config = Configuration::create_default_configuration_file(path)?;
println!("Please review the config file: `{path}` and restart the tracker if needed.");
Ok(config)
}
}
1 change: 1 addition & 0 deletions src/bootstrap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
//! like cleaning torrents, and other jobs because they can be enabled/disabled depending on the configuration.
//! For example, you can have more than one UDP and HTTP tracker, each server is executed like a independent job.
pub mod app;
pub mod config;
pub mod jobs;
pub mod logging;