mirror of https://github.com/rwf2/Rocket.git
Add the [global] psuedo-environment for global configuration.
This commit is contained in:
parent
da7cb44671
commit
d91e3e0454
|
@ -1,8 +1,2 @@
|
|||
[dev]
|
||||
template_dir = "static"
|
||||
|
||||
[stage]
|
||||
template_dir = "static"
|
||||
|
||||
[prod]
|
||||
[global]
|
||||
template_dir = "static"
|
||||
|
|
|
@ -21,7 +21,7 @@ pub struct Config {
|
|||
/// The environment that this configuration corresponds to.
|
||||
pub env: Environment,
|
||||
session_key: RwLock<Option<String>>,
|
||||
extra: HashMap<String, Value>,
|
||||
extras: HashMap<String, Value>,
|
||||
filename: String,
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ impl Config {
|
|||
port: 8000,
|
||||
log_level: LoggingLevel::Normal,
|
||||
session_key: RwLock::new(None),
|
||||
extra: HashMap::new(),
|
||||
extras: HashMap::new(),
|
||||
env: env,
|
||||
filename: filename.to_string(),
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ impl Config {
|
|||
port: 80,
|
||||
log_level: LoggingLevel::Normal,
|
||||
session_key: RwLock::new(None),
|
||||
extra: HashMap::new(),
|
||||
extras: HashMap::new(),
|
||||
env: env,
|
||||
filename: filename.to_string(),
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ impl Config {
|
|||
port: 80,
|
||||
log_level: LoggingLevel::Critical,
|
||||
session_key: RwLock::new(None),
|
||||
extra: HashMap::new(),
|
||||
extras: HashMap::new(),
|
||||
env: env,
|
||||
filename: filename.to_string(),
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ impl Config {
|
|||
"log level ('normal', 'critical', 'debug')"))
|
||||
};
|
||||
} else {
|
||||
self.extra.insert(name.into(), val.clone());
|
||||
self.extras.insert(name.into(), val.clone());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -130,26 +130,26 @@ impl Config {
|
|||
|
||||
#[inline(always)]
|
||||
pub fn extras<'a>(&'a self) -> impl Iterator<Item=(&'a String, &'a Value)> {
|
||||
self.extra.iter()
|
||||
self.extras.iter()
|
||||
}
|
||||
|
||||
pub fn get_str<'a>(&'a self, name: &str) -> config::Result<&'a str> {
|
||||
let value = self.extra.get(name).ok_or_else(|| ConfigError::NotFound)?;
|
||||
let value = self.extras.get(name).ok_or_else(|| ConfigError::NotFound)?;
|
||||
parse!(self, name, value, as_str, "a string")
|
||||
}
|
||||
|
||||
pub fn get_int<'a>(&'a self, name: &str) -> config::Result<i64> {
|
||||
let value = self.extra.get(name).ok_or_else(|| ConfigError::NotFound)?;
|
||||
let value = self.extras.get(name).ok_or_else(|| ConfigError::NotFound)?;
|
||||
parse!(self, name, value, as_integer, "an integer")
|
||||
}
|
||||
|
||||
pub fn get_bool<'a>(&'a self, name: &str) -> config::Result<bool> {
|
||||
let value = self.extra.get(name).ok_or_else(|| ConfigError::NotFound)?;
|
||||
let value = self.extras.get(name).ok_or_else(|| ConfigError::NotFound)?;
|
||||
parse!(self, name, value, as_bool, "a boolean")
|
||||
}
|
||||
|
||||
pub fn get_float<'a>(&'a self, name: &str) -> config::Result<f64> {
|
||||
let value = self.extra.get(name).ok_or_else(|| ConfigError::NotFound)?;
|
||||
let value = self.extras.get(name).ok_or_else(|| ConfigError::NotFound)?;
|
||||
parse!(self, name, value, as_float, "a float")
|
||||
}
|
||||
|
||||
|
@ -191,6 +191,12 @@ impl Config {
|
|||
self.env = var;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn extra(mut self, name: &str, value: &Value) -> Self {
|
||||
self.extras.insert(name.into(), value.clone());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Config {
|
||||
|
@ -207,7 +213,7 @@ impl PartialEq for Config {
|
|||
&& self.port == other.port
|
||||
&& self.log_level == other.log_level
|
||||
&& self.env == other.env
|
||||
&& self.extra == other.extra
|
||||
&& self.extras == other.extras
|
||||
&& self.filename == other.filename
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,12 @@ impl Environment {
|
|||
pub fn valid() -> &'static str {
|
||||
"development, staging, production"
|
||||
}
|
||||
|
||||
/// Returns a list of all of the possible environments.
|
||||
#[inline(always)]
|
||||
pub fn all() -> [Environment; 3] {
|
||||
[Development, Staging, Production]
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Environment {
|
||||
|
|
|
@ -58,9 +58,10 @@ impl ConfigError {
|
|||
info_!("{}", reason);
|
||||
}
|
||||
BadEntry(ref name, ref filename) => {
|
||||
let valid_entries = format!("{}, and global", valid_envs);
|
||||
error!("[{}] is not a known configuration environment", name);
|
||||
info_!("in {}", White.paint(filename));
|
||||
info_!("valid environments are: {}", White.paint(valid_envs));
|
||||
info_!("valid environments are: {}", White.paint(valid_entries));
|
||||
}
|
||||
BadEnv(ref name) => {
|
||||
error!("'{}' is not a valid ROCKET_ENV value", name);
|
||||
|
|
|
@ -47,11 +47,12 @@
|
|||
//! each environment. The file is optional. If it is not present, the default
|
||||
//! configuration parameters are used.
|
||||
//!
|
||||
//! The file must be a series of tables, one for each environment, where each
|
||||
//! table contains key-value pairs corresponding to configuration parameters for
|
||||
//! that environment. If a configuration parameter is missing, the default value
|
||||
//! is used. The following is a complete `Rocket.toml` file, where every
|
||||
//! standard configuration parameter is specified with the default value:
|
||||
//! The file must be a series of tables, at most one for each environment and a
|
||||
//! "global" table, where each table contains key-value pairs corresponding to
|
||||
//! configuration parameters for that environment. If a configuration parameter
|
||||
//! is missing, the default value is used. The following is a complete
|
||||
//! `Rocket.toml` file, where every standard configuration parameter is
|
||||
//! specified with the default value:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [development]
|
||||
|
@ -74,6 +75,23 @@
|
|||
//! session_key = "adL5fFIPmZBrlyHk2YT4NLV3YCk2gFXz"
|
||||
//! ```
|
||||
//!
|
||||
//! The "global" pseudo-environment can be used to set and/or override
|
||||
//! configuration parameters globally. A parameter defined in a `[global]` table
|
||||
//! sets, or overrides if already present, that parameter in every environment.
|
||||
//! For example, given the following `Rocket.toml` file, the value of `address`
|
||||
//! will be `"1.2.3.4"` in every environment:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [global]
|
||||
//! address = "1.2.3.4"
|
||||
//!
|
||||
//! [devolopment]
|
||||
//! address = "localhost"
|
||||
//!
|
||||
//! [production]
|
||||
//! address = "0.0.0.0"
|
||||
//! ```
|
||||
//!
|
||||
//! ## Retrieving Configuration Parameters
|
||||
//!
|
||||
//! Configuration parameters for the currently active configuration environment
|
||||
|
@ -127,6 +145,8 @@ static mut CONFIG: Option<RocketConfig> = None;
|
|||
|
||||
const CONFIG_FILENAME: &'static str = "Rocket.toml";
|
||||
|
||||
const GLOBAL_ENV_NAME: &'static str = "global";
|
||||
|
||||
/// Wraps `std::result` with the error type of
|
||||
/// [ConfigError](enum.ConfigError.html).
|
||||
pub type Result<T> = ::std::result::Result<T, ConfigError>;
|
||||
|
@ -198,16 +218,14 @@ impl RocketConfig {
|
|||
}).collect()
|
||||
))?;
|
||||
|
||||
// Create a config with the defaults, but the set the env to the active
|
||||
// Create a config with the defaults; set the env to the active one.
|
||||
let mut config = RocketConfig::active_default(filename)?;
|
||||
|
||||
// Store all of the global overrides, if any, for later use.
|
||||
let mut global = None;
|
||||
|
||||
// Parse the values from the TOML file.
|
||||
for (entry, value) in toml {
|
||||
// Parse the environment from the table entry name.
|
||||
let env = entry.as_str().parse().map_err(|_| {
|
||||
ConfigError::BadEntry(entry.clone(), filename.into())
|
||||
})?;
|
||||
|
||||
// Each environment must be a table.
|
||||
let kv_pairs = match value.as_table() {
|
||||
Some(table) => table,
|
||||
|
@ -216,9 +234,25 @@ impl RocketConfig {
|
|||
))
|
||||
};
|
||||
|
||||
if entry.as_str() == GLOBAL_ENV_NAME {
|
||||
global = Some(kv_pairs.clone());
|
||||
} else {
|
||||
// Parse the environment from the table entry name.
|
||||
let env = entry.as_str().parse().map_err(|_| {
|
||||
ConfigError::BadEntry(entry.clone(), filename.into())
|
||||
})?;
|
||||
|
||||
// Set the environment configuration from the kv pairs.
|
||||
config.set(env, &kv_pairs)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Override all of the environments with the global values.
|
||||
if let Some(ref global_kv_pairs) = global {
|
||||
for env in &Environment::all() {
|
||||
config.set(*env, global_kv_pairs)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
@ -320,7 +354,7 @@ mod test {
|
|||
use std::env;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use super::{RocketConfig, ConfigError};
|
||||
use super::{RocketConfig, ConfigError, GLOBAL_ENV_NAME};
|
||||
use super::environment::{Environment, CONFIG_ENV};
|
||||
use super::Environment::*;
|
||||
use super::config::Config;
|
||||
|
@ -678,4 +712,42 @@ mod test {
|
|||
session_key = "abcv" = other
|
||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_global_overrides() {
|
||||
// Take the lock so changing the environment doesn't cause races.
|
||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||
|
||||
// Test first that we can override each environment.
|
||||
for env in &Environment::all() {
|
||||
env::set_var(CONFIG_ENV, env.to_string());
|
||||
|
||||
check_config!(RocketConfig::parse(format!(r#"
|
||||
[{}]
|
||||
address = "7.6.5.4"
|
||||
"#, GLOBAL_ENV_NAME), TEST_CONFIG_FILENAME), {
|
||||
default_config(*env).address(
|
||||
"7.6.5.4".into()
|
||||
)
|
||||
});
|
||||
|
||||
check_config!(RocketConfig::parse(format!(r#"
|
||||
[{}]
|
||||
database = "mysql"
|
||||
"#, GLOBAL_ENV_NAME), TEST_CONFIG_FILENAME), {
|
||||
default_config(*env).extra("database",
|
||||
&Value::String("mysql".into())
|
||||
)
|
||||
});
|
||||
|
||||
check_config!(RocketConfig::parse(format!(r#"
|
||||
[{}]
|
||||
port = 3980
|
||||
"#, GLOBAL_ENV_NAME), TEST_CONFIG_FILENAME), {
|
||||
default_config(*env).port(
|
||||
3980
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue