Skip to content

Commit

Permalink
Merge #367: Improve docker UX
Browse files Browse the repository at this point in the history
ec7bd7d fix: env var name. Wrong prefix (Jose Celano)
8936c6e feat!: continue running the tracker after creating default config file (Jose Celano)
702dd14 feat: allow to change the config.toml file path (Jose Celano)
0adf373 refactor: [#361] rename constants representing env vars (Jose Celano)
8a79fbe refactor: [#361] extract mod for configuration (Jose Celano)

Pull request description:

  Some minor improvements to make using docker and the app configuration a smoother experience.

Top commit has no ACKs.

Tree-SHA512: eef1d68b78e0a228714c926881e6a09f5c859632488fbf69fd5dcdc4d34e8654835afc32d4620af7d7753a99ee2a92d8ddc49f97e055ae72b4f987aad261609c
  • Loading branch information
josecelano committed Aug 9, 2023
2 parents 5a0441b + ec7bd7d commit 3bc0a8c
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 57 deletions.
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;

0 comments on commit 3bc0a8c

Please sign in to comment.