From 60c68762b64b7b909987fc6002447af7c823adbe Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 2 Jul 2024 08:23:23 +0100 Subject: [PATCH] feat: [#937] add version to configration file following semver. Add version and namespace to the configuration. It will fail if the provided version is not supported. ```toml version = "2" ``` It only supports the exact match '2'. --- packages/configuration/src/lib.rs | 62 ++++++++++++++++++- packages/configuration/src/v2/mod.rs | 20 +++++- .../config/tracker.container.mysql.toml | 2 + .../config/tracker.container.sqlite3.toml | 2 + .../config/tracker.development.sqlite3.toml | 2 + .../config/tracker.e2e.container.sqlite3.toml | 2 + .../config/tracker.udp.benchmarking.toml | 2 + 7 files changed, 89 insertions(+), 3 deletions(-) diff --git a/packages/configuration/src/lib.rs b/packages/configuration/src/lib.rs index 841a5182e..e5bfa6eb7 100644 --- a/packages/configuration/src/lib.rs +++ b/packages/configuration/src/lib.rs @@ -12,7 +12,7 @@ use std::sync::Arc; use std::time::Duration; use camino::Utf8PathBuf; -use derive_more::Constructor; +use derive_more::{Constructor, Display}; use serde::{Deserialize, Serialize}; use serde_with::serde_as; use thiserror::Error; @@ -45,6 +45,63 @@ pub type Threshold = v2::logging::Threshold; pub type AccessTokens = HashMap; +pub const LATEST_VERSION: &str = "2"; + +/// Info about the configuration specification. +#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Display)] +pub struct Metadata { + #[serde(default = "Metadata::default_version")] + #[serde(flatten)] + version: Version, +} + +impl Default for Metadata { + fn default() -> Self { + Self { + version: Self::default_version(), + } + } +} + +impl Metadata { + fn default_version() -> Version { + Version::latest() + } +} + +/// The configuration version. +#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Display)] +pub struct Version { + #[serde(default = "Version::default_semver")] + version: String, +} + +impl Default for Version { + fn default() -> Self { + Self { + version: Self::default_semver(), + } + } +} + +impl Version { + fn new(semver: &str) -> Self { + Self { + version: semver.to_owned(), + } + } + + fn latest() -> Self { + Self { + version: LATEST_VERSION.to_string(), + } + } + + fn default_semver() -> String { + LATEST_VERSION.to_string() + } +} + #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Constructor)] pub struct TrackerPolicy { // Cleanup job configuration @@ -208,6 +265,9 @@ pub enum Error { #[error("The error for errors that can never happen.")] Infallible, + + #[error("Unsupported configuration version: {version}")] + UnsupportedVersion { version: Version }, } impl From for Error { diff --git a/packages/configuration/src/v2/mod.rs b/packages/configuration/src/v2/mod.rs index 92ac88506..3425dc0de 100644 --- a/packages/configuration/src/v2/mod.rs +++ b/packages/configuration/src/v2/mod.rs @@ -251,16 +251,24 @@ use self::health_check_api::HealthCheckApi; use self::http_tracker::HttpTracker; use self::tracker_api::HttpApi; use self::udp_tracker::UdpTracker; -use crate::{Error, Info}; +use crate::{Error, Info, Metadata, Version}; + +/// This configuration version +const VERSION_2: &str = "2"; /// Prefix for env vars that overwrite configuration options. const CONFIG_OVERRIDE_PREFIX: &str = "TORRUST_TRACKER_CONFIG_OVERRIDE_"; + /// Path separator in env var names for nested values in configuration. const CONFIG_OVERRIDE_SEPARATOR: &str = "__"; /// Core configuration for the tracker. #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Default)] pub struct Configuration { + /// Configuration metadata. + #[serde(flatten)] + pub metadata: Metadata, + /// Logging configuration pub logging: Logging, @@ -326,6 +334,12 @@ impl Configuration { let config: Configuration = figment.extract()?; + if config.metadata.version != Version::new(VERSION_2) { + return Err(Error::UnsupportedVersion { + version: config.metadata.version, + }); + } + Ok(config) } @@ -378,7 +392,9 @@ mod tests { #[cfg(test)] fn default_config_toml() -> String { - let config = r#"[logging] + let config = r#"version = "2" + + [logging] threshold = "info" [core] diff --git a/share/default/config/tracker.container.mysql.toml b/share/default/config/tracker.container.mysql.toml index 68cc8db8a..9465c0ef8 100644 --- a/share/default/config/tracker.container.mysql.toml +++ b/share/default/config/tracker.container.mysql.toml @@ -1,3 +1,5 @@ +version = "2" + [core.database] driver = "MySQL" path = "mysql://db_user:db_user_secret_password@mysql:3306/torrust_tracker" diff --git a/share/default/config/tracker.container.sqlite3.toml b/share/default/config/tracker.container.sqlite3.toml index 63e169a70..aa8aefa5e 100644 --- a/share/default/config/tracker.container.sqlite3.toml +++ b/share/default/config/tracker.container.sqlite3.toml @@ -1,3 +1,5 @@ +version = "2" + [core.database] path = "/var/lib/torrust/tracker/database/sqlite3.db" diff --git a/share/default/config/tracker.development.sqlite3.toml b/share/default/config/tracker.development.sqlite3.toml index 84754794e..554835922 100644 --- a/share/default/config/tracker.development.sqlite3.toml +++ b/share/default/config/tracker.development.sqlite3.toml @@ -1,3 +1,5 @@ +version = "2" + [[udp_trackers]] bind_address = "0.0.0.0:6969" diff --git a/share/default/config/tracker.e2e.container.sqlite3.toml b/share/default/config/tracker.e2e.container.sqlite3.toml index fb33a8e32..6b1383fb5 100644 --- a/share/default/config/tracker.e2e.container.sqlite3.toml +++ b/share/default/config/tracker.e2e.container.sqlite3.toml @@ -1,3 +1,5 @@ +version = "2" + [core.database] path = "/var/lib/torrust/tracker/database/sqlite3.db" diff --git a/share/default/config/tracker.udp.benchmarking.toml b/share/default/config/tracker.udp.benchmarking.toml index c01fcd25e..907a05456 100644 --- a/share/default/config/tracker.udp.benchmarking.toml +++ b/share/default/config/tracker.udp.benchmarking.toml @@ -1,3 +1,5 @@ +version = "2" + [logging] threshold = "error"