summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2024-11-22 18:10:12 +0100
committerSebastian Holmin <sebastian.holmin@mullvad.net>2025-01-22 13:32:06 +0100
commitaab565ed60931f7c75aaded815f3ac5b46fa6bb5 (patch)
tree1a737dc875015676d6635a33af459945e5d539b4
parente913da1df1185c56673c99a1eb6e42d08d8361ed (diff)
downloadmullvadvpn-aab565ed60931f7c75aaded815f3ac5b46fa6bb5.tar.xz
mullvadvpn-aab565ed60931f7c75aaded815f3ac5b46fa6bb5.zip
Convert test-manager config into a module
-rw-r--r--test/test-manager/src/config/error.rs15
-rw-r--r--test/test-manager/src/config/io.rs80
-rw-r--r--test/test-manager/src/config/manifest.rs47
-rw-r--r--test/test-manager/src/config/mod.rs19
-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")]