Skip to content

Commit

Permalink
feat: define only non-defaults in toml config templates
Browse files Browse the repository at this point in the history
After implementing the configuration with Figment, it's now possible to
omit values if they have a default value. Therefore we don't need to add
all options in templates. We only need to add values that are
overwriting deffault values.
  • Loading branch information
josecelano committed May 13, 2024
1 parent 3c78bba commit 445bd53
Show file tree
Hide file tree
Showing 11 changed files with 169 additions and 185 deletions.
28 changes: 26 additions & 2 deletions packages/configuration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,22 @@ pub struct AnnouncePolicy {
impl Default for AnnouncePolicy {
fn default() -> Self {
Self {
interval: 120,
interval_min: 120,
interval: Self::default_interval(),
interval_min: Self::default_interval_min(),
}
}
}

impl AnnouncePolicy {
fn default_interval() -> u32 {
120
}

fn default_interval_min() -> u32 {
120
}
}

/// Errors that can occur when loading the configuration.
#[derive(Error, Debug)]
pub enum Error {
Expand Down Expand Up @@ -166,12 +176,26 @@ impl From<figment::Error> for Error {
pub struct TslConfig {
/// Path to the SSL certificate file.
#[serde_as(as = "NoneAsEmptyString")]
#[serde(default = "TslConfig::default_ssl_cert_path")]
pub ssl_cert_path: Option<Utf8PathBuf>,
/// Path to the SSL key file.
#[serde_as(as = "NoneAsEmptyString")]
#[serde(default = "TslConfig::default_ssl_key_path")]
pub ssl_key_path: Option<Utf8PathBuf>,
}

impl TslConfig {
#[allow(clippy::unnecessary_wraps)]
fn default_ssl_cert_path() -> Option<Utf8PathBuf> {
Some(Utf8PathBuf::new())
}

#[allow(clippy::unnecessary_wraps)]
fn default_ssl_key_path() -> Option<Utf8PathBuf> {
Some(Utf8PathBuf::new())
}
}

#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Clone)]
#[serde(rename_all = "lowercase")]
pub enum LogLevel {
Expand Down
83 changes: 72 additions & 11 deletions packages/configuration/src/v1/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,58 +10,71 @@ use crate::{AnnouncePolicy, LogLevel};
pub struct Core {
/// Logging level. Possible values are: `Off`, `Error`, `Warn`, `Info`,
/// `Debug` and `Trace`. Default is `Info`.
#[serde(default = "Core::default_log_level")]
pub log_level: Option<LogLevel>,
/// Tracker mode. See [`TrackerMode`] for more information.
#[serde(default = "Core::default_mode")]
pub mode: TrackerMode,

// Database configuration
/// Database driver. Possible values are: `Sqlite3`, and `MySQL`.
#[serde(default = "Core::default_db_driver")]
pub db_driver: DatabaseDriver,
/// Database connection string. The format depends on the database driver.
/// For `Sqlite3`, the format is `path/to/database.db`, for example:
/// `./storage/tracker/lib/database/sqlite3.db`.
/// For `Mysql`, the format is `mysql://db_user:db_user_password:port/db_name`, for
/// example: `root:password@localhost:3306/torrust`.
#[serde(default = "Core::default_db_path")]
pub db_path: String,

/// See [`AnnouncePolicy::interval`]
#[serde(default = "AnnouncePolicy::default_interval")]
pub announce_interval: u32,

/// See [`AnnouncePolicy::interval_min`]
#[serde(default = "AnnouncePolicy::default_interval_min")]
pub min_announce_interval: u32,
/// Weather the tracker is behind a reverse proxy or not.
/// If the tracker is behind a reverse proxy, the `X-Forwarded-For` header
/// sent from the proxy will be used to get the client's IP address.
#[serde(default = "Core::default_on_reverse_proxy")]
pub on_reverse_proxy: bool,
/// The external IP address of the tracker. If the client is using a
/// loopback IP address, this IP address will be used instead. If the peer
/// is using a loopback IP address, the tracker assumes that the peer is
/// in the same network as the tracker and will use the tracker's IP
/// address instead.
#[serde(default = "Core::default_external_ip")]
pub external_ip: Option<IpAddr>,
/// Weather the tracker should collect statistics about tracker usage.
/// If enabled, the tracker will collect statistics like the number of
/// connections handled, the number of announce requests handled, etc.
/// Refer to the [`Tracker`](https://docs.rs/torrust-tracker) for more
/// information about the collected metrics.
#[serde(default = "Core::default_tracker_usage_statistics")]
pub tracker_usage_statistics: bool,
/// If enabled the tracker will persist the number of completed downloads.
/// That's how many times a torrent has been downloaded completely.
#[serde(default = "Core::default_persistent_torrent_completed_stat")]
pub persistent_torrent_completed_stat: bool,

// Cleanup job configuration
/// Maximum time in seconds that a peer can be inactive before being
/// considered an inactive peer. If a peer is inactive for more than this
/// time, it will be removed from the torrent peer list.
#[serde(default = "Core::default_max_peer_timeout")]
pub max_peer_timeout: u32,
/// Interval in seconds that the cleanup job will run to remove inactive
/// peers from the torrent peer list.
#[serde(default = "Core::default_inactive_peer_cleanup_interval")]
pub inactive_peer_cleanup_interval: u64,
/// If enabled, the tracker will remove torrents that have no peers.
/// The clean up torrent job runs every `inactive_peer_cleanup_interval`
/// seconds and it removes inactive peers. Eventually, the peer list of a
/// torrent could be empty and the torrent will be removed if this option is
/// enabled.
#[serde(default = "Core::default_remove_peerless_torrents")]
pub remove_peerless_torrents: bool,
}

Expand All @@ -70,19 +83,67 @@ impl Default for Core {
let announce_policy = AnnouncePolicy::default();

Self {
log_level: Some(LogLevel::Info),
mode: TrackerMode::Public,
db_driver: DatabaseDriver::Sqlite3,
db_path: String::from("./storage/tracker/lib/database/sqlite3.db"),
log_level: Self::default_log_level(),
mode: Self::default_mode(),
db_driver: Self::default_db_driver(),
db_path: Self::default_db_path(),
announce_interval: announce_policy.interval,
min_announce_interval: announce_policy.interval_min,
max_peer_timeout: 900,
on_reverse_proxy: false,
external_ip: Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))),
tracker_usage_statistics: true,
persistent_torrent_completed_stat: false,
inactive_peer_cleanup_interval: 600,
remove_peerless_torrents: true,
max_peer_timeout: Self::default_max_peer_timeout(),
on_reverse_proxy: Self::default_on_reverse_proxy(),
external_ip: Self::default_external_ip(),
tracker_usage_statistics: Self::default_tracker_usage_statistics(),
persistent_torrent_completed_stat: Self::default_persistent_torrent_completed_stat(),
inactive_peer_cleanup_interval: Self::default_inactive_peer_cleanup_interval(),
remove_peerless_torrents: Self::default_remove_peerless_torrents(),
}
}
}

impl Core {
#[allow(clippy::unnecessary_wraps)]
fn default_log_level() -> Option<LogLevel> {
Some(LogLevel::Info)
}

fn default_mode() -> TrackerMode {
TrackerMode::Public
}

fn default_db_driver() -> DatabaseDriver {
DatabaseDriver::Sqlite3
}

fn default_db_path() -> String {
String::from("./storage/tracker/lib/database/sqlite3.db")
}

fn default_on_reverse_proxy() -> bool {
false
}

#[allow(clippy::unnecessary_wraps)]
fn default_external_ip() -> Option<IpAddr> {
Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)))
}

fn default_tracker_usage_statistics() -> bool {
true
}

fn default_persistent_torrent_completed_stat() -> bool {
false
}

fn default_max_peer_timeout() -> u32 {
900
}

fn default_inactive_peer_cleanup_interval() -> u64 {
600
}

fn default_remove_peerless_torrents() -> bool {
true
}
}
9 changes: 8 additions & 1 deletion packages/configuration/src/v1/health_check_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,20 @@ pub struct HealthCheckApi {
/// The format is `ip:port`, for example `127.0.0.1:1313`. If you want to
/// listen to all interfaces, use `0.0.0.0`. If you want the operating
/// system to choose a random port, use port `0`.
#[serde(default = "HealthCheckApi::default_bind_address")]

Check warning on line 14 in packages/configuration/src/v1/health_check_api.rs

View check run for this annotation

Codecov / codecov/patch

packages/configuration/src/v1/health_check_api.rs#L14

Added line #L14 was not covered by tests
pub bind_address: SocketAddr,
}

impl Default for HealthCheckApi {
fn default() -> Self {
Self {
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 1313),
bind_address: Self::default_bind_address(),
}
}
}

impl HealthCheckApi {
fn default_bind_address() -> SocketAddr {
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 1313)
}
}
24 changes: 21 additions & 3 deletions packages/configuration/src/v1/http_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,44 @@ use crate::TslConfig;
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub struct HttpTracker {
/// Weather the HTTP tracker is enabled or not.
#[serde(default = "HttpTracker::default_enabled")]
pub enabled: bool,
/// The address the tracker will bind to.
/// The format is `ip:port`, for example `0.0.0.0:6969`. If you want to
/// listen to all interfaces, use `0.0.0.0`. If you want the operating
/// system to choose a random port, use port `0`.
#[serde(default = "HttpTracker::default_bind_address")]
pub bind_address: SocketAddr,
/// Weather the HTTP tracker will use SSL or not.
#[serde(default = "HttpTracker::default_ssl_enabled")]
pub ssl_enabled: bool,
/// TSL config. Only used if `ssl_enabled` is true.
#[serde(flatten)]
#[serde(default = "TslConfig::default")]
pub tsl_config: TslConfig,
}

impl Default for HttpTracker {
fn default() -> Self {
Self {
enabled: false,
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 7070),
ssl_enabled: false,
enabled: Self::default_enabled(),
bind_address: Self::default_bind_address(),
ssl_enabled: Self::default_ssl_enabled(),
tsl_config: TslConfig::default(),
}
}
}

impl HttpTracker {
fn default_enabled() -> bool {
false
}

fn default_bind_address() -> SocketAddr {
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 7070)
}

fn default_ssl_enabled() -> bool {
false
}
}
35 changes: 28 additions & 7 deletions packages/configuration/src/v1/tracker_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,61 @@ pub type AccessTokens = HashMap<String, String>;
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub struct HttpApi {
/// Weather the HTTP API is enabled or not.
#[serde(default = "HttpApi::default_enabled")]
pub enabled: bool,
/// The address the tracker will bind to.
/// The format is `ip:port`, for example `0.0.0.0:6969`. If you want to
/// listen to all interfaces, use `0.0.0.0`. If you want the operating
/// system to choose a random port, use port `0`.
#[serde(default = "HttpApi::default_bind_address")]
pub bind_address: SocketAddr,
/// Weather the HTTP API will use SSL or not.
#[serde(default = "HttpApi::default_ssl_enabled")]
pub ssl_enabled: bool,
/// TSL config. Only used if `ssl_enabled` is true.
#[serde(flatten)]
#[serde(default = "TslConfig::default")]
pub tsl_config: TslConfig,
/// Access tokens for the HTTP API. The key is a label identifying the
/// token and the value is the token itself. The token is used to
/// authenticate the user. All tokens are valid for all endpoints and have
/// all permissions.
#[serde(default = "HttpApi::default_access_tokens")]
pub access_tokens: AccessTokens,
}

impl Default for HttpApi {
fn default() -> Self {
Self {
enabled: true,
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 1212),
ssl_enabled: false,
enabled: Self::default_enabled(),
bind_address: Self::default_bind_address(),
ssl_enabled: Self::default_ssl_enabled(),
tsl_config: TslConfig::default(),
access_tokens: [(String::from("admin"), String::from("MyAccessToken"))]
.iter()
.cloned()
.collect(),
access_tokens: Self::default_access_tokens(),
}
}
}

impl HttpApi {
fn default_enabled() -> bool {
true
}

fn default_bind_address() -> SocketAddr {
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 1212)
}

fn default_ssl_enabled() -> bool {
false
}

fn default_access_tokens() -> AccessTokens {
[(String::from("admin"), String::from("MyAccessToken"))]
.iter()
.cloned()
.collect()
}

pub fn override_admin_token(&mut self, api_admin_token: &str) {
self.access_tokens.insert("admin".to_string(), api_admin_token.to_string());
}
Expand Down
16 changes: 14 additions & 2 deletions packages/configuration/src/v1/udp_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,30 @@ use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub struct UdpTracker {
/// Weather the UDP tracker is enabled or not.
#[serde(default = "UdpTracker::default_enabled")]

Check warning on line 8 in packages/configuration/src/v1/udp_tracker.rs

View check run for this annotation

Codecov / codecov/patch

packages/configuration/src/v1/udp_tracker.rs#L8

Added line #L8 was not covered by tests
pub enabled: bool,
/// The address the tracker will bind to.
/// The format is `ip:port`, for example `0.0.0.0:6969`. If you want to
/// listen to all interfaces, use `0.0.0.0`. If you want the operating
/// system to choose a random port, use port `0`.
#[serde(default = "UdpTracker::default_bind_address")]

Check warning on line 14 in packages/configuration/src/v1/udp_tracker.rs

View check run for this annotation

Codecov / codecov/patch

packages/configuration/src/v1/udp_tracker.rs#L14

Added line #L14 was not covered by tests
pub bind_address: SocketAddr,
}
impl Default for UdpTracker {
fn default() -> Self {
Self {
enabled: false,
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 6969),
enabled: Self::default_enabled(),
bind_address: Self::default_bind_address(),
}
}
}

impl UdpTracker {
fn default_enabled() -> bool {
false
}

fn default_bind_address() -> SocketAddr {
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 6969)
}
}
Loading

0 comments on commit 445bd53

Please sign in to comment.