diff options
| author | Markus Pettersson <markus.pettersson@mullvad.net> | 2024-11-22 18:10:12 +0100 |
|---|---|---|
| committer | Sebastian Holmin <sebastian.holmin@mullvad.net> | 2025-01-22 13:32:06 +0100 |
| commit | aab565ed60931f7c75aaded815f3ac5b46fa6bb5 (patch) | |
| tree | 1a737dc875015676d6635a33af459945e5d539b4 | |
| parent | e913da1df1185c56673c99a1eb6e42d08d8361ed (diff) | |
| download | mullvadvpn-aab565ed60931f7c75aaded815f3ac5b46fa6bb5.tar.xz mullvadvpn-aab565ed60931f7c75aaded815f3ac5b46fa6bb5.zip | |
Convert test-manager config into a module
| -rw-r--r-- | test/test-manager/src/config/error.rs | 15 | ||||
| -rw-r--r-- | test/test-manager/src/config/io.rs | 80 | ||||
| -rw-r--r-- | test/test-manager/src/config/manifest.rs | 47 | ||||
| -rw-r--r-- | test/test-manager/src/config/mod.rs | 19 | ||||
| -rw-r--r-- | test/test-manager/src/config/vm.rs (renamed from test/test-manager/src/config.rs) | 140 |
5 files changed, 165 insertions, 136 deletions
diff --git a/test/test-manager/src/config/error.rs b/test/test-manager/src/config/error.rs new file mode 100644 index 0000000000..17ad599da9 --- /dev/null +++ b/test/test-manager/src/config/error.rs @@ -0,0 +1,15 @@ +use std::io; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Could not find config dir")] + FindConfigDir, + #[error("Could not create config dir")] + CreateConfigDir(#[source] io::Error), + #[error("Failed to read config")] + Read(#[source] io::Error), + #[error("Failed to parse config")] + InvalidConfig(#[from] serde_json::Error), + #[error("Failed to write config")] + Write(#[source] io::Error), +} diff --git a/test/test-manager/src/config/io.rs b/test/test-manager/src/config/io.rs new file mode 100644 index 0000000000..2dcc05ca0b --- /dev/null +++ b/test/test-manager/src/config/io.rs @@ -0,0 +1,80 @@ +//! See [ConfigFile]. + +use std::io; +use std::ops::Deref; +use std::path::{Path, PathBuf}; + +use super::{Config, Error}; + +/// On-disk representation of [Config]. +pub struct ConfigFile { + path: PathBuf, + config: Config, +} + +impl ConfigFile { + /// Make config changes and save them to disk + pub async fn edit(&mut self, edit: impl FnOnce(&mut Config)) -> Result<(), Error> { + Self::ensure_config_dir().await?; + edit(&mut self.config); + self.config_save().await + } + + /// Make config changes and save them to disk + pub async fn load_or_default() -> Result<Self, Error> { + let path = Self::get_config_path()?; + let config = Self::config_load_or_default(&path).await?; + let config_file = Self { path, config }; + Ok(config_file) + } + + async fn config_load_or_default<P: AsRef<Path>>(path: P) -> Result<Config, Error> { + Self::config_load(path).await.or_else(|error| match error { + Error::Read(ref io_err) if io_err.kind() == io::ErrorKind::NotFound => { + log::trace!("Failed to read config file"); + Ok(Config::default()) + } + error => Err(error), + }) + } + + async fn config_load<P: AsRef<Path>>(path: P) -> Result<Config, Error> { + let data = tokio::fs::read(path).await.map_err(Error::Read)?; + serde_json::from_slice(&data).map_err(Error::InvalidConfig) + } + + async fn config_save(&self) -> Result<(), Error> { + let data = serde_json::to_vec_pretty(&self.config).unwrap(); + tokio::fs::write(&self.path, &data) + .await + .map_err(Error::Write) + } + + /// Get configuration file path + fn get_config_path() -> Result<PathBuf, Error> { + Ok(Self::get_config_dir()?.join("config.json")) + } + + /// Get configuration file directory + fn get_config_dir() -> Result<PathBuf, Error> { + let dir = dirs::config_dir() + .ok_or(Error::FindConfigDir)? + .join("mullvad-test"); + Ok(dir) + } + + /// Create configuration file directory if it does not exist + async fn ensure_config_dir() -> Result<(), Error> { + tokio::fs::create_dir_all(Self::get_config_dir()?) + .await + .map_err(Error::CreateConfigDir) + } +} + +impl Deref for ConfigFile { + type Target = Config; + + fn deref(&self) -> &Self::Target { + &self.config + } +} diff --git a/test/test-manager/src/config/manifest.rs b/test/test-manager/src/config/manifest.rs new file mode 100644 index 0000000000..8ef96dc89d --- /dev/null +++ b/test/test-manager/src/config/manifest.rs @@ -0,0 +1,47 @@ +//! Config definition. +//! TODO: Document struct and link to that documentation + +use std::collections::BTreeMap; + +use serde::{Deserialize, Serialize}; + +use super::VmConfig; +use crate::tests::config::DEFAULT_MULLVAD_HOST; + +#[derive(Default, Serialize, Deserialize, Clone)] +pub struct Config { + #[serde(skip)] + pub runtime_opts: RuntimeOptions, + pub vms: BTreeMap<String, VmConfig>, + pub mullvad_host: Option<String>, +} + +#[derive(Default, Serialize, Deserialize, Clone)] +pub struct RuntimeOptions { + pub display: Display, + pub keep_changes: bool, +} + +#[derive(Default, Serialize, Deserialize, Clone)] +pub enum Display { + #[default] + None, + Local, + Vnc, +} + +impl Config { + pub fn get_vm(&self, name: &str) -> Option<&VmConfig> { + self.vms.get(name) + } + + /// Get the Mullvad host to use. + /// + /// Defaults to [`DEFAULT_MULLVAD_HOST`] if the host was not provided in the [`ConfigFile`]. + pub fn get_host(&self) -> String { + self.mullvad_host.clone().unwrap_or_else(|| { + log::debug!("No Mullvad host has been set explicitly. Falling back to default host"); + DEFAULT_MULLVAD_HOST.to_owned() + }) + } +} diff --git a/test/test-manager/src/config/mod.rs b/test/test-manager/src/config/mod.rs new file mode 100644 index 0000000000..4dc6e72482 --- /dev/null +++ b/test/test-manager/src/config/mod.rs @@ -0,0 +1,19 @@ +//! Test manager configuration. + +mod error; +mod io; +mod manifest; +mod vm; + +use error::Error; +pub use io::ConfigFile; +pub use manifest::{Config, Display}; +pub use vm::{Architecture, OsType, PackageType, Provisioner, VmConfig, VmType}; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_relay_location_per_test_override() {} +} diff --git a/test/test-manager/src/config.rs b/test/test-manager/src/config/vm.rs index 95a13c48a6..911d2fcf64 100644 --- a/test/test-manager/src/config.rs +++ b/test/test-manager/src/config/vm.rs @@ -1,141 +1,9 @@ -//! Test manager configuration. +//! Virtual machine configuration. -use serde::{Deserialize, Serialize}; -use std::{ - collections::BTreeMap, - env, io, - ops::Deref, - path::{Path, PathBuf}, -}; - -use crate::tests::config::DEFAULT_MULLVAD_HOST; - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error("Could not find config dir")] - FindConfigDir, - #[error("Could not create config dir")] - CreateConfigDir(#[source] io::Error), - #[error("Failed to read config")] - Read(#[source] io::Error), - #[error("Failed to parse config")] - InvalidConfig(#[from] serde_json::Error), - #[error("Failed to write config")] - Write(#[source] io::Error), -} - -#[derive(Default, Serialize, Deserialize, Clone)] -pub struct Config { - #[serde(skip)] - pub runtime_opts: RuntimeOptions, - pub vms: BTreeMap<String, VmConfig>, - pub mullvad_host: Option<String>, -} - -#[derive(Default, Serialize, Deserialize, Clone)] -pub struct RuntimeOptions { - pub display: Display, - pub keep_changes: bool, -} - -#[derive(Default, Serialize, Deserialize, Clone)] -pub enum Display { - #[default] - None, - Local, - Vnc, -} - -impl Config { - async fn load_or_default<P: AsRef<Path>>(path: P) -> Result<Self, Error> { - Self::load(path).await.or_else(|error| match error { - Error::Read(ref io_err) if io_err.kind() == io::ErrorKind::NotFound => { - Ok(Self::default()) - } - error => Err(error), - }) - } - - async fn load<P: AsRef<Path>>(path: P) -> Result<Self, Error> { - let data = tokio::fs::read(path).await.map_err(Error::Read)?; - serde_json::from_slice(&data).map_err(Error::InvalidConfig) - } - - async fn save<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> { - let data = serde_json::to_vec_pretty(self).unwrap(); - tokio::fs::write(path, &data).await.map_err(Error::Write) - } - - pub fn get_vm(&self, name: &str) -> Option<&VmConfig> { - self.vms.get(name) - } - - /// Get the Mullvad host to use. - /// - /// Defaults to [`DEFAULT_MULLVAD_HOST`] if the host was not provided in the [`ConfigFile`]. - pub fn get_host(&self) -> String { - self.mullvad_host.clone().unwrap_or_else(|| { - log::debug!("No Mullvad host has been set explicitly. Falling back to default host"); - DEFAULT_MULLVAD_HOST.to_owned() - }) - } -} - -pub struct ConfigFile { - path: PathBuf, - config: Config, -} - -impl ConfigFile { - /// Make config changes and save them to disk - pub async fn load_or_default() -> Result<Self, Error> { - Self::load_or_default_inner(Self::get_config_path()?).await - } - - /// Get configuration file path - fn get_config_path() -> Result<PathBuf, Error> { - Ok(Self::get_config_dir()?.join("config.json")) - } - - /// Get configuration file directory - fn get_config_dir() -> Result<PathBuf, Error> { - let dir = dirs::config_dir() - .ok_or(Error::FindConfigDir)? - .join("mullvad-test"); - Ok(dir) - } - - /// Create configuration file directory if it does not exist - async fn ensure_config_dir() -> Result<(), Error> { - tokio::fs::create_dir_all(Self::get_config_dir()?) - .await - .map_err(Error::CreateConfigDir) - } +use std::env; +use std::path::{Path, PathBuf}; - /// Make config changes and save them to disk - async fn load_or_default_inner<P: AsRef<Path>>(path: P) -> Result<Self, Error> { - Ok(Self { - path: path.as_ref().to_path_buf(), - config: Config::load_or_default(path).await?, - }) - } - - /// Make config changes and save them to disk - pub async fn edit(&mut self, edit: impl FnOnce(&mut Config)) -> Result<(), Error> { - Self::ensure_config_dir().await?; - - edit(&mut self.config); - self.config.save(&self.path).await - } -} - -impl Deref for ConfigFile { - type Target = Config; - - fn deref(&self) -> &Self::Target { - &self.config - } -} +use serde::{Deserialize, Serialize}; #[derive(clap::Args, Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "snake_case")] |
