1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-31 09:24:31 +03:00

Load the configuration from a common Figment instance

This should avoid loading the same files multiple times.
It should also make it easier to do post-processing on the
configuration, like validation.

This does deprecate one undocumented feature: the ability to override
some fields during the configuration generation using environment
variables.
This commit is contained in:
Quentin Gliech
2024-03-20 15:16:35 +01:00
parent d20e579290
commit 1cf283337b
18 changed files with 108 additions and 126 deletions

View File

@ -21,7 +21,7 @@ anyhow.workspace = true
camino = { workspace = true, features = ["serde1"] }
chrono.workspace = true
figment = { version = "0.10.15", features = ["env", "yaml", "test"] }
figment.workspace = true
ipnetwork = { version = "0.20.0", features = ["serde", "schemars"] }
schemars.workspace = true
ulid.workspace = true

View File

@ -201,7 +201,10 @@ impl ConfigurationSection for ClientsConfig {
mod tests {
use std::str::FromStr;
use figment::Jail;
use figment::{
providers::{Format, Yaml},
Figment, Jail,
};
use super::*;
@ -249,7 +252,9 @@ mod tests {
"#,
)?;
let config = ClientsConfig::load_from_file("config.yaml")?;
let config = Figment::new()
.merge(Yaml::file("config.yaml"))
.extract_inner::<ClientsConfig>("clients")?;
assert_eq!(config.0.len(), 5);

View File

@ -164,7 +164,10 @@ impl ConfigurationSection for DatabaseConfig {
#[cfg(test)]
mod tests {
use figment::Jail;
use figment::{
providers::{Format, Yaml},
Figment, Jail,
};
use super::*;
@ -179,7 +182,9 @@ mod tests {
",
)?;
let config = DatabaseConfig::load_from_file("config.yaml")?;
let config = Figment::new()
.merge(Yaml::file("config.yaml"))
.extract_inner::<DatabaseConfig>("database")?;
assert_eq!(
config.options,

View File

@ -76,7 +76,10 @@ impl ConfigurationSection for MatrixConfig {
#[cfg(test)]
mod tests {
use figment::Jail;
use figment::{
providers::{Format, Yaml},
Figment, Jail,
};
use super::*;
@ -92,10 +95,12 @@ mod tests {
",
)?;
let config = MatrixConfig::load_from_file("config.yaml")?;
let config = Figment::new()
.merge(Yaml::file("config.yaml"))
.extract_inner::<MatrixConfig>("matrix")?;
assert_eq!(config.homeserver, "matrix.org".to_owned());
assert_eq!(config.secret, "test".to_owned());
assert_eq!(&config.homeserver, "matrix.org");
assert_eq!(&config.secret, "test");
Ok(())
});

View File

@ -12,14 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use anyhow::Context;
use async_trait::async_trait;
use camino::Utf8Path;
use figment::{
error::Error as FigmentError,
providers::{Env, Format, Serialized, Yaml},
Figment, Profile,
};
use figment::{error::Error as FigmentError, Figment};
use rand::Rng;
use serde::{de::DeserializeOwned, Serialize};
@ -35,64 +29,13 @@ pub trait ConfigurationSection: Sized + DeserializeOwned + Serialize {
where
R: Rng + Send;
/// Generate a sample configuration and override it with environment
/// variables.
///
/// This is what backs the `config generate` subcommand, allowing to
/// programmatically generate a configuration file, e.g.
///
/// ```sh
/// export MAS_OAUTH2_ISSUER=https://example.com/
/// export MAS_HTTP_ADDRESS=127.0.0.1:1234
/// matrix-authentication-service config generate
/// ```
///
/// # Errors
///
/// Returns an error if the configuration could not be generated or if the
/// existing configuration could not be loaded
async fn load_and_generate<R>(rng: R) -> anyhow::Result<Self>
where
R: Rng + Send,
{
let base = Self::generate(rng)
.await
.context("could not generate configuration")?;
Figment::new()
.merge(Serialized::from(&base, Profile::Default))
.merge(Env::prefixed("MAS_").split("_"))
.extract_inner(Self::path())
.context("could not load configuration")
}
/// Load configuration from a list of files and environment variables.
/// Extract configuration from a Figment instance.
///
/// # Errors
///
/// Returns an error if the configuration could not be loaded
fn load_from_files<P>(paths: &[P]) -> Result<Self, FigmentError>
where
P: AsRef<Utf8Path>,
{
let base = Figment::new().merge(Env::prefixed("MAS_").split("_"));
paths
.iter()
.fold(base, |f, path| f.merge(Yaml::file(path.as_ref())))
.extract_inner(Self::path())
}
/// Load configuration from a file and environment variables.
///
/// # Errors
///
/// Returns an error if the configuration could not be loaded
fn load_from_file<P>(path: P) -> Result<Self, FigmentError>
where
P: AsRef<Utf8Path>,
{
Self::load_from_files(&[path])
fn extract(figment: &Figment) -> Result<Self, FigmentError> {
figment.extract_inner(Self::path())
}
/// Generate config used in unit tests